User:Pietinger/Tutorials/Boot kernel via UEFI
Booting a kernel directly with UEFI without using a bootmanager.
Tutorial: Boot kernel via UEFI
This tutorial shows you all the steps you need to take if you want to boot your manually configured kernel directly from UEFI instead of using a boot manager. It is not valid if you have a kernel with associated initramfs (*) in use. In this case, just read this and then read (and do): EFI_stub
(*) More exact: This only applies if you are using a kernel with an external CPIO as initramfs. If you use a kernel with an embedded initramfs you can of course also use this guide :-)
Installation
Prerequisites for an UEFI boot
... which you have normally already done. Think of it as a checklist.
1. Your BIOS setting must allow an UEFI boot instead an old CSM boot. So "CSM mode" is disabled in your BIOS. Some BIOS call this option "Legacy mode"; then this must be disabled.
2. Your harddisk must have GPT (instead MBR). You have done this already in Handbook:AMD64/Installation/Disks. If not and you work with parted you do this with (EXAMPLE):
root #
parted -a optimal /dev/nvme0n1
> mklabel gpt
3. One partition is reserved to be the ESP (Efi System Partion) The ESP is usually the first partition of your harddisk. It is highly recommended to use only ONE ESP in your system. If you have more operating systems and you have therefore already an ESP then you should use only this one and do not create another ESP. In parted you do this as first with:
> unit mib > mkpart primary 1 256
4. This ESP must have the ESP flag enabled == setting the correct Partition type GUID (ESP has => C12A7328-F81F-11D2-BA4B-00A0C93EC93B) [[1]]. You have done this already in Handbook:AMD64/Installation/Disks#Creating_the_EFI_System_Partition_.28ESP.29 with the command t. In parted you do this with:
> set 1 boot on
You can check whether it is already set with (Example of my disk; see line number 1):
root #
parted -l
Model: Samsung SSD 980 PRO 1TB (nvme) Disk /dev/nvme0n1: 1000GB Sector size (logical/physical): 512B/512B Partition Table: gpt Disk Flags: Number Start End Size File system Name Flags 1 1049kB 268MB 267MB fat32 ESP boot, esp 2 268MB 4295MB 4027MB linux-swap(v1) Swap 3 4295MB 1000GB 996GB ext4 Root
5. Optional: I work with Partition Labels and gave this partition the name: "ESP":
> name 1 ESP
6. This partition must be formatted with a FAT variant. It is recommended to use FAT32. You have done this already in Handbook:AMD64/Installation/Disks#Applying_a_filesystem_to_a_partition with:
root #
mkfs.vfat -F 32 /dev/nvme0n1p1
7. On this partition must be a directory named \EFI (or \efi because we have FAT and dont care if it is uppercase or lowercase). If you have already other Operating Systems or you have installed a bootmanager like grub, you will have it already. If not we will create it in the next chapter. Hint: If you mount this partition in a Linux system to a directory like /efi you will SEE it as: /efi/EFI (or /efi/efi).
8. You will need a mount point in your root directory of your root partition. In the good old days this was /boot. Since September 2023 there is a new recommendation to use /efi as mount point.
See more here: [[2]]
Usually you have done this already in Handbook:AMD64/Installation/Base#UEFI_systems. If not create it with:
root #
mkdir /efi
9. Of course this partition must be mounted to this mount point later. You can do this always manual with:
root #
mount /dev/nvme0n1p1 /efi
Or you create an entry in your /etc/fstab like this:
/dev/nvme0n1p1 /efi vfat noauto,noatime 0 2
and can now do a:
root #
mount /efi
Usually you have done it already in Handbook:AMD64/Installation/System#For_an_EFI_system
Because I work with Partition Labels (see 5) my line is:
PARTLABEL=ESP /efi vfat noauto,noatime 0 2
If you ask why we use the parm "noauto" the answer is: It is good old Unix tradition to not mount a partition which is not used for daily work and so this partition is secure when doing a crazy "rm -rf /" ... ;-)
10. If you want boot your kernel with UEFI then your kernel must be configured to be a "stub" Kernel. We have already done it ! You may check the kernel settings here: EFI_stub
Further requirements
... which you probably still have to fulfill:
1. You need the "efibootmgr". Get it with Efibootmgr#Emerge
2. Mount your ESP to /efi if not already done and check if there is already a directory called \EFI or \efi. If it already exists, note whether it is capitalized or not and adapt all subsequent commands accordingly. If it does not exist, create it with :
root #
mkdir /efi/efi
3. Because it is highly recommended to always have a backup kernel we create two subdirectories. These names are completely arbitrary and you can use whatever you prefer. See this as an example:
root #
mkdir /efi/efi/backup
root #
mkdir /efi/efi/secure
4. Make sure that your kernel gets the information where its root partition is. The kernel gets this information via the command line parameter "root=". There are two ways (*) to pass this parameter. I only use the built-in command line option. If not already configured do:
Processor type and features --->
[*] Built-in kernel command line
(root=PARTUUID=6979eed7-ffaf-425e-8ac7-2832f6d15e0a ro)
[*] Built-in command line overrides boot loader arguments
(* 2nd way: INSTEAD of these settings in the kernel configuration you could use also UEFI; see more here: User:Pietinger/Tutorials/Kernel_Commandline_Parameter#Using_UEFI)
Of course you have to use your PARTUUID of your root partition, and finish this with a make and a make modules_install. But we don't need a make install anymore, because we do NOT want to copy the kernel to /boot, but ...
5. Copy your newly created kernel (twice) into these directories and rename it to bzImage.efi at the same time:
root #
cp /usr/src/linux/arch/x86/boot/bzImage /efi/efi/backup/bzImage.efi
root #
cp /usr/src/linux/arch/x86/boot/bzImage /efi/efi/secure/bzImage.efi
If you are thinking "I only copy the backup kernel when I do the next kernel update", then you should know the following:
Most (all?) UEFIs check at system startup whether the UEFI entries also point to an actually existing binary.efi ... and if not, UEFI simply deletes the entry. This means that if you make an entry for \efi\backup\bzImage.efi in the next chapter, it will be displayed, but if no \efi\backup\bzImage.efi exists, your UEFI will delete this entry the next time you start the system.
Create the necessary UEFI entries
If we create a new UEFI entry with efibootmgr, this will also be the first entry in the boot sequence. Therefore, we must first create the entry for our backup kernel and then the entry for the kernel we always want to boot. The name we assign with the parameter "-L" is the name you will see in the BIOS and can of course be customized by you (and should not be too long). Because UEFI see the ESP as FAT partition you must use BACKSLASHES. If your ESP is the first partition, we do not need the "-p" parameter. If your ESP is the second (or third) partition of your hard disk, add "-p 2" (or "-p 3"). Of course you have to assign exactly the names you created under (3) for the "-l" parameter.
root #
efibootmgr -c -d /dev/nvme0n1 -L "Backup" -l "\efi\backup\bzImage.efi"
root #
efibootmgr -c -d /dev/nvme0n1 -L "Secure" -l "\efi\secure\bzImage.efi"
If you get an error from efibootmgr then you miss probably a kernel setting (not possible if you have configured with my tutorials) OR you miss the mounting of "efivarfs". See more here: Efivarfs#Kernel and Efibootmgr#EFI_vars
You can finally check it with:
root #
efibootmgr
BootCurrent: 0002 Timeout: 1 seconds BootOrder: 0002,0001,0000 Boot0000* gentoo HD(1,GPT,0adcbfee-21aa-42ea-9a9a-2e53bd05e6a2,0x800,0x7f800)/File(\EFI\gentoo\grubx64.efi) Boot0001* Backup HD(1,GPT,0adcbfee-21aa-42ea-9a9a-2e53bd05e6a2,0x800,0x7f800)/File(\EFI\backup\bzImage.efi) Boot0002* Secure HD(1,GPT,0adcbfee-21aa-42ea-9a9a-2e53bd05e6a2,0x800,0x7f800)/File(\EFI\secure\bzImage.efi)
This example shows also a grub which was installed before. It is not necessary to deinstall the grub, because you can use it also as a backup.
If you reboot now, UEFI should start your kernel directly from /efi/efi/secure :-)
Cheat Sheets
Cheat Sheets for a standard stub kernel
- Updating to a new kernel version:
root #
emerge -1uvDp gentoo-sources
root #
mount /efi
root #
# go into the directory of the new kernel:
root #
cd /usr/src/linux-X.Y.Z-gentoo
root #
cp /usr/src/linux/.config .
root #
make oldconfig
root #
# For X use nr. of your CPU cores:
root #
make -j X
root #
make modules_install
root #
# We move our current kernel to its backup place
root #
mv /efi/efi/secure/bzImage.efi /efi/efi/backup/.
root #
# and copy the new kernel to
root #
cp arch/x86/boot/bzImage /efi/efi/secure/bzImage.efi
root #
# Maybe you want to backup your configuration. I do this into:
root #
cp .config /etc/MY/config-X-Y-Z
root #
eselect kernel list
root #
eselect kernel set X
root #
umount /efi
root #
reboot
- Changing the configuration of your used kernel:
root #
mount /efi
root #
cd /usr/src/linux
root #
make menuconfig
root #
make -j X
root #
make modules_install
root #
mv /efi/efi/secure/bzImage.efi /efi/efi/backup/.
root #
cp arch/x86/boot/bzImage /efi/efi/secure/bzImage.efi
root #
cp .config /etc/MY/config-X-Y-Z-revA
root #
umount /efi
root #
reboot
Cheat Sheet for a stub kernel booted with SecureBoot
I have SecureBoot enabled and did this: [[3]]
Therefore instead this line in both CheatSheets above:
root #
cp arch/x86/boot/bzImage /efi/efi/secure/bzImage.efi
I do:
root #
sbsign --key /mnt/stick/keys/DB.key --cert /mnt/stick/keys/DB.crt --output /efi/efi/secure/bzImage.efi arch/x86/boot/bzImage
You can see here that the sbsign command also takes over the copying at the same time. Of course you have to adapt this to your circumstances.