EFI stub

From Gentoo Wiki
Jump to:navigation Jump to:search
This page contains changes which are not marked for translation.
Other languages:
Resources
This article has some todo items:
  • CONFIG_PM_STD_PARTITION for hibernation

An EFI (boot) stub[1] is a kernel that is an EFI executable (i.e., can boot directly from UEFI); EFI stub kernels may boot with or without a bootloader.

Kernel configuration

EFI stub support

The following kernel configuration options must be enabled:

KERNEL Enable EFI stub support for Kernels 6.1+
Processor type and features  --->
    [*] EFI runtime service support Search for <code>CONFIG_EFI</code> to find this item.
    [*]     EFI stub support Search for <code>CONFIG_EFI_STUB</code> to find this item.
    [ ]     EFI mixed-mode support (OPTIONAL) Search for <code>CONFIG_EFI_MIXED</code> to find this item.
Note
EFI mixed-mode support is only required to boot a 64-bit kernel from 32-bit firmware if the CPU supports 64-bit mode and EFI handover is enabled.

Installation

Tip
If an EFI System Partition (ESP) does not exist, please follow the steps to set it up first.

Automated

Warning
Since UEFI implementations differ between vendors, EFI Stub booting is not guaranteed to work for all UEFI systems; ensure a backup boot method is available before attempting (automated) EFI Stub booting.

Automated EFI stub booting is provided by sys-kernel/installkernel when the efistub USE flag is enabled; this relocates the regular boot layout from /boot to the EFI/Gentoo directory on the ESP.

Systemd kernel-install

When both the efistub and systemd USE flags are enabled on sys-kernel/installkernel, kernel-install calls kernel-bootcfg from app-emulation/virt-firmware to add or remove a boot entry for the installed or removed kernel. Installkernel is called automatically by the kernel's make install or by the Distribution Kernels' post-install phase; therefore, no special action is required when installing a new kernel, though the kernel-bootcfg-boot-successful init service from app-emulation/virt-firmware should be enabled to automatically make an entry for a new kernel permanent when it successfully boots.

For systemd systems:

root #systemctl enable --now kernel-bootcfg-boot-successful.service

For OpenRC systems:

root #rc-update add kernel-bootcfg-boot-successful default

When the to-be-registered kernel image is not a Unified Kernel Image (UKI), a kernel command line for the new entry is read from:

  • /etc/kernel/cmdline, or
  • /usr/lib/kernel/cmdline, or
  • /proc/cmdline

in this order. In addition, the initrd= kernel command line argument is automatically added if an initramfs was generated while installing the kernel. If on the other hand the to-be-registered kernel is a UKI, then no command line is added to the new entry; instead, the command line built into the UKI is used and the contents of this built-in command line are usually read from the same files when the UKI is generated.

Tip
The initramfs and kernel command line may also be embedded into the kernel: see the sections below for more information.

Traditional installkernel

When the efistub USE flag is enabled on sys-kernel/installkernel but the systemd USE flag is disabled Installkernel calls uefi-mkconfig from sys-boot/uefi-mkconfig to dynamically update the UEFI configuration; if the shim EFI executable is present in the same directory as the kernel image, the kernels will be chainloaded via Shim.

Manual

With the kernel configured with EFI Stub support and assuming the ESP is mounted at /efi, create a separate directory below /efi/EFI:

root #mkdir -p /efi/EFI/example
Note
On some systems /efi/EFI or /efi/efi (in lowercase) may already exist (assuming the ESP is mounted at /efi). The FAT file system of the ESP is not case-sensitive, but case-preserving (VFAT); with the default VFAT mount options, the above command will work in both cases. See the case sensitivity section in the FAT article for further details.

The kernel is created from the current kernel directory and copied to the new directory. This will install the kernel to /efi/EFI/example/bzImage.efi:

/usr/src/linux #make && make modules_install && cp arch/x86/boot/bzImage /efi/EFI/example/bzImage.efi
Tip
It is recommended when upgrading the kernel to keep an older version which is known to work:
user $tree -L 3 /efi
 /efi
 └── EFI
     └── example
         ├── bzImage-6.1.67.efi
         └── bzImage-6.1.70.efi

