]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/image-fit.c
spl: move comment to the right place
[karo-tx-uboot.git] / common / image-fit.c
index de6fce629ac62e27e1192d50302b5e45c6f22af3..a272ea2e83456d9a50018ffb1752b0e2016ddcf7 100644 (file)
@@ -6,23 +6,7 @@
  * (C) Copyright 2000-2006
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #ifdef USE_HOSTCC
 #include <time.h>
 #else
 #include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+DECLARE_GLOBAL_DATA_PTR;
 #endif /* !USE_HOSTCC*/
 
 #include <bootstage.h>
-#include <sha1.h>
 #include <u-boot/crc.h>
 #include <u-boot/md5.h>
+#include <u-boot/sha1.h>
+#include <u-boot/sha256.h>
 
 /*****************************************************************************/
 /* New uImage format routines */
@@ -71,7 +59,7 @@ static int fit_parse_spec(const char *spec, char sepc, ulong addr_curr,
  * @conf_name double pointer to a char, will hold pointer to a configuration
  * unit name
  *
- * fit_parse_conf() expects configuration spec in the for of [<addr>]#<conf>,
+ * fit_parse_conf() expects configuration spec in the form of [<addr>]#<conf>,
  * where <addr> is a FIT image address that contains configuration
  * with a <conf> unit name.
  *
@@ -97,7 +85,7 @@ int fit_parse_conf(const char *spec, ulong addr_curr,
  * subimage
  * @image_name: double pointer to a char, will hold pointer to a subimage name
  *
- * fit_parse_subimage() expects subimage spec in the for of
+ * fit_parse_subimage() expects subimage spec in the form of
  * [<addr>]:<subimage>, where <addr> is a FIT image address that contains
  * subimage with a <subimg> unit name.
  *
@@ -124,6 +112,7 @@ static void fit_get_debug(const void *fit, int noffset,
              fdt_strerror(err));
 }
 
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_FIT_SPL_PRINT)
 /**
  * fit_print_contents - prints out the contents of the FIT format image
  * @fit: pointer to the FIT format image header
@@ -149,11 +138,8 @@ void fit_print_contents(const void *fit)
        const char *p;
        time_t timestamp;
 
-#ifdef USE_HOSTCC
-       p = "";
-#else
-       p = "   ";
-#endif
+       /* Indent string is defined in header image.h */
+       p = IMAGE_INDENT_STRING;
 
        /* Root node properties */
        ret = fit_get_desc(fit, 0, &desc);
@@ -228,6 +214,102 @@ void fit_print_contents(const void *fit)
        }
 }
 
+/**
+ * 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 properies 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 properies 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_image_print - prints out the FIT component image details
  * @fit: pointer to the FIT format image header
@@ -262,6 +344,17 @@ void fit_image_print(const void *fit, int image_noffset, const char *p)
        else
                printf("%s\n", desc);
 
+       if (IMAGE_ENABLE_TIMESTAMP) {
+               time_t timestamp;
+
+               ret = fit_get_timestamp(fit, 0, &timestamp);
+               printf("%s  Created:      ", p);
+               if (ret)
+                       printf("unavailable\n");
+               else
+                       genimg_print_time(timestamp);
+       }
+
        fit_image_get_type(fit, image_noffset, &type);
        printf("%s  Type:         %s\n", p, genimg_get_type_name(type));
 
@@ -272,10 +365,13 @@ void fit_image_print(const void *fit, int image_noffset, const char *p)
 
 #ifndef USE_HOSTCC
        printf("%s  Data Start:   ", p);
-       if (ret)
+       if (ret) {
                printf("unavailable\n");
-       else
-               printf("0x%08lx\n", (ulong)data);
+       } else {
+               void *vdata = (void *)data;
+
+               printf("0x%08lx\n", (ulong)map_to_sysmem(vdata));
+       }
 #endif
 
        printf("%s  Data Size:    ", p);
@@ -323,61 +419,11 @@ void fit_image_print(const void *fit, int image_noffset, const char *p)
             noffset = fdt_next_node(fit, noffset, &ndepth)) {
                if (ndepth == 1) {
                        /* Direct child node of the component image node */
