efiboot – An UEFI payload for coreboot

Hacking

Because the source code for this project cannot be released at this time, the information contained in this section is a little sparse and probably not too interesting for the greater public.

The efiboot code is built in a sandbox w/ the following directory structure:

efiboot/ 
efiboot/coreboot 
efiboot/libpayload 
efiboot/edk2 
efiboot/efiload

The CorebootPkg

Check out the CorebootPkg and place it in efiboot/edk2/CorebootPkg. No further adjustments are required.

The CorebootPkg contains a platform description file (*.dsc), a package declaration file (*.dec), a flash description file (*.fdf) and an implementation of the PeCoffLib interface which operates on ELF images instead of PE32+ files.

The platform description file determines what actual implementation backs which library interface. It also determines which modules are built for this platform. Finally, it contains the definitions (as opposed to the declarations) of the PCD values known at compile time. The platform description file (*.dsc) format is specified by the TianoCore EDK II. The CorebootPkg is very similar to all other packages in the EDK II tree. The one notable difference is that it maps the PeCoffLib library interface to its own implementation.

When modifying the CorebootPkg, either by adding new modules or when updating to a newer TianoCore code base, it is frequently required to find out which implementations of a given library interface are available. A command like this one, issued from the edk2/ directory can be used for this task:

$ find . -name "*.inf" | xargs grep -e "LIBRARY_CLASS *= *PeCoffLib"

The package declaration file must declare (as opposed to define) all PCD values known at build time and referenced in the package. The package declaration file (*.dec) format is specified by the TianoCore EDK II. Previously, those values had been declared in the platform description file, too, but have apparently been moved to a separate file in more recent version of the TianoCore EDK II source tree. Failing to declare the PCDs will yield in errors from the build toolchain.

The flash description file (*.fdf) format is specified by the TianoCore EDK II as well. The file contains meta-data about the flash devices and images the build system deals with. Specifically, it defines what firmware volumes will be build and what modules they will contain. The CorebootPkg defines one firmware volume named “FvRecovery” containing all required modules. The minimum requirements are the DXE Core plus those modules that install the “architectural protocols”, i.e. implement the UEFI boot and runtime services referenced from the system table.

UEFI components

Place the EDK II source code in the efiboot/edk2 directory. Go to the BaseTools subdirectory and build the toolchain for the EDK II code. On Ubuntu, make sure the uuid-dev package is installed (along with the compiler, of course). In order to work with ELF images only, replace BaseTools/Source/C/GenFw/GenFw.c. The replacement tool must accept the same parameters as the original one. It’s only task is to copy the input file to a “branded” output file: The build process passes the “-e” parameter when invoking the GenFw utility, indicating what kind of module the binary is (e.g. UEFI_DRIVER, DXE_CORE, …). This information is used at runtime to e.g. find the DXE Core module in the firmware volume. The e_flags field in the ELF header can be used to store that data.

Source in the edksetup.sh script from the edk2 directory in order to set-up the required workspace files such as e.g. Conf/tools_def.txt.

Then adjust the file Conf/tools_def.txt so the tool chain produces executable files instead of shared objects: Look for the ELFGCC tag and remove the –shared parameter from the linker flags. Instead add -Ttext 0x00 to the linker flags. The linker flags have two effects: First, the linker will fail if the output file has unresolved symbols. Second, linking the binary at address 0x00 will make it easier to do the math, should you attempt to attach a debugger and load a symbol file. Depending on your compiler, you may also need to add -fno-stack-protector to the compiler flags.

Adjust the file Conf/target.txt so the active target is the CorebootPkg and the toolchain tag is ELFGCC.

Finally, run build.

The file BuildNotes2.txt, also part of the EDK II source tree, contains further information about the build process and tweaking it.

efiload

Store the efiload source code in efiboot/efiload. Create a symbolic link named FVRECOVERY.Fv that points to ../edk2/Build/Coreboot/DEBUG_ELFGCC/FV/FVRECOVERY.Fv. Compile the code via make. The output of the build process is the file efiloader.elf which is used as the coreboot payload.

coreboot

Place the coreboot source code in the efiboot/coreboot directory. The coreboot Build HOWTO contains further information on this topic. When configuring coreboot via make menuconfig, make sure the payload points to the efiloader.elf file that contains the efiload code.