Merge branch 'master' of git://git.denx.de/u-boot
[oweals/u-boot.git] / common / image-fit.c
index f6e956ad963a0d2a390c64bed812b23de9d4dbbc..368b73088a2af9d0683e050ec13a9e33513f1481 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 2013, Google Inc.
  *
@@ -5,13 +6,12 @@
  *
  * (C) Copyright 2000-2006
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #ifdef USE_HOSTCC
 #include "mkimage.h"
 #include <time.h>
+#include <u-boot/crc.h>
 #else
 #include <linux/compiler.h>
 #include <linux/kconfig.h>
@@ -23,6 +23,7 @@
 DECLARE_GLOBAL_DATA_PTR;
 #endif /* !USE_HOSTCC*/
 
+#include <bootm.h>
 #include <image.h>
 #include <bootstage.h>
 #include <u-boot/crc.h>
@@ -143,7 +144,191 @@ int fit_get_subimage_count(const void *fit, int images_noffset)
        return count;
 }
 
-#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_FIT_SPL_PRINT)
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FIT_PRINT)
+/**
+ * fit_image_print_data() - prints out the hash node details
+ * @fit: pointer to the FIT format image header
+ * @noffset: offset of the hash node
+ * @p: pointer to prefix string
+ * @type: Type of information to print ("hash" or "sign")
+ *
+ * fit_image_print_data() lists properties for the processed hash node
+ *
+ * This function avoid using puts() since it prints a newline on the host
+ * but does not in U-Boot.
+ *
+ * returns:
+ *     no returned results
+ */
+static void fit_image_print_data(const void *fit, int noffset, const char *p,
+                                const char *type)
+{
+       const char *keyname;
+       uint8_t *value;
+       int value_len;
+       char *algo;
+       const char *padding;
+       bool required;
+       int ret, i;
+
+       debug("%s  %s node:    '%s'\n", p, type,
+             fit_get_name(fit, noffset, NULL));
+       printf("%s  %s algo:    ", p, type);
+       if (fit_image_hash_get_algo(fit, noffset, &algo)) {
+               printf("invalid/unsupported\n");
+               return;
+       }
+       printf("%s", algo);
+       keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL);
+       required = fdt_getprop(fit, noffset, FIT_KEY_REQUIRED, NULL) != NULL;
+       if (keyname)
+               printf(":%s", keyname);
+       if (required)
+               printf(" (required)");
+       printf("\n");
+
+       padding = fdt_getprop(fit, noffset, "padding", NULL);
+       if (padding)
+               printf("%s  %s padding: %s\n", p, type, padding);
+
+       ret = fit_image_hash_get_value(fit, noffset, &value,
+                                      &value_len);
+       printf("%s  %s value:   ", p, type);
+       if (ret) {
+               printf("unavailable\n");
+       } else {
+               for (i = 0; i < value_len; i++)
+                       printf("%02x", value[i]);
+               printf("\n");
+       }
+
+       debug("%s  %s len:     %d\n", p, type, value_len);
+
+       /* Signatures have a time stamp */
+       if (IMAGE_ENABLE_TIMESTAMP && keyname) {
+               time_t timestamp;
+
+               printf("%s  Timestamp:    ", p);
+               if (fit_get_timestamp(fit, noffset, &timestamp))
+                       printf("unavailable\n");
+               else
+                       genimg_print_time(timestamp);
+       }
+}
+
+/**
+ * fit_image_print_verification_data() - prints out the hash/signature details
+ * @fit: pointer to the FIT format image header
+ * @noffset: offset of the hash or signature node
+ * @p: pointer to prefix string
+ *
+ * This lists properties for the processed hash node
+ *
+ * returns:
+ *     no returned results
+ */
+static void fit_image_print_verification_data(const void *fit, int noffset,
+                                             const char *p)
+{
+       const char *name;
+
+       /*
+        * Check subnode name, must be equal to "hash" or "signature".
+        * Multiple hash/signature nodes require unique unit node
+        * names, e.g. hash-1, hash-2, signature-1, signature-2, etc.
+        */
+       name = fit_get_name(fit, noffset, NULL);
+       if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) {
+               fit_image_print_data(fit, noffset, p, "Hash");
+       } else if (!strncmp(name, FIT_SIG_NODENAME,
+                               strlen(FIT_SIG_NODENAME))) {
+               fit_image_print_data(fit, noffset, p, "Sign");
+       }
+}
+
+/**
+ * fit_conf_print - prints out the FIT configuration details
+ * @fit: pointer to the FIT format image header
+ * @noffset: offset of the configuration node
+ * @p: pointer to prefix string
+ *
+ * fit_conf_print() lists all mandatory properties for the processed
+ * configuration node.
+ *
+ * returns:
+ *     no returned results
+ */
+static void fit_conf_print(const void *fit, int noffset, const char *p)
+{
+       char *desc;
+       const char *uname;
+       int ret;
+       int fdt_index, loadables_index;
+       int ndepth;
+
+       /* Mandatory properties */
+       ret = fit_get_desc(fit, noffset, &desc);
+       printf("%s  Description:  ", p);
+       if (ret)
+               printf("unavailable\n");
+       else
+               printf("%s\n", desc);
+
+       uname = fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
+       printf("%s  Kernel:       ", p);
+       if (!uname)
+               printf("unavailable\n");
+       else
+               printf("%s\n", uname);
+
+       /* Optional properties */
+       uname = fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL);
+       if (uname)
+               printf("%s  Init Ramdisk: %s\n", p, uname);
+
+       uname = fdt_getprop(fit, noffset, FIT_FIRMWARE_PROP, NULL);
+       if (uname)
+               printf("%s  Firmware:     %s\n", p, uname);
+
+       for (fdt_index = 0;
+            uname = fdt_stringlist_get(fit, noffset, FIT_FDT_PROP,
+                                       fdt_index, NULL), uname;
+            fdt_index++) {
+               if (fdt_index == 0)
+                       printf("%s  FDT:          ", p);
+               else
+                       printf("%s                ", p);
+               printf("%s\n", uname);
+       }
+
+       uname = fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL);
+       if (uname)
+               printf("%s  FPGA:         %s\n", p, uname);
+
+       /* Print out all of the specified loadables */
+       for (loadables_index = 0;
+            uname = fdt_stringlist_get(fit, noffset, FIT_LOADABLE_PROP,
+                                       loadables_index, NULL), uname;
+            loadables_index++) {
+               if (loadables_index == 0) {
+                       printf("%s  Loadables:    ", p);
+               } else {
+                       printf("%s                ", p);
+               }
+               printf("%s\n", uname);
+       }
+
+       /* Process all hash subnodes of the component configuration node */
+       for (ndepth = 0, noffset = fdt_next_node(fit, noffset, &ndepth);
+            (noffset >= 0) && (ndepth > 0);
+            noffset = fdt_next_node(fit, noffset, &ndepth)) {
+               if (ndepth == 1) {
+                       /* Direct child node of the component configuration node */
+                       fit_image_print_verification_data(fit, noffset, p);
+               }
+       }
+}
+
 /**
  * fit_print_contents - prints out the contents of the FIT format image
  * @fit: pointer to the FIT format image header
@@ -241,103 +426,7 @@ void fit_print_contents(const void *fit)
                               fit_get_name(fit, noffset, NULL));
 
                        fit_conf_print(fit, noffset, p);
-               }
-       }
-}
-
-/**
- * fit_image_print_data() - prints out the hash node details
- * @fit: pointer to the FIT format image header
- * @noffset: offset of the hash node
- * @p: pointer to prefix string
- * @type: Type of information to print ("hash" or "sign")
- *
- * fit_image_print_data() lists properties for the processed hash node
- *
- * This function avoid using puts() since it prints a newline on the host
- * but does not in U-Boot.
- *
- * returns:
- *     no returned results
- */
-static void fit_image_print_data(const void *fit, int noffset, const char *p,
-                                const char *type)
-{
-       const char *keyname;
-       uint8_t *value;
-       int value_len;
-       char *algo;
-       int required;
-       int ret, i;
-
-       debug("%s  %s node:    '%s'\n", p, type,
-             fit_get_name(fit, noffset, NULL));
-       printf("%s  %s algo:    ", p, type);
-       if (fit_image_hash_get_algo(fit, noffset, &algo)) {
-               printf("invalid/unsupported\n");
-               return;
-       }
-       printf("%s", algo);
-       keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
-       required = fdt_getprop(fit, noffset, "required", NULL) != NULL;
-       if (keyname)
-               printf(":%s", keyname);
-       if (required)
-               printf(" (required)");
-       printf("\n");
-
-       ret = fit_image_hash_get_value(fit, noffset, &value,
-                                       &value_len);
-       printf("%s  %s value:   ", p, type);
-       if (ret) {
-               printf("unavailable\n");
-       } else {
-               for (i = 0; i < value_len; i++)
-                       printf("%02x", value[i]);
-               printf("\n");
-       }
-
-       debug("%s  %s len:     %d\n", p, type, value_len);
-
-       /* Signatures have a time stamp */
-       if (IMAGE_ENABLE_TIMESTAMP && keyname) {
-               time_t timestamp;
-
-               printf("%s  Timestamp:    ", p);
-               if (fit_get_timestamp(fit, noffset, &timestamp))
-                       printf("unavailable\n");
-               else
-                       genimg_print_time(timestamp);
-       }
-}
-
-/**
- * fit_image_print_verification_data() - prints out the hash/signature details
- * @fit: pointer to the FIT format image header
- * @noffset: offset of the hash or signature node
- * @p: pointer to prefix string
- *
- * This lists properties for the processed hash node
- *
- * returns:
- *     no returned results
- */
-static void fit_image_print_verification_data(const void *fit, int noffset,
-                                      const char *p)
-{
-       const char *name;
-
-       /*
-        * Check subnode name, must be equal to "hash" or "signature".
-        * Multiple hash/signature nodes require unique unit node
-        * names, e.g. hash-1, hash-2, signature-1, signature-2, etc.
-        */
-       name = fit_get_name(fit, noffset, NULL);
-       if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) {
-               fit_image_print_data(fit, noffset, p, "Hash");
-       } else if (!strncmp(name, FIT_SIG_NODENAME,
-                               strlen(FIT_SIG_NODENAME))) {
-               fit_image_print_data(fit, noffset, p, "Sign");
+               }
        }
 }
 
