Fix merge problems
[platform/kernel/u-boot.git] / common / cmd_bootm.c
index 3390be7..18d7100 100644 (file)
@@ -21,7 +21,6 @@
  * MA 02111-1307 USA
  */
 
-#define DEBUG
 
 /*
  * Boot support
 #include <zlib.h>
 #include <bzlib.h>
 #include <environment.h>
+#include <lmb.h>
 #include <asm/byteorder.h>
 
-#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
-#include <rtc.h>
+#if defined(CONFIG_CMD_USB)
+#include <usb.h>
 #endif
 
 #ifdef CFG_HUSH_PARSER
 #include <hush.h>
 #endif
 
-#ifdef CONFIG_HAS_DATAFLASH
-#include <dataflash.h>
-#endif
-
 DECLARE_GLOBAL_DATA_PTR;
 
 extern int gunzip (void *dst, int dstlen, unsigned char *src, unsigned long *lenp);
@@ -73,7 +69,13 @@ static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
 static void fixup_silent_linux (void);
 #endif
 
-static void print_type (image_header_t *hdr);
+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[]);
 
 /*
@@ -86,8 +88,7 @@ extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
  */
 typedef void boot_os_fn (cmd_tbl_t *cmdtp, int flag,
                        int argc, char *argv[],
-                       image_header_t *hdr,    /* of image to boot */
-                       int verify);            /* getenv("verify")[0] != 'n' */
+                       bootm_headers_t *images); /* pointers to os/initrd/fdt */
 
 extern boot_os_fn do_bootm_linux;
 static boot_os_fn do_bootm_netbsd;
@@ -103,11 +104,17 @@ 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
 
 ulong load_addr = CFG_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")));
 
 
 /*******************************************************************/
@@ -116,101 +123,92 @@ ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */
 int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
        ulong           iflag;
-       char            *name, *s;
-       int             (*appl)(int, char *[]);
+       const char      *type_name;
        uint            unc_len = CFG_BOOTM_LEN;
-       int             verify = getenv_verify();
+       uint8_t         comp, type, os;
 
-       image_header_t  *hdr;
-       ulong           img_addr;
+       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;
 
+       struct lmb lmb;
 
-       if (argc < 2) {
-               img_addr = load_addr;
-       } else {
-               img_addr = simple_strtoul(argv[1], NULL, 16);
-       }
+       memset ((void *)&images, 0, sizeof (images));
+       images.verify = getenv_yesno ("verify");
+       images.autostart = getenv_yesno ("autostart");
+       images.lmb = &lmb;
 
-       show_boot_progress (1);
-       printf ("## Booting image at %08lx ...\n", img_addr);
+       lmb_init(&lmb);
 
-#ifdef CONFIG_HAS_DATAFLASH
-       if (addr_dataflash (img_addr)){
-               hdr = (image_header_t *)CFG_LOAD_ADDR;
-               read_dataflash (img_addr, image_get_header_size (), (char *)hdr);
-       } else
-#endif
-       hdr = (image_header_t *)img_addr;
+       mem_start = getenv_bootm_low();
+       mem_size = getenv_bootm_size();
 
-       if (!image_check_magic(hdr)) {
-               puts ("Bad Magic Number\n");
-               show_boot_progress (-1);
-               return 1;
-       }
-       show_boot_progress (2);
+       lmb_add(&lmb, (phys_addr_t)mem_start, mem_size);
 
-       if (!image_check_hcrc (hdr)) {
-               puts ("Bad Header Checksum\n");
-               show_boot_progress (-2);
+       board_lmb_reserve(&lmb);
+
+       /* 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) {
+               puts ("ERROR: can't get kernel image!\n");
                return 1;
        }
-       show_boot_progress (3);
 
-#ifdef CONFIG_HAS_DATAFLASH
-       if (addr_dataflash (img_addr))
-               read_dataflash (img_addr + image_get_header_size (),
-                               image_get_data_size (hdr),
-                               (char *)image_get_data (hdr));
-#endif
+       /* 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);
 
-       /* uImage is in a system RAM, pointed to by hdr */
-       print_image_hdr (hdr);
+               image_end = image_get_image_end (os_hdr);
+               load_start = 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)) {
+                       puts ("Can't get image type!\n");
+                       show_boot_progress (-109);
+                       return 1;
+               }
 