-                       fit_image_print_hash(fit, noffset, p);
+                       fit_image_print_verification_data(fit, noffset, p);
                }
        }
 }
-
-/**
- * fit_image_print_hash - 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
- *
- * fit_image_print_hash() lists properies for the processed hash node
- *
- * returns:
- *     no returned results
- */
-void fit_image_print_hash(const void *fit, int noffset, const char *p)
-{
-       char *algo;
-       uint8_t *value;
-       int value_len;
-       int i, ret;
-
-       /*
-        * Check subnode name, must be equal to "hash".
-        * Multiple hash nodes require unique unit node
-        * names, e.g. hash@1, hash@2, etc.
-        */
-       if (strncmp(fit_get_name(fit, noffset, NULL),
-                   FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME)) != 0)
-               return;
-
-       debug("%s  Hash node:    '%s'\n", p,
-             fit_get_name(fit, noffset, NULL));
-
-       printf("%s  Hash algo:    ", p);
-       if (fit_image_hash_get_algo(fit, noffset, &algo)) {
-               printf("invalid/unsupported\n");
-               return;
-       }
-       printf("%s\n", algo);
-
-       ret = fit_image_hash_get_value(fit, noffset, &value,
-                                       &value_len);
-       printf("%s  Hash value:   ", p);
-       if (ret) {
-               printf("unavailable\n");
-       } else {
-               for (i = 0; i < value_len; i++)
-                       printf("%02x", value[i]);
-               printf("\n");
-       }
-
-       debug("%s  Hash len:     %d\n", p, value_len);
-}
+#endif
 
 /**
  * fit_get_desc - get node description property
@@ -787,7 +833,7 @@ static int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore)
  *
  * returns:
  *     0, on success
- *     -1, on property read failure
+ *     -ENOSPC if no space in device tree, -1 for other error
  */
 int fit_set_timestamp(void *fit, int noffset, time_t timestamp)
 {
@@ -801,7 +847,7 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp)
                printf("Can't set '%s' property for '%s' node (%s)\n",
                       FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL),
                       fdt_strerror(ret));
-               return -1;
+               return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -1;
        }
 
        return 0;
@@ -828,16 +874,20 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp)
 int calculate_hash(const void *data, int data_len, const char *algo,
                        uint8_t *value, int *value_len)
 {
-       if (strcmp(algo, "crc32") == 0) {
+       if (IMAGE_ENABLE_CRC32 && strcmp(algo, "crc32") == 0) {
                *((uint32_t *)value) = crc32_wd(0, data, data_len,
                                                        CHUNKSZ_CRC32);
                *((uint32_t *)value) = cpu_to_uimage(*((uint32_t *)value));
                *value_len = 4;
-       } else if (strcmp(algo, "sha1") == 0) {
+       } else if (IMAGE_ENABLE_SHA1 && strcmp(algo, "sha1") == 0) {
                sha1_csum_wd((unsigned char *)data, data_len,
                             (unsigned char *)value, CHUNKSZ_SHA1);
                *value_len = 20;
-       } else if (strcmp(algo, "md5") == 0) {
+       } else if (IMAGE_ENABLE_SHA256 && strcmp(algo, "sha256") == 0) {
+               sha256_csum_wd((unsigned char *)data, data_len,
+                              (unsigned char *)value, CHUNKSZ_SHA256);
+               *value_len = SHA256_SUM_LEN;
+       } else if (IMAGE_ENABLE_MD5 && strcmp(algo, "md5") == 0) {
                md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5);
                *value_len = 16;
        } else {
@@ -912,13 +962,23 @@ int fit_image_verify(const void *fit, int image_noffset)
 {
        const void      *data;
        size_t          size;
-       int             noffset;
+       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";
-               return 0;
+               goto error;
+       }
+
+       /* Verify all required signatures */
+       if (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";
+               goto error;
        }
 
        /* Process all hash subnodes of the component image node */
@@ -938,6 +998,15 @@ int fit_image_verify(const void *fit, int image_noffset)
                                                 &err_msg))
                                goto error;
                        puts("+ ");
