X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=common%2Fcmd_bootm.c;h=529596926001730d491e23eb35a8593e6d9d1e30;hb=e1c3dbada349992875934575c97b328ab2cb33ca;hp=a32a5a25613215c23f40acb3ed5ec043cc1ef933;hpb=e822d7fc4dd4755d4d0a22f05e33f33d1a0481da;p=oweals%2Fu-boot.git diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index a32a5a2561..5295969260 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -21,7 +21,6 @@ * MA 02111-1307 USA */ -#define DEBUG /* * Boot support @@ -37,6 +36,10 @@ #include #include +#if defined(CONFIG_CMD_USB) +#include +#endif + #ifdef CFG_HUSH_PARSER #include #endif @@ -66,7 +69,12 @@ static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); static void fixup_silent_linux (void); #endif -static void *get_kernel (cmd_tbl_t *cmdtp, int flag,int argc, char *argv[], +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); +#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[]); @@ -96,7 +104,6 @@ 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[]); #endif #if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) -extern uchar (*env_get_char)(int); /* Returns a character from the environment */ static boot_os_fn do_bootm_artos; #endif @@ -124,34 +131,34 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ulong os_data, os_len; ulong image_start, image_end; ulong load_start, load_end; + ulong mem_start; + phys_size_t mem_size; struct lmb lmb; memset ((void *)&images, 0, sizeof (images)); - images.verify = getenv_verify(); - images.autostart = getenv_autostart(); + images.verify = getenv_yesno ("verify"); images.lmb = &lmb; lmb_init(&lmb); -#ifdef CFG_SDRAM_BASE - lmb_add(&lmb, CFG_SDRAM_BASE, gd->bd->bi_memsize); -#else - lmb_add(&lmb, 0, gd->bd->bi_memsize); -#endif + mem_start = getenv_bootm_low(); + mem_size = getenv_bootm_size(); + + lmb_add(&lmb, (phys_addr_t)mem_start, mem_size); board_lmb_reserve(&lmb); /* get kernel image header, start address and length */ - os_hdr = get_kernel (cmdtp, flag, argc, argv, + os_hdr = boot_get_kernel (cmdtp, flag, argc, argv, &images, &os_data, &os_len); - if (os_len == 0) + if (os_len == 0) { + puts ("ERROR: can't get kernel image!\n"); return 1; - - show_boot_progress (6); + } /* get image parameters */ - switch (gen_image_get_format (os_hdr)) { + switch (genimg_get_format (os_hdr)) { case IMAGE_FORMAT_LEGACY: type = image_get_type (os_hdr); comp = image_get_comp (os_hdr); @@ -162,8 +169,36 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: - fit_unsupported ("bootm"); - return 1; + if (fit_image_get_type (images.fit_hdr_os, + images.fit_noffset_os, &type)) { + puts ("Can't get image type!\n"); + show_boot_progress (-109); + return 1; + } + + if (fit_image_get_comp (images.fit_hdr_os, + images.fit_noffset_os, &comp)) { + puts ("Can't get image compression!\n"); + show_boot_progress (-110); + return 1; + } + + if (fit_image_get_os (images.fit_hdr_os, + images.fit_noffset_os, &os)) { + puts ("Can't get image OS!\n"); + show_boot_progress (-111); + return 1; + } + + image_end = fit_get_end (images.fit_hdr_os); + + if (fit_image_get_load (images.fit_hdr_os, images.fit_noffset_os, + &load_start)) { + puts ("Can't get image load address!\n"); + show_boot_progress (-112); + return 1; + } + break; #endif default: puts ("ERROR: unknown image format type!\n"); @@ -172,7 +207,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) image_start = (ulong)os_hdr; load_end = 0; - type_name = image_get_type_name (type); + type_name = genimg_get_type_name (type); /* * We have reached the point of no return: we are going to @@ -181,6 +216,20 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) */ iflag = 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_AMIGAONEG3SE /* * We've possible left the caches enabled during @@ -201,16 +250,16 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) memmove_wd ((void *)load_start, (void *)os_data, os_len, CHUNKSZ); - - load_end = load_start + os_len; - puts("OK\n"); } + load_end = load_start + os_len; + puts("OK\n"); break; case IH_COMP_GZIP: printf (" Uncompressing %s ... ", type_name); if (gunzip ((void *)load_start, unc_len, (uchar *)os_data, &os_len) != 0) { - puts ("GUNZIP ERROR - must RESET board to recover\n"); + puts ("GUNZIP: uncompress or overwrite error " + "- must RESET board to recover\n"); show_boot_progress (-6); do_reset (cmdtp, flag, argc, argv); } @@ -229,7 +278,8 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) &unc_len, (char *)os_data, os_len, CFG_MALLOC_LEN < (4096 * 1024), 0); if (i != BZ_OK) { - printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i); + printf ("BUNZIP2: uncompress or overwrite error %d " + "- must RESET board to recover\n", i); show_boot_progress (-6); do_reset (cmdtp, flag, argc, argv); } @@ -252,8 +302,16 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) debug ("image_start = 0x%lX, image_end = 0x%lx\n", image_start, image_end); debug ("load_start = 0x%lx, load_end = 0x%lx\n", load_start, load_end); - puts ("ERROR: image overwritten - must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); + 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"); + } else { + puts ("ERROR: new format image overwritten - " + "must RESET the board to recover\n"); + show_boot_progress (-113); + do_reset (cmdtp, flag, argc, argv); + } } show_boot_progress (8); @@ -305,20 +363,23 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) puts ("\n## Control returned to monitor - resetting...\n"); do_reset (cmdtp, flag, argc, argv); #endif + if (iflag) + enable_interrupts(); + return 1; } /** - * get_kernel - find kernel image - * @os_data: pointer to a ulong variable, will hold os data start address - * @os_len: pointer to a ulong variable, will hold os data length + * image_get_kernel - verify legacy format kernel image + * @img_addr: in RAM address of the legacy format image to be verified + * @verify: data CRC verification flag * - * get_kernel() tries to find a kernel image, verifies its integrity - * and locates kernel data. + * image_get_kernel() verifies legacy image integrity and returns pointer to + * legacy image header if image verification was completed successfully. * * returns: - * pointer to image header if valid image was found, plus kernel start - * address and length, otherwise NULL + * 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) { @@ -360,18 +421,65 @@ static image_header_t *image_get_kernel (ulong img_addr, int verify) } /** - * get_kernel - find kernel image + * fit_check_kernel - verify FIT format kernel subimage + * @fit_hdr: pointer to the FIT image header + * os_noffset: kernel subimage node offset within FIT image + * @verify: data CRC verification flag + * + * fit_check_kernel() verifies integrity of the kernel subimage and from + * specified FIT image. + * + * returns: + * 1, on success + * 0, on failure + */ +#if defined (CONFIG_FIT) +static int fit_check_kernel (const void *fit, int os_noffset, int verify) +{ + 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); + return 0; + } + puts ("OK\n"); + } + show_boot_progress (105); + + if (!fit_image_check_target_arch (fit, os_noffset)) { + puts ("Unsupported Architecture\n"); + show_boot_progress (-105); + 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); + return 0; + } + + show_boot_progress (107); + return 1; +} +#endif /* CONFIG_FIT */ + +/** + * boot_get_kernel - find kernel image * @os_data: pointer to a ulong variable, will hold os data start address * @os_len: pointer to a ulong variable, will hold os data length * - * get_kernel() tries to find a kernel image, verifies its integrity + * boot_get_kernel() tries to find a kernel image, verifies its integrity * and locates kernel data. * * returns: * pointer to image header if valid image was found, plus kernel start * address and length, otherwise NULL */ -static void *get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], +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) { image_header_t *hdr; @@ -380,6 +488,10 @@ static void *get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], void *fit_hdr; const char *fit_uname_config = NULL; const char *fit_uname_kernel = NULL; + const void *data; + size_t len; + int cfg_noffset; + int os_noffset; #endif /* find out kernel image address */ @@ -403,21 +515,22 @@ static void *get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], } show_boot_progress (1); - printf ("## Booting kernel image at %08lx ...\n", img_addr); /* copy from dataflash if needed */ - img_addr = gen_get_image (img_addr); + img_addr = genimg_get_image (img_addr); /* check image type, for FIT images get FIT kernel node */ - switch (gen_image_get_format ((void *)img_addr)) { + *os_data = *os_len = 0; + switch (genimg_get_format ((void *)img_addr)) { case IMAGE_FORMAT_LEGACY: - - debug ("* kernel: legacy format image\n"); + 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); + /* get os_data and os_len */ switch (image_get_type (hdr)) { case IH_TYPE_KERNEL: *os_data = image_get_data (hdr); @@ -431,24 +544,92 @@ static void *get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], show_boot_progress (-5); return NULL; } + + /* + * copy image header to allow for image overwrites during kernel + * decompression. + */ + 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; + images->legacy_hdr_valid = 1; + show_boot_progress (6); break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: fit_hdr = (void *)img_addr; - debug ("* kernel: FIT format image\n"); - fit_unsupported ("kernel"); - return NULL; + 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); + return NULL; + } + show_boot_progress (100); + + 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 + */ + show_boot_progress (101); + cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); + if (cfg_noffset < 0) { + show_boot_progress (-101); + 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); + } else { + /* get kernel component image node offset */ + show_boot_progress (102); + os_noffset = fit_image_get_node (fit_hdr, fit_uname_kernel); + } + if (os_noffset < 0) { + show_boot_progress (-103); + return NULL; + } + + printf (" Trying '%s' kernel subimage\n", fit_uname_kernel); + + show_boot_progress (104); + 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); + return NULL; + } + show_boot_progress (108); + + *os_len = len; + *os_data = (ulong)data; + images->fit_hdr_os = 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); return NULL; } - debug (" kernel data at 0x%08lx, end = 0x%08lx\n", - *os_data, *os_data + *os_len); + debug (" kernel data at 0x%08lx, len = 0x%08lx (%ld)\n", + *os_data, *os_len, *os_len); return (void *)img_addr; } @@ -466,6 +647,14 @@ U_BOOT_CMD( "\tuse a '-' for the second argument. If you do not pass a third\n" "\ta bd_info struct will be passed instead\n" #endif +#if defined(CONFIG_FIT) + "\t\nFor the new multi component uImage format (FIT) addresses\n" + "\tmust be extened to include component or configuration unit name:\n" + "\taddr: - direct component image specification\n" + "\taddr# - configuration specification\n" + "\tUse iminfo command to get the list of existing component\n" + "\timages and configurations.\n" +#endif ); /*******************************************************************/ @@ -531,7 +720,7 @@ static int image_info (ulong addr) printf ("\n## Checking Image at %08lx ...\n", addr); - switch (gen_image_get_format (hdr)) { + switch (genimg_get_format (hdr)) { case IMAGE_FORMAT_LEGACY: puts (" Legacy image found\n"); if (!image_check_magic (hdr)) { @@ -556,7 +745,13 @@ static int image_info (ulong addr) #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: puts (" FIT image found\n"); - fit_unsupported ("iminfo"); + + if (!fit_check_format (hdr)) { + puts ("Bad FIT image format!\n"); + return 1; + } + + fit_print_contents (hdr); return 0; #endif default: @@ -599,11 +794,8 @@ int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) if (!hdr) goto next_sector; - switch (gen_image_get_format (hdr)) { + switch (genimg_get_format (hdr)) { case IMAGE_FORMAT_LEGACY: - if (!image_check_magic (hdr)) - goto next_sector; - if (!image_check_hcrc (hdr)) goto next_sector; @@ -619,8 +811,11 @@ int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: + if (!fit_check_format (hdr)) + goto next_sector; + printf ("FIT Image at %08lX:\n", (ulong)hdr); - fit_unsupported ("imls"); + fit_print_contents (hdr); break; #endif default: @@ -714,7 +909,7 @@ static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, * address of the original image header. */ os_hdr = NULL; - if (image_check_type (hdr, IH_TYPE_MULTI)) { + 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; @@ -771,7 +966,7 @@ static void do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], bootm_headers_t *images) { - image_header_t *hdr = images->legacy_hdr_os; + image_header_t *hdr = &images->legacy_hdr_os_copy; #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) { @@ -788,7 +983,7 @@ static void do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], bootm_headers_t *images) { - image_header_t *hdr = images->legacy_hdr_os; + image_header_t *hdr = &images->legacy_hdr_os_copy; void (*entry_point)(bd_t *); #if defined(CONFIG_FIT) @@ -818,10 +1013,10 @@ static void do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, bootm_headers_t *images) { char str[80]; - image_header_t *hdr = images->legacy_hdr_os; + image_header_t *hdr = &images->legacy_hdr_os_copy; #if defined(CONFIG_FIT) - if (hdr == NULL) { + if (!images->legacy_hdr_valid) { fit_unsupported_reset ("VxWorks"); do_reset (cmdtp, flag, argc, argv); } @@ -838,7 +1033,7 @@ static void do_bootm_qnxelf(cmd_tbl_t *cmdtp, int flag, { char *local_args[2]; char str[16]; - image_header_t *hdr = images->legacy_hdr_os; + image_header_t *hdr = &images->legacy_hdr_os_copy; #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) { @@ -865,7 +1060,7 @@ static void do_bootm_artos (cmd_tbl_t *cmdtp, int flag, int i, j, nxt, len, envno, envsz; bd_t *kbd; void (*entry)(bd_t *bd, char *cmdline, char **fwenv, ulong top); - image_header_t *hdr = images->legacy_hdr_os; + image_header_t *hdr = &images->legacy_hdr_os_copy; #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) {