lbmk maintenance manual

Return to previous index

In addition to this manual, you should also refer to porting.html and testing.html.

Please also read about the lbmk coding style and design.

Automated coreboot build system

This document describes the entire Libreboot build system, its design philosophy and how it’s used to prepare Libreboot releases; it is provided as a reference for Libreboot development, pertaining to the current development branch of Libreboot’s build system (called lbmk).

The homepage of Libreboot says that Libreboot is a coreboot distro, providing the necessary integration of coreboot, payloads and utilities so as to provide releases, much like Linux distros do for your operating system, but here we are concerned about the boot firmware instead. Libreboot is to coreboot, what Debian is to Linux. It provides easier, more automated configuration and installation.

The build system, lbmk, is that coreboot distro, at its very core. You can basically think of it as a package manager; it is even a source-based package manager. If you simply want to build ROM images, refer instead to the basic build instructions.

This build system, lbmk, is completely automated in every way. It is designed to take care of itself; so long as build dependencies are installed, it will check itself when running any command; if another command had to be executed first, it will do so automatically. Therefore, you can run any part of lbmk on its own, and the entire design is modular.

Best practises for learning lbmk

The follow sections will cover subdirectories, within lbmk. Contrary to what some may otherwise assume, it’s best to learn about everything except scripts or code within Libreboot, first. No, you should first learn about config files used in the Libreboot build system, and then learn about the logic. By doing it in this order, you will have greater context later when reading about those scripts. Learning about each upstream project (such as coreboot) will also be useful; check documentation provided by each project.

After learning about configuration, you will then read about files and directories generated by the build system; only then will this document describe each script or program that forms part of the build system. In other words, this document adopts a top-down approach to education, rather than bottom-up; most documents take the latter approach, in other projects, but most people naturally want to learn how a specific thing works first, hence the approach taken here.

Don’t be deceived by simplicity

Libreboot’s build system is powerful, and highly configurable, yet deceptively simple at the same time. Remember this rule, a rule that applies to all software projects: code equals bugs, so smaller codebases will yield fewer bugs. Libreboot is regularly audited.

Many people will be shocked by how small Libreboot is, at its core. You will be surprised by just how much can be done with so little. Continue reading!

libreboot blob reduction policy

The coreboot software is nominally free, but it requires additional binary blobs on many supported systems. These blobs lack source code, and the coreboot project does not control them, but they can be used to perform specific initialization tasks.

The libreboot project allows binary blobs from coreboot, but there is still a lot of nuance to precisely what is allowed. It is important that you understand these nuances, when working on libreboot.

Please read the blob reduction guidelines and also the freedom status page.

Before configuration info, you will first be shown a brief overview of every project that Libreboot imports, such as coreboot.

Projects/files downloaded/generated by lbmk

The following sections will describe files and directories that are not included in lbmk.git, but are created by running various lbmk commands; many of these will also be provided, pre-generated, under release archives.

Some of these are downloaded by Libreboot’s build system, automatically, while others are created during the build process based on these downloaded programs.


This directory is created when running any of the following commands, with the right arguments:

./build boot roms ARGUMENTS_HERE
./build serprog stm32
./build serprog rp2040

Simply speaking, bin/ shall contain finished ROM images or firmware, that can then be installed (flashed) to the target device.

The files under bin/ are provided in regular Libreboot releases.


Used by the blob handler scripts. The upstream that we use is here:

Specifically: the pfs extract utility from this is used on Dell vendor updates, to extract SCH5545 EC (Environment Control) firmware.


Used by the blob handler scripts. The upstream that we use is here:

The script is used here, to extract from Dell BIOS updates, to get at the VGA ROM for Nvidia GPU on certain models of Dell Latitude E6400.


Used by the blob handler scripts, referenced in certain coreboot configs.

Certain binary blobs such as Intel ME or SCH5545 EC firmware are downloaded here; not all blobs are downloaded here however, as some are handled under separate directories.


The build system compiles cbfstool and ifdtool, from coreboot, and then places the executables here for use on coreboot ROM images.


Please also visit:

Coreboot is the main boot firmware, providing hardware initialisation. Libreboot makes extensive use of coreboot, on supported mainboards.

Coreboot trees go here. Libreboot’s build system does not simply use one tree, or multiple branches in the same tree; entirely separate directories are created, for each revision of coreboot used, each able to have its own patches. These can then be re-use appropriately, per mainboard. For example:

This may be less efficient on disk usage, but it simplifies the logic greatly. Coreboot also uses its own toolchain called crossgcc, and crossgcc is in fact compiled per tree in Libreboot.

KBC1126 EC firmware goes here, required on HP EliteBook laptops. These images are inserted into those coreboot images, under elf/ and bin/.


Compiled binaries (compiled by lbmk) go here, but they are not the final binaries; coreboot ROM images are compiled without payloads, then cached here under elf/coreboot as one example; ditto GRUB and SeaBIOS which go under elf/grub and elf/seabios respectively - elf/u-boot is another example.

Binaries under elf/ are compiled first, which lbmk then uses to generate the files under bin/; the latter files under bin/ are intended for installation by the user.

