Record loadables to FDT passed to next boot stage. This is required for spl_invoke_opensbi(), for example, which requires u-boot/kernel load or entry address to fill opensbi_info.next_addr entry.
spl_load_simple_fit() does it, make spl_load_fit_image() also capable of recording loadables into next stage. One limitation remains: if the FIT image does not contain an FDT blob, spl_load_fit_image() will not use gd->fdt_blob as a fallback, unlike spl_load_simple_fit() which does. Signed-off-by: Nikita Shubin <[email protected]> --- common/spl/spl_fit.c | 80 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 16 deletions(-) diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 26c6cfad116..cc6fc066f40 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -601,6 +601,33 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, return ret; } +/** + * fit_record_loadable() - Record a loaded FIT image in the next-stage FDT + * + * Adds a /fit-images/<name> node to @fdt_blob describing the image, taking + * the type, OS and architecture from the image node in the FIT. + * + * @fit: Pointer to the FIT + * @node: Offset of the image node within @fit + * @idx: Index of the loadable + * @name: Name of the image + * @load_addr: Address the image was loaded to + * @size: Size of the image + * @entry_point: Entry address of the image, or FDT_ERROR if none + * @fdt_blob: FDT to update + * Return: 0 on success, -ve on error + */ +static int fit_record_loadable(const void *fit, int node, int idx, + const char *name, ulong load_addr, ulong size, + ulong entry_point, void *fdt_blob) +{ + return fdt_record_loadable(fdt_blob, idx, name, load_addr, size, + entry_point, + fdt_getprop(fit, node, FIT_TYPE_PROP, NULL), + fdt_getprop(fit, node, FIT_OS_PROP, NULL), + fdt_getprop(fit, node, FIT_ARCH_PROP, NULL)); +} + static int spl_fit_record_loadable(const struct spl_fit_info *ctx, int index, void *blob, struct spl_image_info *image) { @@ -614,13 +641,9 @@ static int spl_fit_record_loadable(const struct spl_fit_info *ctx, int index, node = spl_fit_get_image_node(ctx, FIT_LOADABLE_PROP, index); - ret = fdt_record_loadable(blob, index, name, image->load_addr, - image->size, image->entry_point, - fdt_getprop(ctx->fit, node, FIT_TYPE_PROP, NULL), - fdt_getprop(ctx->fit, node, FIT_OS_PROP, NULL), - fdt_getprop(ctx->fit, node, FIT_ARCH_PROP, NULL)); - - return ret; + return fit_record_loadable(ctx->fit, node, index, name, + image->load_addr, image->size, + image->entry_point, blob); } static int spl_fit_image_is_fpga(const void *fit, int node) @@ -1047,7 +1070,7 @@ int spl_load_fit_image(struct spl_image_info *spl_image, const char *uname; ulong fw_data = 0, dt_data = 0, img_data = 0; ulong fw_len = 0, dt_len = 0, img_len = 0; - int idx, conf_noffset; + int idx, conf_noffset, noffset; int ret; images.verify = CONFIG_IS_ENABLED(FIT_SIGNATURE); @@ -1096,6 +1119,14 @@ int spl_load_fit_image(struct spl_image_info *spl_image, } } + /* Try to make space, so we can inject details on the loadable */ + if (spl_image->fdt_addr) { + ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192); + if (ret < 0) + log_debug("Failed to prepare FDT for loadables: %d\n", + ret); + } + conf_noffset = fit_conf_get_node((const void *)header, fit_uname_config); if (conf_noffset < 0) @@ -1104,17 +1135,34 @@ int spl_load_fit_image(struct spl_image_info *spl_image, for (idx = 0; uname = fdt_stringlist_get((const void *)header, conf_noffset, FIT_LOADABLE_PROP, idx, - NULL), uname; + NULL), uname; idx++) { images.verify = CONFIG_IS_ENABLED(FIT_SIGNATURE); - ret = fit_image_load(&images, virt_to_phys((void *)header), - &uname, &fit_uname_config, - IH_ARCH_DEFAULT, IH_TYPE_LOADABLE, -1, - FIT_LOAD_OPTIONAL_NON_ZERO, - &img_data, &img_len); - if (ret < 0) - return ret; + noffset = fit_image_load(&images, virt_to_phys((void *)header), + &uname, &fit_uname_config, + IH_ARCH_DEFAULT, IH_TYPE_LOADABLE, -1, + FIT_LOAD_OPTIONAL_NON_ZERO, + &img_data, &img_len); + if (noffset < 0) + return noffset; + + /* Record our loadables into the FDT */ + if (spl_image->fdt_addr) { + ulong entry_addr = FDT_ERROR; + + fit_image_get_entry((const void *)header, noffset, + &entry_addr); + log_debug("%s entry addr: 0x%lx\n", uname, entry_addr); + + ret = fit_record_loadable((const void *)header, noffset, + idx, uname, img_data, img_len, + entry_addr, + spl_image->fdt_addr); + if (ret < 0) + log_debug("Couldn't record loadable %s: %d\n", + uname, ret); + } } spl_image->flags |= SPL_FIT_FOUND; -- 2.55.0
