UEFI Bootloaders

From ArchWiki
Revision as of 02:00, 23 January 2013 by Bluerider (Talk | contribs) (Setting up EFISTUB)

Jump to: navigation, search

This page contains info about various UEFI Bootloaders capable of booting Linux kernel. It is recommended to read the UEFI and GPT pages before reading this page. The following bootloaders (listed in decreasing order of stability) are explained here:

Linux Kernel EFISTUB

Linux (Kernel >= 3.3) supports EFISTUB (EFI BOOT STUB) booting. It is enabled by by default on Arch Linux kernels or can be activated by setting CONFIG_EFI_STUB=y in the Kernel configuration (see The EFI Boot Stub for more information).

A single EFISTUB kernel is not capable of launching other kernels, hence each EFISTUB Kernel + Initramfs pair requires a separate boot menu entry. It is recommended to use a UEFI Boot Manager to manage multiple kernels.

Setting up EFISTUB

  1. Create a FAT32 UEFI System Partition
  2. Mount the UEFI System Partition at /boot/efi with # mount <UEFI Partition /boot/efi
  3. Create /boot/efi/EFI/arch/ directory # mkdir /boot/efi/EFI/arch/
  4. Copy the following files from source to destination
Boot File Source UEFI Destination
/boot/vmlinuz-linux to /boot/efi/EFI/arch/vmlinuz-linux.efi
/boot/initramfs-linux.img /boot/efi/EFI/arch/initramfs-linux.img
/boot/initramfs-linux-fallback.img /boot/efi/EFI/initramfs-arch-fallback.img
Warning: Linux Kernel EFISTUB booting uses \ instead of / and should be relative to the UEFI System Partition's root. For example, if the initram is located in /boot/efi/EFI/arch/initramfs-linux.img, the corresponding UEFI formatted line would be \EFI\arch\initramfs-linux.img. Failure to convert the options will lead to a system hang without any error message from the firmware or kernel.

Sync EFISTUB Kernel in UEFISYS partition using Systemd

Systemd init system supports defining tasks that should be performed when certain files/paths are changed. This feature of systemd is used to copy updated EFISTUB kernel and initramfs files when they are updated in /boot, like during package updates or during manual run of mkinitcpio etc.

For this create the files as defined below:

Description=Copy EFISTUB Kernel to UEFISYS Partition


Description=Copy EFISTUB Kernel to UEFISYS Partition

ExecStart=/bin/cp -f /boot/vmlinuz-linux /boot/efi/EFI/arch/vmlinuz-arch.efi
ExecStart=/bin/cp -f /boot/initramfs-linux.img /boot/efi/EFI/arch/initramfs-arch.img
ExecStart=/bin/cp -f /boot/initramfs-linux-fallback.img /boot/efi/EFI/arch/initramfs-arch-fallback.img

After creating the files run:

# systemctl enable efistub-update.path
# systemctl start efistub-update.path

Sync EFISTUB Kernel in UEFISYS partition using Incron

Incron can also be used to automatically sync the EFISTUB kernel after updates.

First, install the incron package from the Official Repositories.

Next you will need to set up a script to do the actual copying. You can call this script whatever you want, but make sure you use absolute paths in the commands.

File: /usr/local/bin/efistub-update.sh
/bin/cp -f /boot/vmlinuz-linux /boot/efi/EFI/arch/vmlinuz-arch.efi
/bin/cp -f /boot/initramfs-linux.img /boot/efi/EFI/arch/initramfs-arch.img
/bin/cp -f /boot/initramfs-linux-fallback.img /boot/efi/EFI/arch/initramfs-arch-fallback.img

Specify which file to watch for changes in /etc/incron.d/efistub-update.conf. The first parameter is the file to watch: /boot/initramfs-linux-fallback.img. The second parameter IN_CLOSE_WRITE is the action to watch for. The third parameter /usr/local/bin/efistub-update.sh is the script to execute.

File: /etc/incron.d/efistub-update.conf
/boot/initramfs-linux-fallback.img IN_CLOSE_WRITE /usr/local/bin/efistub-update.sh

Now just add incrond to the daemon list in /etc/rc.conf and it will automatically start up and copy the new files to the proper place every time the kernel is updated.

