Using UEFI Boot Without a Bootloader

calendar

April 25, 2022

categories
Guides
tags
boot linux uefi
comments

1 Comment

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 /boot 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.

If you like what we do, consider supporting us on Ko-fi