Adding EFI runtime support to the Arm's FF-A bus

Hi guys,
I'd like to ask for advice regarding adding EFI RT support to the Arm's FF-A bus in U-Boot.
The objective is to enable the FF-A messaging APIs in EFI RT to be used for comms with the secure world. This will help getting/setting EFI variables through FF-A.
The existing FF-A APIs in U-Boot call the DM APIs (which are not available at RT).
Two possible solutions:
1/ having the entire U-Boot in RT space (as Simon stated in this discussion[1])
2/ Create an RT variant for the FF-A APIs needed. These RT variant don't call the DM APIs (e.g: ffa_mm_communicate_runtime, ffa_sync_send_receive_runtime, ...)
What do you recommend please ?
[1]: https://lore.kernel.org/all/CAPnjgZ21qLnSFcCJ9rPQXEfQf-NjMBF3kYUDBBOc6WUQXQt...
Cheers, Abdellatif

Date: Thu, 14 Dec 2023 15:53:46 +0000 From: Abdellatif El Khlifi abdellatif.elkhlifi@arm.com
Hi Abdellatif,
Hi guys,
I'd like to ask for advice regarding adding EFI RT support to the Arm's FF-A bus in U-Boot.
The objective is to enable the FF-A messaging APIs in EFI RT to be used for comms with the secure world. This will help getting/setting EFI variables through FF-A.
The existing FF-A APIs in U-Boot call the DM APIs (which are not available at RT).
Two possible solutions:
1/ having the entire U-Boot in RT space (as Simon stated in this discussion[1])
I don't think this is a terribly good idea. With this approach orders of magnitude more code will be present in kernel address space one the OS kernel is running and calling into the EFI runtime. Including code that may access hardware devices that are now under OS control. It will be nigh impossible to audit all that code and make sure that only a safe subset of it gets called. So...
2/ Create an RT variant for the FF-A APIs needed. These RT variant don't call the DM APIs (e.g: ffa_mm_communicate_runtime, ffa_sync_send_receive_runtime, ...)
What do you recommend please ?
...this is what I would recommend. Preferably in a way that refactors the code such that the low-level functionality is shared between the DM and non-DM APIs.
Cheers, Abdellatif

Hi Mark, Abdellatif
On Thu, 14 Dec 2023 at 18:47, Mark Kettenis mark.kettenis@xs4all.nl wrote:
Date: Thu, 14 Dec 2023 15:53:46 +0000 From: Abdellatif El Khlifi abdellatif.elkhlifi@arm.com
Hi Abdellatif,
Hi guys,
I'd like to ask for advice regarding adding EFI RT support to the Arm's FF-A bus in U-Boot.
The objective is to enable the FF-A messaging APIs in EFI RT to be used for comms with the secure world. This will help getting/setting EFI variables through FF-A.
The existing FF-A APIs in U-Boot call the DM APIs (which are not available at RT).
Two possible solutions:
1/ having the entire U-Boot in RT space (as Simon stated in this discussion[1])
I don't think this is a terribly good idea. With this approach orders of magnitude more code will be present in kernel address space one the OS kernel is running and calling into the EFI runtime. Including code that may access hardware devices that are now under OS control. It will be nigh impossible to audit all that code and make sure that only a safe subset of it gets called. So...
+100 I think we should draw a line here. I mentioned it on another thread, but I did a shot BoF in Plumbers discussing issues like this, problems, and potential solutions [0] [1]. Since that talk patches for the kernel that 'solve' the problem for RPMBs got pulled into linux-next [2]. The TL;DR of that talk is that if the kernel ends up being in control of the hardware that stores the EFI variables, we need to find elegant ways to teach the kernel how to store those directly. The EFI requirement of an isolated flash is something that mostly came from the x86 world and is not a reality on the majority of embedded boards. I also think we should give up on Authenticated EFI variables in that case. We get zero guarantees unless the medium has similar properties to an RPMB. If a vendor cares about proper UEFI secure boot he can implement proper hardware.
2/ Create an RT variant for the FF-A APIs needed. These RT variant don't call the DM APIs (e.g: ffa_mm_communicate_runtime, ffa_sync_send_receive_runtime, ...)
What do you recommend please ?
...this is what I would recommend. Preferably in a way that refactors the code such that the low-level functionality is shared between the DM and non-DM APIs.
Yes. The only thing you need to keep alive is the machinery to talk to the secure world. The bus, flash driver etc should all be running isolated in there. In that case you can implement SetVariableRT as described the the EFI spec.
[...]
[0] https://www.youtube.com/watch?v=UdQk0SCUAlA [1] https://lpc.events/event/17/contributions/1653/attachments/1338/2682/Plumber... [2] https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?...
/Ilias

