|
@@ -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
|