+               } else if (IMAGE_ENABLE_VERIFY && verify_all &&
+                               !strncmp(name, FIT_SIG_NODENAME,
+                                       strlen(FIT_SIG_NODENAME))) {
+                       ret = fit_image_check_sig(fit, noffset, data,
+                                                       size, -1, &err_msg);
+                       if (ret)
+                               puts("- ");
+                       else
+                               puts("+ ");
                }
        }
 
@@ -1267,7 +1336,7 @@ int fit_conf_find_compat(const void *fit, const void *fdt)
  *
  * 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 retrived from FIT_DEFAULT_PROP property of the '/configurations'
+ * name is retrieved from FIT_DEFAULT_PROP property of the '/configurations'
  * node.
  *
  * returns:
@@ -1322,63 +1391,6 @@ int fit_conf_get_prop_node(const void *fit, int noffset,
        return fit_image_get_node(fit, uname);
 }
 
-/**
- * fit_conf_get_kernel_node - get kernel image node offset that corresponds to
- * a given configuration
- * @fit: pointer to the FIT format image header
- * @noffset: configuration node offset
- *
- * fit_conf_get_kernel_node() retrives kernel image node unit name from
- * configuration FIT_KERNEL_PROP property and translates it to the node
- * offset.
- *
- * returns:
- *     image node offset when found (>=0)
- *     negative number on failure (FDT_ERR_* code)
- */
-int fit_conf_get_kernel_node(const void *fit, int noffset)
-{
-       return fit_conf_get_prop_node(fit, noffset, FIT_KERNEL_PROP);
-}
-
-/**
- * fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to
- * a given configuration
- * @fit: pointer to the FIT format image header
- * @noffset: configuration node offset
- *
- * fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from
- * configuration FIT_KERNEL_PROP property and translates it to the node
- * offset.
- *
- * returns:
- *     image node offset when found (>=0)
- *     negative number on failure (FDT_ERR_* code)
- */
-int fit_conf_get_ramdisk_node(const void *fit, int noffset)
-{
-       return fit_conf_get_prop_node(fit, noffset, FIT_RAMDISK_PROP);
-}
-
-/**
- * fit_conf_get_fdt_node - get fdt image node offset that corresponds to
- * a given configuration
- * @fit: pointer to the FIT format image header
- * @noffset: configuration node offset
- *
- * fit_conf_get_fdt_node() retrives fdt image node unit name from
- * configuration FIT_KERNEL_PROP property and translates it to the node
- * offset.
- *
- * returns:
- *     image node offset when found (>=0)
- *     negative number on failure (FDT_ERR_* code)
- */
-int fit_conf_get_fdt_node(const void *fit, int noffset)
-{
-       return fit_conf_get_prop_node(fit, noffset, FIT_FDT_PROP);
-}
-
 /**
  * fit_conf_print - prints out the FIT configuration details
  * @fit: pointer to the FIT format image header
@@ -1422,23 +1434,7 @@ void fit_conf_print(const void *fit, int noffset, const char *p)
                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
-int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch,
-                       int verify)
+static int fit_image_select(const void *fit, int rd_noffset, int verify)
 {
        fit_image_print(fit, rd_noffset, "   ");
 
@@ -1446,23 +1442,276 @@ int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch,
                puts("   Verifying Hash Integrity ... ");
                if (!fit_image_verify(fit, rd_noffset)) {
                        puts("Bad Data Hash\n");
-                       bootstage_error(BOOTSTAGE_ID_FIT_RD_HASH);
-                       return 0;
+                       return -EACCES;
                }
                puts("OK\n");
        }
 
-       bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL);
-       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));
-               bootstage_error(BOOTSTAGE_ID_FIT_RD_CHECK_ALL);
-               return 0;
+       return 0;
+}
+
+int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name,
+                       ulong addr)
+{
+       int cfg_noffset;
+       void *fit_hdr;
+       int noffset;
+
+       debug("*  %s: using config '%s' from image at 0x%08lx\n",
+             prop_name, images->fit_uname_cfg, addr);
+
+       /* Check whether configuration has this property defined */
+       fit_hdr = map_sysmem(addr, 0);
+       cfg_noffset = fit_conf_get_node(fit_hdr, images->fit_uname_cfg);
+       if (cfg_noffset < 0) {
+               debug("*  %s: no such config\n", prop_name);
+               return -ENOENT;
        }
 
