Fix crash on sequoia in ppc_4xx_eth_init
[oweals/u-boot.git] / common / image.c
index 9278ea92b3c48531b71855aada89225f64c5c389..d218f2f88ba77397fd69b24e8e6f17cd9dde1954 100644 (file)
@@ -23,7 +23,6 @@
  * MA 02111-1307 USA
  */
 
-#define DEBUG
 
 #ifndef USE_HOSTCC
 #include <common.h>
 
 #include <image.h>
 
-#if defined(CONFIG_FIT)
+#if defined(CONFIG_FIT) || defined (CONFIG_OF_LIBFDT)
 #include <fdt.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#endif
+
+#if defined(CONFIG_FIT)
+#include <u-boot/md5.h>
 #include <sha1.h>
+
+static int fit_check_ramdisk (const void *fit, int os_noffset,
+               uint8_t arch, int verify);
 #endif
 
 #ifdef CONFIG_CMD_BDI
@@ -60,11 +66,11 @@ extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
 
 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);
+static image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch,
+                                               int verify);
 #else
 #include "mkimage.h"
+#include <u-boot/md5.h>
 #include <time.h>
 #include <image.h>
 #endif /* !USE_HOSTCC*/
@@ -373,10 +379,6 @@ inline void image_print_contents_noindent (image_header_t *hdr)
 #ifndef USE_HOSTCC
 /**
  * image_get_ramdisk - get and verify ramdisk image
- * @cmdtp: command table pointer
- * @flag: command flag
- * @argc: command argument count
- * @argv: command argument list
  * @rd_addr: ramdisk image start address
  * @arch: expected ramdisk architecture
  * @verify: checksum verification flag
@@ -393,14 +395,10 @@ inline void image_print_contents_noindent (image_header_t *hdr)
  *     pointer to a ramdisk image header, if image was found and valid
  *     otherwise, return NULL
  */
-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)
+static image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch,
+                                               int verify)
 {
-       image_header_t *rd_hdr;
-
-       show_boot_progress (9);
-       rd_hdr = (image_header_t *)rd_addr;
+       image_header_t *rd_hdr = (image_header_t *)rd_addr;
 
        if (!image_check_magic (rd_hdr)) {
                puts ("Bad Magic Number\n");
@@ -466,8 +464,10 @@ ulong getenv_bootm_low(void)
                return tmp;
        }
 
-#ifdef CFG_SDRAM_BASE
+#if defined(CFG_SDRAM_BASE)
        return CFG_SDRAM_BASE;
+#elif defined(CONFIG_ARM)
+       return gd->bd->bi_dram[0].start;
 #else
        return 0;
 #endif
@@ -481,7 +481,11 @@ ulong getenv_bootm_size(void)
                return tmp;
        }
 
+#if defined(CONFIG_ARM)
+       return gd->bd->bi_dram[0].size;
+#else
        return gd->bd->bi_memsize;
+#endif
 }
 
 void memmove_wd (void *to, void *from, size_t len, ulong chunksz)
@@ -740,10 +744,28 @@ ulong genimg_get_image (ulong img_addr)
        return ram_addr;
 }
 
+/**
+ * fit_has_config - check if there is a valid FIT configuration
+ * @images: pointer to the bootm command headers structure
+ *
+ * fit_has_config() checks if there is a FIT configuration in use
+ * (if FTI support is present).
+ *
+ * returns:
+ *     0, no FIT support or no configuration found
+ *     1, configuration found
+ */
+int genimg_has_config (bootm_headers_t *images)
+{
+#if defined(CONFIG_FIT)
+       if (images->fit_uname_cfg)
+               return 1;
+#endif
+       return 0;
+}
+
 /**
  * boot_get_ramdisk - main ramdisk handling routine
- * @cmdtp: command table pointer
- * @flag: command flag
  * @argc: command argument count
  * @argv: command argument list
  * @images: pointer to the bootm images structure
@@ -757,14 +779,15 @@ ulong genimg_get_image (ulong img_addr)
  *      - commandline provided address of decicated ramdisk image.
  *
  * returns:
+ *     0, if ramdisk image was found and valid, or skiped
  *     rd_start and rd_end are set to ramdisk start/end addresses if
  *     ramdisk image is found and valid
+ *
+ *     1, if ramdisk image is found but corrupted
  *     rd_start and rd_end are set to 0 if no ramdisk exists
- *     return 1 if ramdisk image is found but corrupted
  */
