跳转至内容

EFI 系统分区

来自 ArchWiki

EFI 系统分区(也称为 ESP)是一个与操作系统无关的分区,它充当 UEFI 固件要启动的 UEFI 引导加载程序、应用程序和驱动程序的存储位置。UEFI 引导是强制性的。

检查现有分区

如果您正在将 Arch Linux 安装到支持 UEFI 的计算机上,并且该计算机上已安装了操作系统,例如 Windows 10,那么您很可能已经有一个 EFI 系统分区。

要找出磁盘分区方案和系统分区,请以 root 身份在您要从中引导的磁盘上使用 fdisk

# fdisk -l /dev/sdx

命令返回

  • 磁盘分区表:如果分区表是 GPT,它将显示 Disklabel type: gpt;如果是 MBR,则显示 Disklabel type: dos
  • 磁盘上的分区列表:在列表中查找 EFI 系统分区,它通常至少为 100 MiB 大,并且类型为 EFI SystemEFI (FAT-12/16/32)。要确认这是否是 ESP,请 挂载 它并检查它是否包含名为 EFI 的目录;如果是,这绝对是 ESP。
提示 要确定它是 FAT12、FAT16 还是 FAT32 文件系统,请遵循 FAT#检测 FAT 类型
警告 在双引导时,请尽量避免重新格式化 ESP,因为它可能包含引导其他操作系统所需的文件。如果现有的 ESP 小于建议的最小尺寸,您可能需要将其替换为更大的分区

如果您找到了一个可接受的现有 EFI 系统分区,请继续 #挂载分区。如果您没有找到,则需要创建它,请继续 #创建分区

创建分区

以下两节将介绍如何创建 EFI 系统分区(ESP)。

警告 EFI 系统分区必须是磁盘主分区表中的物理分区,而不是 LVM 或软件 RAID 等下的分区。

分区大小应提供足够的空间来存储引导加载程序和其他引导所需的文件。

建议将分区设置为 1 GiB 大小,以确保它有足够的空间容纳多个内核或统一内核映像、引导加载程序、固件更新文件以及任何其他操作系统或 OEM 文件。如果您仍不确定,4 GiB 应该足够了。

对于 Limine 引导加载程序(支持 Btrfs 的 Snapper 集成)(支持创建多个可引导快照)和 Archiso on ESP(无需外部介质即可引导的系统恢复 ISO 映像)之类的工具,请考虑更大的尺寸(例如 8 GiB)。

注意 可以使用较小的分区,但要留意潜在的兼容性问题。
  • 对于早期和/或有 bug 的 UEFI 实现,可能需要至少 512 MiB 的尺寸。[1]
  • 如果您计划将分区挂载到 /boot 并且不安装多个内核,那么 400 MiB 将足够。
  • 与 Windows 双引导时,对于逻辑扇区大小为 4096 的驱动器(高级格式化 4Kn 驱动器),大小应至少为 300 MiB[2];否则至少应为 100 MiB。[3]
  • 为确保分区可以格式化为 FAT32,对于逻辑扇区大小为 512 字节的驱动器,它应至少为 36 MiB,对于逻辑扇区大小为 4096 字节的驱动器,它应至少为 260 MiB。[4]
  • 如果以上情况都不适用,分区大小可以小至 2 MiB,在这种情况下,它只能容纳引导加载程序。

GPT 分区磁盘

GUID 分区表上的 EFI 系统分区由分区类型 GUID C12A7328-F81F-11D2-BA4B-00A0C93EC93B 标识。

选择以下一种方法为 GPT 分区磁盘创建 ESP。

  • fdisk:创建一个分区,并使用 t 命令将其分区类型更改为 EFI System,使用别名 uefi
  • gdisk:创建一个分区,类型为 EF00
  • GNU Parted:创建一个分区,文件系统类型为 fat32,并为其设置 esp 标志。

创建分区后,应使用文件系统进行格式化。请继续以下#格式化分区部分。

MBR 分区磁盘

警告 强烈建议使用 GPT 而非 MBR。