-       if (verify) {
-               puts ("   Verifying Checksum ... ");
-               if (!image_check_dcrc (hdr)) {
-                       printf ("Bad Data CRC\n");
-                       show_boot_progress (-3);
+               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;
                }
-               puts ("OK\n");
-       }
-       show_boot_progress (4);
 
-       if (!image_check_target_arch (hdr)) {
-               printf ("Unsupported Architecture 0x%x\n", image_get_arch (hdr));
-               show_boot_progress (-4);
-               return 1;
-       }
-       show_boot_progress (5);
-
-       switch (image_get_type (hdr)) {
-       case IH_TYPE_STANDALONE:
-               name = "Standalone Application";
-               /* A second argument overwrites the load address */
-               if (argc > 2) {
-                       image_set_load (hdr, simple_strtoul (argv[2], NULL, 16));
+               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;
-       case IH_TYPE_KERNEL:
-               name = "Kernel Image";
-               os_data = image_get_data (hdr);
-               os_len = image_get_data_size (hdr);
-               break;
-       case IH_TYPE_MULTI:
-               name = "Multi-File Image";
-               image_multi_getimg (hdr, 0, &os_data, &os_len);
-               break;
+#endif
        default:
-               printf ("Wrong Image Type for %s command\n", cmdtp->name);
-               show_boot_progress (-5);
+               puts ("ERROR: unknown image format type!\n");
                return 1;
        }
-       show_boot_progress (6);
+
+       image_start = (ulong)os_hdr;
+       load_end = 0;
+       type_name = genimg_get_type_name (type);
 
        /*
         * We have reached the point of no return: we are going to
@@ -219,6 +217,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
@@ -230,30 +242,25 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
        dcache_disable();
 #endif
 
-       image_start = (ulong)hdr;
-       image_end = image_get_image_end (hdr);
-       load_start = image_get_load (hdr);
-       load_end = 0;
-
-       switch (image_get_comp (hdr)) {
+       switch (comp) {
        case IH_COMP_NONE:
-               if (image_get_load (hdr) == img_addr) {
-                       printf ("   XIP %s ... ", name);
+               if (load_start == (ulong)os_hdr) {
+                       printf ("   XIP %s ... ", type_name);
                } else {
-                       printf ("   Loading %s ... ", name);
+                       printf ("   Loading %s ... ", type_name);
 
-                       memmove_wd ((void *)image_get_load (hdr),
+                       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 ... ", name);
-               if (gunzip ((void *)image_get_load (hdr), unc_len,
+               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);
                }
@@ -262,17 +269,18 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                break;
 #ifdef CONFIG_BZIP2
        case IH_COMP_BZIP2:
-               printf ("   Uncompressing %s ... ", name);
+               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*)image_get_load (hdr),
+               int i = BZ2_bzBuffToBuffDecompress ((char*)load_start,
                                        &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);
                }
@@ -283,87 +291,70 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
        default:
                if (iflag)
                        enable_interrupts();
-               printf ("Unimplemented compression type %d\n", image_get_comp (hdr));
+               printf ("Unimplemented compression type %d\n", comp);
                show_boot_progress (-7);
                return 1;
        }
        puts ("OK\n");
+       debug ("   kernel loaded at 0x%08lx, end = 0x%08lx\n", load_start, load_end);
        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);
 
-               puts ("ERROR: image overwritten - must RESET the board to recover.\n");
-               do_reset (cmdtp, flag, argc, argv);
-       }
-
-       switch (image_get_type (hdr)) {
-       case IH_TYPE_STANDALONE:
-               if (iflag)
-                       enable_interrupts();
-
-               /* load (and uncompress), but don't start if "autostart"
-                * is set to "no"
-                */
-               if (((s = getenv("autostart")) != NULL) && (strcmp(s,"no") == 0)) {
-                       char buf[32];
-                       sprintf(buf, "%lX", image_get_data_size(hdr));
-                       setenv("filesize", buf);
-                       return 0;
+               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);
                }