It is technically possible to re-use these files elsewhere. For example, you may wish to only compile GRUB with lbmk, and then use the grub.elf file from lbmk in your own custom coreboot ROM (that you didn’t build with lbmk).

This is only used by the build system, but these images are not provided in releases (only the images under bin/ are provided).


Please also visit:

Although currently unused by any part of lbmk, we provide flashrom for the convenience of users, and this is copied to release archives. Flashrom is the program that you will use to read, erase and write the flash, containing coreboot firmware.


Please also visit:

The GNU GRUB bootloader, a reference multiboot implementation with its own small kernel/OS and drivers (e.g. file systems, cryptography). This is the default recommended coreboot payload on x86-based Libreboot systems. GRUB will load and execute your Linux kernel, which then runs on the bare metal.

The utilities for GRUB are compiled here, and used from here; specifically, the grub-mkstandalone utility is executed from here to create the final GRUB image under elf/grub/.

NOTE: This is only provided for x86 machines, in Libreboot. For ARM, we ship U-Boot instead.


Please also visit:

This is used by Libreboot, to neuter Intel ME images. The intel ME images are auto-downloaded from the vendor during each build process, cached on disk and processed by me_cleaner. It removes almost all code from Intel ME, leaving only the basic bringup code (analogous to running coreboot without a payload). More information available at these pages:

The blob scripts are what handle this, specifically the download script located at script/update/blobs/download.


Please also visit:

This is provided inside ROM images, as a payload executed from main GRUB or SeaBIOS payload. It checks for corrupted memory.


Please also visit: - the handling of this, in Libreboot, is based largely on the information there.

This contains the Intel MRC blob, auto-downloaded during build by script/update/blobs/mrc, called by the user directly or by script/update/blobs/download. This provides raminit and peripheral init on certain Haswell and Broadwell platforms.

In some cases, libre MRC firmware is also available, and provided by Libreboot as an alternative choice.


PCI Option ROMs, currently used only for the VGA ROM on models of Dell Latitude E6400 containing an Nvidia GPU; it provides video initialisation, where coreboot currently only initialises Intel GPUs natively, on Libreboot systems.


The scripts under script/build/release/ create tar archives in here, which constitute regular Libreboot releases. It is meticulously maintained, as per current lbmk behaviour, and executed so as to provide Libreboot release archives.

This provides source tarballs, and ROM images for example; however, ROM images containing non-redistributable blobs are scrubbed such that those blobs must, in regular releases, be re-added manually by the user.


Please also visit:

This is the PC BIOS implementation used by Libreboot, on x86 machines (not all of them). A BIOS/UEFI implementation is not required, because Linux and BSD kernels can execute on bare metal, but it can nonetheless still be useful; in particular, the BSD bootloaders can be executed from SeaBIOS.

This is provided as a coreboot payload, either as first payload or it can be executed from GRUB (if GRUB is the main payload, on a given target).


The TMPDIR environmental variable is set by lbmk, to a location under /tmp, but some users may have /tmp mounted as a tmpfs (file system in RAM), and may not have much RAM.

Where large files (or a large number of files) are handled by lbmk on a temporary basis, this tmp/ directory is created and then used.


Please also visit:

This is a bootloader provided on ARM chromebooks, within Libreboot. It also provides UEFI. Information about that can be found on these resources:

This is currently the only payload on ARM systems, within Libreboot.


Please also visit:

This is compiled, so as to provide UEFIExtract. Currently used by the blob download script at script/update/blobs/download, to download SCH5545 EC firmware (used for fan control on Dell Precision T1650).


Used by lbmk, to build firmware for serprog-based SPI flashers with RP2040 SoC. Alongside this, util-fw/rp2040/pico-sdk is imported which is required for building it.

Please visit these pages:


Used by lbmk, to build firmware for serprog-based SPI flashers with STM32 MCU. Alongside this, libopencm3 is imported which is required for building it.

These serprog programmers are quite desirable, owing to their low cost and ease of use. You can learn more on the SPI flashing guide.

Before moving onto configurations, we will now cover utilities provided by Libreboot itself (included within lbmk, rather than being downloaded like the third party projects listed above):


Not to be confused with util-fw/!

If a codebase is not frequently used by Libreboot, is actively developed (making it not viable to maintain in Libreboot) or the codebase is very large, we would import that as a third party module in lbmk - this rule exists for all projects, where the intention is that lbmk.git itself should be small and efficient.

Where appropriate, and where the code is small enough, or it is otherwise deemed desirable, lbmk.git provides a few utilities as part of itself, namely:


This program, written by Nicholas Chin, unlocks the boot flash on Dell Latitude E6400; it permits internal flashing, from factory firmware to Libreboot, so that the user need not disassemble and flash externally.


This is a special fork of me_cleaner, specifically for parsing and neutering Intel ME images provided by Lenovo for ThinkPad X220 and other Lenovo ThinkPads of Intel SandyBridge platform. You can find information about this on the original repository:

