[new uImage] Add autostart flag to bootm_headers structure
[oweals/u-boot.git] / common / image.c
index 736232867165d8d8578d2456066b1e7f4b5b76ed..4f2ff9c97719328b86603fa4c2fa02afedb68a77 100644 (file)
 #include <logbuff.h>
 #endif
 
+#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
+#include <rtc.h>
+#endif
+
 #if defined(CONFIG_FIT)
 #include <fdt.h>
 #include <libfdt.h>
 #include <fdt_support.h>
 #endif
 
-extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
-
 #ifdef CONFIG_CMD_BDI
 extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
 #endif
 
 DECLARE_GLOBAL_DATA_PTR;
+
+static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag,
+               int argc, char *argv[],
+               ulong rd_addr, uint8_t arch, int verify);
 #else
 #include "mkimage.h"
 #endif /* USE_HOSTCC*/
@@ -120,6 +126,12 @@ int getenv_verify (void)
        return (s && (*s == 'n')) ? 0 : 1;
 }
 
+int getenv_autostart (void)
+{
+       char *s = getenv ("autostart");
+       return (s && (*s == 'n')) ? 0 : 1;
+}
+
 void memmove_wd (void *to, void *from, size_t len, ulong chunksz)
 {
 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
@@ -310,6 +322,56 @@ const char* image_get_comp_name (uint8_t comp)
        return name;
 }
 
+static void image_print_type (image_header_t *hdr)
+{
+       const char *os, *arch, *type, *comp;
+
+       os = image_get_os_name (image_get_os (hdr));
+       arch = image_get_arch_name (image_get_arch (hdr));
+       type = image_get_type_name (image_get_type (hdr));
+       comp = image_get_comp_name (image_get_comp (hdr));
+
+       printf ("%s %s %s (%s)", arch, os, type, comp);
+}
+
+void image_print_contents (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:   ");
+       image_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");
+               }
+       }
+}
+
 /**
  * gen_image_get_format - get image format type
  * @img_addr: image start address
@@ -317,6 +379,10 @@ const char* image_get_comp_name (uint8_t comp)
  * gen_image_get_format() checks whether provided address points to a valid
  * legacy or FIT image.
  *
+ * New uImage format and FDT blob are based on a libfdt. FDT blob
+ * may be passed directly or embedded in a FIT image. In both situations
+ * gen_image_get_format() must be able to dectect libfdt header.
+ *
  * returns:
  *     image format type or IMAGE_FORMAT_INVALID if no image is present
  */