-               appl = (int (*)(int, char *[]))image_get_ep (hdr);
-               (*appl)(argc-1, &argv[1]);
-               return 0;
-       case IH_TYPE_KERNEL:
-       case IH_TYPE_MULTI:
-               /* handled below */
-               break;
-       default:
-               if (iflag)
-                       enable_interrupts();
-               printf ("Can't boot image type %d\n", image_get_type (hdr));
-               show_boot_progress (-8);
-               return 1;
        }
+
        show_boot_progress (8);
 
-       switch (image_get_os (hdr)) {
+       lmb_reserve(&lmb, load_start, (load_end - load_start));
+
+       switch (os) {
        default:                        /* handled by (original) Linux case */
        case IH_OS_LINUX:
 #ifdef CONFIG_SILENT_CONSOLE
            fixup_silent_linux();
 #endif
-           do_bootm_linux (cmdtp, flag, argc, argv, hdr, verify);
+           do_bootm_linux (cmdtp, flag, argc, argv, &images);
            break;
 
        case IH_OS_NETBSD:
-           do_bootm_netbsd (cmdtp, flag, argc, argv, hdr, verify);
+           do_bootm_netbsd (cmdtp, flag, argc, argv, &images);
            break;
 
 #ifdef CONFIG_LYNXKDI
        case IH_OS_LYNXOS:
-           do_bootm_lynxkdi (cmdtp, flag, argc, argv, hdr, verify);
+           do_bootm_lynxkdi (cmdtp, flag, argc, argv, &images);
            break;
 #endif
 
        case IH_OS_RTEMS:
-           do_bootm_rtems (cmdtp, flag, argc, argv, hdr, verify);
+           do_bootm_rtems (cmdtp, flag, argc, argv, &images);
            break;
 
 #if defined(CONFIG_CMD_ELF)
        case IH_OS_VXWORKS:
-           do_bootm_vxworks (cmdtp, flag, argc, argv, hdr, verify);
+           do_bootm_vxworks (cmdtp, flag, argc, argv, &images);
            break;
 
        case IH_OS_QNX:
-           do_bootm_qnxelf (cmdtp, flag, argc, argv, hdr, verify);
+           do_bootm_qnxelf (cmdtp, flag, argc, argv, &images);
            break;
 #endif
 
 #ifdef CONFIG_ARTOS
        case IH_OS_ARTOS:
-           do_bootm_artos (cmdtp, flag, argc, argv, hdr, verify);
+           do_bootm_artos (cmdtp, flag, argc, argv, &images);
            break;
 #endif
        }
@@ -371,11 +362,280 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
        show_boot_progress (-9);
 #ifdef DEBUG
        puts ("\n## Control returned to monitor - resetting...\n");
-       do_reset (cmdtp, flag, argc, argv);
+       if (images.autostart)
+               do_reset (cmdtp, flag, argc, argv);
 #endif
+       if (!images.autostart && iflag)
+               enable_interrupts();
+
        return 1;
 }
 
