summaryrefslogtreecommitdiff
path: root/common/cmd_bootm.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/cmd_bootm.c')
-rw-r--r--common/cmd_bootm.c216
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