Julius, Simon,
It appears there are opinions you carry around UUID being complicated, bloated, code being an eyesore, parsing these lists early with MMU/Caches disabled, calculating checksums etc. While there is certainly a LOT of truth to those statements, these concerns need to be put into context and may not necessarily apply to all platforms running TF-A. Standardization and interoperability may be valued more on some platforms and some of the bloat and performance issues may be worth those tradeoffs. Some of these concerns may not even apply on powerful CPU’s and SoC’s with lots of memory. Also a quick grep for “uuid” in the TF-A repository shows that there is significant use of UUID’s for FIP, some SMC’s, secure partitions etc so use of UUID is not something new to TF-A.
While there are many ways to solve the same problem, there are also potential dis-advantages to something like the mechanism pointed out below. For example, this is yet another solution to an already solved problem. If we use UEFI hob’s, the code and problem has been solved for decades and there is code re-use possible and that *potentially*(opinions may vary) is better for security as there have been eyes on it for long and is more stable.(I’m very aware UEFI is not the gold standard for security, but again, it is a blanket statement to say all UEFI code is bad).
Does the method mentioned below allow you to create a dynamic list of arbitrary lengths and NOT lists of lengths decided at compile time? It appears that it is mainly being used on lists fixed at compile time.
What about interoperability with UEFI? Coreboot is great for platforms/companies that use it but what about platforms that *must* use UEFI for various reasons? Do we need a conversion from the method below to a UEFI HOB if BL33 is UEFI? Clearly the solution below was tailored to coreboot.
We can support multiple ways in the same code base through build and run time options and a platform should be free to make calls on whether the problems you mentioned below really apply or not. What is a pain to do(having co-ordination with multiple companies vs vendor defined tags/UUID’s) is also subjective and whether or not it is overstated is matter of opinion/context.
I think it may be best to discuss this in the call and understand the requirements fully. It may turn out that what you have proposed below works anyway 😊
Thanks
Raghu
From: TF-A tf-a-bounces@lists.trustedfirmware.org On Behalf Of Julius Werner via TF-A Sent: Wednesday, March 24, 2021 7:44 PM To: Simon Glass sjg@chromium.org Cc: Harb Abdulhamid OS abdulhamid@os.amperecomputing.com; Boot Architecture Mailman List boot-architecture@lists.linaro.org; tf-a@lists.trustedfirmware.org; U-Boot Mailing List u-boot@lists.denx.de; Paul Isaac's paul.isaacs@linaro.org; Ron Minnich rminnich@google.com Subject: Re: [TF-A] Proposal: TF-A to adopt hand-off blocks (HOBs) for information passing between boot stages
Just want to point out that TF-A currently already supports a (very simple) mechanism like this:
https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+...
https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+...
https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+...
It's just a linked list of tagged elements. The tag space is split into TF-A-wide generic tags and SiP-specific tags (with plenty of room to spare if more areas need to be defined -- a 64-bit tag can fit a lot). This is currently being used by some platforms that run coreboot in place of BL1/BL2, to pass information from coreboot (BL2) to BL31.
I would echo Simon's sentiment of keeping this as simple as possible and avoiding complicated and bloated data structures with UUIDs. You usually want to parse something like this as early as possible in the passed-to firmware stage, particularly if the structure encodes information about the debug console (like it does for the platforms I mentioned above). For example, in BL31 this basically means doing it right after moving from assembly to C in bl31_early_platform_setup2() to get the console up before running anything else. At that point in the BL31 initialization, the MMU and caches are disabled, so data accesses are pretty expensive and you don't want to spend a lot of parsing effort or calculate complicated checksums or the like. You just want something extremely simple where you ideally have to touch every data word only once.
On Wed, Mar 24, 2021 at 5:06 PM Simon Glass via TF-A <tf-a@lists.trustedfirmware.org mailto:tf-a@lists.trustedfirmware.org > wrote:
Hi Harb,
On Wed, 24 Mar 2021 at 11:39, Harb Abdulhamid OS <abdulhamid@os.amperecomputing.com mailto:abdulhamid@os.amperecomputing.com > wrote:
Hello Folks,
Appreciate the feedback and replies on this. Glad to see that there is interest in this topic. 😊
I try to address the comments/feedback from Francois and Simon below….
mailto:francois.ozog@linaro.org @François Ozog – happy to discuss this on a zoom call. I will make that time slot work, and will be available to attend April 8, 4pm CT.
Note that I’m using the term “HOB” here more generically, as there are typically vendor specific structures beyond the resource descriptor HOB, which provides only a small subset of the information that needs to be passed between the boot phases.
The whole point here is to provide mechanism to develop firmware that we can build ARM Server SoC’s that support *any* BL33 payload (e.g. EDK2, AptioV, CoreBoot, and maybe even directly boot strapping LinuxBoot at some point). In other-words, we are trying to come up with a TF-A that would be completely agnostic to the implementation of BL33 (i.e. BL33 is built completely independently by a separate entity – e.g. an ODM/OEM).
Keep in mind, in the server/datacenter market segment we are not building vertically integrated systems with a single entity compiling firmware/software stacks like most folks in TF-A have become use to. There are two categories of higher level firmware code blobs in the server/datacenter model:
1. “SoC” or “silicon” firmware – in TF-A this may map to BL1, BL2, BL31, and *possibly* one or more BL32 instances 2. “Platform” or “board” firmware – in TF-A this may map to BL33 and *possibly* one or more BL32 instances.
Even the platform firmware stack could be further fragmented by having multiple entities involved in delivering the entire firmware stack: IBVs, ODMs, OEMs, CSPs, and possibly even device vendor code.
To support a broad range of platform designs with a broad range of memory devices, we need a crisp and clear contract between the SoC firmware that initializes memory (e.g. BL2) and how that platform boot firmware (e.g. BL33) gathers information about what memory that was initialized, at what speeds, NUMA topology, and many other relevant information that needs to be known and comprehended by the platform firmware and eventually by the platform software.
I understand the versatility of DT, but I see two major problems with DT:
* DT requires more complicated parsing to get properties, and even more complex to dynamically set properties – this HOB structures may need to be generated in boot phases where DDR is not available, and therefore we will be extremely memory constrained. * DT is probably overkill for this purpose – We really just want a list of pointers to simple C structures that code cast (e.g. JEDEC SPD data blob)
I think that we should not mix the efforts around DT/ACPI specs with what we are doing here, because those specs and concepts were developed for a completely different purpose (i.e. abstractions needed for OS / RTOS software, and not necessarily suitable for firmware-to-firmware hand-offs).
Frankly, I would personally push back pretty hard on defining SMC’s for something that should be one way information passing. Every SMC we add is another attack vector to the secure world and an increased burden on the folks that have to do security auditing and threat analysis. I see no benefit in exposing these boot/HOB/BOB structures at run-time via SMC calls.
Please do let me know if you disagree and why. Look forward to discussing on this thread or on the call.
mailto:sjg@chromium.org @Simon Glass - Thanks for the pointer to bloblist. I briefly reviewed and it seems like a good baseline for what we may be looking for.
That being said, I would say that there is some benefit in having some kind of unique identifiers (e.g. UUID or some unique signature) so that we can tie standardized data structures (based on some future TBD specs) to a particular ID. For example, if the TPM driver in BL33 is looking for the TPM structure in the HOB/BOB list, and may not care about the other data blobs. The driver needs a way to identify and locate the blob it cares about.
The tag is intended to serve that purpose, although perhaps it should switch from an auto-allocating enum to one with explicit values for each entry and a range for 'local' use.
I guess we can achieve this with the tag, but the problem with tag when you have eco-system with a lot of parties doing parallel development, you can end up with tag collisions and folks fighting about who has rights to what tag values. We would need some official process for folks to register tags for whatever new structures we define, or maybe some tag range for vendor specific structures. This comes with a lot of pain and bureaucracy. On the other hand, UUID has been a proven way to make it easy to just define your own blobs with *either* standard or vendor specific structures without worry of ID collisions between vendors.
True. I think the pain is overstated, though. In this case I think we actually want something that can be shared between projects and orgs, so some amount of coordination could be considered a benefit. It could just be a github pull request. I find the UUID unfriendly and not just to code size and eyesight! Trying to discover what GUIDs mean or are valid is quite tricky. E.g. see this code:
#define FSP_HOB_RESOURCE_OWNER_TSEG_GUID \ EFI_GUID(0xd038747c, 0xd00c, 0x4980, \ 0xb3, 0x19, 0x49, 0x01, 0x99, 0xa4, 0x7d, 0x55)
(etc.)
static struct guid_name { efi_guid_t guid; const char *name; } guid_name[] = { { FSP_HOB_RESOURCE_OWNER_TSEG_GUID, "TSEG" }, { FSP_HOB_RESOURCE_OWNER_FSP_GUID, "FSP" }, { FSP_HOB_RESOURCE_OWNER_SMM_PEI_SMRAM_GUID, "SMM PEI SMRAM" }, { FSP_NON_VOLATILE_STORAGE_HOB_GUID, "NVS" }, { FSP_VARIABLE_NV_DATA_HOB_GUID, "Variable NVS" }, { FSP_GRAPHICS_INFO_HOB_GUID, "Graphics info" }, { FSP_HOB_RESOURCE_OWNER_PCD_DATABASE_GUID1, "PCD database ea" }, { FSP_HOB_RESOURCE_OWNER_PCD_DATABASE_GUID2, "PCD database 9b" },
(never figured out what those two are)
{ FSP_HOB_RESOURCE_OWNER_PEIM_DXE_GUID, "PEIM Init DXE" }, { FSP_HOB_RESOURCE_OWNER_ALLOC_STACK_GUID, "Alloc stack" }, { FSP_HOB_RESOURCE_OWNER_SMBIOS_MEMORY_GUID, "SMBIOS memory" }, { {}, "zero-guid" }, {} };
static const char *guid_to_name(const efi_guid_t *guid) { struct guid_name *entry;
for (entry = guid_name; entry->name; entry++) { if (!guidcmp(guid, &entry->guid)) return entry->name; }
return NULL; }
Believe it or not it took a fair bit of effort to find just that small list, with nearly every one in a separate doc, from memory.
We can probably debate whether there is any value in GUID/UUID or not during the call… but again, boblist seems like a reasonable starting point as an alternative to HOB.
Indeed. There is certainly value in both approaches.
Regards,
Simon
Thanks,
--Harb
From: François Ozog <francois.ozog@linaro.org mailto:francois.ozog@linaro.org > Sent: Tuesday, March 23, 2021 10:00 AM To: François Ozog <francois.ozog@linaro.org mailto:francois.ozog@linaro.org >; Ron Minnich <rminnich@google.com mailto:rminnich@google.com >; Paul Isaac's <paul.isaacs@linaro.org mailto:paul.isaacs@linaro.org > Cc: Simon Glass <sjg@chromium.org mailto:sjg@chromium.org >; Harb Abdulhamid OS <abdulhamid@os.amperecomputing.com mailto:abdulhamid@os.amperecomputing.com >; Boot Architecture Mailman List <boot-architecture@lists.linaro.org mailto:boot-architecture@lists.linaro.org >; tf-a@lists.trustedfirmware.org mailto:tf-a@lists.trustedfirmware.org Subject: Re: [TF-A] Proposal: TF-A to adopt hand-off blocks (HOBs) for information passing between boot stages
+Ron Minnich mailto:rminnich@google.com +Paul Isaac's mailto:paul.isaacs@linaro.org
Adding Ron and Paul because I think this interface should be also benefiting LinuxBoot efforts.
On Tue, 23 Mar 2021 at 11:17, François Ozog via TF-A <tf-a@lists.trustedfirmware.org mailto:tf-a@lists.trustedfirmware.org > wrote:
Hi,
I propose we cover the topic at the next Trusted Substrate https://collaborate.linaro.org/display/TS/Trusted+Substrate+Home zoom call https://linaro-org.zoom.us/j/94563644892 on April 8th 4pm CET.
The agenda:
ABI between non-secure firmware and the rest of firmware (EL3, S-EL1, S-EL2, SCP) to adapt hardware description to some runtime conditions.
runtime conditions here relates to DRAM size and topology detection, secure DRAM memory carvings, PSCI and SCMI interface publishing.
For additional background on existing metadata: https://uefi.org/sites/default/files/resources/PI_Spec_1_7_final_Jan_2019.pdf UEFI Platform Initialization Specification Version 1.7, 5.5 Resource Descriptor HOB
Out of the ResourceType we care about is EFI_RESOURCE_SYSTEM_MEMORY.
This HOB lacks memory NUMA attachment or something that could be related to fill SRAT table for ACPI or relevant DT proximity domains.
HOB is not consistent accros platforms: some platforms (Arm) lists memory from the booting NUMA node, other platforms (x86) lists all memory from all NUMA nodes. (At least this is the case on the two platforms I tested).
There are two proposals to use memory structures from SPL/BLx up to the handover function (as defined in the Device Tree technical report https://docs.google.com/document/d/1CLkhLRaz_zcCq44DLGmPZQFPbYHOC6nzPowaL0XmRk0/edit?usp=sharing ) which can be U-boot (BL33 or just U-Boot in case of SPL/U-Boot scheme) or EDK2.
I would propose we also discuss possibility of FF-A interface to actually query information or request actions to be done (this is a model actually used in some SoCs with proprietary SMC calls).
Requirements (to be validated):
- ACPI and DT hardware descriptions.
- agnostic to boot framework (SPL/U-Boot, TF-A/U-Boot, TF-A/EDK2)
- agnostic to boot framework (SPL/U-Boot, TF-A/U-Boot, TF-A/EDK2, TF-A/LinuxBoot)
- at least allows complete DRAM description and "persistent" usage (reserved areas for secure world or other usages)
- support secure world device assignment
Cheers
FF
On Mon, 22 Mar 2021 at 19:56, Simon Glass <sjg@chromium.org mailto:sjg@chromium.org > wrote:
Hi,
Can I suggest using bloblist for this instead? It is lightweight, easier to parse, doesn't have GUIDs and is already used within U-Boot for passing info between SPL/U-Boot, etc.
Docs here: https://github.com/u-boot/u-boot/blob/master/doc/README.bloblist Header file describes the format: https://github.com/u-boot/u-boot/blob/master/include/bloblist.h
Full set of unit tests: https://github.com/u-boot/u-boot/blob/master/test/bloblist.c
Regards, Simon
On Mon, 22 Mar 2021 at 23:58, François Ozog <francois.ozog@linaro.org mailto:francois.ozog@linaro.org > wrote:
+Boot Architecture Mailman List <boot-architecture@lists.linaro.org mailto:boot-architecture@lists.linaro.org >
standardization is very much welcomed here and need to accommodate a very diverse set of situations. For example, TEE OS may need to pass memory reservations to BL33 or "capture" a device for the secure world.
I have observed a number of architectures:
- pass information from BLx to BLy in the form of a specific object
- BLx called by BLy by a platform specific SMC to get information
- BLx called by BLy by a platform specific SMC to perform Device Tree
fixups
I also imagined a standardized "broadcast" FF-A call so that any firmware element can either provide information or "do something".
My understanding of your proposal is about standardizing on architecture 1) with the HOB format.
The advantage of the HOB is simplicity but it may be difficult to implement schemes such as pruning a DT because device assignment in the secure world.
In any case, it looks feasible to have TF-A and OP-TEE complement the list of HOBs to pass information downstream (the bootflow).
It would be good to start with building the comprehensive list of information that need to be conveyed between firmware elements:
information. | authoritative entity | reporting entity | information exchanged: dram | TFA | TFA | <format to be detailed, NUMA topology to build the SRAT table or DT equivalent?> PSCI | SCP | TFA? | SCMI | SCP or TEE-OS | TFA? TEE-OS?| secure SRAM | TFA. | TFA. | secure DRAM | TFA? TEE-OS? | TFA? TEE-OS? | other? | | |
Cheers
FF
On Mon, 22 Mar 2021 at 09:34, Harb Abdulhamid OS via TF-A < tf-a@lists.trustedfirmware.org mailto:tf-a@lists.trustedfirmware.org > wrote:
Hello Folks,
I'm emailing to start an open discussion about the adoption of a concept known as "hand-off blocks" or HOB to become a part of the TF-A Firmware Framework Architecture (FFA). This is something that is a pretty major pain point when it comes to the adoption of TF-A in ARM Server SoC’s designed to enable a broad range of highly configurable datacenter platforms.
What is a HOB (Background)?
UEFI PI spec describes a particular definition for how HOB may be used for transitioning between the PEI and DXE boot phases, which is a good reference point for this discussion, but not necessarily the exact solution appropriate for TF-A.
A HOB is simply a dynamically generated data structure passed in between two boot phases. This is information that was obtained through discovery and needs to be passed forward to the next boot phase *once*, with no API needed to call back (e.g. no call back into previous firmware phase is needed to fetch this information at run-time - it is simply passed one time during boot).
There may be one or more HOBs passed in between boot phases. If there are more than one HOB that needs to be passed, this can be in a form of a "HOB table", which (for example) could be a UUID indexed array of pointers to HOB structures, used to locate a HOB of interest (based on UUID). In such cases, instead of passing a single HOB, the boot phases may rely on passing the pointer to the HOB table.
This has been extremely useful concept to employ on highly configurable systems that must rely on flexible discovery mechanisms to initialize and boot the system. This is especially helpful when you have multiple
Why do we need HOBs in TF-A?:
It is desirable that EL3 firmware (e.g. TF-A) built for ARM Server SoC in a way that is SoC specific *but* platform agnostic. This means that a single ARM SoC that a SiP may deliver to customers may provide a single TF-A binary (e.g. BL1, BL2, BL31) that could be used to support a broad range of platform designs and configurations in order to boot a platform specific firmware (e.g. BL33 and possibly even BL32 code). In order to achieve this, the platform configuration must be *discovered* instead of statically compiled as it is today in TF-A via device tree based enumeration. The mechanisms of discovery may differ broadly depending on the relevant industry standard, or in some cases may have rely on SiP specific discovery flows.
For example: On server systems that support a broad range DIMM memory population/topologies, all the necessary information required to boot is fully discovered via standard JEDEC Serial Presence Detect (SPD) over an I2C bus. Leveraging the SPD bus, may platform variants could be supported with a single TF-A binary. Not only is this information required to initialize memory in early boot phases (e.g. BL2), the subsequent boot phases will also need this SPD info to construct a system physical address map and properly initialize the MMU based on the memory present, and where the memory may be present. Subsequent boot phases (e.g. BL33 / UEFI) may need to generate standard firmware tables to the operating systems, such as SMBIOS tables describing DIMM topology and various ACPI tables (e.g. SLIT, SRAT, even NFIT if NVDIMM's are present).
In short, it all starts with a standardized or vendor specific discovery flow in an early boot stage (e.g. BL1/BL2), followed by the passing of information to the next boot stages (e.g. BL31/BL32/BL33).
Today, every HOB may be a vendor specific structure, but in the future there may be benefit of defining standard HOBs. This may be useful for memory discovery, passing the system physical address map, enabling TPM measured boot, and potentially many other common HOB use-cases.
It would be extremely beneficial to the datacenter market segment if the TF-A community would adopt this concept of information passing between all boot phases as opposed to rely solely on device tree enumeration. This is not intended to replace device tree, rather intended as an alternative way to describe the info that must be discovered and dynamically generated.
Conclusion:
We are proposing that the TF-A community begin pursuing the adoption of HOBs as a mechanism used for information exchange between each boot stage (e.g. BL1->BL2, BL2->BL31, BL31->BL32, and BL31->BL33)? Longer term we want to explore standardizing some HOB structures for the BL33 phase (e.g. UEFI HOB structures), but initially would like to agree on this being a useful mechanism used to pass information between each boot stage.
Thanks,
--Harb
-- TF-A mailing list TF-A@lists.trustedfirmware.org mailto:TF-A@lists.trustedfirmware.org https://lists.trustedfirmware.org/mailman/listinfo/tf-a
-- François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org mailto:francois.ozog@linaro.org | Skype: ffozog _______________________________________________ boot-architecture mailing list boot-architecture@lists.linaro.org mailto:boot-architecture@lists.linaro.org https://lists.linaro.org/mailman/listinfo/boot-architecture
Hi Raghu,
On Sat, 27 Mar 2021 at 03:59, raghu.ncstate@icloud.com wrote:
Julius, Simon,
It appears there are opinions you carry around UUID being complicated, bloated, code being an eyesore, parsing these lists early with MMU/Caches disabled, calculating checksums etc. While there is certainly a LOT of truth to those statements, these concerns need to be put into context and may not necessarily apply to all platforms running TF-A. Standardization and interoperability may be valued more on some platforms and some of the bloat and performance issues may be worth those tradeoffs. Some of these concerns may not even apply on powerful CPU’s and SoC’s with lots of memory. Also a quick grep for “uuid” in the TF-A repository shows that there is significant use of UUID’s for FIP, some SMC’s, secure partitions etc so use of UUID is not something new to TF-A.
Fair enough. I hope, though, that if we can agree on a simple implementation like bloblist, then it becomes the standard and we can move away from the problems you mention with UUIDs.
I do find it odd, but even the latest SoCs often seem to start up in a mode with limited memory and not at full speed. I also find that many projects don't care a whit about boot speed, but others care a lot.
While there are many ways to solve the same problem, there are also potential dis-advantages to something like the mechanism pointed out below. For example, this is yet another solution to an already solved problem. If we use UEFI hob’s, the code and problem has been solved for decades and there is code re-use possible and that **potentially**(opinions may vary) is better for security as there have been eyes on it for long and is more stable.(I’m very aware UEFI is not the gold standard for security, but again, it is a blanket statement to say all UEFI code is bad).
I've not looked at UEFI code recently...I think it was 6 years ago. It really was not something I wondered to get involved in. I suspect it has improved a lot. The HOB data structure is not that complicated (apart from the UUIDs) and not all that different to bloblist. But turning it around, wouldn't you prefer to use some simple code that is easy to read and has a good set of unit tests?
Does the method mentioned below allow you to create a dynamic list of arbitrary lengths and NOT lists of lengths decided at compile time? It appears that it is mainly being used on lists fixed at compile time.
Well the API does allow any length to be created:
void *bloblist_add(uint tag, int size, int align);
Typically the data structures are defined across boundaries though, such that (e.g.) a C struct is shared. I suppose the length might change if you are passing a console log.
What about interoperability with UEFI? Coreboot is great for platforms/companies that use it but what about platforms that **must** use UEFI for various reasons? Do we need a conversion from the method below to a UEFI HOB if BL33 is UEFI? Clearly the solution below was tailored to coreboot.
Turning that around, must all open-source platforms use UEFI features, APIs, data structures, etc? It could be useful for UEFI to learn a bit about interoperability and fit in with some of the open-source solutions. BTW the bloblist is actually a U-Boot thing, although yes indeed it is inspired by open-source.
We can support multiple ways in the same code base through build and run time options and a platform should be free to make calls on whether the problems you mentioned below really apply or not. What is a pain to do(having co-ordination with multiple companies vs vendor defined tags/UUID’s) is also subjective and whether or not it is overstated is matter of opinion/context.
I think it may be best to discuss this in the call and understand the requirements fully. It may turn out that what you have proposed below works anyway 😊
Yes OK. I am not sure I can attend tomorrow's call, but we'll see.
Regards, Simon
Thanks
Raghu
*From:* TF-A tf-a-bounces@lists.trustedfirmware.org *On Behalf Of *Julius Werner via TF-A *Sent:* Wednesday, March 24, 2021 7:44 PM *To:* Simon Glass sjg@chromium.org *Cc:* Harb Abdulhamid OS abdulhamid@os.amperecomputing.com; Boot Architecture Mailman List boot-architecture@lists.linaro.org; tf-a@lists.trustedfirmware.org; U-Boot Mailing List u-boot@lists.denx.de; Paul Isaac's paul.isaacs@linaro.org; Ron Minnich rminnich@google.com *Subject:* Re: [TF-A] Proposal: TF-A to adopt hand-off blocks (HOBs) for information passing between boot stages
Just want to point out that TF-A currently already supports a (very simple) mechanism like this:
https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+...
https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+...
https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+...
It's just a linked list of tagged elements. The tag space is split into TF-A-wide generic tags and SiP-specific tags (with plenty of room to spare if more areas need to be defined -- a 64-bit tag can fit a lot). This is currently being used by some platforms that run coreboot in place of BL1/BL2, to pass information from coreboot (BL2) to BL31.
I would echo Simon's sentiment of keeping this as simple as possible and avoiding complicated and bloated data structures with UUIDs. You usually want to parse something like this as early as possible in the passed-to firmware stage, particularly if the structure encodes information about the debug console (like it does for the platforms I mentioned above). For example, in BL31 this basically means doing it right after moving from assembly to C in bl31_early_platform_setup2() to get the console up before running anything else. At that point in the BL31 initialization, the MMU and caches are disabled, so data accesses are pretty expensive and you don't want to spend a lot of parsing effort or calculate complicated checksums or the like. You just want something extremely simple where you ideally have to touch every data word only once.
On Wed, Mar 24, 2021 at 5:06 PM Simon Glass via TF-A < tf-a@lists.trustedfirmware.org> wrote:
Hi Harb,
On Wed, 24 Mar 2021 at 11:39, Harb Abdulhamid OS < abdulhamid@os.amperecomputing.com> wrote:
Hello Folks,
Appreciate the feedback and replies on this. Glad to see that there is interest in this topic. 😊
I try to address the comments/feedback from Francois and Simon below….
@François Ozog francois.ozog@linaro.org – happy to discuss this on a zoom call. I will make that time slot work, and will be available to attend April 8, 4pm CT.
Note that I’m using the term “HOB” here more generically, as there are typically vendor specific structures beyond the resource descriptor HOB, which provides only a small subset of the information that needs to be passed between the boot phases.
The whole point here is to provide mechanism to develop firmware that we can build ARM Server SoC’s that support **any** BL33 payload (e.g. EDK2, AptioV, CoreBoot, and maybe even directly boot strapping LinuxBoot at some point). In other-words, we are trying to come up with a TF-A that would be completely agnostic to the implementation of BL33 (i.e. BL33 is built completely independently by a separate entity – e.g. an ODM/OEM).
Keep in mind, in the server/datacenter market segment we are not building vertically integrated systems with a single entity compiling firmware/software stacks like most folks in TF-A have become use to. There are two categories of higher level firmware code blobs in the server/datacenter model:
- “SoC” or “silicon” firmware – in TF-A this may map to BL1, BL2,
BL31, and **possibly** one or more BL32 instances 2. “Platform” or “board” firmware – in TF-A this may map to BL33 and * *possibly** one or more BL32 instances.
Even the platform firmware stack could be further fragmented by having multiple entities involved in delivering the entire firmware stack: IBVs, ODMs, OEMs, CSPs, and possibly even device vendor code.
To support a broad range of platform designs with a broad range of memory devices, we need a crisp and clear contract between the SoC firmware that initializes memory (e.g. BL2) and how that platform boot firmware (e.g. BL33) gathers information about what memory that was initialized, at what speeds, NUMA topology, and many other relevant information that needs to be known and comprehended by the platform firmware and eventually by the platform software.
I understand the versatility of DT, but I see two major problems with DT:
- DT requires more complicated parsing to get properties, and even
more complex to dynamically set properties – this HOB structures may need to be generated in boot phases where DDR is not available, and therefore we will be extremely memory constrained.
- DT is probably overkill for this purpose – We really just want a
list of pointers to simple C structures that code cast (e.g. JEDEC SPD data blob)
I think that we should not mix the efforts around DT/ACPI specs with what we are doing here, because those specs and concepts were developed for a completely different purpose (i.e. abstractions needed for OS / RTOS software, and not necessarily suitable for firmware-to-firmware hand-offs).
Frankly, I would personally push back pretty hard on defining SMC’s for something that should be one way information passing. Every SMC we add is another attack vector to the secure world and an increased burden on the folks that have to do security auditing and threat analysis. I see no benefit in exposing these boot/HOB/BOB structures at run-time via SMC calls.
Please do let me know if you disagree and why. Look forward to discussing on this thread or on the call.
@Simon Glass sjg@chromium.org - Thanks for the pointer to bloblist. I briefly reviewed and it seems like a good baseline for what we may be looking for.
That being said, I would say that there is some benefit in having some kind of unique identifiers (e.g. UUID or some unique signature) so that we can tie standardized data structures (based on some future TBD specs) to a particular ID. For example, if the TPM driver in BL33 is looking for the TPM structure in the HOB/BOB list, and may not care about the other data blobs. The driver needs a way to identify and locate the blob it cares about.
The tag is intended to serve that purpose, although perhaps it should switch from an auto-allocating enum to one with explicit values for each entry and a range for 'local' use.
I guess we can achieve this with the tag, but the problem with tag when you have eco-system with a lot of parties doing parallel development, you can end up with tag collisions and folks fighting about who has rights to what tag values. We would need some official process for folks to register tags for whatever new structures we define, or maybe some tag range for vendor specific structures. This comes with a lot of pain and bureaucracy. On the other hand, UUID has been a proven way to make it easy to just define your own blobs with **either** standard or vendor specific structures without worry of ID collisions between vendors.
True. I think the pain is overstated, though. In this case I think we actually want something that can be shared between projects and orgs, so some amount of coordination could be considered a benefit. It could just be a github pull request. I find the UUID unfriendly and not just to code size and eyesight! Trying to discover what GUIDs mean or are valid is quite tricky. E.g. see this code:
#define FSP_HOB_RESOURCE_OWNER_TSEG_GUID \ EFI_GUID(0xd038747c, 0xd00c, 0x4980, \ 0xb3, 0x19, 0x49, 0x01, 0x99, 0xa4, 0x7d, 0x55)
(etc.)
static struct guid_name { efi_guid_t guid; const char *name; } guid_name[] = { { FSP_HOB_RESOURCE_OWNER_TSEG_GUID, "TSEG" }, { FSP_HOB_RESOURCE_OWNER_FSP_GUID, "FSP" }, { FSP_HOB_RESOURCE_OWNER_SMM_PEI_SMRAM_GUID, "SMM PEI SMRAM" }, { FSP_NON_VOLATILE_STORAGE_HOB_GUID, "NVS" }, { FSP_VARIABLE_NV_DATA_HOB_GUID, "Variable NVS" }, { FSP_GRAPHICS_INFO_HOB_GUID, "Graphics info" }, { FSP_HOB_RESOURCE_OWNER_PCD_DATABASE_GUID1, "PCD database ea" }, { FSP_HOB_RESOURCE_OWNER_PCD_DATABASE_GUID2, "PCD database 9b" },
(never figured out what those two are)
{ FSP_HOB_RESOURCE_OWNER_PEIM_DXE_GUID, "PEIM Init DXE" }, { FSP_HOB_RESOURCE_OWNER_ALLOC_STACK_GUID, "Alloc stack" }, { FSP_HOB_RESOURCE_OWNER_SMBIOS_MEMORY_GUID, "SMBIOS memory" }, { {}, "zero-guid" }, {} };
static const char *guid_to_name(const efi_guid_t *guid) { struct guid_name *entry;
for (entry = guid_name; entry->name; entry++) { if (!guidcmp(guid, &entry->guid)) return entry->name; }
return NULL; }
Believe it or not it took a fair bit of effort to find just that small list, with nearly every one in a separate doc, from memory.
We can probably debate whether there is any value in GUID/UUID or not during the call… but again, boblist seems like a reasonable starting point as an alternative to HOB.
Indeed. There is certainly value in both approaches.
Regards,
Simon
Thanks,
--Harb
*From:* François Ozog francois.ozog@linaro.org *Sent:* Tuesday, March 23, 2021 10:00 AM *To:* François Ozog francois.ozog@linaro.org; Ron Minnich < rminnich@google.com>; Paul Isaac's paul.isaacs@linaro.org *Cc:* Simon Glass sjg@chromium.org; Harb Abdulhamid OS < abdulhamid@os.amperecomputing.com>; Boot Architecture Mailman List < boot-architecture@lists.linaro.org>; tf-a@lists.trustedfirmware.org *Subject:* Re: [TF-A] Proposal: TF-A to adopt hand-off blocks (HOBs) for information passing between boot stages
+Ron Minnich rminnich@google.com +Paul Isaac's paul.isaacs@linaro.org
Adding Ron and Paul because I think this interface should be also benefiting LinuxBoot efforts.
On Tue, 23 Mar 2021 at 11:17, François Ozog via TF-A < tf-a@lists.trustedfirmware.org> wrote:
Hi,
I propose we cover the topic at the next Trusted Substrate https://collaborate.linaro.org/display/TS/Trusted+Substrate+Home zoom call https://linaro-org.zoom.us/j/94563644892 on April 8th 4pm CET.
The agenda:
ABI between non-secure firmware and the rest of firmware (EL3, S-EL1, S-EL2, SCP) to adapt hardware description to some runtime conditions.
runtime conditions here relates to DRAM size and topology detection, secure DRAM memory carvings, PSCI and SCMI interface publishing.
For additional background on existing metadata: UEFI Platform Initialization Specification Version 1.7 https://uefi.org/sites/default/files/resources/PI_Spec_1_7_final_Jan_2019.pdf , 5.5 Resource Descriptor HOB
Out of the ResourceType we care about is EFI_RESOURCE_SYSTEM_MEMORY.
This HOB lacks memory NUMA attachment or something that could be related to fill SRAT table for ACPI or relevant DT proximity domains.
HOB is not consistent accros platforms: some platforms (Arm) lists memory from the booting NUMA node, other platforms (x86) lists all memory from all NUMA nodes. (At least this is the case on the two platforms I tested).
There are two proposals to use memory structures from SPL/BLx up to the handover function (as defined in the Device Tree technical report https://docs.google.com/document/d/1CLkhLRaz_zcCq44DLGmPZQFPbYHOC6nzPowaL0XmRk0/edit?usp=sharing) which can be U-boot (BL33 or just U-Boot in case of SPL/U-Boot scheme) or EDK2.
I would propose we also discuss possibility of FF-A interface to actually query information or request actions to be done (this is a model actually used in some SoCs with proprietary SMC calls).
Requirements (to be validated):
ACPI and DT hardware descriptions.
agnostic to boot framework (SPL/U-Boot, TF-A/U-Boot, TF-A/EDK2)
agnostic to boot framework (SPL/U-Boot, TF-A/U-Boot, TF-A/EDK2,
TF-A/LinuxBoot)
- at least allows complete DRAM description and "persistent" usage
(reserved areas for secure world or other usages)
- support secure world device assignment
Cheers
FF
On Mon, 22 Mar 2021 at 19:56, Simon Glass sjg@chromium.org wrote:
Hi,
Can I suggest using bloblist for this instead? It is lightweight, easier to parse, doesn't have GUIDs and is already used within U-Boot for passing info between SPL/U-Boot, etc.
Docs here: https://github.com/u-boot/u-boot/blob/master/doc/README.bloblist Header file describes the format: https://github.com/u-boot/u-boot/blob/master/include/bloblist.h
Full set of unit tests: https://github.com/u-boot/u-boot/blob/master/test/bloblist.c
Regards, Simon
On Mon, 22 Mar 2021 at 23:58, François Ozog francois.ozog@linaro.org wrote:
+Boot Architecture Mailman List boot-architecture@lists.linaro.org
standardization is very much welcomed here and need to accommodate a very diverse set of situations. For example, TEE OS may need to pass memory reservations to BL33 or "capture" a device for the secure world.
I have observed a number of architectures:
- pass information from BLx to BLy in the form of a specific object
- BLx called by BLy by a platform specific SMC to get information
- BLx called by BLy by a platform specific SMC to perform Device Tree
fixups
I also imagined a standardized "broadcast" FF-A call so that any firmware element can either provide information or "do something".
My understanding of your proposal is about standardizing on architecture
with the HOB format.
The advantage of the HOB is simplicity but it may be difficult to
implement
schemes such as pruning a DT because device assignment in the secure
world.
In any case, it looks feasible to have TF-A and OP-TEE complement the
list
of HOBs to pass information downstream (the bootflow).
It would be good to start with building the comprehensive list of information that need to be conveyed between firmware elements:
information. | authoritative entity | reporting entity | information exchanged: dram | TFA | TFA | <format to be detailed, NUMA topology to build the SRAT table or DT equivalent?> PSCI | SCP | TFA? | SCMI | SCP or TEE-OS | TFA? TEE-OS?| secure SRAM | TFA. | TFA. | secure DRAM | TFA? TEE-OS? | TFA? TEE-OS? | other? | | |
Cheers
FF
On Mon, 22 Mar 2021 at 09:34, Harb Abdulhamid OS via TF-A < tf-a@lists.trustedfirmware.org> wrote:
Hello Folks,
I'm emailing to start an open discussion about the adoption of a
concept
known as "hand-off blocks" or HOB to become a part of the TF-A Firmware Framework Architecture (FFA). This is something that is a pretty major pain point when it comes to the adoption of TF-A in ARM Server SoC’s designed to enable a broad range of highly configurable datacenter platforms.
What is a HOB (Background)?
UEFI PI spec describes a particular definition for how HOB may be used
for
transitioning between the PEI and DXE boot phases, which is a good reference point for this discussion, but not necessarily the exact
solution
appropriate for TF-A.
A HOB is simply a dynamically generated data structure passed in
between
two boot phases. This is information that was obtained through
discovery
and needs to be passed forward to the next boot phase *once*, with no
API
needed to call back (e.g. no call back into previous firmware phase is needed to fetch this information at run-time - it is simply passed one
time
during boot).
There may be one or more HOBs passed in between boot phases. If there
are
more than one HOB that needs to be passed, this can be in a form of a
"HOB
table", which (for example) could be a UUID indexed array of pointers
to
HOB structures, used to locate a HOB of interest (based on UUID). In
such
cases, instead of passing a single HOB, the boot phases may rely on
passing
the pointer to the HOB table.
This has been extremely useful concept to employ on highly configurable systems that must rely on flexible discovery mechanisms to initialize
and
boot the system. This is especially helpful when you have multiple
Why do we need HOBs in TF-A?:
It is desirable that EL3 firmware (e.g. TF-A) built for ARM Server SoC
in
a way that is SoC specific *but* platform agnostic. This means that a single ARM SoC that a SiP may deliver to customers may provide a single TF-A binary (e.g. BL1, BL2, BL31) that could be used to support a broad range of platform designs and configurations in order to boot a
platform
specific firmware (e.g. BL33 and possibly even BL32 code). In order to achieve this, the platform configuration must be *discovered* instead
of
statically compiled as it is today in TF-A via device tree based enumeration. The mechanisms of discovery may differ broadly depending
on
the relevant industry standard, or in some cases may have rely on SiP specific discovery flows.
For example: On server systems that support a broad range DIMM memory population/topologies, all the necessary information required to boot
is
fully discovered via standard JEDEC Serial Presence Detect (SPD) over
an
I2C bus. Leveraging the SPD bus, may platform variants could be
supported
with a single TF-A binary. Not only is this information required to initialize memory in early boot phases (e.g. BL2), the subsequent boot phases will also need this SPD info to construct a system physical
address
map and properly initialize the MMU based on the memory present, and
where
the memory may be present. Subsequent boot phases (e.g. BL33 / UEFI)
may
need to generate standard firmware tables to the operating systems,
such as
SMBIOS tables describing DIMM topology and various ACPI tables (e.g.
SLIT,
SRAT, even NFIT if NVDIMM's are present).
In short, it all starts with a standardized or vendor specific
discovery
flow in an early boot stage (e.g. BL1/BL2), followed by the passing of information to the next boot stages (e.g. BL31/BL32/BL33).
Today, every HOB may be a vendor specific structure, but in the future there may be benefit of defining standard HOBs. This may be useful for memory discovery, passing the system physical address map, enabling TPM measured boot, and potentially many other common HOB use-cases.
It would be extremely beneficial to the datacenter market segment if
the
TF-A community would adopt this concept of information passing between
all
boot phases as opposed to rely solely on device tree enumeration.
This is
not intended to replace device tree, rather intended as an alternative
way
to describe the info that must be discovered and dynamically generated.
Conclusion:
We are proposing that the TF-A community begin pursuing the adoption of HOBs as a mechanism used for information exchange between each boot
stage
(e.g. BL1->BL2, BL2->BL31, BL31->BL32, and BL31->BL33)? Longer term we want to explore standardizing some HOB structures for the BL33 phase
(e.g.
UEFI HOB structures), but initially would like to agree on this being a useful mechanism used to pass information between each boot stage.
Thanks,
--Harb
-- TF-A mailing list TF-A@lists.trustedfirmware.org https://lists.trustedfirmware.org/mailman/listinfo/tf-a
-- François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog _______________________________________________ boot-architecture mailing list boot-architecture@lists.linaro.org https://lists.linaro.org/mailman/listinfo/boot-architecture
--
*François-Frédéric Ozog* | *Director Linaro Edge & Fog Computing Group*
T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog
-- TF-A mailing list TF-A@lists.trustedfirmware.org https://lists.trustedfirmware.org/mailman/listinfo/tf-a
--
*François-Frédéric Ozog* | *Director Linaro Edge & Fog Computing Group*
T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog
-- TF-A mailing list TF-A@lists.trustedfirmware.org https://lists.trustedfirmware.org/mailman/listinfo/tf-a
On 29/03/2021 08:42, Simon Glass wrote:
Hi Raghu,
On Sat, 27 Mar 2021 at 03:59, raghu.ncstate@icloud.com wrote:
Julius, Simon,
It appears there are opinions you carry around UUID being complicated, bloated, code being an eyesore, parsing these lists early with
MMU/Caches
disabled, calculating checksums etc. While there is certainly a LOT of truth to those statements, these concerns need to be put into
context and
may not necessarily apply to all platforms running TF-A. Standardization and interoperability may be valued more on some platforms and some
of the
bloat and performance issues may be worth those tradeoffs. Some of these concerns may not even apply on powerful CPU’s and SoC’s with lots of memory. Also a quick grep for “uuid” in the TF-A repository shows that there is significant use of UUID’s for FIP, some SMC’s, secure
partitions
etc so use of UUID is not something new to TF-A.
Fair enough. I hope, though, that if we can agree on a simple implementation like bloblist, then it becomes the standard and we can
move
away from the problems you mention with UUIDs.
Ummm... I don't follow. How are UUIDs either complex or bloated? A UUIDs is simply a 128 bit number that is matched using a fixed length compare.
What I like about the UUID scheme is it has collision avoidance built in, and it is adopted across multiple projects.
g. IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
Hi Grant, On Mon, 29 Mar 2021 at 23:19, Grant Likely grant.likely@arm.com wrote:
On 29/03/2021 08:42, Simon Glass wrote:
Hi Raghu,
On Sat, 27 Mar 2021 at 03:59, raghu.ncstate@icloud.com wrote:
Julius, Simon,
It appears there are opinions you carry around UUID being complicated, bloated, code being an eyesore, parsing these lists early with
MMU/Caches
disabled, calculating checksums etc. While there is certainly a LOT of truth to those statements, these concerns need to be put into
context and
may not necessarily apply to all platforms running TF-A. Standardization and interoperability may be valued more on some platforms and some
of the
bloat and performance issues may be worth those tradeoffs. Some of these concerns may not even apply on powerful CPU’s and SoC’s with lots of memory. Also a quick grep for “uuid” in the TF-A repository shows that there is significant use of UUID’s for FIP, some SMC’s, secure
partitions
etc so use of UUID is not something new to TF-A.
Fair enough. I hope, though, that if we can agree on a simple implementation like bloblist, then it becomes the standard and we can
move
away from the problems you mention with UUIDs.
Ummm... I don't follow. How are UUIDs either complex or bloated? A UUIDs is simply a 128 bit number that is matched using a fixed length compare.
What I like about the UUID scheme is it has collision avoidance built in, and it is adopted across multiple projects.
It's partly the UUIDs and partly the code that results (see earlier in thread). But this is off-topic really, so I won't continue here.
- Simon
Hi Raghu,
It appears there are opinions you carry around UUID being complicated, bloated, code being an eyesore, parsing these lists early with MMU/Caches disabled, calculating checksums etc. While there is certainly a LOT of truth to those statements, these concerns need to be put into context and may not necessarily apply to all platforms running TF-A. Standardization and interoperability may be valued more on some platforms and some of the bloat and performance issues may be worth those tradeoffs. Some of these concerns may not even apply on powerful CPU’s and SoC’s with lots of memory. Also a quick grep for “uuid” in the TF-A repository shows that there is significant use of UUID’s for FIP, some SMC’s, secure partitions etc so use of UUID is not something new to TF-A.
Granted, I understand that different platforms have different requirements, and there may not be a one-size-fits-all solution for this. But if you have a system with a powerful CPU and lots of memory that doesn't care that much about boot speed, why wouldn't you just use FDT? I thought FDT is already established on many platforms to pass information between TF-A boot stages today, and it should certainly be flexible enough to fill your needs. Most of the earlier discussion in this thread seemed to focus on people wanting a different mechanism besides FDT because FDT is complex and not performant enough for all use cases, but then why would we replace it with a different mechanism that also has complexity and performance problems?
Basically, as far as I'm aware there are two established mechanisms to pass data between boot stages in TF-A today (some platforms, like Rockchip's, even support both of them at once): passing an FDT and the bl_aux_params linked list. They are intentionally on opposite ends of the complexity spectrum because different platforms can have different needs. The question is really just whether we need to add a third one, and whether that offers anything that the other two can't already cover. I guess we can support the exact UEFI HOB format just to make things easier for UEFI users, and maybe that's okay, but it does add maintenance burden to TF-A to support so many different things and we should at least consider if the UEFI part couldn't just translate its stuff into an FDT instead. But mainly, the way this thread started it sounded more like "we want to standardize on a new HOB format that will be used by everyone", and for that goal, I think sticking with what we have would make a lot more sense for TF-A. If UEFI HOB support was added in addition then I think only UEFI users would really gain any benefit from that, and that mechanism would only end up getting used by UEFI platforms (which again, maybe that's okay, but I'm just saying I don't think this is going to become some great new "one HOB format to rule them all" design if it doesn't do anything better than the established FDT format already does).
Does the method mentioned below allow you to create a dynamic list of arbitrary lengths and NOT lists of lengths decided at compile time? It appears that it is mainly being used on lists fixed at compile time.
The bl_aux_params list elements don't need to have a fixed size. The only common thing about each element is the tag (and the next pointer), everything else (including size) is tag-specific. You can just define a new tag where the next uint64_t after the next pointer defines the size of the rest of the element or something like that. Heck, you can even have the list element contain pointers to other random stuff in memory that isn't directly part of the list. (The whole thing is not consecutive in memory anyway. It's not designed to be a serializable, persistent thing like an FDT blob, just something that a calling bootloader stage can quickly assemble in its own memory right before handoff and that will only stay valid until the next stage is done parsing it and starts reusing available memory for its own purposes.)
Clearly the solution below was tailored to coreboot.
Not really, it was just the simplest flexible design I could come up with at the point. The APIs upstream is in the TF-A repo and coreboot (and other software) can include it from there.
Hi Julius,
that doesn't care that much about boot speed, why wouldn't you just use FDT?
[RK]I think you answered this question yourself. “there may not be a one-size-fits-all solution”. Can we use it? Yes! Do we want to use it, probably not, in a given context. UEFI HOB I think would fall in between for complexity and flexibility and you yourself said “They are intentionally on opposite ends of the complexity spectrum”. Two opposite ends may not fit the bill. There are perceptions around FDT too, just as there are perceptions around UEFI HOB. Bloblist, is also in-between the two complexity spectrums and I think it was said that may turn out to be acceptable with potential tweaks to tag assignment etc. To quote earlier emails:
I understand the versatility of DT, but I see two major problems with DT:
* DT requires more complicated parsing to get properties, and even more complex to dynamically set properties – this HOB structures may need to be generated in boot phases where DDR is not available, and therefore we will be extremely memory constrained. * DT is probably overkill for this purpose – We really just want a list of pointers to simple C structures that code cast (e.g. JEDEC SPD data blob)
but then why would we replace it with a different mechanism that also has complexity and performance problems?
and it should certainly be flexible enough to fill your needs
[RK] I concede that this is your view but others may view UEFI HOB’s as not as complex and more performant than FDT. You may not agree with this assessment, but we can agree to disagree. Also, having this debate in itself proves that there are folks that think what is currently in TF-A does not meet needs of more than few ARM platform vendors. You assumption that FDT should be flexible enough to fill our needs is incorrect.
and maybe that's okay, but it does add maintenance burden to TF-A to support so many different things and we should at least consider if the UEFI part couldn't just translate its stuff into an FDT instead.
[RK] Agree. EDK2 has been around a lot longer and changing all of EDK2 to use FDT is likely a harder path and larger effort. Incorporating UEFI compatibility into TF-A(given that it runs before UEFI starts) has general ARM adoption benefits in many market segments that you may not work on or care about. As for maintenance burden, sure, anything that you add has extra burden but if the benefits outweigh the burden, we should consider it, and obviously I think it does. If the options are well managed, I think we should be fine burden wise.
I think only UEFI users would really gain any benefit from that, and that mechanism would only end up getting used by UEFI platforms (which again, maybe that's okay, but I'm just saying I don't think this is going to become some great new "one HOB format to rule them all" >>design if it doesn't do anything better than the established FDT format already does).
[RK] I don’t think the intent of the proposal was “one HOB format to rule them all”. Perhaps you should read the earlier emails again. It only explains why FDT may not work for certain market segments and why HOB may be useful and a better fit in UEFI platforms. I wouldn’t dismiss the benefit to UEFI users as they are just as much a part of the ARM ecosystem as users of any other boot loader.
Not really, it was just the simplest flexible design I could come up with at the point. The APIs upstream is in the TF-A repo and coreboot (and other software) can include it from there.
[RK] Not trying to find fault at all with the design. Just saying it may not work very well the way it is today for some systems and may be perfect for other systems!
Thanks
Raghu
From: Julius Werner jwerner@chromium.org Sent: Monday, March 29, 2021 4:48 PM To: raghu.ncstate@icloud.com Cc: Julius Werner jwerner@chromium.org; Simon Glass sjg@chromium.org; Harb Abdulhamid OS abdulhamid@os.amperecomputing.com; Boot Architecture Mailman List boot-architecture@lists.linaro.org; U-Boot Mailing List u-boot@lists.denx.de; Paul Isaac's paul.isaacs@linaro.org; Ron Minnich rminnich@google.com Subject: Re: [TF-A] Proposal: TF-A to adopt hand-off blocks (HOBs) for information passing between boot stages
Hi Raghu,
It appears there are opinions you carry around UUID being complicated, bloated, code being an eyesore, parsing these lists early with MMU/Caches disabled, calculating checksums etc. While there is certainly a LOT of truth to those statements, these concerns need to be put into context and may not necessarily apply to all platforms running TF-A. Standardization and interoperability may be valued more on some platforms and some of the bloat and performance issues may be worth those tradeoffs. Some of these concerns may not even apply on powerful CPU’s and SoC’s with lots of memory. Also a quick grep for “uuid” in the TF-A repository shows that there is significant use of UUID’s for FIP, some SMC’s, secure partitions etc so use of UUID is not something new to TF-A.
Granted, I understand that different platforms have different requirements, and there may not be a one-size-fits-all solution for this. But if you have a system with a powerful CPU and lots of memory that doesn't care that much about boot speed, why wouldn't you just use FDT? I thought FDT is already established on many platforms to pass information between TF-A boot stages today, and it should certainly be flexible enough to fill your needs. Most of the earlier discussion in this thread seemed to focus on people wanting a different mechanism besides FDT because FDT is complex and not performant enough for all use cases, but then why would we replace it with a different mechanism that also has complexity and performance problems?
Basically, as far as I'm aware there are two established mechanisms to pass data between boot stages in TF-A today (some platforms, like Rockchip's, even support both of them at once): passing an FDT and the bl_aux_params linked list. They are intentionally on opposite ends of the complexity spectrum because different platforms can have different needs. The question is really just whether we need to add a third one, and whether that offers anything that the other two can't already cover. I guess we can support the exact UEFI HOB format just to make things easier for UEFI users, and maybe that's okay, but it does add maintenance burden to TF-A to support so many different things and we should at least consider if the UEFI part couldn't just translate its stuff into an FDT instead. But mainly, the way this thread started it sounded more like "we want to standardize on a new HOB format that will be used by everyone", and for that goal, I think sticking with what we have would make a lot more sense for TF-A. If UEFI HOB support was added in addition then I think only UEFI users would really gain any benefit from that, and that mechanism would only end up getting used by UEFI platforms (which again, maybe that's okay, but I'm just saying I don't think this is going to become some great new "one HOB format to rule them all" design if it doesn't do anything better than the established FDT format already does).
Does the method mentioned below allow you to create a dynamic list of arbitrary lengths and NOT lists of lengths decided at compile time? It appears that it is mainly being used on lists fixed at compile time.
The bl_aux_params list elements don't need to have a fixed size. The only common thing about each element is the tag (and the next pointer), everything else (including size) is tag-specific. You can just define a new tag where the next uint64_t after the next pointer defines the size of the rest of the element or something like that. Heck, you can even have the list element contain pointers to other random stuff in memory that isn't directly part of the list. (The whole thing is not consecutive in memory anyway. It's not designed to be a serializable, persistent thing like an FDT blob, just something that a calling bootloader stage can quickly assemble in its own memory right before handoff and that will only stay valid until the next stage is done parsing it and starts reusing available memory for its own purposes.)
Clearly the solution below was tailored to coreboot.
Not really, it was just the simplest flexible design I could come up with at the point. The APIs upstream is in the TF-A repo and coreboot (and other software) can include it from there.
boot-architecture@lists.linaro.org