X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=common%2Fimage-fit.c;h=7f17fd1410ed8a3b37e48f33f7ddf14dd4b54f65;hb=fe12386c2aa586e29f32b7b3ee4c621af8c56679;hp=4eb4d42655e9bebb0fae767d89961327a100e0c8;hpb=0eb25b619699270a8af95c2f76791fd6c4b52972;p=u-boot diff --git a/common/image-fit.c b/common/image-fit.c index 4eb4d42655..7f17fd1410 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -11,16 +11,19 @@ #ifdef USE_HOSTCC #include "mkimage.h" -#include #include #else +#include +#include #include #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ +#include #include #include #include @@ -147,7 +150,7 @@ int fit_get_subimage_count(const void *fit, int images_noffset) * @p: pointer to prefix string * * fit_print_contents() formats a multi line FIT image contents description. - * The routine prints out FIT image properties (root node level) follwed by + * The routine prints out FIT image properties (root node level) followed by * the details of each component image. * * returns: @@ -249,7 +252,7 @@ void fit_print_contents(const void *fit) * @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 + * 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. @@ -314,7 +317,7 @@ static void fit_image_print_data(const void *fit, int noffset, const char *p, * @noffset: offset of the hash or signature node * @p: pointer to prefix string * - * This lists properies for the processed hash node + * This lists properties for the processed hash node * * returns: * no returned results @@ -344,7 +347,7 @@ static void fit_image_print_verification_data(const void *fit, int noffset, * @image_noffset: offset of the component image node * @p: pointer to prefix string * - * fit_image_print() lists all mandatory properies for the processed component + * fit_image_print() lists all mandatory properties for the processed component * image. If present, hash nodes are printed out as well. Load * address for images of type firmware is also printed out. Since the load * address is not mandatory for firmware images, it will be output as @@ -422,7 +425,8 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) } if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || - (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK)) { + (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK) || + (type == IH_TYPE_FPGA)) { ret = fit_image_get_load(fit, image_noffset, &load); printf("%s Load Address: ", p); if (ret) @@ -431,9 +435,13 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) printf("0x%08lx\n", load); } + /* optional load address for FDT */ + if (type == IH_TYPE_FLATDT && !fit_image_get_load(fit, image_noffset, &load)) + printf("%s Load Address: 0x%08lx\n", p, load); + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || (type == IH_TYPE_RAMDISK)) { - fit_image_get_entry(fit, image_noffset, &entry); + ret = fit_image_get_entry(fit, image_noffset, &entry); printf("%s Entry Point: ", p); if (ret) printf("unavailable\n"); @@ -458,10 +466,10 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) * fit_get_desc - get node description property * @fit: pointer to the FIT format image header * @noffset: node offset - * @desc: double pointer to the char, will hold pointer to the descrption + * @desc: double pointer to the char, will hold pointer to the description * * fit_get_desc() reads description property from a given node, if - * description is found pointer to it is returened in third call argument. + * description is found pointer to it is returned in third call argument. * * returns: * 0, on success @@ -486,8 +494,8 @@ int fit_get_desc(const void *fit, int noffset, char **desc) * @noffset: node offset * @timestamp: pointer to the time_t, will hold read timestamp * - * fit_get_timestamp() reads timestamp poperty from given node, if timestamp - * is found and has a correct size its value is retured in third call + * fit_get_timestamp() reads timestamp property from given node, if timestamp + * is found and has a correct size its value is returned in third call * argument. * * returns: @@ -519,7 +527,7 @@ int fit_get_timestamp(const void *fit, int noffset, time_t *timestamp) * @fit: pointer to the FIT format image header * @image_uname: component image node unit name * - * fit_image_get_node() finds a component image (withing the '/images' + * fit_image_get_node() finds a component image (within the '/images' * node) of a provided unit name. If image is found its node offset is * returned to the caller. * @@ -675,6 +683,34 @@ int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp) return 0; } +static int fit_image_get_address(const void *fit, int noffset, char *name, + ulong *load) +{ + int len, cell_len; + const fdt32_t *cell; + uint64_t load64 = 0; + + cell = fdt_getprop(fit, noffset, name, &len); + if (cell == NULL) { + fit_get_debug(fit, noffset, name, len); + return -1; + } + + if (len > sizeof(ulong)) { + printf("Unsupported %s address size\n", name); + return -1; + } + + cell_len = len >> 2; + /* Use load64 to avoid compiling warning for 32-bit target */ + while (cell_len--) { + load64 = (load64 << 32) | uimage_to_cpu(*cell); + cell++; + } + *load = (ulong)load64; + + return 0; +} /** * fit_image_get_load() - get load addr property for given component image node * @fit: pointer to the FIT format image header @@ -690,17 +726,7 @@ int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp) */ int fit_image_get_load(const void *fit, int noffset, ulong *load) { - int len; - const uint32_t *data; - - data = fdt_getprop(fit, noffset, FIT_LOAD_PROP, &len); - if (data == NULL) { - fit_get_debug(fit, noffset, FIT_LOAD_PROP, len); - return -1; - } - - *load = uimage_to_cpu(*data); - return 0; + return fit_image_get_address(fit, noffset, FIT_LOAD_PROP, load); } /** @@ -722,17 +748,7 @@ int fit_image_get_load(const void *fit, int noffset, ulong *load) */ int fit_image_get_entry(const void *fit, int noffset, ulong *entry) { - int len; - const uint32_t *data; - - data = fdt_getprop(fit, noffset, FIT_ENTRY_PROP, &len); - if (data == NULL) { - fit_get_debug(fit, noffset, FIT_ENTRY_PROP, len); - return -1; - } - - *entry = uimage_to_cpu(*data); - return 0; + return fit_image_get_address(fit, noffset, FIT_ENTRY_PROP, entry); } /** @@ -766,6 +782,54 @@ int fit_image_get_data(const void *fit, int noffset, return 0; } +/** + * Get 'data-offset' property from a given image node. + * + * @fit: pointer to the FIT image header + * @noffset: component image node offset + * @data_offset: holds the data-offset property + * + * returns: + * 0, on success + * -ENOENT if the property could not be found + */ +int fit_image_get_data_offset(const void *fit, int noffset, int *data_offset) +{ + const fdt32_t *val; + + val = fdt_getprop(fit, noffset, FIT_DATA_OFFSET_PROP, NULL); + if (!val) + return -ENOENT; + + *data_offset = fdt32_to_cpu(*val); + + return 0; +} + +/** + * Get 'data-size' 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(const void *fit, int noffset, int *data_size) +{ + const fdt32_t *val; + + val = fdt_getprop(fit, noffset, FIT_DATA_SIZE_PROP, NULL); + if (!val) + return -ENOENT; + + *data_size = fdt32_to_cpu(*val); + + return 0; +} + /** * fit_image_hash_get_algo - get hash algorithm name * @fit: pointer to the FIT format image header @@ -851,6 +915,11 @@ static int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore) return 0; } +ulong fit_get_end(const void *fit) +{ + return map_to_sysmem((void *)(fit + fdt_totalsize(fit))); +} + /** * fit_set_timestamp - set node timestamp property * @fit: pointer to the FIT format image header @@ -873,9 +942,9 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp) ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t, sizeof(uint32_t)); if (ret) { - printf("Can't set '%s' property for '%s' node (%s)\n", - FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL), - fdt_strerror(ret)); + debug("Can't set '%s' property for '%s' node (%s)\n", + FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL), + fdt_strerror(ret)); return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -1; } @@ -975,7 +1044,7 @@ static int fit_image_check_hash(const void *fit, int noffset, const void *data, } /** - * fit_image_verify - verify data intergity + * fit_image_verify - verify data integrity * @fit: pointer to the FIT format image header * @image_noffset: component image node offset * @@ -1011,7 +1080,7 @@ int fit_image_verify(const void *fit, int image_noffset) } /* Process all hash subnodes of the component image node */ - fdt_for_each_subnode(fit, noffset, image_noffset) { + fdt_for_each_subnode(noffset, fit, image_noffset) { const char *name = fit_get_name(fit, noffset, NULL); /* @@ -1030,6 +1099,13 @@ int fit_image_verify(const void *fit, int image_noffset) strlen(FIT_SIG_NODENAME))) { ret = fit_image_check_sig(fit, noffset, data, size, -1, &err_msg); + + /* + * Show an indication on failure, but do not return + * an error. Only keys marked 'required' can cause + * an image validation failure. See the call to + * fit_image_verify_required_sigs() above. + */ if (ret) puts("- "); else @@ -1052,7 +1128,7 @@ error: } /** - * fit_all_image_verify - verify data intergity for all images + * fit_all_image_verify - verify data integrity for all images * @fit: pointer to the FIT format image header * * fit_all_image_verify() goes over all images in the FIT and @@ -1089,8 +1165,9 @@ int fit_all_image_verify(const void *fit) * Direct child node of the images parent node, * i.e. component image node. */ - printf(" Hash(es) for Image %u (%s): ", count++, + printf(" Hash(es) for Image %u (%s): ", count, fit_get_name(fit, noffset, NULL)); + count++; if (!fit_image_verify(fit, noffset)) return 0; @@ -1138,11 +1215,18 @@ int fit_image_check_os(const void *fit, int noffset, uint8_t os) int fit_image_check_arch(const void *fit, int noffset, uint8_t arch) { uint8_t image_arch; + int aarch32_support = 0; + +#ifdef CONFIG_ARM64_SUPPORT_AARCH32 + aarch32_support = 1; +#endif if (fit_image_get_arch(fit, noffset, &image_arch)) return 0; return (arch == image_arch) || - (arch == IH_ARCH_I386 && image_arch == IH_ARCH_X86_64); + (arch == IH_ARCH_I386 && image_arch == IH_ARCH_X86_64) || + (arch == IH_ARCH_ARM64 && image_arch == IH_ARCH_ARM && + aarch32_support); } /** @@ -1358,8 +1442,8 @@ int fit_conf_find_compat(const void *fit, const void *fdt) * @fit: pointer to the FIT format image header * @conf_uname: configuration node unit name * - * fit_conf_get_node() finds a configuration (withing the '/configurations' - * parant node) of a provided unit name. If configuration is found its node + * 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 @@ -1375,6 +1459,8 @@ int fit_conf_get_node(const void *fit, const char *conf_uname) { int noffset, confs_noffset; int len; + const char *s; + char *conf_uname_copy = NULL; confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); if (confs_noffset < 0) { @@ -1396,36 +1482,65 @@ int fit_conf_get_node(const void *fit, const char *conf_uname) debug("Found default configuration: '%s'\n", conf_uname); } + s = strchr(conf_uname, '#'); + if (s) { + len = s - conf_uname; + conf_uname_copy = malloc(len + 1); + if (!conf_uname_copy) { + debug("Can't allocate uname copy: '%s'\n", + conf_uname); + return -ENOMEM; + } + memcpy(conf_uname_copy, conf_uname, len); + conf_uname_copy[len] = '\0'; + conf_uname = conf_uname_copy; + } + noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname); if (noffset < 0) { debug("Can't get node offset for configuration unit name: '%s' (%s)\n", conf_uname, fdt_strerror(noffset)); } + if (conf_uname_copy) + free(conf_uname_copy); + return noffset; } -int fit_conf_get_prop_node(const void *fit, int noffset, +int fit_conf_get_prop_node_count(const void *fit, int noffset, const char *prop_name) { - char *uname; + return fdt_stringlist_count(fit, noffset, prop_name); +} + +int fit_conf_get_prop_node_index(const void *fit, int noffset, + const char *prop_name, int index) +{ + const char *uname; int len; /* get kernel image unit name from configuration kernel property */ - uname = (char *)fdt_getprop(fit, noffset, prop_name, &len); + uname = fdt_stringlist_get(fit, noffset, prop_name, index, &len); if (uname == NULL) return len; return fit_image_get_node(fit, uname); } +int fit_conf_get_prop_node(const void *fit, int noffset, + const char *prop_name) +{ + 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 properies for the processed + * fit_conf_print() lists all mandatory properties for the processed * configuration node. * * returns: @@ -1434,8 +1549,9 @@ int fit_conf_get_prop_node(const void *fit, int noffset, void fit_conf_print(const void *fit, int noffset, const char *p) { char *desc; - char *uname; + const char *uname; int ret; + int fdt_index, loadables_index; /* Mandatory properties */ ret = fit_get_desc(fit, noffset, &desc); @@ -1445,7 +1561,7 @@ void fit_conf_print(const void *fit, int noffset, const char *p) else printf("%s\n", desc); - uname = (char *)fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL); + uname = fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL); printf("%s Kernel: ", p); if (uname == NULL) printf("unavailable\n"); @@ -1453,13 +1569,38 @@ void fit_conf_print(const void *fit, int noffset, const char *p) printf("%s\n", uname); /* Optional properties */ - uname = (char *)fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL); + uname = fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL); if (uname) printf("%s Init Ramdisk: %s\n", p, uname); - uname = (char *)fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL); + 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 FDT: %s\n", p, 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) @@ -1493,13 +1634,13 @@ int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, 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; + return -EINVAL; } 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 -ENOENT; } return noffset; @@ -1515,7 +1656,7 @@ 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 + * but we don't have access to the short name, and "fdt" is different * anyway. So let's just keep it here. */ switch (type) { @@ -1527,6 +1668,10 @@ static const char *fit_get_image_type_property(int type) return FIT_RAMDISK_PROP; case IH_TYPE_X86_SETUP: return FIT_SETUP_PROP; + case IH_TYPE_LOADABLE: + return FIT_LOADABLE_PROP; + case IH_TYPE_FPGA: + return FIT_FPGA_PROP; } return "unknown"; @@ -1540,18 +1685,23 @@ int fit_image_load(bootm_headers_t *images, ulong addr, int cfg_noffset, noffset; const char *fit_uname; const char *fit_uname_config; + const char *fit_base_uname_config; const void *fit; const void *buf; size_t size; int type_ok, os_ok; ulong load, data, len; uint8_t os; +#ifndef USE_HOSTCC + uint8_t os_arch; +#endif 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; + fit_base_uname_config = NULL; prop_name = fit_get_image_type_property(image_type); printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr); @@ -1585,11 +1735,11 @@ int fit_image_load(bootm_headers_t *images, ulong addr, 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); + 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 */ - images->fit_uname_cfg = fit_uname_config; + 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)) { @@ -1629,6 +1779,12 @@ int fit_image_load(bootm_headers_t *images, ulong addr, return -ENOEXEC; } #endif + +#ifndef USE_HOSTCC + fit_image_get_arch(fit, noffset, &os_arch); + 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"); @@ -1637,14 +1793,22 @@ int fit_image_load(bootm_headers_t *images, ulong addr, 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)); + fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE) || + (image_type == IH_TYPE_KERNEL && + fit_image_check_type(fit, noffset, IH_TYPE_KERNEL_NOLOAD)); os_ok = image_type == IH_TYPE_FLATDT || + 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); - if (!type_ok || !os_ok) { + + /* + * If either of the checks fail, we should report an error, but + * if the image type is coming from the "loadables" field, we + * don't care what it is + */ + if ((!type_ok || !os_ok) && image_type != IH_TYPE_LOADABLE) { fit_image_get_os(fit, noffset, &os); printf("No %s %s %s Image\n", genimg_get_os_name(os), @@ -1662,6 +1826,12 @@ int fit_image_load(bootm_headers_t *images, ulong addr, bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA); return -ENOENT; } + +#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); +#endif + len = (ulong)size; /* verify that image data is a proper FDT blob */ @@ -1725,7 +1895,8 @@ int fit_image_load(bootm_headers_t *images, ulong addr, if (fit_unamep) *fit_unamep = (char *)fit_uname; if (fit_uname_configp) - *fit_uname_configp = (char *)fit_uname_config; + *fit_uname_configp = (char *)(fit_uname_config ? : + fit_base_uname_config); return noffset; } @@ -1749,3 +1920,144 @@ int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch, return ret; } + +#ifndef USE_HOSTCC +int boot_get_fdt_fit(bootm_headers_t *images, ulong addr, + const char **fit_unamep, const char **fit_uname_configp, + int arch, ulong *datap, ulong *lenp) +{ + int fdt_noffset, cfg_noffset, count; + const void *fit; + const char *fit_uname = NULL; + const char *fit_uname_config = NULL; + char *fit_uname_config_copy = NULL; + char *next_config = NULL; + ulong load, len; +#ifdef CONFIG_OF_LIBFDT_OVERLAY + ulong image_start, image_end; + ulong ovload, ovlen; + const char *uconfig; + const char *uname; + void *base, *ov; + int i, err, noffset, ov_noffset; +#endif + + fit_uname = fit_unamep ? *fit_unamep : NULL; + + if (fit_uname_configp && *fit_uname_configp) { + fit_uname_config_copy = strdup(*fit_uname_configp); + if (!fit_uname_config_copy) + return -ENOMEM; + + next_config = strchr(fit_uname_config_copy, '#'); + if (next_config) + *next_config++ = '\0'; + if (next_config - 1 > fit_uname_config_copy) + fit_uname_config = fit_uname_config_copy; + } + + fdt_noffset = fit_image_load(images, + addr, &fit_uname, &fit_uname_config, + arch, IH_TYPE_FLATDT, + BOOTSTAGE_ID_FIT_FDT_START, + FIT_LOAD_OPTIONAL, &load, &len); + + if (fdt_noffset < 0) + goto out; + + debug("fit_uname=%s, fit_uname_config=%s\n", + fit_uname ? fit_uname : "", + fit_uname_config ? fit_uname_config : ""); + + fit = map_sysmem(addr, 0); + + cfg_noffset = fit_conf_get_node(fit, fit_uname_config); + + /* single blob, or error just return as well */ + count = fit_conf_get_prop_node_count(fit, cfg_noffset, FIT_FDT_PROP); + if (count <= 1 && !next_config) + goto out; + + /* we need to apply overlays */ + +#ifdef CONFIG_OF_LIBFDT_OVERLAY + image_start = addr; + image_end = addr + fit_get_size(fit); + /* verify that relocation took place by load address not being in fit */ + if (load >= image_start && load < image_end) { + /* check is simplified; fit load checks for overlaps */ + printf("Overlayed FDT requires relocation\n"); + fdt_noffset = -EBADF; + goto out; + } + + base = map_sysmem(load, len); + + /* apply extra configs in FIT first, followed by args */ + for (i = 1; ; i++) { + if (i < count) { + noffset = fit_conf_get_prop_node_index(fit, cfg_noffset, + FIT_FDT_PROP, i); + uname = fit_get_name(fit, noffset, NULL); + uconfig = NULL; + } else { + if (!next_config) + break; + uconfig = next_config; + next_config = strchr(next_config, '#'); + if (next_config) + *next_config++ = '\0'; + uname = NULL; + } + + debug("%d: using uname=%s uconfig=%s\n", i, uname, uconfig); + + ov_noffset = fit_image_load(images, + addr, &uname, &uconfig, + arch, IH_TYPE_FLATDT, + BOOTSTAGE_ID_FIT_FDT_START, + FIT_LOAD_REQUIRED, &ovload, &ovlen); + if (ov_noffset < 0) { + printf("load of %s failed\n", uname); + continue; + } + debug("%s loaded at 0x%08lx len=0x%08lx\n", + uname, ovload, ovlen); + ov = map_sysmem(ovload, ovlen); + + base = map_sysmem(load, len + ovlen); + err = fdt_open_into(base, base, len + ovlen); + if (err < 0) { + printf("failed on fdt_open_into\n"); + fdt_noffset = err; + goto out; + } + /* the verbose method prints out messages on error */ + err = fdt_overlay_apply_verbose(base, ov); + if (err < 0) { + fdt_noffset = err; + goto out; + } + fdt_pack(base); + len = fdt_totalsize(base); + } +#else + printf("config with overlays but CONFIG_OF_LIBFDT_OVERLAY not set\n"); + fdt_noffset = -EBADF; +#endif + +out: + if (datap) + *datap = load; + if (lenp) + *lenp = len; + if (fit_unamep) + *fit_unamep = fit_uname; + if (fit_uname_configp) + *fit_uname_configp = fit_uname_config; + + if (fit_uname_config_copy) + free(fit_uname_config_copy); + return fdt_noffset; +} +#endif