+/**
+ * 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
+ *
+ * image_get_kernel() verifies legacy image integrity and returns pointer to
+ * legacy image header if image verification was completed successfully.
+ *
+ * returns:
+ *     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)
+{
+       image_header_t *hdr = (image_header_t *)img_addr;
+
+       if (!image_check_magic(hdr)) {
+               puts ("Bad Magic Number\n");
+               show_boot_progress (-1);
+               return NULL;
+       }
+       show_boot_progress (2);
+
+       if (!image_check_hcrc (hdr)) {
+               puts ("Bad Header Checksum\n");
+               show_boot_progress (-2);
+               return NULL;
+       }
+
+       show_boot_progress (3);
+       image_print_contents (hdr);
+
+       if (verify) {
+               puts ("   Verifying Checksum ... ");
+               if (!image_check_dcrc (hdr)) {
+                       printf ("Bad Data CRC\n");
+                       show_boot_progress (-3);
+                       return NULL;
+               }
+               puts ("OK\n");
+       }
+       show_boot_progress (4);
+
+       if (!image_check_target_arch (hdr)) {
+               printf ("Unsupported Architecture 0x%x\n", image_get_arch (hdr));
+               show_boot_progress (-4);
+               return NULL;
+       }
+       return hdr;
+}
+
+/**
+ * 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
+ *
+ * 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 *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;
+       ulong           img_addr;
+#if defined(CONFIG_FIT)
+       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 */
+       if (argc < 2) {
+               img_addr = load_addr;
+               debug ("*  kernel: default image load address = 0x%08lx\n",
+                               load_addr);
+#if defined(CONFIG_FIT)
+       } else if (fit_parse_conf (argv[1], load_addr, &img_addr,
+                                                       &fit_uname_config)) {
+               debug ("*  kernel: config '%s' from image at 0x%08lx\n",
+                               fit_uname_config, img_addr);
+       } else if (fit_parse_subimage (argv[1], load_addr, &img_addr,
+                                                       &fit_uname_kernel)) {
+               debug ("*  kernel: subimage '%s' from image at 0x%08lx\n",
+                               fit_uname_kernel, img_addr);
+#endif
+       } else {
+               img_addr = simple_strtoul(argv[1], NULL, 16);
+               debug ("*  kernel: cmdline image address = 0x%08lx\n", img_addr);
+       }
+
+       show_boot_progress (1);
+
+       /* copy from dataflash if needed */
+       img_addr = genimg_get_image (img_addr);
+
+       /* check image type, for FIT images get FIT kernel node */
+       *os_data = *os_len = 0;
+       switch (genimg_get_format ((void *)img_addr)) {
+       case IMAGE_FORMAT_LEGACY:
+               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);
+                       *os_len = image_get_data_size (hdr);
+                       break;
+               case IH_TYPE_MULTI:
+                       image_multi_getimg (hdr, 0, os_data, os_len);
+                       break;
+               default:
+                       printf ("Wrong Image Type for %s command\n", cmdtp->name);
+                       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;
+               show_boot_progress (6);
+               break;
+#if defined(CONFIG_FIT)
+       case IMAGE_FORMAT_FIT:
+               fit_hdr = (void *)img_addr;
+               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, len = 0x%08lx (%ld)\n",
+                       *os_data, *os_len, *os_len);
+
+       return (void *)img_addr;
+}
+
 U_BOOT_CMD(
        bootm,  CFG_MAXARGS,    1,      do_bootm,
        "bootm   - boot application image from memory\n",
@@ -389,6 +649,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:<subimg_uname> - direct component image specification\n"
+       "\taddr#<conf_uname>   - configuration specification\n"
+       "\tUse iminfo command to get the list of existing component\n"
+       "\timages and configurations.\n"
+#endif
 );
 
 /*******************************************************************/
