双系统 — EFI 分区共存与 GRUB chainload / Dual Boot with Shared EFI Partitions and GRUB Chainloading
📅 创建时间:2026-06-17 🏷️ 标签:#双系统 #EFI #GRUB #chainload #efibootmgr 📚 前置知识:[[02-firmware-bios-uefi]], [[06-linux-boot]], [[07-windows-boot]], [[10-linux-disk-practice]]
📋 本章目标
- 理解 EFI 分区(ESP)的内部结构——Linux 和 Windows 各自放了什么
- 掌握 UEFI 启动项管理——
efibootmgr查看和修改 NVRAM 条目 - 理解 GRUB 的
os-prober——如何自动发现 Windows - 理解 GRUB chainload 的本质——把控制权交给另一个
.efi文件 - 理解 systemd-boot 的多系统配置
- 掌握常见双系统故障的修复方法
- 能够用 Arch Live USB 重建 GRUB 和 EFI 启动项
第1部分:ESP 里面到底有什么
1.1 双系统的 ESP 完整解剖
┌─────────────────────────────────────────────────────────────┐
│ ESP 分区内部结构 (Arch + Windows) │
├─────────────────────────────────────────────────────────────┤
│ │
│ /boot/ (挂载到 ESP) │
│ └── EFI/ │
│ ├── BOOT/ │
│ │ └── BOOTX64.EFI ← UEFI 的 fallback 启动文件 │
│ │ 任何 UEFI 固件都会尝试这个 │
│ │ (通常放 Windows Boot Manager│
│ │ 或 GRUB 的副本) │
│ │ │
│ ├── Linux/ │
│ │ └── grubx64.efi ← 你安装的 GRUB │
│ │ (或者: systemd/systemd-bootx64.efi) │
│ │ │
│ ├── Microsoft/ │
│ │ ├── Boot/ │
│ │ │ ├── bootmgfw.efi ← Windows Boot Manager │
│ │ │ ├── bootmgr.efi ← (副本) │
│ │ │ ├── BCD ← Windows 的启动配置数据库 │
│ │ │ ├── boot.stl ← 启动徽标 │
│ │ │ └── ... │
│ │ └── Recovery/ │
│ │ └── BCD ← Windows 恢复环境的配置 │
│ │ │
│ └── Arch/ (可选, 如果用 systemd-boot) │
│ └── grubx64.efi (或 vmlinuz-linux 作为 EFI Stub) │
│ │
│ 关键文件一览: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 文件 用途 │ │
│ │ ───────────────────────────────────────────────── │ │
│ │ EFI/Linux/grubx64.efi GRUB │ │
│ │ EFI/systemd/systemd-boot... systemd-boot │ │
│ │ EFI/Microsoft/Boot/bootmgfw.efi Windows Boot Manager│ │
│ │ EFI/BOOT/BOOTX64.EFI Fallback (UEFI 兜底) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 一个 ESP, 两个 OS, 和平共处 —— 只要不互相覆盖 │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
第2部分:efibootmgr — 管理 UEFI 启动项
2.1 UEFI 启动项存在哪里
┌─────────────────────────────────────────────────────────────┐
│ NVRAM 中的启动项 │
├─────────────────────────────────────────────────────────────┤
│ │
│ UEFI 启动项不是文件——它们存在主板 NVRAM 中: │
│ │
│ $ efibootmgr │
│ BootCurrent: 0001 │
│ Timeout: 5 seconds │
│ BootOrder: 0001,0000,0002 │
│ │
│ Boot0000* Windows Boot Manager │
│ HD(1,GPT,xxx-xxx,0x800,0x100000) │
│ \EFI\Microsoft\Boot\bootmgfw.efi │
│ │
│ Boot0001* Arch Linux │
│ HD(1,GPT,xxx-xxx,0x800,0x100000) │
│ \EFI\Linux\grubx64.efi │
│ │
│ Boot0002 UEFI: Built-in EFI Shell │
│ │
│ 关键: BootOrder = 0001, 0000, 0002 │
│ → 固件先尝试 0001 (Arch Linux) │
│ → 如果失败 → 尝试 0000 (Windows) │
│ → 如果还失败 → 尝试 0002 (EFI Shell) │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2.2 efibootmgr 常用操作
┌─────────────────────────────────────────────────────────────┐
│ efibootmgr 命令速查 │
├─────────────────────────────────────────────────────────────┤
│ │
│ # 查看所有启动项 │
│ efibootmgr │
│ │
│ # 创建新启动项 │
│ efibootmgr --create \ │
│ --disk /dev/nvme0n1 --part 1 \ │
│ --label "Arch Linux" \ │
│ --loader /EFI/Linux/grubx64.efi │
│ │
│ # 修改启动顺序 │
│ efibootmgr --bootorder 0001,0000,0002 │
│ │
│ # 删除启动项 │
│ efibootmgr --delete --bootnum 0003 │
│ │
│ # 设置超时 (秒) │
│ efibootmgr --timeout 5 │
│ │
│ # 激活/停用启动项 (不删除) │
│ efibootmgr --bootnum 0003 --inactive │
│ efibootmgr --bootnum 0003 --active │
│ │
│ # 下次启动选择 (一次性, 不改变 BootOrder) │
│ efibootmgr --bootnext 0000 │
│ → 仅下次启动时进 Windows │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
第3部分:GRUB chainload — 把控制权交出去
3.1 chainload 的原理
┌─────────────────────────────────────────────────────────────┐
│ GRUB chainload — 启动接力赛 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 正常 GRUB 启动 Linux: │
│ UEFI → grubx64.efi → 加载 vmlinuz + initramfs → 内核启动 │
│ │
│ GRUB chainload Windows: │
│ UEFI → grubx64.efi → 加载 bootmgfw.efi → Windows 启动链 │
│ ↑ ↑ │
│ GRUB 不启动 Linux 控制权完全交给 Windows │
│ 而是"链式加载"另一个 从这一步开始跟 GRUB │
│ .efi 文件 无关了 │
│ │
│ chainload 的本质: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 1. GRUB 用 UEFI 的 LoadImage() 协议加载 │ │
│ │ bootmgfw.efi 到内存 │ │
│ │ │ │
│ │ 2. GRUB 用 UEFI 的 StartImage() 协议启动它 │ │
│ │ │ │
│ │ 3. 从这一刻起: │ │
│ │ • GRUB 的内存被 UEFI 回收 │ │
│ │ • bootmgfw.efi 获得完全控制权 │ │
│ │ • 就像 UEFI 固件直接启动了 Windows 一样 │ │
│ │ │ │
│ │ 关键: chainload 不是"GRUB 加载 Windows 内核" │ │
│ │ 而是 "GRUB 请 UEFI 固件换一个人来启动" │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
3.2 GRUB 怎么发现 Windows — os-prober
┌─────────────────────────────────────────────────────────────┐
│ os-prober 的工作方式 │
├─────────────────────────────────────────────────────────────┤
│ │
│ $ sudo os-prober │
│ /dev/nvme0n1p3@/EFI/Microsoft/Boot/bootmgfw.efi: │
│ Windows Boot Manager:Windows:efi │
│ │
│ 输出含义: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 设备路径: /dev/nvme0n1p3 │ │
│ │ bootloader 路径: /EFI/Microsoft/Boot/bootmgfw.efi │ │
│ │ 名称: Windows Boot Manager │ │
│ │ 操作系统: Windows │ │
│ │ 类型: efi (UEFI 启动) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ os-prober 做的事: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 1. 挂载所有分区 │ │
│ │ 2. 在每个分区找 Windows 的标志文件: │ │
│ │ • /Windows/System32/winload.efi │ │
│ │ • /EFI/Microsoft/Boot/bootmgfw.efi │ │
│ │ 3. 如果有 → "这里有个 Windows!" │ │
│ │ 4. 输出发现的系统列表 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ GRUB 用 os-prober 的输出自动生成菜单项: │
│ │
│ # /etc/grub.d/30_os-prober 自动生成: │
│ menuentry 'Windows Boot Manager (on /dev/nvme0n1p3)' { │
│ insmod part_gpt │
│ insmod fat │
│ search --fs-uuid --set=root <ESP-UUID> │
│ chainloader /EFI/Microsoft/Boot/bootmgfw.efi │
│ } │
│ │
│ chainloader 指令 = "把这个 .efi 文件交给 UEFI 固件执行" │
│ │
│ 重新生成 GRUB 配置: │
│ $ sudo grub-mkconfig -o /boot/grub/grub.cfg │
│ │
│ 注: 如果你的 GRUB 找不到 Windows: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 1. 确保 os-prober 已安装 │ │
│ │ 2. 确保 ESP 分区已挂载到 /boot │ │
│ │ 3. 在 /etc/default/grub 中设置: │ │
│ │ GRUB_DISABLE_OS_PROBER=false │ │
│ │ 4. 重新 grub-mkconfig │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
第4部分:systemd-boot 的多系统配置
┌─────────────────────────────────────────────────────────────┐
│ systemd-boot — GRUB 的轻量替代 │
├─────────────────────────────────────────────────────────────┤
│ │
│ systemd-boot 比 GRUB 简单得多: 扫描 ESP 里的配置文件 │
│ │
│ ESP 目录结构 (systemd-boot): │
│ /boot/ │
│ └── loader/ │
│ ├── loader.conf │
│ │ default arch │
│ │ timeout 3 │
│ │ │
│ └── entries/ │
│ ├── arch.conf │
│ │ title Arch Linux │
│ │ linux /vmlinuz-linux │
│ │ initrd /initramfs-linux.img │
│ │ options root=UUID=xxx rw quiet │
│ │ │
│ └── windows.conf │
│ title Windows 11 │
│ efi /EFI/Microsoft/Boot/bootmgfw.efi │
│ ↑ │
│ 就是 chainload ! │
│ │
│ systemd-boot 的 chainload 写法: │
│ efi /EFI/Microsoft/Boot/bootmgfw.efi │
│ → systemd-boot 也使用 UEFI LoadImage/StartImage 协议 │
│ → 和 GRUB 的 chainload 完全一样的效果 │
│ │
│ systemd-boot 的优势: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 配置文件极简 (几行文本) │ │
│ │ • 不需要 grub-mkconfig 重新生成 │ │
│ │ • 自动发现 ESP 里的所有 .efi 文件 (如果配置了) │ │
│ │ • 启动比 GRUB 快 │ │
│ │ │ │
│ │ 缺点: │ │
│ │ • 只能从 ESP 启动 (GRUB 可以从任何分区) │ │
│ │ • 没有 os-prober (需要手动写 entries) │ │
│ │ • 不支持 BIOS/Legacy 模式 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
第5部分:常见故障与修复
5.1 Windows 更新后 GRUB 消失了
┌─────────────────────────────────────────────────────────────┐
│ 故障:Windows Update 覆盖了 BootOrder │
├─────────────────────────────────────────────────────────────┤
│ │
│ 症状: 开机直接进 Windows,看不到 GRUB 菜单 │
│ │
│ 原因: Windows 更新可能: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 1. 修改 NVRAM 的 BootOrder → 把 Windows 放第一 │ │
│ │ 2. 覆盖 EFI/BOOT/BOOTX64.EFI (把 GRUB 的换成 Win 的)│ │
│ │ 3. 重写 Boot#### 条目 │ │
│ │ │ │
│ │ 注意: Windows 一般不会删除 EFI/Linux/grubx64.efi │ │
│ │ 所以 GRUB 文件还在, 只是启动项被改了 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 修复方法 (用 Arch Live USB 启动): │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 1. 从 Live USB 启动 │ │
│ │ │ │
│ │ 2. 挂载你的系统: │ │
│ │ mount /dev/nvme0n1p3 /mnt │ │
│ │ mount /dev/nvme0n1p1 /mnt/boot │ │
│ │ │ │
│ │ 3. 重建 efibootmgr 启动项: │ │
│ │ efibootmgr --create \ │ │
│ │ --disk /dev/nvme0n1 --part 1 \ │ │
│ │ --label "Arch Linux" \ │ │
│ │ --loader /EFI/Linux/grubx64.efi │ │
│ │ │ │
│ │ 4. 调整启动顺序: │ │
│ │ efibootmgr --bootorder <你的Arch ID>,<Windows ID> │ │
│ │ │ │
│ │ 5. 重启 → GRUB 回来了 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
5.2 GRUB 找不到 Windows
┌─────────────────────────────────────────────────────────────┐
│ 故障:GRUB 菜单里没有 Windows 选项 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 可能原因: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 1. ESP 没有挂载 → GRUB 找不到 bootmgfw.efi │ │
│ │ 2. os-prober 没有运行或被禁用 │ │
│ │ 3. Windows 快速启动开启 → 分区处于"脏"状态 │ │
│ │ 4. 手动挂载 ESP 后忘记重新 grub-mkconfig │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 修复: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 1. 确保 ESP 已挂载: │ │
│ │ mount | grep /boot │ │
│ │ # 如果有输出 → ESP 已挂载 │ │
│ │ # 如果没有 → mount /dev/nvme0n1p1 /boot │ │
│ │ │ │
│ │ 2. 运行 os-prober: │ │
│ │ sudo os-prober │ │
│ │ # 期望输出: /dev/nvme0n1p1@/EFI/Microsoft/... │ │
│ │ # 没有输出 → Windows 的 .efi 文件找不到了 │ │
│ │ # 检查 ESP 里 \EFI\Microsoft\Boot 是否还存在 │ │
│ │ │ │
│ │ 3. 确保 GRUB 不禁用 os-prober: │ │
│ │ 编辑 /etc/default/grub: │ │
│ │ GRUB_DISABLE_OS_PROBER=false │ │
│ │ │ │
│ │ 4. 重新生成 GRUB 配置: │ │
│ │ sudo grub-mkconfig -o /boot/grub/grub.cfg │ │
│ │ # 观察输出: 是否显示 "Found Windows Boot Manager" │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
5.3 GRUB 进入 rescue 模式
┌─────────────────────────────────────────────────────────────┐
│ grub rescue> 提示符 — 如何自救 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 症状: 开机后不是 GRUB 菜单, 而是: │
│ error: no such partition. │
│ grub rescue> │
│ │
│ 原因: GRUB 找不到 /boot/grub/ (grub.cfg 所在位置) │
│ 可能是分区 UUID 变了 / 磁盘顺序变了 │
│ │
│ 在 grub rescue> 下手动启动: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 1. 找到 /boot 在哪: │ │
│ │ grub rescue> ls │ │
│ │ (hd0) (hd0,gpt1) (hd0,gpt2) (hd0,gpt3) │ │
│ │ │ │
│ │ 2. 逐个尝试找 /boot/grub: │ │
│ │ grub rescue> ls (hd0,gpt1)/ │ │
│ │ grub rescue> ls (hd0,gpt1)/grub/ │ │
│ │ # 找到有 grub.cfg 的那个 │ │
│ │ │ │
│ │ 3. 设置 GRUB 的根: │ │
│ │ grub rescue> set prefix=(hd0,gpt1)/grub │ │
│ │ grub rescue> set root=(hd0,gpt1) │ │
│ │ │ │
│ │ 4. 加载 normal 模块: │ │
│ │ grub rescue> insmod normal │ │
│ │ grub rescue> normal │ │
│ │ → GRUB 菜单出现了! │ │
│ │ │ │
│ │ 5. 进入系统后修复: │ │
│ │ sudo grub-install /dev/nvme0n1 │ │
│ │ sudo grub-mkconfig -o /boot/grub/grub.cfg │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
核心总结
总结1:双系统四个关键文件
1. grubx64.efi — 你的 GRUB, 在 ESP/EFI/Linux/
2. bootmgfw.efi — Windows 的门, 在 ESP/EFI/Microsoft/Boot/
3. /boot/grub/grub.cfg — GRUB 的菜单配置
4. NVRAM BootOrder — 主板上的启动顺序 (用 efibootmgr 管理)2
3
4
总结2:GRUB chainload 的两行本质
search --fs-uuid --set=root <ESP-UUID>
chainloader /EFI/Microsoft/Boot/bootmgfw.efi2
总结3:出事了三件套
1. Live USB 启动 → 挂载系统 → arch-chroot
2. grub-install /dev/nvme0n1 (重装 GRUB 到磁盘)
3. grub-mkconfig -o /boot/grub/grub.cfg (重新生成配置)2
3
章节测试
测试1:ESP 内容
ESP 分区里 Linux 和 Windows 各自放在哪个目录?
测试2:chainload
GRUB 的 chainloader 指令做了什么?它是 GRUB 自己加载 Windows 内核吗?
测试3:Windows 更新覆盖
Windows 更新后,GRUB 消失了。你的 GRUB 文件(grubx64.efi 和 grub.cfg)还在吗?怎么修复?
测试4:grub rescue
你看到了 grub rescue> 提示符。第一步应该做什么?
参考答案
测试1答案
- Linux (GRUB):
ESP/EFI/Linux/grubx64.efi;如果用 systemd-boot:ESP/EFI/systemd/systemd-bootx64.efi - Windows:
ESP/EFI/Microsoft/Boot/bootmgfw.efi - Fallback(UEFI 兜底):
ESP/EFI/BOOT/BOOTX64.EFI
测试2答案
不。chainloader 不是 GRUB 加载 Windows 内核。GRUB 做的事是:(1) 通过 UEFI 的 LoadImage() 协议,把 bootmgfw.efi 加载到内存;(2) 通过 UEFI 的 StartImage() 协议启动它。此后 GRUB 的内存被回收,控制权完全移交给 Windows 的启动链。这相当于 UEFI 固件换了一个启动程序来执行——所以叫"链式加载"(chain load)。
测试3答案
GRUB 文件通常还在。Windows 更新一般只修改 NVRAM 的 BootOrder 或覆盖 EFI/BOOT/BOOTX64.EFI,不会删除 EFI/Linux/grubx64.efi。修复:用 Live USB 启动,挂载 ESP,用 efibootmgr --create 重建 Arch Linux 的启动项,调整 BootOrder 把 Arch 放第一位。
测试4答案
第一步:用 ls 命令探索可用的分区,找到包含 /grub/grub.cfg 的那个分区。然后手动设置 prefix 和 root 变量指向它,加载 normal 模块,就能恢复 GRUB 菜单。进入系统后立即执行 grub-install 和 grub-mkconfig 做永久修复。
相关笔记
- [[02-firmware-bios-uefi]] - UEFI 和 ESP 的基础
- [[06-linux-boot]] - Linux 启动链全流程
- [[07-windows-boot]] - Windows 启动链全流程
- [[10-linux-disk-practice]] - 挂载 ESP 和 chroot 救援
🎉 系列完结
恭喜完成整个 OS 底层知识系列!你已经从"通电那一刻"走到了"双系统 GRUB 菜单"。
返回总览:00 - OS 底层知识学习路线
学习状态:完成