X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=common%2Fcmd_bootm.c;h=15f4599d45f28f5f005403abb9908c8cd07e0317;hb=0ac6db263132113f2ada36628a04e73d3dc2949a;hp=d5745b14e2ce54427ce7153759b0f39a0bb8fa3f;hpb=1086c5d6f8541460f0f10e4a302d8aac27e0e6e0;p=u-boot diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index d5745b14e2..15f4599d45 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #if defined(CONFIG_CMD_USB) @@ -47,7 +48,6 @@ #endif #if defined(CONFIG_OF_LIBFDT) -#include #include #include #endif @@ -80,10 +80,16 @@ static int image_info(unsigned long addr); #include #include extern flash_info_t flash_info[]; /* info for FLASH chips */ +#endif + +#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND) static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); #endif -#ifdef CONFIG_SILENT_CONSOLE +#include +#include + +#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY) static void fixup_silent_linux(void); #endif @@ -92,7 +98,7 @@ static image_header_t *image_get_kernel(ulong img_addr, int verify); static int fit_check_kernel(const void *fit, int os_noffset, int verify); #endif -static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, +static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], bootm_headers_t *images, ulong *os_data, ulong *os_len); @@ -123,6 +129,9 @@ static boot_os_fn do_bootm_rtems; #if defined(CONFIG_BOOTM_OSE) static boot_os_fn do_bootm_ose; #endif +#if defined(CONFIG_BOOTM_PLAN9) +static boot_os_fn do_bootm_plan9; +#endif #if defined(CONFIG_CMD_ELF) static boot_os_fn do_bootm_vxworks; static boot_os_fn do_bootm_qnxelf; @@ -149,6 +158,9 @@ static boot_os_fn *boot_os[] = { #if defined(CONFIG_BOOTM_OSE) [IH_OS_OSE] = do_bootm_ose, #endif +#if defined(CONFIG_BOOTM_PLAN9) + [IH_OS_PLAN9] = do_bootm_plan9, +#endif #if defined(CONFIG_CMD_ELF) [IH_OS_VXWORKS] = do_bootm_vxworks, [IH_OS_QNX] = do_bootm_qnxelf, @@ -161,7 +173,7 @@ static boot_os_fn *boot_os[] = { bootm_headers_t images; /* pointers to os/initrd/fdt images */ /* Allow for arch specific config before we boot */ -void __arch_preboot_os(void) +static void __arch_preboot_os(void) { /* please define platform specific arch_preboot_os() */ } @@ -169,35 +181,38 @@ 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[]) { - void *os_hdr; - int ret; + const void *os_hdr; + int ret; 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 +237,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 +260,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; @@ -261,7 +276,7 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] #if defined(CONFIG_FIT) } else if (images.fit_uname_os) { ret = fit_image_get_entry(images.fit_hdr_os, - images.fit_noffset_os, &images.ep); + images.fit_noffset_os, &images.ep); if (ret) { puts("Can't get entry point property!\n"); return 1; @@ -348,7 +363,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 +385,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 +404,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 +422,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 +438,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", @@ -445,9 +459,7 @@ static int bootm_start_standalone(ulong iflag, int argc, char * const argv[]) /* Don't start if "autostart" is set to "no" */ if (((s = getenv("autostart")) != NULL) && (strcmp(s, "no") == 0)) { - char buf[32]; - sprintf(buf, "%lX", images.os.image_len); - setenv("filesize", buf); + setenv_hex("filesize", images.os.image_len); return 0; } appl = (int (*)(int, char * const []))(ulong)ntohl(images.ep); @@ -472,7 +484,7 @@ static cmd_tbl_t cmd_bootm_sub[] = { U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""), }; -int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc, +static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int ret = 0; @@ -493,12 +505,13 @@ 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) { + if (images.state < BOOTM_STATE_START || + images.state >= state) { printf("Trying to execute a command out of order\n"); - return cmd_usage(cmdtp); + return CMD_RET_USAGE; } images.state |= state; @@ -521,21 +534,18 @@ int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc, case BOOTM_STATE_RAMDISK: { ulong rd_len = images.rd_end - images.rd_start; - char str[17]; ret = boot_ramdisk_high(&images.lmb, images.rd_start, rd_len, &images.initrd_start, &images.initrd_end); if (ret) return ret; - sprintf(str, "%lx", images.initrd_start); - setenv("initrd_start", str); - sprintf(str, "%lx", images.initrd_end); - setenv("initrd_end", str); + setenv_hex("initrd_start", images.initrd_start); + setenv_hex("initrd_end", images.initrd_end); } break; #endif -#if defined(CONFIG_OF_LIBFDT) +#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB) case BOOTM_STATE_FDT: { boot_fdt_add_mem_rsv_regions(&images.lmb, @@ -562,6 +572,13 @@ int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc, break; case BOOTM_STATE_OS_GO: disable_interrupts(); +#ifdef CONFIG_NETCONSOLE + /* + * Stop the ethernet stack if NetConsole could have + * left it up + */ + eth_halt(); +#endif arch_preboot_os(); boot_fn(BOOTM_STATE_OS_GO, argc, argv, &images); break; @@ -583,12 +600,18 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #ifdef CONFIG_NEEDS_MANUAL_RELOC static int relocated = 0; - /* relocate boot function table */ if (!relocated) { int i; + + /* relocate boot function table */ for (i = 0; i < ARRAY_SIZE(boot_os); i++) if (boot_os[i] != NULL) boot_os[i] += gd->reloc_off; + + /* relocate names of sub-command table */ + for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++) + cmd_bootm_sub[i].name += gd->reloc_off; + relocated = 1; } #endif @@ -620,6 +643,11 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) */ iflag = disable_interrupts(); +#ifdef CONFIG_NETCONSOLE + /* Stop the ethernet stack if NetConsole could have left it up */ + eth_halt(); +#endif + #if defined(CONFIG_CMD_USB) /* * turn off USB to prevent the host controller from writing to the @@ -649,14 +677,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,9 +699,9 @@ 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 defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY) if (images.os.os == IH_OS_LINUX) fixup_silent_linux(); #endif @@ -685,7 +713,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 +721,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 +763,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; @@ -788,30 +816,30 @@ static int fit_check_kernel(const void *fit, int os_noffset, int verify) if (verify) { puts(" Verifying Hash Integrity ... "); - if (!fit_image_check_hashes(fit, os_noffset)) { + if (!fit_image_verify(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 */ @@ -828,14 +856,15 @@ static int fit_check_kernel(const void *fit, int os_noffset, int verify) * pointer to image header if valid image was found, plus kernel start * address and length, otherwise NULL */ -static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, +static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], bootm_headers_t *images, ulong *os_data, ulong *os_len) { image_header_t *hdr; ulong img_addr; + const void *buf; #if defined(CONFIG_FIT) - void *fit_hdr; + const void *fit_hdr; const char *fit_uname_config = NULL; const char *fit_uname_kernel = NULL; const void *data; @@ -864,21 +893,22 @@ 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); /* check image type, for FIT images get FIT kernel node */ *os_data = *os_len = 0; - switch (genimg_get_format((void *)img_addr)) { + buf = map_sysmem(img_addr, 0); + switch (genimg_get_format(buf)) { case IMAGE_FORMAT_LEGACY: printf("## Booting kernel from Legacy Image at %08lx ...\n", img_addr); 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 +927,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,20 +942,20 @@ 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: - fit_hdr = (void *)img_addr; + fit_hdr = buf; printf("## Booting kernel from FIT Image at %08lx ...\n", img_addr); 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 +964,22 @@ 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); +#ifdef CONFIG_FIT_BEST_MATCH + if (fit_uname_config) + cfg_noffset = + fit_conf_get_node(fit_hdr, + fit_uname_config); + else + cfg_noffset = + fit_conf_find_compat(fit_hdr, + gd->fdt_blob); +#else cfg_noffset = fit_conf_get_node(fit_hdr, fit_uname_config); +#endif 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 +990,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,51 +998,50 @@ 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; - images->fit_hdr_os = fit_hdr; + images->fit_hdr_os = (void *)fit_hdr; images->fit_uname_os = fit_uname_kernel; images->fit_noffset_os = os_noffset; break; #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; } debug(" kernel data at 0x%08lx, len = 0x%08lx (%ld)\n", *os_data, *os_len, *os_len); - return (void *)img_addr; + return buf; } -U_BOOT_CMD( - bootm, CONFIG_SYS_MAXARGS, 1, do_bootm, - "boot application image from memory", +#ifdef CONFIG_SYS_LONGHELP +static char bootm_help_text[] = "[addr [arg ...]]\n - boot application image stored in memory\n" "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n" "\t'arg' can be the address of an initrd image\n" @@ -1025,7 +1065,7 @@ U_BOOT_CMD( "issued in the order below (it's ok to not issue all sub-commands):\n" "\tstart [addr [arg ...]]\n" "\tloados - load OS image\n" -#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) +#if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH) "\tramdisk - relocate initrd, set env initrd_start/initrd_end\n" #endif #if defined(CONFIG_OF_LIBFDT) @@ -1034,7 +1074,12 @@ U_BOOT_CMD( "\tcmdline - OS specific command line processing/setup\n" "\tbdt - OS specific bd_t processing\n" "\tprep - OS specific prep before relocation or go\n" - "\tgo - start OS" + "\tgo - start OS"; +#endif + +U_BOOT_CMD( + bootm, CONFIG_SYS_MAXARGS, 1, do_bootm, + "boot application image from memory", bootm_help_text ); /*******************************************************************/ @@ -1045,14 +1090,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; } @@ -1076,7 +1115,7 @@ U_BOOT_CMD( /* iminfo - print header info for a requested image */ /*******************************************************************/ #if defined(CONFIG_CMD_IMI) -int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +static int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int arg; ulong addr; @@ -1133,7 +1172,7 @@ static int image_info(ulong addr) fit_print_contents(hdr); - if (!fit_all_image_check_hashes(hdr)) { + if (!fit_all_image_verify(hdr)) { puts("Bad hash in FIT image!\n"); return 1; } @@ -1163,7 +1202,7 @@ U_BOOT_CMD( /* imls - list all images found in flash */ /*******************************************************************/ #if defined(CONFIG_CMD_IMLS) -int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +static int do_imls_nor(void) { flash_info_t *info; int i, j; @@ -1212,6 +1251,161 @@ next_sector: ; } next_bank: ; } + return 0; +} +#endif + +#if defined(CONFIG_CMD_IMLS_NAND) +static int nand_imls_legacyimage(nand_info_t *nand, int nand_dev, loff_t off, + size_t len) +{ + void *imgdata; + int ret; + + imgdata = malloc(len); + if (!imgdata) { + printf("May be a Legacy Image at NAND device %d offset %08llX:\n", + nand_dev, off); + printf(" Low memory(cannot allocate memory for image)\n"); + return -ENOMEM; + } + + ret = nand_read_skip_bad(nand, off, &len, + imgdata); + if (ret < 0 && ret != -EUCLEAN) { + free(imgdata); + return ret; + } + + if (!image_check_hcrc(imgdata)) { + free(imgdata); + return 0; + } + + printf("Legacy Image at NAND device %d offset %08llX:\n", + nand_dev, off); + image_print_contents(imgdata); + + puts(" Verifying Checksum ... "); + if (!image_check_dcrc(imgdata)) + puts("Bad Data CRC\n"); + else + puts("OK\n"); + + free(imgdata); + + return 0; +} + +static int nand_imls_fitimage(nand_info_t *nand, int nand_dev, loff_t off, + size_t len) +{ + void *imgdata; + int ret; + + imgdata = malloc(len); + if (!imgdata) { + printf("May be a FIT Image at NAND device %d offset %08llX:\n", + nand_dev, off); + printf(" Low memory(cannot allocate memory for image)\n"); + return -ENOMEM; + } + + ret = nand_read_skip_bad(nand, off, &len, + imgdata); + if (ret < 0 && ret != -EUCLEAN) { + free(imgdata); + return ret; + } + + if (!fit_check_format(imgdata)) { + free(imgdata); + return 0; + } + + printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off); + + fit_print_contents(imgdata); + free(imgdata); + + return 0; +} + +static int do_imls_nand(void) +{ + nand_info_t *nand; + int nand_dev = nand_curr_device; + size_t len; + loff_t off; + u32 buffer[16]; + + if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) { + puts("\nNo NAND devices available\n"); + return -ENODEV; + } + + printf("\n"); + + for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) { + nand = &nand_info[nand_dev]; + if (!nand->name || !nand->size) + continue; + + for (off = 0; off < nand->size; off += nand->erasesize) { + const image_header_t *header; + int ret; + + if (nand_block_isbad(nand, off)) + continue; + + len = sizeof(buffer); + + ret = nand_read(nand, off, &len, (u8 *)buffer); + if (ret < 0 && ret != -EUCLEAN) { + printf("NAND read error %d at offset %08llX\n", + ret, off); + continue; + } + + switch (genimg_get_format(buffer)) { + case IMAGE_FORMAT_LEGACY: + header = (const image_header_t *)buffer; + + len = image_get_image_size(header); + nand_imls_legacyimage(nand, nand_dev, off, len); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + len = fit_get_size(buffer); + nand_imls_fitimage(nand, nand_dev, off, len); + break; +#endif + } + } + } + + return 0; +} +#endif + +#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND) +static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int ret_nor = 0, ret_nand = 0; + +#if defined(CONFIG_CMD_IMLS) + ret_nor = do_imls_nor(); +#endif + +#if defined(CONFIG_CMD_IMLS_NAND) + ret_nand = do_imls_nand(); +#endif + + if (ret_nor) + return ret_nor; + + if (ret_nand) + return ret_nand; return (0); } @@ -1220,18 +1414,23 @@ U_BOOT_CMD( imls, 1, 1, do_imls, "list all images found in flash", "\n" - " - Prints information about all images found at sector\n" - " boundaries in flash." + " - Prints information about all images found at sector/block\n" + " boundaries in nor/nand flash." ); #endif /*******************************************************************/ /* helper routines */ /*******************************************************************/ -#ifdef CONFIG_SILENT_CONSOLE +#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY) + +#define CONSOLE_ARG "console=" +#define CONSOLE_ARG_LEN (sizeof(CONSOLE_ARG) - 1) + static void fixup_silent_linux(void) { - char buf[256], *start, *end; + char *buf; + const char *env_val; char *cmdline = getenv("bootargs"); /* Only fix cmdline when requested */ @@ -1239,25 +1438,37 @@ static void fixup_silent_linux(void) return; debug("before silent fix-up: %s\n", cmdline); - if (cmdline) { - start = strstr(cmdline, "console="); + if (cmdline && (cmdline[0] != '\0')) { + char *start = strstr(cmdline, CONSOLE_ARG); + + /* Allocate space for maximum possible new command line */ + buf = malloc(strlen(cmdline) + 1 + CONSOLE_ARG_LEN + 1); + if (!buf) { + debug("%s: out of memory\n", __func__); + return; + } + if (start) { - end = strchr(start, ' '); - strncpy(buf, cmdline, (start - cmdline + 8)); + char *end = strchr(start, ' '); + int num_start_bytes = start - cmdline + CONSOLE_ARG_LEN; + + strncpy(buf, cmdline, num_start_bytes); if (end) - strcpy(buf + (start - cmdline + 8), end); + strcpy(buf + num_start_bytes, end); else - buf[start - cmdline + 8] = '\0'; + buf[num_start_bytes] = '\0'; } else { - strcpy(buf, cmdline); - strcat(buf, " console="); + sprintf(buf, "%s %s", cmdline, CONSOLE_ARG); } + env_val = buf; } else { - strcpy(buf, "console="); + buf = NULL; + env_val = CONSOLE_ARG; } - setenv("bootargs", buf); - debug("after silent fix-up: %s\n", buf); + setenv("bootargs", env_val); + debug("after silent fix-up: %s\n", env_val); + free(buf); } #endif /* CONFIG_SILENT_CONSOLE */ @@ -1340,7 +1551,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 +1609,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 +1642,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: @@ -1443,6 +1654,39 @@ static int do_bootm_ose(int flag, int argc, char * const argv[], } #endif /* CONFIG_BOOTM_OSE */ +#if defined(CONFIG_BOOTM_PLAN9) +static int do_bootm_plan9(int flag, int argc, char * const argv[], + bootm_headers_t *images) +{ + void (*entry_point)(void); + + if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) + return 1; + +#if defined(CONFIG_FIT) + if (!images->legacy_hdr_valid) { + fit_unsupported_reset("Plan 9"); + return 1; + } +#endif + + entry_point = (void (*)(void))images->ep; + + printf("## Transferring control to Plan 9 (at address %08lx) ...\n", + (ulong)entry_point); + + bootstage_mark(BOOTSTAGE_ID_RUN_OS); + + /* + * Plan 9 Parameters: + * None + */ + (*entry_point)(); + + return 1; +} +#endif /* CONFIG_BOOTM_PLAN9 */ + #if defined(CONFIG_CMD_ELF) static int do_bootm_vxworks(int flag, int argc, char * const argv[], bootm_headers_t *images) @@ -1512,7 +1756,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 +1767,137 @@ 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(); + +#ifdef CONFIG_NETCONSOLE + /* Stop the ethernet stack if NetConsole could have left it up */ + eth_halt(); +#endif + +#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 + +#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY) + 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; +} + +#ifdef CONFIG_SYS_LONGHELP +static char bootz_help_text[] = + "[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 + +U_BOOT_CMD( + bootz, CONFIG_SYS_MAXARGS, 1, do_bootz, + "boot Linux zImage image from memory", bootz_help_text +); +#endif /* CONFIG_CMD_BOOTZ */