@@ -324,14 +390,14 @@ int gen_image_get_format (void *img_addr)
 {
        ulong           format = IMAGE_FORMAT_INVALID;
        image_header_t  *hdr;
-#if defined(CONFIG_FIT)
+#if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
        char            *fit_hdr;
 #endif
 
        hdr = (image_header_t *)img_addr;
        if (image_check_magic(hdr))
                format = IMAGE_FORMAT_LEGACY;
-#if defined(CONFIG_FIT)
+#if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
        else {
                fit_hdr = (char *)img_addr;
                if (fdt_check_header (fit_hdr) == 0)
@@ -354,55 +420,57 @@ int gen_image_get_format (void *img_addr)
  */
 ulong gen_get_image (ulong img_addr)
 {
-       ulong ram_addr, h_size, d_size;
-
-       h_size = image_get_header_size ();
-#if defined(CONFIG_FIT)
-       if (sizeof(struct fdt_header) > h_size)
-               h_size = sizeof(struct fdt_header);
-#endif
+       ulong ram_addr = img_addr;
 
 #ifdef CONFIG_HAS_DATAFLASH
+       ulong h_size, d_size;
+
        if (addr_dataflash (img_addr)){
+               /* ger RAM address */
                ram_addr = CFG_LOAD_ADDR;
+
+               /* get header size */
+               h_size = image_get_header_size ();
+#if defined(CONFIG_FIT)
+               if (sizeof(struct fdt_header) > h_size)
+                       h_size = sizeof(struct fdt_header);
+#endif
+
+               /* read in header */
                debug ("   Reading image header from dataflash address "
                        "%08lx to RAM address %08lx\n", img_addr, ram_addr);
-               read_dataflash (img_addr, h_size, (char *)ram_addr);
-       } else
-#endif
-               return img_addr;
 
-       ram_addr = img_addr;
+               read_dataflash (img_addr, h_size, (char *)ram_addr);
 
-       switch (gen_image_get_format ((void *)ram_addr)) {
-       case IMAGE_FORMAT_LEGACY:
-               d_size = image_get_data_size ((image_header_t *)ram_addr);
-               debug ("   Legacy format image found at 0x%08lx, size 0x%08lx\n",
-                               ram_addr, d_size);
-               break;
+               /* get data size */
+               switch (gen_image_get_format ((void *)ram_addr)) {
+               case IMAGE_FORMAT_LEGACY:
+                       d_size = image_get_data_size ((image_header_t *)ram_addr);
+                       debug ("   Legacy format image found at 0x%08lx, size 0x%08lx\n",
+                                       ram_addr, d_size);
+                       break;
 #if defined(CONFIG_FIT)
-       case IMAGE_FORMAT_FIT:
-               d_size = fdt_totalsize((void *)ram_addr) - h_size;
-               debug ("   FIT/FDT format image found at 0x%08lx, size 0x%08lx\n",
-                               ram_addr, d_size);
-
-               break;
+               case IMAGE_FORMAT_FIT:
+                       d_size = fdt_totalsize((void *)ram_addr) - h_size;
+                       debug ("   FIT/FDT format image found at 0x%08lx, size 0x%08lx\n",
+                                       ram_addr, d_size);
+                       break;
 #endif
-       default:
-               printf ("   No valid image found at 0x%08lx\n", img_addr);
-               return ram_addr;
-       }
+               default:
+                       printf ("   No valid image found at 0x%08lx\n", img_addr);
+                       return ram_addr;
+               }
 
-#ifdef CONFIG_HAS_DATAFLASH
-       if (addr_dataflash (img_addr)) {
+               /* read in image data */
                debug ("   Reading image remaining data from dataflash address "
                        "%08lx to RAM address %08lx\n", img_addr + h_size,
                        ram_addr + h_size);
 
                read_dataflash (img_addr + h_size, d_size,
                                (char *)(ram_addr + h_size));
+
        }
-#endif
+#endif /* CONFIG_HAS_DATAFLASH */
 
        return ram_addr;
 }
@@ -427,41 +495,38 @@ ulong gen_get_image (ulong img_addr)
  *
  * returns:
  *     pointer to a ramdisk image header, if image was found and valid
- *     otherwise, board is reset
+ *     otherwise, return NULL
  */
-image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag,
+static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag,
                int argc, char *argv[],
                ulong rd_addr, uint8_t arch, int verify)
 {
        image_header_t *rd_hdr;
 
        show_boot_progress (9);
-
-       /* copy from dataflash if needed */
-       rd_addr = gen_get_image (rd_addr);
        rd_hdr = (image_header_t *)rd_addr;
 
        if (!image_check_magic (rd_hdr)) {
                puts ("Bad Magic Number\n");
                show_boot_progress (-10);
-               do_reset (cmdtp, flag, argc, argv);
+               return NULL;
        }
 
        if (!image_check_hcrc (rd_hdr)) {
                puts ("Bad Header Checksum\n");
                show_boot_progress (-11);
-               do_reset (cmdtp, flag, argc, argv);
+               return NULL;
        }
 
        show_boot_progress (10);
-       print_image_hdr (rd_hdr);
+       image_print_contents (rd_hdr);
 
        if (verify) {
                puts("   Verifying Checksum ... ");
                if (!image_check_dcrc_wd (rd_hdr, CHUNKSZ)) {
                        puts ("Bad Data CRC\n");
                        show_boot_progress (-12);
-                       do_reset (cmdtp, flag, argc, argv);
+                       return NULL;
                }
                puts("OK\n");
        }
@@ -474,7 +539,7 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag,
                printf ("No Linux %s Ramdisk Image\n",
                                image_get_arch_name(arch));
                show_boot_progress (-13);
-               do_reset (cmdtp, flag, argc, argv);
+               return NULL;
        }
 
        return rd_hdr;
@@ -486,8 +551,7 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag,
  * @flag: command flag
  * @argc: command argument count
  * @argv: command argument list
- * @hdr: pointer to the posiibly multi componet kernel image
- * @verify: checksum verification flag
+ * @images: pointer to the bootm images structure
  * @arch: expected ramdisk architecture
  * @rd_start: pointer to a ulong variable, will hold ramdisk start address
  * @rd_end: pointer to a ulong variable, will hold ramdisk end
@@ -501,59 +565,120 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag,
  *     rd_start and rd_end are set to ramdisk start/end addresses if
  *     ramdisk image is found and valid
  *     rd_start and rd_end are set to 0 if no ramdisk exists
- *     board is reset if ramdisk image is found but corrupted
+ *     return 1 if ramdisk image is found but corrupted
  */
-void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
-               image_header_t *hdr, int verify, uint8_t arch,
+int get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
+               bootm_headers_t *images, uint8_t arch,
                ulong *rd_start, ulong *rd_end)
 {
-       ulong rd_addr;
+       ulong rd_addr, rd_load;
        ulong rd_data, rd_len;
        image_header_t *rd_hdr;
+#if defined(CONFIG_FIT)
+       void            *fit_hdr;
+       const char      *fit_uname_config = NULL;
+       const char      *fit_uname_ramdisk = NULL;
+       ulong           default_addr;
+#endif
 
-       if (argc >= 3) {
+       /*
+        * Look for a '-' which indicates to ignore the
+        * ramdisk argument
+        */
+       if ((argc >= 3) && (strcmp(argv[2], "-") ==  0)) {
+               debug ("## Skipping init Ramdisk\n");
+               rd_len = rd_data = 0;
+       } else if (argc >= 3) {
+#if defined(CONFIG_FIT)
                /*
-                * Look for a '-' which indicates to ignore the
-                * ramdisk argument
+                * If the init ramdisk comes from the FIT image and the FIT image
+                * address is omitted in the command line argument, try to use
+                * os FIT image address or default load address.
                 */
-               if (strcmp(argv[2], "-") ==  0) {
-                       debug ("## Skipping init Ramdisk\n");
-                       rd_len = rd_data = 0;
-               } else {
-                       /*
-                        * Check if there is an initrd image at the
-                        * address provided in the second bootm argument
-                        */
-                       rd_addr = simple_strtoul (argv[2], NULL, 16);
-                       printf ("## Loading init Ramdisk Image at %08lx ...\n",
+               if (images->fit_uname_os)
+                       default_addr = (ulong)images->fit_hdr_os;
+               else
+                       default_addr = load_addr;
+
+               if (fit_parse_conf (argv[2], default_addr,
+                                       &rd_addr, &fit_uname_config)) {
+                       debug ("*  ramdisk: config '%s' from image at 0x%08lx\n",
+                                       fit_uname_config, rd_addr);
+               } else if (fit_parse_subimage (argv[2], default_addr,
+                                       &rd_addr, &fit_uname_ramdisk)) {
+                       debug ("*  ramdisk: subimage '%s' from image at 0x%08lx\n",
+                                       fit_uname_ramdisk, rd_addr);
+               } else
+#endif
+               {
+                       rd_addr = simple_strtoul(argv[2], NULL, 16);
+                       debug ("*  ramdisk: cmdline image address = 0x%08lx\n",
                                        rd_addr);
+               }
+
+               /* copy from dataflash if needed */
+               printf ("## Loading init Ramdisk Image at %08lx ...\n",
+                               rd_addr);
+               rd_addr = gen_get_image (rd_addr);
+
+               /*
+                * Check if there is an initrd image at the
+                * address provided in the second bootm argument
+                * check image type, for FIT images get FIT node.
+                */
+               switch (gen_image_get_format ((void *)rd_addr)) {
+               case IMAGE_FORMAT_LEGACY:
+
+                       debug ("*  ramdisk: legacy format image\n");
 
                        rd_hdr = image_get_ramdisk (cmdtp, flag, argc, argv,
-                                               rd_addr, arch, verify);
+                                               rd_addr, arch, images->verify);
+
+                       if (rd_hdr == NULL) {
+                               *rd_start = 0;
+                               *rd_end = 0;
+                               return 1;
+                       }
 
                        rd_data = image_get_data (rd_hdr);
                        rd_len = image_get_data_size (rd_hdr);
+                       rd_load = image_get_load (rd_hdr);
+                       break;
+#if defined(CONFIG_FIT)
+               case IMAGE_FORMAT_FIT:
+                       fit_hdr = (void *)rd_addr;
+                       debug ("*  ramdisk: FIT format image\n");
+                       fit_unsupported_reset ("ramdisk");
+                       return 1;
+#endif
+               default:
+                       printf ("Wrong Image Format for %s command\n",
+                                       cmdtp->name);
+                       rd_data = rd_len = 0;
+               }
 
 #if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO)
-                       /*
-                        *we need to copy the ramdisk to SRAM to let Linux boot
-                        */
-                       memmove ((void *)image_get_load (rd_hdr),
-                                       (uchar *)rd_data, rd_len);
-
-                       rd_data = image_get_load (rd_hdr);
-#endif /* CONFIG_B2 || CONFIG_EVB4510 || CONFIG_ARMADILLO */
+               /*
+                * We need to copy the ramdisk to SRAM to let Linux boot
+                */
+               if (rd_data) {
+                       memmove ((void *)rd_load, (uchar *)rd_data, rd_len);
+                       rd_data = rd_load;
                }
+#endif /* CONFIG_B2 || CONFIG_EVB4510 || CONFIG_ARMADILLO */
 
-       } else if (image_check_type (hdr, IH_TYPE_MULTI)) {
+       } else if (images->legacy_hdr_valid &&
+                       image_check_type (images->legacy_hdr_os, IH_TYPE_MULTI)) {
                /*
-                * Now check if we have a multifile image
-                * Get second entry data start address and len
+                * Now check if we have a legacy mult-component image,
+                * get second entry data start address and len.
                 */
                show_boot_progress (13);
                printf ("## Loading init Ramdisk from multi component "
-                               "Image at %08lx ...\n", (ulong)hdr);
-               image_multi_getimg (hdr, 1, &rd_data, &rd_len);
+                               "Image at %08lx ...\n",
+                               (ulong)images->legacy_hdr_os);
+
+               image_multi_getimg (images->legacy_hdr_os, 1, &rd_data, &rd_len);
        } else {
                /*
                 * no initrd image
@@ -572,6 +697,8 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
        }
        debug ("   ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n",
                        *rd_start, *rd_end);
+
+       return 0;
 }
 
 #if defined(CONFIG_PPC) || defined(CONFIG_M68K)
@@ -579,7 +706,6 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
  * ramdisk_high - relocate init ramdisk
  * @rd_data: ramdisk data start address
  * @rd_len: ramdisk data length
- * @kbd: kernel board info copy (within BOOTMAPSZ boundary)
  * @sp_limit: stack pointer limit (including BOOTMAPSZ)
  * @sp: current stack pointer
  * @initrd_start: pointer to a ulong variable, will hold final init ramdisk
@@ -597,7 +723,7 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
  *     - returns new allc_current, next free address below BOOTMAPSZ
  */
 ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len,
-               bd_t *kbd, ulong sp_limit, ulong sp,
+               ulong sp_limit, ulong sp,
                ulong *initrd_start, ulong *initrd_end)
 {
        char    *s;
@@ -619,9 +745,9 @@ ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len,
 
 #ifdef CONFIG_LOGBUFFER
        /* Prevent initrd from overwriting logbuffer */
-       if (initrd_high < (kbd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD))
-               initrd_high = kbd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD;
-       debug ("## Logbuffer at 0x%08lx ", kbd->bi_memsize - LOGBUFF_LEN);
+       if (initrd_high < (gd->bd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD))
+           initrd_high = gd->bd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD;
+       debug ("## Logbuffer at 0x%08lx ", gd->bd->bi_memsize - LOGBUFF_LEN);
 #endif
        debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n",
                        initrd_high, initrd_copy_to_ram);
@@ -850,6 +976,7 @@ inline int fit_parse_subimage (const char *spec, ulong addr_curr,
 {
        return fit_parse_spec (spec, ':', addr_curr, addr, image_name);
 }
+
 #endif /* CONFIG_FIT */
 
 #endif /* USE_HOSTCC */