Message ID | 20250112223755.179959-2-marek.vasut+renesas@mailbox.org |
---|---|
State | Superseded |
Delegated to: | Marek Vasut |
Headers | show |
Series | [1/3] arm64: Add late jump to kernel board hook | expand |
Hi Marex, Thanks for the patch > -----Original Message----- > From: U-Boot <u-boot-bounces@lists.denx.de> On Behalf Of Marek Vasut > Sent: 12 January 2025 22:37 > Subject: [PATCH 2/3] image: Add support for starting TFA BL31 as fitImage loadables > > 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. In this case, who will do switching from secure world to normal world, u-boot? Do you have any link to the u-boot patch from secure to normal world switching with kernel entry point passed to BL31? Otherwise, kernel, also will be executing in secure world mode. Cheers, Biju
On 1/13/25 1:15 PM, Biju Das wrote: > Hi Marex, > > Thanks for the patch > >> -----Original Message----- >> From: U-Boot <u-boot-bounces@lists.denx.de> On Behalf Of Marek Vasut >> Sent: 12 January 2025 22:37 >> Subject: [PATCH 2/3] image: Add support for starting TFA BL31 as fitImage loadables >> >> 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. > > In this case, who will do switching from secure world to normal world, u-boot? > Do you have any link to the u-boot patch from secure to normal world switching > with kernel entry point passed to BL31? > > Otherwise, kernel, also will be executing in secure world mode. See 3/3 , U-Boot runs in EL3 , before starting kernel it jumps into TFA BL31 , TFA BL31 does its setup and switches from EL3 to EL2 , TFA BL31 returns to U-Boot armv8_switch_to_el2 which checks if this code is running in EL2 (it is) and does the last few steps before starting kernel, and then finally jumps to the kernel .
Hi Marex, > -----Original Message----- > From: Marek Vasut <marek.vasut@mailbox.org> > Sent: 13 January 2025 12:40 > Subject: Re: [PATCH 2/3] image: Add support for starting TFA BL31 as fitImage loadables > > On 1/13/25 1:15 PM, Biju Das wrote: > > Hi Marex, > > > > Thanks for the patch > > > >> -----Original Message----- > >> From: U-Boot <u-boot-bounces@lists.denx.de> On Behalf Of Marek Vasut > >> Sent: 12 January 2025 22:37 > >> Subject: [PATCH 2/3] image: Add support for starting TFA BL31 as > >> fitImage loadables > >> > >> 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 intendedSecure) > >> to be used. Second is the ability to easily and safely update of any component in the fitImage, be > it TFA, Linux or DT. > > > > In this case, who will do switching from secure world to normal world, u-boot? > > Do you have any link to the u-boot patch from secure to normal world > > switching with kernel entry point passed to BL31? > > > > Otherwise, kernel, also will be executing in secure world mode. > See 3/3 , U-Boot runs in EL3 , before starting kernel it jumps into TFA > BL31 , TFA BL31 does its setup and switches from EL3 to EL2 , TFA BL31 returns to U-Boot > armv8_switch_to_el2 which checks if this code is running in EL2 (it is) and does the last few steps > before starting kernel, and then finally jumps to the kernel . Thanks for the explanation. I missed the details in 3/3. BL2(Secure)->U-boot(Secure)->BL31(Secure)-->U-boot(Normal)->Linux Kernel(Normal) Cheers, Biju
On Sun, Jan 12, 2025 at 11:36:58PM +0100, 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"; > 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 */ > }; > }; > }; > > Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org> Reviewed-by: Tom Rini <trini@konsulko.com>
Hi Marek, Biju, On 1/13/25 2:31 PM, Biju Das wrote: > Hi Marex, > >> -----Original Message----- >> From: Marek Vasut <marek.vasut@mailbox.org> >> Sent: 13 January 2025 12:40 >> Subject: Re: [PATCH 2/3] image: Add support for starting TFA BL31 as fitImage loadables >> >> On 1/13/25 1:15 PM, Biju Das wrote: >>> Hi Marex, >>> >>> Thanks for the patch >>> >>>> -----Original Message----- >>>> From: U-Boot <u-boot-bounces@lists.denx.de> On Behalf Of Marek Vasut >>>> Sent: 12 January 2025 22:37 >>>> Subject: [PATCH 2/3] image: Add support for starting TFA BL31 as >>>> fitImage loadables >>>> >>>> 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 intendedSecure) >>>> to be used. Second is the ability to easily and safely update of any component in the fitImage, be >> it TFA, Linux or DT. >>> >>> In this case, who will do switching from secure world to normal world, u-boot? >>> Do you have any link to the u-boot patch from secure to normal world >>> switching with kernel entry point passed to BL31? >>> >>> Otherwise, kernel, also will be executing in secure world mode. >> See 3/3 , U-Boot runs in EL3 , before starting kernel it jumps into TFA >> BL31 , TFA BL31 does its setup and switches from EL3 to EL2 , TFA BL31 returns to U-Boot >> armv8_switch_to_el2 which checks if this code is running in EL2 (it is) and does the last few steps >> before starting kernel, and then finally jumps to the kernel . > > Thanks for the explanation. I missed the details in 3/3. > > BL2(Secure)->U-boot(Secure)->BL31(Secure)-->U-boot(Normal)->Linux Kernel(Normal) > If the fit image is missing the TF-A loadable property for example (and maybe in other corner case scenario?) the kernel will start in EL3 though and fail very early since it needs TF-A BL31 for a few things. However, part of the kernel code will actually run in EL3 and that could be enough to mess things up with a carefully crafted kernel image. Is this actually possible or am I making stuff up? If it is possible, isn't that an issue? Currently, this is already possible and has happened a few times already at my company with people forgetting to bundle TF-A in U-Boot and then the kernel would boot but stops early (no console output even IIRC). But the bootloader is not THAT often updated in the field compared to kernel (especially if coming from distros) which would now allow to store the TF-A, so this opens an even bigger can of worms? In a way, it allows to update TF-A likely more securely (which is VERY welcome on Rockchip for example, where we usually start new SoC bringups with a blob from Rockchip and then have upstream TF-A catch up a few years later. Having BL31 part of U-Boot is a huge pain because it is difficult for some devices to do safe updates of U-Boot) but may introduce some bigger security issues? Finally, another question, what happens if we have a U-Boot with bundled TF-A BL31 AND it tries to boot a fitimage with a TF-A BL31 loadable? Should we only allow to load tf-a BL31 if running from EL3 (meaning if in EL2, TF-A is expected to be already running)? Cheers, Quentin
On 1/15/25 12:51 PM, Quentin Schulz wrote: > Hi Marek, Biju, Hi, [...] >>> See 3/3 , U-Boot runs in EL3 , before starting kernel it jumps into TFA >>> BL31 , TFA BL31 does its setup and switches from EL3 to EL2 , TFA >>> BL31 returns to U-Boot >>> armv8_switch_to_el2 which checks if this code is running in EL2 (it >>> is) and does the last few steps >>> before starting kernel, and then finally jumps to the kernel . >> >> Thanks for the explanation. I missed the details in 3/3. >> >> BL2(Secure)->U-boot(Secure)->BL31(Secure)-->U-boot(Normal)->Linux >> Kernel(Normal) >> > > If the fit image is missing the TF-A loadable property for example (and > maybe in other corner case scenario?) the kernel will start in EL3 > though and fail very early since it needs TF-A BL31 for a few things. Not quite, even if the TFA loadable is not present, the kernel will still be started through armv8_switch_to_el2() , which will switch the core into EL2 and then start the kernel. The kernel will however likely fail to boot because it will attempt to access PSCI via SMC and there will be nothing there, so it will fail at that point. There will be a follow up patch for R-Car Gen4, which will extend and enable the current minimal R-Car Gen4 PSCI support in U-Boot, so even if you do not bundle TFA into the fitImage, the kernel won't fail to boot entirely. With the current R-Car Gen4 PSCI implementation in U-Boot, the kernel can boot and run on a single CPU core only, because the CPU core start and stop callbacks are not implemented and not advertised to Linux yet. Any other SoC that would like to move TFA start after U-Boot start would also likely have to implement at least minimal PSCI implementation to provide a safety net for users who do not bundle the TFA BL31 PSCI provider blob into the fitImage for some reason. The current R-Car Gen4 PSCI implementation is generic enough, that it can act as a template for such other future SoC specific PSCI implementations. > However, part of the kernel code will actually run in EL3 and that could > be enough to mess things up with a carefully crafted kernel image. > > Is this actually possible or am I making stuff up? If it is possible, > isn't that an issue? > > Currently, this is already possible and has happened a few times already > at my company with people forgetting to bundle TF-A in U-Boot and then > the kernel would boot but stops early (no console output even IIRC). But > the bootloader is not THAT often updated in the field compared to kernel > (especially if coming from distros) which would now allow to store the > TF-A, so this opens an even bigger can of worms? See above, I think that answers this question. > In a way, it allows to > update TF-A likely more securely That is very much the point of this, yes. Also, safely update as much as possible in lockstep, for example in case someone has the idea to extend the TFA PSCI implementation with custom SMC call handler(s) and make vendor Linux kernel fork depend on those custom SMC calls for something (*). If the next kernel fork depends on a different set of custom SMC calls (because stable ABI in such cases may not be a guarantee) then updating only the kernel may lead to unbootable system. Worse, updating the bootloader and kernel may lead to kernel boot failure, AND if (usually seldom updated) recovery system kernel did not get updated in lockstep with bootloader, recovery system which depends on the old SMC ABI would also fail to boot, leaving the system unrecoverable. If both kernel and the custom TFA implementation are updated and booted as part of the same fitImage file, the ABI problem goes away. Also, it allows for easy experimentation with the TFA, you can keep swapping blobs in and out as needed to test them out. (*) This is not the case with Renesas to my knowledge , whew ! > (which is VERY welcome on Rockchip for > example, where we usually start new SoC bringups with a blob from > Rockchip and then have upstream TF-A catch up a few years later. Having > BL31 part of U-Boot is a huge pain because it is difficult for some > devices to do safe updates of U-Boot) but may introduce some bigger > security issues? U-Boot will run in EL3 instead of EL2 in this case, which gives it complete unrestricted access to the entire system. It can act as a debug tool, the way it was designed to work since the very beginning. Do you have anything specific in mind here ? > Finally, another question, what happens if we have a U-Boot with bundled > TF-A BL31 AND it tries to boot a fitimage with a TF-A BL31 loadable? It very much depends on the SoC specific TFA BL31 start handler implementation (see patch 3/3). It is possible to add check in there to test whether the system is already running in EL2 for example, and if anything responds to PSCI version SMC call, and if so, skip starting the TFA again. I don't think TFA BL31 can be started in EL2 in any case. > Should we only allow to load tf-a BL31 if running from EL3 (meaning if > in EL2, TF-A is expected to be already running)? That's for the SoC specific handler to decide, see above.
Hi Marek, 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/ > 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: rk3399: Image 1 (atf-1) Description: ARM Trusted Firmware Created: Wed Jan 29 16:24:16 2025 Type: Firmware Compression: uncompressed Data Size: 143438 Bytes = 140.08 KiB = 0.14 MiB Architecture: AArch64 OS: ARM Trusted Firmware Load Address: 0x00040000 Hash algo: sha256 Hash value: 44285ea3a629cceee42a5fbfe838b6193e7c9a2f6643b0496dae617e2f7e2e8a Image 2 (atf-2) Description: ARM Trusted Firmware Created: Wed Jan 29 16:24:16 2025 Type: Firmware Compression: uncompressed Data Size: 8024 Bytes = 7.84 KiB = 0.01 MiB Architecture: AArch64 OS: ARM Trusted Firmware Load Address: 0xff3b0000 Hash algo: sha256 Hash value: 7da49d2642204ded0a8eff093ae5c0e7300cfb18427d7a3e2f4e4cb227e4c2e9 Image 3 (atf-3) Description: ARM Trusted Firmware Created: Wed Jan 29 16:24:16 2025 Type: Firmware Compression: uncompressed Data Size: 4096 Bytes = 4.00 KiB = 0.00 MiB Architecture: AArch64 OS: ARM Trusted Firmware Load Address: 0xff8c0000 Hash algo: sha256 Hash value: 52c626d345ceeab61d8ede858a191834843f234cb4c2d2145546fd824e09c815 Image 4 (atf-4) Description: ARM Trusted Firmware Created: Wed Jan 29 16:24:16 2025 Type: Firmware Compression: uncompressed Data Size: 4096 Bytes = 4.00 KiB = 0.00 MiB Architecture: AArch64 OS: ARM Trusted Firmware Load Address: 0xff8c1000 Hash algo: sha256 Hash value: 50a7da66c26f838220d3befe84dd070988d238fa8abb34d1342815dae1083ec6 Image 5 (atf-5) Description: ARM Trusted Firmware Created: Wed Jan 29 16:24:16 2025 Type: Firmware Compression: uncompressed Data Size: 0 Bytes = 0.00 KiB = 0.00 MiB Architecture: AArch64 OS: ARM Trusted Firmware Load Address: 0xff8c2000 Hash algo: sha256 Hash value: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 Image 6 (fdt-1) Description: fdt-rockchip/rk3399-puma-haikou Created: Wed Jan 29 16:24:16 2025 Type: Flat Device Tree Compression: uncompressed Data Size: 93264 Bytes = 91.08 KiB = 0.09 MiB Architecture: Unknown Architecture Hash algo: sha256 Hash value: 9bcaaba8ea986042273421510acb76d5043bde550e463e80c2ee306239864f4c Default Configuration: 'config-1' Configuration 0 (config-1) Description: rockchip/rk3399-puma-haikou.dtb Kernel: unavailable Firmware: atf-1 FDT: fdt-1 Loadables: u-boot atf-2 atf-3 atf-4 atf-5 px30: Image 1 (atf-1) Description: ARM Trusted Firmware Created: Wed Jan 29 17:06:59 2025 Type: Firmware Compression: uncompressed Data Size: 102526 Bytes = 100.12 KiB = 0.10 MiB Architecture: AArch64 OS: ARM Trusted Firmware Load Address: 0x00040000 Hash algo: sha256 Hash value: d3eb0776f5e1628eaaa38355992bc8a4cc8b12de565ebd6098897269e70345b3 Image 2 (atf-2) Description: ARM Trusted Firmware Created: Wed Jan 29 17:06:59 2025 Type: Firmware Compression: uncompressed Data Size: 112 Bytes = 0.11 KiB = 0.00 MiB Architecture: AArch64 OS: ARM Trusted Firmware Load Address: 0xff020000 Hash algo: sha256 Hash value: 19968b2d18472c485c02be72c609c2e9cc5dc4ea7993b86f462a788d109977d6 Image 3 (fdt-1) Description: fdt-rockchip/px30-ringneck-haikou Created: Wed Jan 29 17:06:59 2025 Type: Flat Device Tree Compression: uncompressed Data Size: 50032 Bytes = 48.86 KiB = 0.05 MiB Architecture: Unknown Architecture Hash algo: sha256 Hash value: f8416b75b2c0a16fd4599f47a4b24d763eb1e2dc0fdaac597510f5b907575c4d Default Configuration: 'config-1' Configuration 0 (config-1) Description: rockchip/px30-ringneck-haikou.dtb Kernel: unavailable Firmware: atf-1 FDT: fdt-1 Loadables: u-boot atf-2 rk3588: Image 1 (atf-1) Description: ARM Trusted Firmware Created: Wed Jan 29 17:08:54 2025 Type: Firmware Compression: uncompressed Data Size: 204860 Bytes = 200.06 KiB = 0.20 MiB Architecture: AArch64 OS: ARM Trusted Firmware Load Address: 0x00040000 Hash algo: sha256 Hash value: 7612223b82b911a56f044a2be63befd1e0d47f9579c50e5b59ca62f12361912d Image 2 (atf-2) Description: ARM Trusted Firmware Created: Wed Jan 29 17:08:54 2025 Type: Firmware Compression: uncompressed Data Size: 24576 Bytes = 24.00 KiB = 0.02 MiB Architecture: AArch64 OS: ARM Trusted Firmware Load Address: 0x000f0000 Hash algo: sha256 Hash value: b2af21b50499777f862cc9d8d6ca9707248694b739badbe875e3b6834ae77e0d Image 3 (atf-3) Description: ARM Trusted Firmware Created: Wed Jan 29 17:08:54 2025 Type: Firmware Compression: uncompressed Data Size: 36864 Bytes = 36.00 KiB = 0.04 MiB Architecture: AArch64 OS: ARM Trusted Firmware Load Address: 0xff100000 Hash algo: sha256 Hash value: 70505bb764db81a665c8bba4953d804ed9eab580d5428888a4436121eff11c50 Image 4 (fdt-1) Description: fdt-rockchip/rk3588-tiger-haikou Created: Wed Jan 29 17:08:54 2025 Type: Flat Device Tree Compression: uncompressed Data Size: 115080 Bytes = 112.38 KiB = 0.11 MiB Architecture: Unknown Architecture Hash algo: sha256 Hash value: c78f6f09dacfaf504d95d8f7d65ab8e0150b9014f033c5aaca85e45448fe177d Default Configuration: 'config-1' Configuration 0 (config-1) Description: rockchip/rk3588-tiger-haikou.dtb Kernel: unavailable Firmware: atf-1 FDT: fdt-1 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? 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? 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? Cheers, Quentin
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.
On 1/29/25 6:38 PM, Marek Vasut wrote: > 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 ? > https://github.com/open-source-firmware/flat-image-tree I guess? [...] >> 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? > Fair point. Not sure if I'll have time to look into this soon though. >> 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. Up to distros to implement the proper security measures then :) Cheers, Quentin
diff --git a/boot/image-fit.c b/boot/image-fit.c index db7fb61bca9..3b6d7231aff 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -2167,6 +2167,7 @@ int fit_image_load(struct bootm_headers *images, ulong addr, type_ok = fit_image_check_type(fit, noffset, image_type) || fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE) || fit_image_check_type(fit, noffset, IH_TYPE_TEE) || + fit_image_check_type(fit, noffset, IH_TYPE_TFA_BL31) || (image_type == IH_TYPE_KERNEL && fit_image_check_type(fit, noffset, IH_TYPE_KERNEL_NOLOAD)); diff --git a/boot/image.c b/boot/image.c index abac254e026..139c5bd035a 100644 --- a/boot/image.c +++ b/boot/image.c @@ -183,6 +183,7 @@ static const table_entry_t uimage_type[] = { { IH_TYPE_FDT_LEGACY, "fdt_legacy", "legacy Image with Flat Device Tree ", }, { IH_TYPE_RENESAS_SPKG, "spkgimage", "Renesas SPKG Image" }, { IH_TYPE_STARFIVE_SPL, "sfspl", "StarFive SPL Image" }, + { IH_TYPE_TFA_BL31, "tfa-bl31", "TFA BL31 Image", }, { -1, "", "", }, }; diff --git a/include/image.h b/include/image.h index 0a61dfd556c..3adb7219809 100644 --- a/include/image.h +++ b/include/image.h @@ -232,6 +232,7 @@ enum image_type_t { IH_TYPE_FDT_LEGACY, /* Binary Flat Device Tree Blob in a Legacy Image */ IH_TYPE_RENESAS_SPKG, /* Renesas SPKG image */ IH_TYPE_STARFIVE_SPL, /* StarFive SPL image */ + IH_TYPE_TFA_BL31, /* TFA BL31 image */ IH_TYPE_COUNT, /* Number of image types */ };
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"; 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 */ }; }; }; Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org> --- Cc: Andre Przywara <andre.przywara@arm.com> Cc: Caleb Connolly <caleb.connolly@linaro.org> Cc: Igor Opaniuk <igor.opaniuk@gmail.com> Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org> Cc: Julien Masson <jmasson@baylibre.com> Cc: Mattijs Korpershoek <mkorpershoek@baylibre.com> Cc: Maxim Moskalets <maximmosk4@gmail.com> Cc: Michael Walle <mwalle@kernel.org> Cc: Nobuhiro Iwamatsu <iwamatsu@nigauri.org> Cc: Patrick Rudolph <patrick.rudolph@9elements.com> Cc: Paul Barker <paul.barker.ct@bp.renesas.com> Cc: Paul-Erwan Rio <paulerwan.rio@gmail.com> Cc: Peter Hoyes <Peter.Hoyes@arm.com> Cc: Raymond Mao <raymond.mao@linaro.org> Cc: Sam Protsenko <semen.protsenko@linaro.org> Cc: Simon Glass <sjg@chromium.org> Cc: Sughosh Ganu <sughosh.ganu@linaro.org> Cc: Tom Rini <trini@konsulko.com> Cc: u-boot@lists.denx.de --- boot/image-fit.c | 1 + boot/image.c | 1 + include/image.h | 1 + 3 files changed, 3 insertions(+)