-int boot_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)
+int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images,
+               uint8_t arch, ulong *rd_start, ulong *rd_end)
 {
        ulong rd_addr, rd_load;
        ulong rd_data, rd_len;
@@ -774,8 +797,15 @@ int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
        const char      *fit_uname_config = NULL;
        const char      *fit_uname_ramdisk = NULL;
        ulong           default_addr;
+       int             rd_noffset;
+       int             cfg_noffset;
+       const void      *data;
+       size_t          size;
 #endif
 
+       *rd_start = 0;
+       *rd_end = 0;
+
        /*
         * Look for a '-' which indicates to ignore the
         * ramdisk argument
@@ -783,37 +813,65 @@ int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
        if ((argc >= 3) && (strcmp(argv[2], "-") ==  0)) {
                debug ("## Skipping init Ramdisk\n");
                rd_len = rd_data = 0;
-       } else if (argc >= 3) {
+       } else if (argc >= 3 || genimg_has_config (images)) {
 #if defined(CONFIG_FIT)
-               /*
-                * 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 (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
+               if (argc >= 3) {
+                       /*
+                        * 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 (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);
+                       {
+                               rd_addr = simple_strtoul(argv[2], NULL, 16);
+                               debug ("*  ramdisk: cmdline image address = 0x%08lx\n",
+                                               rd_addr);
+                       }
+#if defined(CONFIG_FIT)
+               } else {
+                       /* use FIT configuration provided in first bootm
+                        * command argument
+                        */
+                       rd_addr = (ulong)images->fit_hdr_os;
+                       fit_uname_config = images->fit_uname_cfg;
+                       debug ("*  ramdisk: using config '%s' from image at 0x%08lx\n",
+                                       fit_uname_config, rd_addr);
+
+                       /*
+                        * Check whether configuration has ramdisk defined,
+                        * if not, don't try to use it, quit silently.
+                        */
+                       fit_hdr = (void *)rd_addr;
+                       cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config);
+                       if (cfg_noffset < 0) {
+                               debug ("*  ramdisk: no such config\n");
+                               return 0;
+                       }
+
+                       rd_noffset = fit_conf_get_ramdisk_node (fit_hdr, cfg_noffset);
+                       if (rd_noffset < 0) {
+                               debug ("*  ramdisk: no ramdisk in config\n");
+                               return 0;
+                       }
                }
+#endif
 
                /* copy from dataflash if needed */
-               printf ("## Loading init Ramdisk Image at %08lx ...\n",
-                               rd_addr);
                rd_addr = genimg_get_image (rd_addr);
 
                /*
@@ -823,17 +881,15 @@ int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
                 */
                switch (genimg_get_format ((void *)rd_addr)) {
                case IMAGE_FORMAT_LEGACY:
+                       printf ("## Loading init Ramdisk from Legacy "
+                                       "Image at %08lx ...\n", rd_addr);
 
-                       debug ("*  ramdisk: legacy format image\n");
+                       show_boot_progress (9);
+                       rd_hdr = image_get_ramdisk (rd_addr, arch,
+                                                       images->verify);
 
-                       rd_hdr = image_get_ramdisk (cmdtp, flag, argc, argv,
-                                               rd_addr, arch, images->verify);
-
-                       if (rd_hdr == NULL) {
-                               *rd_start = 0;
-                               *rd_end = 0;
+                       if (rd_hdr == NULL)
                                return 1;
-                       }
 
                        rd_data = image_get_data (rd_hdr);
                        rd_len = image_get_data_size (rd_hdr);
@@ -842,14 +898,78 @@ int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
 #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;
+                       printf ("## Loading init Ramdisk from FIT "
+                                       "Image at %08lx ...\n", rd_addr);
+
+                       show_boot_progress (120);
+                       if (!fit_check_format (fit_hdr)) {
+                               puts ("Bad FIT ramdisk image format!\n");
+                               show_boot_progress (-120);
+                               return 0;
+                       }
+                       show_boot_progress (121);
+
+                       if (!fit_uname_ramdisk) {
+                               /*
+                                * no ramdisk 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 (122);
+                               cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config);
+                               if (cfg_noffset < 0) {
+                                       puts ("Could not find configuration node\n");
+                                       show_boot_progress (-122);
+                                       return 0;
+                               }
+                               fit_uname_config = fdt_get_name (fit_hdr, cfg_noffset, NULL);
+                               printf ("   Using '%s' configuration\n", fit_uname_config);
+
+                               rd_noffset = fit_conf_get_ramdisk_node (fit_hdr, cfg_noffset);
+                               fit_uname_ramdisk = fit_get_name (fit_hdr, rd_noffset, NULL);
+                       } else {
+                               /* get ramdisk component image node offset */
+                               show_boot_progress (123);
+                               rd_noffset = fit_image_get_node (fit_hdr, fit_uname_ramdisk);
+                       }
+                       if (rd_noffset < 0) {
+                               puts ("Could not find subimage node\n");
+                               show_boot_progress (-124);
+                               return 0;
+                       }
+
+                       printf ("   Trying '%s' ramdisk subimage\n", fit_uname_ramdisk);
+
+                       show_boot_progress (125);
+                       if (!fit_check_ramdisk (fit_hdr, rd_noffset, arch, images->verify))
+                               return 0;
+
+                       /* get ramdisk image data address and length */
+                       if (fit_image_get_data (fit_hdr, rd_noffset, &data, &size)) {
+                               puts ("Could not find ramdisk subimage data!\n");
+                               show_boot_progress (-127);
+                               return 0;
+                       }
+                       show_boot_progress (128);
+
+                       rd_data = (ulong)data;
+                       rd_len = size;
+
+                       if (fit_image_get_load (fit_hdr, rd_noffset, &rd_load)) {
+                               puts ("Can't get ramdisk subimage load address!\n");
+                               show_boot_progress (-129);
+                               return 0;
+                       }
+                       show_boot_progress (129);
+
+                       images->fit_hdr_rd = fit_hdr;
+                       images->fit_uname_rd = fit_uname_ramdisk;
+                       images->fit_noffset_rd = rd_noffset;
+                       break;
 #endif
                default:
-                       printf ("Wrong Image Format for %s command\n",
-                                       cmdtp->name);
-                       rd_data = rd_len = 0;
+                       puts ("Wrong Ramdisk Image Format\n");
+                       rd_data = rd_len = rd_load = 0;
                }
 
 #if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO)
