UEFI Bootloaders: Difference between revisions
(gummiboot is in [core] now) |
(→Sync EFISTUB Kernel: added method "/etc/fstab bind mount" for KISS kernel update and location management) |
||
Line 128: | Line 128: | ||
{{Tip|Add {{ic|efistub-update}} to the list of hooks in {{ic|/etc/mkinitcpio.conf}}}} | {{Tip|Add {{ic|efistub-update}} to the list of hooks in {{ic|/etc/mkinitcpio.conf}}}} | ||
==== /etc/fstab bind mount ==== | |||
{{Note| | |||
* The following method should work similarly with any distribution or any combination thereof. | |||
* This involves no special scripts, services, or bootloader filesystem drivers. | |||
* This centralizes kernels across installations on one partition. | |||
* Beyond initial configuration this should persist without special consideration or maintenance. | |||
* This should be transparent to any action normally affecting {{ic|/boot}} and the files therein.}} | |||
{{Warning| | |||
* This requires both a kernel and a bootloader compatible with the FAT32 filesystem. | |||
* Initial configuration requires {{ic|root}} level access. | |||
* This may require a large EFI system partition in order to accomodate multiple installations. | |||
* All kernels will require at least a {{ic|1=root=''system root''}} parameter passed at boot.}} | |||
; Method: Whereas the general convention is to mount the EFI system partition to a {{ic|/boot/efi}} subfolder, the following will achieve the opposite. | |||
* Create a {{ic|ef00}} type EFI system partition of FAT32 format as described elsewhere. | |||
:{{Tip| | |||
:* It may be beneficial to make it several gigabytes in size to accomodate multiple installations. | |||
:* Use the GPT partition name feature for added convenience. For example name the partition {{ic|esp}}.}} | |||
* Create a mount-point and mount the EFI system partition somewhere on the filesystem. For example: | |||
: {{ic|$ mkdir /esp<br />$ mount -L esp /esp}} | |||
* Create a folder in {{ic|/EFI/boot}} for your current system's {{ic|/boot}} files on the EFI system partition. For example: | |||
: {{ic|$ mkdir /esp/EFI/boot/arch64-laptop}} | |||
: {{Tip| | |||
:* The refind bootloader automatically detects and adds EFI loadable kernel files installed to the EFI system partition in {{ic|/EFI/boot/*/}}. | |||
:* Keying {{ic|F2}} on a highlighted refind menu entry at boot will enable you to add the required {{ic|1=root=}} kernel parameter to an auto-added menu entry without first configuring its {{ic|refind.conf}} file.}} | |||
* Move all files in {{ic|/boot}} to the newly created folder on your EFI system partition. For example: | |||
: {{ic|$ mv /boot/* /esp/EFI/boot/arch64-laptop/}} | |||
* Bind mount the newly populated folder on your EFI system partition to {{ic|/boot}}. For example: | |||
: {{ic|$ mount --bind /esp/EFI/boot/arch64-laptop /boot}} | |||
* Verify your files are available as expected with {{ic|$ ls /boot/}} then persist the configuration by editing {{ic|/etc/fstab}}. For example: | |||
: {{ic|##/etc/fstab<br />LABEL=arch64-laptop_rootfs / ext4 defaults 0 0<br />LABEL=esp /esp vfat defaults 0 0<br />/esp/EFI/boot/arch64-laptop /boot none defaults,bind 0 0}} | |||
* Update your bootloader to apply the {{ic|1=root=}} kernel boot parameter as necessary. For example: | |||
: {{ic|##/boot/refind.conf<br />... root=LABEL=arch64-laptop_rootfs ...}} | |||
{{Note| As of [https://www.archlinux.org/packages/extra/any/refind-efi/ refind-efi 0.2.7], refind automatically detects kernels in {{ic|/boot}}. They do not have to be renamed to have a {{ic|.efi}} extension either. Hence, the following sync scripts aren't needed if using [https://wiki.archlinux.org/index.php/UEFI_Bootloaders#Using_rEFInd refind]. You do need to isntall an EFI driver to read the Linux filesystem on which the kernel is stored, though.}} | {{Note| As of [https://www.archlinux.org/packages/extra/any/refind-efi/ refind-efi 0.2.7], refind automatically detects kernels in {{ic|/boot}}. They do not have to be renamed to have a {{ic|.efi}} extension either. Hence, the following sync scripts aren't needed if using [https://wiki.archlinux.org/index.php/UEFI_Bootloaders#Using_rEFInd refind]. You do need to isntall an EFI driver to read the Linux filesystem on which the kernel is stored, though.}} | ||
Revision as of 05:45, 29 September 2013
zh-CN:UEFI Bootloaders 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 are explained here:
Linux Kernel EFISTUB
Linux (Kernel >= 3.3) supports EFISTUB (EFI BOOT STUB)
booting. It is enabled 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
- Create a FAT32 EFI System Partition
- Mount the EFI System Partition (EFISYS) (mountpoint hereafter mentioned as
$esp
in the below commands) either at/boot
(former recommended if you are planning to use Gummiboot) or some other location of your choice (most distros and tools use/boot/efi
).
/boot
as the EFISYS mountpoint.- Create
$esp/EFI/arch/
- Copy the following files from source to destination
Boot File Source | UEFI Destination |
---|---|
/boot/vmlinuz-linux | $esp/EFI/arch/vmlinuz-arch.efi |
/boot/initramfs-linux.img | $esp/EFI/arch/initramfs-arch.img |
/boot/initramfs-linux-fallback.img | $esp/EFI/arch/initramfs-arch-fallback.img |
Sync EFISTUB Kernel
/boot
as the EFISYS mountpoint.Systemd
Systemd features event triggered tasks. In this particular case, the ability to detect a change in path is used to sync the EFISTUB kernel and initramfs files when they are updated in boot
.
/etc/systemd/system/efistub-update.path
[Unit] Description=Copy EFISTUB Kernel to UEFISYS Partition [Path] PathChanged=/boot/initramfs-linux-fallback.img [Install] WantedBy=multi-user.target
/etc/systemd/system/efistub-update.service
[Unit] Description=Copy EFISTUB Kernel to UEFISYS Partition [Service] Type=oneshot ExecStart=/usr/bin/cp -f /boot/vmlinuz-linux $esp/EFI/arch/vmlinuz-arch.efi ExecStart=/usr/bin/cp -f /boot/initramfs-linux.img $esp/EFI/arch/initramfs-arch.img ExecStart=/usr/bin/cp -f /boot/initramfs-linux-fallback.img $esp/EFI/arch/initramfs-arch-fallback.img
# systemctl enable efistub-update.path
Incron
incron can run a script to sync the EFISTUB Kernel after updates
/usr/local/bin/efistub-update.sh
#!/usr/bin/env bash /usr/bin/cp -f /boot/vmlinuz-linux $esp/EFI/arch/vmlinuz-arch.efi /usr/bin/cp -f /boot/initramfs-linux.img $esp/EFI/arch/initramfs-arch.img /usr/bin/cp -f /boot/initramfs-linux-fallback.img $esp/EFI/arch/initramfs-arch-fallback.img
/etc/incron.d/efistub-update.conf
/boot/initramfs-linux-fallback.img
is the file to watch. 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./boot/initramfs-linux-fallback.img IN_CLOSE_WRITE /usr/local/bin/efistub-update.sh
# systemctl enable incrond.service
Mkinitcpio hook
Mkinitcpio can generate a hook that does not need a system level daemon to function. It spawns a background process which waits for the generation of vm-linuz
, initramfs-linux.img
, and initramfs-linux-fallback.img
; then follows step 4 in Setting up EFISTUB
/usr/lib/initcpio/install/efistub-update
#!/usr/bin/env bash build() { /root/watch.sh & } help() { cat <<HELPEOF This hook waits for mkinitcpio to finish and copies the finished ramdisk and kernel to the ESP HELPEOF }
/root/watch.sh
and make it executable#!/usr/bin/env bash while [[ -d "/proc/$PPID" ]]; do sleep 1 done /usr/bin/cp -f /boot/vmlinuz-linux $esp/EFI/arch/vmlinuz-arch.efi /usr/bin/cp -f /boot/initramfs-linux.img $esp/EFI/arch/initramfs-arch.img /usr/bin/cp -f /boot/initramfs-linux-fallback.img $esp/EFI/arch/initramfs-arch-fallback.img echo "Synced kernel with ESP"
efistub-update
to the list of hooks in /etc/mkinitcpio.conf
/etc/fstab bind mount
- The following method should work similarly with any distribution or any combination thereof.
- This involves no special scripts, services, or bootloader filesystem drivers.
- This centralizes kernels across installations on one partition.
- Beyond initial configuration this should persist without special consideration or maintenance.
- This should be transparent to any action normally affecting
/boot
and the files therein.
- This requires both a kernel and a bootloader compatible with the FAT32 filesystem.
- Initial configuration requires
root
level access. - This may require a large EFI system partition in order to accomodate multiple installations.
- All kernels will require at least a
root=system root
parameter passed at boot.
- Method
- Whereas the general convention is to mount the EFI system partition to a
/boot/efi
subfolder, the following will achieve the opposite.
- Create a
ef00
type EFI system partition of FAT32 format as described elsewhere.
- Tip:
- It may be beneficial to make it several gigabytes in size to accomodate multiple installations.
- Use the GPT partition name feature for added convenience. For example name the partition
esp
.
- Create a mount-point and mount the EFI system partition somewhere on the filesystem. For example:
$ mkdir /esp
$ mount -L esp /esp
- Create a folder in
/EFI/boot
for your current system's/boot
files on the EFI system partition. For example:
$ mkdir /esp/EFI/boot/arch64-laptop
- Tip:
- The refind bootloader automatically detects and adds EFI loadable kernel files installed to the EFI system partition in
/EFI/boot/*/
. - Keying
F2
on a highlighted refind menu entry at boot will enable you to add the requiredroot=
kernel parameter to an auto-added menu entry without first configuring itsrefind.conf
file.
- The refind bootloader automatically detects and adds EFI loadable kernel files installed to the EFI system partition in
- Move all files in
/boot
to the newly created folder on your EFI system partition. For example:
$ mv /boot/* /esp/EFI/boot/arch64-laptop/
- Bind mount the newly populated folder on your EFI system partition to
/boot
. For example:
$ mount --bind /esp/EFI/boot/arch64-laptop /boot
- Verify your files are available as expected with
$ ls /boot/
then persist the configuration by editing/etc/fstab
. For example:
##/etc/fstab
LABEL=arch64-laptop_rootfs / ext4 defaults 0 0
LABEL=esp /esp vfat defaults 0 0
/esp/EFI/boot/arch64-laptop /boot none defaults,bind 0 0
- Update your bootloader to apply the
root=
kernel boot parameter as necessary. For example:
##/boot/refind.conf
... root=LABEL=arch64-laptop_rootfs ...
/boot
. They do not have to be renamed to have a .efi
extension either. Hence, the following sync scripts aren't needed if using refind. You do need to isntall an EFI driver to read the Linux filesystem on which the kernel is stored, though.Booting EFISTUB
$esp/EFI/arch/initramfs-linux.img
, the corresponding UEFI formatted line should be initrd=/EFI/arch/initramfs-linux.img
or initrd=\EFI\arch\initramfs-linux.img
.One can boot the EFISTUB kernel using one of the following ways :
Using gummiboot
Gummiboot is a UEFI Boot Manager which provides a nice menu for EFISTUB Kernels. It is available in [core] as gummiboot is the recommended boot manager for EFISTUB booting. See gummiboot for more info.
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.
- Install refind-efi package with
# pacman -S refind-efi
- Copy the following files from their source directory to their destination
$ uname -m
to get the architecture. Replace <arch> with "ia32" for 32 bit systems, and <arch> with "x64" for 64 bit systems.rEFInd File Source | UEFI Destination |
---|---|
/usr/share/refind/refind_<arch>.efi | $esp/EFI/refind/refind_<arch>.efi |
/usr/share/refind/refind.conf-sample | $esp/EFI/refind/refind.conf |
/usr/share/refind/icons | $esp/EFI/refind/icons |
/usr/share/refind/drivers_<arch> | $esp/EFI/refind/drivers |
$esp/EFI/refind/refind.conf
. The file is well commented./boot
, if there are UEFI drivers for the filesystem used by /boot partition (or / partition if no separate /boot is used) in the ESP, and are loaded by rEFInd. This is enabled in the default configuration in refind.conf
(you may need to include the PATH to the drivers folders in the ESP). See [2] for more info.Edit the refind_linux.conf
configuration file to be similar to the template below. Replace the string after PARTUUID with your root's PARTUUID
$ ls -l /dev/disk/by-partuuid/
refind_linux.conf
"Boot with defaults" "root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 rw rootfstype=ext4 add_efi_memmap systemd.unit=graphical.target" "Boot to Terminal" "root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 rw rootfstype=ext4 add_efi_memmap systemd.unit=multi-user.target"
refind_linux.conf
is displayed as a submenu by rEFInd. Access the submenu with "+" or "insert" keys.# efibootmgr -c -d /dev/sdX -p Y -l /EFI/refind/refind_<arch>.efi -L "rEFInd"
Systemd Automation
/usr/lib/systemd/scripts/refind_name_patchv2
#!/usr/bin/env bash ## 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 ## 7/15/2013 : Changed arch to match 32-bit (ia32) and 64-bit (x64) naming scheme ## : Changed directory copying in update-efi-dir to copy tools and drivers directories explicitly ## : Changed efibootmgr writing code to be more concise and added (-w) to write the entry as per dusktreader's excellent guide : https://docs.google.com/document/d/1pvgm3BprpXoadsQi38FxqMOCUZhcSqFhZ26FZBkmn9I/edit ## : Function to check if NVRAM boot entry was already listed was fixed to use awk and an if then clause ## : ref_bin_escape was modified from : ref_bin_escape=${ref_bin//\//\\\\} to remove extra backslashes (error does not show up when using cmdline) ## 7/29/2013 : Changed location of tools,drivers, and binary directory to match capricious upstream move to /usr/share/refind function main () { ## main insertion function declare -r refind_dir="/boot/efi/EFI/refind"; ## set the refind directory arch=$(uname -m | awk -F'_' '{if ($1 == "x86") {print "x"$2} else if ($1 == "i686") {print "ia32"}}') && ## 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"; fi; if [ "$arch" ]; then ## check if anything was stored in $arch cp -r /usr/share/refind/{refind_$arch.efi,keys,images,icons,fonts,docs,{tools,drivers}_$arch} $refind_dir/ && ## update the bins and dirs echo "Updated binaries and directory files for refind at $refind_dir"; else echo "Failed to detect an x86 architecture"; exit; fi; } function update-efi-nvram () { ## update the nvram with efibootmgr declare -r ref_bin=${refind_dir/\/boot\/efi}/refind_$arch.efi; ## get path of refind binary (without /boot/efi) declare -r ref_bin_escape=${ref_bin//\//\\}; ## insert escape characters into $ref_bin [ "$(efibootmgr -v | awk "/${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 nvram; add it declare -r esp=$(mount -l | awk '/ESP/ {print $1}') && ## get ESP partition efibootmgr -cgw -d ${esp:0:8} -p ${esp:8} -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
/boot
. They do not have to be renamed to have a .efi
extension either. Hence, the following sync scripts aren't needed if using refind. You do need to isntall an EFI driver to read the Linux filesystem on which the kernel is stored, though./usr/lib/systemd/system/refind_update.path
[Unit] Description=Update rEFInd bootloader files [Path] PathChanged=/usr/share/refind/refind_<arch>.efi Unit=refind_update.service [Install] WantedBy=multi-user.target
/usr/lib/systemd/system/refind_update.service
[Unit] Description=Update rEFInd directories, binaries, and nvram [Service] Type=oneshot ExecStart=/usr/bin/bash /usr/lib/systemd/scripts/refind_name_patchv2 RemainAfterExit=no
# systemctl enable refind_update.path
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
VirtualBox
In case of VirtualBox, see VirtualBox#Using_Arch_under_Virtualbox_EFI_mode.
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
You can also write a simple archlinux.nsh
file with your boot parameters and put it in your UEFI System Partition, then run it with:
fs0: archlinux
Example Script:
echo -on \EFI\arch\vmlinuz-arch.efi root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 rootfstype=ext4 add_efi_memmap initrd=EFI/arch/initramfs-arch.img
This way you can specify UUID's without needing to remember the name or type out 20-30 characters.
Using efibootmgr entry
It is possible to directly embed the kernel parameters within the boot entry created by efibootmgr. This means that you can use your UEFI boot order/GUI to directly boot Arch Linux without a separate bootloader like GRUB (below, the EFI System Partition is on /dev/sdX
, partition Y
).
# efibootmgr -c -d /dev/sdX -p Y -l /EFI/arch/vmlinuz-arch.efi -L "Arch Linux (EFISTUB)" -u "$(cat /proc/cmdline)"
It is a good idea to run
# efibootmgr -v
to verify that the resulting entry is correct. You should also consider reordering the boot options (efibootmgr -o
) to place the Arch entry last, which could make the system easier to recover if it fails.
More info about efibootmgr at UEFI#efibootmgr. Forum post https://bbs.archlinux.org/viewtopic.php?pid=1090040#p1090040 .
GRUB 2.xx
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-bzrAUR.
SYSLINUX 6.xx
Install syslinux (from [testing]) or syslinux-firmware-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 ia32 UEFI firmwares), and then create a boot entry using efibootmgr in the firmware boot manager.
ELILO
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-efiAUR.
Troubleshooting
- On some UEFI motherboards like the Intel Z77 boards, adding entries with efibootmgr or bcfg from efi shell will not work because they don't show up on the boot menu list after being added to NVRAM.
- To solve this you have to trick the UEFI firmware that Windows boot manager is present on the ESP partition.
- Copy the bootx64.efi file from USB drive as bootmgfw.efi efi file to your ESP partition by booting into EFI shell and typing:
FS1: cd EFI mkdir Microsoft cd Microsoft mkdir Boot cp FS0:\EFI\BOOT\bootx64.efi FS1:\EFI\Microsoft\Boot\bootmgfw.efi
- After reboot, any entries added to NVRAM should show up in the boot menu.