@@ -392,7 +481,7 @@ void fit_image_print(const void *fit, int image_noffset, const char *p)
        fit_image_get_comp(fit, image_noffset, &comp);
        printf("%s  Compression:  %s\n", p, genimg_get_comp_name(comp));
 
-       ret = fit_image_get_data(fit, image_noffset, &data, &size);
+       ret = fit_image_get_data_and_size(fit, image_noffset, &data, &size);
 
 #ifndef USE_HOSTCC
        printf("%s  Data Start:   ", p);
@@ -419,7 +508,8 @@ void fit_image_print(const void *fit, int image_noffset, const char *p)
                printf("%s  Architecture: %s\n", p, genimg_get_arch_name(arch));
        }
 
-       if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK)) {
+       if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK) ||
+           (type == IH_TYPE_FIRMWARE)) {
                fit_image_get_os(fit, image_noffset, &os);
                printf("%s  OS:           %s\n", p, genimg_get_os_name(os));
        }
@@ -459,8 +549,10 @@ void fit_image_print(const void *fit, int image_noffset, const char *p)
                }
        }
 }
-
-#endif /* !defined(CONFIG_SPL_BUILD) || defined(CONFIG_FIT_SPL_PRINT) */
+#else
+void fit_print_contents(const void *fit) { }
+void fit_image_print(const void *fit, int image_noffset, const char *p) { }
+#endif /* !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FIT_PRINT) */
 
 /**
  * fit_get_desc - get node description property
@@ -855,6 +947,81 @@ int fit_image_get_data_size(const void *fit, int noffset, int *data_size)
        return 0;
 }
 
+/**
+ * Get 'data-size-unciphered' property from a given image node.
+ *
+ * @fit: pointer to the FIT image header
+ * @noffset: component image node offset
+ * @data_size: holds the data-size property
+ *
+ * returns:
+ *     0, on success
+ *     -ENOENT if the property could not be found
+ */
+int fit_image_get_data_size_unciphered(const void *fit, int noffset,
+                                      size_t *data_size)
+{
+       const fdt32_t *val;
+
+       val = fdt_getprop(fit, noffset, "data-size-unciphered", NULL);
+       if (!val)
+               return -ENOENT;
+
+       *data_size = (size_t)fdt32_to_cpu(*val);
+
+       return 0;
+}
+
+/**
+ * fit_image_get_data_and_size - get data and its size including
+ *                              both embedded and external data
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @data: double pointer to void, will hold data property's data address
+ * @size: pointer to size_t, will hold data property's data size
+ *
+ * fit_image_get_data_and_size() finds data and its size including
+ * both embedded and external data. If the property is found
+ * its data start address and size are returned to the caller.
+ *
+ * returns:
+ *     0, on success
+ *     otherwise, on failure
+ */
+int fit_image_get_data_and_size(const void *fit, int noffset,
+                               const void **data, size_t *size)
+{
+       bool external_data = false;
+       int offset;
+       int len;
+       int ret;
+
+       if (!fit_image_get_data_position(fit, noffset, &offset)) {
+               external_data = true;
+       } else if (!fit_image_get_data_offset(fit, noffset, &offset)) {
+               external_data = true;
+               /*
+                * For FIT with external data, figure out where
+                * the external images start. This is the base
+                * for the data-offset properties in each image.
+                */
+               offset += ((fdt_totalsize(fit) + 3) & ~3);
+       }
+
+       if (external_data) {
+               debug("External Data\n");
+               ret = fit_image_get_data_size(fit, noffset, &len);
+               if (!ret) {
+                       *data = fit + offset;
+                       *size = len;
+               }
+       } else {
+               ret = fit_image_get_data(fit, noffset, data, size);
+       }
+
+       return ret;
+}
+
 /**
  * fit_image_hash_get_algo - get hash algorithm name
  * @fit: pointer to the FIT format image header
@@ -940,6 +1107,33 @@ static int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore)
        return 0;
 }
 
+/**
+ * fit_image_cipher_get_algo - get cipher algorithm name
+ * @fit: pointer to the FIT format image header
+ * @noffset: cipher node offset
+ * @algo: double pointer to char, will hold pointer to the algorithm name
+ *
+ * fit_image_cipher_get_algo() finds cipher algorithm property in a given
+ * cipher node. If the property is found its data start address is returned
+ * to the caller.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on failure
+ */
+int fit_image_cipher_get_algo(const void *fit, int noffset, char **algo)
+{
+       int len;
+
+       *algo = (char *)fdt_getprop(fit, noffset, FIT_ALGO_PROP, &len);
+       if (!*algo) {
+               fit_get_debug(fit, noffset, FIT_ALGO_PROP, len);
+               return -1;
+       }
+
+       return 0;
+}
+
 ulong fit_get_end(const void *fit)
 {
        return map_to_sysmem((void *)(fit + fdt_totalsize(fit)));
@@ -1068,36 +1262,16 @@ static int fit_image_check_hash(const void *fit, int noffset, const void *data,
        return 0;
 }
 
-/**
- * fit_image_verify - verify data integrity
- * @fit: pointer to the FIT format image header
- * @image_noffset: component image node offset
- *
- * fit_image_verify() goes over component image hash nodes,
- * re-calculates each data hash and compares with the value stored in hash
- * node.
- *
- * returns:
- *     1, if all hashes are valid
- *     0, otherwise (or on error)
- */
-int fit_image_verify(const void *fit, int image_noffset)
+int fit_image_verify_with_data(const void *fit, int image_noffset,
+                              const void *data, size_t size)
 {
-       const void      *data;
-       size_t          size;
        int             noffset = 0;
        char            *err_msg = "";
        int verify_all = 1;
        int ret;
 
-       /* Get image data and data length */
-       if (fit_image_get_data(fit, image_noffset, &data, &size)) {
-               err_msg = "Can't get image data/size";
-               goto error;
-       }
-
        /* Verify all required signatures */
-       if (IMAGE_ENABLE_VERIFY &&
+       if (FIT_IMAGE_ENABLE_VERIFY &&
            fit_image_verify_required_sigs(fit, image_noffset, data, size,
                                           gd_fdt_blob(), &verify_all)) {
                err_msg = "Unable to verify required signature";
@@ -1119,7 +1293,7 @@ int fit_image_verify(const void *fit, int image_noffset)
                                                 &err_msg))
                                goto error;
                        puts("+ ");
-               } else if (IMAGE_ENABLE_VERIFY && verify_all &&
+               } else if (FIT_IMAGE_ENABLE_VERIFY && verify_all &&
                                !strncmp(name, FIT_SIG_NODENAME,
                                        strlen(FIT_SIG_NODENAME))) {
                        ret = fit_image_check_sig(fit, noffset, data,
@@ -1152,6 +1326,38 @@ error:
        return 0;
 }
 
+/**
+ * fit_image_verify - verify data integrity
+ * @fit: pointer to the FIT format image header
+ * @image_noffset: component image node offset
+ *
+ * fit_image_verify() goes over component image hash nodes,
+ * re-calculates each data hash and compares with the value stored in hash
+ * node.
+ *
+ * returns:
+ *     1, if all hashes are valid
+ *     0, otherwise (or on error)
+ */
+int fit_image_verify(const void *fit, int image_noffset)
+{
+       const void      *data;
+       size_t          size;
+       int             noffset = 0;
+       char            *err_msg = "";
+
+       /* Get image data and data length */
+       if (fit_image_get_data_and_size(fit, image_noffset, &data, &size)) {
+               err_msg = "Can't get image data/size";
+               printf("error!\n%s for '%s' hash node in '%s' image node\n",
+                      err_msg, fit_get_name(fit, noffset, NULL),
+                      fit_get_name(fit, image_noffset, NULL));
+               return 0;
+       }
+
+       return fit_image_verify_with_data(fit, image_noffset, data, size);
+}
+
 /**
  * fit_all_image_verify - verify data integrity for all images
  * @fit: pointer to the FIT format image header
@@ -1202,6 +1408,32 @@ int fit_all_image_verify(const void *fit)
        return 1;
 }
 
+#ifdef CONFIG_FIT_CIPHER
+static int fit_image_uncipher(const void *fit, int image_noffset,
+                             void **data, size_t *size)
+{
+       int cipher_noffset, ret;
+       void *dst;
+       size_t size_dst;
+
+       cipher_noffset = fdt_subnode_offset(fit, image_noffset,
+                                           FIT_CIPHER_NODENAME);
+       if (cipher_noffset < 0)
+               return 0;
+
+       ret = fit_image_decrypt_data(fit, image_noffset, cipher_noffset,
+                                    *data, *size, &dst, &size_dst);
+       if (ret)
+               goto out;
+
+       *data = dst;
+       *size = size_dst;
+
+ out:
+       return ret;
+}
+#endif /* CONFIG_FIT_CIPHER */
+
 /**
  * fit_image_check_os - check whether image node is of a given os type
  * @fit: pointer to the FIT format image header
@@ -1371,6 +1603,10 @@ int fit_check_format(const void *fit)
  * compatible list, "foo,bar", matches a compatible string in the root of fdt1.
  * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1.
  *
+ * As an optimization, the compatible property from the FDT's root node can be
+ * copied into the configuration node in the FIT image. This is required to
+ * match configurations with compressed FDTs.
+ *
  * returns:
  *     offset to the configuration to use if one was found
  *     -1 otherwise
@@ -1403,48 +1639,62 @@ int fit_conf_find_compat(const void *fit, const void *fdt)
        for (noffset = fdt_next_node(fit, confs_noffset, &ndepth);
                        (noffset >= 0) && (ndepth > 0);
                        noffset = fdt_next_node(fit, noffset, &ndepth)) {
-               const void *kfdt;
+               const void *fdt;
                const char *kfdt_name;
-               int kfdt_noffset;
+               int kfdt_noffset, compat_noffset;
                const char *cur_fdt_compat;
                int len;
-               size_t size;
+               size_t sz;
                int i;
 
                if (ndepth > 1)
                        continue;
 
-               kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
-               if (!kfdt_name) {
-                       debug("No fdt property found.\n");
-                       continue;
-               }
-               kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
-                                                 kfdt_name);
-               if (kfdt_noffset < 0) {
-                       debug("No image node named \"%s\" found.\n",
-                             kfdt_name);
-                       continue;
-               }
-               /*
-                * Get a pointer to this configuration's fdt.
-                */
-               if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) {
-                       debug("Failed to get fdt \"%s\".\n", kfdt_name);
-                       continue;
+               /* If there's a compat property in the config node, use that. */
+               if (fdt_getprop(fit, noffset, "compatible", NULL)) {
+                       fdt = fit;                /* search in FIT image */
+                       compat_noffset = noffset; /* search under config node */
+               } else {        /* Otherwise extract it from the kernel FDT. */
+                       kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
+                       if (!kfdt_name) {
+                               debug("No fdt property found.\n");
+                               continue;
+                       }
+                       kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
+                                                         kfdt_name);
+                       if (kfdt_noffset < 0) {
+                               debug("No image node named \"%s\" found.\n",
+                                     kfdt_name);
+                               continue;
+                       }
+
+                       if (!fit_image_check_comp(fit, kfdt_noffset,
+                                                 IH_COMP_NONE)) {
+                               debug("Can't extract compat from \"%s\" "
+                                     "(compressed)\n", kfdt_name);
+                               continue;
+                       }
+
+                       /* search in this config's kernel FDT */
+                       if (fit_image_get_data(fit, kfdt_noffset, &fdt, &sz)) {
+                               debug("Failed to get fdt \"%s\".\n", kfdt_name);
+                               continue;
+                       }
+
+                       compat_noffset = 0;  /* search kFDT under root node */
                }
 
                len = fdt_compat_len;
                cur_fdt_compat = fdt_compat;
                /*
                 * Look for a match for each U-Boot compatibility string in
-                * turn in this configuration's fdt.
+                * turn in the compat string property.
                 */
                for (i = 0; len > 0 &&
                     (!best_match_offset || best_match_pos > i); i++) {
                        int cur_len = strlen(cur_fdt_compat) + 1;
 
-                       if (!fdt_node_check_compatible(kfdt, 0,
+                       if (!fdt_node_check_compatible(fdt, compat_noffset,
                                                       cur_fdt_compat)) {
                                best_match_offset = noffset;
                                best_match_pos = i;
@@ -1462,24 +1712,6 @@ int fit_conf_find_compat(const void *fit, const void *fdt)
        return best_match_offset;
 }
 
-/**
- * fit_conf_get_node - get node offset for configuration of a given unit name
- * @fit: pointer to the FIT format image header
- * @conf_uname: configuration node unit name
- *
- * fit_conf_get_node() finds a configuration (within the '/configurations'
- * parent node) of a provided unit name. If configuration is found its node
- * offset is returned to the caller.
- *
- * When NULL is provided in second argument fit_conf_get_node() will search
- * for a default configuration node instead. Default configuration node unit
- * name is retrieved from FIT_DEFAULT_PROP property of the '/configurations'
- * node.
- *
- * returns:
- *     configuration node offset when found (>=0)
- *     negative number on failure (FDT_ERR_* code)
- */
 int fit_conf_get_node(const void *fit, const char *conf_uname)
 {
        int noffset, confs_noffset;
@@ -1559,75 +1791,6 @@ int fit_conf_get_prop_node(const void *fit, int noffset,
        return fit_conf_get_prop_node_index(fit, noffset, prop_name, 0);
 }
 
-/**
- * fit_conf_print - prints out the FIT configuration details
- * @fit: pointer to the FIT format image header
- * @noffset: offset of the configuration node
- * @p: pointer to prefix string
- *
- * fit_conf_print() lists all mandatory properties for the processed
- * configuration node.
- *
- * returns:
- *     no returned results
- */
-void fit_conf_print(const void *fit, int noffset, const char *p)
-{
-       char *desc;
-       const char *uname;
-       int ret;
-       int fdt_index, loadables_index;
-
-       /* Mandatory properties */
-       ret = fit_get_desc(fit, noffset, &desc);
-       printf("%s  Description:  ", p);
-       if (ret)
-               printf("unavailable\n");
-       else
-               printf("%s\n", desc);
-
-       uname = fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
-       printf("%s  Kernel:       ", p);
-       if (uname == NULL)
-               printf("unavailable\n");
-       else
-               printf("%s\n", uname);
-
-       /* Optional properties */
-       uname = fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL);
-       if (uname)
-               printf("%s  Init Ramdisk: %s\n", p, uname);
-
-       for (fdt_index = 0;
-            uname = fdt_stringlist_get(fit, noffset, FIT_FDT_PROP,
-                                       fdt_index, NULL), uname;
-            fdt_index++) {
-
-               if (fdt_index == 0)
-                       printf("%s  FDT:          ", p);
-               else
-                       printf("%s                ", p);
-               printf("%s\n", uname);
-       }
-
-       uname = fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL);
-       if (uname)
-               printf("%s  FPGA:         %s\n", p, uname);
-
-       /* Print out all of the specified loadables */
-       for (loadables_index = 0;
-            uname = fdt_stringlist_get(fit, noffset, FIT_LOADABLE_PROP,
-                                       loadables_index, NULL), uname;
-            loadables_index++) {
-               if (loadables_index == 0) {
-                       printf("%s  Loadables:    ", p);
-               } else {
-                       printf("%s                ", p);
-               }
-               printf("%s\n", uname);
-       }
-}
-
 static int fit_image_select(const void *fit, int rd_noffset, int verify)
 {
        fit_image_print(fit, rd_noffset, "   ");
@@ -1697,6 +1860,8 @@ static const char *fit_get_image_type_property(int type)
                return FIT_LOADABLE_PROP;
        case IH_TYPE_FPGA:
                return FIT_FPGA_PROP;
+       case IH_TYPE_STANDALONE:
+               return FIT_STANDALONE_PROP;
        }
 
        return "unknown";
@@ -1712,11 +1877,12 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
        const char *fit_uname_config;
        const char *fit_base_uname_config;
        const void *fit;
-       const void *buf;
+       void *buf;
+       void *loadbuf;
        size_t size;
        int type_ok, os_ok;
-       ulong load, data, len;
-       uint8_t os;
+       ulong load, load_end, data, len;
+       uint8_t os, comp;
 #ifndef USE_HOSTCC
        uint8_t os_arch;
 #endif
@@ -1760,30 +1926,32 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
                                        BOOTSTAGE_SUB_NO_UNIT_NAME);
                        return -ENOENT;
                }
+
                fit_base_uname_config = fdt_get_name(fit, cfg_noffset, NULL);
                printf("   Using '%s' configuration\n", fit_base_uname_config);
-               if (image_type == IH_TYPE_KERNEL) {
-                       /* Remember (and possibly verify) this config */
+               /* Remember this config */
+               if (image_type == IH_TYPE_KERNEL)
                        images->fit_uname_cfg = fit_base_uname_config;
-                       if (IMAGE_ENABLE_VERIFY && images->verify) {
-                               puts("   Verifying Hash Integrity ... ");
-                               if (fit_config_verify(fit, cfg_noffset)) {
-                                       puts("Bad Data Hash\n");
-                                       bootstage_error(bootstage_id +
-                                               BOOTSTAGE_SUB_HASH);
-                                       return -EACCES;
-                               }
-                               puts("OK\n");
+
+               if (FIT_IMAGE_ENABLE_VERIFY && images->verify) {
+                       puts("   Verifying Hash Integrity ... ");
+                       if (fit_config_verify(fit, cfg_noffset)) {
+                               puts("Bad Data Hash\n");
+                               bootstage_error(bootstage_id +
+                                       BOOTSTAGE_SUB_HASH);
+                               return -EACCES;
                        }
-                       bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG);
+                       puts("OK\n");
                }
 
+               bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG);
+
                noffset = fit_conf_get_prop_node(fit, cfg_noffset,
                                                 prop_name);
                fit_uname = fit_get_name(fit, noffset, NULL);
        }
        if (noffset < 0) {
-               puts("Could not find subimage node\n");
+               printf("Could not find subimage node type '%s'\n", prop_name);
                bootstage_error(bootstage_id + BOOTSTAGE_SUB_SUBNODE);
                return -ENOENT;
        }
