Originally written: 3/11/2011; last update: 7/7/2018
This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!
|Donate $1.00||Donate $2.50||Donate $5.00||Donate $10.00||Donate another value|
This page is part of my Managing EFI Boot Loaders for Linux document. If a Web search has brought you to this page, you may want to start at the beginning.
In late 2011, Linux kernel developers began work on a new way to boot Linux on EFI-based systems. This approach turns the Linux kernel into an EFI application. Once loaded, the kernel takes over the computer, effectively bypassing the need for a boot loader in the strictest sense. This approach has its own unique advantages and disadvantages, as detailed on this page. (If you're interested in the technical details, you can read about them in the Linux Kernel Mailing List thread on this topic.)
The Linux kernel's EFI stub loader has a number of unique features. Some are positive, some are negative, and some can be either. Broadly speaking, reasons you might want to use it include:
Reasons you might not want to use the EFI stub loader include:
In practice, the EFI stub loader is generally used with a separate boot manager program—most commonly rEFInd or gummiboot/systemd-boot, but GRUB 2 can be used this way, too. rEFInd's filesystem drivers can mitigate the first EFI stub loader disadvantage, and the configuration features of any of these boot managers mitigates the second disadvantage. The third is only a problem if you want to boot a very old kernel. The use of a separate boot manager also eliminates the first advantage, and the second is largely theoretical. Thus, the advantages and disadvantages of the EFI stub loader are largely irrelevant or depend on the features of the boot manager with which the EFI stub loader is paired. One partial exception is if you configure your computer's built-in boot manager to launch a Linux kernel. In this case, the kernel must reside on the ESP or some other EFI-accessible partition; and configuration becomes awkward, because it must be done through the efibootmgr utility. Some people like this minimalist approach to booting, though.
Reliability of the EFI stub loader is good, in my experience, but not perfect. My 32-bit Mac Mini won't boot a kernel loaded from a FAT partition, but it works fine when the kernel resides on another partition (either an HFS+ partition or a Linux-native partition read via an add-on EFI filesystem driver). There's also a known bug in Ubuntu's 3.13.0-100 kernel, and later kernels in the 3.13.0 series, that causes boot failures. This kernel series was originally released with Ubuntu 14.04, but later kernel series do not exhibit this problem, so updating to them is a suitable workaround. I've seen other problems reported from time to time, such as this one among Arch Linux users. These problems have always faded from view, sooner or later, and have never been widespread.
Installing the EFI stub loader entails configuring your 3.3.0 or later kernel and compiling it (or obtaining a suitably pre-configured kernel) and then installing the kernel on your ESP (or on some other EFI-accessible partition) in the usual way for an EFI boot loader. If you need help compiling your own kernel, consult a Web page on the topic, such as How to: Compile Linux Kernel 2.6 or Compiling the Linux Kernel. If you've never done it before, be aware that the worst part of the task is sifting through the thousands of kernel options to decide what you need. A generic kernel configuration file can be handy; it will set the options that will work on most computers, similar to what distribution providers use. You should pay attention to one, or possibly two, kernel configuration options:
Both of these features are highlighted (via GIMP trickery) in the below make xconfig screen shot:
With the kernel compiled, you should install its modules in the usual way (by typing make modules_install) and prepare an initial RAM disk in the usual way (using mkinitrd or mkinitramfs, typically—details vary from one distribution to another). Instead of (or in addition to) copying your kernel file and initial RAM disk to the Linux /boot directory, though, you should copy these files to your ESP. For instance, you might use the EFI/linux subdirectory on the ESP to hold these files.
The kernel's stub loader requires no configuration per se, although building options into it may be desirable in some cases. When compiled without them, you must know how to pass it options that you would normally pass it on an options line in a boot loader. You must also pass it the name of the initial RAM disk, if you use one. The resulting command, typed at an EFI shell, might look like this:
fs0:> bzImage.efi root=/dev/sda4 ro initrd=\EFI\linux\initrd.img
This is a very minimal example. It assumes that you've called the kernel file bzImage.efi, that your root Linux filesystem is on /dev/sda4, and that the initial RAM disk is stored in the ESP's EFI/linux/initrd.img file. The ro option tells Linux to mount the root filesystem read-only. (This is standard; initialization scripts later re-mount the filesystem read/write.) Note that the root= option identifies the Linux root filesystem using Linux-style forward slashes (/) to separate directory elements, and relative to the Linux root (/) filesystem; but the initrd= specification uses EFI-style backslashes (\) and identifies the initial RAM disk relative to the ESP's root. This is extremely important; an incorrect initrd= specification causes the kernel to hang. With early versions of the EFI stub loader (3.3.0 through at least 3.4.0), there were no error messages. With more recent versions (as of 3.6.0, and perhaps 3.5.x kernels), the kernel displays an error message when it can't read its initrd file.
EFI implementations include their own boot managers, but they're usually quite primitive. Nonetheless, if yours enables you to choose a boot loader, or if you're satisfied with always booting just one kernel, you can set it up with the efibootmgr program in Linux. You can do this with a command like the following:
# efibootmgr -c -d /dev/sda -p 1 -L "Arch Linux" -l '\EFI\arch\vmlinuz-arch.efi' -u root=/dev/sda3 ro initrd=EFI/arch/initramfs-arch.img
This command tells the EFI to boot the \EFI\arch\vmlinuz-arch.efi file using the arguments specified following the -u option. The -d and -p options are theoretically unnecessary if you use /dev/sda1 as your ESP; I've included them in this example in case your ESP is elsewhere and you need to change them. If your EFI implementation supports a decent boot menu, you can use multiple commands like this to create alternative boot options—say, to boot different kernels, multiple distributions, or using alternate options.
If you're using a separate EFI boot manager program, such as rEFInd or gummiboot/systemd-boot, you can look into configuring it to pass the necessary options to the kernel. As already noted, this isn't possible with rEFIt. My fork of rEFIt, rEFInd, supports two ways of passing options to the EFI stub loader: You can write boot loader stanza definitions in the main refind.conf file; or you can rely on semi-automated discovery that reads options for all kernels in a directory from a file called refind_linux.conf, or that extracts minimal options from /etc/fstab or by inferring the root (/) partition's location based on partition type codes. Either approach can make the combination of this kernel support and rEFInd a flexible and relatively easy-to-maintain combination in a multi-boot environment; however, you may need to do at least a little manual maintenance. gummiboot/systemd-boot requires a separate configuration file for each of its main-menu options. Few or no distributions support it with maintenance scripts, so you'll have to maintain it manually; however, the associated Boot Loader Specification, if it ever gains popular support, could change this issue for the better.
It's theoretically possible to launch a Linux kernel compiled with EFI stub support from GRUB Legacy or GRUB 2 using their chainloader option rather than their kernel or linux options. (I've not tried this, though.) Using chainloader might provide advantages if you're having problems with hardware initialization when launching in the usual way; however, I can make no promises about that.
EFI drivers for ext2fs/ext3fs, ext4fs, ReiserFS, Btrfs, and others are available, which makes it possible to load a Linux kernel with EFI stub support from a Linux filesystem. This could simplify configuration in some environments, since you won't need to copy the kernel to the ESP, although you might need to rename it or create a link to the kernel with an extension of .efi. This page describes using EFI drivers, with an emphasis on configuring rEFInd to load them.
Because most distributions don't support booting directly via the kernel's EFI stub loader, you're on your own when it comes to maintenance. In the future, it's possible that distributions will use efibootmgr or other tools to help maintain installations that use this approach, or support it by maintaining the configuration files for GRUB, rEFInd, or gummiboot/systemd-boot. Because rEFInd requires little or no maintenance when you add new kernels, the maintenance needs for the combination of the EFI stub loader and rEFInd are quite low.
Go on to "Using rEFIt"
Return to "Managing EFI Boot Loaders for Linux" main page
copyright © 2011–2018 by Roderick W. Smith
If you have problems with or comments about this web page, please e-mail me at firstname.lastname@example.org. Thanks.
Return to my main Web page.