+ [IH_OS_LYNXOS] = do_bootm_lynxkdi,
+#endif
+#ifdef CONFIG_BOOTM_RTEMS
+ [IH_OS_RTEMS] = do_bootm_rtems,
+#endif
+#if defined(CONFIG_CMD_ELF)
+ [IH_OS_VXWORKS] = do_bootm_vxworks,
+ [IH_OS_QNX] = do_bootm_qnxelf,
+#endif
+#ifdef CONFIG_INTEGRITY
+ [IH_OS_INTEGRITY] = do_bootm_integrity,
+#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")));
+
+/* Allow for arch specific config before we boot */
+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
+
+static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ 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);
+
+ mem_start = getenv_bootm_low();
+ mem_size = getenv_bootm_size();
+
+ lmb_add(&images.lmb, (phys_addr_t)mem_start, mem_size);
+
+ arch_lmb_reserve(&images.lmb);
+ board_lmb_reserve(&images.lmb);
+
+ /* get kernel image header, start address and length */
+ 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");
+ return 1;
+ }
+
+ /* get image parameters */
+ 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.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, &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, &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, &images.os.os)) {
+ puts ("Can't get image OS!\n");
+ show_boot_progress (-111);
+ return 1;
+ }
+
+ images.os.end = fit_get_end (images.fit_hdr_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);
+ return 1;
+ }
+ break;
+#endif
+ default:
+ 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);
+#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);
+ if (ret) {
+ puts ("Can't get entry point property!\n");
+ return 1;
+ }
+#endif
+ } else {
+ puts ("Could not find kernel entry point!\n");
+ return 1;
+ }
+
+ 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);
+ if (ret) {
+ 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);
+ if (ret) {
+ puts ("Could not find a valid device tree\n");
+ return 1;
+ }
+
+ set_working_fdt_addr(images.ft_addr);
+#endif
+#endif
+ }
+
+ images.os.start = (ulong)os_hdr;
+ images.state = BOOTM_STATE_START;
+
+ 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 = CONFIG_SYS_BOOTM_LEN;
+
+ 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);
+ } else {
+ printf (" Loading %s ... ", type_name);
+
+ if (load != image_start) {
+ memmove_wd ((void *)load,
+ (void *)image_start, image_len, CHUNKSZ);
+ }
+ }
+ *load_end = load + image_len;
+ puts("OK\n");
+ break;
+ 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");
+ if (boot_progress)
+ show_boot_progress (-6);
+ return BOOTM_ERR_RESET;
+ }
+
+ *load_end = load + image_len;
+ break;
+#ifdef CONFIG_BZIP2
+ case IH_COMP_BZIP2:
+ 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,
+ &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 "
+ "- must RESET board to recover\n", i);
+ if (boot_progress)
+ show_boot_progress (-6);
+ return BOOTM_ERR_RESET;
+ }
+
+ *load_end = load + unc_len;
+ break;
+#endif /* CONFIG_BZIP2 */
+#ifdef CONFIG_LZMA
+ case IH_COMP_LZMA:
+ printf (" Uncompressing %s ... ", type_name);
+
+ int ret = lzmaBuffToBuffDecompress(
+ (unsigned char *)load, &unc_len,
+ (unsigned char *)image_start, image_len);
+ if (ret != SZ_OK) {
+ printf ("LZMA: uncompress or overwrite error %d "
+ "- must RESET board to recover\n", ret);
+ show_boot_progress (-6);
+ return BOOTM_ERR_RESET;
+ }
+ *load_end = load + unc_len;
+ break;
+#endif /* CONFIG_LZMA */
+ default:
+ 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);
+
+ return BOOTM_ERR_OVERLAP;
+ }
+
+ return 0;
+}
+
+static int bootm_start_standalone(ulong iflag, int argc, char *argv[])
+{
+ char *s;
+ int (*appl)(int, char *[]);
+
+ /* 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);
+ return 0;
+ }
+ appl = (int (*)(int, char *[]))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[] = {
+ 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)
+ 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, "", ""),