@@ -1810,12 +1978,6 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
        images->os.arch = os_arch;
 #endif
 
-       if (image_type == IH_TYPE_FLATDT &&
-           !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) {
-               puts("FDT image is compressed");
-               return -EPROTONOSUPPORT;
-       }
-
        bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
        type_ok = fit_image_check_type(fit, noffset, image_type) ||
                  fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE) ||
@@ -1826,7 +1988,9 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
                image_type == IH_TYPE_FPGA ||
                fit_image_check_os(fit, noffset, IH_OS_LINUX) ||
                fit_image_check_os(fit, noffset, IH_OS_U_BOOT) ||
-               fit_image_check_os(fit, noffset, IH_OS_OPENRTOS);
+               fit_image_check_os(fit, noffset, IH_OS_OPENRTOS) ||
+               fit_image_check_os(fit, noffset, IH_OS_EFI) ||
+               fit_image_check_os(fit, noffset, IH_OS_VXWORKS);
 
        /*
         * If either of the checks fail, we should report an error, but
@@ -1846,38 +2010,36 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
        bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK);
 
        /* get image data address and length */
-       if (fit_image_get_data(fit, noffset, &buf, &size)) {
+       if (fit_image_get_data_and_size(fit, noffset,
+                                       (const void **)&buf, &size)) {
                printf("Could not find %s subimage data!\n", prop_name);
                bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA);
                return -ENOENT;
        }
 
