This puts the loop body in a new function called try_this_kernel. As an added benefit, we can drop one level of indentation. This change is hard to read as a patch. It gets better if one just applies it and then looks at it with "git diff -w" or similar. Signed-off-by: Werner Almesberger --- Index: qi/src/phase2.c =================================================================== --- qi.orig/src/phase2.c 2009-01-08 23:20:16.000000000 -0200 +++ qi/src/phase2.c 2009-01-08 23:21:01.000000000 -0200 @@ -96,292 +96,274 @@ return len; } -void bootloader_second_phase(void) +static void try_this_kernel(void) { void (*the_kernel)(int zero, int arch, uint params); - int kernel = 0; const struct board_variant * board_variant = (this_board->get_board_variant)(); unsigned int initramfs_len = 0; static char commandline_rootfs_append[512] = ""; + static void * last_block_init = NULL; + static int last_block_init_result = 0; int ret; - void * last_block_init = NULL; - int last_block_init_result = 0; - - /* we try the possible kernels for this board in order */ - - this_kernel = &this_board->kernel_source[kernel++]; + const char *p; + char * cmdline; + struct tag *params = (struct tag *)this_board->linux_tag_placement; + void * kernel_dram = (void *)this_board->linux_mem_start + 0x8000; + unsigned long crc; + image_header_t *hdr; + u32 kernel_size; + + partition_offset_blocks = 0; + partition_length_blocks = 0; + + /* eat leading white space */ + for (p = this_board->commandline_board; *p == ' '; p++); + + puts("\nTrying kernel: "); + puts(this_kernel->name); + puts("\n"); - while (this_kernel->name) { - const char *p; - char * cmdline; - struct tag *params = (struct tag *)this_board->linux_tag_placement; - void * kernel_dram = (void *)this_board->linux_mem_start + 0x8000; - unsigned long crc; - image_header_t *hdr; - u32 kernel_size; - - partition_offset_blocks = 0; - partition_length_blocks = 0; - - /* eat leading white space */ - for (p = this_board->commandline_board; *p == ' '; p++); - - puts("\nTrying kernel: "); - puts(this_kernel->name); - puts("\n"); + indicate(UI_IND_MOUNT_PART); - indicate(UI_IND_MOUNT_PART); + /* if this device needs initializing, try to init it */ + if (this_kernel->block_init) { + /* + * cache result to limit attempts for same + * block device to one time + */ + if (this_kernel->block_init != last_block_init) + last_block_init_result = (this_kernel->block_init)(); - /* if this device needs initializing, try to init it */ - if (this_kernel->block_init) { - /* - * cache result to limit attempts for same - * block device to one time - */ + if (last_block_init_result) { + puts("block device init failed\n"); if (this_kernel->block_init != last_block_init) - last_block_init_result = - (this_kernel->block_init)(); - - if (last_block_init_result) { - puts("block device init failed\n"); - if (this_kernel->block_init != last_block_init) - indicate(UI_IND_MOUNT_FAIL); - this_kernel = &this_board-> - kernel_source[kernel++]; - last_block_init = this_kernel->block_init; - continue; - } - last_block_init = this_kernel->block_init; + indicate(UI_IND_MOUNT_FAIL); + last_block_init = this_kernel[1].block_init; + return; } + last_block_init = this_kernel->block_init; + } - /* if there's a partition table implied, parse it, otherwise - * just use a fixed offset - */ - if (this_kernel->partition_index) { - unsigned char *p = kernel_dram; + /* if there's a partition table implied, parse it, otherwise + * just use a fixed offset + */ + if (this_kernel->partition_index) { + unsigned char *p = kernel_dram; - if ((int)this_kernel->block_read(kernel_dram, 0, 4) - < 0) { - puts("Bad partition read\n"); - this_kernel = &this_board-> - kernel_source[kernel++]; - indicate(UI_IND_MOUNT_FAIL); - continue; - } + if ((int)this_kernel->block_read(kernel_dram, 0, 4) < 0) { + puts("Bad partition read\n"); + indicate(UI_IND_MOUNT_FAIL); + return; + } - if ((p[0x1fe] != 0x55) || (p[0x1ff] != 0xaa)) { - puts("partition signature missing\n"); - this_kernel = &this_board-> - kernel_source[kernel++]; - indicate(UI_IND_MOUNT_FAIL); - continue; - } + if ((p[0x1fe] != 0x55) || (p[0x1ff] != 0xaa)) { + puts("partition signature missing\n"); + indicate(UI_IND_MOUNT_FAIL); + return; + } - p += 0x1be + 8 + (0x10 * - (this_kernel->partition_index - 1)); + p += 0x1be + 8 + (0x10 * (this_kernel->partition_index - 1)); - partition_offset_blocks = (((u32)p[3]) << 24) | - (((u32)p[2]) << 16) | - (((u32)p[1]) << 8) | - p[0]; - partition_length_blocks = (((u32)p[7]) << 24) | - (((u32)p[6]) << 16) | - (((u32)p[5]) << 8) | - p[4]; - - puts(" Partition: "); - printdec(this_kernel->partition_index); - puts(" start +"); - printdec(partition_offset_blocks); - puts(" 512-byte blocks, size "); - printdec(partition_length_blocks / 2048); - puts(" MiB\n"); - - } else - partition_offset_blocks = - this_kernel->offset_blocks512_if_no_partition; - - /* does he want us to skip this? */ - - ret = read_file(this_board->noboot, kernel_dram, 512); - if (ret != -1) { - /* -2 (mount fail) should make us give up too */ - if (ret >= 0) { - puts(" (Skipping on finding "); - puts(this_board->noboot); - puts(")\n"); - indicate(UI_IND_SKIPPING); - } - this_kernel = &this_board->kernel_source[kernel++]; - continue; + partition_offset_blocks = (((u32)p[3]) << 24) | + (((u32)p[2]) << 16) | + (((u32)p[1]) << 8) | + p[0]; + partition_length_blocks = (((u32)p[7]) << 24) | + (((u32)p[6]) << 16) | + (((u32)p[5]) << 8) | + p[4]; + + puts(" Partition: "); + printdec(this_kernel->partition_index); + puts(" start +"); + printdec(partition_offset_blocks); + puts(" 512-byte blocks, size "); + printdec(partition_length_blocks / 2048); + puts(" MiB\n"); + + } else + partition_offset_blocks = + this_kernel->offset_blocks512_if_no_partition; + + /* does he want us to skip this? */ + + ret = read_file(this_board->noboot, kernel_dram, 512); + if (ret != -1) { + /* -2 (mount fail) should make us give up too */ + if (ret >= 0) { + puts(" (Skipping on finding "); + puts(this_board->noboot); + puts(")\n"); + indicate(UI_IND_SKIPPING); } + return; + } - /* is there a commandline append file? */ + /* is there a commandline append file? */ - commandline_rootfs_append[0] = '\0'; - read_file(this_board->append, (u8 *)commandline_rootfs_append, - 512); + commandline_rootfs_append[0] = '\0'; + read_file(this_board->append, (u8 *)commandline_rootfs_append, 512); - indicate(UI_IND_KERNEL_PULL); + indicate(UI_IND_KERNEL_PULL); - /* pull the kernel image */ + /* pull the kernel image */ - if (read_file(this_kernel->filepath, kernel_dram, 4096) < 0) { - this_kernel = &this_board->kernel_source[kernel++]; - continue; - } + if (read_file(this_kernel->filepath, kernel_dram, 4096) < 0) + return; - hdr = (image_header_t *)kernel_dram; + hdr = (image_header_t *)kernel_dram; - if (__be32_to_cpu(hdr->ih_magic) != IH_MAGIC) { - puts("bad magic "); - print32(hdr->ih_magic); - puts("\n"); - this_kernel = &this_board->kernel_source[kernel++]; - continue; - } + if (__be32_to_cpu(hdr->ih_magic) != IH_MAGIC) { + puts("bad magic "); + print32(hdr->ih_magic); + puts("\n"); + return; + } - puts(" Found: \""); - puts((const char *)hdr->ih_name); - puts("\"\n Size: "); - printdec(__be32_to_cpu(hdr->ih_size) >> 10); - puts(" KiB\n"); - - kernel_size = ((__be32_to_cpu(hdr->ih_size) + - sizeof(image_header_t) + 2048) & ~(2048 - 1)); - - if (read_file(this_kernel->filepath, kernel_dram, - kernel_size) < 0) { - this_kernel = &this_board->kernel_source[kernel++]; - indicate(UI_IND_KERNEL_PULL_FAIL); - continue; - } + puts(" Found: \""); + puts((const char *)hdr->ih_name); + puts("\"\n Size: "); + printdec(__be32_to_cpu(hdr->ih_size) >> 10); + puts(" KiB\n"); + + kernel_size = ((__be32_to_cpu(hdr->ih_size) + + sizeof(image_header_t) + 2048) & ~(2048 - 1)); + + if (read_file(this_kernel->filepath, kernel_dram, kernel_size) < 0) { + indicate(UI_IND_KERNEL_PULL_FAIL); + return; + } - indicate(UI_IND_KERNEL_PULL_OK); + indicate(UI_IND_KERNEL_PULL_OK); - /* initramfs if needed */ + /* initramfs if needed */ - if (this_kernel->initramfs_filepath) { - indicate(UI_IND_INITRAMFS_PULL); - initramfs_len = read_file(this_kernel->initramfs_filepath, - (u8 *)this_board->linux_mem_start + INITRD_OFFSET, - 16 * 1024 * 1024); - if (initramfs_len < 0) { - puts("initramfs load failed\n"); - this_kernel = &this_board->kernel_source[kernel++]; - indicate(UI_IND_INITRAMFS_PULL_FAIL); - continue; - } - indicate(UI_IND_INITRAMFS_PULL_OK); + if (this_kernel->initramfs_filepath) { + indicate(UI_IND_INITRAMFS_PULL); + initramfs_len = read_file(this_kernel->initramfs_filepath, + (u8 *)this_board->linux_mem_start + INITRD_OFFSET, + 16 * 1024 * 1024); + if (initramfs_len < 0) { + puts("initramfs load failed\n"); + indicate(UI_IND_INITRAMFS_PULL_FAIL); + return; } + indicate(UI_IND_INITRAMFS_PULL_OK); + } - /* - * It's good for now to know that our kernel is intact from - * the storage before we jump into it and maybe crash silently - * even though it costs us some time - */ - crc = crc32(0, kernel_dram + sizeof(image_header_t), + /* + * It's good for now to know that our kernel is intact from + * the storage before we jump into it and maybe crash silently + * even though it costs us some time + */ + crc = crc32(0, kernel_dram + sizeof(image_header_t), __be32_to_cpu(hdr->ih_size)); - if (crc != __be32_to_cpu(hdr->ih_dcrc)) { - puts("\nKernel CRC ERROR: read 0x"); - print32(crc); - puts(" vs hdr CRC 0x"); - print32(__be32_to_cpu(hdr->ih_dcrc)); - puts("\n"); - this_kernel = &this_board->kernel_source[kernel++]; - continue; - } - - the_kernel = (void (*)(int, int, uint)) - (((char *)hdr) + sizeof(image_header_t)); - - /* first tag */ - params->hdr.tag = ATAG_CORE; - params->hdr.size = tag_size (tag_core); - params->u.core.flags = 0; - params->u.core.pagesize = 0; - params->u.core.rootdev = 0; - params = tag_next(params); - - /* revision tag */ - params->hdr.tag = ATAG_REVISION; - params->hdr.size = tag_size (tag_revision); - params->u.revision.rev = board_variant->machine_revision; - params = tag_next(params); + if (crc != __be32_to_cpu(hdr->ih_dcrc)) { + puts("\nKernel CRC ERROR: read 0x"); + print32(crc); + puts(" vs hdr CRC 0x"); + print32(__be32_to_cpu(hdr->ih_dcrc)); + puts("\n"); + return; + } - /* memory tags */ - params->hdr.tag = ATAG_MEM; - params->hdr.size = tag_size (tag_mem32); - params->u.mem.start = this_board->linux_mem_start; - params->u.mem.size = this_board->linux_mem_size; - params = tag_next(params); + the_kernel = (void (*)(int, int, uint)) + (((char *)hdr) + sizeof(image_header_t)); - if (this_kernel->initramfs_filepath) { - /* INITRD2 tag */ - params->hdr.tag = ATAG_INITRD2; - params->hdr.size = tag_size (tag_initrd); - params->u.initrd.start = this_board->linux_mem_start + + /* first tag */ + params->hdr.tag = ATAG_CORE; + params->hdr.size = tag_size (tag_core); + params->u.core.flags = 0; + params->u.core.pagesize = 0; + params->u.core.rootdev = 0; + params = tag_next(params); + + /* revision tag */ + params->hdr.tag = ATAG_REVISION; + params->hdr.size = tag_size (tag_revision); + params->u.revision.rev = board_variant->machine_revision; + params = tag_next(params); + + /* memory tags */ + params->hdr.tag = ATAG_MEM; + params->hdr.size = tag_size (tag_mem32); + params->u.mem.start = this_board->linux_mem_start; + params->u.mem.size = this_board->linux_mem_size; + params = tag_next(params); + + if (this_kernel->initramfs_filepath) { + /* INITRD2 tag */ + params->hdr.tag = ATAG_INITRD2; + params->hdr.size = tag_size (tag_initrd); + params->u.initrd.start = this_board->linux_mem_start + INITRD_OFFSET; - params->u.initrd.size = initramfs_len; - params = tag_next(params); - } + params->u.initrd.size = initramfs_len; + params = tag_next(params); + } - /* kernel commandline */ + /* kernel commandline */ - cmdline = params->u.cmdline.cmdline; - cmdline += strlen(strcpy(cmdline, p)); - if (this_kernel->commandline_append) + cmdline = params->u.cmdline.cmdline; + cmdline += strlen(strcpy(cmdline, p)); + if (this_kernel->commandline_append) + cmdline += strlen(strcpy(cmdline, + this_kernel->commandline_append)); + if (commandline_rootfs_append[0]) cmdline += strlen(strcpy(cmdline, - this_kernel->commandline_append)); - if (commandline_rootfs_append[0]) - cmdline += strlen(strcpy(cmdline, - commandline_rootfs_append)); + commandline_rootfs_append)); - /* - * if he's still holding down the UI_ACTION_SKIPKERNEL key - * now we finished loading the kernel, take it to mean he wants - * to have the debugging options added to the commandline - */ + /* + * if he's still holding down the UI_ACTION_SKIPKERNEL key + * now we finished loading the kernel, take it to mean he wants + * to have the debugging options added to the commandline + */ - if (this_board->commandline_board_debug && - this_board->get_ui_keys) - if ((this_board->get_ui_keys)() & UI_ACTION_SKIPKERNEL) - cmdline += strlen(strcpy(cmdline, this_board-> - commandline_board_debug)); - - params->hdr.tag = ATAG_CMDLINE; - params->hdr.size = (sizeof (struct tag_header) + - strlen(params->u.cmdline.cmdline) + 1 + 4) >> 2; + if (this_board->commandline_board_debug && this_board->get_ui_keys) + if ((this_board->get_ui_keys)() & UI_ACTION_SKIPKERNEL) + cmdline += strlen(strcpy(cmdline, this_board-> + commandline_board_debug)); + + params->hdr.tag = ATAG_CMDLINE; + params->hdr.size = (sizeof (struct tag_header) + + strlen(params->u.cmdline.cmdline) + 1 + 4) >> 2; + + puts(" Cmdline: "); + puts(params->u.cmdline.cmdline); + puts("\n"); + + params = tag_next (params); + + /* needs to always be the last tag */ + params->hdr.tag = ATAG_NONE; + params->hdr.size = 0; - puts(" Cmdline: "); - puts(params->u.cmdline.cmdline); - puts("\n"); - - params = tag_next (params); + /* give board implementation a chance to shut down + * anything it may have going on, leave GPIO set for Linux + */ + if (this_board->close) + (this_board->close)(); - /* needs to always be the last tag */ - params->hdr.tag = ATAG_NONE; - params->hdr.size = 0; + puts ("Starting --->\n\n"); + indicate(UI_IND_KERNEL_START); - /* give board implementation a chance to shut down - * anything it may have going on, leave GPIO set for Linux - */ - if (this_board->close) - (this_board->close)(); + /* + * ooh that's it, we're gonna try boot this image! + * never mind the cache, Linux will take care of it + */ + the_kernel(0, this_board->linux_machine_id, + this_board->linux_tag_placement); - puts ("Starting --->\n\n"); - indicate(UI_IND_KERNEL_START); + /* we won't come back here no matter what */ +} - /* - * ooh that's it, we're gonna try boot this image! - * never mind the cache, Linux will take care of it - */ - the_kernel(0, this_board->linux_machine_id, - this_board->linux_tag_placement); +void bootloader_second_phase(void) +{ + /* we try the possible kernels for this board in order */ - /* we won't come back here no matter what */ - } + for (this_kernel = this_board->kernel_source; this_kernel->name; + this_kernel++) + try_this_kernel(); /* none of the kernels worked out */ --