Hi,
On Thu, 14 Dec 2023 at 12:47, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi Mark, Abdellatif
On Thu, 14 Dec 2023 at 18:47, Mark Kettenis mark.kettenis@xs4all.nl wrote:
Date: Thu, 14 Dec 2023 15:53:46 +0000 From: Abdellatif El Khlifi abdellatif.elkhlifi@arm.com
Hi Abdellatif,
Hi guys,
I'd like to ask for advice regarding adding EFI RT support to the Arm's FF-A bus in U-Boot.
The objective is to enable the FF-A messaging APIs in EFI RT to be used for comms with the secure world. This will help getting/setting EFI variables through FF-A.
The existing FF-A APIs in U-Boot call the DM APIs (which are not available at RT).
Two possible solutions:
1/ having the entire U-Boot in RT space (as Simon stated in this discussion[1])
I don't think this is a terribly good idea. With this approach orders of magnitude more code will be present in kernel address space one the OS kernel is running and calling into the EFI runtime. Including code that may access hardware devices that are now under OS control. It will be nigh impossible to audit all that code and make sure that only a safe subset of it gets called. So...
+100 I think we should draw a line here. I mentioned it on another thread, but I did a shot BoF in Plumbers discussing issues like this, problems, and potential solutions [0] [1]. Since that talk patches for the kernel that 'solve' the problem for RPMBs got pulled into linux-next [2]. The TL;DR of that talk is that if the kernel ends up being in control of the hardware that stores the EFI variables, we need to find elegant ways to teach the kernel how to store those directly. The EFI requirement of an isolated flash is something that mostly came from the x86 world and is not a reality on the majority of embedded boards. I also think we should give up on Authenticated EFI variables in that case. We get zero guarantees unless the medium has similar properties to an RPMB. If a vendor cares about proper UEFI secure boot he can implement proper hardware.
Just to copy in my thoughts as they are lost at this point:
We would need to publish a runtime interface with access to the driver API. I did ask for this when the EFI runtime support was added, but it wasn't done.
It would be possible to create a new 'runtime' phase of U-Boot (RPL?), separate from the others. That will be much easier once we get the XPL stuff sorted out., since adding new [hase would be fairly trivial CPL died as another contributor had a series which went in first...then I never got back to it.
So for now having the entire U-Boot in runtime space seems reasonable to me.
I'll also mention that it would be nice to have s new-style API (replacing the old API U-Boot currently has) which uses more of a module approach. E.g. we could declare that uclass_first_device() is exported and can be called from outside U-Boot.
2/ Create an RT variant for the FF-A APIs needed. These RT variant don't call the DM APIs (e.g: ffa_mm_communicate_runtime, ffa_sync_send_receive_runtime, ...)
What do you recommend please ?
...this is what I would recommend. Preferably in a way that refactors the code such that the low-level functionality is shared between the DM and non-DM APIs.
Yes. The only thing you need to keep alive is the machinery to talk to the secure world. The bus, flash driver etc should all be running isolated in there. In that case you can implement SetVariableRT as described the the EFI spec.
The current approach is pretty brittle, since it relies on putting some of the U-Boot code into a separate area. There is no good way to know which U-Boot code should be in that area, since we don't create a separate build. If a function calls one that has not been specially marked, or accesses data that is not in the area, then it will crash or hang.
So, as I said, I think we need a new build, if we want to avoid all of U-Boot in there. Anything else is hard to maintain.
[...]
[0] https://www.youtube.com/watch?v=UdQk0SCUAlA [1] https://lpc.events/event/17/contributions/1653/attachments/1338/2682/Plumber... [2] https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?...
Regards, Simon

Am 18. Dezember 2023 16:01:44 MEZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Thu, 14 Dec 2023 at 12:47, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi Mark, Abdellatif
On Thu, 14 Dec 2023 at 18:47, Mark Kettenis mark.kettenis@xs4all.nl wrote:
Date: Thu, 14 Dec 2023 15:53:46 +0000 From: Abdellatif El Khlifi abdellatif.elkhlifi@arm.com
Hi Abdellatif,
Hi guys,
I'd like to ask for advice regarding adding EFI RT support to the Arm's FF-A bus in U-Boot.
The objective is to enable the FF-A messaging APIs in EFI RT to be used for comms with the secure world. This will help getting/setting EFI variables through FF-A.
The existing FF-A APIs in U-Boot call the DM APIs (which are not available at RT).
Two possible solutions:
1/ having the entire U-Boot in RT space (as Simon stated in this discussion[1])
I don't think this is a terribly good idea. With this approach orders of magnitude more code will be present in kernel address space one the OS kernel is running and calling into the EFI runtime. Including code that may access hardware devices that are now under OS control. It will be nigh impossible to audit all that code and make sure that only a safe subset of it gets called. So...
+100 I think we should draw a line here. I mentioned it on another thread, but I did a shot BoF in Plumbers discussing issues like this, problems, and potential solutions [0] [1]. Since that talk patches for the kernel that 'solve' the problem for RPMBs got pulled into linux-next [2]. The TL;DR of that talk is that if the kernel ends up being in control of the hardware that stores the EFI variables, we need to find elegant ways to teach the kernel how to store those directly. The EFI requirement of an isolated flash is something that mostly came from the x86 world and is not a reality on the majority of embedded boards. I also think we should give up on Authenticated EFI variables in that case. We get zero guarantees unless the medium has similar properties to an RPMB. If a vendor cares about proper UEFI secure boot he can implement proper hardware.
Just to copy in my thoughts as they are lost at this point:
We would need to publish a runtime interface with access to the driver API. I did ask for this when the EFI runtime support was added, but it wasn't done.
It would be possible to create a new 'runtime' phase of U-Boot (RPL?), separate from the others. That will be much easier once we get the XPL stuff sorted out., since adding new [hase would be fairly trivial CPL died as another contributor had a series which went in first...then I never got back to it.
So for now having the entire U-Boot in runtime space seems reasonable to me.
I'll also mention that it would be nice to have s new-style API (replacing the old API U-Boot currently has) which uses more of a module approach. E.g. we could declare that uclass_first_device() is exported and can be called from outside U-Boot.
2/ Create an RT variant for the FF-A APIs needed. These RT variant don't call the DM APIs (e.g: ffa_mm_communicate_runtime, ffa_sync_send_receive_runtime, ...)
What do you recommend please ?
...this is what I would recommend. Preferably in a way that refactors the code such that the low-level functionality is shared between the DM and non-DM APIs.
Yes. The only thing you need to keep alive is the machinery to talk to the secure world. The bus, flash driver etc should all be running isolated in there. In that case you can implement SetVariableRT as described the the EFI spec.
The current approach is pretty brittle, since it relies on putting some of the U-Boot code into a separate area. There is no good way to know which U-Boot code should be in that area, since we don't create a separate build. If a function calls one that has not been specially marked, or accesses data that is not in the area, then it will crash or hang.
So, as I said, I think we need a new build, if we want to avoid all of U-Boot in there. Anything else is hard to maintain.
The EFI runtime is the most security exposed part of U-Boot. We should strive to keep the attack surface small. No matter how we define the runtime (by section assignment as today or by a dedicated build) I would not want to have the driver model in the runtime.
The only drivers that are required by the EBBR are for resetting the system. ARM has PSCI as reset handler, RISC-V has SBI. These are invoked by simple ecalls.
Any runtime device drivers for variable storage should not be in the U-Boot runtime but live in the secure world (e.g. OP-TEE). FF-A is the new ARM protocol for talking to the secure world and hence fits into the picture.
@Abdellatif
Does an OP-TEE module for managing EFI variables via FF-A already exist? For QEMU?
Best regards
Heinrich
[...]
[0] https://www.youtube.com/watch?v=UdQk0SCUAlA [1] https://lpc.events/event/17/contributions/1653/attachments/1338/2682/Plumber... [2] https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?...
Regards, Simon

Hi Heinrich,
Any runtime device drivers for variable storage should not be in the U-Boot runtime but live in the secure world (e.g. OP-TEE) FF-A is the new ARM protocol for talking to the secure world and hence fits into the picture.
What if I just want a simple embedded boot stack where I don't want any secure world and just want to be able to boot a COTS linux distribution via EFI?
Assuming, that there might be a simple dedicated EEPROM to store the variables which is not exposed to linux, is that something which would be rejected by u-boot mainline now?
-michael

From: Michael Walle mwalle@kernel.org Date: Tue, 19 Dec 2023 11:11:24 +0100
Hi Heinrich,
Hi Michael,
Any runtime device drivers for variable storage should not be in the U-Boot runtime but live in the secure world (e.g. OP-TEE) FF-A is the new ARM protocol for talking to the secure world and hence fits into the picture.
What if I just want a simple embedded boot stack where I don't want any secure world and just want to be able to boot a COTS linux distribution via EFI?
That already works for many Linux distros. As long as the distro installs the appropriate BOOTxxx.EFI file you don't actually need to set any EFI variables for the OS to boot. It can't get any simpler than that. Of the main Linux distros it seems that only Debian doesn't do this. Someone should probably lobby Debian to do this as well as it would mean that Debian would just work on an EBBR compliant system.
Things get more complicated if you want to install multiple OSes. Then having EFI variable support makes things a lot more straightforward.
And of course EFI secure boot needs EFI variable support as well (with proper support) for authenticated EFI variables. But IMHO that no longer falls into "simple embedded boot stack" territory.
Assuming, that there might be a simple dedicated EEPROM to store the variables which is not exposed to linux, is that something which would be rejected by u-boot mainline now?
Not necessarily. But such an approach will have limitations:
* Completely hiding the EEPROM from the OS may be hard. Even if you have a dedicated SPI controller for the EEPROM things like the SPI bus clock or power domains may still be under OS control.
* It is not possible to properly implement authenticated variables for secure boot if the EEPROM and associated hardware is just removed from the device tree but still accessable to the OS. An implementation that pretends the variables are "secure" will probably be rejected.
Cheers,
Mark

Hi Mark,
Any runtime device drivers for variable storage should not be in the U-Boot runtime but live in the secure world (e.g. OP-TEE) FF-A is the new ARM protocol for talking to the secure world and hence fits into the picture.
What if I just want a simple embedded boot stack where I don't want any secure world and just want to be able to boot a COTS linux distribution via EFI?
That already works for many Linux distros. As long as the distro installs the appropriate BOOTxxx.EFI file you don't actually need to set any EFI variables for the OS to boot. It can't get any simpler than that. Of the main Linux distros it seems that only Debian doesn't do this. Someone should probably lobby Debian to do this as well as it would mean that Debian would just work on an EBBR compliant system.
I know. Last time I checked CentOS (or was it Ubuntu?) tried to set EFI variables and the installer just failed. Might be fixed now, though.
Things get more complicated if you want to install multiple OSes. Then having EFI variable support makes things a lot more straightforward.
And of course EFI secure boot needs EFI variable support as well (with proper support) for authenticated EFI variables. But IMHO that no longer falls into "simple embedded boot stack" territory.
Thats clear.
Assuming, that there might be a simple dedicated EEPROM to store the variables which is not exposed to linux, is that something which would be rejected by u-boot mainline now?
Not necessarily. But such an approach will have limitations:
- Completely hiding the EEPROM from the OS may be hard. Even if you have a dedicated SPI controller for the EEPROM things like the SPI bus clock or power domains may still be under OS control.
Fair point, but I was thinking about the ls1028a for example, where - if I remember correctly - there was one dedicated i2c controller in a sense of isolation, probably to use with a secure OS. Also there is no dynamic clocking.
So, technically it should be possible, even with a low overhead, like no device model etc, which could reside in the efi os services. Just testing the waters here, not that I'm interested in adding support for that in u-boot. Just a bit concerned that it (EFI variables) will only work with a full stack (tf-a, optee) in the future.
- It is not possible to properly implement authenticated variables for secure boot if the EEPROM and associated hardware is just removed from the device tree but still accessable to the OS. An implementation that pretends the variables are "secure" will probably be rejected.
Sure. I excluded any secure stuff. But, with that i2c controller i was talking about earlier, it should be possible to mark it as EL3 access only.
Thanks, -michael

On Tue, Dec 19, 2023 at 01:47:07PM +0100, Michael Walle wrote:
Hi Mark,
Any runtime device drivers for variable storage should not be in the U-Boot runtime but live in the secure world (e.g. OP-TEE) FF-A is the new ARM protocol for talking to the secure world and hence fits into the picture.
What if I just want a simple embedded boot stack where I don't want any secure world and just want to be able to boot a COTS linux distribution via EFI?
That already works for many Linux distros. As long as the distro installs the appropriate BOOTxxx.EFI file you don't actually need to set any EFI variables for the OS to boot. It can't get any simpler than that. Of the main Linux distros it seems that only Debian doesn't do this. Someone should probably lobby Debian to do this as well as it would mean that Debian would just work on an EBBR compliant system.
I know. Last time I checked CentOS (or was it Ubuntu?) tried to set EFI variables and the installer just failed. Might be fixed now, though.
Things get more complicated if you want to install multiple OSes. Then having EFI variable support makes things a lot more straightforward.
And of course EFI secure boot needs EFI variable support as well (with proper support) for authenticated EFI variables. But IMHO that no longer falls into "simple embedded boot stack" territory.
Thats clear.
Assuming, that there might be a simple dedicated EEPROM to store the variables which is not exposed to linux, is that something which would be rejected by u-boot mainline now?
Not necessarily. But such an approach will have limitations:
- Completely hiding the EEPROM from the OS may be hard. Even if you have a dedicated SPI controller for the EEPROM things like the SPI bus clock or power domains may still be under OS control.
Fair point, but I was thinking about the ls1028a for example, where - if I remember correctly - there was one dedicated i2c controller in a sense of isolation, probably to use with a secure OS. Also there is no dynamic clocking.
So, technically it should be possible, even with a low overhead, like no device model etc, which could reside in the efi os services. Just testing the waters here, not that I'm interested in adding support for that in u-boot. Just a bit concerned that it (EFI variables) will only work with a full stack (tf-a, optee) in the future.
I would fully expect us to continue to support the case you're describing. It just may have limitations or as you describe implementation work needing to be done to support handling security differently. But it should (*cough*) be abstracted such that it's possible to do so.

Hi Michael
On Tue, 19 Dec 2023 at 14:47, Michael Walle mwalle@kernel.org wrote:
Hi Mark,
Any runtime device drivers for variable storage should not be in the U-Boot runtime but live in the secure world (e.g. OP-TEE) FF-A is the new ARM protocol for talking to the secure world and hence fits into the picture.
What if I just want a simple embedded boot stack where I don't want any secure world and just want to be able to boot a COTS linux distribution via EFI?
That already works for many Linux distros. As long as the distro installs the appropriate BOOTxxx.EFI file you don't actually need to set any EFI variables for the OS to boot. It can't get any simpler than that. Of the main Linux distros it seems that only Debian doesn't do this. Someone should probably lobby Debian to do this as well as it would mean that Debian would just work on an EBBR compliant system.
I know. Last time I checked CentOS (or was it Ubuntu?) tried to set EFI variables and the installer just failed. Might be fixed now, though.
It's not. The error message is less scary in distros nowadays, but setting the variable for Boot0000 is still not working. That being said I have a plan to fix it for variables stored in a file, that's why we standardized the efi variable format in EBBR.
Things get more complicated if you want to install multiple OSes. Then having EFI variable support makes things a lot more straightforward.
And of course EFI secure boot needs EFI variable support as well (with proper support) for authenticated EFI variables. But IMHO that no longer falls into "simple embedded boot stack" territory.
Thats clear.
Assuming, that there might be a simple dedicated EEPROM to store the variables which is not exposed to linux, is that something which would be rejected by u-boot mainline now?
Depends by 'not exposed'. And keep in mind that with a simple SPI flash you also have to worry about easy hardware attacks. E.g. someone replaces your SPI flash with his version of authenticated EFI variables.
We have patches on the ML adding variable support to SPI a SPI flash, but excluding authenticated variables. [0]
Not necessarily. But such an approach will have limitations:
- Completely hiding the EEPROM from the OS may be hard. Even if you have a dedicated SPI controller for the EEPROM things like the SPI bus clock or power domains may still be under OS control.
Fair point, but I was thinking about the ls1028a for example, where - if I remember correctly - there was one dedicated i2c controller in a sense of isolation, probably to use with a secure OS. Also there is no dynamic clocking.
So, technically it should be possible, even with a low overhead, like no> device model etc, which could reside in the efi os services. Just testing the waters here, not that I'm interested in adding support for that in u-boot. Just a bit concerned that it (EFI variables) will only work with a full stack (tf-a, optee) in the future.
- It is not possible to properly implement authenticated variables for secure boot if the EEPROM and associated hardware is just removed from the device tree but still accessable to the OS. An implementation that pretends the variables are "secure" will probably be rejected.
That would be an EEPROM dedicated to the secure world. At some point, I got involved with an EDK2 implementation for supporting EFI variables on a SolidRun honeycomb. We even fixed SetVariableRT and we run the whole thing via OP-TEE (just like we do for RPMB in U-Boot). So this (minus the physical attacks) is quite secure, because even the code running the crypto checks for authenticating variables, runs isolated in the secure world.
It's been a while, but IIRC StMM has FVBs (firmware block protocols) in EDK2 parlance. We have StMM FVBs for RPMBs and EEPROMs and we can launch StMM from OP-TEE. Adding runtime variable support for the RPMB is close to impossible if you want to adhere to the EFI spec, but for it's doable for the EEPROM.
Ping me on IRC if you start adding support, I can help.
Sure. I excluded any secure stuff. But, with that i2c controller i was talking about earlier, it should be possible to mark it as EL3 access only.
Yes, there was a slight implication. NXP some had timer on that I2C or something, but it's been too long to remember the details...
Thanks, -michael
Thanks /Ilias
[0] https://lore.kernel.org/u-boot/20231126220836.374956-2-i@shantur.com/

On Wed, Dec 20, 2023 at 6:37 AM Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi Michael
On Tue, 19 Dec 2023 at 14:47, Michael Walle mwalle@kernel.org wrote:
Hi Mark,
Any runtime device drivers for variable storage should not be in the U-Boot runtime but live in the secure world (e.g. OP-TEE) FF-A is the new ARM protocol for talking to the secure world and hence fits into the picture.
What if I just want a simple embedded boot stack where I don't want any secure world and just want to be able to boot a COTS linux distribution via EFI?
That already works for many Linux distros. As long as the distro installs the appropriate BOOTxxx.EFI file you don't actually need to set any EFI variables for the OS to boot. It can't get any simpler than that. Of the main Linux distros it seems that only Debian doesn't do this. Someone should probably lobby Debian to do this as well as it would mean that Debian would just work on an EBBR compliant system.
I know. Last time I checked CentOS (or was it Ubuntu?) tried to set EFI variables and the installer just failed. Might be fixed now, though.
It's not. The error message is less scary in distros nowadays, but setting the variable for Boot0000 is still not working. That being said I have a plan to fix it for variables stored in a file, that's why we standardized the efi variable format in EBBR.
The actual error is coming from efibootmgr, which is the tool trying to set the variable and is just passed up to installers.
It's now mostly a soft error as if you confirm the error the device still boots via the EFI Fallback methods.
Things get more complicated if you want to install multiple OSes. Then having EFI variable support makes things a lot more straightforward.
And of course EFI secure boot needs EFI variable support as well (with proper support) for authenticated EFI variables. But IMHO that no longer falls into "simple embedded boot stack" territory.
Thats clear.
Assuming, that there might be a simple dedicated EEPROM to store the variables which is not exposed to linux, is that something which would be rejected by u-boot mainline now?
Depends by 'not exposed'. And keep in mind that with a simple SPI flash you also have to worry about easy hardware attacks. E.g. someone replaces your SPI flash with his version of authenticated EFI variables.
We have patches on the ML adding variable support to SPI a SPI flash, but excluding authenticated variables. [0]
Not necessarily. But such an approach will have limitations:
- Completely hiding the EEPROM from the OS may be hard. Even if you have a dedicated SPI controller for the EEPROM things like the SPI bus clock or power domains may still be under OS control.
Fair point, but I was thinking about the ls1028a for example, where - if I remember correctly - there was one dedicated i2c controller in a sense of isolation, probably to use with a secure OS. Also there is no dynamic clocking.
So, technically it should be possible, even with a low overhead, like no> device model etc, which could reside in the efi os services. Just testing the waters here, not that I'm interested in adding support for that in u-boot. Just a bit concerned that it (EFI variables) will only work with a full stack (tf-a, optee) in the future.
- It is not possible to properly implement authenticated variables for secure boot if the EEPROM and associated hardware is just removed from the device tree but still accessable to the OS. An implementation that pretends the variables are "secure" will probably be rejected.
That would be an EEPROM dedicated to the secure world. At some point, I got involved with an EDK2 implementation for supporting EFI variables on a SolidRun honeycomb. We even fixed SetVariableRT and we run the whole thing via OP-TEE (just like we do for RPMB in U-Boot). So this (minus the physical attacks) is quite secure, because even the code running the crypto checks for authenticating variables, runs isolated in the secure world.
It's been a while, but IIRC StMM has FVBs (firmware block protocols) in EDK2 parlance. We have StMM FVBs for RPMBs and EEPROMs and we can launch StMM from OP-TEE. Adding runtime variable support for the RPMB is close to impossible if you want to adhere to the EFI spec, but for it's doable for the EEPROM.
Ping me on IRC if you start adding support, I can help.
Sure. I excluded any secure stuff. But, with that i2c controller i was talking about earlier, it should be possible to mark it as EL3 access only.
Yes, there was a slight implication. NXP some had timer on that I2C or something, but it's been too long to remember the details...
Thanks, -michael
Thanks /Ilias
[0] https://lore.kernel.org/u-boot/20231126220836.374956-2-i@shantur.com/

Hi Illias,
On Wed, Dec 20, 2023 at 3:43 PM Peter Robinson pbrobinson@gmail.com wrote:
On Wed, Dec 20, 2023 at 6:37 AM Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi Michael
On Tue, 19 Dec 2023 at 14:47, Michael Walle mwalle@kernel.org wrote:
Hi Mark,
Any runtime device drivers for variable storage should not be in the U-Boot runtime but live in the secure world (e.g. OP-TEE) FF-A is the new ARM protocol for talking to the secure world and hence fits into the picture.
What if I just want a simple embedded boot stack where I don't want any secure world and just want to be able to boot a COTS linux distribution via EFI?
That already works for many Linux distros. As long as the distro installs the appropriate BOOTxxx.EFI file you don't actually need to set any EFI variables for the OS to boot. It can't get any simpler than that. Of the main Linux distros it seems that only Debian doesn't do this. Someone should probably lobby Debian to do this as well as it would mean that Debian would just work on an EBBR compliant system.
I know. Last time I checked CentOS (or was it Ubuntu?) tried to set EFI variables and the installer just failed. Might be fixed now, though.
It's not. The error message is less scary in distros nowadays, but setting the variable for Boot0000 is still not working. That being said I have a plan to fix it for variables stored in a file, that's why we standardized the efi variable format in EBBR.
Does this mean supporting SetVariableRT for files ? If yes, would it work without the driver model in runtime?
Kind regards, Shantur

Hi Shantur
On Thu, 21 Dec 2023 at 00:57, Shantur Rathore i@shantur.com wrote:
Hi Illias,
On Wed, Dec 20, 2023 at 3:43 PM Peter Robinson pbrobinson@gmail.com wrote:
On Wed, Dec 20, 2023 at 6:37 AM Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi Michael
On Tue, 19 Dec 2023 at 14:47, Michael Walle mwalle@kernel.org wrote:
Hi Mark,
> Any runtime device drivers for variable storage should not be in the > U-Boot runtime but live in the secure world (e.g. OP-TEE) FF-A is the > new ARM protocol for talking to the secure world and hence fits into > the picture.
What if I just want a simple embedded boot stack where I don't want any secure world and just want to be able to boot a COTS linux distribution via EFI?
That already works for many Linux distros. As long as the distro installs the appropriate BOOTxxx.EFI file you don't actually need to set any EFI variables for the OS to boot. It can't get any simpler than that. Of the main Linux distros it seems that only Debian doesn't do this. Someone should probably lobby Debian to do this as well as it would mean that Debian would just work on an EBBR compliant system.
I know. Last time I checked CentOS (or was it Ubuntu?) tried to set EFI variables and the installer just failed. Might be fixed now, though.
It's not. The error message is less scary in distros nowadays, but setting the variable for Boot0000 is still not working. That being said I have a plan to fix it for variables stored in a file, that's why we standardized the efi variable format in EBBR.
Does this mean supporting SetVariableRT for files ? If yes, would it work without the driver model in runtime?
Yes.
The reasoning here is pretty simple. You can't keep alive drivers etc for devices that the *kernel* eventually owns. The proposal is to ignore the EFI spec and teach the kernel to write those directly. We already do that when the variables are stored in an RPMB, we need to figure out a decent scalable architecture for the rest.
/Ilias
Kind regards, Shantur

Hi Ilias,
On Thu, Dec 21, 2023 at 6:30 AM Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi Shantur
On Thu, 21 Dec 2023 at 00:57, Shantur Rathore i@shantur.com wrote:
Hi Illias,
On Wed, Dec 20, 2023 at 3:43 PM Peter Robinson pbrobinson@gmail.com wrote:
On Wed, Dec 20, 2023 at 6:37 AM Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi Michael
On Tue, 19 Dec 2023 at 14:47, Michael Walle mwalle@kernel.org wrote:
Hi Mark,
> > Any runtime device drivers for variable storage should not be in the > > U-Boot runtime but live in the secure world (e.g. OP-TEE) FF-A is the > > new ARM protocol for talking to the secure world and hence fits into > > the picture. > > What if I just want a simple embedded boot stack where I don't > want any secure world and just want to be able to boot a COTS linux > distribution via EFI?
That already works for many Linux distros. As long as the distro installs the appropriate BOOTxxx.EFI file you don't actually need to set any EFI variables for the OS to boot. It can't get any simpler than that. Of the main Linux distros it seems that only Debian doesn't do this. Someone should probably lobby Debian to do this as well as it would mean that Debian would just work on an EBBR compliant system.
I know. Last time I checked CentOS (or was it Ubuntu?) tried to set EFI variables and the installer just failed. Might be fixed now, though.
It's not. The error message is less scary in distros nowadays, but setting the variable for Boot0000 is still not working. That being said I have a plan to fix it for variables stored in a file, that's why we standardized the efi variable format in EBBR.
Does this mean supporting SetVariableRT for files ? If yes, would it work without the driver model in runtime?
Yes.
The reasoning here is pretty simple. You can't keep alive drivers etc for devices that the *kernel* eventually owns. The proposal is to ignore the EFI spec and teach the kernel to write those directly. We already do that when the variables are stored in an RPMB, we need to figure out a decent scalable architecture for the rest.
Thanks for explaining this. It would be a good idea to provide EFI var storage info like location, offset, maxsize to linux and linux can modify vars as required.
Eg.
location=espfile://u-boot-efi.vars offset=0 maxsize=-1 or location=spi://0 offset=0x3D0000 maxsize=0xFFFF
Then the linux kernel is able to modify vars correctly. I think SPI might be simpler to implement vs file as there can be. many different ESP partitions on multiple drives or no ESP partition at all.
Kind regards, Shantur
/Ilias
Kind regards, Shantur

[...]
I know. Last time I checked CentOS (or was it Ubuntu?) tried to set EFI variables and the installer just failed. Might be fixed now, though.
It's not. The error message is less scary in distros nowadays, but setting the variable for Boot0000 is still not working. That being said I have a plan to fix it for variables stored in a file, that's why we standardized the efi variable format in EBBR.
Does this mean supporting SetVariableRT for files ? If yes, would it work without the driver model in runtime?
Yes.
The reasoning here is pretty simple. You can't keep alive drivers etc for devices that the *kernel* eventually owns. The proposal is to ignore the EFI spec and teach the kernel to write those directly. We already do that when the variables are stored in an RPMB, we need to figure out a decent scalable architecture for the rest.
Thanks for explaining this. It would be a good idea to provide EFI var storage info like location, offset, maxsize to linux and linux can modify vars as required.
Eg.
location=espfile://u-boot-efi.vars offset=0 maxsize=-1 or location=spi://0 offset=0x3D0000 maxsize=0xFFFF
Yes, you need the flash, offset and size, but I as trying to figure out if we hand over those as an EFI config table. I haven't managed to do any coding though yet.
/Ilias
Then the linux kernel is able to modify vars correctly. I think SPI might be simpler to implement vs file as there can be. many different ESP partitions on multiple drives or no ESP partition at all.
Kind regards, Shantur
/Ilias
Kind regards, Shantur

Hi Heinrich,
On Mon, Dec 18, 2023 at 09:59:13PM +0100, Heinrich Schuchardt wrote:
Am 18. Dezember 2023 16:01:44 MEZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Thu, 14 Dec 2023 at 12:47, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi Mark, Abdellatif
On Thu, 14 Dec 2023 at 18:47, Mark Kettenis mark.kettenis@xs4all.nl wrote:
Date: Thu, 14 Dec 2023 15:53:46 +0000 From: Abdellatif El Khlifi abdellatif.elkhlifi@arm.com
Hi Abdellatif,
Hi guys,
I'd like to ask for advice regarding adding EFI RT support to the Arm's FF-A bus in U-Boot.
The objective is to enable the FF-A messaging APIs in EFI RT to be used for comms with the secure world. This will help getting/setting EFI variables through FF-A.
The existing FF-A APIs in U-Boot call the DM APIs (which are not available at RT).
Two possible solutions:
1/ having the entire U-Boot in RT space (as Simon stated in this discussion[1])
I don't think this is a terribly good idea. With this approach orders of magnitude more code will be present in kernel address space one the OS kernel is running and calling into the EFI runtime. Including code that may access hardware devices that are now under OS control. It will be nigh impossible to audit all that code and make sure that only a safe subset of it gets called. So...
+100 I think we should draw a line here. I mentioned it on another thread, but I did a shot BoF in Plumbers discussing issues like this, problems, and potential solutions [0] [1]. Since that talk patches for the kernel that 'solve' the problem for RPMBs got pulled into linux-next [2]. The TL;DR of that talk is that if the kernel ends up being in control of the hardware that stores the EFI variables, we need to find elegant ways to teach the kernel how to store those directly. The EFI requirement of an isolated flash is something that mostly came from the x86 world and is not a reality on the majority of embedded boards. I also think we should give up on Authenticated EFI variables in that case. We get zero guarantees unless the medium has similar properties to an RPMB. If a vendor cares about proper UEFI secure boot he can implement proper hardware.
Just to copy in my thoughts as they are lost at this point:
We would need to publish a runtime interface with access to the driver API. I did ask for this when the EFI runtime support was added, but it wasn't done.
It would be possible to create a new 'runtime' phase of U-Boot (RPL?), separate from the others. That will be much easier once we get the XPL stuff sorted out., since adding new [hase would be fairly trivial CPL died as another contributor had a series which went in first...then I never got back to it.
So for now having the entire U-Boot in runtime space seems reasonable to me.
I'll also mention that it would be nice to have s new-style API (replacing the old API U-Boot currently has) which uses more of a module approach. E.g. we could declare that uclass_first_device() is exported and can be called from outside U-Boot.
2/ Create an RT variant for the FF-A APIs needed. These RT variant don't call the DM APIs (e.g: ffa_mm_communicate_runtime, ffa_sync_send_receive_runtime, ...)
What do you recommend please ?
...this is what I would recommend. Preferably in a way that refactors the code such that the low-level functionality is shared between the DM and non-DM APIs.
Yes. The only thing you need to keep alive is the machinery to talk to the secure world. The bus, flash driver etc should all be running isolated in there. In that case you can implement SetVariableRT as described the the EFI spec.
The current approach is pretty brittle, since it relies on putting some of the U-Boot code into a separate area. There is no good way to know which U-Boot code should be in that area, since we don't create a separate build. If a function calls one that has not been specially marked, or accesses data that is not in the area, then it will crash or hang.
So, as I said, I think we need a new build, if we want to avoid all of U-Boot in there. Anything else is hard to maintain.
The EFI runtime is the most security exposed part of U-Boot. We should strive to keep the attack surface small. No matter how we define the runtime (by section assignment as today or by a dedicated build) I would not want to have the driver model in the runtime.
The only drivers that are required by the EBBR are for resetting the system. ARM has PSCI as reset handler, RISC-V has SBI. These are invoked by simple ecalls.
Any runtime device drivers for variable storage should not be in the U-Boot runtime but live in the secure world (e.g. OP-TEE). FF-A is the new ARM protocol for talking to the secure world and hence fits into the picture.
@Abdellatif
Does an OP-TEE module for managing EFI variables via FF-A already exist?
Yes, that's available in two ways:
1) The smm-gateway SP from Trusted Services (aka TS) [1] provides EFI variable service over FF-A [2]. It's not OP-TEE specific, it can run on top of any S-EL1 SPMC. 2) StMM
[1]: https://trusted-services.readthedocs.io/en/stable/deployments/secure-partiti... [2]: https://github.com/u-boot/u-boot/blob/master/doc/arch/arm64.ffa.rst
For QEMU?
Yes, smm-gateway is tested on QEMU through the qemuarm64-secureboot Yocto machine [1]. Also, there is an in-progress PR to add TS on QEMU support in the OP-TEE integration system [2].
[1]: https://git.yoctoproject.org/meta-arm/tree/meta-arm/conf/machine/qemuarm64-s... , https://git.yoctoproject.org/meta-arm/tree/meta-arm/recipes-security/trusted... [2]: https://github.com/OP-TEE/build/pull/688
Cheers, Abdellatif

Hi Heinrich,
On Mon, 18 Dec 2023 at 13:59, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 18. Dezember 2023 16:01:44 MEZ schrieb Simon Glass sjg@chromium.org:
Hi,
On Thu, 14 Dec 2023 at 12:47, Ilias Apalodimas ilias.apalodimas@linaro.org wrote:
Hi Mark, Abdellatif
On Thu, 14 Dec 2023 at 18:47, Mark Kettenis mark.kettenis@xs4all.nl wrote:
Date: Thu, 14 Dec 2023 15:53:46 +0000 From: Abdellatif El Khlifi abdellatif.elkhlifi@arm.com
Hi Abdellatif,
Hi guys,
I'd like to ask for advice regarding adding EFI RT support to the Arm's FF-A bus in U-Boot.
The objective is to enable the FF-A messaging APIs in EFI RT to be used for comms with the secure world. This will help getting/setting EFI variables through FF-A.
The existing FF-A APIs in U-Boot call the DM APIs (which are not available at RT).
Two possible solutions:
1/ having the entire U-Boot in RT space (as Simon stated in this discussion[1])
I don't think this is a terribly good idea. With this approach orders of magnitude more code will be present in kernel address space one the OS kernel is running and calling into the EFI runtime. Including code that may access hardware devices that are now under OS control. It will be nigh impossible to audit all that code and make sure that only a safe subset of it gets called. So...
+100 I think we should draw a line here. I mentioned it on another thread, but I did a shot BoF in Plumbers discussing issues like this, problems, and potential solutions [0] [1]. Since that talk patches for the kernel that 'solve' the problem for RPMBs got pulled into linux-next [2]. The TL;DR of that talk is that if the kernel ends up being in control of the hardware that stores the EFI variables, we need to find elegant ways to teach the kernel how to store those directly. The EFI requirement of an isolated flash is something that mostly came from the x86 world and is not a reality on the majority of embedded boards. I also think we should give up on Authenticated EFI variables in that case. We get zero guarantees unless the medium has similar properties to an RPMB. If a vendor cares about proper UEFI secure boot he can implement proper hardware.
Just to copy in my thoughts as they are lost at this point:
We would need to publish a runtime interface with access to the driver API. I did ask for this when the EFI runtime support was added, but it wasn't done.
It would be possible to create a new 'runtime' phase of U-Boot (RPL?), separate from the others. That will be much easier once we get the XPL stuff sorted out., since adding new [hase would be fairly trivial CPL died as another contributor had a series which went in first...then I never got back to it.
So for now having the entire U-Boot in runtime space seems reasonable to me.
I'll also mention that it would be nice to have s new-style API (replacing the old API U-Boot currently has) which uses more of a module approach. E.g. we could declare that uclass_first_device() is exported and can be called from outside U-Boot.
2/ Create an RT variant for the FF-A APIs needed. These RT variant don't call the DM APIs (e.g: ffa_mm_communicate_runtime, ffa_sync_send_receive_runtime, ...)
What do you recommend please ?
...this is what I would recommend. Preferably in a way that refactors the code such that the low-level functionality is shared between the DM and non-DM APIs.
Yes. The only thing you need to keep alive is the machinery to talk to the secure world. The bus, flash driver etc should all be running isolated in there. In that case you can implement SetVariableRT as described the the EFI spec.
The current approach is pretty brittle, since it relies on putting some of the U-Boot code into a separate area. There is no good way to know which U-Boot code should be in that area, since we don't create a separate build. If a function calls one that has not been specially marked, or accesses data that is not in the area, then it will crash or hang.
So, as I said, I think we need a new build, if we want to avoid all of U-Boot in there. Anything else is hard to maintain.
The EFI runtime is the most security exposed part of U-Boot. We should strive to keep the attack surface small. No matter how we define the runtime (by section assignment as today or by a dedicated build) I would not want to have the driver model in the runtime.
The only drivers that are required by the EBBR are for resetting the system. ARM has PSCI as reset handler, RISC-V has SBI. These are invoked by simple ecalls.
So why not have Linux do it? Why do we need the runtime at all?
But from the other POV, what if this expands? We are creating a little runtime stub without driver model? I suppose it will work until it doesn't.
Any runtime device drivers for variable storage should not be in the U-Boot runtime but live in the secure world (e.g. OP-TEE). FF-A is the new ARM protocol for talking to the secure world and hence fits into the picture.
OK. This is all very complicated, of course. But OK.
@Abdellatif
Does an OP-TEE module for managing EFI variables via FF-A already exist? For QEMU?
Best regards
Heinrich
[...]
[0] https://www.youtube.com/watch?v=UdQk0SCUAlA [1] https://lpc.events/event/17/contributions/1653/attachments/1338/2682/Plumber... [2] https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?...
Regards, Simon

Hi Ilias
On Thu, Dec 14, 2023 at 09:47:13PM +0200, Ilias Apalodimas wrote:
Hi Mark, Abdellatif
On Thu, 14 Dec 2023 at 18:47, Mark Kettenis mark.kettenis@xs4all.nl wrote:
Date: Thu, 14 Dec 2023 15:53:46 +0000 From: Abdellatif El Khlifi abdellatif.elkhlifi@arm.com
Hi Abdellatif,
Hi guys,
I'd like to ask for advice regarding adding EFI RT support to the Arm's FF-A bus in U-Boot.
The objective is to enable the FF-A messaging APIs in EFI RT to be used for comms with the secure world. This will help getting/setting EFI variables through FF-A.
The existing FF-A APIs in U-Boot call the DM APIs (which are not available at RT).
Two possible solutions:
1/ having the entire U-Boot in RT space (as Simon stated in this discussion[1])
I don't think this is a terribly good idea. With this approach orders of magnitude more code will be present in kernel address space one the OS kernel is running and calling into the EFI runtime. Including code that may access hardware devices that are now under OS control. It will be nigh impossible to audit all that code and make sure that only a safe subset of it gets called. So...
+100 I think we should draw a line here. I mentioned it on another thread, but I did a shot BoF in Plumbers discussing issues like this, problems, and potential solutions [0] [1]. Since that talk patches for the kernel that 'solve' the problem for RPMBs got pulled into linux-next [2].
I watched your talk. Great work, thanks :)
The TL;DR of that talk is that if the kernel ends up being in control of the hardware that stores the EFI variables, we need to find elegant ways to teach the kernel how to store those directly. The EFI requirement of an isolated flash is something that mostly came from the x86 world and is not a reality on the majority of embedded boards. I also think we should give up on Authenticated EFI variables in that case. We get zero guarantees unless the medium has similar properties to an RPMB. If a vendor cares about proper UEFI secure boot he can implement proper hardware.
2/ Create an RT variant for the FF-A APIs needed. These RT variant don't call the DM APIs (e.g: ffa_mm_communicate_runtime, ffa_sync_send_receive_runtime, ...)
What do you recommend please ?
...this is what I would recommend. Preferably in a way that refactors the code such that the low-level functionality is shared between the DM and non-DM APIs.
Yes. The only thing you need to keep alive is the machinery to talk to the secure world. The bus, flash driver etc should all be running isolated in there. In that case you can implement SetVariableRT as described the the EFI spec.
Cool, thanks. That's my preferred solution too.
mm_communicate() should be able to detect runtime mode so it calls ffa_mm_communicate_runtime().
Is there a way to check whether we are in EFI runtime or not ?
Suggested changes (pseudo-code):
__efi_runtime mm_communicate () { #if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) if (RT) { /* NEW */ ret = ffa_mm_communicate_runtime(comm_buf, dsize); /* NEW */ } else { mm_comms = get_mm_comms(); if (mm_comms == MM_COMMS_FFA) ret = ffa_mm_communicate(comm_buf, dsize); else ret = optee_mm_communicate(comm_buf, dsize); } #else ... #endif
Existing code: https://github.com/u-boot/u-boot/blob/master/lib/efi_loader/efi_variable_tee...
Cheers, Abdellatif

Happy new year Ilias,
On Mon, Dec 18, 2023 at 04:59:09PM +0000, Abdellatif El Khlifi wrote:
Hi Ilias
On Thu, Dec 14, 2023 at 09:47:13PM +0200, Ilias Apalodimas wrote:
Hi Mark, Abdellatif
On Thu, 14 Dec 2023 at 18:47, Mark Kettenis mark.kettenis@xs4all.nl wrote:
Date: Thu, 14 Dec 2023 15:53:46 +0000 From: Abdellatif El Khlifi abdellatif.elkhlifi@arm.com
Hi Abdellatif,
Hi guys,
I'd like to ask for advice regarding adding EFI RT support to the Arm's FF-A bus in U-Boot.
The objective is to enable the FF-A messaging APIs in EFI RT to be used for comms with the secure world. This will help getting/setting EFI variables through FF-A.
The existing FF-A APIs in U-Boot call the DM APIs (which are not available at RT).
Two possible solutions:
1/ having the entire U-Boot in RT space (as Simon stated in this discussion[1])
I don't think this is a terribly good idea. With this approach orders of magnitude more code will be present in kernel address space one the OS kernel is running and calling into the EFI runtime. Including code that may access hardware devices that are now under OS control. It will be nigh impossible to audit all that code and make sure that only a safe subset of it gets called. So...
+100 I think we should draw a line here. I mentioned it on another thread, but I did a shot BoF in Plumbers discussing issues like this, problems, and potential solutions [0] [1]. Since that talk patches for the kernel that 'solve' the problem for RPMBs got pulled into linux-next [2].
I watched your talk. Great work, thanks :)
The TL;DR of that talk is that if the kernel ends up being in control of the hardware that stores the EFI variables, we need to find elegant ways to teach the kernel how to store those directly. The EFI requirement of an isolated flash is something that mostly came from the x86 world and is not a reality on the majority of embedded boards. I also think we should give up on Authenticated EFI variables in that case. We get zero guarantees unless the medium has similar properties to an RPMB. If a vendor cares about proper UEFI secure boot he can implement proper hardware.
2/ Create an RT variant for the FF-A APIs needed. These RT variant don't call the DM APIs (e.g: ffa_mm_communicate_runtime, ffa_sync_send_receive_runtime, ...)
What do you recommend please ?
...this is what I would recommend. Preferably in a way that refactors the code such that the low-level functionality is shared between the DM and non-DM APIs.
Yes. The only thing you need to keep alive is the machinery to talk to the secure world. The bus, flash driver etc should all be running isolated in there. In that case you can implement SetVariableRT as described the the EFI spec.
Cool, thanks. That's my preferred solution too.
mm_communicate() should be able to detect runtime mode so it calls ffa_mm_communicate_runtime().
Is there a way to check whether we are in EFI runtime or not ?
Suggested changes (pseudo-code):
__efi_runtime mm_communicate () { #if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) if (RT) { /* NEW */ ret = ffa_mm_communicate_runtime(comm_buf, dsize); /* NEW */ } else { mm_comms = get_mm_comms(); if (mm_comms == MM_COMMS_FFA) ret = ffa_mm_communicate(comm_buf, dsize); else ret = optee_mm_communicate(comm_buf, dsize); } #else ... #endif
Existing code: https://github.com/u-boot/u-boot/blob/master/lib/efi_loader/efi_variable_tee...
A gentle reminder about the question above please (Is there a way to check whether we are in EFI runtime or not).
Cheers, Abdellatif

On 08.01.24 15:12, Abdellatif El Khlifi wrote:
Happy new year Ilias,
On Mon, Dec 18, 2023 at 04:59:09PM +0000, Abdellatif El Khlifi wrote:
Hi Ilias
On Thu, Dec 14, 2023 at 09:47:13PM +0200, Ilias Apalodimas wrote:
Hi Mark, Abdellatif
On Thu, 14 Dec 2023 at 18:47, Mark Kettenis mark.kettenis@xs4all.nl wrote:
Date: Thu, 14 Dec 2023 15:53:46 +0000 From: Abdellatif El Khlifi abdellatif.elkhlifi@arm.com
Hi Abdellatif,
Hi guys,
I'd like to ask for advice regarding adding EFI RT support to the Arm's FF-A bus in U-Boot.
The objective is to enable the FF-A messaging APIs in EFI RT to be used for comms with the secure world. This will help getting/setting EFI variables through FF-A.
The existing FF-A APIs in U-Boot call the DM APIs (which are not available at RT).
Two possible solutions:
1/ having the entire U-Boot in RT space (as Simon stated in this discussion[1])
I don't think this is a terribly good idea. With this approach orders of magnitude more code will be present in kernel address space one the OS kernel is running and calling into the EFI runtime. Including code that may access hardware devices that are now under OS control. It will be nigh impossible to audit all that code and make sure that only a safe subset of it gets called. So...
+100 I think we should draw a line here. I mentioned it on another thread, but I did a shot BoF in Plumbers discussing issues like this, problems, and potential solutions [0] [1]. Since that talk patches for the kernel that 'solve' the problem for RPMBs got pulled into linux-next [2].
I watched your talk. Great work, thanks :)
The TL;DR of that talk is that if the kernel ends up being in control of the hardware that stores the EFI variables, we need to find elegant ways to teach the kernel how to store those directly. The EFI requirement of an isolated flash is something that mostly came from the x86 world and is not a reality on the majority of embedded boards. I also think we should give up on Authenticated EFI variables in that case. We get zero guarantees unless the medium has similar properties to an RPMB. If a vendor cares about proper UEFI secure boot he can implement proper hardware.
2/ Create an RT variant for the FF-A APIs needed. These RT variant don't call the DM APIs (e.g: ffa_mm_communicate_runtime, ffa_sync_send_receive_runtime, ...)
What do you recommend please ?
...this is what I would recommend. Preferably in a way that refactors the code such that the low-level functionality is shared between the DM and non-DM APIs.
Yes. The only thing you need to keep alive is the machinery to talk to the secure world. The bus, flash driver etc should all be running isolated in there. In that case you can implement SetVariableRT as described the the EFI spec.
Cool, thanks. That's my preferred solution too.
mm_communicate() should be able to detect runtime mode so it calls ffa_mm_communicate_runtime().
Is there a way to check whether we are in EFI runtime or not ?
Relevant UEFI event groups for the transition to the OS are:
EFI_EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES EFI_EVENT_GROUP_EXIT_BOOT_SERVICES EFI_EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE
Once EFI_EVENT_GROUP_EXIT_BOOT_SERVICES is signaled you are at runtime.
Use CreateEventEx() to create an event for the group.
Best regards
Heinrich
Suggested changes (pseudo-code):
__efi_runtime mm_communicate () { #if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) if (RT) { /* NEW */ ret = ffa_mm_communicate_runtime(comm_buf, dsize); /* NEW */ } else { mm_comms = get_mm_comms(); if (mm_comms == MM_COMMS_FFA) ret = ffa_mm_communicate(comm_buf, dsize); else ret = optee_mm_communicate(comm_buf, dsize); } #else ... #endif
Existing code: https://github.com/u-boot/u-boot/blob/master/lib/efi_loader/efi_variable_tee...
A gentle reminder about the question above please (Is there a way to check whether we are in EFI runtime or not).
Cheers, Abdellatif

On Mon, 8 Jan 2024 at 16:32, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 08.01.24 15:12, Abdellatif El Khlifi wrote:
Happy new year Ilias,
On Mon, Dec 18, 2023 at 04:59:09PM +0000, Abdellatif El Khlifi wrote:
Hi Ilias
On Thu, Dec 14, 2023 at 09:47:13PM +0200, Ilias Apalodimas wrote:
Hi Mark, Abdellatif
On Thu, 14 Dec 2023 at 18:47, Mark Kettenis mark.kettenis@xs4all.nl wrote:
Date: Thu, 14 Dec 2023 15:53:46 +0000 From: Abdellatif El Khlifi abdellatif.elkhlifi@arm.com
Hi Abdellatif,
Hi guys,
I'd like to ask for advice regarding adding EFI RT support to the Arm's FF-A bus in U-Boot.
The objective is to enable the FF-A messaging APIs in EFI RT to be used for comms with the secure world. This will help getting/setting EFI variables through FF-A.
The existing FF-A APIs in U-Boot call the DM APIs (which are not available at RT).
Two possible solutions:
1/ having the entire U-Boot in RT space (as Simon stated in this discussion[1])
I don't think this is a terribly good idea. With this approach orders of magnitude more code will be present in kernel address space one the OS kernel is running and calling into the EFI runtime. Including code that may access hardware devices that are now under OS control. It will be nigh impossible to audit all that code and make sure that only a safe subset of it gets called. So...
+100 I think we should draw a line here. I mentioned it on another thread, but I did a shot BoF in Plumbers discussing issues like this, problems, and potential solutions [0] [1]. Since that talk patches for the kernel that 'solve' the problem for RPMBs got pulled into linux-next [2].
I watched your talk. Great work, thanks :)
The TL;DR of that talk is that if the kernel ends up being in control of the hardware that stores the EFI variables, we need to find elegant ways to teach the kernel how to store those directly. The EFI requirement of an isolated flash is something that mostly came from the x86 world and is not a reality on the majority of embedded boards. I also think we should give up on Authenticated EFI variables in that case. We get zero guarantees unless the medium has similar properties to an RPMB. If a vendor cares about proper UEFI secure boot he can implement proper hardware.
2/ Create an RT variant for the FF-A APIs needed. These RT variant don't call the DM APIs (e.g: ffa_mm_communicate_runtime, ffa_sync_send_receive_runtime, ...)
What do you recommend please ?
...this is what I would recommend. Preferably in a way that refactors the code such that the low-level functionality is shared between the DM and non-DM APIs.
Yes. The only thing you need to keep alive is the machinery to talk to the secure world. The bus, flash driver etc should all be running isolated in there. In that case you can implement SetVariableRT as described the the EFI spec.
Cool, thanks. That's my preferred solution too.
mm_communicate() should be able to detect runtime mode so it calls ffa_mm_communicate_runtime().
Is there a way to check whether we are in EFI runtime or not ?
Relevant UEFI event groups for the transition to the OS are:
EFI_EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES EFI_EVENT_GROUP_EXIT_BOOT_SERVICES EFI_EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE
Once EFI_EVENT_GROUP_EXIT_BOOT_SERVICES is signaled you are at runtime.
Use CreateEventEx() to create an event for the group.
On top of that, we are already calling efi_variables_boot_exit_notify() based on those events. We could reuse that
Regards /Ilias
Best regards
Heinrich
Suggested changes (pseudo-code):
__efi_runtime mm_communicate () { #if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) if (RT) { /* NEW */ ret = ffa_mm_communicate_runtime(comm_buf, dsize); /* NEW */ } else { mm_comms = get_mm_comms(); if (mm_comms == MM_COMMS_FFA) ret = ffa_mm_communicate(comm_buf, dsize); else ret = optee_mm_communicate(comm_buf, dsize); } #else ... #endif
Existing code: https://github.com/u-boot/u-boot/blob/master/lib/efi_loader/efi_variable_tee...
A gentle reminder about the question above please (Is there a way to check whether we are in EFI runtime or not).
Cheers, Abdellatif

Hi Ilias, Heinrich
On Mon, Jan 08, 2024 at 04:35:59PM +0200, Ilias Apalodimas wrote:
On Mon, 8 Jan 2024 at 16:32, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 08.01.24 15:12, Abdellatif El Khlifi wrote:
Happy new year Ilias,
On Mon, Dec 18, 2023 at 04:59:09PM +0000, Abdellatif El Khlifi wrote:
Hi Ilias
On Thu, Dec 14, 2023 at 09:47:13PM +0200, Ilias Apalodimas wrote:
Hi Mark, Abdellatif
On Thu, 14 Dec 2023 at 18:47, Mark Kettenis mark.kettenis@xs4all.nl wrote:
> Date: Thu, 14 Dec 2023 15:53:46 +0000 > From: Abdellatif El Khlifi abdellatif.elkhlifi@arm.com
Hi Abdellatif,
> Hi guys, > > I'd like to ask for advice regarding adding EFI RT support to the Arm's FF-A bus > in U-Boot. > > The objective is to enable the FF-A messaging APIs in EFI RT to be > used for comms with the secure world. This will help getting/setting > EFI variables through FF-A. > > The existing FF-A APIs in U-Boot call the DM APIs (which are not available at RT). > > Two possible solutions: > > 1/ having the entire U-Boot in RT space (as Simon stated in this discussion[1])
I don't think this is a terribly good idea. With this approach orders of magnitude more code will be present in kernel address space one the OS kernel is running and calling into the EFI runtime. Including code that may access hardware devices that are now under OS control. It will be nigh impossible to audit all that code and make sure that only a safe subset of it gets called. So...
+100 I think we should draw a line here. I mentioned it on another thread, but I did a shot BoF in Plumbers discussing issues like this, problems, and potential solutions [0] [1]. Since that talk patches for the kernel that 'solve' the problem for RPMBs got pulled into linux-next [2].
I watched your talk. Great work, thanks :)
The TL;DR of that talk is that if the kernel ends up being in control of the hardware that stores the EFI variables, we need to find elegant ways to teach the kernel how to store those directly. The EFI requirement of an isolated flash is something that mostly came from the x86 world and is not a reality on the majority of embedded boards. I also think we should give up on Authenticated EFI variables in that case. We get zero guarantees unless the medium has similar properties to an RPMB. If a vendor cares about proper UEFI secure boot he can implement proper hardware.
> > 2/ Create an RT variant for the FF-A APIs needed. > These RT variant don't call the DM APIs > (e.g: ffa_mm_communicate_runtime, ffa_sync_send_receive_runtime, ...) > > What do you recommend please ?
...this is what I would recommend. Preferably in a way that refactors the code such that the low-level functionality is shared between the DM and non-DM APIs.
Yes. The only thing you need to keep alive is the machinery to talk to the secure world. The bus, flash driver etc should all be running isolated in there. In that case you can implement SetVariableRT as described the the EFI spec.
Cool, thanks. That's my preferred solution too.
mm_communicate() should be able to detect runtime mode so it calls ffa_mm_communicate_runtime().
Is there a way to check whether we are in EFI runtime or not ?
Relevant UEFI event groups for the transition to the OS are:
EFI_EVENT_GROUP_BEFORE_EXIT_BOOT_SERVICES EFI_EVENT_GROUP_EXIT_BOOT_SERVICES EFI_EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE
Once EFI_EVENT_GROUP_EXIT_BOOT_SERVICES is signaled you are at runtime.
Use CreateEventEx() to create an event for the group.
Thanks
On top of that, we are already calling efi_variables_boot_exit_notify() based on those events. We could reuse that
Currently efi_variables_boot_exit_notify() isn't located in the EFI section (__efi_runtime) as shown here [1].
Should we add __efi_runtime to the prototype ?
[1]: https://github.com/u-boot/u-boot/blob/master/lib/efi_loader/efi_variable_tee...
Cheers, Abdellatif

Hi Mark,
On Thu, Dec 14, 2023 at 05:47:42PM +0100, Mark Kettenis wrote:
Date: Thu, 14 Dec 2023 15:53:46 +0000 From: Abdellatif El Khlifi abdellatif.elkhlifi@arm.com
Hi Abdellatif,
Hi guys,
I'd like to ask for advice regarding adding EFI RT support to the Arm's FF-A bus in U-Boot.
The objective is to enable the FF-A messaging APIs in EFI RT to be used for comms with the secure world. This will help getting/setting EFI variables through FF-A.
The existing FF-A APIs in U-Boot call the DM APIs (which are not available at RT).
Two possible solutions:
1/ having the entire U-Boot in RT space (as Simon stated in this discussion[1])
I don't think this is a terribly good idea. With this approach orders of magnitude more code will be present in kernel address space one the OS kernel is running and calling into the EFI runtime. Including code that may access hardware devices that are now under OS control. It will be nigh impossible to audit all that code and make sure that only a safe subset of it gets called. So...
2/ Create an RT variant for the FF-A APIs needed. These RT variant don't call the DM APIs (e.g: ffa_mm_communicate_runtime, ffa_sync_send_receive_runtime, ...)
What do you recommend please ?
...this is what I would recommend. Preferably in a way that refactors the code such that the low-level functionality is shared between the DM and non-DM APIs.
That's my preferred solution, thanks.
Cheers, Abdellatif
participants (9)
-
Abdellatif El Khlifi
-
Heinrich Schuchardt
-
Ilias Apalodimas
-
Mark Kettenis
-
Michael Walle
-
Peter Robinson
-
Shantur Rathore
-
Simon Glass
-
Tom Rini