-       bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK);
-       return 1;
+       noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name);
+       if (noffset < 0) {
+               debug("*  %s: no '%s' in config\n", prop_name, prop_name);
+               return -ENOLINK;
+       }
+
+       return noffset;
+}
+
+/**
+ * fit_get_image_type_property() - get property name for IH_TYPE_...
+ *
+ * @return the properly name where we expect to find the image in the
+ * config node
+ */
+static const char *fit_get_image_type_property(int type)
+{
+       /*
+        * This is sort-of available in the uimage_type[] table in image.c
+        * but we don't have access to the sohrt name, and "fdt" is different
+        * anyway. So let's just keep it here.
+        */
+       switch (type) {
+       case IH_TYPE_FLATDT:
+               return FIT_FDT_PROP;
+       case IH_TYPE_KERNEL:
+               return FIT_KERNEL_PROP;
+       case IH_TYPE_RAMDISK:
+               return FIT_RAMDISK_PROP;
+       case IH_TYPE_X86_SETUP:
+               return FIT_SETUP_PROP;
+       }
+
+       return "unknown";
+}
+
+int fit_image_load(bootm_headers_t *images, ulong addr,
+                  const char **fit_unamep, const char **fit_uname_configp,
+                  int arch, int image_type, int bootstage_id,
+                  enum fit_load_op load_op, ulong *datap, ulong *lenp)
+{
+       int cfg_noffset, noffset;
+       const char *fit_uname;
+       const char *fit_uname_config;
+       const void *fit;
+       const void *buf;
+       size_t size;
+       int type_ok, os_ok;
+       ulong load, data, len;
+       const char *prop_name;
+       int ret;
+
+       fit = map_sysmem(addr, 0);
+       fit_uname = fit_unamep ? *fit_unamep : NULL;
+       fit_uname_config = fit_uname_configp ? *fit_uname_configp : NULL;
+       prop_name = fit_get_image_type_property(image_type);
+       printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr);
+
+       bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT);
+       if (!fit_check_format(fit)) {
+               printf("Bad FIT %s image format!\n", prop_name);
+               bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT);
+               return -ENOEXEC;
+       }
+       bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK);
+       if (fit_uname) {
+               /* get FIT component image node offset */
+               bootstage_mark(bootstage_id + BOOTSTAGE_SUB_UNIT_NAME);
+               noffset = fit_image_get_node(fit, fit_uname);
+       } else {
+               /*
+                * no 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
+                */
+               bootstage_mark(bootstage_id + BOOTSTAGE_SUB_NO_UNIT_NAME);
+               if (IMAGE_ENABLE_BEST_MATCH && !fit_uname_config) {
+                       cfg_noffset = fit_conf_find_compat(fit, gd_fdt_blob());
+               } else {
+                       cfg_noffset = fit_conf_get_node(fit,
+                                                       fit_uname_config);
+               }
+               if (cfg_noffset < 0) {
+                       puts("Could not find configuration node\n");
+                       bootstage_error(bootstage_id +
+                                       BOOTSTAGE_SUB_NO_UNIT_NAME);
+                       return -ENOENT;
+               }
+               fit_uname_config = fdt_get_name(fit, cfg_noffset, NULL);
+               printf("   Using '%s' configuration\n", fit_uname_config);
+               if (image_type == IH_TYPE_KERNEL) {
+                       /* Remember (and possibly verify) this config */
+                       images->fit_uname_cfg = fit_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");
+                       }
+                       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");
+               bootstage_error(bootstage_id + BOOTSTAGE_SUB_SUBNODE);
+               return -ENOENT;
+       }
+
+       printf("   Trying '%s' %s subimage\n", fit_uname, prop_name);
+
+       ret = fit_image_select(fit, noffset, images->verify);
+       if (ret) {
+               bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH);
+               return ret;
+       }
+
+       bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
+#if !defined(USE_HOSTCC) && !defined(CONFIG_SANDBOX)
+       if (!fit_image_check_target_arch(fit, noffset)) {
+               puts("Unsupported Architecture\n");
+               bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
+               return -ENOEXEC;
+       }
+#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) ||
+               (image_type == IH_TYPE_KERNEL &&
+                       fit_image_check_type(fit, noffset,
+                                            IH_TYPE_KERNEL_NOLOAD));
+       os_ok = image_type == IH_TYPE_FLATDT ||
+               fit_image_check_os(fit, noffset, IH_OS_LINUX);
+       if (!type_ok || !os_ok) {
+               printf("No Linux %s %s Image\n", genimg_get_arch_name(arch),
+                      genimg_get_type_name(image_type));
+               bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
+               return -EIO;
+       }
+
+       bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK);
+
+       /* get image data address and length */
+       if (fit_image_get_data(fit, noffset, &buf, &size)) {
+               printf("Could not find %s subimage data!\n", prop_name);
+               bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA);
+               return -ENOENT;
+       }
+       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);
+       }
+
+       if (load_op == FIT_LOAD_IGNORED) {
+               /* Don't load */
+       } else if (fit_image_get_load(fit, noffset, &load)) {
+               if (load_op == FIT_LOAD_REQUIRED) {
+                       printf("Can't get %s subimage load address!\n",
+                              prop_name);
+                       bootstage_error(bootstage_id + BOOTSTAGE_SUB_LOAD);
+                       return -EBADF;
+               }
+       } 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,
+                * make sure we don't overwrite initial image
+                */
+               image_start = addr;
+               image_end = addr + fit_get_size(fit);
+
+               load_end = load + len;
+               if (image_type != IH_TYPE_KERNEL &&
+                   load < image_end && load_end > image_start) {
+                       printf("Error: %s overwritten\n", prop_name);
+                       return -EXDEV;
+               }
+
+               printf("   Loading %s from 0x%08lx to 0x%08lx\n",
+                      prop_name, data, load);
+
+               dst = map_sysmem(load, len);
+               memmove(dst, buf, len);
+               data = load;
+       }
+       bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD);
+
+       *datap = data;
+       *lenp = len;
+       if (fit_unamep)
+               *fit_unamep = (char *)fit_uname;
+       if (fit_uname_configp)
+               *fit_uname_configp = (char *)fit_uname_config;
+
+       return noffset;
+}
+
+int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch,
+                       ulong *setup_start, ulong *setup_len)
+{
+       int noffset;
+       ulong addr;
+       ulong len;
+       int ret;
+
+       addr = map_to_sysmem(images->fit_hdr_os);
+       noffset = fit_get_node_from_config(images, FIT_SETUP_PROP, addr);
+       if (noffset < 0)
+               return noffset;
+
+       ret = fit_image_load(images, addr, NULL, NULL, arch,
+                            IH_TYPE_X86_SETUP, BOOTSTAGE_ID_FIT_SETUP_START,
+                            FIT_LOAD_REQUIRED, setup_start, &len);
+
+       return ret;
 }
-#endif /* USE_HOSTCC */