X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=common%2Fcmd_bootm.c;h=15f4599d45f28f5f005403abb9908c8cd07e0317;hb=0ac6db263132113f2ada36628a04e73d3dc2949a;hp=32fd9bb3f3cdcaa2f9eca34f8803418850c7767e;hpb=7c32dc5bed053348003da5ba3635d4c61c420e66;p=u-boot diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 32fd9bb3f3..15f4599d45 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -36,6 +36,8 @@ #include #include #include +#include +#include #if defined(CONFIG_CMD_USB) #include @@ -46,7 +48,6 @@ #endif #if defined(CONFIG_OF_LIBFDT) -#include #include #include #endif @@ -57,9 +58,12 @@ #include #endif /* CONFIG_LZMA */ +#ifdef CONFIG_LZO +#include +#endif /* CONFIG_LZO */ + DECLARE_GLOBAL_DATA_PTR; -extern int gunzip (void *dst, int dstlen, unsigned char *src, unsigned long *lenp); #ifndef CONFIG_SYS_BOOTM_LEN #define CONFIG_SYS_BOOTM_LEN 0x800000 /* use 8MByte as default max gunzip size */ #endif @@ -69,27 +73,34 @@ extern void bz_internal_error(int); #endif #if defined(CONFIG_CMD_IMI) -static int image_info (unsigned long addr); +static int image_info(unsigned long addr); #endif #if defined(CONFIG_CMD_IMLS) #include +#include extern flash_info_t flash_info[]; /* info for FLASH chips */ -static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); #endif -#ifdef CONFIG_SILENT_CONSOLE -static void fixup_silent_linux (void); +#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 -static image_header_t *image_get_kernel (ulong img_addr, int verify); +#include +#include + +#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY) +static void fixup_silent_linux(void); +#endif + +static image_header_t *image_get_kernel(ulong img_addr, int verify); #if defined(CONFIG_FIT) -static int fit_check_kernel (const void *fit, int os_noffset, 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, char *argv[], - bootm_headers_t *images, ulong *os_data, ulong *os_len); -extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +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); /* * Continue booting an OS image; caller already has: @@ -99,13 +110,9 @@ extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); * - loaded (first part of) image to header load address, * - disabled interrupts. */ -typedef int boot_os_fn (int flag, int argc, char *argv[], +typedef int boot_os_fn(int flag, int argc, char * const argv[], bootm_headers_t *images); /* pointers to os/initrd/fdt */ -#define CONFIG_BOOTM_LINUX 1 -#define CONFIG_BOOTM_NETBSD 1 -#define CONFIG_BOOTM_RTEMS 1 - #ifdef CONFIG_BOOTM_LINUX extern boot_os_fn do_bootm_linux; #endif @@ -114,22 +121,28 @@ static boot_os_fn do_bootm_netbsd; #endif #if defined(CONFIG_LYNXKDI) static boot_os_fn do_bootm_lynxkdi; -extern void lynxkdi_boot (image_header_t *); +extern void lynxkdi_boot(image_header_t *); #endif #ifdef CONFIG_BOOTM_RTEMS static boot_os_fn do_bootm_rtems; #endif +#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; -int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); -int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); +int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); #endif #if defined(CONFIG_INTEGRITY) static boot_os_fn do_bootm_integrity; #endif -boot_os_fn * boot_os[] = { +static boot_os_fn *boot_os[] = { #ifdef CONFIG_BOOTM_LINUX [IH_OS_LINUX] = do_bootm_linux, #endif @@ -142,6 +155,12 @@ boot_os_fn * boot_os[] = { #ifdef CONFIG_BOOTM_RTEMS [IH_OS_RTEMS] = do_bootm_rtems, #endif +#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, @@ -151,170 +170,150 @@ boot_os_fn * boot_os[] = { #endif }; -ulong load_addr = CONFIG_SYS_LOAD_ADDR; /* Default Load Address */ -static bootm_headers_t images; /* pointers to os/initrd/fdt images */ - -void __board_lmb_reserve(struct lmb *lmb) -{ - /* please define platform specific board_lmb_reserve() */ -} -void board_lmb_reserve(struct lmb *lmb) __attribute__((weak, alias("__board_lmb_reserve"))); - -void __arch_lmb_reserve(struct lmb *lmb) -{ - /* please define platform specific arch_lmb_reserve() */ -} -void arch_lmb_reserve(struct lmb *lmb) __attribute__((weak, alias("__arch_lmb_reserve"))); +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() */ } void arch_preboot_os(void) __attribute__((weak, alias("__arch_preboot_os"))); -#if defined(__ARM__) - #define IH_INITRD_ARCH IH_ARCH_ARM -#elif defined(__avr32__) - #define IH_INITRD_ARCH IH_ARCH_AVR32 -#elif defined(__bfin__) - #define IH_INITRD_ARCH IH_ARCH_BLACKFIN -#elif defined(__I386__) - #define IH_INITRD_ARCH IH_ARCH_I386 -#elif defined(__M68K__) - #define IH_INITRD_ARCH IH_ARCH_M68K -#elif defined(__microblaze__) - #define IH_INITRD_ARCH IH_ARCH_MICROBLAZE -#elif defined(__mips__) - #define IH_INITRD_ARCH IH_ARCH_MIPS -#elif defined(__nios__) - #define IH_INITRD_ARCH IH_ARCH_NIOS -#elif defined(__nios2__) - #define IH_INITRD_ARCH IH_ARCH_NIOS2 -#elif defined(__PPC__) - #define IH_INITRD_ARCH IH_ARCH_PPC -#elif defined(__sh__) - #define IH_INITRD_ARCH IH_ARCH_SH -#elif defined(__sparc__) - #define IH_INITRD_ARCH IH_ARCH_SPARC -#else -# error Unknown CPU type -#endif +#define IH_INITRD_ARCH IH_ARCH_DEFAULT -static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +#ifdef CONFIG_LMB +static void boot_start_lmb(bootm_headers_t *images) { ulong mem_start; phys_size_t mem_size; - void *os_hdr; - int ret; - memset ((void *)&images, 0, sizeof (images)); - images.verify = getenv_yesno ("verify"); - - 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); +} +#else +#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[]) +{ + const void *os_hdr; + int ret; + + memset((void *)&images, 0, sizeof(images)); + images.verify = getenv_yesno("verify"); + + boot_start_lmb(&images); - arch_lmb_reserve(&images.lmb); - board_lmb_reserve(&images.lmb); + 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, + os_hdr = boot_get_kernel(cmdtp, flag, argc, argv, &images, &images.os.image_start, &images.os.image_len); if (images.os.image_len == 0) { - puts ("ERROR: can't get kernel image!\n"); + puts("ERROR: can't get kernel image!\n"); return 1; } /* get image parameters */ - switch (genimg_get_format (os_hdr)) { + switch (genimg_get_format(os_hdr)) { case IMAGE_FORMAT_LEGACY: - images.os.type = image_get_type (os_hdr); - images.os.comp = image_get_comp (os_hdr); - images.os.os = image_get_os (os_hdr); + images.os.type = image_get_type(os_hdr); + images.os.comp = image_get_comp(os_hdr); + images.os.os = image_get_os(os_hdr); - images.os.end = image_get_image_end (os_hdr); - images.os.load = image_get_load (os_hdr); + images.os.end = image_get_image_end(os_hdr); + images.os.load = image_get_load(os_hdr); break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: - if (fit_image_get_type (images.fit_hdr_os, + 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); + puts("Can't get image type!\n"); + bootstage_error(BOOTSTAGE_ID_FIT_TYPE); return 1; } - if (fit_image_get_comp (images.fit_hdr_os, + 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); + puts("Can't get image compression!\n"); + bootstage_error(BOOTSTAGE_ID_FIT_COMPRESSION); return 1; } - if (fit_image_get_os (images.fit_hdr_os, + 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); + puts("Can't get image OS!\n"); + bootstage_error(BOOTSTAGE_ID_FIT_OS); return 1; } - images.os.end = fit_get_end (images.fit_hdr_os); + images.os.end = fit_get_end(images.fit_hdr_os); - if (fit_image_get_load (images.fit_hdr_os, images.fit_noffset_os, + 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); + puts("Can't get image load address!\n"); + bootstage_error(BOOTSTAGE_ID_FIT_LOADADDR); return 1; } break; #endif default: - puts ("ERROR: unknown image format type!\n"); + puts("ERROR: unknown image format type!\n"); return 1; } /* find kernel entry point */ if (images.legacy_hdr_valid) { - images.ep = image_get_ep (&images.legacy_hdr_os_copy); + images.ep = image_get_ep(&images.legacy_hdr_os_copy); #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); + ret = fit_image_get_entry(images.fit_hdr_os, + images.fit_noffset_os, &images.ep); if (ret) { - puts ("Can't get entry point property!\n"); + puts("Can't get entry point property!\n"); return 1; } #endif } else { - puts ("Could not find kernel entry point!\n"); + puts("Could not find kernel entry point!\n"); return 1; } - if (images.os.os == IH_OS_LINUX) { + if (images.os.type == IH_TYPE_KERNEL_NOLOAD) { + images.os.load = images.os.image_start; + images.ep += images.os.load; + } + + if (((images.os.type == IH_TYPE_KERNEL) || + (images.os.type == IH_TYPE_KERNEL_NOLOAD) || + (images.os.type == IH_TYPE_MULTI)) && + (images.os.os == IH_OS_LINUX)) { /* find ramdisk */ - ret = boot_get_ramdisk (argc, argv, &images, IH_INITRD_ARCH, + 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"); + puts("Ramdisk image is corrupt or invalid\n"); return 1; } #if defined(CONFIG_OF_LIBFDT) -#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) /* find flattened device tree */ - ret = boot_get_fdt (flag, argc, argv, &images, - &images.ft_addr, &images.ft_len); + 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"); + puts("Could not find a valid device tree\n"); return 1; } set_working_fdt_addr(images.ft_addr); -#endif #endif } @@ -335,54 +334,58 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) ulong blob_end = os.end; ulong image_start = os.image_start; ulong image_len = os.image_len; - uint unc_len = CONFIG_SYS_BOOTM_LEN; + __maybe_unused uint unc_len = CONFIG_SYS_BOOTM_LEN; + int no_overlap = 0; +#if defined(CONFIG_LZMA) || defined(CONFIG_LZO) + int ret; +#endif /* defined(CONFIG_LZMA) || defined(CONFIG_LZO) */ - const char *type_name = genimg_get_type_name (os.type); + const char *type_name = genimg_get_type_name(os.type); switch (comp) { case IH_COMP_NONE: - if (load == blob_start) { - printf (" XIP %s ... ", type_name); + if (load == blob_start || load == image_start) { + printf(" XIP %s ... ", type_name); + no_overlap = 1; } else { - printf (" Loading %s ... ", type_name); - - if (load != image_start) { - memmove_wd ((void *)load, - (void *)image_start, image_len, CHUNKSZ); - } + printf(" Loading %s ... ", type_name); + memmove_wd((void *)load, (void *)image_start, + image_len, CHUNKSZ); } *load_end = load + image_len; puts("OK\n"); break; +#ifdef CONFIG_GZIP case IH_COMP_GZIP: - printf (" Uncompressing %s ... ", type_name); - if (gunzip ((void *)load, unc_len, - (uchar *)image_start, &image_len) != 0) { - puts ("GUNZIP: uncompress, out-of-mem or overwrite error " - "- must RESET board to recover\n"); + printf(" Uncompressing %s ... ", type_name); + if (gunzip((void *)load, unc_len, + (uchar *)image_start, &image_len) != 0) { + 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; } *load_end = load + image_len; break; +#endif /* CONFIG_GZIP */ #ifdef CONFIG_BZIP2 case IH_COMP_BZIP2: - printf (" Uncompressing %s ... ", type_name); + printf(" Uncompressing %s ... ", type_name); /* * If we've got less than 4 MB of malloc() space, * use slower decompression algorithm which requires * at most 2300 KB of memory. */ - int i = BZ2_bzBuffToBuffDecompress ((char*)load, + int i = BZ2_bzBuffToBuffDecompress((char *)load, &unc_len, (char *)image_start, image_len, CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); if (i != BZ_OK) { - printf ("BUNZIP2: uncompress or overwrite error %d " + 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; } @@ -390,33 +393,58 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) break; #endif /* CONFIG_BZIP2 */ #ifdef CONFIG_LZMA - case IH_COMP_LZMA: - printf (" Uncompressing %s ... ", type_name); + case IH_COMP_LZMA: { + SizeT lzma_len = unc_len; + printf(" Uncompressing %s ... ", type_name); - int ret = lzmaBuffToBuffDecompress( - (unsigned char *)load, &unc_len, + ret = lzmaBuffToBuffDecompress( + (unsigned char *)load, &lzma_len, (unsigned char *)image_start, image_len); + unc_len = lzma_len; if (ret != SZ_OK) { - printf ("LZMA: uncompress or overwrite error %d " + 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; break; + } #endif /* CONFIG_LZMA */ +#ifdef CONFIG_LZO + case IH_COMP_LZO: + printf(" Uncompressing %s ... ", type_name); + + ret = lzop_decompress((const unsigned char *)image_start, + image_len, (unsigned char *)load, + &unc_len); + if (ret != LZO_E_OK) { + printf("LZO: uncompress or overwrite error %d " + "- must RESET board to recover\n", ret); + if (boot_progress) + bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); + return BOOTM_ERR_RESET; + } + + *load_end = load + unc_len; + break; +#endif /* CONFIG_LZO */ default: - printf ("Unimplemented compression type %d\n", comp); + printf("Unimplemented compression type %d\n", comp); return BOOTM_ERR_UNIMPLEMENTED; } - puts ("OK\n"); - debug (" kernel loaded at 0x%08lx, end = 0x%08lx\n", load, *load_end); - if (boot_progress) - show_boot_progress (7); - if ((load < blob_end) && (*load_end > blob_start)) { - debug ("images.os.start = 0x%lX, images.os.end = 0x%lx\n", blob_start, blob_end); - debug ("images.os.load = 0x%lx, load_end = 0x%lx\n", load, *load_end); + flush_cache(load, (*load_end - load) * sizeof(ulong)); + + puts("OK\n"); + debug(" kernel loaded at 0x%08lx, end = 0x%08lx\n", load, *load_end); + 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", + blob_start, blob_end); + debug("images.os.load = 0x%lx, load_end = 0x%lx\n", load, + *load_end); return BOOTM_ERR_OVERLAP; } @@ -424,52 +452,50 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) return 0; } -static int bootm_start_standalone(ulong iflag, int argc, char *argv[]) +static int bootm_start_standalone(ulong iflag, int argc, char * const argv[]) { char *s; - int (*appl)(int, char *[]); + int (*appl)(int, char * const []); /* 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 *[]))ntohl(images.ep); + appl = (int (*)(int, char * const []))(ulong)ntohl(images.ep); (*appl)(argc-1, &argv[1]); - return 0; } /* we overload the cmd field with our state machine info instead of a * function pointer */ -cmd_tbl_t cmd_bootm_sub[] = { +static cmd_tbl_t cmd_bootm_sub[] = { U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""), U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""), -#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) +#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""), #endif #ifdef CONFIG_OF_LIBFDT U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)BOOTM_STATE_FDT, "", ""), #endif - U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""), U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""), + U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""), U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""), U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""), }; -int do_bootm_subcommand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { int ret = 0; - int state; + long state; cmd_tbl_t *c; boot_os_fn *boot_fn; c = find_cmd_tbl(argv[1], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub)); if (c) { - state = (int)c->cmd; + state = (long)c->cmd; /* treat start special since it resets the state machine */ if (state == BOOTM_STATE_START) { @@ -477,17 +503,15 @@ int do_bootm_subcommand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) argv++; return bootm_start(cmdtp, flag, argc, argv); } - } - /* Unrecognized command */ - else { - cmd_usage(cmdtp); - return 1; + } else { + /* Unrecognized command */ + return CMD_RET_USAGE; } - if (images.state >= state) { - printf ("Trying to execute a command out of order\n"); - cmd_usage(cmdtp); - return 1; + if (images.state < BOOTM_STATE_START || + images.state >= state) { + printf("Trying to execute a command out of order\n"); + return CMD_RET_USAGE; } images.state |= state; @@ -506,29 +530,27 @@ int do_bootm_subcommand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load)); break; -#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) +#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH 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) && defined(CONFIG_SYS_BOOTMAPSZ) +#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB) case BOOTM_STATE_FDT: { - ulong bootmap_base = getenv_bootm_low(); - ret = boot_relocate_fdt(&images.lmb, bootmap_base, + boot_fdt_add_mem_rsv_regions(&images.lmb, + images.ft_addr); + ret = boot_relocate_fdt(&images.lmb, &images.ft_addr, &images.ft_len); break; } @@ -536,20 +558,27 @@ int do_bootm_subcommand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) case BOOTM_STATE_OS_CMDLINE: ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, &images); if (ret) - printf ("cmdline subcommand not supported\n"); + printf("cmdline subcommand not supported\n"); break; case BOOTM_STATE_OS_BD_T: ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, &images); if (ret) - printf ("bdt subcommand not supported\n"); + printf("bdt subcommand not supported\n"); break; case BOOTM_STATE_OS_PREP: ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, &images); if (ret) - printf ("prep subcommand not supported\n"); + printf("prep subcommand not supported\n"); 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; @@ -562,21 +591,27 @@ int do_bootm_subcommand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) /* bootm - boot application image from image in memory */ /*******************************************************************/ -int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { ulong iflag; ulong load_end = 0; int ret; boot_os_fn *boot_fn; -#ifndef CONFIG_RELOC_FIXUP_WORKS +#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 @@ -608,6 +643,11 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *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 @@ -621,36 +661,30 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) usb_stop(); #endif -#ifdef CONFIG_AMIGAONEG3SE - /* - * We've possible left the caches enabled during - * bios emulation, so turn them off again - */ - icache_disable(); - dcache_disable(); -#endif - ret = bootm_load_os(images.os, &load_end, 1); if (ret < 0) { if (ret == BOOTM_ERR_RESET) - do_reset (cmdtp, flag, argc, argv); + do_reset(cmdtp, flag, argc, argv); if (ret == BOOTM_ERR_OVERLAP) { if (images.legacy_hdr_valid) { - if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI) - puts ("WARNING: legacy format multi component " - "image overwritten\n"); + image_header_t *hdr; + hdr = &images.legacy_hdr_os_copy; + if (image_get_type(hdr) == IH_TYPE_MULTI) + puts("WARNING: legacy format multi " + "component image " + "overwritten\n"); } else { - puts ("ERROR: new format image overwritten - " + puts("ERROR: new format image overwritten - " "must RESET the board to recover\n"); - show_boot_progress (-113); - do_reset (cmdtp, flag, argc, argv); + 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; } } @@ -665,9 +699,9 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *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 @@ -677,9 +711,9 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) if (boot_fn == NULL) { if (iflag) enable_interrupts(); - printf ("ERROR: booting os '%s' (%d) is not supported\n", + 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; } @@ -687,15 +721,30 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *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"); + puts("\n## Control returned to monitor - resetting...\n"); #endif - do_reset (cmdtp, flag, argc, argv); + do_reset(cmdtp, flag, argc, argv); return 1; } +int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd) +{ + const char *ep = getenv("autostart"); + + if (ep && !strcmp(ep, "yes")) { + char *local_args[2]; + local_args[0] = (char *)cmd; + local_args[1] = NULL; + printf("Automatic boot of image at addr 0x%08lX ...\n", load_addr); + return do_bootm(cmdtp, 0, 1, local_args); + } + + return 0; +} + /** * image_get_kernel - verify legacy format kernel image * @img_addr: in RAM address of the legacy format image to be verified @@ -708,40 +757,40 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) * pointer to a legacy image header if valid image was found * otherwise return NULL */ -static image_header_t *image_get_kernel (ulong img_addr, int verify) +static image_header_t *image_get_kernel(ulong img_addr, int verify) { image_header_t *hdr = (image_header_t *)img_addr; if (!image_check_magic(hdr)) { - puts ("Bad Magic Number\n"); - show_boot_progress (-1); + puts("Bad Magic Number\n"); + 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); + if (!image_check_hcrc(hdr)) { + puts("Bad Header Checksum\n"); + bootstage_error(BOOTSTAGE_ID_CHECK_HEADER); return NULL; } - show_boot_progress (3); - image_print_contents (hdr); + 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); + puts(" Verifying Checksum ... "); + if (!image_check_dcrc(hdr)) { + printf("Bad Data CRC\n"); + bootstage_error(BOOTSTAGE_ID_CHECK_CHECKSUM); return NULL; } - puts ("OK\n"); + 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); + if (!image_check_target_arch(hdr)) { + printf("Unsupported Architecture 0x%x\n", image_get_arch(hdr)); + bootstage_error(BOOTSTAGE_ID_CHECK_ARCH); return NULL; } return hdr; @@ -760,36 +809,37 @@ static image_header_t *image_get_kernel (ulong img_addr, int verify) * 1, on success * 0, on failure */ -#if defined (CONFIG_FIT) -static int fit_check_kernel (const void *fit, int os_noffset, int verify) +#if defined(CONFIG_FIT) +static int fit_check_kernel(const void *fit, int os_noffset, int verify) { - fit_image_print (fit, os_noffset, " "); + fit_image_print(fit, os_noffset, " "); if (verify) { - puts (" Verifying Hash Integrity ... "); - if (!fit_image_check_hashes (fit, os_noffset)) { - puts ("Bad Data Hash\n"); - show_boot_progress (-104); + puts(" Verifying Hash Integrity ... "); + if (!fit_image_verify(fit, os_noffset)) { + puts("Bad Data Hash\n"); + bootstage_error(BOOTSTAGE_ID_FIT_CHECK_HASH); return 0; } - puts ("OK\n"); + 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); + if (!fit_image_check_target_arch(fit, os_noffset)) { + puts("Unsupported Architecture\n"); + bootstage_error(BOOTSTAGE_ID_FIT_CHECK_ARCH); return 0; } - show_boot_progress (106); - if (!fit_image_check_type (fit, os_noffset, IH_TYPE_KERNEL)) { - puts ("Not a kernel image\n"); - 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"); + bootstage_error(BOOTSTAGE_ID_FIT_CHECK_KERNEL); return 0; } - show_boot_progress (107); + bootstage_mark(BOOTSTAGE_ID_FIT_CHECKED); return 1; } #endif /* CONFIG_FIT */ @@ -806,13 +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, char *argv[], - bootm_headers_t *images, ulong *os_data, ulong *os_len) +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; @@ -824,153 +876,172 @@ static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] /* find out kernel image address */ if (argc < 2) { img_addr = load_addr; - debug ("* kernel: default image load address = 0x%08lx\n", + debug("* kernel: default image load address = 0x%08lx\n", load_addr); #if defined(CONFIG_FIT) - } else if (fit_parse_conf (argv[1], load_addr, &img_addr, + } else if (fit_parse_conf(argv[1], load_addr, &img_addr, &fit_uname_config)) { - debug ("* kernel: config '%s' from image at 0x%08lx\n", + debug("* kernel: config '%s' from image at 0x%08lx\n", fit_uname_config, img_addr); - } else if (fit_parse_subimage (argv[1], load_addr, &img_addr, + } else if (fit_parse_subimage(argv[1], load_addr, &img_addr, &fit_uname_kernel)) { - debug ("* kernel: subimage '%s' from image at 0x%08lx\n", + debug("* kernel: subimage '%s' from image at 0x%08lx\n", fit_uname_kernel, img_addr); #endif } else { img_addr = simple_strtoul(argv[1], NULL, 16); - debug ("* kernel: cmdline image address = 0x%08lx\n", img_addr); + 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); + 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", + printf("## Booting kernel from Legacy Image at %08lx ...\n", img_addr); - hdr = image_get_kernel (img_addr, images->verify); + 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)) { + switch (image_get_type(hdr)) { case IH_TYPE_KERNEL: - *os_data = image_get_data (hdr); - *os_len = image_get_data_size (hdr); + case IH_TYPE_KERNEL_NOLOAD: + *os_data = image_get_data(hdr); + *os_len = image_get_data_size(hdr); break; case IH_TYPE_MULTI: - image_multi_getimg (hdr, 0, os_data, os_len); + image_multi_getimg(hdr, 0, os_data, os_len); break; case IH_TYPE_STANDALONE: - if (argc >2) { - hdr->ih_load = htonl(simple_strtoul(argv[2], NULL, 16)); - } - *os_data = image_get_data (hdr); - *os_len = image_get_data_size (hdr); + *os_data = image_get_data(hdr); + *os_len = image_get_data_size(hdr); break; default: - printf ("Wrong Image Type for %s command\n", cmdtp->name); - show_boot_progress (-5); + printf("Wrong Image Type for %s command\n", + cmdtp->name); + bootstage_error(BOOTSTAGE_ID_CHECK_IMAGETYPE); return NULL; } /* - * copy image header to allow for image overwrites during kernel - * decompression. + * copy image header to allow for image overwrites during + * kernel decompression. */ - memmove (&images->legacy_hdr_os_copy, hdr, sizeof(image_header_t)); + memmove(&images->legacy_hdr_os_copy, hdr, + sizeof(image_header_t)); /* save pointer to image header */ 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; - printf ("## Booting kernel from FIT Image at %08lx ...\n", + 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); + if (!fit_check_format(fit_hdr)) { + puts("Bad FIT kernel image format!\n"); + bootstage_error(BOOTSTAGE_ID_FIT_FORMAT); return NULL; } - show_boot_progress (100); + bootstage_mark(BOOTSTAGE_ID_FIT_FORMAT); if (!fit_uname_kernel) { /* * no kernel image node unit name, try to get config * node first. If config unit node name is NULL - * fit_conf_get_node() will try to find default config node + * fit_conf_get_node() will try to find default config + * node */ - show_boot_progress (101); - cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); + 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 * bootm argument */ - images->fit_uname_cfg = fdt_get_name (fit_hdr, cfg_noffset, NULL); - printf (" Using '%s' configuration\n", images->fit_uname_cfg); - show_boot_progress (103); - - os_noffset = fit_conf_get_kernel_node (fit_hdr, cfg_noffset); - fit_uname_kernel = fit_get_name (fit_hdr, os_noffset, NULL); + images->fit_uname_cfg = fdt_get_name(fit_hdr, + cfg_noffset, + NULL); + printf(" Using '%s' configuration\n", + images->fit_uname_cfg); + bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG); + + os_noffset = fit_conf_get_kernel_node(fit_hdr, + cfg_noffset); + fit_uname_kernel = fit_get_name(fit_hdr, os_noffset, + NULL); } else { /* get kernel component image node offset */ - show_boot_progress (102); - os_noffset = fit_image_get_node (fit_hdr, fit_uname_kernel); + 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); + printf(" Trying '%s' kernel subimage\n", fit_uname_kernel); - show_boot_progress (104); - if (!fit_check_kernel (fit_hdr, os_noffset, images->verify)) + 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); + if (fit_image_get_data(fit_hdr, os_noffset, &data, &len)) { + puts("Could not find kernel subimage data!\n"); + 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); + printf("Wrong Image Format for %s command\n", cmdtp->name); + bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO); return NULL; } - debug (" kernel data at 0x%08lx, len = 0x%08lx (%ld)\n", + 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" @@ -994,34 +1065,33 @@ 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) "\tfdt - relocate flat device tree\n" #endif - "\tbdt - OS specific bd_t processing\n" "\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 ); /*******************************************************************/ /* bootd - boot default image */ /*******************************************************************/ #if defined(CONFIG_CMD_BOOTD) -int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +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) + if (run_command(getenv("bootcmd"), flag) < 0) rcode = 1; -#endif return rcode; } @@ -1045,72 +1115,72 @@ 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 *argv[]) +static int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int arg; ulong addr; int rcode = 0; if (argc < 2) { - return image_info (load_addr); + return image_info(load_addr); } for (arg = 1; arg < argc; ++arg) { - addr = simple_strtoul (argv[arg], NULL, 16); - if (image_info (addr) != 0) + addr = simple_strtoul(argv[arg], NULL, 16); + if (image_info(addr) != 0) rcode = 1; } return rcode; } -static int image_info (ulong addr) +static int image_info(ulong addr) { void *hdr = (void *)addr; - printf ("\n## Checking Image at %08lx ...\n", addr); + printf("\n## Checking Image at %08lx ...\n", addr); - switch (genimg_get_format (hdr)) { + switch (genimg_get_format(hdr)) { case IMAGE_FORMAT_LEGACY: - puts (" Legacy image found\n"); - if (!image_check_magic (hdr)) { - puts (" Bad Magic Number\n"); + puts(" Legacy image found\n"); + if (!image_check_magic(hdr)) { + puts(" Bad Magic Number\n"); return 1; } - if (!image_check_hcrc (hdr)) { - puts (" Bad Header Checksum\n"); + if (!image_check_hcrc(hdr)) { + puts(" Bad Header Checksum\n"); return 1; } - image_print_contents (hdr); + image_print_contents(hdr); - puts (" Verifying Checksum ... "); - if (!image_check_dcrc (hdr)) { - puts (" Bad Data CRC\n"); + puts(" Verifying Checksum ... "); + if (!image_check_dcrc(hdr)) { + puts(" Bad Data CRC\n"); return 1; } - puts ("OK\n"); + puts("OK\n"); return 0; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: - puts (" FIT image found\n"); + puts(" FIT image found\n"); - if (!fit_check_format (hdr)) { - puts ("Bad FIT image format!\n"); + if (!fit_check_format(hdr)) { + puts("Bad FIT image format!\n"); return 1; } - fit_print_contents (hdr); + fit_print_contents(hdr); - if (!fit_all_image_check_hashes (hdr)) { - puts ("Bad hash in FIT image!\n"); + if (!fit_all_image_verify(hdr)) { + puts("Bad hash in FIT image!\n"); return 1; } return 0; #endif default: - puts ("Unknown image format!\n"); + puts("Unknown image format!\n"); break; } @@ -1132,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 *argv[]) +static int do_imls_nor(void) { flash_info_t *info; int i, j; @@ -1149,28 +1219,28 @@ int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) if (!hdr) goto next_sector; - switch (genimg_get_format (hdr)) { + switch (genimg_get_format(hdr)) { case IMAGE_FORMAT_LEGACY: - if (!image_check_hcrc (hdr)) + if (!image_check_hcrc(hdr)) goto next_sector; - printf ("Legacy Image at %08lX:\n", (ulong)hdr); - image_print_contents (hdr); + printf("Legacy Image at %08lX:\n", (ulong)hdr); + image_print_contents(hdr); - puts (" Verifying Checksum ... "); - if (!image_check_dcrc (hdr)) { - puts ("Bad Data CRC\n"); + puts(" Verifying Checksum ... "); + if (!image_check_dcrc(hdr)) { + puts("Bad Data CRC\n"); } else { - puts ("OK\n"); + puts("OK\n"); } break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: - if (!fit_check_format (hdr)) + if (!fit_check_format(hdr)) goto next_sector; - printf ("FIT Image at %08lX:\n", (ulong)hdr); - fit_print_contents (hdr); + printf("FIT Image at %08lX:\n", (ulong)hdr); + fit_print_contents(hdr); break; #endif default: @@ -1181,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); } @@ -1189,43 +1414,61 @@ 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 -static void fixup_silent_linux () +#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 *cmdline = getenv ("bootargs"); + char *buf; + const char *env_val; + char *cmdline = getenv("bootargs"); /* Only fix cmdline when requested */ if (!(gd->flags & GD_FLG_SILENT)) return; - debug ("before silent fix-up: %s\n", cmdline); - if (cmdline) { - if ((start = strstr (cmdline, "console=")) != NULL) { - end = strchr (start, ' '); - strncpy (buf, cmdline, (start - cmdline + 8)); + debug("before silent fix-up: %s\n", cmdline); + 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) { + 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 */ @@ -1235,7 +1478,7 @@ static void fixup_silent_linux () /*******************************************************************/ #ifdef CONFIG_BOOTM_NETBSD -static int do_bootm_netbsd (int flag, int argc, char *argv[], +static int do_bootm_netbsd(int flag, int argc, char * const argv[], bootm_headers_t *images) { void (*loader)(bd_t *, image_header_t *, char *, char *); @@ -1249,7 +1492,7 @@ static int do_bootm_netbsd (int flag, int argc, char *argv[], #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) { - fit_unsupported_reset ("NetBSD"); + fit_unsupported_reset("NetBSD"); return 1; } #endif @@ -1267,20 +1510,20 @@ static int do_bootm_netbsd (int flag, int argc, char *argv[], * address of the original image header. */ os_hdr = NULL; - if (image_check_type (&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) { - image_multi_getimg (hdr, 1, &kernel_data, &kernel_len); + if (image_check_type(&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) { + image_multi_getimg(hdr, 1, &kernel_data, &kernel_len); if (kernel_len) os_hdr = hdr; } consdev = ""; -#if defined (CONFIG_8xx_CONS_SMC1) +#if defined(CONFIG_8xx_CONS_SMC1) consdev = "smc1"; -#elif defined (CONFIG_8xx_CONS_SMC2) +#elif defined(CONFIG_8xx_CONS_SMC2) consdev = "smc2"; -#elif defined (CONFIG_8xx_CONS_SCC2) +#elif defined(CONFIG_8xx_CONS_SCC2) consdev = "scc2"; -#elif defined (CONFIG_8xx_CONS_SCC3) +#elif defined(CONFIG_8xx_CONS_SCC3) consdev = "scc3"; #endif @@ -1289,25 +1532,26 @@ static int do_bootm_netbsd (int flag, int argc, char *argv[], int i; for (i = 2, len = 0; i < argc; i += 1) - len += strlen (argv[i]) + 1; - cmdline = malloc (len); + len += strlen(argv[i]) + 1; + cmdline = malloc(len); for (i = 2, len = 0; i < argc; i += 1) { if (i > 2) cmdline[len++] = ' '; - strcpy (&cmdline[len], argv[i]); - len += strlen (argv[i]); + strcpy(&cmdline[len], argv[i]); + len += strlen(argv[i]); } - } else if ((cmdline = getenv ("bootargs")) == NULL) { + } else if ((cmdline = getenv("bootargs")) == NULL) { cmdline = ""; } loader = (void (*)(bd_t *, image_header_t *, char *, char *))images->ep; - printf ("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n", + printf("## Transferring control to NetBSD stage-2 loader " + "(at address %08lx) ...\n", (ulong)loader); - show_boot_progress (15); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); /* * NetBSD Stage-2 Loader Parameters: @@ -1316,14 +1560,14 @@ static int do_bootm_netbsd (int flag, int argc, char *argv[], * r5: console device * r6: boot args string */ - (*loader) (gd->bd, os_hdr, consdev, cmdline); + (*loader)(gd->bd, os_hdr, consdev, cmdline); return 1; } #endif /* CONFIG_BOOTM_NETBSD*/ #ifdef CONFIG_LYNXKDI -static int do_bootm_lynxkdi (int flag, int argc, char *argv[], +static int do_bootm_lynxkdi(int flag, int argc, char * const argv[], bootm_headers_t *images) { image_header_t *hdr = &images->legacy_hdr_os_copy; @@ -1333,19 +1577,19 @@ static int do_bootm_lynxkdi (int flag, int argc, char *argv[], #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) { - fit_unsupported_reset ("Lynx"); + fit_unsupported_reset("Lynx"); return 1; } #endif - lynxkdi_boot ((image_header_t *)hdr); + lynxkdi_boot((image_header_t *)hdr); return 1; } #endif /* CONFIG_LYNXKDI */ #ifdef CONFIG_BOOTM_RTEMS -static int do_bootm_rtems (int flag, int argc, char *argv[], +static int do_bootm_rtems(int flag, int argc, char * const argv[], bootm_headers_t *images) { void (*entry_point)(bd_t *); @@ -1355,17 +1599,17 @@ static int do_bootm_rtems (int flag, int argc, char *argv[], #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) { - fit_unsupported_reset ("RTEMS"); + fit_unsupported_reset("RTEMS"); return 1; } #endif entry_point = (void (*)(bd_t *))images->ep; - printf ("## Transferring control to RTEMS (at address %08lx) ...\n", + printf("## Transferring control to RTEMS (at address %08lx) ...\n", (ulong)entry_point); - show_boot_progress (15); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); /* * RTEMS Parameters: @@ -1377,8 +1621,74 @@ static int do_bootm_rtems (int flag, int argc, char *argv[], } #endif /* CONFIG_BOOTM_RTEMS */ +#if defined(CONFIG_BOOTM_OSE) +static int do_bootm_ose(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("OSE"); + return 1; + } +#endif + + entry_point = (void (*)(void))images->ep; + + printf("## Transferring control to OSE (at address %08lx) ...\n", + (ulong)entry_point); + + bootstage_mark(BOOTSTAGE_ID_RUN_OS); + + /* + * OSE Parameters: + * None + */ + (*entry_point)(); + + return 1; +} +#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 *argv[], +static int do_bootm_vxworks(int flag, int argc, char * const argv[], bootm_headers_t *images) { char str[80]; @@ -1388,7 +1698,7 @@ static int do_bootm_vxworks (int flag, int argc, char *argv[], #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) { - fit_unsupported_reset ("VxWorks"); + fit_unsupported_reset("VxWorks"); return 1; } #endif @@ -1400,7 +1710,7 @@ static int do_bootm_vxworks (int flag, int argc, char *argv[], return 1; } -static int do_bootm_qnxelf(int flag, int argc, char *argv[], +static int do_bootm_qnxelf(int flag, int argc, char * const argv[], bootm_headers_t *images) { char *local_args[2]; @@ -1411,7 +1721,7 @@ static int do_bootm_qnxelf(int flag, int argc, char *argv[], #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) { - fit_unsupported_reset ("QNX"); + fit_unsupported_reset("QNX"); return 1; } #endif @@ -1426,7 +1736,7 @@ static int do_bootm_qnxelf(int flag, int argc, char *argv[], #endif #ifdef CONFIG_INTEGRITY -static int do_bootm_integrity (int flag, int argc, char *argv[], +static int do_bootm_integrity(int flag, int argc, char * const argv[], bootm_headers_t *images) { void (*entry_point)(void); @@ -1436,17 +1746,17 @@ static int do_bootm_integrity (int flag, int argc, char *argv[], #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) { - fit_unsupported_reset ("INTEGRITY"); + fit_unsupported_reset("INTEGRITY"); return 1; } #endif entry_point = (void (*)(void))images->ep; - printf ("## Transferring control to INTEGRITY (at address %08lx) ...\n", + printf("## Transferring control to INTEGRITY (at address %08lx) ...\n", (ulong)entry_point); - show_boot_progress (15); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); /* * INTEGRITY Parameters: @@ -1457,3 +1767,137 @@ static int do_bootm_integrity (int flag, int argc, char *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 */