~whynothugo/candyboot

UEFI stub for bundling a kernel, cmdline and initrd from a single UEFI executable
Remove unnecessary semicolons
Simplify handling of NULL

clone

read-only
https://git.sr.ht/~whynothugo/candyboot
read/write
[email protected]:~whynothugo/candyboot

You can also use your local clone with git send-email.

#candyboot

Source | Issues | Patches | Chat

Simple and lightweight UEFI stub loader for the Linux kernel.

Candyboot is used to produce UEFI bundle executables which include a kernel, cmdline and initrd. A UEFI system can run this executable directly to boot into a regular Linux setup. The bundle can be signed with Secure Boot keys and ensures that no portion of the load chain has been tampered.

#Current state

  • Boots into a regular x86_64 setup.
  • No support for DeviceTree yet (e.g.: likely won't work on ARM yet).
  • Missing support for loading microcode.
  • Needs an audit by a second pair of eyes.

#Quirks

The current implementation creates a copy of the initrd in memory when the kernel requests it. It is likely that this can be improved in future by simply passing a pointer to the existing in-memory copy.

#Mode of operation

Candyboot must be bundled into a single executable with .linux, .initrd and .cmdline sections.

When executed, candyboot shall:

  • Retain a pointer to the .initrd section.
  • Register a UEFI boot service which exposes the LoadFile2 UEFI protocol with the LINUX_INITRD_DEVICE_PATH device path.
  • Encode the cmdline into UTF-16 (this is what the kernel expects when executed via a UEFI stub).
  • Execute the kernel image in the .linux section.

Once the kernel starts, it will detect the service exposed with the LINUX_INITRD_DEVICE_PATH device path and use it to load an initrd. Candyboot's registered service shall made a copy into a new buffer, and return a pointer to it to the kernel.

Candyboot does not rely on the handover protocol, which was deprecated as of Linux v5.10, in late 2020.

#Hints

  • The initrd= kernel command line parameter shall be ignored by the kernel.

#Security model

Because all of the above components (candyboot, kernel, cmdline, initrd) are stored in the executable file, signing this single file allows for a simple UEFI boot setup where Secure Boot can be effectively enabled. Candyboot trusts only its own embedded payload and does not read external files or runtime inputs. Therefore, it does not trust any inputs.

The previous stage bootloader (or the firmware itself) is responsible for validating the signature of the UEFI executable before executing it.

#Compatibility

Candyboot currently works with ukify:

# the .uname section is unused, but required by ukify.
ukify build \
  --linux path/to/vmlinuz \
  --initrd path/to/initramfs \
  --cmdline @path/to/cmdline \
  --uname "Linux Edge via CandyBoot" \
  --stub path/to/candyboot.efi \
  --output path/to/ESP/efi/boot/bootx64.efi

Candyboot does not currently work with efi-mkuki due to some hard-coded sizes. See: https://github.com/jirutka/efi-mkuki/issues/4

#Trivia

  • Candyboot is smaller than both gummiboot-efistub and systemd-efistub.
  • Gummiboot is unmaintained, and depends on Linux's deprecated handover protocol. It also won't compile with recent versions of its dependencies.

#Licence

This project is licensed under the ISC licence. See LICENCE.md for details.