diff options
Diffstat (limited to 'common/spl/spl_fit.c')
-rw-r--r-- | common/spl/spl_fit.c | 95 |
1 files changed, 81 insertions, 14 deletions
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index c496f45b72..128af1bbd6 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -2,7 +2,7 @@ * Copyright (C) 2016 Google, Inc * Written by Simon Glass <sjg@chromium.org> * - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> @@ -16,22 +16,24 @@ #endif /** - * spl_fit_get_image_node(): By using the matching configuration subnode, + * spl_fit_get_image_name(): By using the matching configuration subnode, * retrieve the name of an image, specified by a property name and an index * into that. * @fit: Pointer to the FDT blob. * @images: Offset of the /images subnode. * @type: Name of the property within the configuration subnode. * @index: Index into the list of strings in this property. + * @outname: Name of the image * - * Return: the node offset of the respective image node or a negative - * error number. + * Return: 0 on success, or a negative error number */ -static int spl_fit_get_image_node(const void *fit, int images, - const char *type, int index) +static int spl_fit_get_image_name(const void *fit, int images, + const char *type, int index, + char **outname) { const char *name, *str; - int node, conf_node; + __maybe_unused int node; + int conf_node; int len, i; conf_node = fit_find_config_node(fit); @@ -63,7 +65,35 @@ static int spl_fit_get_image_node(const void *fit, int images, } } + *outname = (char *)str; + return 0; +} + +/** + * spl_fit_get_image_node(): By using the matching configuration subnode, + * retrieve the name of an image, specified by a property name and an index + * into that. + * @fit: Pointer to the FDT blob. + * @images: Offset of the /images subnode. + * @type: Name of the property within the configuration subnode. + * @index: Index into the list of strings in this property. + * + * Return: the node offset of the respective image node or a negative + * error number. + */ +static int spl_fit_get_image_node(const void *fit, int images, + const char *type, int index) +{ + char *str; + int err; + int node; + + err = spl_fit_get_image_name(fit, images, type, index, &str); + if (err) + return err; + debug("%s: '%s'\n", type, str); + node = fdt_subnode_offset(fit, images, str); if (node < 0) { debug("cannot find image node '%s': %d\n", str, node); @@ -116,15 +146,15 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size, * @info: points to information about the device to load data from * @sector: the start sector of the FIT image on the device * @fit: points to the flattened device tree blob describing the FIT - * image + * image * @base_offset: the beginning of the data area containing the actual * image data, relative to the beginning of the FIT * @node: offset of the DT node describing the image to load (relative - * to @fit) + * to @fit) * @image_info: will be filled with information about the loaded image - * If the FIT node does not contain a "load" (address) property, - * the image gets loaded to the address pointed to by the - * load_addr member in this struct. + * If the FIT node does not contain a "load" (address) property, + * the image gets loaded to the address pointed to by the + * load_addr member in this struct. * * Return: 0 on success or a negative error number. */ @@ -239,6 +269,35 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, image_info.load_addr = spl_image->load_addr + spl_image->size; ret = spl_load_fit_image(info, sector, fit, base_offset, node, &image_info); + + if (ret < 0) + return ret; + + /* Make the load-address of the FDT available for the SPL framework */ + spl_image->fdt_addr = (void *)image_info.load_addr; + /* Try to make space, so we can inject details on the loadables */ + ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192); + + return ret; +} + +static int spl_fit_record_loadable(const void *fit, int images, int index, + void *blob, struct spl_image_info *image) +{ + char *name; + int node, ret; + + ret = spl_fit_get_image_name(fit, images, "loadables", + index, &name); + if (ret < 0) + return ret; + + node = spl_fit_get_image_node(fit, images, "loadables", index); + + ret = fdt_record_loadable(blob, index, name, image->load_addr, + image->size, image->entry_point, + fdt_getprop(fit, node, "type", NULL), + fdt_getprop(fit, node, "os", NULL)); return ret; } @@ -364,9 +423,11 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, if (!fit_image_get_os(fit, node, &os_type)) debug("Loadable is %s\n", genimg_get_os_name(os_type)); - if (spl_image->os == IH_OS_U_BOOT) - spl_fit_append_fdt(spl_image, info, sector, + if (os_type == IH_OS_U_BOOT) { + spl_fit_append_fdt(&image_info, info, sector, fit, images, base_offset); + spl_image->fdt_addr = image_info.fdt_addr; + } /* * If the "firmware" image did not provide an entry point, @@ -375,6 +436,12 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, if (spl_image->entry_point == FDT_ERROR && image_info.entry_point != FDT_ERROR) spl_image->entry_point = image_info.entry_point; + + /* Record our loadables into the FDT */ + if (spl_image->fdt_addr) + spl_fit_record_loadable(fit, images, index, + spl_image->fdt_addr, + &image_info); } /* |