ME7 Update Parser was originally written for Heads, another coreboot distro very similar to Libreboot that provides coreboot build automation with Linux based payload configurations. Their build system auto-downloads and auto-neuters Intel ME images, during build, so that the user does not have to manually extract such images from dumps of the original vendor firmware (in the flash) on a given machine.

Such logic was ported to Libreboot, courtesy of shmalebx9 as mentioned on the who page - Caleb is a core developer in the Libreboot project.


The nvmutil software allows you to set the MAC address on Intel GbE NVM files. It also allows you to set random MAC addresses, in addition to arbitrary ones.

This directory contains the source code for nvmutil, which you can read about here:

nvmutil manual


FSF has original copyright on this; it was imported from coreboot, who in turn imported it from GRUB with very little modification. Therefore, this code is canonically based on what is provided in GNU GRUB.

This is a receiving client for spkmodem, which is a method of providing serial consoles via pulses on the PC speaker. The spkmodem_recv client will decode these pulses. Coreboot has a driver for generating these pulses, as does GRUB; this client code was imported from GRUB, and has in fact been provided by every Libreboot release since the start of the project (look inside the GRUB or coreboot source code and you’ll find it).

However, the original code from GRUB was of quite poor quality and this code is often used. For fun, it was decided that this utility would be imported directly into lbmk.git, and thoroughly cleaned. The lbmk version has been more or less re-written, using the original logic as a base; variables are more clearly named. A top-down, OpenBSD-inspired coding style is used, replacing the GNU coding style implemented in the original code. The [OpenBSD coding style][] is much easier to read.

This code has been modified to make use of the pledge() system call, when used on OpenBSD; the original version from GRUB did not do this. Other improvemnts include:

Now in the next sections, you will learn about configuration files provided by lbmk:


This directory contains configuration files, used by the Libreboot build system. These next sections will cover specific configuration files.



URLs and hashes for vendor files containing Intel ME images within them. Where feasible, backup URLs are also provided. SHA1 checksums are defined, so that lbmk can verify the integrity of downloaded files.

When building for sandybridge, ivybridge and haswell machines, Libreboot’s bulid system automatically downloads such updates from the vendor, to extract the Intel ME image and neuter it with me_cleaner or

Such auto-download logic was ported from the Heads build system, to be used in the Libreboot build system. It is the bee’s knees, because it prevents the need for manual extraction of Intel ME images from vendor dumps. It means that you can just build Libreboot (from lbmk) and then just flash the resulting image, without having to worry.

Of course, backing up the original firmware is still a good idea, before installing Libreboot or any other spin of coreboot.

This file is also used to define the VGA ROM, on Nvidia models of Dell Latitude E6400.



When a given coreboot tree is compiled, for a given target, this file defines which files to copy from the coreboot directory, which are then copied to a location under elf/coreboot.


Each target name (e.g. x200_8mb) has its own directory under here. Targets that do not define defconfigs also exist here; for example, the default directory defines a coreboot revision and patches.

Targets under config/coreboot can specify tree=TREE where TREE could, for example, be default. In other words, they can refer to other trees.

The coreboot downloads are based on scanning of these directories, and ROM images are also built based on them; coreboot defconfigs are also used by the blob scripts, for adding or removing certain binary blobs (for example, a config will define where me.bin is located, and if it doesn’t exist, the blob scripts will look up that file and download/process it with me_cleaner).


For any given coreboot tree, patches with the patch file extension are placed here, alphanumerically in the order that they should be applied.

These patches are then so applied, when lbmk downloads the given source tree.


This file can contain several configuration lines, each being a string, such as:

The tree value refers to config/coreboot/TREE; in other words, a given target could specify a name other than its own as the tree; it would then re-use code from that tree, rather than providing its own.