Root partition configuration

To boot directly from UEFI, the kernel or its initramfs must know where to find the root partition of the system to be booted; when using a bootmanager like grub, the kernel gets the root's path from the bootmanager via the command line; when using a stub kernel, two options may be used to give the kernel this information - choose one of these options:

Option 1: Configuring it into the kernel
KERNEL Root Partition information for Kernels 6.1+
Processor type and features  --->
    [*] Built-in kernel command line
    (root=PARTUUID=adf55784-15d9-4ca3-bb3f-56de0b35d88d rw)
Important
The value adf55784-15d9-4ca3-bb3f-56de0b35d88d is an example and must be replaced with the real root's UUID, which can be obtained by using the blkid command:
root #blkid | grep sda3
/dev/sda3: UUID="d1e0c1e0-3a40-42c5-8931-cfa2c7deae32" TYPE="ext4" PARTUUID="adf55784-15d9-4ca3-bb3f-56de0b35d88d"
The partition's PARTUUID is distinct from the filesystem's UUID; the UUID refers to the unique filesystem partition and must be used with a initramfs, while the PARTUUID refers to the disk partition and can be used when booting a kernel.
Option 2: Configuring it into UEFI

To add an entry with command line arguments:

root #efibootmgr --create --disk /dev/sda --label "Gentoo EFI Stub" --loader "\EFI\example\bzImage.efi" -u "root=/dev/sda3"
Important
When using a initramfs, setting the root location using a PARTUUID or (filesystem) UUID is generally preferable and less error prone.

More examples may be found in Creating a boot entry.

Optional: Kernel with initramfs

When using a kernel with an external initramfs (as a CPIO archive), additional steps are necessary. There is always an initramfs file when building a dist-kernel or using genkernel; when using a dist-kernel, this initramfs is named "initrd" and is in /usr/src/linux-6.1.57-gentoo-dist/arch/x86/boot/initrd and it must be copied into the ESP:

root #cp /path/to/my/initramfs/myinitrd.cpio.gz /efi/EFI/example/initrd.cpio.gz

Now the kernel needs its initramfs, and the initramfs needs its root; UEFI must provide both:

root #efibootmgr -c -d /dev/sda -p 1 -L "Gentoo EFI Stub" -l '\EFI\example\bzImage.efi' -u 'root=UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx initrd=\EFI\example\initrd.cpio.gz'

A Forum post explains in more detail, solving some user errors in the process: Forums topic - Booting UEFI without Grub

When using Early Userspace Mounting, the Generating the Initramfs and Using a Stub Kernel sections also provide a more thorough explanation.

Optional: Embedded initramfs

It's also possible to embed the initramfs directly into the kernel. Advantages include: the initramfs being verified by Secure Boot when verifying the kernel, a simplified boot process and EFI partition, and making loading the kernel by hand easier (because callers needn't specify the initramfs). Disadvantages include reduced flexibility, potential mistakes, and an unconventional boot setup.

Warning
If your initramfs contains Microcode, it is critical (for security) that it receives updates; when embedded, the initramfs can't update independently of the kernel and a kernel rebuild will be necessary every time the initramfs is updated. In particular, please ensure that if:
root #make clean
is not run prior to rebuilding the kernel,
root #rm usr/initramfs_data.cpio
is run to clear the cached initramfs CPIO archive from the last build.
  • When the initramfs has an update, the kernel is rebuilt and reinstalled.
  • If the initramfs is managed by sys-apps/portage, it is updated before the kernel.

The kernel supports both CPIO files (e.g., as produced by Dracut) and source directories (which are to be compressed into a CPIO archive). The following shows the latter with /usr/src/initramfs; however, it should be substituted with /path/to/my/initramfs/myinitrd.cpio.gz if the former case is desired (it usually is, unless using a Custom Initramfs).