有关 MBR 的限制以及 GPT 的一般优势,请参阅 Partitioning#在 GPT 和 MBR 之间进行选择

主引导记录(Master Boot Record)分区表上的 EFI 系统分区由分区类型 ID EF 标识。

选择以下一种方法为 MBR 分区磁盘创建 ESP。

  • fdisk:创建一个主分区,并使用 t 命令将其分区类型更改为 EFI (FAT-12/16/32)
  • GNU Parted:创建一个主分区,文件系统类型为 fat32,并为其设置 esp 标志。

创建分区后,应使用文件系统进行格式化。请继续以下#格式化分区部分。

格式化分区

UEFI 规范要求支持 FAT12、FAT16 和 FAT32 文件系统(参见 UEFI 规范版本 2.11,第 13.3.1.1 节),但任何符合标准的供应商都可以选择添加对其他文件系统的支持;例如,Apple Macs 的固件支持 HFS+ 文件系统。

为避免与其他操作系统可能出现的问题,并且由于 UEFI 规范规定 UEFI "包含使用 FAT32 作为系统分区,以及使用 FAT12 或 FAT16 作为可移动介质"[5],建议使用 FAT32。使用来自 dosfstoolsmkfs.fat(8) 工具。

# mkfs.fat -F 32 /dev/sdxY

如果收到消息 WARNING: Number of clusters for 32 bit FAT is less than suggested minimum. 且您无法创建更大的 ESP,请使用 mkfs.fat -s 2 -F 32 ...-s 1 减小集群大小;否则该分区可能无法被 UEFI 读取。有关支持的集群大小,请参阅 mkfs.fat(8)

对于小于 32 MiB 的分区,可能无法使用 FAT32。在这种情况下,请将其格式化为 FAT16 甚至 FAT12。例如,一个 2 MiB 的 ESP 只能支持 FAT12。

# mkfs.fat -F 12 /dev/sdxY

挂载分区

内核、initramfs 文件,以及在大多数情况下,CPU 的微码,都需要被引导加载程序或 UEFI 本身访问才能成功引导系统。因此,如果您想保持设置简单,您的引导加载程序选择将限制 EFI 系统分区的可用挂载点。

注意 如果 ESP 没有挂载到 /boot,请确保在内核升级期间不依赖 systemd 的自动挂载机制(包括 systemd-gpt-auto-generator)。在进行任何系统或内核更新之前,务必手动挂载它,否则更新后您可能无法挂载它,从而被锁定在当前运行的内核中,无法更新 ESP 上的内核副本。

或者,在引导时预加载所需的内核模块,例如:

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

典型挂载点

挂载 EFI 系统分区的三个典型场景是:

  • 挂载 ESP 到 /boot
    • 这有助于系统维护和管理,因为 /boot微码包放置 CPU 微码 initramfs 文件的默认路径,也是 mkinitcpio 放置 内核initramfs 映像的路径。
    • 这确保了上述文件可被大多数 引导加载程序访问,因为并非所有引导加载程序都能访问其他卷上的文件。
    • 这可以防止设置文件特定的 权限和/或 扩展属性,因为 FAT 在挂载时设置全局权限。
    • 这增加了 ESP 的大小要求,因为通常安装在 /boot 的文件将与用于 UEFI 引导的文件合并。
    • 这会将内核和 initramfs 映像暴露给可启动驱动器或其他操作系统在双引导时的潜在危险操作。
    • 这使得加密 /boot 不可能,因为引导加载程序及其文件必须对固件可见。
    • 这使得根卷快照(使用 BtrfsBcachefsZFSLVM)效果不佳,因为 /boot 的内容不会被包含。在内核更新的情况下,恢复到包含旧内核版本的快照将导致系统无法引导,并需要使用外部介质手动降级内核
  • 挂载 ESP 到 /efi
    • 注意 目前只有 GRUBrEFInd 支持此方案。
    • 它确保了操作系统文件和 UEFI 文件之间的关注点分离,其中可能包含其他不宜干扰的操作系统文件。
    • 它避免了增加 ESP 的大小要求,因为它不会将安装到 /boot 的文件放在 ESP 上:只有 EFI 二进制文件(引导加载程序(以及可选的驱动程序)和/或统一内核映像)将存储在 ESP 上,从而节省存储空间。
    • 它允许为驻留在 /boot 中的文件保留 Linux 特定的文件系统权限,避免了 FAT 的限制。
    • 它允许根据需要单独挂载 ESP,例如,仅在升级引导加载程序时。
    • 如果使用系统加密并进行适当的设置,它可以只留下少数必需的文件未加密,同时 /boot 保持受保护:这对于能够访问存储在其他位置的内核和文件的统一内核映像引导加载程序可能很有用。
  • 挂载 ESP 到 /efi,并另外将“扩展引导加载程序分区”(XBOOTLDR)挂载到 /boot。当之前创建的 ESP 太小而无法容纳多个引导加载程序和/或内核,但 ESP 又无法轻松调整大小时(例如,在 Windows 之后安装 Linux 进行双引导),此方法可能很有用。至少 systemd-boot 支持此方法。
  • /efi 是历史上的且现在不推荐使用的 ESP 挂载点 /boot/efi[6][7] 的替代品。
  • /efi 目录默认不可用,您需要先创建它,然后再将 ESP 挂载到其中。

