efiboot – An UEFI payload for coreboot

Implementation

… of coreboot

Coreboot is a separate and independent project. No changes to coreboot are required for efiboot.

… of efiload

The efiload component is build with the help of libpayload which is a library part of the coreboot project. The library implements a limited set of the standard C library functions. It also implements start-up code so that an application can be written to start at its main() function instead of worrying about the low-level details. Efiload makes use of those facilities and uses libpayload data structures to locate and parse the coreboot tables. This latter task can be regarded as the input path of efiload.

The output path of efiload uses data structures implemented as part of the TianoCore EDK2 project. Those structures are documented in the UEFI and PI specifications and define how a Hand-off Block (HOB) should look like. Efiload transforms the coreboot tables into a HOB list.

The HOB list produced by efiload contains the following HOBs:

  • The HOB List Header, described by a structure of type EFI_HOB_HANDOFF_INFO_TABLE. This HOB describes the basic memory layout of the system, i.e. lowest and highest addresses along with information on what memory is available to the DXE phase.
  • A Firmware Volume HOB, encoded in a structure of type EFI_HOB_FIRMWARE_VOLUME. This HOB encodes information on where the Firmware Volume (FV) of the boot flash resides. Because the FV is encapsulated in the coreboot flash image, the efiload component shadows the firmware volume to main memory and stores information about the shadow copy only in the HOB. Currently, the location of the shadow copy is defined to be the highest memory range available, e.g. an 8 MByte flash image will be shadowed to 8 MBytes below the top of physical memory.
  • One or more resource description HOBs which are structures of type EFI_HOB_RESOURCE_DESCRIPTOR. The resource description HOBs are used to pass information about the location of individual, possibly non-continuous blocks of physical system memory. Because the Firmware Volume is shadowed below the top of physical memory, the resource descriptor HOBs currently do not announce that memory region to the DXE phase.
  • One memory allocation HOB of type EFI_HOB_MEMORY_ALLOCATION_MODULE. The HOB is used to record the memory allocation of the loaded DXE core ELF image.
  • One CPU HOB, i.e. a EFI_HOB_CPU structure, that describes the capabilities of the CPU, namely number of address lines and the size of the CPUs I/O space. Currently, the information passed in this HOB is hard-coded to the i386 values of 32 address lines and 16 Bit wide I/O addresses.
  • The HOB list is terminated by a HOB of type EFI_HOB_TYPE_END_OF_HOB_LIST which consists only of a generic HOB header, a structure of type EFI_HOB_GENERIC_HEADER.

When efiload is done with the data transformation, it locates the DXE core in a UEFI Firmware Volume (FV). For ease of implementation and testing, the FV is appended as a binary section to the efiload binary. This allows the efiload code to address the size and location of the FV using symbols, i.e. simple C pointers. The code in efiload that searches the FV also makes use of data structures implemented in the TianoCore EDK2 project.

.. of the UEFI layer

The UEFI Layer is implemented using the code provided by the TianoCore EDK II project. The EDK II code implements all three Platform Initialization (PI) phases SEC, PEI and DXE mandated by the UEFI-related Platform Initialization Specification. For the efiboot project, only the DXE phase is relevant. All other code is not used.

The code contained in the EDK II itself can probably be used without modifications. However, the CorebootPkg has been added to package and enhance the EDK II code. Also, to aid debugging, the EDK II build tools have been modified to work with ELF images instead of PE32+ binaries. By default, the TianoCore tools will work with ELF images, but convert them to a PE32+ binary before placing them into the firmware flash.

Boot Flash Layout

Coreboot expects the payload to be known at compile time. This is required because the coreboot build process compresses the payload and packages it along with the coreboot code in a flash image.

The UEFI specification and the implementation of the UEFI components dictate that all of the UEFI components are stored in an UEFI Firmware Volume (FV), a special format for a kind of file system in the firmware flash.

Fig. 2: Boot Flash Layout
Fig. 2: Boot Flash Layout

In order to fulfill both somewhat contradicting requirements, the UEFI Firmware Volume is encapsuled in the coreboot payload at compile time. At runtime, the efiload layer extracts the UEFI Firmware Volume and shadows it to a memory location. This means, the coreboot build process is used to assemble a bootable flash image and hence the boot flash layout follows the coreboot guidelines. Also, the UEFI components will always work on a UEFI Firmware Volume shadowed into system memory.