KERNEL Embedding the initramfs into the kernel
General Setup  --->
    [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
    (/usr/src/initramfs) Initramfs source file(s)
EFI configuration

To ensure everything is functioning properly, the kernel may be booted without the initrd command line argument.

To create the UKI entry:

root #efibootmgr --create --disk /dev/sda --label "Gentoo EFI Stub" --loader "\EFI\example\bzImage.efi"

Optional: Booting without dedicated UEFI entry

UEFI specifies that when booting from a particular ESP, the default behavior is to load an EFI executable from a specific path, dependent on the host architecture: for example, on an AMD64 system, an EFI stub placed at $(ESP)\efi\boot\bootx64.efi would be automatically loaded when booting from that ESP.

Combined with setting the relevant drive's boot priority, this setup can automatically boot the kernel upon power-on without entering a boot menu whilst still preserving the option to do so if desired.

This can be used to circumvent the use of efibootmgr and the creation of UEFI entries with the cost of less flexibility; it runs the risk of rendering the system unbootable if a new, broken kernel were to be installed to the default path.

Backup kernel

It is recommended to always have a backup kernel; if a bootmanager like grub is already installed, it should not be uninstalled because grub can boot a stub kernel just like a normal kernel. Another possibility working with an additional UEFI entry: before installing a new kernel, the current one can be copied from /efi/EFI/example to /efi/EFI/backup. In the example below, other names were used and the second UEFI entry was created with efibootmgr:

root #efibootmgr
BootCurrent: 0002
Timeout: 1 seconds
BootOrder: 0002,0000,0001
Boot0000* Secure        HD(1,GPT,0adcbfee-21aa-42ea-9a9a-2e53bd05e6a2,0x800,0x7f800)/File(\EFI\secure\bzImage.efi)
Boot0001* gentoo        HD(1,GPT,0adcbfee-21aa-42ea-9a9a-2e53bd05e6a2,0x800,0x7f800)/File(\EFI\gentoo\grubx64.efi)
Boot0002* Backup        HD(1,GPT,0adcbfee-21aa-42ea-9a9a-2e53bd05e6a2,0x800,0x7f800)/File(\EFI\backup\bzImage.efi)

Microcode loading

When using a kernel without an initramfs, it is recommended to load the microcode described in the following articles:

Optional: Signing for Secure Boot

If Secure Booting this kernel, it must be signed with sbsign, part of app-crypt/sbsigntools:

root #sbsign --key {db key} --cert {db cert} /efi/EFI/example/bzImage.efi

More information is available at Secure Boot.

Warning
It is not possible to EFI Stub boot via sys-boot/shim due to the vanilla EFI Stub missing the required .sbat sbat section; as such, the used signing keys must be registered directly with the UEFI firmware to EFI Stub boot with Secure Boot enabled. See the UKI wiki page for an alternate EFI Stub boot method that supports booting via shim.

Troubleshooting

Tip
Some rare UEFI implementations do not accept individual EFI entries; in this case, it often works to use the removable media boot path, see EFI System Partition #removable media for details. For example, this command will copy the kernel for an amd64 UEFI:
root #cp /usr/src/linux/arch/x86/boot/bzImage /efi/EFI/boot/bootx64.efi
Be advised that this is against the UEFI specification as it circumvents the boot selection on internal drives (which are configured using EFI boot entries).
Tip
If command /usr/lib/kernel/postinst.d/95-efistub-uefi-mkconfig.install fails during the first install (no EFI kernel found), use mkdir /efi/Gentoo to create an empty folder.
root #efibootmgr -c -L "Gentoo Linux" -l '\EFI\Gentoo\bootx64.efi' -u 'root=PARTUUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
To create a boot entry with hibernation on swap partition:
root #efibootmgr -c -L "Gentoo Linux" -l '\EFI\Gentoo\bootx64.efi' -u 'root=PARTUUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX resume=PARTUUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'

See also

External resources

References

  1. The kernel doc lacks unification in the terminology. The doc page [1] is titled "(the) EFI Boot Stub", but the word "EFI stub" is also used.