kevin at koconnor.net
Wed Sep 30 19:03:20 CEST 2009
There has been suggestions recently on using parts of libpayload in
seabios. The following is my thoughts on some challenges of such an
Constrained memory - unlike a normal libpayload app, SeaBIOS must
reserve all memory that it uses during runtime in the e820 map. This
reserved memory then can't be used by the OS. Naturally, this means
reserved memory needs to be kept to a minimum - it would be a shame to
keep any sizable amount of memory unusable by the OS just so that it
can be used for the 5 seconds or so before the OS starts. I'd say all
code and ram used by SeaBIOS runtime shouldn't exceed 256KB. Right
now, SeaBIOS is using around 80K.
Also, code needed from 16bit mode must be located in the first 1Meg of
ram. The constraints on memory here are even stricter - I'd say all
code and ram here shouldn't exceed 100K.
As a result of these restrictions, SeaBIOS code uses different memory
"zones" (6 of them) and purposely allocates ram from the different
zones to optimize the memory footprint. (For example, an allocation
needed only during init wouldn't be reserved in the e820, an
allocation needed during runtime but not from 16bit code would be in
e820 high-mem, and only those allocations needed during 16bit run-time
would go into the e820 low-mem.)
Support for 16bit mode - SeaBIOS is fundamentally a 16bit bios
implementation and that means supporting 16bit callers. Because
SeaBIOS uses gcc, this isn't as difficult as it may seem, but it does
require implementation restrictions. All code needs to be compiled by
the seabios build (to manipulate the assembler and set compiler
flags); it's not possible to just link in a library. Also, special
macro wrappers must be placed in the code around all non-stack memory
Because of these memory restrictions, seabios tends to pass parameters
by value (so as to avoid lots of macro accesses). Seabios also tends
to avoid function pointers (is the pointer to the 16bit version of the
function or to the 32bit version of the function?).
Finally, available stack space in 16bit mode is severely constrained.
A hw irq handler probably shouldn't use more than 100 bytes of stack.
A regular 16bit handler probably shouldn't use more than 250 bytes of
Seabios must work without coreboot - seabios can be used natively with
qemu, bochs, and kvm. This isn't necessarily a problem for pulling in
a libpayload driver, but it does constrain other parts of libpayload.
(For example, it's not possible to assume a coreboot table will be
Parts of libpayload tend to assume other parts of libpayload are
available - this can be difficult for "cherry picking" drivers. For
example, usb requires malloc, in/out, printf, mdelay,
pci_config_write, etc. These can be redirected, but that's
troublesome for maintenance because the different implementations may
have subtly different behavior. Alternatively, one could try to
introduce more parts of libpayload into seabios, but that further
expands the scope of conflicts. For example, should the libpayload
version of malloc know how to do e820 map allocations?
On the flip side, the clear advantage of using libpayload in seabios
is a reduction of the overall code that needs to be maintained. It
could also lead to better test coverage of the code and a higher
In general, I think this raises a high-level question. Is there a
desire to introduce the memory and operating constraints into the
libpayload code that SeaBIOS will need? This is a bit of a difficult
question, as the other users (eg, filo) have no need to worry about
these restrictions and it will definitely make maintenance and testing
My general feel has been that this isn't worth the cost. The amount
of code being duplicated I would estimate is around 3000 lines. This
is unarguably very tricky code (eg, hw init, timing, malloc), but
there is not an overwhelming amount of it.
More information about the coreboot