EFI system partition - ArchWiki

# EFI system partition

From ArchWiki
Jump to navigation Jump to search

Related articles

- Unified Extensible Firmware Interface
- Boot loader

The EFI system partition (also called ESP) is an OS independent partition that acts as the storage place for the EFI bootloaders, applications and drivers to be launched by the UEFI firmware. It is mandatory for UEFI boot.

This article or section is a candidate for moving to Unified Extensible Firmware Interface#UEFI drivers.

Notes: Drivers for non-FAT file systems are out of scope of this article. (Discuss in Talk:EFI system partition#)

The UEFI specification mandates support for the FAT12, FAT16, and FAT32 file systems (see UEFI specification version 2.8, section 13.3.1.1), but any conformant vendor can optionally add support for additional file systems; for example, the firmware in Apple Macs supports the HFS+ file system.

## Check for an existing partition

If you are installing Arch Linux on an UEFI-capable computer with an installed operating system, like Windows 10 for example, it is very likely that you already have an EFI system partition.

To find out the disk partition scheme and the system partition, use fdisk as root on the disk you want to boot from:

    # fdisk -l /dev/sdx

The command returns:

- The disk's partition table: it indicates `Disklabel type: gpt` if the partition table is GPT or `Disklabel type: dos` if it is MBR.
- The list of partitions on the disk: Look for the EFI system partition in the list, it is a small (usually about 100–550 MiB) partition with a type `EFI System` or `EFI (FAT-12/16/32)`. To confirm this is the ESP, mount it and check whether it contains a directory named `EFI`, if it does this is definitely the ESP.

Tip: To find out whether it is a FAT12, FAT16 or FAT32 file system, use `minfo` from mtools.

    # minfo -i /dev/sdxY :: | grep 'disk type'

Warning: When dual-booting, avoid reformatting the ESP, as it may contain files required to boot other operating systems.

If you found an existing EFI system partition, simply proceed to #Mount the partition. If you did not find one, you will need to create it, proceed to #Create the partition.

## Create the partition

The following two sections show how to create an EFI system partition (ESP).

Warning: The EFI system partition must be a physical partition in the main partition table of the disk, not under LVM or software RAID etc.
Note: It is recommended to use GPT since some firmwares might not support UEFI/MBR booting due to it not being supported by Windows. See also Partitioning#Choosing between GPT and MBR for the advantages of GPT in general.

To provide adequate space for storing boot loaders and other files required for booting, and to prevent interoperability issues with other operating systems[1] the partition should be at least 260 MiB. For early and/or buggy UEFI implementations the size of at least 512 MiB might be needed.[2]

### GPT partitioned disks

EFI system partition on a GUID Partition Table is identified by the partition type GUID `C12A7328-F81F-11D2-BA4B-00A0C93EC93B`.

Choose one of the following methods to create an ESP for a GPT partitioned disk:

- fdisk: Create a partition with partition type `EFI System`.
- gdisk: Create a partition with partition type `EF00`.
- GNU Parted: Create a partition with `fat32` as the file system type and set the `esp` flag on it.

Proceed to #Format the partition section below.

### MBR partitioned disks

EFI system partition on a Master Boot Record partition table is identified by the partition type ID `EF`.

Choose one of the following methods to create an ESP for a MBR partitioned disk:

- fdisk: Create a primary partition with partition type `EFI (FAT-12/16/32)`.
- GNU Parted: Create a primary partition with `fat32` as the file system type and set the `esp` flag on it.

Proceed to #Format the partition section below.

## Format the partition

The UEFI specification mandates support for the FAT12, FAT16, and FAT32 file systems[3]. To prevent potential issues with other operating systems and also since the UEFI specification only mandates supporting FAT16 and FAT12 on removable media[4], it is recommended to use FAT32.

After creating the partition, format it as FAT32. To use the `mkfs.fat` utility, install dosfstools.

    # mkfs.fat -F32 /dev/sdxY

If you get the message `WARNING: Not enough clusters for a 32 bit FAT!`, reduce cluster size with `mkfs.fat -s2 -F32 ...` or `-s1`; otherwise the partition may be unreadable by UEFI. See mkfs.fat(8) for supported cluster sizes.

## Mount the partition

The kernels, initramfs files, and, in most cases, the processor's microcode, need to be accessible by the boot loader or UEFI itself to successfully boot the system. Thus if you want to keep the setup simple, your boot loader choice limits the available mount points for EFI system partition.

### Typical mount points

This article or section needs expansion.

Reason: The boot loader needs to access `/boot` regardless if it is separate from `/` or not. If `/boot` is inside anything more complex than just a file system on a partition (e.g. LUKS, RAID, LVM), the loader needs needs drivers for those layers too. (Discuss in Talk:EFI system partition#Preffered mount point for LVM users)

The simplest scenarios for mounting EFI system partition are:

- mount ESP to `/efi` and use a boot loader which has a driver for your root file system (eg. GRUB, rEFInd).
- mount ESP to `/boot`. This is the preferred method when directly booting a EFISTUB kernel from UEFI.

Tip:

- `/efi` is a replacement[5] for the previously popular (and possibly still used by other Linux distributions) ESP mountpoint `/boot/efi`.
- The `/efi` directory is not available by default, you will need to first create it with mkdir(1) before mounting the ESP to it.

### Alternative mount points

If you do not use one of the simple methods from #Mount the partition, you will need to copy your boot files to ESP (referred to hereafter as `esp`).

    # mkdir -p esp/EFI/arch
    # cp -a /boot/vmlinuz-linux esp/EFI/arch/
    # cp -a /boot/initramfs-linux.img esp/EFI/arch/
    # cp -a /boot/initramfs-linux-fallback.img esp/EFI/arch/

Note: You may also need to copy the Microcode to the boot-entry location.

Furthermore, you will need to keep the files on the ESP up-to-date with later kernel updates. Failure to do so could result in an unbootable system. The following sections discuss several mechanisms for automating it.

Note: If ESP is not mounted to `/boot`, make sure to not rely on the systemd automount mechanism (including that of systemd-gpt-auto-generator(8)). Always have it mounted manually prior to the any system or kernel update, otherwise you may not be able to mount it after the update, locking you in the currently running kernel with no ability to update the copy of kernel on ESP.

Alternatively preload the required kernel modules on boot, e.g.:

    /etc/modules-load.d/vfat.conf

    vfat
    nls_cp437
    nls_iso8859-1

#### Using bind mount

Instead of mounting the ESP itself to `/boot`, you can mount a directory of the ESP to `/boot` using a bind mount (see mount(8)). This allows pacman to update the kernel directly while keeping the ESP organized to your liking.

Note:

- This requires a kernel and bootloader compatible with FAT32. This is not an issue for a regular Arch install, but could be problematic for other distributions (namely those that require symlinks in `/boot/`). See the forum post here.
- You must use the `root=` kernel parameter in order to boot using this method.

Just like in #Alternative mount points, copy all boot files to a directory on your ESP, but mount the ESP outside `/boot`. Then bind mount the directory:

    # mount --bind esp/EFI/arch /boot

After verifying success, edit your Fstab to make the changes persistent:

    /etc/fstab

    esp/EFI/arch /boot none defaults,bind 0 0

#### Using 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/`. The file watched for changes is `initramfs-linux-fallback.img` since this is the last file built by mkinitcpio, to make sure all files have been built before starting the copy. The systemd path and service files to be created are:

    /etc/systemd/system/efistub-update.path

    [Unit]
    Description=Copy EFISTUB Kernel to EFI system partition

    [Path]
    PathChanged=/boot/initramfs-linux-fallback.img

    [Install]
    WantedBy=multi-user.target
    WantedBy=system-update.target

    /etc/systemd/system/efistub-update.service

    [Unit]
    Description=Copy EFISTUB Kernel to EFI system partition

    [Service]
    Type=oneshot
    ExecStart=/usr/bin/cp -af /boot/vmlinuz-linux esp/EFI/arch/
    ExecStart=/usr/bin/cp -af /boot/initramfs-linux.img esp/EFI/arch/
    ExecStart=/usr/bin/cp -af /boot/initramfs-linux-fallback.img esp/EFI/arch/

Then enable and start `efistub-update.path`.

Tip: For Secure Boot with your own keys, you can set up the service to also sign the image using sbsigntools:

    ExecStart=/usr/bin/sbsign --key /path/to/db.key --cert /path/to/db.crt --output esp/EFI/arch/vmlinuz-linux /boot/vmlinuz-linux

#### Using filesystem events

Filesystem events can be used to run a script syncing the EFISTUB Kernel after kernel updates. An example with incron follows.

    /usr/local/bin/efistub-update

    #!/bin/sh
    cp -af /boot/vmlinuz-linux esp/EFI/arch/
    cp -af /boot/initramfs-linux.img esp/EFI/arch/
    cp -af /boot/initramfs-linux-fallback.img esp/EFI/arch/

Note: The first parameter `/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` is the script to execute.

    /etc/incron.d/efistub-update.conf

    /boot/initramfs-linux-fallback.img IN_CLOSE_WRITE /usr/local/bin/efistub-update

In order to use this method, enable the `incrond.service`.

#### Using 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 `vmlinuz`, `initramfs-linux.img`, and `initramfs-linux-fallback.img` before copying the files.

Add `efistub-update` to the list of hooks in `/etc/mkinitcpio.conf`.

    /etc/initcpio/install/efistub-update

    #!/usr/bin/env bash
    build() {
    	/usr/local/bin/efistub-copy $$ &
    }

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

    /usr/local/bin/efistub-copy

    #!/usr/bin/env bash

    if [[ $1 -gt 0 ]]
    then
    	while [ -e /proc/$1 ]
    	do
    		sleep .5
    	done
    fi

    rsync -a /boot/ esp/

    echo "Synced /boot with ESP"

#### Using mkinitcpio hook (2)

Another alternative to the above solutions, that is potentially cleaner because there are less copies and does not need a system level daemon to function. The logic is reversed, the initramfs is directly stored in the EFI partition, not copied in `/boot/`. Then the kernel and any other additional files are copied to the ESP partition, thanks to a mkinitcpio hook.

Edit the file `/etc/mkinitcpio.d/linux.preset` :

    /etc/mkinitcpio.d/linux.preset

    # mkinitcpio preset file for the 'linux' package

    # Directory to copy the kernel, the initramfs...
    ESP_DIR="esp/EFI/arch"

    ALL_config="/etc/mkinitcpio.conf"
    ALL_kver="/boot/vmlinuz-linux"

    PRESETS=('default' 'fallback')

    #default_config="/etc/mkinitcpio.conf"
    default_image="${ESP_DIR}/initramfs-linux.img"
    default_options="-A esp-update-linux"

    #fallback_config="/etc/mkinitcpio.conf"
    fallback_image="${ESP_DIR}/initramfs-linux-fallback.img"
    fallback_options="-S autodetect"

Then create the file `/etc/initcpio/install/esp-update-linux` which need to be executable :

    /etc/initcpio/install/esp-update-linux

    # Directory to copy the kernel, the initramfs...
    ESP_DIR="esp/EFI/arch"

    build() {
    	cp -af /boot/vmlinuz-linux "${ESP_DIR}/"
    	[[ -e /boot/intel-ucode.img ]] && cp -af /boot/intel-ucode.img "${ESP_DIR}/"
    	[[ -e /boot/amd-ucode.img ]] && cp -af /boot/amd-ucode.img "${ESP_DIR}/"
    }

    help() {
    	cat <<HELPEOF
    This hook copies the kernel to the ESP partition
    HELPEOF
    }

To test that, just run:

    # rm /boot/initramfs-linux-fallback.img
    # rm /boot/initramfs-linux.img
    # mkinitcpio -p linux

#### Using mkinitcpio preset

As the presets in `/etc/mkinitcpio.d/` support shell scripting, the kernel and initramfs can be copied by just editing the presets.

    /etc/mkinitcpio.d/0.preset

    ESP_DIR="esp/EFI/arch"
    cp -af "/boot/vmlinuz-linux${suffix}" "$ESP_DIR/"
    ALL_config="/etc/mkinitcpio.conf"
    ALL_kver="$ESP_DIR/vmlinuz-linux${suffix}"
    PRESETS=('default')
    default_config="/etc/mkinitcpio.conf"
    default_image="$ESP_DIR/initramfs-linux${suffix}.img"

    /etc/mkinitcpio.d/linux.preset

    source /etc/mkinitcpio.d/0.preset

    /etc/mkinitcpio.d/linux-zen.preset

    suffix='-zen'
    source /etc/mkinitcpio.d/0.preset

#### Using pacman hook

A last option relies on the pacman hooks that are run at the end of the transaction.

The first file is a hook that monitors the relevant files, and it is run if they were modified in the former transaction.

    /etc/pacman.d/hooks/999-kernel-efi-copy.hook

    [Trigger]
    Type = File
    Operation = Install
    Operation = Upgrade
    Target = boot/vmlinuz*
    Target = usr/lib/initcpio/*
    Target = boot/*-ucode.img

    [Action]
    Description = Copying linux and initramfs to EFI directory...
    When = PostTransaction
    Exec = /usr/local/bin/kernel-efi-copy.sh

The second file is the script itself. Create the file and make it executable:

    /usr/local/bin/kernel-efi-copy.sh

    #!/usr/bin/env bash
    #
    # Copy kernel and initramfs images to EFI directory
    #

    ESP_DIR="esp/EFI/arch"

    for file in /boot/vmlinuz*
    do
            cp -af "$file" "$ESP_DIR/$(basename "$file").efi"
            [[ $? -ne 0 ]] && exit 1
    done

    for file in /boot/initramfs*
    do
            cp -af "$file" "$ESP_DIR/"
            [[ $? -ne 0 ]] && exit 1
    done

    [[ -e /boot/intel-ucode.img ]] && cp -af /boot/intel-ucode.img "$ESP_DIR/"
    [[ -e /boot/amd-ucode.img ]] && cp -af /boot/amd-ucode.img "$ESP_DIR/"

    exit 0

## Troubleshooting

### ESP on software RAID1

It is possible to make the ESP part of a RAID1 array, but doing so brings the risk of data corruption, and further considerations need to be taken when creating the ESP. See [6] and [7] for details.

See UEFI booting and RAID1 for a in-depth guide.

The key part is to use `--metadata 1.0` in order to keep the RAID metadata at the end of the partition, otherwise the firmware will not be able to access it:

    # mdadm --create --verbose --level=1 --metadata=1.0 --raid-devices=2 /dev/md/ESP /dev/sdaX /dev/sdbY

## See also

- The EFI system partition and the default boot behavior

Category:

- Boot process

Hidden categories:

- Pages or sections flagged with Template:Move
- Pages or sections flagged with Template:Expansion