@@ -450,29 +718,50 @@ int do_iminfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 
 static int image_info (ulong addr)
 {
-       image_header_t *hdr = (image_header_t *)addr;
+       void *hdr = (void *)addr;
 
        printf ("\n## Checking Image at %08lx ...\n", addr);
 
-       if (!image_check_magic (hdr)) {
-               puts ("   Bad Magic Number\n");
-               return 1;
-       }
+       switch (genimg_get_format (hdr)) {
+       case IMAGE_FORMAT_LEGACY:
+               puts ("   Legacy image found\n");
+               if (!image_check_magic (hdr)) {
+                       puts ("   Bad Magic Number\n");
+                       return 1;
+               }
 
-       if (!image_check_hcrc (hdr)) {
-               puts ("   Bad Header Checksum\n");
-               return 1;
-       }
+               if (!image_check_hcrc (hdr)) {
+                       puts ("   Bad Header Checksum\n");
+                       return 1;
+               }
 
-       print_image_hdr (hdr);
+               image_print_contents (hdr);
 
-       puts ("   Verifying Checksum ... ");
-       if (!image_check_dcrc (hdr)) {
-               puts ("   Bad Data CRC\n");
-               return 1;
+               puts ("   Verifying Checksum ... ");
+               if (!image_check_dcrc (hdr)) {
+                       puts ("   Bad Data CRC\n");
+                       return 1;
+               }
+               puts ("OK\n");
+               return 0;
+#if defined(CONFIG_FIT)
+       case IMAGE_FORMAT_FIT:
+               puts ("   FIT image found\n");
+
+               if (!fit_check_format (hdr)) {
+                       puts ("Bad FIT image format!\n");
+                       return 1;
+               }
+
+               fit_print_contents (hdr);
+               return 0;
+#endif
+       default:
+               puts ("Unknown image format!\n");
+               break;
        }
-       puts ("OK\n");
-       return 0;
+
+       return 1;
 }
 
 U_BOOT_CMD(
@@ -494,7 +783,7 @@ int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
        flash_info_t *info;
        int i, j;
-       image_header_t *hdr;
+       void *hdr;
 
        for (i = 0, info = &flash_info[0];
                i < CFG_MAX_FLASH_BANKS; ++i, ++info) {
@@ -503,23 +792,38 @@ int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                        goto next_bank;
                for (j = 0; j < info->sector_count; ++j) {
 
-                       hdr = (image_header_t *)info->start[j];
-
-                       if (!hdr || !image_check_magic (hdr))
+                       hdr = (void *)info->start[j];
+                       if (!hdr)
                                goto next_sector;
 
-                       if (!image_check_hcrc (hdr))
+                       switch (genimg_get_format (hdr)) {
+                       case IMAGE_FORMAT_LEGACY:
+                               if (!image_check_hcrc (hdr))
+                                       goto next_sector;
+
+                               printf ("Legacy Image at %08lX:\n", (ulong)hdr);
+                               image_print_contents (hdr);
+
+                               puts ("   Verifying Checksum ... ");
+                               if (!image_check_dcrc (hdr)) {
+                                       puts ("Bad Data CRC\n");
+                               } else {
+                                       puts ("OK\n");
+                               }
+                               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_print_contents (hdr);
+                               break;
+#endif
+                       default:
                                goto next_sector;
-
-                       printf ("Image at %08lX:\n", (ulong)hdr);
-                       print_image_hdr (hdr);
-
-                       puts ("   Verifying Checksum ... ");
-                       if (!image_check_dcrc (hdr)) {
-                               puts ("Bad Data CRC\n");
-                       } else {
-                               puts ("OK\n");
                        }
+
 next_sector:           ;
                }
 next_bank:     ;
@@ -538,111 +842,8 @@ U_BOOT_CMD(
 #endif
 
 /*******************************************************************/
-/* */
+/* helper routines */
 /*******************************************************************/
-void print_image_hdr (image_header_t *hdr)
-{
-#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
-       time_t timestamp = (time_t)image_get_time (hdr);
-       struct rtc_time tm;
-#endif
-
-       printf ("   Image Name:   %.*s\n", IH_NMLEN, image_get_name (hdr));
-
-#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
-       to_tm (timestamp, &tm);
-       printf ("   Created:      %4d-%02d-%02d  %2d:%02d:%02d UTC\n",
-               tm.tm_year, tm.tm_mon, tm.tm_mday,
-               tm.tm_hour, tm.tm_min, tm.tm_sec);
-#endif
-       puts ("   Image Type:   ");
-       print_type (hdr);
-
-       printf ("\n   Data Size:    %d Bytes = ", image_get_data_size (hdr));
-       print_size (image_get_data_size (hdr), "\n");
-       printf ("   Load Address: %08x\n"
-               "   Entry Point:  %08x\n",
-                image_get_load (hdr), image_get_ep (hdr));
-
-       if (image_check_type (hdr, IH_TYPE_MULTI)) {
-               int i;
-               ulong data, len;
-               ulong count = image_multi_count (hdr);
-
-               puts ("   Contents:\n");
-               for (i = 0; i < count; i++) {
-                       image_multi_getimg (hdr, i, &data, &len);
-                       printf ("   Image %d: %8ld Bytes = ", i, len);
-                       print_size (len, "\n");
-               }
-       }
-}
-
-static void print_type (image_header_t *hdr)
-{
-       char *os, *arch, *type, *comp;
-
-       switch (image_get_os (hdr)) {
-       case IH_OS_INVALID:     os = "Invalid OS";              break;
-       case IH_OS_NETBSD:      os = "NetBSD";                  break;
-       case IH_OS_LINUX:       os = "Linux";                   break;
-       case IH_OS_VXWORKS:     os = "VxWorks";                 break;
-       case IH_OS_QNX:         os = "QNX";                     break;
-       case IH_OS_U_BOOT:      os = "U-Boot";                  break;
-       case IH_OS_RTEMS:       os = "RTEMS";                   break;
-#ifdef CONFIG_ARTOS
-       case IH_OS_ARTOS:       os = "ARTOS";                   break;
-#endif
-#ifdef CONFIG_LYNXKDI
-       case IH_OS_LYNXOS:      os = "LynxOS";                  break;
-#endif
-       default:                os = "Unknown OS";              break;
-       }
-
-       switch (image_get_arch (hdr)) {
-       case IH_ARCH_INVALID:   arch = "Invalid CPU";           break;
-       case IH_ARCH_ALPHA:     arch = "Alpha";                 break;
-       case IH_ARCH_ARM:       arch = "ARM";                   break;
-       case IH_ARCH_AVR32:     arch = "AVR32";                 break;
-       case IH_ARCH_BLACKFIN:  arch = "Blackfin";              break;
-       case IH_ARCH_I386:      arch = "Intel x86";             break;
-       case IH_ARCH_IA64:      arch = "IA64";                  break;
-       case IH_ARCH_M68K:      arch = "M68K";                  break;
-       case IH_ARCH_MICROBLAZE:arch = "Microblaze";            break;
-       case IH_ARCH_MIPS64:    arch = "MIPS 64 Bit";           break;
-       case IH_ARCH_MIPS:      arch = "MIPS";                  break;
-       case IH_ARCH_NIOS2:     arch = "Nios-II";               break;
-       case IH_ARCH_NIOS:      arch = "Nios";                  break;
-       case IH_ARCH_PPC:       arch = "PowerPC";               break;
-       case IH_ARCH_S390:      arch = "IBM S390";              break;
-       case IH_ARCH_SH:        arch = "SuperH";                break;
-       case IH_ARCH_SPARC64:   arch = "SPARC 64 Bit";          break;
-       case IH_ARCH_SPARC:     arch = "SPARC";                 break;
-       default:                arch = "Unknown Architecture";  break;
-       }
-
-       switch (image_get_type (hdr)) {
-       case IH_TYPE_INVALID:   type = "Invalid Image";         break;
-       case IH_TYPE_STANDALONE:type = "Standalone Program";    break;
-       case IH_TYPE_KERNEL:    type = "Kernel Image";          break;
-       case IH_TYPE_RAMDISK:   type = "RAMDisk Image";         break;
-       case IH_TYPE_MULTI:     type = "Multi-File Image";      break;
-       case IH_TYPE_FIRMWARE:  type = "Firmware";              break;
-       case IH_TYPE_SCRIPT:    type = "Script";                break;
-       case IH_TYPE_FLATDT:    type = "Flat Device Tree";      break;
-       default:                type = "Unknown Image";         break;
-       }
-
-       switch (image_get_comp (hdr)) {
-       case IH_COMP_NONE:      comp = "uncompressed";          break;
-       case IH_COMP_GZIP:      comp = "gzip compressed";       break;
-       case IH_COMP_BZIP2:     comp = "bzip2 compressed";      break;
-       default:                comp = "unknown compression";   break;
-       }
-
-       printf ("%s %s %s (%s)", arch, os, type, comp);
-}
-
 #ifdef CONFIG_SILENT_CONSOLE
 static void fixup_silent_linux ()
 {
@@ -682,14 +883,22 @@ static void fixup_silent_linux ()
 
 static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag,
                            int argc, char *argv[],
-                           image_header_t *hdr, int verify)
+                           bootm_headers_t *images)
 {
        void (*loader)(bd_t *, image_header_t *, char *, char *);
-       image_header_t *img_addr;
+       image_header_t *os_hdr, *hdr;
        ulong kernel_data, kernel_len;
        char *consdev;
        char *cmdline;
 
+#if defined(CONFIG_FIT)
+       if (!images->legacy_hdr_valid) {
+               fit_unsupported_reset ("NetBSD");
+               do_reset (cmdtp, flag, argc, argv);
+       }
+#endif
+       hdr = images->legacy_hdr_os;
+
        /*
         * Booting a (NetBSD) kernel image
         *
@@ -701,12 +910,11 @@ static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag,
         * line, the name of the console device, and (optionally) the
         * address of the original image header.
         */
-
-       img_addr = 0;
-       if (image_check_type (hdr, IH_TYPE_MULTI)) {
+       os_hdr = NULL;
+       if (image_check_type (&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) {
                image_multi_getimg (hdr, 1, &kernel_data, &kernel_len);
                if (kernel_len)
-                       img_addr = hdr;
+                       os_hdr = hdr;
        }
 
        consdev = "";
@@ -752,24 +960,41 @@ static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag,
         *   r5: console device
         *   r6: boot args string
         */
-       (*loader) (gd->bd, img_addr, consdev, cmdline);
+       (*loader) (gd->bd, os_hdr, consdev, cmdline);
 }
 
 #ifdef CONFIG_LYNXKDI
 static void do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag,
                             int argc, char *argv[],
-                            image_header_t *hdr, int verify)
+                            bootm_headers_t *images)
 {
-       lynxkdi_boot (hdr);
+       image_header_t *hdr = &images->legacy_hdr_os_copy;
+
+#if defined(CONFIG_FIT)
+       if (!images->legacy_hdr_valid) {
+               fit_unsupported_reset ("Lynx");
+               do_reset (cmdtp, flag, argc, argv);
+       }
+#endif
+
+       lynxkdi_boot ((image_header_t *)hdr);
 }
 #endif /* CONFIG_LYNXKDI */
 
 static void do_bootm_rtems (cmd_tbl_t *cmdtp, int flag,
                           int argc, char *argv[],
-                          image_header_t *hdr, int verify)
+                          bootm_headers_t *images)
 {
+       image_header_t *hdr = &images->legacy_hdr_os_copy;
        void (*entry_point)(bd_t *);
 
+#if defined(CONFIG_FIT)
+       if (!images->legacy_hdr_valid) {
+               fit_unsupported_reset ("RTEMS");
+               do_reset (cmdtp, flag, argc, argv);
+       }
+#endif
+
        entry_point = (void (*)(bd_t *))image_get_ep (hdr);
 
        printf ("## Transferring control to RTEMS (at address %08lx) ...\n",
@@ -787,9 +1012,17 @@ static void do_bootm_rtems (cmd_tbl_t *cmdtp, int flag,
 #if defined(CONFIG_CMD_ELF)
 static void do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag,
                             int argc, char *argv[],
-                            image_header_t *hdr, int verify)
+                            bootm_headers_t *images)
 {
        char str[80];
+       image_header_t *hdr = &images->legacy_hdr_os_copy;
+
+#if defined(CONFIG_FIT)
+       if (!images->legacy_hdr_valid) {
+               fit_unsupported_reset ("VxWorks");
+               do_reset (cmdtp, flag, argc, argv);
+       }
+#endif
 
        sprintf(str, "%x", image_get_ep (hdr)); /* write entry-point into string */
        setenv("loadaddr", str);
@@ -798,10 +1031,18 @@ static void do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag,
 
 static void do_bootm_qnxelf(cmd_tbl_t *cmdtp, int flag,
                            int argc, char *argv[],
-                           image_header_t *hdr, int verify)
+                           bootm_headers_t *images)
 {
        char *local_args[2];
        char str[16];
+       image_header_t *hdr = &images->legacy_hdr_os_copy;
+
+#if defined(CONFIG_FIT)
+       if (!images->legacy_hdr_valid) {
+               fit_unsupported_reset ("QNX");
+               do_reset (cmdtp, flag, argc, argv);
+       }
+#endif
 
        sprintf(str, "%x", image_get_ep (hdr)); /* write entry-point into string */
        local_args[0] = argv[0];
@@ -813,7 +1054,7 @@ static void do_bootm_qnxelf(cmd_tbl_t *cmdtp, int flag,
 #if defined(CONFIG_ARTOS) && defined(CONFIG_PPC)
 static void do_bootm_artos (cmd_tbl_t *cmdtp, int flag,
                           int argc, char *argv[],
-                          image_header_t *hdr, int verify)
+                          bootm_headers_t *images)
 {
        ulong top;
        char *s, *cmdline;
@@ -821,6 +1062,14 @@ 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_copy;
+
+#if defined(CONFIG_FIT)
+       if (!images->legacy_hdr_valid) {
+               fit_unsupported_reset ("ARTOS");
+               do_reset (cmdtp, flag, argc, argv);
+       }
+#endif
 
        /*
         * Booting an ARTOS kernel image + application