从零写OS内核 | Windows GPT+UEFI 启动:ESP 分区、NVRAM 启动项与 Secure Boot 完整解析
上一章讲了 MBR+BIOS 模式下的 Windows 启动链路,System Reserved 分区是整个链路的核心锚点——BOOTMGR 和 BCD 都在那个 100MB 的 FAT32 分区里,BIOS 通过 MBR 的活动分区标记找到它。
但如果你买的是 2014 年后出厂的品牌机(ThinkPad、戴尔、惠普台式机),大概率已经不在 MBR 模式下了——它用的是 GPT+UEFI,System Reserved 分区消失了,取而代之的是一个 ESP(EFI System Partition),启动项不再靠”活动分区标记”,而是由 NVRAM(非易失性内存)里的启动条目管理。
这两个模式不只是”分区表格式不同”,是完全不同的启动哲学:
| MBR+BIOS | GPT+UEFI | |
|---|---|---|
| 分区表位置 | LBA 0(512 字节混在一起) | LBA 1(GPT Header)+ LBA 2-33(分区表) |
| 启动标记 | MBR 分区表 0x80 活动位 | NVRAM 的 BootOrder(闪存,不在磁盘上) |
| 引导管理器位置 | System Reserved(FAT32,100MB) | ESP(FAT32,≥100MB) |
| 启动文件格式 | BOOTMGR(16 位实模式) | bootmgfw.efi(64 位 PE/COFF) |
| 安全启动 | 无(BIOS 模式无签名验证) | Secure Boot(签名链验证) |
| 多系统共存 | GRUB 写 MBR + 链式加载 | GRUB 写 ESP + NVRAM 条目 |
| 磁盘容量限制 | 2TB(32 位 LBA) | 8ZB(64 位 LBA,无上限) |
这一章,我们来把 Windows GPT+UEFI 启动链路彻底拆解——ESP 分区里装了什么,NVRAM 的 BootOrder 是怎么工作的,Secure Boot 签名链是怎么回事,以及所有相关的工具怎么用。
启动链路:完整的 10 步流程
GPT+UEFI 模式下,Windows 的启动链路比 MBR+BIOS 更长,但每一步都更清晰:
① 电源按下
→ CPU 从固化在硅片里的初始微代码开始执行
→ 初始化 UART(GDB 调试用)、初始化内存控制器
② UEFI 固件初始化(SEC → PEI → DXE → BDS)
→ SEC(Security):初始化 CPU 微码、内存检测(最早的无 DRAM 阶段)
→ PEI(Pre-EFI Initialization):内存初始化,找到引导设备
→ DXE(Driver Execution Environment):加载设备驱动(USB/SATA/NVMe)
→ BDS(Boot Device Selection):按启动顺序查找启动项
③ 读取 NVRAM 里的 BootOrder
→ NVRAM 里有 NVRAM BootOrder(启动优先级列表)
→ 第一个可用的启动项被选中
→ 例如:Boot0001 = EFIMicrosoftBootbootmgfw.efi
④ 加载 bootmgfw.efi
→ 路径:ESP/EFI/Microsoft/Boot/bootmgfw.efi
→ 格式:64 位 PE/COFF 可执行文件(不是 COM/MZ 格式)
→ UEFI 固件验证文件签名(Secure Boot 模式下)
⑤ bootmgfw.efi 读取 BCD
→ 位置:ESP/Boot/BCD(或 ESP/EFI/Microsoft/Boot/BCD)
→ 格式:注册表 hive(和 MBR 模式完全一样)
→ 显示启动菜单(或直接加载默认项)
⑥ 根据 BCD 里的 osdevice 找到 Windows 分区
→ MBR 模式靠"活动分区标记",UEFI 模式靠 GPT 分区 GUID
→ GPT 里每个分区都有唯一的 GUID,不会搞混
⑦ 加载 winload.efi
→ 路径:C:WindowsSystem32winload.efi
→ 和 MBR 模式的 winload.exe 不同,efi 版本是 64 位 PE/COFF
→ 再次验证签名(Secure Boot 模式)
⑧ winload.efi 读取注册表
→ HKLMSYSTEMSelectCurrent(确定 ControlSet)
→ 加载 WindowsSystem32configSYSTEM
⑨ 加载内核 ntoskrnl.exe + 驱动
→ 切换到更高特权级
→ 启动 Windows
⑩ 登录界面ESP 分区:UEFI 模式下的”System Reserved”
ESP 的标准位置和大小
ESP(EFI System Partition)是一个 FAT32 文件系统的小分区,最小 100MB,推荐 260MB 以上(给 GRUB 未来升级留空间)。
ESP 典型布局(GPT,500GB SSD):
分区号 文件系统 大小 挂载点 内容
─────────────────────────────────────────────────────
/dev/sda1 FAT32 260MB /boot/efi(Linux) ESP(Windows + GRUB)
/dev/sda2 NTFS 233GB C: Windows 系统
/dev/sda3 - 16MB - Microsoft Reserved为什么是 FAT32? 因为 UEFI 规范要求所有 UEFI 固件必须支持 FAT32(对 ESP 是强制要求)。NTFS、ext4、APFS 都不在 UEFI 规范里,所以 ESP 必须是 FAT32。
ESP 里到底装了什么
ESP 分区内容(Windows + Linux 双系统):
/EFI/
├── Boot/
│ └── BOOTX64.EFI ← 默认回退启动项(每台 UEFI 机器都有)
│ 类似于 BIOS 的"默认启动设备"
├── Microsoft/
│ └── Boot/
│ ├── bootmgfw.efi ← Windows Boot Manager(UEFI 版本)
│ ├── bootmgr.efi ← 备用的 boot manager(和安全启动相关)
│ ├── BCD ← 启动配置数据(BCD 注册表 hive)
│ ├── BCD.LOG ← BCD 事务日志
│ ├── BCD.LOG1 ← 更早的日志
│ ├── BCD.LOG2
│ ├── boot.stl ← 启动菜单静态资源(字体、图标)
│ ├── fonts/
│ │ ├── boot.ttf ← 启动菜单字体(中文等)
│ │ └── seguisub.ttf ← 备用字体
│ ├── Resources/
│ │ ├── bootres.dll ← UI 资源文件
│ │ └── ...
│ ├── zh-CN/
│ │ ├── bootmgfw.efi.mui # 本地化资源
│ │ ├── bootmgr.efi.mui
│ │ └── ...
│ └── Recovery/ ← WinRE 镜像(不是所有机器都有)
├── ubuntu/
│ ├── grubx64.efi ← GRUB 2 主程序(Ubuntu)
│ ├── grub.cfg ← GRUB 配置文件
│ ├── shimx64.efi ← Secure Boot 签名垫片(Ubuntu)
│ └── MokManager.efi ← MOK 管理工具(机器所有者密钥)
└── arch/
└── grubx64.efi ← Arch 的 GRUBbootmgfw.efi vs bootmgr.exe
| 文件 | 模式 | 字长 | 格式 |
|---|---|---|---|
bootmgfw.efi |
UEFI | 64 位 | PE/COFF(和 .exe 相同,.efi 扩展名) |
bootmgr.exe |
BIOS | 16/32 位 | Windows PE 可执行程序(NTFS 压缩) |
bootmgr.efi |
UEFI | 64 位 | bootmgfw.efi 的备用名(部分机器用这个文件名) |
bootmgfw.efi 是 UEFI 规范下的”UEFI 应用”,它和 Windows 里普通的 .exe 一样是 PE/COFF 格式,但扩展名 .efi 让固件知道”这是一个 UEFI 应用,固件可以直接执行它”。
NVRAM:启动项的”数据库”
NVRAM 是什么
NVRAM(Non-Volatile RAM,非易失性内存)是 UEFI 固件的一部分,通常是 Flash 芯片(或 EEPROM)的一小块区域,即使关机也不会丢失数据。它存储了:
- BootOrder:启动优先级列表(按顺序尝试每个启动项)
- BootXXXX:每个启动项的详细信息(名字、路径、参数)
- DriverOrder:UEFI 驱动加载顺序(不常见)
- PlatformLang:首选语言
- KeyPad/Timeout:启动菜单超时时间
NVRAM 存储的内容(简化示例):
BootOrder: 0001, 0000, 0002
Boot0000: Windows Boot Manager HD(1,GPT,...)File(EFIMicrosoftBootbootmgfw.efi)
Boot0001: ubuntu HD(2,GPT,...)File(EFIubuntushimx64.efi)
Boot0002: USB Drive Removable(HW)
DriverOrder: (通常为空)
Timeout: 10NVRAM 的工作原理
NVRAM 存储在 UEFI 固件的 Flash 芯片里,不是磁盘上。这意味着:
- 格式化磁盘不会影响启动项(和 MBR 模式不同)
- 重装 Windows 会重新写入 NVRAM(覆盖 GRUB 的条目)
- BIOS 设置被清除/恢复可能导致 NVRAM 丢失(某些型号)
NVRAM 损坏的症状:
- 按 F12/Del 进入启动菜单时,选项全部消失
- 或者启动顺序变成空的,BIOS 提示 “No bootable device”
efibootmgr:Linux 下操作 NVRAM
# 查看所有启动项(无需 root)
efibootmgr
# 输出示例:
# BootCurrent: 0001
# BootOrder: 0001, 0000, 0002
# Boot0000* Windows Boot Manager
# Boot0001* ubuntu
# Boot0002* USB Drive (UEFI)
# Timeout: 10 seconds
# 查看详细信息(含设备路径)
efibootmgr -v
# 创建新的启动项
# 格式:efibootmgr -c -d /dev/sda -p 1 -l "EFIubuntugrubx64.efi" -L "Ubuntu"
# -c:创建新条目
# -d:磁盘设备
# -p:分区号(1=ESP)
# -l:EFI 文件路径(相对于 ESP 根目录)
# -L:启动项名称(在启动菜单里显示的名字)
# 示例:添加 Arch Linux 启动项
sudo efibootmgr -c -d /dev/sda -p 1 -l "EFIarchgrubx64.efi" -L "Arch Linux"
# 删除启动项(按 Boot 编号)
sudo efibootmgr -B -b 0001
# -B:删除
# -b 0001:删除 Boot0001
# 修改启动顺序
sudo efibootmgr -o 0000,0001
# 现在 Windows Boot Manager 排第一
# 修改超时时间
sudo efibootmgr -t 5
# 下次启动时,等待 5 秒再自动选择
# 查看 NVRAM 里某项的详细信息
efibootmgr -v -B -b 0000bcdedit:Windows 下操作 NVRAM
# 查看所有启动项(包括固件层面的)
bcdedit /enum firmware
# 查看详细(和 efibootmgr -v 类似)
bcdedit /enum all
# 设置默认启动项
bcdedit /default {identifier}
# 添加 UEFI 启动项(Windows 安装盘里用)
bcdedit /set "{bootmgr}" "path EFIMicrosoftBootbootmgfw.efi"
# 删除启动项
bcdedit /delete {identifier}
# 导出 NVRAM 启动项(备份用)
bcdedit /enum all > bcd-backup.txtSecure Boot:签名验证的完整链
什么是 Secure Boot
Secure Boot 是 UEFI 规范里的可选安全特性,它要求所有启动代码(bootloader、驱动、内核)必须被可信的公钥签名,才能执行。这防止了”插入恶意 USB,重写 bootloader”的攻击。
Secure Boot 的信任链:
UEFI 固件(内置微软等 PK)
↓
shimx64.efi(微软签名,发行版内置)
↓(验证)
grubx64.efi(发行版签名,shim 验证)
↓(验证)
vmlinuz(内核镜像,发行版签名)
↓(验证)
initramfs(initrd 镜像)签名数据库
UEFI 固件的 Flash 里存储了签名数据库:
签名数据库(签名在 Flash NVRAM 里):
├── PK(Platform Key):最高权威,生产时写入,厂商持有
├── KEK(Key Exchange Keys):允许更新签名数据库的密钥(微软是主要 KEK)
├── db(允许的签名):允许执行的 .efi 文件签名列表
└── dbx(禁止的签名):已撤销的签名(吊销列表)微软的 KEK 是全球大多数 UEFI 固件里预置的,所以微软签名的 .efi(shimx64.efi)可以在大多数机器上启动。
Windows 的签名链
Windows 10/11 的启动链在 UEFI 下是:
UEFI → bootmgfw.efi(微软签名) → winload.efi(微软签名) → ntoskrnl.exe(微软签名)所有 .efi 和 .sys 文件都必须有微软签名才能在 Secure Boot 开启时运行。这就是为什么”禁用了驱动签名强制”的测试模式(TestSigning)在 Secure Boot 关闭时才能用。
检查 Secure Boot 状态
Linux:
mokutil --sb-state
# SecureBoot disabled → 未启用
# SecureBoot enabled → 启用
# 查看 db 里的签名
mokutil --db /EFI/Microsoft/Boot/db.authWindows:
# 系统信息里查看
msinfo32 → Secure Boot State
# 或者
powerShell
Confirm-SecureBootUEFI
# True = 启用,False = 禁用shim:绕过签名限制的垫片
shim(shimx64.efi)是 Linux 发行版提供的”签名垫片”,它有微软签名(能在 Secure Boot 开启时运行),内部包含了发行版自己的公钥。
shim 工作原理:
1. UEFI 固件验证 shimx64.efi 的签名(微软签)→ 通过
2. shim 用内置的发行版公钥验证 grubx64.efi → 通过
3. grubx64.efi 加载发行版签名的 vmlinuz → 通过
结果:即使是未经微软签名的内核,只要有发行版签名,通过 shim 就能在 Secure Boot 下启动。禁用 Secure Boot(开发用)
开发环境需要加载未签名的内核或 bootloader 时,禁用 Secure Boot:
进入 UEFI 设置的方法(不同机器不同):
- 开机按 Delete/F2/F12 → UEFI Setup → Boot → Secure Boot → Disabled
- 或者:设置 → 更新和安全 → 恢复 → 高级启动 → 固件设置
注意:禁用 Secure Boot 后,Windows 可能报告 "Secure Boot 不正确配置"
解决:进入 Windows → bcdedit /set {current} bootstatuspolicy IgnoreSecureBootFailuresBCD 在 UEFI 模式下的新内容
和 MBR 模式相比,GPT+UEFI 模式的 BCD 内容增加了一些 UEFI 特定的字段:
bcdedit /store ?GLOBALROOTdeviceharddisk0partition1BootBCD /enum all
# UEFI 模式下 BCD 的新字段:
{bootmgr}
description = Windows Boot Manager
device = partition=DeviceHarddiskVolume1 ← GPT 分区路径(不再是 C:)
path = EFIMicrosoftBootbootmgfw.efi ← .efi 文件路径
locale = zh-CN
{default}
description = Windows 10
device = partition=C:
osdevice = partition=C:
path = Windowssystem32winload.efi ← 注意:.efi 不是 .exe
systemroot = Windows
# UEFI 特有的 recovery 相关字段:
{default}
recoveryenabled = Yes
recoverysequence = {某些 GUID}BCD 里用 GPT 分区 GUID 而不是驱动器字母来标识分区:
MBR 模式设备路径:
device = partition=C:
UEFI 模式设备路径:
device = partition=DeviceHarddiskVolume2
# 或者完整 GPT 路径:
device = partition=HD(PartitionID,GPT,DeviceHarddiskVolume2)bcdboot:从 ESP 重新创建 BCD 和启动文件
bcdboot.exe 是 Windows 里重建整个 UEFI 启动环境的工具,比 bcdedit 更”一键化”:
# 重建整个 ESP 启动环境(在 WinRE 或管理员 CMD 里)
bcdboot C:Windows /s C: /f UEFI
# 参数说明:
# C:Windows → 源 Windows 目录
# /s C: → 目标 ESP 分区(这里 C: 是 ESP 的盘符,需要先 assign)
# /f UEFI → 生成 UEFI 模式启动文件(不是 BIOS/MBR)
# 从 C: 重新初始化 ESP(修复损坏的 bootmgfw.efi)
# 假设 ESP 是 D:
bcdboot C:Windows /s D: /f UEFI
# 这会把 bootmgfw.efi、BCD、fonts、Resources 全部从 C:WindowsBoot 复制到 D:
# 指定固件架构(x64 是最常见的)
bcdboot C:Windows /s D: /f UEFI /arch x64
# 完整修复流程(UEFI 模式下 BOOTMGR 损坏)
# 1. 在 WinRE 里确认 ESP 的盘符
diskpart
list volume
select volume X # FAT32 那个,100MB-300MB
assign letter=Z # 临时给 Z:
exit
# 2. 重建启动文件
bcdboot C:Windows /s Z: /f UEFI
# 3. 如果有 Secure Boot 问题,还要重建签名数据
# 在 UEFI 设置里 Reset Secure Boot keys(危险,会清空 PK)工具:Linux 下操作 ESP 和 BCD
挂载 ESP(读写模式)
# 找到 ESP(GPT 里类型为 ESP / EFI System Partition)
sudo fdisk -l /dev/sda | grep -i "esp|efi|boot"
# 输出示例:
# /dev/sda1 EFI System Partition FAT32 260MB /boot/efi
# 挂载 ESP(UEFI 标准挂载点)
sudo mount /dev/sda1 /boot/efi
# 查看 ESP 内容
ls -la /boot/efi/EFI/
# 输出:Boot/ Microsoft/ ubuntu/ ...
# 卸载
sudo umount /boot/efi挂载 ESP(只读,防止误改)
sudo mount -t fat -o ro,uid=1000,gid=1000 /dev/sda1 /mnt/esp用 hexdump / xxd 查看 GPT 分区表
# 查看 GPT Header(LBA 1)
sudo dd if=/dev/sda bs=512 count=1 skip=1 2>/dev/null | hexdump -C | head -20
# GPT Header 特征:偏移 0x38 处有 "EFI PART"(45 46 49 20 50 41 52 54)
# 检查方法:
sudo dd if=/dev/sda bs=1 skip=8 count=8 2>/dev/null | xxd
# 应该输出:45 46 49 20 50 41 52 54
# 查看 GPT 分区表(LBA 2-33,16KB = 32 扇区)
sudo dd if=/dev/sda bs=512 count=32 skip=2 2>/dev/null | hexdump -C | head -40
# 每个分区条目 128 字节,包含:
# 偏移 0x00:类型 GUID(16 字节)
# 偏移 0x10:分区 GUID(16 字节)
# 偏移 0x20:起始 LBA(8 字节)
# 偏移 0x28:结束 LBA(8 字节)
# 偏移 0x30:属性标志(8 字节)
# 偏移 0x38:分区名称(72 字节,UTF-16)用 sgdisk 操作 GPT 分区
# 查看所有分区(详细)
sudo sgdisk -p /dev/sda
# 查看分区详细信息(按编号)
sudo sgdisk -i 1 /dev/sda
# 输出示例:
# Partition 1 info:
# Type: EFI System Partition (C12A7328-F81F-11D2-BA4B-00A0C93EC93B)
# Partition GUID: A2B3C4D5-E6F7-8A9B-0C1D-2E3F4A5B6C7D
# First LBA: 2048
# Last LBA: 499711
# Attribute flags: 0x0000000000000000
# Name: 'EFI System Partition'efivar:操作 UEFI 变量(NVRAM 里的东西)
# 列出所有 UEFI 变量(NVRAM)
sudo efivar -l
# 查看特定变量(BootOrder)
sudo efivar -n 8be4df61-93ca-11d2-aa0d-00e098032b8c-BootOrder
# BootOrder GUID: 8be4df61-93ca-11d2-aa0d-00e098032b8c
# 格式:{GUID}-{VariableName}
# 格式化显示(Readable)
sudo efivar -p 8be4df61-93ca-11d2-aa0d-00e098032b8c-BootOrder
# 导出启动项列表(和 efibootmgr 等价)
sudo cat /sys/firmware/efi/efivars/BootOrder-* | xxd实战修复:UEFI 模式下 Windows 启动损坏
场景 1:bootmgfw.efi 损坏导致黑屏
症状:开机后屏幕黑,无任何输出,UEFI 设置可以进入。
# 用 Windows 安装U盘启动 → 修复计算机 → 命令提示符
# 1. 确认 ESP 盘符
diskpart
list volume
# 找到 FAT32 的卷,假设是 D:
# 2. 重建 bootmgfw.efi 和 BCD
bcdboot C:Windows /s D: /f UEFI
# 3. 验证文件是否创建
dir D:EFIMicrosoftBoot
# 应该能看到 bootmgfw.efi, BCD, fonts/ 等
# 4. 如果 Secure Boot 有问题,还要注册启动项
bcdedit /set {bootmgr} path EFIMicrosoftBootbootmgfw.efi场景 2:NVRAM 启动项全部消失
症状:UEFI 设置里启动项为空,BIOS 提示 “No bootable device found”。
# 在 Linux 里重建 NVRAM 启动项
# 注意:这需要知道 .efi 文件的正确路径
# 假设 /dev/sda1 是 ESP
# 1. 挂载 ESP
sudo mount /dev/sda1 /boot/efi
# 2. 手动添加 Windows 启动项
sudo efibootmgr -c -d /dev/sda -p 1 -l "EFIMicrosoftBootbootmgfw.efi" -L "Windows Boot Manager"
# 3. 如果有多个 Windows 安装(双系统),每个都要单独添加
# 查看有哪些 .efi
ls /boot/efi/EFI/Microsoft/Boot/
# bootmgfw.efi 是默认的,还有其他语言的变体
# 4. 验证
efibootmgr -v场景 3:重装 Windows 后 GRUB 消失
症状:UEFI 模式下重装 Windows,GRUB 被覆盖,Linux 无法启动。
# Linux Live USB 启动
# 1. 挂载 Linux 和 ESP
sudo mount /dev/sda2 /mnt # Linux root(假设 /dev/sda2)
sudo mount /dev/sda1 /mnt/boot/efi # ESP(假设 /dev/sda1)
# 2. chroot
sudo mount --bind /dev /mnt/dev
sudo chroot /mnt
# 3. 重新安装 GRUB 到 ESP(不是 MBR!)
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=ubuntu
# 注意:这里没有 /dev/sda,因为是 UEFI 模式,不是 MBR 模式
# 4. 重建 grub.cfg
update-grub
# 应该检测到 Windows(bootmgfw.efi)
# 5. 退出重启
exit
sudo reboot场景 4:Secure Boot 开启但 GRUB 无法启动
症状:启用 Secure Boot 后,GRUB 菜单不出现,直接进入 Windows。
# 1. 检查 Secure Boot 状态
mokutil --sb-state
# 如果是 enabled,GRUB 需要通过 shim 加载
# 检查 shim 是否存在
ls /boot/efi/EFI/ubuntu/shimx64.efi
# 2. 重新安装 shim + GRUB
sudo grub-install --target=x86_64-efi
--efi-directory=/boot/efi
--bootloader-id=ubuntu
--shim /boot/efi/EFI/ubuntu/shimx64.efi
--install-modules="normal trust boot linux reboot"
# 3. 手动注册 shim 到 NVRAM
sudo efibootmgr -c -d /dev/sda -p 1
-l "EFIubuntushimx64.efi"
-L "ubuntu (Secure Boot)"WinRE 在 UEFI 模式下的管理
UEFI 模式下,WinRE 的配置方式略有不同:
# 查看 WinRE 状态
reagentc /info
# 输出示例:
# Windows Recovery Environment (Windows RE) 状态:
# Windows RE 位置: ?GLOBALROOTdeviceharddisk0partition1RecoveryWindowsRE
# WinRE 启用: true
# WinRE 镜像已启用: false
# 启用 WinRE(指向 WIM 文件)
reagentc /setreimage /path ?GLOBALROOTdeviceharddisk0partition1RecoveryWindowsRE /guid {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
# 启用 WinRE(简单方式:从 WIM 文件安装)
reagentc /setosimage /path C:WindowsSystem32Recoverywinre.wim /index 1
# 禁用 WinRE
reagentc /disableUEFI 模式下,WinRE 镜像默认存在 RecoveryWindowsRE(在 Windows 系统分区里),不是 ESP。
踩坑与注意事项
坑 1:UEFI 模式下 ESP 被删导致”无启动设备”
现象:磁盘管理里误删了 ESP 分区(通常最小、最前面的 FAT32 分区),开机报 “Reboot and Select proper Boot device”。
原因:ESP 包含了 bootmgfw.efi 和 BCD,没有它 UEFI 固件找不到任何可启动的 .efi 文件。
解决:用 Windows 安装U盘 → 修复计算机 → 命令提示符:
diskpart
list volume
# 找到 C:(Windows 系统分区)
# 从未分配空间重建 ESP
create partition primary size=260
format fs=fat quick
assign letter=Z
# 用 bcdboot 重建
bcdboot C:Windows /s Z: /f UEFI
# 再注册 NVRAM 启动项
efibootmgr -c -d /dev/sda -p 1 -l "EFIMicrosoftBootbootmgfw.efi" -L "Windows"坑 2:重装 Windows 后 BootOrder 被 Windows 覆盖
现象:UEFI 模式下重装 Windows,GRUB 的启动项从 NVRAM 消失,直接进 Windows。
原因:Windows 安装程序会重置 NVRAM BootOrder,把 Windows Boot Manager 放在最前面。
解决:进入 Linux Live USB,手动用 efibootmgr -o 调整顺序:
# 查看当前启动顺序
efibootmgr
# 把 GRUB 调回第一位
sudo efibootmgr -o 0001,0000
# 0001 = ubuntu,0000 = Windows Boot Manager坑 3:bcdedit 在普通 CMD 里权限不足
现象:普通用户运行 bcdedit 报错”拒绝访问”。
原因:BCD 是受保护的系统配置,需要管理员权限。
解决:用管理员权限打开 CMD:
# 方法 1:搜索 cmd → 右键 → 以管理员身份运行
# 方法 2:Win+X → 终端(管理员)
# 方法 3:在 WinRE 环境里自动是管理员权限坑 4:UEFI 设置里 Secure Boot 和 CSM 混用导致启动混乱
现象:开启了 Secure Boot 但禁用了 CSM(Compatibility Support Module),某些启动盘找不到(只支持 Legacy USB)。
解决:在 UEFI 设置里明确选择”UEFI Only”,不要同时开 Secure Boot 和 Legacy Support。
正确设置:
- Secure Boot: Enabled(生产环境)
- Boot Mode: UEFI Only
- CSM: Disabled
- USB Boot: Enabled(允许 USB 设备以 UEFI 方式启动)坑 5:bcdboot 用错盘符导致”Windows 没有正确安装”
现象:执行 bcdboot C:Windows /s D: /f UEFI 后,启动报错”你的电脑尚未正确设置”。
原因:D: 盘符不是 ESP,而是另一个 FAT32 分区,或者 ESP 和 Windows 不在同一个磁盘上。
解决:用 diskpart 确认 ESP 和 Windows 分区的实际盘符,再重建:
diskpart
list volume
# 卷 0:FAT32 260MB D: ← ESP
# 卷 1:NTFS 233GB C: ← Windows 系统分区
# 确认后再执行 bcdboot
bcdboot C:Windows /s D: /f UEFI写在最后
Windows GPT+UEFI 启动链路,相比 MBR+BIOS,是一次彻底的架构升级:
POST → UEFI 固件初始化 → NVRAM BootOrder → bootmgfw.efi(64 位 PE)
→ ESP/Boot/BCD → winload.efi → ntoskrnl.exe关键变化:
- System Reserved → ESP:启动文件从隐藏分区移到了专用 FAT32 分区
- 活动分区标记 → NVRAM:启动顺序不再依赖磁盘分区表,而存在固件 Flash 里
- 0x55AA → CRC32:启动标志从简单的 2 字节变成了 GPT 的校验机制
- BOOTMGR → bootmgfw.efi:从 16 位实模式变成了 64 位 UEFI 应用
- 无 Secure Boot → Secure Boot:签名链验证从无到有(微软签名 + 发行版签名)
修复工具的核心也变了:
bootrec几乎不用了(MBR 代码不再使用)bcdedit+bcdboot是主要工具efibootmgr(Linux)和bcdedit(Windows)是管理 NVRAM 启动项的两把钥匙
wandos 目前没有 UEFI 启动支持。如果要做,需要实现 UEFI 应用入口点(PE/COFF 格式),支持 GPT 分区解析(读取 LBA 2-33 的分区表),实现 FAT32 文件系统读写,然后通过 NVRAM 注册自己的 .efi 文件。这比 MBR+BIOS 复杂很多,但也是工业级 OS 的必经之路。
下篇预告(366):候选方向——ext2 文件系统:inode、块组与目录项,或者第一个用户态进程:从内核启动到 /sbin/init 的完整链路。你选哪个?
仓库:https://github.com/golang12306/os-kernel-from-scratch
相关阅读
- UEFI Spec 2.8+:
https://uefi.org/specifications(GPT、Secure Boot、NVRAM 规范) - Microsoft Docs: “BCD Store Format” — BCD 注册表 hive 的二进制结构
- Microsoft Docs: “Secure Boot” — 签名数据库和签名链
- Linux Kernel:
arch/x86/boot/header.S(Linux 的 UEFI 入口点) - efibootmgr 源码:
https://github.com/rhboot/efibootmgr - https://github.com/zhangfuwen/wandos — Linux 内核教程
动手环节
想深入理解本文内容?动手实践是最好的方式:
今天的目标:在你的 UEFI 机器上操作 ESP、NVRAM 和 Secure Boot。
-
查看你的 ESP 分区和启动项:
# 查看所有启动项(NVRAM) efibootmgr -v # 查看分区表 sudo fdisk -l /dev/sda | grep -E "GPT|EFI" # 挂载 ESP(只读) sudo mount -t fat /dev/sda1 /mnt/esp -o ro ls -la /mnt/esp/EFI/ -
备份 ESP 内容:
mkdir -p ~/esp-backup sudo mount -t fat /dev/sda1 /mnt/esp -o ro rsync -av /mnt/esp/ ~/esp-backup/ ls -la ~/esp-backup/ -
在虚拟机里模拟 UEFI 启动修复:
# 创建 UEFI 模式的虚拟机(QEMU) qemu-img create -f qcow2 win10-uefi.qcow2 50G # 安装时确保选择 UEFI(不是 BIOS/MBR) # 安装完成后,模拟 ESP 损坏,练习用 bcdboot 重建 -
操作 NVRAM 启动项:
# 查看当前启动顺序 efibootmgr # 调整顺序(把 Windows 调成默认) sudo efibootmgr -o 0000,0001 # 假设 0000=Windows, 0001=ubuntu # 删除 GRUB 启动项(模拟 Windows 重装后 GRUB 消失) sudo efibootmgr -B -b 0001 # 重新添加(GRUB 被覆盖后修复) sudo efibootmgr -c -d /dev/sda -p 1 -l "EFIubuntugrubx64.efi" -L "ubuntu" -
检查 Secure Boot 状态和签名:
mokutil --sb-state # 如果是 enabled,查看签名数据库 mokutil --list-enrolled
提示:操作 NVRAM(efibootmgr)是安全的——它只是修改 Flash 芯片里的数据,不会破坏磁盘内容。但误删重要的启动项(如 Windows Boot Manager)会导致该 OS 无法启动,需要重新注册。
评论