[9804 views]

[]

Linux UEFI boot

How to setup a Linux system that it boot via UEFI?

EFI System Partition

  1. Create a GPT partition table: use the g command in fdisk
  2. Create an EFI System Partition (ESP) of sufficient size (e.g. 500MB) to hold grub binaries, kernel and initramfs/initrd: use the t command in fdisk and select type 1
  3. Format the ESP as FAT32 and give it a nice label:
    mkfs.vfat -F 32 /dev/sda1
    fatlabel /dev/sda1 BOOT
    
  4. Create all your other partitions for the root filesystem and swap if you need as usual

The UEFI firmware will look for the ESP in the GPT and boot grub from it. UEFI boot does not require a BIOS Boot Partition (BBP) to hold the grub binary. In fact some UEFI firmwares do not like it when a BBP is present (HPE server for example) and will refuse to look for an ESP! So better remove the BBP.

FAT32 filesystems support no ownership, no permissions and no symlinks. So you can't create the infamous /boot/boot -> . symlink.

Installing Grub

Boot a kernel with at least EFIVAR_FS=Y or EFI_VARS=Y. It's fine to boot via legacy/CSM/non-EFI for that. This is required to be able to install the UEFI boot loader.

Mount the ESP under /boot and install the grub EFI binary on it with:

grub-install --target=x86_64-efi --efi-directory=/boot --removable

Create a suitable grub config file /boot/grub/grub.cfg:

default=0
timeout=3

# provides video modes
insmod efi_gop

menuentry 'Linux 5.14' {
  search --no-floppy --set=root --label BOOT
  linux /linux-5.14.4 root=LABEL=ROOT rootfstype=ext4 ro net.ifnames=0
  initrd /intel-uc.img /initrd.img
}

menuentry 'UEFI Firmware Settings' {
  fwsetup
}
  1. Note how we use the label to find the boot partition.
  2. Note how we use a label for the root filesystem too. This uses syntax recognized by mount, assuming your init script in initrd passes that string to mount.
  3. Note how kernel, intel microcode and initrd path use absolute path with respect to the filesystem on the ESP boot partition.

Install a kernel

The kernel needs to support at least these UEFI options:
 EFI=Y
 EFIVAR_FS=Y
 EFI_PARTITION=Y
 FB_EFI=Y

The EFI_VARS option is old and no longer required. Modern systems use only EFIVAR_FS.
See my Kernel Config Guide for more.

Copy the normal kernel binary to /boot. Make sure the name is consistent with the linux line in grub.cfg. Don't forget your initrd and you are ready to boot!

Firmware menu

Some UEFI firmwares (Tianocore, HPE servers) have an option to configure the boot menu entries and boot order. It may be necessary to add such a custom entry that specifies to load EFI/BOOT/BOOTX64.EFI.

Booting from USB Stick

If you are not confident of converting your system yet and just want to try and play, or for other reasons such as the lack of space for a FAT partition you can also use a different disk or USB stick. Just do the GPT formating and make a FAT partition on it and mount that under /boot to install Grub. You then probably have to tell your BIOS/Firmware to boot from it.

This way you can safely play without touching an existing working system.

UEFI under QEMU/KVM

For virtual machines under QEMU you need the Tianocore Open Virtual Machine Firmware. Gentoo's package is called sys-firmware/edk2-ovmf and installs into /usr/share/edk2-ovmf/. Start qemu with options like these:
qemu-system-x86_64 -machine q35,accel=kvm,smm=on \
 -cpu host \
 -boot menu=on \
 -global driver=cfi.pflash01,property=secure,value=on \
 -drive if=pflash,format=raw,unit=0,file=/usr/share/edk2-ovmf/OVMF_CODE.fd,readonly=on \
 -drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd \
 ...
If the firmware does not boot your disk you may need to enter the firmware menu and add a custom boot entry. This will let you select the EFI/BOOT/BOOTX64.EFI file.