The romtype entry is used during the building of ROM images, to define special steps; for example, d8d16sas` would tell lbmk that a fake PIKE2008 ROM must be inserted into CBFS (prevents hanging on SeaBIOS).

The rev entry defines which coreboot revision to use, from the coreboot Git repository. At present, lbmk only supports use of the official repository from the upstream coreboot project.

The arch entry specifies which CPU architecture is to be used: currently recognized entries are x86_32, x86_64, ARMv7 and AArch64. Setting it to a non-native arch means that necessary crossgcc-arch will be compiled and be available when building roms, but not necessarily built or discovered when individual scripts are called manually.

The payload_grub entry specifies whether or not GRUB is to be included in ROM images.

The payload_grub_withseabios entry specifies whether or not SeaBIOS is to be included with GRUB, in ROM images. Turning this on also turns on payload_seabios_withgrub, unless that option is explicitly turned off.

The payload_seabios entry specifies whether or not SeaBIOS is to be included in ROM images. This option is automatically enabled if payload_grub_withseabios and/or payload_seabios_withgrub are also turned on.

The payload_memtest entry specifies whether or not MemTest86+ is to be included in ROM images; it will only be included in ROM images for text mode startup, on x86 machines.

The payload_uboot entry specifies whether or not U-Boot is to be included in ROM images.

The uboot_config option specifies which U-Boot board configuration file variant should be used. It currently doesn’t make sense for this to be anything other than default, which is the default if the option is missing.

The grub_scan_disk option specifies can be ahci, ata or both, and it determines which types of disks are to be scanned, when the grub.cfg file in GRUB payloads tries to automatically find other grub.cfg files supplied by your Linux distribution. On some machines, setting it to ata or ahci can improve boot speed by reducing delays; for example, trying to scan ata0 on a ThinkPad X60 with the optical drive may cause GRUB to hang, so on that machine it is advisable to set this option to ahci (becuse the default HDD slot is AHCI).

The blobs_required entry doesn’t affect anything in code, except that the noblobs string will be appended to ROM image file names, on releases; ditto nomicrocode but in that case, the behaviour is: if no microcode to begin with, only nomicrocode images will be named, otherwise ROM images with and without microcode updates will be provided in releases (CPU microcode updates).


Files in this directory are coreboot configuration files.

Configuration file names can be as follows:

Information pertaining to this can be found on the installation manual

In lbmk, a board-specific directory under config/coreboot/ should never specify a coreboot revision. Rather, a directory without coreboot configs should be created, specifying a coreboot revision. For example, the directory config/coreboot/default/ specifies a coreboot revision. In the board-specific directory, your board.cfg could then specify cbtree="default" but without specifying a coreboot revision (this is specified by config/coreboot/default/board.cfg).

When you create a coreboot configuration, you should set the payload to none because lbmk itself will assume that is the case, and insert payloads itself.

Configurations with libgfxinit will use coreboot’s native graphics init code if available on that board. If the file name has txtmode in it, coreboot will be configured to start in text mode, when setting up the display. If the file name has corebootfb in it, coreboot will be configured to set up a high resolution frame buffer, when initializing the display.

NOTE: If the configuration file is libgfxinit_txtmode, the SeaBIOS payload can still run external VGA option ROMs on graphics cards, and this is the recommended setup (SeaBIOS in text mode) if you have a board with both onboard and an add-on graphics card (e.g. PCI express slot) installed.

Configuration files with vgarom in the name have coreboot itself configured to run VGA option ROMs (and perhaps other option ROMs). This setup is not strictly recommended for SeaBIOS, and it is recommended that you only run GRUB in this setup. As such, if you wish for a board to have coreboot initialize the VGA ROM (on an add-on graphics card, as opposed to onboard chipset), you should have a separate directory just for that, under config/coreboot/; another directory for that board will have configs with libgfxinit. HOWEVER:

It is supported in lbmk to have SeaBIOS used, on either setup. In the directory config/seabios/ there are SeaBIOS configs for both; the vgarom one sets VGA hardware type to none while the libgfxinit one sets it to coreboot linear framebuffer. However, if you use SeaBIOS on a setup with coreboot also doing option ROM initialization, such initialization is being performed twice. As such, if you want to use an add-on graphics card in SeaBIOS, but the board has libgfxinit, it is recommended that you do it from a libgfxinit ROM.

HOWEVER: there’s no hard and fast rule. For example, you could make a vgarom configuration, on a board in lbmk, but in its coreboot configuration, don’t enable native init or oproms, and do SeaBIOS-only on that board.

On vgarom setups, coreboot can be configured to start with a high resolution VESA frame buffer (NOT to be confused with the coreboot frame buffer), or just normal text mode. Text mode startup is always recommended, and in that setup, GRUB (including coreboot GRUB, but also PC GRUB) can use VGA modes.

The name libgfxinit is simply what ./build boot roms uses, but it may be that a board uses the old-school native video init code written in C. On some platforms, coreboot implemented a 3rd party library called libgfxinit, which is written in Ada and handles video initialization. In this setup, coreboot itself should never be configured to run any option ROMs, whether you start in text mode or with the coreboot framebuffer initialization.

The normal config type is for desktop boards that lack onboard graphics chipsets, where you would always use an add-on graphics card (or no graphics card, which would be perfectly OK on servers).

Even if your board doesn’t actually use libgfxinit, the config for it should still be named as such. From a user’s perspective, it really makes no difference.


Files here are so named, and called like so: e.g. the debian file would be referenced when running:

./build dependencies debian

These files define a list of packages, and the correct package manager command to use on a given distro. This can be used to install build dependencies, which are required for compiling Libreboot from source code.


Configuration related to third-party Git repositories, that Libreboot makes use of.


This file defines third party codebases, with repository links, revision IDs, and dependencies (referring to other modules defined in this file).

Almost every third party codebase that lbmk downloads is based on the handling of this file. Some of the codebases defined here will also have a directory of their own; for example, config/grub/ exists.



Splash screen images applied duing startup when using the GRUB payload.


Used on ThinkPad X60 and T60.


Used on all other machines, besides X60 and T60 thinkpads.

NOTE: the grub_background option can be set under target.cfg in the relevant coreboot directory, under config/coreboot/; for example, config/coreboot/x60/target.cfg specifies this:



Licensing info for GRUB bootsplash images.


GRUB configuration files.


Author info for GRUB configuration files.


Licensing info for GRUB configuration files.


This is a configuration file. It is used to program GRUB’s shell.

This is inserted (as grub.cfg) into the GRUB memdisk, in the ROM image. It contains a lot of logic in it, for booting various system configurations, when the GRUB payload is in use.

It can be overridden by inserting grub.cfg into coreboot’s main CBFS root.

A grubtest.cfg can be inserted into CBFS, but it will not override the default grub.cfg (either in CBFS or on memdisk); however, the one in memdisk will provide a menuentry for switching to this, if available.


This GRUB configuration checks whether grub.cfg exists in CBFS and switches to that first (not provided by default) or, if one is not available in CBFS, it will load the grub.cfg stored inside GRUB memdisk.

The GRUB memdisk is a file system within grub.elf, itself stored within the coreboot file system named CBFS, which is part of the coreboot ROM image on every coreboot target.


Keymap files used by GRUB. They can alter the character set corresponding to inputted scancodes.


The keymap files themselves. These are inserted into the GRUB memdisk, and the grub.cfg file can specify which one is to be used.

These files are binary-encoded, defining which characters correspond to which scancodes. It is handled by grub-core/commands/keylayouts.c in the GRUB source code.


This defines which modules are inserted into grub.elf. These modules can be anything from file systems, small applications/utilities, launchers (e.g. the linux command will execute a Linux kernel), you name it.

Libreboot defines only a very conservative set of modules here, so as to reduce the amount of space used in the main boot flash. (GRUB payloads are also compressed when they are inserted into coreboot images)

This list is used by lbmk when it runs grub-mkstandalone, which is the utility from GRUB that generates grub.elf files (to be compressed inside CBFS and then executed as a coreboot payload).


For a given GRUB revision, patches with the patch file extension are placed here, alphanumerically in the order that they should be applied. For example, Libreboot provides argon2 key derivation support out of tree, allowing LUKS2 partitions to be decrypted by GRUB.

These patches are then so applied, when lbmk downloads the given source tree.


Intel Flash Descriptors and GbE NVM images, which are binary-encoded configuration files. These files are referenced in coreboot defconfigs, used by lbmk to build coreboot ROM images.



When a given SeaBIOS tree is compiled, for a given target, this file defines which files to copy from the seabios/ directory, which are then copied to a location under elf/seabios.


Currently the only tree in use, this defines what SeaBIOS revision is to be used, when the SeaBIOS payload is enabled on a given coreboot target.


Configuration files go in here.


Configuration file for when native video initialisation is available in coreboot.


Configuration file for when native video initialisation is unavailable in coreboot, and VGA ROM initialisation is also not provided by coreboot (in this configuration, the usual setup will be that SeaBIOS finds and executes them, instead of coreboot).


Configuration file for when native video initialisation is unavailable in coreboot, and VGA ROM initialisation is provided by coreboot; in this setup, SeaBIOS should not execute VGA ROMs.


Similar concept to target.cfg files provided by coreboot. This specifies which SeaBIOS revision (from Git) is to be used, when compiling SeaBIOS images.


This directory contains configuration, patches and so on, for each mainboard that can use U-Boot as a payload in the lbmk build system. U-Boot doesn’t yet have reliable generic configurations that can work across all coreboot boards (per-architecture), so these are used to build it per-board.


When a given U-Boot tree is compiled, for a given target, this file defines which files to copy from the u-boot/ directory, which are then copied to a location under elf/u-boot/.


Each TREENAME directory defines configuration for a corresponding mainboard. It doesn’t actually have to be for a board; it can also be used to just define a U-Boot revision, with patches and so on. To enable use as a payload in ROM images, this must have the same name as its config/coreboot/TREENAME/ counterpart.


For any given U-Boot tree, patches with the patch file extension are placed here, alphanumerically in the order that they should be applied.

These patches are then so applied, when lbmk downloads the given source tree.


This file can contain several configuration lines, each being a string, such as:

These are similar in meaning to their coreboot counterparts.

The treeentry is actually a link, where its value is a directory name underconfig/u-boot. For example,tree=“default”would refer toconfig/u-boot/defaultand the corresponding U-Boot source tree created (when running./update project trees u-boot, which makes use oftarget.cfg) would beu-boot/default/. In other words: atarget.cfgfile inconfig/u-boot/foomight refer toconfig/u-boot/barby specifyingtree=“bar”, and the created u-boot source tree would beu-boot/bar/`. ALSO:

