diff options
Diffstat (limited to 'common/cmd_bootm.c')
-rw-r--r-- | common/cmd_bootm.c | 216 |
1 files changed, 126 insertions, 90 deletions
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index dc88e63..5f7458b 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -150,22 +150,11 @@ void board_lmb_reserve(struct lmb *lmb) __attribute__((weak, alias("__board_lmb_ # error Unknown CPU type #endif -/*******************************************************************/ -/* bootm - boot application image from image in memory */ -/*******************************************************************/ -int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - ulong iflag; - const char *type_name; - uint unc_len = CFG_BOOTM_LEN; - uint8_t comp, type, os; - - void *os_hdr; - ulong os_data, os_len; - ulong image_start, image_end; - ulong load_start, load_end; ulong mem_start; phys_size_t mem_size; + void *os_hdr; int ret; memset ((void *)&images, 0, sizeof (images)); @@ -182,8 +171,8 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) /* get kernel image header, start address and length */ os_hdr = boot_get_kernel (cmdtp, flag, argc, argv, - &images, &os_data, &os_len); - if (os_len == 0) { + &images, &images.os.image_start, &images.os.image_len); + if (images.os.image_len == 0) { puts ("ERROR: can't get kernel image!\n"); return 1; } @@ -191,40 +180,40 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) /* get image parameters */ switch (genimg_get_format (os_hdr)) { case IMAGE_FORMAT_LEGACY: - type = image_get_type (os_hdr); - comp = image_get_comp (os_hdr); - 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); - image_end = image_get_image_end (os_hdr); - load_start = 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, - images.fit_noffset_os, &type)) { + images.fit_noffset_os, &images.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)) { + images.fit_noffset_os, &images.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)) { + images.fit_noffset_os, &images.os.os)) { puts ("Can't get image OS!\n"); show_boot_progress (-111); return 1; } - image_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, - &load_start)) { + &images.os.load)) { puts ("Can't get image load address!\n"); show_boot_progress (-112); return 1; @@ -253,7 +242,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return 1; } - if (os == IH_OS_LINUX) { + if (images.os.os == IH_OS_LINUX) { /* find ramdisk */ ret = boot_get_ramdisk (argc, argv, &images, IH_INITRD_ARCH, &images.rd_start, &images.rd_end); @@ -275,64 +264,52 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #endif } - image_start = (ulong)os_hdr; - load_end = 0; - type_name = genimg_get_type_name (type); + images.os.start = (ulong)os_hdr; + images.valid = 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... - */ - 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 + return 0; +} +#define BOOTM_ERR_RESET -1 +#define BOOTM_ERR_OVERLAP -2 +#define BOOTM_ERR_UNIMPLEMENTED -3 +static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) +{ + uint8_t comp = os.comp; + ulong load = os.load; + ulong blob_start = os.start; + ulong blob_end = os.end; + ulong image_start = os.image_start; + ulong image_len = os.image_len; + uint unc_len = CFG_BOOTM_LEN; -#ifdef CONFIG_AMIGAONEG3SE - /* - * We've possible left the caches enabled during - * bios emulation, so turn them off again - */ - icache_disable(); - dcache_disable(); -#endif + const char *type_name = genimg_get_type_name (os.type); switch (comp) { case IH_COMP_NONE: - if (load_start == (ulong)os_hdr) { + if (load == blob_start) { printf (" XIP %s ... ", type_name); } else { printf (" Loading %s ... ", type_name); - memmove_wd ((void *)load_start, - (void *)os_data, os_len, CHUNKSZ); + memmove_wd ((void *)load, + (void *)image_start, image_len, CHUNKSZ); } - load_end = load_start + os_len; + *load_end = load + image_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) { + if (gunzip ((void *)load, unc_len, + (uchar *)image_start, &image_len) != 0) { puts ("GUNZIP: uncompress or overwrite error " "- must RESET board to recover\n"); - show_boot_progress (-6); - do_reset (cmdtp, flag, argc, argv); + if (boot_progress) + show_boot_progress (-6); + return BOOTM_ERR_RESET; } - load_end = load_start + os_len; + *load_end = load + image_len; break; #ifdef CONFIG_BZIP2 case IH_COMP_BZIP2: @@ -342,51 +319,110 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) * use slower decompression algorithm which requires * at most 2300 KB of memory. */ - int i = BZ2_bzBuffToBuffDecompress ((char*)load_start, - &unc_len, (char *)os_data, os_len, + int i = BZ2_bzBuffToBuffDecompress ((char*)load, + &unc_len, (char *)image_start, image_len, CFG_MALLOC_LEN < (4096 * 1024), 0); if (i != BZ_OK) { printf ("BUNZIP2: uncompress or overwrite error %d " "- must RESET board to recover\n", i); - show_boot_progress (-6); - do_reset (cmdtp, flag, argc, argv); + if (boot_progress) + show_boot_progress (-6); + return BOOTM_ERR_RESET; } - load_end = load_start + unc_len; + *load_end = load + unc_len; break; #endif /* CONFIG_BZIP2 */ default: - if (iflag) - enable_interrupts(); printf ("Unimplemented compression type %d\n", comp); - show_boot_progress (-7); - return 1; + return BOOTM_ERR_UNIMPLEMENTED; } puts ("OK\n"); - debug (" kernel loaded at 0x%08lx, end = 0x%08lx\n", load_start, load_end); - show_boot_progress (7); + debug (" kernel loaded at 0x%08lx, end = 0x%08lx\n", load, load_end); + if (boot_progress) + show_boot_progress (7); - if ((load_start < image_end) && (load_end > image_start)) { - 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); + 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); - 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); + return BOOTM_ERR_OVERLAP; + } + + return 0; +} + +/*******************************************************************/ +/* bootm - boot application image from image in memory */ +/*******************************************************************/ +int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + + ulong iflag; + ulong load_end = 0; + int ret; + + bootm_start(cmdtp, flag, argc, argv); + + /* + * 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... + */ + 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 + * 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); + 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"); + } else { + puts ("ERROR: new format image overwritten - " + "must RESET the board to recover\n"); + show_boot_progress (-113); + do_reset (cmdtp, flag, argc, argv); + } + } + if (ret == BOOTM_ERR_UNIMPLEMENTED) { + if (iflag) + enable_interrupts(); + show_boot_progress (-7); + return 1; } } - show_boot_progress (8); + lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load)); - lmb_reserve(&images.lmb, load_start, (load_end - load_start)); + show_boot_progress (8); - switch (os) { + switch (images.os.os) { default: /* handled by (original) Linux case */ case IH_OS_LINUX: #ifdef CONFIG_SILENT_CONSOLE |