Skip to content

Commit

Permalink
SPL: FIT: allow loading multiple images
Browse files Browse the repository at this point in the history
So far we were not using the FIT image format to its full potential:
The SPL FIT loader was just loading the first image from the /images
node plus one of the listed DTBs.
Now with the refactored loader code it's easy to load an arbitrary
number of images in addition to the two mentioned above.
As described in the FIT image source file format description, iterate
over all images listed at the "loadables" property in the configuration
node and load every image at its desired location.
This allows to load any kind of images:
- firmware images to execute before U-Boot proper (for instance
  ARM Trusted Firmware (ATF))
- firmware images for management processors (SCP, arisc, ...)
- firmware images for devices like WiFi controllers
- bit files for FPGAs
- additional configuration data
- kernels and/or ramdisks
The actual usage of this feature would be platform and/or board specific.

Also update the FIT documentation to mention the new SPL feature and
provide an example .its file to demonstrate its features.

Signed-off-by: Andre Przywara <[email protected]>
Reviewed-by: Lokesh Vutla <[email protected]>
Reviewed-by: Simon Glass <[email protected]>
Tested-by: Heiko Stuebner <[email protected]>
Reviewed-by: Kever Yang <[email protected]>
Tested-by: Kever Yang <[email protected]>
Tested-by: Jagan Teki <[email protected]>
Reviewed-by: Jagan Teki <[email protected]>
  • Loading branch information
Andre-ARM authored and Jagan Teki committed May 17, 2017
1 parent 8baa381 commit 411cf32
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 2 deletions.
42 changes: 40 additions & 2 deletions common/spl/spl_fit.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
struct spl_image_info image_info;
int node, images, ret;
int base_offset, align_len = ARCH_DMA_MINALIGN - 1;
int index = 0;

/*
* Figure out where the external images start. This is the base for the
Expand Down Expand Up @@ -278,6 +279,11 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
if (node < 0) {
debug("could not find firmware image, trying loadables...\n");
node = spl_fit_get_image_node(fit, images, "loadables", 0);
/*
* If we pick the U-Boot image from "loadables", start at
* the second image when later loading additional images.
*/
index = 1;
}
if (node < 0) {
debug("%s: Cannot find u-boot image node: %d\n",
Expand Down Expand Up @@ -305,6 +311,38 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
* Align the destination address to ARCH_DMA_MINALIGN.
*/
image_info.load_addr = spl_image->load_addr + spl_image->size;
return spl_load_fit_image(info, sector, fit, base_offset, node,
&image_info);
ret = spl_load_fit_image(info, sector, fit, base_offset, node,
&image_info);
if (ret < 0)
return ret;

/* Now check if there are more images for us to load */
for (; ; index++) {
node = spl_fit_get_image_node(fit, images, "loadables", index);
if (node < 0)
break;

ret = spl_load_fit_image(info, sector, fit, base_offset, node,
&image_info);
if (ret < 0)
continue;

/*
* If the "firmware" image did not provide an entry point,
* use the first valid entry point from the loadables.
*/
if (spl_image->entry_point == FDT_ERROR &&
image_info.entry_point != FDT_ERROR)
spl_image->entry_point = image_info.entry_point;
}

/*
* If a platform does not provide CONFIG_SYS_UBOOT_START, U-Boot's
* Makefile will set it to 0 and it will end up as the entry point
* here. What it actually means is: use the load address.
*/
if (spl_image->entry_point == FDT_ERROR || spl_image->entry_point == 0)
spl_image->entry_point = spl_image->load_addr;

return 0;
}
21 changes: 21 additions & 0 deletions doc/uImage.FIT/howto.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,27 @@ image source file mkimage + dtc transfer to target
+ ---------------> image file --------------------> bootm
image data file(s)

SPL usage
---------

The SPL can make use of the new image format as well, this traditionally
is used to ship multiple device tree files within one image. Code in the SPL
will choose the one matching the current board and append this to the
U-Boot proper binary to be automatically used up by it.
Aside from U-Boot proper and one device tree blob the SPL can load multiple,
arbitrary image files as well. These binaries should be specified in their
own subnode under the /images node, which should then be referenced from one or
multiple /configurations subnodes. The required images must be enumerated in
the "loadables" property as a list of strings.

If a platform specific image source file (.its) is shipped with the U-Boot
source, it can be specified using the CONFIG_SPL_FIT_SOURCE Kconfig symbol.
In this case it will be automatically used by U-Boot's Makefile to generate
the image.
If a static source file is not flexible enough, CONFIG_SPL_FIT_GENERATOR
can point to a script which generates this image source file during
the build process. It gets passed a list of device tree files (taken from the
CONFIG_OF_LIST symbol).

Example 1 -- old-style (non-FDT) kernel booting
-----------------------------------------------
Expand Down
89 changes: 89 additions & 0 deletions doc/uImage.FIT/multi_spl.its
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/dts-v1/;

/*
* (Bogus) example FIT image description file demonstrating the usage
* of multiple images loaded by the SPL.
* Several binaries will be loaded at their respective load addresses.
* Finally the one image specifying an entry point will be entered by the SPL.
*/

/ {
description = "multiple firmware blobs and U-Boot, loaded by SPL";
#address-cells = <0x1>;

images {

uboot {
description = "U-Boot (64-bit)";
type = "standalone";
arch = "arm64";
compression = "none";
load = <0x4a000000>;
};

atf {
description = "ARM Trusted Firmware";
type = "firmware";
arch = "arm64";
compression = "none";
load = <0x18000>;
entry = <0x18000>;
};

mgmt-firmware {
description = "arisc management processor firmware";
type = "firmware";
arch = "or1k";
compression = "none";
load = <0x40000>;
};

fdt@1 {
description = "Pine64+ DT";
type = "flat_dt";
compression = "none";
load = <0x4fa00000>;
arch = "arm64";
};

fdt@2 {
description = "Pine64 DT";
type = "flat_dt";
compression = "none";
load = <0x4fa00000>;
arch = "arm64";
};

kernel {
description = "4.7-rc5 kernel";
type = "kernel";
compression = "none";
load = <0x40080000>;
arch = "arm64";
};

initrd {
description = "Debian installer initrd";
type = "ramdisk";
compression = "none";
load = <0x4fe00000>;
arch = "arm64";
};
};

configurations {
default = "config@1";

config@1 {
description = "sun50i-a64-pine64-plus";
loadables = "uboot", "atf", "kernel", "initrd";
fdt = "fdt@1";
};

config@2 {
description = "sun50i-a64-pine64";
loadables = "uboot", "atf", "mgmt-firmware";
fdt = "fdt@2";
};
};
};

0 comments on commit 411cf32

Please sign in to comment.