EFI boot stub

From ArchWiki

An EFI boot stub (aka EFI stub) is a kernel that is an EFI executable, i.e. that can directly be booted from the UEFI.

Historically, this article and the Debian Wiki used the terms as one word (EFISTUB or EFIStub).

By default Arch Linux kernels are EFI boot stubs. If compiling the kernel, activate it by setting CONFIG_EFI_STUB=y. See The EFI Boot Stub for more information.

Before continuing, you need an EFI system partition and choose how it is mounted.

Tip:
  • pacman will directly update the kernel that the UEFI will read if you mount the ESP to /boot.
  • EFI boot stubs can also be booted indirectly using a boot loader:
    • There are several UEFI boot managers which can provide additional options or simplify the process of UEFI booting
    • This is especially useful if you are experimenting with kernel parameters or if you have multiple kernels/operating systems and your motherboard's UEFI boot menu is not easy to use.
    • A boot manager which has a file system driver for the partition where the kernel and initramfs reside (e.g. rEFInd) allows keeping them off of the ESP.

Booting an EFI boot stub

Note: The initramfs path passed to the kernel EFI boot stub should be relative to the EFI system partition's root and use backslashes (in accordance with EFI standards). For example, if the initramfs is located in esp/EFI/arch/initramfs-linux.img, the corresponding UEFI formatted line should be initrd=\EFI\arch\initramfs-linux.img. In the following examples we will assume that everything is under esp/.

Using UEFI directly

UEFI is designed to remove the need for an intermediate bootloader such as GRUB. If your motherboard has a good UEFI implementation, it is possible to embed the kernel parameters within a UEFI boot entry and for the motherboard to boot Arch directly. You can use efibootmgr or UEFI Shell v2 to modify your motherboard's boot entries.

Note:
  • Outdated UEFI implementations may have compatibility issues with the Linux kernel. If there is a newer version of your UEFI with bug fixes, consider flashing it with the manufacturer's recommended tool.
  • Some firmwares (notably Lenovo and Dell laptops) do not pass command line parameters from the boot entries in NVRAM to the EFI binaries.[1] In that case, the kernel and parameters can be combined into a unified kernel image, then create a boot entry with the resulting .efi file.

efibootmgr

To create a boot entry with efibootmgr that will load the kernel:

# efibootmgr --create --disk /dev/sdX --part Y --label "Arch Linux" --loader /vmlinuz-linux --unicode 'root=block_device_identifier rw initrd=\initramfs-linux.img'

Where /dev/sdX and Y are the drive and partition number where the ESP is located and root= parameters with your Linux root partitions.

Note: See kernel parameters for supported device name formats, persistent block device naming for how to obtain the corresponding value and Persistent block device naming#Kernel parameters for examples.

If omitted, then the first partition on /dev/sda is used as the ESP.

Note that the -u/--unicode argument in quotes is just the list of kernel parameters, so you may need to add additional parameters (e.g. for suspend to disk).

An example with LTS Linux kernel, NVME storage, BTRFS filesystem with specific subvolume and hibernation on swap partition:

# efibootmgr --create \
 --disk /dev/nvme0n1 --part 1 \
 --label "EFISTUB Arch" \
 --loader /vmlinuz-linux-lts \
 --unicode 'root=UUID=01a40dd8-28f0-4636-be1e-aeed60c98095 resume=UUID=2d877d5d-4ca1-4d46-a3d6-b6ee94cbbd78 rw rootflags=subvol=@ loglevel=3 quiet initrd=\initramfs-linux-lts.img'

For getting a list with the boot entries, setting the boot order or removing them, see efibootmgr.

Tip:

bcfg

Some UEFI implementations make it difficult to modify the NVRAM successfully using efibootmgr. If efibootmgr cannot successfully create an entry, you can use the bcfg command in UEFI Shell v2 (i.e., from the Arch Linux live iso).

First, find out the device number where your ESP resides with:

Shell> map

In this example, 1 is used as the device number. To list the contents of the ESP:

Shell> ls FS1:

To view the current boot entries:

Shell> bcfg boot dump

To add an entry for your kernel, use:

Shell> bcfg boot add N FS1:\vmlinuz-linux "Arch Linux"

Where N is the location where the entry will be added in the boot menu. 0 is the first menu item. Menu items already existing will be shifted in the menu without being discarded.

You can add kernel options directly:

Shell> bcfg boot -opt N "root=/dev/sda2 initrd=\initramfs-linux.img"

Or by creating a file on your ESP:

Shell> edit FS1:\options.txt

In the file, add the boot line. For example:

root=/dev/sda2 rw initrd=\initramfs-linux.img
Note: Add extra spaces in the beginning of the line in the file. There is a byte order mark at the beginning of the line that will squash any character next to it which will cause an error when booting.

Press F2 to save and then F3 to exit.

Add these options to your previous entry:

Shell> bcfg boot -opt N FS1:\options.txt

Repeat this process for any additional entries.

To remove a previously added item do:

Shell> bcfg boot rm N

Using UEFI Shell

If you do not want to create a permanent boot entry it is possible to launch the kernel from UEFI Shell since it is a normal UEFI application:

> FS0:
> \vmlinuz-linux root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 rw initrd=\initramfs-linux.img

In this case, the kernel parameters are passed as normal parameters to the EFI boot stub kernel.

To avoid needing to remember all of your kernel parameters every time, you can save the executable command to a shell script such as archlinux.nsh on your EFI system partition, then run it with:

> FS0:
> archlinux

Using a startup.nsh script

Some UEFI implementations do not retain EFI variables between cold boots (e.g. VirtualBox before version 6.1) and anything set through the UEFI is lost on poweroff.

The UEFI Shell Specification 2.0 establishes that a script called startup.nsh at the root of the ESP partition will always be interpreted and can contain arbitrary instructions; among those you can set a bootloading line. Make sure you mount the ESP partition on /boot and create a startup.nsh script that contains a kernel bootloading line. For example:

vmlinuz-linux rw root=/dev/sdX [rootfs=myfs] [rootflags=myrootflags] \
 [kernel.flag=foo] [mymodule.flag=bar] \
 initrd=\initramfs-linux.img

This method will work with almost all UEFI versions you may encounter in real hardware, you can use it as last resort. The script must be a single long line. Sections in brackets are optional and given only as a guide. Shell style linebreaks are for visual clarification only. FAT filesystems use the backslash as path separator and in this case, the backslash declares the initramfs is located in the root of the ESP partition.

Tips and Tricks

Boot entry with fallback ramdisk

Without a boot manager, the kernel command line is not changeable at boot time. To have at least some sort of fallback possibility, e.g. to use the initramfs-linux-fallback.img and/or start without Intel microcode, simply create a further boot entry with efibootmgr, e.g. labeled "Arch Linux fallback" and the desired fallback options.

Troubleshooting

Unbootable stub on some Dell systems

Several generation Dell firmwares are wrongly passing the arguments to the bootloader, thus making EFISTUB parse a null command line which normally means unbootable system (see the complete linux-efi thread).

A workaround has been found since Linux 5.10 to correct this behavior (see this commit ). For Linux < 5.10, you can use an efi-packer like arch-efiboot, or a different boot loader.

Changes to boot entries are not applied

Some motherboards, such as Haswell-era ASUS boards (as encountered on the french forum), will not notice changes to boot entries unless the system is booted with another pre-existing one.

See also