FUN FACT: such references are infinitely checked until resolved. For example, foo can refer to bar and bar can refer to baz but if there is an infinite loop, this is detected and handled by lbmk. For example, if bar refers to foo which refers back to bar, this is not permitted and will throw an error in lbmk.

The rev entry defines which U-Boot revision to use, from the U-Boot Git repository. At present, lbmk only supports use of the official repository from the upstream U-Boot project.

The arch entry specifies which CPU architecture is to be used: currently recognized entries are x86_32, x86_64, ARMv7 and AArch64. Setting it to a non-native arch means that necessary crossgcc-arch will be compiled and be available when building roms, but not necessarily built or discovered when individual scripts are called manually.


Files in this directory are U-Boot configuration files. Configuration file names can be anything, but for now default is the only one used.

In lbmk, a board-specific directory under config/u-boot/ should never specify a U-Boot revision. Rather, a directory without U-Boot configs should be created, specifying a U-Boot revision. For example, the directory config/u-boot/default/ specifies a U-Boot revision. In the board-specific directory, your board.cfg could then specify ubtree="default" but without specifying a U-Boot revision (this is specified by config/u-boot/default/board.cfg).

Normally, the U-Boot build process results in the U-Boot executable and a device-tree file for the target board, which must further be packaged together to make things work. When you create a U-Boot configuration, you should enable CONFIG_REMAKE_ELF or CONFIG_OF_EMBED that handles this. The former option enables creation of a u-boot.elf that bundles them together after the build, and the latter option embeds it into the u-boot executable.

