X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=common%2Fcmd_bootm.c;h=45e726af8b8bc4870334d9ae48e39df02762e487;hb=4a5edda2ed89fadba28579adab42bb7b7c01632b;hp=d5745b14e2ce54427ce7153759b0f39a0bb8fa3f;hpb=1086c5d6f8541460f0f10e4a302d8aac27e0e6e0;p=u-boot diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index d5745b14e2..45e726af8b 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -169,25 +169,26 @@ void arch_preboot_os(void) __attribute__((weak, alias("__arch_preboot_os"))); #define IH_INITRD_ARCH IH_ARCH_DEFAULT -static void bootm_start_lmb(void) -{ #ifdef CONFIG_LMB +static void boot_start_lmb(bootm_headers_t *images) +{ ulong mem_start; phys_size_t mem_size; - lmb_init(&images.lmb); + lmb_init(&images->lmb); mem_start = getenv_bootm_low(); mem_size = getenv_bootm_size(); - lmb_add(&images.lmb, (phys_addr_t)mem_start, mem_size); + lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size); - arch_lmb_reserve(&images.lmb); - board_lmb_reserve(&images.lmb); + arch_lmb_reserve(&images->lmb); + board_lmb_reserve(&images->lmb); +} #else -# define lmb_reserve(lmb, base, size) +#define lmb_reserve(lmb, base, size) +static inline void boot_start_lmb(bootm_headers_t *images) { } #endif -} static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -197,7 +198,9 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] memset((void *)&images, 0, sizeof(images)); images.verify = getenv_yesno("verify"); - bootm_start_lmb(); + boot_start_lmb(&images); + + bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start"); /* get kernel image header, start address and length */ os_hdr = boot_get_kernel(cmdtp, flag, argc, argv, @@ -222,21 +225,21 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] if (fit_image_get_type(images.fit_hdr_os, images.fit_noffset_os, &images.os.type)) { puts("Can't get image type!\n"); - show_boot_progress(-109); + bootstage_error(BOOTSTAGE_ID_FIT_TYPE); return 1; } if (fit_image_get_comp(images.fit_hdr_os, images.fit_noffset_os, &images.os.comp)) { puts("Can't get image compression!\n"); - show_boot_progress(-110); + bootstage_error(BOOTSTAGE_ID_FIT_COMPRESSION); return 1; } if (fit_image_get_os(images.fit_hdr_os, images.fit_noffset_os, &images.os.os)) { puts("Can't get image OS!\n"); - show_boot_progress(-111); + bootstage_error(BOOTSTAGE_ID_FIT_OS); return 1; } @@ -245,7 +248,7 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] if (fit_image_get_load(images.fit_hdr_os, images.fit_noffset_os, &images.os.load)) { puts("Can't get image load address!\n"); - show_boot_progress(-112); + bootstage_error(BOOTSTAGE_ID_FIT_LOADADDR); return 1; } break; @@ -348,7 +351,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) puts("GUNZIP: uncompress, out-of-mem or overwrite " "error - must RESET board to recover\n"); if (boot_progress) - show_boot_progress(-6); + bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); return BOOTM_ERR_RESET; } @@ -370,7 +373,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) printf("BUNZIP2: uncompress or overwrite error %d " "- must RESET board to recover\n", i); if (boot_progress) - show_boot_progress(-6); + bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); return BOOTM_ERR_RESET; } @@ -389,7 +392,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) if (ret != SZ_OK) { printf("LZMA: uncompress or overwrite error %d " "- must RESET board to recover\n", ret); - show_boot_progress(-6); + bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); return BOOTM_ERR_RESET; } *load_end = load + unc_len; @@ -407,7 +410,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) printf("LZO: uncompress or overwrite error %d " "- must RESET board to recover\n", ret); if (boot_progress) - show_boot_progress(-6); + bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); return BOOTM_ERR_RESET; } @@ -423,8 +426,7 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) puts("OK\n"); debug(" kernel loaded at 0x%08lx, end = 0x%08lx\n", load, *load_end); - if (boot_progress) - show_boot_progress(7); + bootstage_mark(BOOTSTAGE_ID_KERNEL_LOADED); if (!no_overlap && (load < blob_end) && (*load_end > blob_start)) { debug("images.os.start = 0x%lX, images.os.end = 0x%lx\n", @@ -493,12 +495,12 @@ int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc, } } else { /* Unrecognized command */ - return cmd_usage(cmdtp); + return CMD_RET_USAGE; } if (images.state >= state) { printf("Trying to execute a command out of order\n"); - return cmd_usage(cmdtp); + return CMD_RET_USAGE; } images.state |= state; @@ -649,14 +651,14 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } else { puts("ERROR: new format image overwritten - " "must RESET the board to recover\n"); - show_boot_progress(-113); + bootstage_error(BOOTSTAGE_ID_OVERWRITTEN); do_reset(cmdtp, flag, argc, argv); } } if (ret == BOOTM_ERR_UNIMPLEMENTED) { if (iflag) enable_interrupts(); - show_boot_progress(-7); + bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL); return 1; } } @@ -671,7 +673,7 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } - show_boot_progress(8); + bootstage_mark(BOOTSTAGE_ID_CHECK_BOOT_OS); #ifdef CONFIG_SILENT_CONSOLE if (images.os.os == IH_OS_LINUX) @@ -685,7 +687,7 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) enable_interrupts(); printf("ERROR: booting os '%s' (%d) is not supported\n", genimg_get_os_name(images.os.os), images.os.os); - show_boot_progress(-8); + bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS); return 1; } @@ -693,7 +695,7 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) boot_fn(0, argc, argv, &images); - show_boot_progress(-9); + bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED); #ifdef DEBUG puts("\n## Control returned to monitor - resetting...\n"); #endif @@ -735,34 +737,34 @@ static image_header_t *image_get_kernel(ulong img_addr, int verify) if (!image_check_magic(hdr)) { puts("Bad Magic Number\n"); - show_boot_progress(-1); + bootstage_error(BOOTSTAGE_ID_CHECK_MAGIC); return NULL; } - show_boot_progress(2); + bootstage_mark(BOOTSTAGE_ID_CHECK_HEADER); if (!image_check_hcrc(hdr)) { puts("Bad Header Checksum\n"); - show_boot_progress(-2); + bootstage_error(BOOTSTAGE_ID_CHECK_HEADER); return NULL; } - show_boot_progress(3); + bootstage_mark(BOOTSTAGE_ID_CHECK_CHECKSUM); image_print_contents(hdr); if (verify) { puts(" Verifying Checksum ... "); if (!image_check_dcrc(hdr)) { printf("Bad Data CRC\n"); - show_boot_progress(-3); + bootstage_error(BOOTSTAGE_ID_CHECK_CHECKSUM); return NULL; } puts("OK\n"); } - show_boot_progress(4); + bootstage_mark(BOOTSTAGE_ID_CHECK_ARCH); if (!image_check_target_arch(hdr)) { printf("Unsupported Architecture 0x%x\n", image_get_arch(hdr)); - show_boot_progress(-4); + bootstage_error(BOOTSTAGE_ID_CHECK_ARCH); return NULL; } return hdr; @@ -790,28 +792,28 @@ static int fit_check_kernel(const void *fit, int os_noffset, int verify) puts(" Verifying Hash Integrity ... "); if (!fit_image_check_hashes(fit, os_noffset)) { puts("Bad Data Hash\n"); - show_boot_progress(-104); + bootstage_error(BOOTSTAGE_ID_FIT_CHECK_HASH); return 0; } puts("OK\n"); } - show_boot_progress(105); + bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_ARCH); if (!fit_image_check_target_arch(fit, os_noffset)) { puts("Unsupported Architecture\n"); - show_boot_progress(-105); + bootstage_error(BOOTSTAGE_ID_FIT_CHECK_ARCH); return 0; } - show_boot_progress(106); + bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_KERNEL); if (!fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL) && !fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL_NOLOAD)) { puts("Not a kernel image\n"); - show_boot_progress(-106); + bootstage_error(BOOTSTAGE_ID_FIT_CHECK_KERNEL); return 0; } - show_boot_progress(107); + bootstage_mark(BOOTSTAGE_ID_FIT_CHECKED); return 1; } #endif /* CONFIG_FIT */ @@ -864,7 +866,7 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, debug("* kernel: cmdline image address = 0x%08lx\n", img_addr); } - show_boot_progress(1); + bootstage_mark(BOOTSTAGE_ID_CHECK_MAGIC); /* copy from dataflash if needed */ img_addr = genimg_get_image(img_addr); @@ -878,7 +880,7 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, hdr = image_get_kernel(img_addr, images->verify); if (!hdr) return NULL; - show_boot_progress(5); + bootstage_mark(BOOTSTAGE_ID_CHECK_IMAGETYPE); /* get os_data and os_len */ switch (image_get_type(hdr)) { @@ -897,7 +899,7 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, default: printf("Wrong Image Type for %s command\n", cmdtp->name); - show_boot_progress(-5); + bootstage_error(BOOTSTAGE_ID_CHECK_IMAGETYPE); return NULL; } @@ -912,7 +914,7 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, images->legacy_hdr_os = hdr; images->legacy_hdr_valid = 1; - show_boot_progress(6); + bootstage_mark(BOOTSTAGE_ID_DECOMP_IMAGE); break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: @@ -922,10 +924,10 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, if (!fit_check_format(fit_hdr)) { puts("Bad FIT kernel image format!\n"); - show_boot_progress(-100); + bootstage_error(BOOTSTAGE_ID_FIT_FORMAT); return NULL; } - show_boot_progress(100); + bootstage_mark(BOOTSTAGE_ID_FIT_FORMAT); if (!fit_uname_kernel) { /* @@ -934,11 +936,11 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, * fit_conf_get_node() will try to find default config * node */ - show_boot_progress(101); + bootstage_mark(BOOTSTAGE_ID_FIT_NO_UNIT_NAME); cfg_noffset = fit_conf_get_node(fit_hdr, fit_uname_config); if (cfg_noffset < 0) { - show_boot_progress(-101); + bootstage_error(BOOTSTAGE_ID_FIT_NO_UNIT_NAME); return NULL; } /* save configuration uname provided in the first @@ -949,7 +951,7 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, NULL); printf(" Using '%s' configuration\n", images->fit_uname_cfg); - show_boot_progress(103); + bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG); os_noffset = fit_conf_get_kernel_node(fit_hdr, cfg_noffset); @@ -957,28 +959,28 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, NULL); } else { /* get kernel component image node offset */ - show_boot_progress(102); + bootstage_mark(BOOTSTAGE_ID_FIT_UNIT_NAME); os_noffset = fit_image_get_node(fit_hdr, fit_uname_kernel); } if (os_noffset < 0) { - show_boot_progress(-103); + bootstage_error(BOOTSTAGE_ID_FIT_CONFIG); return NULL; } printf(" Trying '%s' kernel subimage\n", fit_uname_kernel); - show_boot_progress(104); + bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_SUBIMAGE); if (!fit_check_kernel(fit_hdr, os_noffset, images->verify)) return NULL; /* get kernel image data address and length */ if (fit_image_get_data(fit_hdr, os_noffset, &data, &len)) { puts("Could not find kernel subimage data!\n"); - show_boot_progress(-107); + bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO_ERR); return NULL; } - show_boot_progress(108); + bootstage_mark(BOOTSTAGE_ID_FIT_KERNEL_INFO); *os_len = len; *os_data = (ulong)data; @@ -989,7 +991,7 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, #endif default: printf("Wrong Image Format for %s command\n", cmdtp->name); - show_boot_progress(-108); + bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO); return NULL; } @@ -1045,14 +1047,8 @@ int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int rcode = 0; -#ifndef CONFIG_SYS_HUSH_PARSER if (run_command(getenv("bootcmd"), flag) < 0) rcode = 1; -#else - if (parse_string_outer(getenv("bootcmd"), - FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0) - rcode = 1; -#endif return rcode; } @@ -1340,7 +1336,7 @@ static int do_bootm_netbsd(int flag, int argc, char * const argv[], "(at address %08lx) ...\n", (ulong)loader); - show_boot_progress(15); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); /* * NetBSD Stage-2 Loader Parameters: @@ -1398,7 +1394,7 @@ static int do_bootm_rtems(int flag, int argc, char * const argv[], printf("## Transferring control to RTEMS (at address %08lx) ...\n", (ulong)entry_point); - show_boot_progress(15); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); /* * RTEMS Parameters: @@ -1431,7 +1427,7 @@ static int do_bootm_ose(int flag, int argc, char * const argv[], printf("## Transferring control to OSE (at address %08lx) ...\n", (ulong)entry_point); - show_boot_progress(15); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); /* * OSE Parameters: @@ -1512,7 +1508,7 @@ static int do_bootm_integrity(int flag, int argc, char * const argv[], printf("## Transferring control to INTEGRITY (at address %08lx) ...\n", (ulong)entry_point); - show_boot_progress(15); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); /* * INTEGRITY Parameters: @@ -1523,3 +1519,127 @@ static int do_bootm_integrity(int flag, int argc, char * const argv[], return 1; } #endif + +#ifdef CONFIG_CMD_BOOTZ + +static int __bootz_setup(void *image, void **start, void **end) +{ + /* Please define bootz_setup() for your platform */ + + puts("Your platform's zImage format isn't supported yet!\n"); + return -1; +} +int bootz_setup(void *image, void **start, void **end) + __attribute__((weak, alias("__bootz_setup"))); + +/* + * zImage booting support + */ +static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[], bootm_headers_t *images) +{ + int ret; + void *zi_start, *zi_end; + + memset(images, 0, sizeof(bootm_headers_t)); + + boot_start_lmb(images); + + /* Setup Linux kernel zImage entry point */ + if (argc < 2) { + images->ep = load_addr; + debug("* kernel: default image load address = 0x%08lx\n", + load_addr); + } else { + images->ep = simple_strtoul(argv[1], NULL, 16); + debug("* kernel: cmdline image address = 0x%08lx\n", + images->ep); + } + + ret = bootz_setup((void *)images->ep, &zi_start, &zi_end); + if (ret != 0) + return 1; + + lmb_reserve(&images->lmb, images->ep, zi_end - zi_start); + + /* Find ramdisk */ + ret = boot_get_ramdisk(argc, argv, images, IH_INITRD_ARCH, + &images->rd_start, &images->rd_end); + if (ret) { + puts("Ramdisk image is corrupt or invalid\n"); + return 1; + } + +#if defined(CONFIG_OF_LIBFDT) + /* find flattened device tree */ + ret = boot_get_fdt(flag, argc, argv, images, + &images->ft_addr, &images->ft_len); + if (ret) { + puts("Could not find a valid device tree\n"); + return 1; + } + + set_working_fdt_addr(images->ft_addr); +#endif + + return 0; +} + +static int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + bootm_headers_t images; + + if (bootz_start(cmdtp, flag, argc, argv, &images)) + return 1; + + /* + * We have reached the point of no return: we are going to + * overwrite all exception vector code, so we cannot easily + * recover from any failures any more... + */ + disable_interrupts(); + +#if defined(CONFIG_CMD_USB) + /* + * turn off USB to prevent the host controller from writing to the + * SDRAM while Linux is booting. This could happen (at least for OHCI + * controller), because the HCCA (Host Controller Communication Area) + * lies within the SDRAM and the host controller writes continously to + * this area (as busmaster!). The HccaFrameNumber is for example + * updated every 1 ms within the HCCA structure in SDRAM! For more + * details see the OpenHCI specification. + */ + usb_stop(); +#endif + +#ifdef CONFIG_SILENT_CONSOLE + fixup_silent_linux(); +#endif + arch_preboot_os(); + + do_bootm_linux(0, argc, argv, &images); +#ifdef DEBUG + puts("\n## Control returned to monitor - resetting...\n"); +#endif + do_reset(cmdtp, flag, argc, argv); + + return 1; +} + +U_BOOT_CMD( + bootz, CONFIG_SYS_MAXARGS, 1, do_bootz, + "boot Linux zImage image from memory", + "[addr [initrd[:size]] [fdt]]\n" + " - boot Linux zImage stored in memory\n" + "\tThe argument 'initrd' is optional and specifies the address\n" + "\tof the initrd in memory. The optional argument ':size' allows\n" + "\tspecifying the size of RAW initrd.\n" +#if defined(CONFIG_OF_LIBFDT) + "\tWhen booting a Linux kernel which requires a flat device-tree\n" + "\ta third argument is required which is the address of the\n" + "\tdevice-tree blob. To boot that kernel without an initrd image,\n" + "\tuse a '-' for the second argument. If you do not pass a third\n" + "\ta bd_info struct will be passed instead\n" +#endif +); +#endif /* CONFIG_CMD_BOOTZ */