I have a few of my own libreboot builds available on my gitbub. By default my custom roms have:
In this guide, I’ll explain exactly what I did to get my builds to look this way. By the end of this guide, you should be able to create your own themes either manually or by using my build system.
Libreboot is open source firmware for hardware initialization. Libreboot will only initialize hardware and then pass to a payload. The default payload for libreboot is GRUB. Linux does not require an actual bios, which is why linux systems can be booted directly from GRUB in libreboot without a more complex payload. GRUB can also chainload other payloads, such as seabios and tianocore which provide the ability to boot operating systems as a normal bios/EFI.
You might notice when installing a linux distro to your machine, that an installer will ask you where to install GRUB (EFI is different, but I won’t get into that here). The installer is basically asking you which physical disk will hold your operating system(s). When you select your disk (like /dev/sda) you might notice that the installer says something about “MBR on /dev/sdx.” The reason for that message is that GRUB isn’t really installed to your OS like a normal program. Instead, the code to run GRUB is placed in a special area of the disk called the Master Boot Record (MBR). When a BIOS runs, it looks for a boot program in the MBR in order to load and operating system.
The MBR isn’t the end of the story though. You might notice that whenever you update your kernel or change your GRUB theme that you are editing files on one of the main partitions of your disk. The grub-install command only runs when you first install your system, but the menu entries and theme can be changed without re-installing GRUB. The reason for this is that GRUB sources a configfile when it first runs. The configfile in question is generally located at /boot/grub/grub.cfg. That configfile includes all of the menuentries you see when you start up your system and the modules needed to load your OS. The configfile might also include the path to a theme file which defines the way GRUB menus appear, the fonts used, and the background image.
GRUB on a normal BIOS therefore works like this:
BIOS finds a disk with a bootloader (GRUB) and executes it > GRUB searches for a configfile on the disk to which it is installed and sources it > Configfile tells GRUB which boot options are available and sources a theme file if needed.
When you first install libreboot you need to use an external programmer to rewrite the code that runs from your machine’s BIOS chip. If you download any of the standard ROMS or any of my builds then the default payload is GRUB. This means that instead of your firmware looking for a bootloader on the disk, it loads the bootloader (GRUB) from the get-go.
The GRUB that runs on the BIOS chip is (almost) the same as the GRUB that would run if it were loaded from your disk. This means that we can do the same basic process to change the theme in libreboot’s GRUB as we would do for a normal BIOS. Instead of putting the configfile and theme file on the disk, we just put those files inside the ROM installed to the BIOS chip.
You probably have an EXT4 or btrfs partition on you computer’s disk. In the same way, you have a filesystem to read and separate files on your BIOS chip with libreboot. The filesystem on you BIOS chip is the Corbeboot Filesystem (cbfs). You can easily read and write from the filesystem on a libreboot ROM with the Coreboot Filesystem Tool (cbfstool). You can install cbfstool from you distro’s repos and then read the contents of a libreboot ROM. For example, here is the output from a libreboot ROM:
> cbfstool t400_8mb_usqwerty.rom print
FMAP REGION: COREBOOT
Name Offset Type Size Comp
cbfs master header 0x0 cbfs header 32 none
fallback/romstage 0x80 (unknown) 58136 none
fallback/ramstage 0xe440 (unknown) 110231 LZMA (242648 decompressed)
config 0x29340 raw 476 none
revision 0x29540 raw 711 none
build_info 0x29840 raw 100 none
fallback/dsdt.aml 0x29900 raw 15108 none
vbt.bin 0x2d440 raw 1412 LZMA (3863 decompressed)
cmos.default 0x2da00 cmos_default 256 none
cmos_layout.bin 0x2db40 cmos_layout 1840 none
fallback/postcar 0x2e2c0 (unknown) 20744 none
seabios.elf 0x33440 simple elf 61348 none
etc/ps2-keyboard-spinup 0x42440 raw 8 none
etc/pci-optionrom-exec 0x42480 raw 8 none
etc/optionroms-checksum 0x424c0 raw 8 none
etc/only-load-option-roms 0x42500 raw 8 none
vgaroms/seavgabios.bin 0x42540 raw 25600 none
fallback/payload 0x48980 simple elf 626548 none
grub.cfg 0xe1940 raw 6627 none
grubtest.cfg 0xe3380 raw 6615 none
(empty) 0xe4d80 null 7364452 none
bootblock 0x7ead00 bootblock 20640 none
The seabios.elf file is what grub loads when pressing B at
the main menu. To see the nuts and bolts, we can extract the grub
configuration file from the rom to inspect it further with
cbfstool t400_8mb_usqwerty.rom extract -n grub.cfg -f grub.cfg
.
You can see how grub chainloads seabios by inspecting the extracted
config.
> grep -A2 'seabios' grub.cfg
if [ -f (cbfsdisk)/seabios.elf ]; then
menuentry 'Load SeaBIOS (payload) [b]' --hotkey='b' {
set root='cbfsdisk'
chainloader /seabios.elf
}
fi
You can view the various devices available from GRUB by pressing c on the GRUB menu and typing ls. Generally, (cbfsdisk)/ is our ROM and (ahci0,msdosx)/ is one of the partitions on our disk. Running ls (cbfsdisk)/ will show you a similar output to what we see with cbfstool.
The file grub.cfg is the GRUB configfile loaded by libreboot when you start your machine. Just like you can theme libreboot on a proprietary BIOS machine by editing the configfile in /boot/grub/grub.cfg, you can edit GRUB in libreboot by editing this file in the cbfs.
If you inspect the grub.cfg file from above you’ll notice that it does not load any fonts, themes, or background images. Since the rom isn’t loading a font that can display the border box around text, these characters appear as ‘?’ in the 20210522 testing release. This issue can be fixed by adding a font to the rom image and telling grub to load it. GRUB’s default font can be found on most linux systems under /boot/grub/fonts/unicode.pf2 Add this font to the rom:
cbfstool t400_8mb_usqwerty.rom add -f unicode.pf2 -n unicode.pf2 -t raw
If you print the contents of the ROM, you’ll find that it now
includes the font we just added. You can then place
loadfont (cbfsdisk)/unicode.pf2
near the top of the grub
config to tell GRUB to use the font. You can then remove the old grub
config and replace it with the new one.
> cbfstool t400_8mb_usqwerty.rom remove -n grub.cfg
> cbfstool t400_8mb_usqwerty.rom add -f grub.cfg -n grub.cfg -t raw
Grub itself supports some pretty extensive theming. To create a grub theme, simply create theme.txt file and source it in the grub config set theme=(cbfsdisk)/theme.txt
After creating your theme, add the theme file, grub.cfg, and all fonts and backgrounds to the rom file with cbfstool.
The theme file can set all kinds of options such as the size and position of the boot menu, optional text, and background image. The overflow in the following text allows you to see easier how the ascii art renders, don’t worry that your browser has an error. As an example, here is the contents of my GRUB theme from my github:
desktop-image: "background.png" title-text: "" terminal-border: "0" terminal-left: "0" terminal-top: "0" terminal-width: "100%" terminal-height: "100%" + boot_menu { left = 0% width = 40% top = 10% height = 60% item_color = "#ffffff" selected_item_color = "#02CCFC" item_height = 20 item_padding = 5 item_spacing = 15 } + vbox { left = 47% top = 15% width = 50% + label { width = 40 height = 20 color = "#ffffff" text = "▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄"} + label { width = 40 height = 20 color = "#ffffff" text = "██ ████▄ ▄██ ▄▄▀██ ▄▄▀██ ▄▄▄██ ▄▄▀██ ▄▄▄ ██ ▄▄▄ █▄▄ ▄▄█"} + label { width = 40 height = 20 color = "#ffffff" text = "██ █████ ███ ▄▄▀██ ▀▀▄██ ▄▄▄██ ▄▄▀██ ███ ██ ███ ███ ███"} + label { width = 40 height = 20 color = "#ffffff" text = "██ ▀▀ █▀ ▀██ ▀▀ ██ ██ ██ ▀▀▀██ ▀▀ ██ ▀▀▀ ██ ▀▀▀ ███ ███"} + label { width = 40 height = 20 color = "#ffffff" text = "▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀"} } + vbox { left = 51% top = 40% width = 50% + label { width = 40 height = 20 color = "#ffffff" text = " ██ "} + label { width = 40 height = 20 color = "#ffffff" text = " ██ ██"} + label { width = 40 height = 20 color = "#ffffff" text = " ███"} + label { width = 40 height = 20 color = "#ffffff" text = " █████████████"} + label { width = 40 height = 20 color = "#ffffff" text = " ████████ "} + label { width = 40 height = 20 color = "#ffffff" text = " ██████"} + label { width = 40 height = 20 color = "#ffffff" text = " ██████"} + label { width = 40 height = 20 color = "#ffffff" text = " ████████"} + label { width = 40 height = 20 color = "#ffffff" text = " ████████████"} + label { width = 40 height = 20 color = "#ffffff" text = " ███████████████████████"} + label { width = 40 height = 20 color = "#ffffff" text = " ██████████████████████████████████"} + label { width = 40 height = 20 color = "#ffffff" text = " █████████████████████████ ███"} + label { width = 40 height = 20 color = "#ffffff" text = " ████████████ ███"} + label { width = 40 height = 20 color = "#ffffff" text = " ███████████ ████"} + label { width = 40 height = 20 color = "#ffffff" text = " ████████"} + label { width = 40 height = 20 color = "#ffffff" text = " ███"} + label { width = 40 height = 20 color = "#ffffff" text = " ████"} + label { width = 40 height = 20 color = "#ffffff" text = "██"} } + vbox { left = 5% top = 80% width = 40% + label { width = 40 height = 20 color = "#ffffff" text = "[↵] Boot selected Entry" } + label { width = 40 height = 20 color = "#ffffff" text = "[↑ and ↓ Key] Navigation" } + label { width = 40 height = 20 color = "#ffffff" text = "[E] Edit Selection" } + label { width = 40 height = 20 color = "#ffffff" text = "[C] GRUB Commandline" } }
If you flash this rom, you’ll see something like this when you boot:
In order to conserve space, I use ascii art in my themes rather than editing the actual background image. By doing so, we can compress the background image quite a bit, or even omit it entirely. That way, the “libreboot” text and the logo are generated by GRUB whenever we boot up.