When making a U-Boot configuration, you should also pay special attention to the CONFIG_SYS_TEXT_BASE (CONFIG_TEXT_BASE in later versions), whose defaults may cause it to overlap coreboot, in which case it won’t boot. Normally, the upstream coreboot build system checks for this when given CONFIG_PAYLOAD_ELF, but lbmk injects the payload itself and doesn’t check for this yet.

Another interesting config option is CONFIG_POSITION_INDEPENDENT for ARM boards, which has been so far enabled in the ones lbmk supports, just to be safe.

U-Boot build system

If you wish to know about U-Boot, refer here:

This and other documents from U-Boot shall help you to understand U-Boot.

You create a config, for config/u-boot/TREENAME/configs, by finding the corresponding board name in the upstream U-Boot configs directory, and running make BOARDNAME_defconfig and make menuconfig commands in the U-Boot build system. You should do this after running ./update project trees u-boot in lbmk.

You might want to consider basing your config on the upstream coreboot boards when possible, but such a board is not available upstream for ARM yet.

You can simply clone U-Boot upstream, add whatever patches you want, and then you can make your config. It will appear afterwards in a file named .config which is your config for inside config/u-boot/TREENAME/.

You can then use git format-patch -nX where X is however many patches you added to that U-Boot tree. You can put them in the patches directory under config/u-boot/BOARDNAME.

The base revision, upon which any custom patches you wrote are applied, shall be the rev entry.

Scripts exist in lbmk for automating the modification/updating of existing configs, but not for adding them. Adding them is to be done manually, based on the above guidance.

Config files in lbmk root directory


This is a text file, containing a single line that says libreboot. This string is used by the build system, when naming releases alongside the version number.


Updated each time lbmk runs, based on either git describe or, on release archives, this file is static and never changes. It says what Libreboot revision is currently in use (or was in use, if lbmk isn’t running).


Updated each time lbmk runs, based on either git describe or, on release archives, this file is static and never changes. It says the time of whichever Libreboot revision is currently in use (time of commit).

At least, you will now learn about the scripts (exclusively written as posix shell scripts) that constitute the entire Libreboot build system, lbmk:

Scripts in root directory of lbmk


Symbolic link, pointing to the lbmk script. This is executed by the user, or by lbmk, referencing scripts under script/build/*/.


This is executed by the lbmk script when it runs, returning non-zero status and exit if global git name/email configuration does not exist; lbmk makes extensive use of git, and coreboot requires this to be set.


If lbmk is in git, this uses git describe to get a version number based on revision and/or git tag, then writing that to a file called version and a corresponding date (as unix timestamp) to versiondate; if this script is executed from a release archive, the value stored in those files (included by default in release archives, but auto-generated in lbmk.git) will be used as-is.

The result of this is then used in many things. For example, lscoreboot on the GRUB terminal will yield this revision number and date.


Symbolic link, pointing to the lbmk script. This is executed by the user, or by lbmk, referencing scripts under script/handle/*/.


This is the main script in lbmk, Libreboot’s build system. It is what executes all other parts of the Libreboot build system. The rules are as follows:

tl;dr break this script and you break Libreboot.


