One bootx64.efi to rule them all

Barry recently blogged about gummiboot, which contains an interesting link to a feature of gummiboot that I overlooked previously. Barry linked to a phoronix article, which linked to a blog post from Harald.

TL;DR: gummiboot has a feature to build a single UEFI binary that contains Linux kernel, initrd, and the kernel command line. One UEFI file that contains the entire OS.

Yes, with this, you can have one bootx64.efi (bootloader) that actually contains the entire operating system (kernel, initrd, etc). While the idea is not new - Rob Landley pushed for ability to embed initrd into vmlinuz a long time ago - this is one step even better: embedding into the bootloader!

Why would we even bother? For one thing, it enables you to carry a stick with FAT32 partition in it, and a single file strategically located and named in /EFI/boot/bootx64.efi which contains the entire operating system for recovery and rescue purposes. It also means the return of boot-time virus - this time in the form of boot-loader virus (instead of boot-sector) from the days past if you are not careful.

Another thing is - if you run an embedded system with UEFI bootloader, after your OS are loaded entirely into the RAM, you can happily replace/upgrade your OS ("firmware") in one swop - there are no transactions needed to check if the bootloader update works ok, if the kernel update works okay, if the initrd works okay ... you just replace one file, if that one file update is okay (checkum matches etc) then all is good.

Harald has the code here, but it's somewhat tied to Fedora and systemd. Here is the extracted code that does the actual magic.
#!/bin/sh

echo your kernel cmdline > cmdline.txt
objcopy \
--add-section .osrel=/etc/os-release --change-section-vma .osrel=0x20000 \
--add-section .cmdline="cmdline.txt" --change-section-vma .cmdline=0x30000 \
--add-section .linux="/path/to/your/vmlinuz" --change-section-vma .linux=0x40000 \
--add-section .initrd="/path/to/your/initrd" --change-section-vma .initrd=0x3000000 \
linuxx64.efi.stub "$1"


The only catch is this - where does this "linuxx64.efi.stub" come from?

This EFI stub is built as part of the gummiboot bootloader. Gummiboot is "obsoleted" as its content are "absorbed" into systemd (and renamed to systemd-boot or something); but the code still exists and still works nicely here: https://cgit.freedesktop.org/gummiboot/ - you just need to checkout one commit before the final one (the final commit deletes everything to persuade people to move to systemd-boot).

I tested this with Fatdog64's initrd, with and without basesfs in it. Without basesfs - I ended up with 61MB bootx64.efi. With basesfs, I ended up with 366MB bootx64.efi. Both works as expected when launched from qemu as long as I have 2GB of RAM or more.



Posted on 19 Apr 2016, 11:09 - Categories: Linux General
Edit - Delete


Comments:

Posted on 15 Dec 2018, 13:09 by abhishekp76
"All in one bootloader does not work with some Dell UEFI or Qemu"
Hi,
This works great on some intel(NUC) and ASUS systems. On some Dell laptops the kernel gets passed no command line.

I thought I will debug this in Qemu but it fails to load there at all (following instruction here https://wiki.osdev.org/UEFI)

Any ideas?

Thanks


Delete

Posted on 8 Feb 2019, 13:06 by jamesbond
"RE: All in one bootloader does not work with some Dell UEFI or Qemu"
This has been quite a while, and I don't have a Dell system to test. I did test this qemu and it worked. To get qemu to run in UEFI, you just need two things:
a) an UEFI bios, and
b) use the cirrus vga parameter.

In short, you need to append "-bios uefi-bios.bin -vga cirrus" to whatever you qemu line is.

You can find free copies of UEFI bios for qemu from many different places; or, if you're running Fatdog64, then it's already included.
Delete



Add Comment

Title
Author
 
Content
Show Smilies
Security Code 4100508
Mascot of Fatdog64
Password (to protect your identity)