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