替代挂载点

如果您不使用#典型挂载点之一,您需要将引导文件复制到 ESP(以下称 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/
注意 如果您使用外部微码 initramfs 映像,它们也需要被复制到引导入口位置。

此外,您需要使 ESP 上的文件与后续内核更新保持同步。否则可能导致系统无法引导。以下各节讨论了几种实现自动化的机制。

使用绑定挂载

与其将 ESP 本身挂载到 /boot,不如使用绑定挂载(参见 mount(8))将 ESP 的一个目录挂载到 /boot。这允许 pacman 直接更新内核,同时保持 ESP 按您的喜好组织。

注意 这需要一个兼容 FAT32 的内核引导加载程序。对于常规的 Arch 安装来说这不成问题,但对于其他发行版(特别是那些要求在 /boot/ 中使用符号链接的发行版)可能会有问题。请参阅论坛帖子 [8]

#替代挂载点中一样,将所有引导文件复制到 ESP 上的一个目录,但将 ESP 挂载在 /boot外部。然后绑定挂载该目录。

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

在成功验证后,编辑您的 Fstab 以使更改持久化。

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

使用 systemd

systemd 具有事件触发任务。在此特定情况下,使用检测路径更改的能力来同步 EFISTUB 内核和 initramfs 文件,当它们在 /boot/ 中更新时。用于监视更改的文件是 initramfs-linux-fallback.img,因为这是 mkinitcpio 构建的最后一个文件,以确保所有文件在开始复制之前已构建完成。要创建的 systemd 路径和服务文件是:

/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/

然后启用启动 efistub-update.path

提示 对于带有您自己密钥的安全启动,您可以设置服务以使用 sbsigntools 来签名映像。
ExecStart=/usr/bin/sbsign --key /path/to/db.key --cert /path/to/db.crt --output esp/EFI/arch/vmlinuz-linux /boot/vmlinuz-linux

使用文件系统事件

文件系统事件可用于在内核更新后运行脚本同步 EFISTUB 内核。以下是一个使用 incron 的示例。

/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/
注意 第一个参数 /boot/initramfs-linux-fallback.img 是要监视的文件。第二个参数 IN_CLOSE_WRITE 是要监视的操作。第三个参数 /usr/local/bin/efistub-update 是要执行的脚本。
/etc/incron.d/efistub-update.conf
/boot/initramfs-linux-fallback.img IN_CLOSE_WRITE /usr/local/bin/efistub-update

为了使用此方法,请启用 incrond.service

使用 mkinitcpio 预设

由于 /etc/mkinitcpio.d/ 中的预设支持 shell 脚本,因此可以通过编辑预设来复制内核和 initramfs。

替换 mkinitcpio hook

编辑文件 /etc/mkinitcpio.d/linux.preset