Sync EFISTUB Kernel in UEFISYS partition using Mkinitcpio hook

This uses a hook that spawns a background process, which waits for the generation process to finish, then copies the finished kernel and initrd.

This approach doesn't need a system level daemon to function.

File: /usr/lib/initcpio/install/efistub-update
#!/usr/bin/env bash

build() {
    local kernel= image=
    while getopts ':c:S:' OPT; do
        case $OPT in
        'c') kernel=$OPTARG;;
        'S') image=$OPTARG;;

    /root/watch.sh $image $kernel &

help() {
    cat <<HELPEOF
This hook simply waits for mkinitcpio to finish and copies the finished ramdisk and kernel to UEFI

# vim: set ft=sh ts=4 sw=4 et:

File: /root/watch.sh




while [[ -d "/proc/$PPID" ]]; do
    sleep 1

echo "Synced $INITRD to $EFI_DIR"

Then simply add efistub-update to the list of hooks in /etc/mkinitcpio.conf


There are various ways of booting EFISTUB kernels. Those described here are:

  1. Using rEFInd UEFI Boot Manager <-- Nice boot GUI.
  2. Using Gummiboot Boot Manager
  3. Using UEFI Shell
  4. Using efibootmgr entry <-- will load Arch Linux directly. No GUI.

Using rEFInd

rEFInd is a fork of rEFIt Boot Manager (used in Intel Macs) by Rod Smith (author of GPT-fdisk). rEFInd fixes many issues in rEFIt with respect to non-Mac UEFI booting and also has support for booting EFISTUB kernels and contains some features specific to them. More info about rEFInd support for EFISTUB is at http://www.rodsbooks.com/refind/linux.html .

Install the refind-efi package from [extra]

# pacman -S refind-efi

Then run the below commands ($esp is the mountpoint of UEFISYS partition)

Tip: The UEFISYS partition is usually mounted at /boot/efi
# mkdir -p $esp/EFI/refind

For 64-bit UEFI

# cp /usr/lib/refind/refind_x64.efi $esp/EFI/refind/refind_x64.efi

For 32-bit UEFI

# cp /usr/lib/refind/refind_ia32.efi $esp/EFI/refind/refind_ia32.efi

Common commands:

# cp /usr/lib/refind/config/refind.conf $esp/EFI/refind/refind.conf
# cp -r /usr/share/refind/icons $esp/EFI/refind/icons

Edit $esp/EFI/refind/refind.conf according to your requirements. The file is well documented/commented. After that create $esp/EFI/arch/refind_linux.conf as shown below (example):

Warning: refind_linux.conf is currently ignored for some reason.
"Boot with defaults" "root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 ro rootfstype=ext4 add_efi_memmap systemd.unit=graphical.target"
"Boot to Terminal"   "root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 ro rootfstype=ext4 add_efi_memmap systemd.unit=multi-user.target"

Please notice the difference between the standard UUID and the PARTUUID shown by ls -l /dev/disk/by-partuuid/.

Note: refind_linux.conf should be in the same directory as the kernel and initramfs files, not the directory refindx64.efi resides.

These options are displayed as a submenu by rEFInd. The sub-menu can be accessed by using "+" or "insert" keys.

In non-Mac systems create an entry for rEFInd using efibootmgr.

# modprobe efivars
# efibootmgr -c -g -d /dev/sdX -p Y -w -L "rEFInd" -l '\EFI\refind\refindx_64.efi'
Tip: If booted under UEFI, the UEFISYS drive and partition can be determined by running
$ mount -l | awk '/ESP/ {print $1}')

where /dev/sdX is the drive and Y is the partition number of UEFISYS in /dev/sdXY.

Systemd Automation
Tip: To automate the process of copying refind files and updating the nvram (if needed) use the following script
Note: Save this script as /usr/lib/systemd/scripts/refind_name_patchv2
Tip: If you want to change the directory that refind is installed in the UEFISYS partition, just change the value of $refind_dir in the script
## COPYRIGHT 2013 : MARK E. LEE (BLUERIDER) : mlee24@binghamton.edu; mark@markelee.com