Symbolic link, pointing to the lbmk script. This is executed by the user, or by lbmk, referencing scripts under script/update/*/.


This directory contains helper scripts, to be included by main scripts using the . command (called the source command in bash, but we rely upon posix sh only).


Common variables, used by all scripts under script/update/blobs/.


Functions used by scripts under script/update/blobs/, for checking defconfig files. These files are checked because the scripts need to know whether a given blob is used; if it is, a path is then specified in defconfig, telling the blob script either where it is, or where it should be downloaded to.


Generic error handling, used by all lbmk scripts.


Used by the main script named lbmk, this provides initialisation of the TMPDIR environmental variable, allowing unified handling of /tmp within lbmk.


All scripts under script/ are executed only by the main lbmk script, conforming to the standard buildpath/mode/option e.g. build/boot/roms - so, running ./build boot roms would run script/build/boot/roms.


These are highly specialised build scripts, written for specific tasks, almost entirely in the context of building firmware images themselves, but some utils are also handled.

The scripts that create release archives are also located under this directory.


This script builds coreboot ROM images. It is largely a shim, which calls the roms_helper script, which does most of the legwork.

Command: ./build boot roms targetname

The targetname argument must be specified, chosen from this output:

./build boot roms list

Pass several board names if you wish to build only for specific targets. For example:

./build boot roms x60 x200_8mb

To build all targets, specify:

./build boot roms all

Since November 2022, this script can build images for x86 and ARM targets. The ARM targets are ChromeOS devices (chromebooks and such); Libreboot uses the U-Boot payload, rather than Google’s depthcharge bootloader. In this setup, U-Boot is running on the bare metal, as enabled by coreboot.

For x86 targets, these scripts build with the GRUB and/or SeaBIOS payloads inserted into the ROM images; secondary payloads like Memtest86+ are also handled and inserted here.


This script builds coreboot ROM images. It is not to be executed directly; user interaction must be done via the main roms script.

It heavily makes use of the target.cfg file, for a given board. This script will only operate on a single target, from a directory in config/coreboot/.

If grub_scan_disk is set, it sets that in the scan.cfg file that is to be inserted into a ROM image, when payload_grub is turned on.

It automatically detects if crossgcc is to be compiled, on a given coreboot tree (in cases where it has not yet been compiled), and compiles it for a target based on the arch entry in target.cfg.

It creates ROM images with GRUB, SeaBIOS, U-Boot, optionally with Memtest86+ also included, in various separate configurations in many different ROM images for user installation.

The romtype entry in target.cfg tells this script what to do with the ROM, after it has been built. Currently, it operates based on these possible values for romtype:

If no payload is defined in target.cfg, the roms_helper script will exit with error status.

If SeaBIOS is to be used, on libgfxinit setups, SeaVGABIOS will also be inserted. This provides a minimal VGA compatibility layer on top of the coreboot framebuffer, but does not allow for switching the VGA mode. It is currently most useful for directly executing ISOLINUX/SYSLINUX bootloaders, and certain OS software (some Windows setups might work, poorly, depending on the board configuration, but don’t hold your breath; it is far from complete).

If SeaBIOS is to be used, in vgarom setups or normal setups, SeaVGABIOS is not inserted and you rely on either coreboot and/or SeaBIOS to execute VGA option ROMs.

In all cases, this script automatically inserts several SeaBIOS runtime configurations, such as: etc/ps2-keyboard-spinup set to 3000 (PS/2 spinup wait time), etc/pci-optionrom-exec set to 2 (despite that already being the default anyway) to enable all option ROMs, unless vgarom setups are used, in which case the option is set to 0 (disabled) because coreboot is then expected to handle option ROMs, and SeaBIOS should not do it.

This script handles U-Boot separately, for ARM-based chromeos devices.

Essentially, the roms_helper script makes use of each and every part of lbmk. It is the beating heart of libreboot. Break it and you break Libreboot.

When the ROM is finished compiling, it will appear under a directory in bin/


It basically just does ls -1 but in a more fault-tolerant way. This is used in certain circumstances, such as ./build boot roms all where a script needs to know what build targets are available.

Command: ./build command options DIRECTORY


This builds coreboot utilities ifdtool and cbfstool, placing them under cbutils/ for use by other parts of lbmk.

Command: ./build coreboot utils


This builds the grub.elf file and keymap configuration files, placing these under elf/grub/ for use by script/build/boot/roms_helper.

Command: ./build grub payload


This builds the grub-mkstandalone utility under grub/, which is then used by script/build/boot/roms_helper to insert GRUB payloads inside coreboot ROM images.

Command: ./build grub utils


This builds release archives, containing ROM images for coreboot and/or serprog programmers. You must only run this after you’ve build all of the ROM images that you wish to release.

Command: ./build release roms

NOTE: This script scrubs certain binary blobs from release ROMs, such as Intel ME or MRC firmware. The release ROMs shall then exclude these blobs within them, requiring manual insertion by the user post-release. See:

Insert binary blobs on Sandybridge/Ivybridge/Haswell


This builds source archives. You must only run this after compiling crossgcc on all coreboot source trees, and after building the ROM images that you wish to release; in other words, it is recommended that you run ./build release roms first.

Command: ./build release src


Build firmware images for serprog-based SPI programmers, where they use an RP2040 MCU.

Example command: ./build serprog rp2040

The list argument is available:

./build serprog rp2040 list

Without arguments, all targets would be compiled, but you can specify a short list of targets instead, based on the output of list.


Build firmware images for serprog-based SPI programmers, where they use an STM32 MCU.

Example command: ./build serprog stm32

The list argument is available:

./build serprog stm32 list

Without arguments, all targets would be compiled, but you can specify a short list of targets instead, based on the output of list.


The handle scripts deal with Kconfig infrastructure across various projects used by lbmk. It also handles the compilation of crossgcc, coreboot’s cross compiling toolchain collection which is used for compiling coreboot itself and also U-Boot (but SeaBIOS is currently built using the host toolchain).


This is the other beating heart of Libreboot. Used heavily by Libreboot, this script is what handles defconfig files for SeaBIOS, U-Boot and coreboot; it used to be separate scripts, but the logic was unified under this single script.

It handles the following files (PROJECT can be coreboot, seabios or u-boot):

Basic command: ./handle make config FLAG projectname

FLAG values are (only one to be used at a time):

As for *projectname", this can either be coreboot, u-boot or seabios.

Example commands:

./handle make config -b coreboot
./handle make config -b coreboot x200_8mb
./handle make config -b coreboot x230_12mb x220_8mb t1650_12mb
./handle make config -x coreboot default
./handle make config -u seabios
./handle make config -m u-boot gru_bob

NOTE: the -x and -c options will cause an exit with zero status, when the target’s corresponding source tree is unavailable; a non-zero status is only return under fault conditions when said source tree is available. ALL other flags will cause the very same source tree to be downloaded and prepared, if unavailable and that too will return with non-zero status under fault conditions.

NOTE: “target” can indeed be the tree name, under some circumstances. For example, ./handle make config -m seabios default

After projectname, a target can be specified, but if no target is specified, then all targets will be operated on. For example, ./handle make config -b coreboot will attempt to build all coreboot ROM images.

NOTE: the coreboot projectname here shall cause the ROM images to go under elf/ - this is the no-payload ROM images, which are later used separately by script/build/boot/roms_helper to provide full images, with payloads inserted. It is an intentional design choice of Libreboot, to split it up this way and not use coreboot’s own build system to handle payloads.

In lbmk, there are two types of git download: simple downloads where only a single revision would ever be used, or multi downloads where different revisions are used depending on target.

All such downloads are simple downloads, except for coreboot, U-Boot and SeaBIOS which are multi downloads. The other requirement is that defconfigs be used, though this could be worked around in the future if a multi setup is needed on a project that does not use defconfigs (this is not yet the case in lbmk).

All of this used to about 20 different scripts, all with much-duplicated logic. Now it is unified, efficiently, under a single script.

Remember: code equals bugs, so less code equals fewer bugs.


Generic handling of Makefiles, and also cmake on some projects. This is used on projects with non-Kconfig-based build systems, where the step for compiling is basically cd projectdir/ && make.

Example commands:

./handle make file -b memtest86plus
./handle make file -c memtest86plus

The -b option runs make all. The -c option tries make clean first, and then make distclean.


These scripts pertain mostly to downloads, of either Git repositories or, where required on given mainboards, binary blobs.


This downloads binary blobs when needed, on a given coreboot target. It does this by scanning the defconfig files of that board, to know where the blobs are (or where they should be) within lbmk.

These blobs are then inserted at build time by the coreboot build system (as defined by defconfigs), or post-release by running the inject script.

More information is available here.


NOTE: Currently broken on some setups. This script is not recommended, but it can extract some binary blobs from vendor dumps. Use of it is ill advised, because it’s not complete, and there’s no guarantee what you’ll get from it.

More information is available here.


This is not used during the build process, but it can be run by the user on release ROMs (which do not contain non-redistributable blobs handled by these blob scripts, but those blobs are required). This script inserts those blobs into the coreboot ROM image; if you’re building from source, using lbmk, you do not need to run the inject script at all.

More information is available here.


This is called by the main blob download script, and downloads Intel MRC images for raminit and peripherals. Libre MRC setups are also provided in Libreboot, as an alternative.

Command: ./update blobs mrc

More information is available here.


Where Kconfig-based infrastructure is not used, and a project only has one revision in use by lbmk, this script is used. It downloads third party software (such as memtest86+), based on entries defined in config/git/revisions and then applies patches, if they exist.

Example command: ./update project repo memtest86plus


Similar to the above, and in fact it does use script/update/project/repo, but then the downloaded tree is copied to multiple directories based on target name. This is used for coreboot, U-Boot and SeaBIOS, to create multiple source trees.

The config/git/revisions file does not specify a revision for these projects; it literally says HEAD, nor are patches applied under this paradigm.

Instead, it looks for patches in config/projectname/target/patches where projectname could be coreboot for example, and target could be default on cros for example; those are tree names, but you could also specify a build target such as x200_8mb if it points to a tree name.

It also updates git submodules, where available. The target.cfg file is used, to know what revision is needed on a given target tree.

Example commands:

./update project trees coreboot
./update project trees seabios
./update project trees u-boot

With no additional arguments provided, it will download all trees for the given project. If you only want to download a specific tree, you can declare either the tree name itself or the target name (pointing to the tree name). For example:

./update project trees coreboot default
./update project trees coreboot x200_8mb

In the above example, x200_8mb is a build target and its target.cfg points to default as tree name, so the practical result of both commands will be exactly the same.

Downloaded source trees are only created for actual tree names; they are not duplicated for targets, where those targets refer to a tree. This saves time, and disk space.

This used to be separate scripts for coreboot and U-Boot, where SeaBIOS was treated as a simple clone (using logic similar to script/update/project/repo but the logic was unified into this one script, greatly simplifying lbmk.

Markdown file for this page:

Subscribe to RSS for this site

Site map

This HTML page was generated by the untitled static site generator.