/etc/mkinitcpio.d/linux.preset
# mkinitcpio preset file for the 'linux' package

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

#ALL_config="/etc/mkinitcpio.conf"
ALL_kver="${ESP_DIR}/vmlinuz-linux"

PRESETS=('default' 'fallback')

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

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

要测试此功能,只需运行:

# rm /boot/initramfs-linux-fallback.img /boot/initramfs-linux.img
# mv /boot/vmlinuz-linux esp/EFI/arch/
# mkinitcpio -p linux
另一个例子
/etc/mkinitcpio.d/linux.preset
ESP_DIR="esp/EFI/arch"
#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-zen.preset
suffix='-zen'
source /etc/mkinitcpio.d/linux.preset

使用 mkinitcpio 后置 hook

可以使用 mkinitcpio 后置 hook 在 initramfs 生成后将内核和 initramfs 映像复制到所需的目录。

创建以下文件并使其可执行

/etc/initcpio/post/copy-kernel-and-initramfs
#!/usr/bin/env bash

kernel="$1"
initramfs="$2"
target_dir="esp/EFI/arch"
files_to_copy=()

for file in "$kernel" "$initramfs"; do
	if [[ -n "$file" ]] && ! cmp -s -- "$file" "${target_dir}/${file##*/}"; then
		files_to_copy+=("$file")
	fi
done