@@ -863,14 +983,14 @@ int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
 #endif /* CONFIG_B2 || CONFIG_EVB4510 || CONFIG_ARMADILLO */
 
        } else if (images->legacy_hdr_valid &&
-                       image_check_type (images->legacy_hdr_os, IH_TYPE_MULTI)) {
+                       image_check_type (&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) {
                /*
                 * 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",
+                               "Legacy Image at %08lx ...\n",
                                (ulong)images->legacy_hdr_os);
 
                image_multi_getimg (images->legacy_hdr_os, 1, &rd_data, &rd_len);
@@ -884,8 +1004,6 @@ int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
 
        if (!rd_data) {
                debug ("## No init Ramdisk\n");
-               *rd_start = 0;
-               *rd_end = 0;
        } else {
                *rd_start = rd_data;
                *rd_end = rd_data + rd_len;
@@ -896,7 +1014,7 @@ int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
        return 0;
 }
 
-#if defined(CONFIG_PPC) || defined(CONFIG_M68K)
+#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC)
 /**
  * boot_ramdisk_high - relocate init ramdisk
  * @lmb: pointer to lmb handle, will be used for memory mgmt
@@ -1823,8 +1941,8 @@ static int calculate_hash (const void *data, int data_len, const char *algo,
                                (unsigned char *) value);
                *value_len = 20;
        } else if (strcmp (algo, "md5") == 0 ) {
-               printf ("MD5 not supported\n");
-               *value_len = 0;
+               md5 ((unsigned char *)data, data_len, value);
+               *value_len = 16;
        } else {
                debug ("Unsupported hash alogrithm\n");
                return -1;
@@ -2337,7 +2455,7 @@ int fit_conf_get_fdt_node (const void *fit, int noffset)
 /**
  * fit_conf_print - prints out the FIT configuration details
  * @fit: pointer to the FIT format image header
- * @conf_noffset: offset of the configuration node
+ * @noffset: offset of the configuration node
  * @p: pointer to prefix string
  *
  * fit_conf_print() lists all mandatory properies for the processed
@@ -2376,4 +2494,48 @@ void fit_conf_print (const void *fit, int noffset, const char *p)
        if (uname)
                printf ("%s  FDT:          %s\n", p, uname);
 }
+
+/**
+ * fit_check_ramdisk - verify FIT format ramdisk subimage
+ * @fit_hdr: pointer to the FIT ramdisk header
+ * @rd_noffset: ramdisk subimage node offset within FIT image
+ * @arch: requested ramdisk image architecture type
+ * @verify: data CRC verification flag
+ *
+ * fit_check_ramdisk() verifies integrity of the ramdisk subimage and from
+ * specified FIT image.
+ *
+ * returns:
+ *     1, on success
+ *     0, on failure
+ */
+#ifndef USE_HOSTCC
+static int fit_check_ramdisk (const void *fit, int rd_noffset, uint8_t arch, int verify)
+{
+       fit_image_print (fit, rd_noffset, "   ");
+
+       if (verify) {
+               puts ("   Verifying Hash Integrity ... ");
+               if (!fit_image_check_hashes (fit, rd_noffset)) {
+                       puts ("Bad Data Hash\n");
+                       show_boot_progress (-125);
+                       return 0;
+               }
+               puts ("OK\n");
+       }
+
+       show_boot_progress (126);
+       if (!fit_image_check_os (fit, rd_noffset, IH_OS_LINUX) ||
+           !fit_image_check_arch (fit, rd_noffset, arch) ||
+           !fit_image_check_type (fit, rd_noffset, IH_TYPE_RAMDISK)) {
+               printf ("No Linux %s Ramdisk Image\n",
+                               genimg_get_arch_name(arch));
+               show_boot_progress (-126);
+               return 0;
+       }
+
+       show_boot_progress (127);
+       return 1;
+}
+#endif /* USE_HOSTCC */
 #endif /* CONFIG_FIT */