Hi Martin,
On Mon, 25 Sept 2023 at 13:51, Martin Roth gaumless@tutanota.com wrote:
Hey Simon, I think this is a good summary of the current situation, though the table doesn't come through in the text version of the email at all. Maybe upload an RFC to the documentation directory so it can be commented on in gerrit?
Can you see this?
https://docs.google.com/document/d/17vLMUFYuUVZnJkHdG2My4iyX_FJW185HosHSIwRf...
I did upload a PoC but I think I was ahead of the game as it needed an RFC first.
As I mentioned in the leadership meeting, I have concerns about a solution that relies solely on embedding this in bootblock. Some of these issues are specific to AMD, but if we're doing this, it should be a solution that we can use across different platforms and architectures.
Issues I see with embedding it the option mechanism in bootblock:1) Bootblock can be signed for verification by cbfs. Modifying the bootblock will cause the CBFS verification to fail. 2) The AMD bootblock is part of the overall AMDFW binary, and not at the top of the ROM as it used to be. This makes locating it and modifying it more difficult - it's not a separate CBFS area as you specified. 3) For AMD, the bootblock can be compressed, which makes it difficult (or impossible) to update this table.4) AMD has 3 copies of the bootblock. Which one gets updated? If all need to be updated, that's very inconvenient and creates issues keeping them in sync. 5) Assuming that you want this to be available to the 1st stage that's run, on AMD, that doesn't have to be bootblock, that can be PSP_verstage instead. 6) What happens when there's only one bootblock and it's in RO, so the options can't be updated? Maybe that's not an issue for ChromeOS because the table would only be used for debug, but if we're adding something new, let's design it so that it's useful for everyone.
I think it would be better to have a single table at a known fixed location in the firmware boot media so that it can be accessed before CBFS is enabled. This can be a separate partition in FMAP and parsed out by Make at build-time, or set as a Kconfig option and put anywhere in flash that is convenient to the architecture or platform (while still being writable). As Arthur said, it's inconvenient when the firmware boot media isn't memory mapped, so we probably need to design this with both options in mind.
I'm fine with an option that lets us choose between embedding something in the bootblock and placing the table somewhere else, so long as we use the same format in either place and only have a single copy in any given coreboot.rom image.
OK, got it.
Also, I'd really like to see this use an existing configuration mechanism instead of adding yet another configuration API. Here are 3 options I see:
CMOS_BUT_IN_FLASHOne option is to use the same interface inside coreboot that we currently use for CMOS. We should be able to just read the options from the boot media (or memory after copying it from flash) instead of CMOS, but use the rest of the parsing mechanisms as they already exist. CCB would just be added as another OPTION_BACKEND in Kconfig. I do like the way we have a method of adding default values for CMOS, so I'd prefer to see the exact same mechanism that we use in CMOS, but stored in flash instead. This would work well as an option for either putting into the bootblock or somewhere else in flash.
It looks like only one backend can be active, but for x86 boards we would want CMOS RAM (for normal settings) as well as SPI flash for CCB). Also the options are accessed using strings which is less efficient than an enum.
SMMSTORE_VIA_ANOTHER_MECHANISMIf that's not practical, we could use the same partition and format used by SMMstore, and create non-SMM routines to be cross-platform and allow it to be used earlier. It looks like SMMstore can already be used as another OPTION_BACKEND. I haven't looked into SMMstore, so I don't know if this is practical, but this still seems better than creating something completely new. Obviously, this doesn't work well to embed into the bootblock.
That looks like a ramstage thing that does some sort of system call to access the data. See for example smmstore_exec(). I am not sure how I could use that here.
CBI_IN_FLASHEven extending CBI to read data from the firmware boot media instead of (or in addition to) the EC would be better than creating an entirely new interface. There's a CBI interface to read the bits directly, but CBI also hooks into devicetree allowing devices to be enabled or disabled at runtime. CBI is currently limited to 64 bits, but that could be extended. This also works well for either embedding into bootblock or placing somewhere else in flash.
That looks more plausible, since it allows reading from multiple places in fw_config_get(). As you say it is only a 64-bit word. Plus it doesn't seem to be standardised across boards. Each one defines its own bits!
Having said that, it looks like the top bit is free in all cases, so I could perhaps add a 'global' config which is used by all boards?
Alternatively, I could rename perhaps fw_config_get() to fw_config_get_base() and add an enum parameter to fw_config_get(). But I would need to plumb this into coreboot's 'devicetree'. That doesn't seem to allow for configs which are common to all boards.
What do you think?
Regards, Simon
Martin
Sep 22, 2023, 13:58 by sjg@chromium.org:
Hi,
Here is an updated version 2 of the RFC
RFCv2: Post-build control of serial console
It is annoying to have to create and maintain two completely different builds of coreboot just to enable or disable the console. It would be much more convenient to have a 'silent' flag in the image, which can be updated as needed, without needing to rebuild
coreboot. For example, if something goes wrong and coreboot hangs, it would be nice to be able to enable serial on the same image, then boot it again to see how far it gets.
I propose a 'Coreboot Control Block' (CCB) which can hold a small number of such settings.
It is designed to be available very early in bootblock, before CBFS is ready. It is able to control the output of the very first bootblock banner. early silicon-init, etc. It is built as part of the bootblock image, so can be accessed simply as a static C struct within the bootblock code. That means that the code overhead is very low and we could
perhaps enable it by default.
The bootblock can have a CBFS file attribute that indicates that it contains a CCB and the offset where it is stored. Other coreboot stages can read this as well, or it could be duplicated in a separate file.
We can provide options in cbfstool to get and set settings in the CCB. This makes it easy to use this feature, e.g. to enable silent:
cbfstool coreboot.rom ccb-set -n serial -V silent
API for the settings:
I propose something like this:
enum ccb_setting {
CCB_SILENT_CONSOLE,
// others here
},
int ccb_read(enum ccb_setting val)
This is very efficient in terms of code size, e.g. it does not require a string, like get_uint_option().
What other APIs exist for reading config?
Mechanism
Control at run-time?
Controlled by image?
Cross-platform
Earlly bootblock
Smmstore
Yes
Yes
No
?
CMOS
Yes
No
No
Yes
Devicetree
No
Yes
Yes
Yes
CBI
Yes
No[1]
Yes
No
SPI ROM
TBD
CBFS flag files
Yes[1]
Yes
Yes
No
VPD
Yes
Yes [2]
Yes
No
CCB
Yes
Yes
Yes
Yes[4]
[1] Resides in EC, if there is one
[2] But changing the VPD is dangerous and we would want to avoid that for debugging. E.g. it might adjust the serial number.
[3] Can someone please point me to an example of flag files being used in coreboot?
[4] To the extent possible. Compression or verification may make this impossible, but this is likely unavoidable
Of the existing mechanisms, none seems to quite meet the requirements.
Why not use a separate CBFS file?
- Boards typically read the entire bootblock and start execution from it. The console is started early so the settings are needed before CBFS is available. By putting the CCB inside the bootblock, it can control things from an early stage.
Why not CMOS RAM / VVRAM?
- If we allocate some space in CMOS for console / logging settings,
then it would allow a similar feature. But it involves changing
settings on the device. Each board would need to provide some CMOS
options for this feature as part of the layout file. It would not be
possible to enable console output without running some code on the
device to update the CMOS RAM.
Why not use Firmware Handoff to pass the CCB to following stages?
- We could do that, particularly if CCB attracts some additional features,
such as logging.
How to deal with Boatguard, verification, etc?
If it is not possible to change the bootblock without causing a failure, then this feature will not work as intended.
How to deal with bootblock running on a different CPU? (AMD)
This should still work OK, since the CBB should be accessible to the CPU.
How to deal with a compressed bootblock?
If the whole bootblock has to be compressed, then this feature will not work, since it is not possible to update the CCB without knowing about the compression.
Regards,
Simon