+#ifdef CONFIG_FIT_CIPHER
+       /* Decrypt data before uncompress/move */
+       if (IMAGE_ENABLE_DECRYPT) {
+               puts("   Decrypting Data ... ");
+               if (fit_image_uncipher(fit, noffset, &buf, &size)) {
+                       puts("Error\n");
+                       return -EACCES;
+               }
+               puts("OK\n");
+       }
+#endif
+
 #if !defined(USE_HOSTCC) && defined(CONFIG_FIT_IMAGE_POST_PROCESS)
        /* perform any post-processing on the image data */
-       board_fit_image_post_process((void **)&buf, &size);
+       board_fit_image_post_process(&buf, &size);
 #endif
 
        len = (ulong)size;
 
-       /* verify that image data is a proper FDT blob */
-       if (image_type == IH_TYPE_FLATDT && fdt_check_header(buf)) {
-               puts("Subimage data is not a FDT");
-               return -ENOEXEC;
-       }
-
        bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK);
 
-       /*
-        * Work-around for eldk-4.2 which gives this warning if we try to
-        * cast in the unmap_sysmem() call:
-        * warning: initialization discards qualifiers from pointer target type
-        */
-       {
-               void *vbuf = (void *)buf;
-
-               data = map_to_sysmem(vbuf);
-       }
-
+       data = map_to_sysmem(buf);
+       load = data;
        if (load_op == FIT_LOAD_IGNORED) {
                /* Don't load */
        } else if (fit_image_get_load(fit, noffset, &load)) {
@@ -1889,8 +2051,6 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
                }
        } else if (load_op != FIT_LOAD_OPTIONAL_NON_ZERO || load) {
                ulong image_start, image_end;
-               ulong load_end;
-               void *dst;
 
                /*
                 * move image data to the load address,
@@ -1908,14 +2068,50 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
 
                printf("   Loading %s from 0x%08lx to 0x%08lx\n",
                       prop_name, data, load);
+       } else {
+               load = data;    /* No load address specified */
+       }
+
+       comp = IH_COMP_NONE;
+       loadbuf = buf;
+       /* Kernel images get decompressed later in bootm_load_os(). */
+       if (!fit_image_get_comp(fit, noffset, &comp) &&
+           comp != IH_COMP_NONE &&
+           !(image_type == IH_TYPE_KERNEL ||
+             image_type == IH_TYPE_KERNEL_NOLOAD ||
+             image_type == IH_TYPE_RAMDISK)) {
+               ulong max_decomp_len = len * 20;
+               if (load == data) {
+                       loadbuf = malloc(max_decomp_len);
+                       load = map_to_sysmem(loadbuf);
+               } else {
+                       loadbuf = map_sysmem(load, max_decomp_len);
+               }
+               if (image_decomp(comp, load, data, image_type,
+                               loadbuf, buf, len, max_decomp_len, &load_end)) {
+                       printf("Error decompressing %s\n", prop_name);
+
+                       return -ENOEXEC;
+               }
+               len = load_end - load;
+       } else if (load != data) {
+               loadbuf = map_sysmem(load, len);
+               memcpy(loadbuf, buf, len);
+       }
+
+       if (image_type == IH_TYPE_RAMDISK && comp != IH_COMP_NONE)
+               puts("WARNING: 'compression' nodes for ramdisks are deprecated,"
+                    " please fix your .its file!\n");
 
-               dst = map_sysmem(load, len);
-               memmove(dst, buf, len);
-               data = load;
+       /* verify that image data is a proper FDT blob */
+       if (image_type == IH_TYPE_FLATDT && fdt_check_header(loadbuf)) {
+               puts("Subimage data is not a FDT");
+               return -ENOEXEC;
        }
+
        bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD);
 
-       *datap = data;
+       *datap = load;
        *lenp = len;
        if (fit_unamep)
                *fit_unamep = (char *)fit_uname;
@@ -2033,6 +2229,18 @@ int boot_get_fdt_fit(bootm_headers_t *images, ulong addr,
                        if (next_config)
                                *next_config++ = '\0';
                        uname = NULL;
+
+                       /*
+                        * fit_image_load() would load the first FDT from the
+                        * extra config only when uconfig is specified.
+                        * Check if the extra config contains multiple FDTs and
+                        * if so, load them.
+                        */
+                       cfg_noffset = fit_conf_get_node(fit, uconfig);
+
+                       i = 0;
+                       count = fit_conf_get_prop_node_count(fit, cfg_noffset,
+                                                            FIT_FDT_PROP);
                }
 
                debug("%d: using uname=%s uconfig=%s\n", i, uname, uconfig);