(( ! ${#files_to_copy[@]} )) && exit 0

cp -af -- "${files_to_copy[@]}" "${target_dir}/"

使用 pacman hook

最后一个选项依赖于 pacman hooks,它们在事务结束时运行。

第一个文件是一个监视相关文件的 hook,如果这些文件在之前的事务中被修改,它将被运行。

/etc/pacman.d/hooks/999-kernel-efi-copy.hook
[Trigger]
Type = Path
Operation = Install
Operation = Upgrade
Target = usr/lib/modules/*/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

第二个文件是脚本本身。创建文件并使其可执行

/usr/local/bin/kernel-efi-copy.sh
#!/bin/sh
#
# 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

技巧与提示

替换为更大的分区

在带有预装操作系统的磁盘上,EFI 系统分区可能小于#创建分区中建议的大小。例如,Windows 安装程序在非 4Kn 驱动器上创建一个仅 100 MiB 的 EFI 系统分区。

在这种情况下,最好创建一个新的、更大的 EFI 系统分区,以防止其空间不足。

在 Windows 中为新分区腾出空间

在 Windows 中,可以使用磁盘管理(diskmgmt.msc)图形化管理分区,或使用 diskpart.exe 实用程序从命令行管理分区。

以管理员身份运行 diskmgmt.msc

  1. 右键单击“(C:)”分区(这是默认 Windows 创建的分区中唯一可以联机调整大小的分区),然后选择“Shrink Volume...”。
  2. 输入 4096 作为要收缩的量,然后单击“Shrink”。

现在“(C:)”分区之后应该有 4 GiB 的未分配空间。

启动到 Arch Linux 或 Arch Linux 安装介质,以继续创建新分区。

删除旧分区并创建新分区

首先,请务必备份 EFI 系统分区的内容。例如,以 esp 为其挂载点:

# cp -a esp /esp_backup

卸载 EFI 系统分区

# umount esp
注意 在已安装的系统上,您可能还需要停止 esp.mountesp.automount 单元,以防止 systemd 再次自动挂载它。

运行 blkid 并记下 UUID 和 PARTUUID 值。稍后将重新使用它们为新分区。

# blkid
/dev/sdxY: UUID="XXXX-XXXX" BLOCK_SIZE="512" TYPE="vfat" PARTLABEL="EFI system partition" PARTUUID="YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY"

使用 gptfdisk 中的 sgdisk 删除旧分区。

# sgdisk --delete=Y /dev/sdx

在最大的未分配空间中创建一个新分区,同时重新使用旧的 PARTUUID 和 PARTLABEL。

# sgdisk --align-end --largest-new=0 --typecode=0:ef00 --change-name=0:'EFI system partition' --partition-guid=0:YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY /dev/sdx

使用 parted 中的 partprobe(8) 让内核重新读取分区表。

# partprobe /dev/sdx

通过 fdisk 列出分区,确认新的 4 GiB EFI 系统分区已创建。

# fdisk -l /dev/sdx
...
Device         Start       End   Sectors  Size Type
/dev/sdx1  158099456 166488063   8388608    4G EFI System
/dev/sdx2     206848    239615     32768   16M Microsoft reserved
/dev/sdx3     239616 158099455 157859840 75.3G Microsoft basic data
/dev/sdx4  166488064 167768063   1280000  625M Windows recovery environment
/dev/sdx5  167768064 176156671   8388608    4G Linux swap
/dev/sdx6  176156672 243265535  67108864   32G Linux root (x86-64)

Partition table entries are not in disk order.

删除和创建分区时,分区编号不会重新排序,因此磁盘上的 EFI 系统分区编号很可能与之前相同。

将分区格式化为 FAT32,并重新使用旧的 UUID(同时删除其中的连字符)。

# mkfs.fat -F 32 -i XXXXXXXX /dev/sdxY

最后,挂载新分区并从备份中恢复其内容。

# mount /dev/sdxY esp
# cp -a /esp_backup/. esp/

如果您之前停止了 esp.automount,请再次启动它。

牺牲相邻的交换分区以扩大 ESP

如果 EFI 系统分区之后有一个交换分区,您可以牺牲它来为扩大 EFI 系统分区腾出空间。例如,使用类似以下的布局:

# fdisk -l /dev/sdx
...
Device       Start       End   Sectors  Size Type
/dev/sdx1     2048    616447    614400  300M EFI System
/dev/sdx2   616448   9005055   8388608    4G Linux swap
/dev/sdx3  9005056 125827071 116822016 55.7G Linux root (x86-64)

首先,禁用交换分区并将其从 fstab 中移除。

使用 fdisk 删除交换分区并扩大 EFI 系统分区。

  1. 运行
    # fdisk /dev/sdx
  2. 使用 d 命令删除交换分区(上面示例布局中的分区编号 2)。
  3. 使用 e 命令扩大 EFI 系统分区(上面示例布局中的分区编号 1)。使用建议的默认值作为新大小,然后按 Enter
  4. 使用 w 命令将更改写入磁盘并退出。

调整分区大小后,您需要调整其中文件系统的大小。由于 fatresize(1) 无法正常工作,libparted 无法调整某些大小的 FAT 卷,唯一的选择是备份现有文件系统中的文件,并创建一个新的文件系统,该文件系统占用分区的所有空间。

记下文件系统 UUID 以便重新用于新文件系统。

$ lsblk -dno UUID /dev/sdxY
XXXX-XXXX

备份 EFI 系统分区的内容。例如,以 esp 为其挂载点:

# cp -a esp /esp_backup

卸载 EFI 系统分区

# umount esp
注意 在已安装的系统上,您可能还需要停止 esp.mountesp.automount 单元,以防止 systemd 再次自动挂载它。

擦除分区上的文件系统签名,以避免旧文件系统的任何痕迹。

# wipefs -af /dev/sdxY

将分区格式化为 FAT32,并重新使用旧的 UUID(同时删除其中的连字符)。

# mkfs.fat -F 32 -i XXXXXXXX /dev/sdxY

最后,挂载新分区并从备份中恢复其内容。

# mount /dev/sdxY esp
# cp -a /esp_backup/. esp/

如果您之前停止了 esp.automount,请再次启动它。

现在交换分区已消失,在交换文件上设置交换。

故障排除

软件 RAID1 上的 ESP

可以将 ESP 作为 RAID1 阵列的一部分,但这会带来数据损坏的风险,并且在创建 ESP 时需要采取进一步的考虑。有关详细信息和解决方案,请参阅 [9][10],以及 UEFI 引导和 RAID1 的深度指南。

关键部分是使用 --metadata 1.0 以将 RAID 元数据保留在分区末尾,否则固件将无法访问它。

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

或者,由于 ESP 不常更新,可以通过在相关更新期间将主 ESP 复制到不同磁盘上的次要 ESP 来管理次要 ESP。然后可以使用 efibootmgr 手动添加次要 ESP 的引导入口。有关实现示例,请参阅 Debian:UEFI#RAID for the EFI System Partition。请注意,虽然这避免了 RAID 方法的一些风险,但它仅在使用单一操作系统时才有效。

固件看不到 EFI 目录

如果您为 FAT 文件系统指定了卷名(即文件系统标签),请确保其名称不是 EFI。这可能会触发某些固件中的 bug(因为卷名与 EFI 目录名称匹配),导致固件表现得好像 EFI 目录不存在一样。

休眠和多系统引导

如果您运行的是多系统引导(包括但不限于与 Windows 双引导),并且希望在主 Arch Linux 休眠时能够引导到其他系统,则必须格外小心,不要在两个系统上挂载 ESP,因为这很可能导致数据损坏和使用时发生 I/O 错误。

有三种可能的缓解策略:

  1. 为每个系统使用单独的 EFI 系统分区。大多数 UEFI 支持此功能,前提是 ESP 位于物理上不同的磁盘上,但硬件支持和可用性可能有所不同。
  2. 使用 systemd 的自动挂载机制,仅在需要时挂载 ESP。确保还指定了空闲超时(x-systemd.idle-timeout= 选项),否则 systemd 将不会在使用后卸载 ESP。但是,请注意两个限制:首先,除非您将 ESP 挂载到 /boot,否则在内核升级期间不得依赖自动挂载(请参见上面的注释)。其次,您必须确保在 systemd 自动卸载 ESP 之后(请参阅自动卸载)休眠系统。
  3. 将 ESP 挂载到 /efi,并在休眠系统之前卸载它,之后再重新挂载它。请参阅下面的说明

通过成功应用上述一种缓解策略,您可以使此系统进入休眠状态,但不能使其他系统进入休眠状态,除非您也对它们应用了其中一种缓解策略。例如,对您的主 Arch Linux 应用其中一种解决方案,可以让您将 Arch Linux 置于休眠状态并启动到另一个,例如 Ubuntu Linux,但不能将该 Ubuntu Linux 置于休眠状态并启动到您的主 Arch Linux。要允许 Windows 实现这一点,需要单独的 EFI 系统分区。

严格来说,将同一个文件系统同时挂载多次的问题既不限于 EFI 系统分区,也不限于系统休眠。然而,对于 ESP 来说,这个问题尤其重要,因为 ESP 预计会在多个系统之间共享。缓解策略也可以适应其他用例。

休眠时卸载并重新挂载 ESP

如果您选择了上述选项 3,您可以创建并启用以下 systemd 系统服务,该服务会在系统休眠前卸载 ESP,并在恢复后重新挂载它。

/etc/systemd/system/efi-remount-on-hibernate.service
[Unit]
Description=Unmount and remount EFI system partition on hibernation
Before=hibernate.target hybrid-sleep.target suspend-then-hibernate.target
StopWhenUnneeded=yes

[Service]
Type=oneshot
RemainAfterExit=yes
ExecCondition=/usr/bin/systemctl is-active --quiet efi.mount
ExecStart=/usr/bin/systemctl stop efi.mount
ExecStop=/usr/bin/systemctl start efi.mount

[Install]
WantedBy=hibernate.target hybrid-sleep.target suspend-then-hibernate.target

然而,由于默认情况下 efi.mountlocal-fs.target 作为依赖项引入,停止 efi.mount 也会永久性地禁用 local-fs.target。这可能会产生各种不良的副作用,包括系统关机时的顺序问题,这可能触发 systemd 将 efi.mount 自动屏蔽为有缺陷。可以通过告知 systemd efi.mount 不是 local-fs.target 所必需的,而是 local-fs.target 所期望的来缓解这种情况。为确保这一点,您必须在 /etc/fstab 中为 /efi 添加以下挂载选项:

x-systemd.wanted-by=local-fs.target,x-systemd.after=local-fs-pre.target,x-systemd.before=local-fs.target

参见