The Linux kernel supports EFISTUB booting which allows EFI firmware to load the kernel as an EFI executable. The option is enabled by default on Arch Linux kernels, or if compiling a the kernel one can activate it by setting
CONFIG_EFI_STUB=y in the Kernel configuration. See The EFI Boot Stub for more information.
With EFISTUB a kernel can be booted directly by a UEFI motherboard or indirectly using a boot loader. Using a boot loader is recommended if you have multiple kernel/initramfs pairs and your motherboard's UEFI boot menu is not easy to use.
Preparing for EFISTUB
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
Using a boot manager
There are several UEFI boot managers which can provide additional options or simplify the process of UEFI booting - especially if you have multiple kernels/operating systems. See Arch boot process#Boot loader for more information.
Using UEFI Shell
It is possible to launch an EFISTUB kernel from UEFI Shell as if it is a normal UEFI application. In this case the kernel parameters are passed as normal parameters to the launched EFISTUB kernel file.
> fs0: > \vmlinuz-linux root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 rw initrd=\initramfs-linux.img
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 UEFI System Partition, then run it with:
> fs0: > archlinux
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.
The command looks like
# efibootmgr --disk /dev/sdX --part Y --create --label "Arch Linux" --loader /vmlinuz-linux --unicode 'root=PARTUUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX rw initrd=\initramfs-linux.img' --verbose
Y are the drive and partition number where the ESP is located. Change the
root= parameter to reflect your Linux root partition. Note that the
--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 or microcode).
After adding the boot entry, you can verify the entry was added properly with:
# efibootmgr --verbose
efibootmgrversion combinations might refuse to create new boot entries. This could be due to lack of free space in the NVRAM. You can try deleting any EFI dump files
# rm /sys/firmware/efi/efivars/dump-*
Or, as a last resort, boot with the
efi_no_storage_paranoia kernel parameter. You can also try to downgrade your efibootmgr install to version 0.11.0. This version works with Linux version 4.0.6. See the bug discussion FS#34641, in particular the closing comment, for more information.
To set the boot order, run:
# efibootmgr --bootorder XXXX,XXXX --verbose
where XXXX is the number that appears in the output of
efibootmgr command against each entry.
The forum post titled [Solved]The linux kernel with build in bootloader? might also be of interest.
efibootmgr with .efi file
If using Secure Boot and sign the initramfs and kernel then create a bootable .efi image, can be used directly to boot the .efi file:AUR and AUR to generate your own keys for
# efibootmgr --create --disk /dev/sdX --part partition_number --label "label" --loader "EFI\folder\file.efi" --verbose
Seefor an explanation of the options.
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 by using:
In this example,
1 is used as the device number. To list the contents of the ESP do:
Shell> ls fs1:
To view the current boot entries do:
Shell> bcfg boot dump
To add an entry for your kernel, use:
Shell> bcfg boot add N fs1:\vmlinuz-linux "Arch Linux"
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.
To add the necessary kernel options, first create a file on your ESP:
Shell> edit fs1:\options.txt
In the file add the boot line. For example:
root=/dev/sda2 ro initrd=\initramfs-linux.img
F2 to save and then
F3 to exit.
To add these options to your previous entry do:
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
Some of the tools above, and more, are briefly discussed in rEFInd#Tools.
Using a startup.nsh script
Some UEFI implementations do not retain EFI variables between cold boots (e.g. VirtualBox) and anything set through the UEFI firmware interface 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=\intel-ucode.img] initrd=\initramfs-linux.img
This method will work with almost all UEFI firmware 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. Only Intel microcode is loaded in the booting parameters line; AMD microcode is read from disk later during the boot process; this is done automatically by the kernel.