Hi Melissa,
On 28.09.2017 07:59, Melissa Yi wrote:
Hi All, Does anyone know how to implement variable read/write in coreboot? like: how to create a block nvram to be accessed by uefipayload?
I don't know any quick solution. Though, here are my thoughts on the matter: AFAIK, coreboot currently doesn't have any specified format for in-flash, mutable configuration variables. Tianocore (or UEFI in general) might already have a format for that, but I would rather introduce something more native to coreboot that can easily be used in coreboot and all its payloads.
I'll try to describe my ideas for a complete solution (and where we already have parts implement and where not) in some layers from bot- tom up:
Flash-chip access =================
You need read/write access to the firmware flash chip. It's save to assume that coreboot at least knows how to read from its flash. And I would argue that writing variables from coreboot itself can be considered optional (or should even be discouraged). Though, when it comes to payloads, flash support is scarce. One option, and my preferred, is to use libflashrom that can currently be compiled and linked with libpayload. I guess it's not feasible to link the latter together with Tianocore (which seems to have its own implementation of the C library), so porting libflashrom to Tianocore is probably the way to go. (One alternative would be to only integrate drivers for the specific chipsets / chips one needs. But I can only advice against it. We should focus on one sophisticated code base for the matter and that is flashrom.)
Flash-chip partitioning =======================
coreboot uses its native FMAP to describe the layout of the flash chip. libpayload has some code for it. Should be easy to find a place and add a new entry for variables.
In-flash variable format ========================
I like to keep things simple and assume that a key=value approach suffices (for this layer). Though, as we have certainly to deal with NOR flash chips (and their erase blocks), we can't just store things in a table that would require an erase cycle for every change of a variable. Here is a random proposal:
VARIABLE MAGIC (4 bytes, for sanity checks) COMPLETE LENGTH (4 bytes, length in bytes of this entry) KEY LENGTH (4 bytes, length of the key name, if 0 or 0xffffffff, entry is invalidated) KEY NAME (KEY LENGTH bytes) VALUE (COMPLETE LENGTH - KEY_LENGTH - 12 bytes)
Read strategy: Either cache and index the whole thing, or read until the first valid entry with matching key.
Write strategy: Invalidate any entry with matching key, append after last entry if there is enough space in the current erase block. If not, finalize current erase block with an invalid entry spanning the free space of the block, write variable into next erase block. If we run out of erase blocks, defragment the whole thing (needs one com- plete erase block size to cache things, afaics)?
Application layer =================
Up to the use case. Could be anything from simple flags over UEFI runtime variables to full programs (e.g. tint easter-egg), I sup- pose.
Hope there is anything helpful in this mail, Nico