On 1/29/25 6:10 PM, Quentin Schulz wrote:
Hi Marek,
Hi,
On 1/12/25 11:36 PM, Marek Vasut wrote:
Add support for starting TFA from U-Boot running in EL3 as part of
fitImage boot, so the user can start U-Boot in the highest privilege
level on the platform, bundle TFA, Linux, DT into a single fitImage
and boot such a bundle as a whole.
There are two main benefits of this approach. First is the ability
to run U-Boot in EL3, where it has unrestricted access to the entire
system and can act as a useful debug tool, as it was always intended
to be used. Second is the ability to easily and safely update of any
component in the fitImage, be it TFA, Linux or DT.
The boot process is similar to regular Linux with DT fitImage boot
process, except the TFA has to be bundled into the fitImage. For the
bundling instructions, see below. The TFA is started as a 'loadables'
with custom U_BOOT_FIT_LOADABLE_HANDLER and armv8_switch_to_el2_prep()
handling implemented in board code, and performing the handoff and
boot in case the TFA was loaded.
The loadables handler is optional and meant to set up any sort of
handoff structures used by the TFA BL31 or perform any other setup
that is needed by the blob. The custom armv8_switch_to_el2_prep()
has to implement the jump to TFA BL31 with return to U-Boot just
before booting the Linux kernel.
Example fitImage image and configuration section:
/dts-v1/;
/ {
description = "Linux kernel with FDT blob and TFA BL31";
images {
kernel-1 { ... };
fdt-1 { ... };
atf-1 { /* This is the TFA BL31 image */
description = "TFA BL31";
data = /incbin/("../build/plat/release/bl31.bin");
type = "tfa-bl31";
This would need to be added to the ITS spec, c.f. https://
fitspec.osfw.foundation/
Where does one do that ?
arch = "arm64";
os = "arm-trusted-firmware";
compression = "none";
load = <0x46400000>;
entry = <0x46400000>;
};
};
configurations {
default = "conf-1";
conf-1 {
description = "Boot Linux";
kernel = "kernel-1";
fdt = "fdt-1";
loadables = "atf-1"; /* This is the TFA BL31 loadable */
We have some special stuff around TF-A (and TEE for that matter IIRC) on
Rockchip. The ELF is split into multiple binaries to load at different
addresses:
[...]
Loadables: u-boot
atf-2
atf-3
I assume this would be supported as well and we would "just" need some
sort of SoC-specific implementation of what was added in patch 1 of this
series?
Yes, I think so.
Is this what you're recommending? We would then identify which
part of the binary it is based on the hardcoded load address instead of
reading the load address from the ITS. Or should we think of a way of
identifying them directly inside the ITS with some property for example?
Maybe try and prototype this loading of TFA for Rockchip and see how
well it fits first (if at all), and then we can decide on the
integration later?
Otherwise a global remark on that feature is I believe it may increase
exposure to exploits. This means U-Boot will happily run anything
provided in EL3. E.g. imagine I provide a script in the ITS which U-Boot
loads and executes before loading the kernel, fdt and loadables. Let's
imagine this is sideloading (we even have some wget support now in U-
Boot so not too far fetched) some app to keep running in EL3 after the
kernel has booted. Or modify registers only accessible from EL3. Now you
better be even more careful about what you're booting from your
linux.itb. Is this a correct interpretation of the situation?
You have freedom to do whatever you want with no restrictions, for
example shoot yourself in the leg by not authenticating random scripts
up front and running whatever unknown stuff, sure. That is not a bad thing.
Running U-Boot in EL2 on top of non-free blobs is not any better, rather
the opposite I think.