Content:
One of the benefits of using UEFI over a traditional BIOS is the greater integration with installed operating systems.
Rather than dealing with drives, UEFI is able to store individual boot entries, complete with labels. While Linux OS’s are generally able to boot using UEFI, they do so through a bootloader – usually GRUB.
It’s possible to skip the bootloader, and set the system up to boot the OS directly through UEFI.
This is ideal if you want to remove the bootloader from the boot process – it can often slow things down. The UEFI boot menu is hidden unless you call for it, whereas the GRUB menu will show for a few seconds before auto booting.
It’s most beneficial if you’re dual booting, and rarely use the second drive. In this case, you’ll hardly ever need to invoke the boot menu.
Note that this is not for the faint of heart – for this guide, you’ll need to compile your own kernel. It’s assumed that you’re already familiar with kernel compilation.
Some distro kernels might have the correct configuration. In this case, the guide will work – but you’re on your own to check your kernel.
Checking If UEFI Is Enabled
To begin with, it’s important to check whether the system is using UEFI or not. There’s no point in creating a boot option we can’t use.
To do this, run
cat /sys/firmware/efi/
If this directory exists, your system is currently booted through UEFI.
If not, you’re using the older BIOS boot method. It might be possible to change this on your system, but this guide is geared towards systems already using UEFI.
Configuring the Kernel
The kernel needs to be configured to add UEFI stub support. To do this, open your kernel .config file.
nano /usr/src/linux/.config
Substitute the path if your linux sources are in a different directory.
In this file, check that the following options are set.
CONFIG_EFI=y
CONFIG_EFI_STUB=y
CONFIG_CMDLINE_BOOL=y
CONFIG_EFIVAR_FS=y
If any of these are not set, change them to match the lines above to enable them.
You’ll also need to set your kernel command line. This is equivalent to the GRUB_CMDLINE_LINUX
parameter used by the GRUB bootloader.
This option needs to be set a little differently. You’ll need find the PARTUUID
of the root partition of your OS. You can do this using blkid
.
blkid | grep /path/to/partition
In my case, /path/to/partition
would be /dev/nvme0n1p1
. If you’re unsure, running lsblk
will list partitions on your system. Look for the one with the mount point of /
.
The blkid
output will look something like
/dev/nvme0n1p1: UUID="25db7212-8b4a-4636-9da1-dd1a7ad962d1" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="f9e538be-9e70-46a2-8591-a3c7d9f910d7"
Add the PARTUUID
to your kernel config as follows.
CONFIG_CMDLINE="root=PARTUUID=f9e538be-9e70-46a2-8591-a3c7d9f910d7"
You can also add other options here. For example, to suppress console output during boot, add quiet
.
CONFIG_CMDLINE="root=PARTUUID=f9e538be-9e70-46a2-8591-a3c7d9f910d7 quiet"
You can now save your config, and recompile your kernel.
Populating the EFI Partition
With the kernel compiled, the kernel files can be moved to the EFI partition.
You can check where the EFI system partition (ESP) is mounted using blkid
. On my system, it’s /boot/efi
, but /boo
t is another common mount point. ESP
will be used in place of this path from now on – substitute this for the relevant path on your system.
Here, you have a choice. You can either use the default fallback EFI location, or create a new folder – The UEFI fallback for 64-bit Intel/AMD PCs is ESP/EFI/Boot/Bootx64.efi
. A new folder is preferable, particularly if you’re planning to multi-boot.
mkdir -p ESP/EFI/Folder
relacing Folder
with the folder name you wish to use.
Copy your /boot/vmlinuz
file to your folder of choice. At this point, you can name the file anything you want.
cp /boot/vmlinuz ESP/EFI/Gentoo/boot.efi
As an aside, bootloaders such as GRUB actually use the fallback location for their boot menu, as it’s the most reliable way of getting the system to boot. If you have a bootloader set up, the fallback location might already be populated. Overwriting this will prevent the bootloader from working.
If you’re using a custom location, I would strongly suggest ensuring the EFI fallback location is also populated. This can be either with an existing bootloader, or another vmlinuz file copied over.
If you’re going to use another vmlinuz
file, it’s a good idea to compile a different kernel version (with the EFI stub changes added). It will be easier to identify which kernel has booted.
cp /boot/vmlinuz-old ESP/EFI/Boot/Bootx64.efi
Ensure this exact file name is used – this is the defined fallback path. Replace vmlinuz-old
with the name of the vmlinuz file you’re copying over.
To explain why populating the fallback is recommended, take a look at our article on installing an OS to a Dell Wyse 3040. Unfortunately, firmware vendors do not always follow the UEFI specifications. It’s possible the custom UEFI path will be completely ignored by your system.
Creating the Boot Entry
If you’re using the EFI fallback location as your main location, you shouldn’t need to go any further. If you reboot your system and enter the system firmware boot menu (on my system, pressing F11 on boot brings this up), you should see an entry with the name of the drive.
UEFI OS: Samsung 960 EVO NVMe
Your system might word things slightly differently, but the entry should be there all the same. The name of the drive is used as each drive can only have one ESP, and each ESP only has one fallback path.
Otherwise, the boot menu entry needs to be created.
Make sure you know the path to your root partition, as you’ll need it later on.
Using efibootmgr
efibootmgr
is one of the easiest ways to add the boot entry. It hooks in to the UEFI, and can manage the boot entries set up there.
You’ll want to check that the EFI system variables are accessible. You can check this using
mount | grep efivars
If this returns a path, you’ll need to remount the variables to allow them to be written to. For security reasons, they are mounted read-only by default.
mount -o remount,rw -t efivarfs efivarfs /sys/firmware/efi/efivars
If the first command failed, your system firmware is not configured for UEFI.
Next, run efibootmgr to add the entry. An example command is broken down below.
efibootmgr -c -d /dev/nvme0n1 -p 1 -L "Gentoo" -l '\EFI\Gentoo\boot.efi'
-c
: This runs efibootmgr in create mode, to create a new entry.-d /dev/nvme0n1
: The drive containing the partition to boot – note this is the drive only, remove the partition number.-p 1
: The partition number on the selected drive. For example, a 1 here equates to a full path of/dev/nvme0n1p1
.-L "Gentoo"
: The boot label. This is the name that will show in the UEFI boot menu.-l '\EFI\Gentoo\boot.efi'
: The path on the ESP partition to the boot file. Set this to whatever path you created earlier on.
If this is successful, you will see the new boot entry list, with your entry added.
BootCurrent: 0002
Timeout: 1 seconds
BootOrder: 0000,0002,0001
Boot0001* Windows Boot Manager
Boot0002* UEFI OS
Boot0000* Gentoo
The boot order shows the order of the entries. Here we can see that the new entry, Boot0000*
(with the Gentoo
label), comes first in the boot order. The UEFI OS
is the UEFI fallback, which is the one I’ve currently booted from – you can see this by checking the BootCurrent
value.
You should now be ready to test the system. Remember to use the relevant key to bring up your system firmware boot menu when your restart the PC.
Testing
Once you have rebooted, you can use efibootmgr again to check the partition we booted from.
BootCurrent: 0000
Timeout: 1 seconds
BootOrder: 0000,0002,0001
Boot0001* Windows Boot Manager
Boot0002* UEFI OS
Boot0000* Gentoo
On this system, you can see the BootCurrent
is now set to 0000
, our new entry. In this case, the system is now set up and ready to go.
Additional boot entries can be added through the same method. Just bare in mind, it’s recommended to have an ESP per drive to prevent broken boot paths if a drive is removed.
Boot Entry Has Disappeared
You might find that the boot entry you’ve added is no longer there. This can occur because the path was set incorrectly, and your system firmware has removed the reference to the non-existent boot file.
It could also be down to your system firmware – as noted in the Dell Wyse 3040 article, some system firmware setups will have odd quirks when handling boot entries.
System Has Booted From the Wrong Partition
If your boot entry is still there, but a different boot option was used, it indicates that the system failed to boot through the new entry. It’s similar to the previous issue, but with the record still in tact.
Double check the path used to create your boot entry – you can see a verbose list of entries using
efibootmgr -v
System Is Not Booting
If the system is not booting, due to either a black screen or kernel panic, it’s possible your kernel is not set up correctly.
If you’re not using an initramfs, you might need to use one with your hardware. Using EFI stub, firmware not built in to the kernel will not be initialised until the kernel has loaded. If your hardware requires extra firmware to run correctly, you’ll need to create an initramfs containing this firmware. Check out our guide if you want to learn how to do this.
Otherwise, double check the kernel config options outlined earlier in the article. If the system gives an error message, this should give a clue as to where the issue lies.
Handling Updates
When compiling newer kernels, you’ll need to copy the new initramfs over the old one, to boot the new kernel. You’ll also need to consider how to handle backup entries – you don’t want to risk a failed kernel build bringing down the system.
On my system, I copy the running kernel to the path of a second ‘Gentoo (Previous)’ entry. My boot layout looks like this:
/EFI/Gentoo/current.efi
/EFI/Gentoo/previous.efi
/EFI/Boot/Bootx64.efi
The file current.efi
becomes previous.efi
, and the new kernel becomes current.efi
. Bootx64.efi
is an old file, that I update sporadically. You are free to use your own system – this is just an idea of how to set things up.
On the plus side, you’ll no longer need to run grub-mkconfig
or similar.
Cleaning Up
If everything is working, you can now remove your previous bootloader.