## LOG
## 1/17/2013 : Version 2 of refind_name_patch is released
##           : Supports long subdirectory location for refind
##           : Updates nvram when needed
##           : 10% speed boost

function main () {  ## main insertion function
  declare -r refind_dir="/boot/efi/EFI/refind"; ## set the refind directory
  declare -r arch=$(uname -m | awk -F'_' '{if ($1 == "x86"){print $2}}') &&  ## get bit architecture
  update-efi-dir;  ## updates or creates the refind directory
  update-efi-nvram;  ## updates nvram if needed

function update-efi-dir () {  ## setup the refind directory
  if [ ! -d $refind_dir ]; then  ## check if refind directory exists
    echo "Couldn't find $refind_dir";
    mkdir $refind_dir &&  ## make the refind directory if needed
    echo "Made $refind_dir";
  if [ "$arch" ]; then  ## check if anything was stored in $arch
    cp -r /usr/{share/refind/*,lib/refind/*$arch*} $refind_dir/  && ## update bin and dirs
    echo "Updated binaries and directory files for refind at $refind_dir";
    echo "Failed to detect an x86 architecture";

function update-efi-nvram () { ## update the nvram with efibootmgr
  declare -r ref_bin=${refind_dir/\/boot\/efi}/$(ls /usr/lib | grep $arch*.efi);  ## get path of refind binary (without /boot/efi)
  declare -r ref_bin_escape=${ref_bin//\//\\\\};  ## insert escape characters into $ref_bin
  modprobe efivars && ## grab the efi variables for efibootmgr
  efibootmgr -v | grep $ref_bin_escape && ( ## check if boot entry is in nvram
    echo "Found boot entry, no need to update nvram";
    ) || ( ## if boot entry is not in nvam; add it
    declare -r esp=$(mount -l | awk '/ESP/ {print $1}') &&  ## get ESP partition
    efibootmgr -c -g -d ${esp:0:8} -p ${esp:8} -w -L "rEFInd" -l $ref_bin_escape && ## update nvram
    echo "
    Updated nvram with entry rEFInd to boot $ref_bin
    Did not copy configuration files, please move refind.conf to $refind_dir/";

main;  ## run the main insertion function
Note: Save the following service file as /usr/lib/systemd/system/refind_update.path
Description=Update refind


Note: Save the following service file as /usr/lib/systemd/system/refind_update.service
Description=Update refind directories, binaries, and nvram


Tip: Enable the systemd units by running :
# systemctl enable refind_update.path;
# systemctl enable refind_update.service;
Apple Macs

In case of Apple Macs, try mactel-bootAUR for an experimental "bless" utility for Linux. If that does not work, use "bless" form within OSX to set rEFInd as default bootloader. Assuming UEFISYS partition is mounted at /mnt/efi within OSX, do

$ sudo bless --setBoot --folder /mnt/efi/EFI/refind --file /mnt/efi/EFI/refind/refind_x64.efi

In case of VirtualBox, see VirtualBox#Using_Arch_under_Virtualbox_EFI_mode.

Using gummiboot

Gummiboot is a UEFI Boot Manager which provides a nice menu for EFISTUB Kernels. It is a new program and relatively untested compared to rEFInd . It is available in [extra] as gummiboot-efi. See http://freedesktop.org/wiki/Software/gummiboot for more info.

Using UEFI Shell

It is possible to launch EFISTUB kernel form 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:
> cd \EFI\arch
> vmlinuz-arch.efi root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 ro rootfstype=ext4 add_efi_memmap initrd=\EFI\arch\initramfs-arch.img

Using efibootmgr entry

Note: This menthod may not work due to limitations in how the kernel handles uefi runtime variables. For example in Lenovo Thinkpads the initrd path is truncated (verified using efibootmgr -v command) and therefore the kernel fails to boot.
Note: Some UEFI firmwares may not support embedding command line parameters to uefi applications in the boot entries.

It is possible to directly embed the kernel parameters within the boot entry created by efibootmgr. This means that in your BIOS/UEFI you will be able to select Arch Linux directly in the default boot order, and on startup it will boot into Arch directly without any kind of boot selection GUI.

Do (as root):

Install efibootmgr if you haven't already.

 # pacman -S --needed efibootmgr

Determine the UUID or PARTUUID of your boot device (ie. the partition for /, not the EFI boot partition)

# blkid

Load the EFI module.

# modprobe efivars

Finally, add the efistub. WARNING: Make sure you replace the following before running this command:

  • 3518bb68-d01e-45c9-b973-0b5d918aae96 -- with the UUID of your / partition. (This is not PARTUUID!)
  • ext4 -- if you use a different file system.
  • /dev/sda -- the drive that contains the EFI boot partition.
  • -p 1 -- the partition number of the EFI boot partition.
# echo 'root=UUID=3518bb68-d01e-45c9-b973-0b5d918aae96 ro rootfstype=ext4 add_efi_memmap initrd=\EFI\arch\initramfs-arch.img' | iconv -f ascii -t ucs2 | efibootmgr -c -g -d /dev/sda -p 1 -L "Arch Linux" -l '\EFI\arch\vmlinuz-arch.efi' -@ -

or you can just run the following line (remember to replace /dev/sda1):

# echo "root=UUID=$(blkid /dev/sda1 -o value -s UUID) ro rootfstype=ext4 add_efi_memmap initrd=\\EFI\\arch\\initramfs-arch.img" | iconv -f ascii -t ucs2 | efibootmgr -c -g -d /dev/sda -p 1 -L "Arch Linux" -l '\EFI\arch\vmlinuz-arch.efi' -@ -
Note: The trailing hyphen after --append-binary-args or -@ is required to instruct efibootmgr to read the parameters from STDIN (standard input). The code should be --append-binary-args - or -@ - .

More info about efibootmgr at UEFI#efibootmgr. Forum post https://bbs.archlinux.org/viewtopic.php?pid=1090040#p1090040 .

Note: Some firmwares may have trouble with the "initrd path" when piping in ucs-2 as shown above. In this case, one may put vmlinuz-linux.efi and the initramfs in the root of the ESP and adjust the efibootmgr entry accordingly.

GRUB 2.x

GRUB 2.x contains its own filesystem drivers and does not rely on the firmware to access the files. It can directly read files from /boot and does not require the kernel and initramfs files to be in the UEFISYS partition. Detailed information at GRUB#UEFI_systems_2. For bzr development version try AUR package - grub-efi-x86_64-bzrAUR.


Note: Syslinux UEFI support is currently part of version 6.00-preXX or in firmware branch of upstream git repo. It is considered alpha quality by upstream. The below information is provided mainly to enable bug-testing. Please report all issues upstream.
Note: Syslinux UEFI can boot only those kernels that support EFI Handover Protocol. Thus LTS kernels are not supported.

Install syslinux-efi-gitAUR AUR package and copy /usr/lib/syslinux/efi64/* to $esp/EFI/syslinux/ ($esp is the mountpoint of UEFISYS partition) (efi64 is for x86_64 UEFI firmwares, replace with efi32 for i386 UEFI firmwares), and then create a boot entry using efibootmgr in the firmware boot manager.


ELILO is the UEFI version of LILO Boot Loader. It was originally created for Intel Itanium systems which supported only EFI (precursor to UEFI). It is the oldest UEFI bootloader for Linux. It is still in development but happens at a very slow pace. Upstream provided compiled binaries are available at http://sourceforge.net/projects/elilo/ . Elilo config file elilo.conf is similar to LILO's config file. AUR package - elilo-efi-x86_64AUR (only for x86_64 UEFI).


EFILINUX is a reference implementation of a UEFI Linux bootloader and precursor to Kenrel EFISTUB support. It is considered to be a alpha quality software (as on 16-MAY-2012). Upstream sources are at https://github.com/mfleming/efilinux . and the usage instructions are at http://thread.gmane.org/gmane.linux.kernel/1172645 and http://article.gmane.org/gmane.linux.kernel/1175060 . AUR packages - efilinux-efi and efilinux-efi-x86_64-gitAUR (only for x86_64 UEFI).

Package Naming Guidelines

UEFI bootloader package(s) should be suffixed with -efi-x86_64 or -efi-i386 to denote package built for 64-bit and 32-bit UEFI respectively. If a single package contains both 64-bit and 32-bit UEFI applications, then -efi suffix should be used in the pkgname.

See also