从零写OS内核 | Windows MBR+BIOS 启动:BOOTMGR 之前发生了什么,以及怎么修复它

你有没有注意过一个现象:组装一台电脑,装上 Windows 10,系统保留分区(System Reserved)占了 100MB,C 盘占了剩下的一切。这个 100MB 的分区,平时在资源管理器里看不到,只有插上 Windows 安装U盘、进入”修复计算机”时,才隐约感觉到它的存在——里面有几个文件夹,叫 BootRecovery,还有一些 .mui 文件。

但如果你仔细看 Disk Management,会发现 System Reserved 的文件系统显示为”FAT32″,而不是 NTFS——这是 Windows 故意为之的,因为 BIOS 启动模式下,BOOTMGR 只能从 FAT 文件系统读取数据。

这一章,我们来把 Windows MBR+BIOS 启动链路彻底拆解——从按下电源键的那一刻,到 Windows 登录界面出现,中间每一个文件、每一步跳转、每一个工具怎么用,全部讲清楚。


BIOS + MBR 模式下 Windows 的启动链路

完整阶段图

Bash
① 电源按下
  → CPU CS:IP = 0xFFFF:0x0000
  → BIOS ROM 执行(0xFFFF0)

② POST(Power-On Self Test)
  → CPU 自检、内存检测、显卡初始化
  → 读取 CMOS 中的启动顺序

③ BIOS 按启动顺序查找"可启动设备"
  → 尝试第一块磁盘的 LBA 0(MBR)

④ MBR 的 512 字节
  → 前 446 字节:BOOTMGR 代码(或 GRUB Stage 1)
  → 中间 64 字节:分区表(4 条 × 16 字节)
  → 最后 2 字节:0x55AA(启动标志)

⑤ BIOS 把 CS:IP 跳转到 0x7C00(MBR 被加载的位置)
  → MBR 里的 BOOTMGR 开始执行

⑥ BOOTMGR(BootBOOTMGR,NTFS 压缩)
  → 读取 BootBCD(BCD 注册表配置)
  → 显示启动菜单(如果有多个启动项)
  → 找到 {default} 启动项的 osdevice

⑦ 加载 winload.exe
  → 路径:C:WindowsSystem32winload.exe
  → 验证启动签名(Secure Boot 相关,在 BIOS 模式下会跳过)
  → 读取 SYSTEM 注册表(获取驱动列表)

⑧ winload.exe 加载 ntoskrnl.exe + 驱动
  → 切换到更高特权级
  → 启动 Windows 内核

整个链路里,唯一放在 MBR 里的 Windows 代码是 BOOTMGR 的一部分,其余所有东西(C 盘里的 winload.exentoskrnl.exe、BCD)都在分区里。MBR 的 446 字节 bootloader 代码只是”第二阶段加载器”,真正的大头在 System Reserved 分区。


System Reserved 分区:100MB 里到底装了什么

正常情况下的分区结构

System Reserved 分区(也叫”系统分区”)在 MBR 模式下是 Windows 强制创建的。它必须是 FAT32 文件系统(不是 NTFS),因为 BIOS 模式下的 BOOTMGR 只认 FAT。

Bash
查看 Windows 系统的系统保留分区(在 Windows 里):
diskpart
list volume
# Volume 1   System Reserved   FAT32   100 MB   启动
# Volume 2   C:               NTFS    233 GB   活动

Bash
System Reserved 分区(FAT32)内容结构:
D:(假设 System Reserved 是 D:)

├── Boot
│   ├── BCD                     ← 启动配置数据(注册表格式)
│   ├── BCD.LOG                ← BCD 事务日志
│   ├── BCD.LOG1               ← 上一个版本的日志
│   ├── BCD.LOG2               ← 更早的日志
│   ├── BOOTMGR                ← Windows Boot Manager(NTFS 压缩文件)
│   ├── bootmgfw.efi           ← UEFI 版本备份(GPT 模式用,MBR 里实际不读)
│   ├── fonts
│   │   ├── boot.ttf           ← 启动字体
│   │   └── segui_boot.ttf     ← 备用字体
│   ├── Resources
│   │   ├── bootres.dll        ← 启动资源(对话框、图标等)
│   │   └── ...
│   └── zh-CN                 ← 启动菜单中文本地化资源
│       ├── bootmgr.exe.mui
│       └── ...
├── System Volume Information  ← 锁定的元数据目录
│   └── MountPointsRemote
└── (隐藏,无盘符,Windows 不分配)

注意:如果你的 Windows 不是装在 MBR 盘上(而是 UEFI + GPT),System Reserved 分区不存在,取而代之的是 ESP(EFI System Partition),路径和内容相同,但文件系统是 FAT32,位置在 ESP 而非 System Reserved。

BOOTMGR 是什么

BOOTMGR(Boot Manager)是 Windows 的核心启动文件。它不是一个普通的 .exe,是一个压缩的 Win32 可执行程序(NTFS 压缩属性 C 标志置位)。

Bash
# 在 Linux 里查看 BOOTMGR 的属性(需要挂载 System Reserved)
# 假设 /dev/sda1 是 System Reserved
sudo mount -t fat /dev/sda1 /mnt/sysres
ls -la /mnt/sysres/Boot/
# -rwxr-xr-x 1 root root  412KB  BOOTMGR    ← 注意:NTFS 压缩状态在这里看不到(FAT32 无压缩)

在 FAT32 的 System Reserved 里,BOOTMGR 不是压缩的(FAT32 不支持 NTFS 压缩)。但从 NTFS 的 C 盘里读取时,它会被标记为压缩——这是 NTFS 的稀疏文件功能。

BOOTMGR 的职责:

  1. 读取 BCD(不管 BCD 在哪里)
  2. 显示”Windows 启动管理器”菜单(超时前默认加载)
  3. 根据 BCD 里的 device / osdevice 找到 Windows 系统分区
  4. 加载 winload.exe 并跳转

BCD:启动配置数据

BCD(Boot Configuration Data)是一个注册表配置单元(Hive),和普通注册表 SYSTEMSOFTWARE 一样是二进制格式,存储在 BootBCD

Cmd
# 在 Windows 里查看 BCD 内容(需要管理员权限)
bcdedit /store C:BootBCD /enum all

BCD 里存储的内容(简化版):

Bash
{bootmgr}
  description     = Windows Boot Manager
  device          = partition=C:    ← BCD 存储在 C: 盘的 BootBCD(MBR 模式)
  locale          = zh-CN          ← 启动菜单语言

{default}
  description     = Windows 10
  device          = partition=C:    ← Windows 在 C: 分区
  osdevice        = partition=C:
  path            = Windowssystem32winload.exe
  systemroot      = Windows
  tools           = partition=D:    ← 指向 System Reserved(D:)

{memdiag}
  description     = Windows Memory Diagnostic
  path            = Windowssystem32memdiag.exe

{noide}
  description     = 禁用 IDE 控制器(故障排除用)

winload.exe:真正的内核加载器

winload.exe(在 C:WindowsSystem32)才是 Windows 的第三阶段加载器——BOOTMGR 找到它并跳转执行,它负责:

  1. 读取注册表 HKLMSYSTEMCurrentControlSetServices*(驱动列表)
  2. 加载内核镜像 ntoskrnl.exe 和硬件驱动(*.sys 文件)
  3. 验证启动签名(在 UEFI 下强制验证,BIOS 下部分跳过)
  4. 初始化内存管理、调度器等子系统
  5. 把控制权交给 ntoskrnl.exe(真正的 Windows 内核)

Bash
winload.exe 的启动过程:
BOOTMGR → 读取 {default} 的 osdevice → 定位 C: 分区
→ 加载 WindowsSystem32winload.exe
→ 读取注册表 HKLMSYSTEMSelectCurrent(确定 ControlSet 编号)
→ 读取 HKLMSYSTEMCurrentControlSetServices*
→ 加载内核 + 驱动
→ ntoskrnl.exe 开始执行
→ Windows 登录界面出现

工具一:bcdedit —— BCD 的”注册表编辑器”

基础用法

Cmd
# 查看当前系统 BCD(默认 store)
bcdedit

# 查看详细参数(所有启动项)
bcdedit /enum all

# 查看特定启动项
bcdedit /enum {default}

# 以特定 store 查看(不用管理员也能读)
bcdedit /store C:BootBCD /enum all

bcdedit 常用操作

Cmd
# 修改启动项名称
bcdedit /set {default} description "Windows 10 Pro 22H2"

# 设置默认启动项(按 identifier 选择)
bcdedit /default {current}    ← 当前启动项设为默认

# 删除启动项(先查看 identifier)
bcdedit /delete {identifier}

# 设置启动参数(禁用 DEP、启用测试模式等)
bcdedit /set {default} nx AlwaysOff           ← 关闭 DEP
bcdedit /set {default} testsigning on        ← 允许测试签名驱动

# 复制启动项(创建新的启动配置)
bcdedit /copy {default} /d "Windows 10 Safe Mode"
# 输出:已复制该条目 {identifier},用以下命令修改其设置:
bcdedit /set {identifier} nx AlwaysOff
bcdedit /set {identifier} safeboot minimal

# 开启 F8 高级启动菜单(MBR 模式默认开启)
bcdedit /set {default} bootmenupolicy Legacy
# 关闭(UEFI 默认):
bcdedit /set {default} bootmenupolicy Standard

bcdedit 和 GRUB 对比

Bash
功能                 bcdedit                  grub-mkconfig / grub.cfg
─────────────────────────────────────────────────────────────
查看配置             bcdedit /enum            cat /boot/grub/grub.cfg
修改超时             bcdedit /set ... timeout  GRUB_TIMEOUT=5 in /etc/default/grub
添加参数             bcdedit /set ... boot执行 bcdedit /set  winload 参数  linux ... ro quiet
删除启动项           bcdedit /delete {id}      删除 grub.cfg 里的 menuentry

工具二:bootrec —— MBR 模式的修复神器

bootrec.exe 是 Windows 安装盘/WinRE 环境里才能运行的修复工具,不是普通 Windows 里能用的。它的作用是重建 MBR 和启动扇区

Cmd
# 进入 WinRE 的方法:
# 1. 设置 → 更新和安全 → 恢复 → 高级启动 → 立即重启
# 2. 或者强制关机 3 次(触发自动修复)
# 3. 或者用 Windows 安装U盘启动,选"修复计算机"

# bootrec 的四个子命令:
bootrec /fixmbr      ← 写入标准 MBR(Windows 自己的,不破坏分区)
bootrec /fixboot     ← 写入新的 BOOTMGR 启动扇区
bootrec /scanbus     ← 扫描所有可启动的 Windows 安装
bootrec /rebuildbcd  ← 重建整个 BCD(从找到的 Windows 安装恢复)

# 完整修复顺序(推荐)
bootrec /fixmbr
bootrec /fixboot
bootrec /rebuildbcd

bootrec /fixmbr 原理

/fixmbr 做的事情非常精准:它读取分区表(不改动),然后只在 MBR 的 446 字节代码区写入 Windows 标准 MBR 代码(不是 GRUB,不是第三方 bootloader)。

Bash
# Linux 下看 MBR 内容(SYSTEM Reserved 在 /dev/sda1,C: 在 /dev/sda2)
# Windows 标准 MBR 的特征:开头有 0x33 字节 xor 跳转模式

sudo dd if=/dev/sda bs=1 count=446 2>/dev/null | hexdump -C | head -5

# Windows MBR boot code 的特征字节(用于鉴别):
# 常见开头:eb 7c(跳转),33 c0(xor ax,ax),8e d8(mov ds,ax)
# GRUB Stage 1 的特征开头:eb 48(跳转),90 nop

bootrec /fixboot 的原理

/fixboot 写入的是活动分区的引导扇区(BOOT sector),不是 MBR。它检查活动分区的文件系统类型(FAT32/NTFS),然后写入对应的引导扇区代码(包括跳转指令 + BPB 参数块 + 引导签名)。

Cmd
# 如果 /fixboot 失败,可能是因为活动分区不是 FAT32
# 在 diskpart 里检查:
diskpart
list volume
# "System Reserved" 的卷通常是 FAT32,活动标志(boot)是它
# 如果活动分区被误标为 C:,bootrec 可能写到错误的分区

工具三:reagentc —— Windows RE 的入口

reagentc 是 Windows RE(Recovery Environment)的配置工具,用来管理 WinRE 镜像的位置和启用状态。

Cmd
# 查看 WinRE 状态
reagentc /info

# 输出示例:
# Windows Recovery Environment (Windows RE) 状态:
#   Windows RE 位置: ?GLOBALROOTdeviceharddisk0partition1RecoveryWindowsRE
#   WinRE 已启用: true

# 禁用 WinRE(临时关闭)
reagentc /disable

# 启用 WinRE(指向正确的 WIM 镜像)
reagentc /enable

# 设置 WinRE 镜像位置(如果镜像被移走了)
reagentc /setreimage /path D:RecoveryWindowsRE /device partition=D:

# 从 WIM 文件安装 WinRE(高级)
reagentc /setosimage /path C:WindowsSystem32Recoverywinre.wim /index 1

WinRE 的工作原理:

  • 镜像文件:C:WindowsSystem32Recoverywinre.wim(约 200-300MB)
  • reagentc /enable 把 winre.wim 挂载到 System Reserved 的 RecoveryWindowsRE 目录
  • 启动时按 F8(或强制关机 3 次)触发 WinRE

Bash
WinRE 启动条件(MBR 模式):
  1. System Reserved 分区存在
  2. RecoveryWindowsREwinre.wim 存在且完整
  3. BCD 里的 {memdiag} 条目指向 winre.wim
  4. BOOTMGR 检测到"上次启动失败"标志(HKLMSYSTEMLastShutdownGood=0

工具四:diskpart —— 分区和启动标记的管理

diskpart 是 Windows 的磁盘管理底层工具,能做 GUI 工具做不了的事,比如设置活动分区(启动标记)。

Cmd
# 启动 diskpart
diskpart

# 查看所有磁盘
list disk

# 查看所有卷
list volume

# 选择磁盘(看哪个磁盘的分区)
select disk 0

# 查看所选磁盘的分区
list partition

# 选择分区
select partition 1

# 查看分区详情(起始偏移、类型、大小)
detail partition

# 设置活动分区(将当前分区标记为可启动)
active

# 取消活动标记(慎用,取消后该盘无法启动)
inactive

活动分区(active)和启动标志的区别

MBR 启动标志 活动分区
位置 MBR 分区表条目(0x80) MBR 分区表条目(0x80)
作用 BIOS 据此判断”这个盘的第一扇区可以启动” BOOTMGR 据此判断”这个分区包含 BOOTMGR 和 BCD”
BIOS 依赖 读取 MBR 时看 分区表必须有 0x80 条目才能启动

Bash
MBR 分区表 4 条条目,每条的第二个字节(偏移 0x01):
  0x80 = 活动分区(可启动)
  0x00 = 非活动

多个活动分区会导致"NO OS"错误(BIOS 只认第一个 0x80)

工具五:bootsect —— 写入启动扇区的底层工具

bootsect.exe 是 Windows SDK 里的工具,在 WinRE 环境或 Windows 安装盘的命令行里可用。它和 bootrec /fixmbr 的区别是:bootrec 写入的是 Windows 自己的 MBR 代码,而 bootsect 可以指定目标是 MBR 还是特定分区。

Cmd
# 写 BOOTMGR MBR(恢复 Windows MBR,不破坏分区表)
bootsect /nt60 C: /mbr

# /nt60 = Windows Vista/7/10/11 启动环境
# C: = 系统分区(C 盘,即活动分区)
# /mbr = 同时更新 MBR 代码(446 字节)

# 完整恢复 Windows MBR(在 WinRE 命令行里)
bootsect /nt60 SYS
# SYS = System Reserved 分区(不是 C:)

# 仅更新分区的引导扇区(不碰 MBR)
bootsect /nt60 D:
# D: = System Reserved(在 BIOS MBR 模式下 D: 通常是 System Reserved)

bootsect vs bootrec

Bash
bootrec /fixmbr   → 只写 MBR 代码(446 字节),分区表不变
bootsect /nt60 X: /mbr → 写 MBR 代码 + 分区引导扇区(更新 X: 的 BOOT sector)

工具六:Linux 下读写 MBR 和 BCD

如果你用 Linux Live USB 而非 Windows 安装盘,也有工具可以操作 Windows 启动数据:

dd:读写 MBR/分区表

Bash
# 读取 MBR(前 512 字节)
sudo dd if=/dev/sda of=/tmp/mbr-backup.img bs=512 count=1

# 查看 MBR 的分区表部分(446-512 字节)
sudo dd if=/dev/sda bs=1 skip=446 count=64 2>/dev/null | hexdump -C

# 备份 System Reserved 的引导区(前 63 个扇区,通常是 boot sector)
sudo dd if=/dev/sda1 of=/tmp/sysres-boot-backup.img bs=512 count=63

# 恢复 MBR(危险!先确认这是正确的镜像)
sudo dd if=/tmp/mbr-backup.img of=/dev/sda bs=512 count=1

hexdump / xxd:直接看二进制内容

Bash
# 用 hexdump 看 MBR 内容
sudo dd if=/dev/sda bs=1 count=512 2>/dev/null | hexdump -C

# 看分区表(从 0x01BE 开始,64 字节)
sudo dd if=/dev/sda bs=1 skip=446 count=64 2>/dev/null | hexdump -C

# 解读分区表字节(4 条 × 16 字节):
# 字节 0:0x80=活动,0x00=非活动
# 字节 1-3:起始 CHS(已过时)
# 字节 4:分区类型(0x07=NTFS,0x17=Hidden NTFS,0x0C=FAT32)
# 字节 5-7:结束 CHS
# 字节 8-11:起始扇区(LBA 32位)
# 字节 12-15:分区大小(扇区数)

mount:挂载 System Reserved(只读)

Bash
# 找到 System Reserved 分区(通常在 C: 前面,大小约 100MB,FAT32)
sudo fdisk -l /dev/sda | grep -E "System|FAT|100M| EFI"

# 挂载(只读,防止误改)
sudo mount -t fat /dev/sda1 /mnt/sysres -o ro

# 查看内容
ls -la /mnt/sysres/Boot/
ls -la /mnt/sysres/Boot/BCD

# 卸载
sudo umount /mnt/sysres

testdisk / photorec:恢复损坏的 BCD

Bash
# 如果 BCD 损坏(分区表还正常),用 testdisk 扫描
sudo testdisk /dev/sda
# 选择 [Proceed]
# 选 [Intel](MBR)
# 选 [Analyse] → [Search] 找丢失的分区
# 如果找到 System Reserved,确保挂载后 BCD 文件完整

# testdisk 也可以恢复被删的分区(但不会恢复 BCD 内容)
# BCD 本身是注册表 hive,没有备份的话损坏只能重建

完整修复案例:重装 Windows 后 GRUB 消失

这是最常见的双系统问题。Windows 安装时覆盖了 MBR,GRUB 被抹掉,Linux 无法启动。

修复前准备:确认 Linux 分区在哪里

Bash
# 用 Linux Live USB 启动(任意 Linux 发行版)

# 列出所有磁盘和分区
sudo fdisk -l /dev/sda | grep -E "Linux|Filesystem"

# 或者用 lsblk
lsblk

# 找到 Linux root 分区(假设是 /dev/sda2)
# 注意:如果 /boot 是独立分区,需要额外挂载 /dev/sda1

修复步骤(完整版)

Bash
# 1. 挂载 Linux 分区
sudo mount /dev/sda2 /mnt          # 假设 /dev/sda2 是 Linux root
# 如果 /boot 是独立分区
sudo mount /dev/sda1 /mnt/boot      # /boot 在 /dev/sda1

# 2. 挂载必要的系统目录
sudo mount --bind /dev /mnt/dev
sudo mount --bind /sys /mnt/sys
sudo mount --bind /proc /mnt/proc

# 3. chroot 进入 Linux
sudo chroot /mnt

# 4. 检查当前环境
grub-install --version
# 如果报错,可能是 chroot 里的 /dev 没正确挂载

# 5. 重新安装 GRUB 到 MBR(MBR 模式)
grub-install /dev/sda

# 6. 重建 grub.cfg(自动检测 Windows)
update-grub
# 输出应该包含:
#   Found Windows Boot Manager on /dev/sda1
#   Generating grub configuration ...
#   Found linux ... on /dev/sda2

# 7. 退出重启
exit
sudo reboot

如果 update-grub 没有检测到 Windows

Bash
# 在 chroot 环境里手动添加 Windows 启动项
# 先确认 Windows System Reserved 分区(假设 /dev/sda1)
blkid | grep -E "sda1|sda2"

# 编辑 /etc/grub.d/40_custom(正确位置,不是 grub.cfg)
cat >> /etc/grub.d/40_custom << 'EOF'
menuentry 'Windows 10 (via bootrec)' {
    insmod ntfs
    search --no-floppy --fs-uuid --set=root A2B3C4D5E6F7
    chainloader +1
}
EOF

# 重新生成 grub.cfg
update-grub

# 如果 Windows 还是没被检测到,检查 UUID 是否正确
# 查看 Windows 分区的 UUID
blkid /dev/sda1   # FAT32 的 System Reserved

实战:手动用 dd 重建 System Reserved 引导区

这个操作可以在不重装系统的情况下,修复 System Reserved 分区损坏导致的”启动设备未找到”错误。

步骤 1:确认 System Reserved 是哪个分区

Cmd
diskpart
list volume
# 找到 FAT32 的"系统保留"卷(假设是 D:,大小 100MB)
# 注意这个分区没有分配盘符,需要先 assign
select volume 0        # 根据 list 的输出调整
assign letter=D        # 临时分配 D: 盘符

步骤 2:从 Windows 安装盘提取 BOOTMGR

Cmd
# 在 WinRE 命令行里
# 先确认 C: 是哪个分区(Windows 系统分区)
# D: 是 System Reserved(刚刚 assign 的)

# 从 Windows 安装镜像的 boot.wim 里提取 BOOTMGR(如果本地 BOOTMGR 损坏)
# boot.wim 在镜像的 sourcesboot.wim 里

# 或者从正常工作的同版本 Windows 系统复制
copy C:WindowsBootPCATbootmgr D:Boot
copy C:WindowsBootPCATbootmgr.exe D:Boot 2>nul

步骤 3:手动写入 boot sector(高级)

Cmd
# bootsect 工具在 Windows 安装盘的 boot 目录下
# 在 WinRE 命令行里运行:
bootsect /nt60 D: /mbr
# 把 D:(System Reserved)的引导扇区写成 Windows 7+ 格式
# /mbr 同时更新 MBR 代码

踩坑与注意事项

坑 1:System Reserved 被删后 Windows 无法启动

现象:磁盘管理里误删了 System Reserved 分区,然后 Windows 启动时直接报 “BOOTMGR is missing”。

原因:BCD 和 BOOTMGR 都在 System Reserved 分区里,没了这个分区,BOOTMGR 找不到了。

解决:用 Windows 安装盘启动 → 修复计算机 → 命令提示符 → 重建 BCD(不重装):

Cmd
# 在 WinRE 命令行里
diskpart
list volume    # 找到 C: 分区(NTFS)
select volume X    # 选 C:
assign letter=C    # 确保 C: 指向正确分区

# 创建新的 System Reserved 分区(从未分配空间)
create partition primary size=100
format fs=fat quick
active
assign letter=D

# 从 C:WindowsBootPCAT 复制启动文件到 D:
bcdboot C:Windows /s D: /f BIOS
# /f BIOS = 生成 MBR 模式启动文件(不是 UEFI)

# 或者用完整的 bootrec 流程:
bootrec /fixmbr
bootrec /fixboot
bootrec /rebuildbcd

坑 2:bcdedit 改错了参数,系统无法正常启动

现象:执行 bcdedit /set {default} nx AlwaysOff 后,系统变得不稳定或无法进入安全模式。

解决:用 WinRE 启动,运行 bcdedit /deletevalue {default} nx 恢复默认值。

坑 3:活动分区标记错误导致 BOOTMGR 找不到

现象:BIOS 报告 “No bootable device”,但 MBR 的 0x55AA 还在。

原因:活动分区标记被误改(比如用 diskpart 把 C: 标为 active 而 System Reserved 变成 inactive),BOOTMGR 所在分区不再是”活动”的。

解决:用 diskpart 重新标记正确的分区为 active:

Cmd
diskpart
list disk
select disk 0
list partition
# 找到 System Reserved(通常是最小的 FAT32 分区,100MB 左右)
select partition X
active      # 设为活动

坑 4:bootsect /nt60 写成 NTFS 分区(而非 System Reserved)

现象:执行 bootsect /nt60 C: 后,C: 盘的引导扇区被改写,但 BOOTMGR 在 System Reserved 里,Windows 仍然无法启动。

原因:BIOS MBR 模式下,BOOTMGR 和 BCD 在 System Reserved(FATE32),不在 C:(NTFS)。bootsect /nt60 C: 只更新 C: 的 boot sector,不管 System Reserved。

解决:确保 bootsect 目标指向正确的分区(System Reserved,即活动分区)。

Cmd
# 正确顺序:先确定活动分区(System Reserved),再 bootsect
diskpart
list volume
# FAT32 的小分区(100MB)是 System Reserved
# 它的 boot flag = Active
# 用 bootsect /nt60 针对这个盘符

写在最后

Windows MBR+BIOS 启动链路,从按下电源键到登录界面,经历了:

Bash
POST → MBR(446B BOOTMGR代码) → BootBOOTMGR → BootBCD
→ WindowsSystem32winload.exe → WindowsSystem32ntoskrnl.exe

System Reserved 分区是这整条链路的”锚点”——没有它,BOOTMGR 无处可读;没有 BCD,BOOTMGR 无从知道该加载哪个 Windows;没有 winload.exe,内核永远不会被执行。

修复 Windows MBR 启动问题的核心工具就四个:bootrec(四板斧:/fixmbr /fixboot /scanos /rebuildbcd)、bcdedit(改 BCD)、bootsect(写引导扇区)、reagentc(管理 WinRE)。记住它们各自的职责,按顺序用,基本没有修不好的 MBR 启动问题。

wandos 目前没有自己的 MBR 启动支持。如果要做 MBR + BIOS 模式下的启动,需要参照 BOOTMGR 的架构:MBR 446 字节放跳转代码,跳转到 System Reserved 或 ESP 的 BOOTMGR,再由后者读取配置文件,找到内核文件。这整个链路比 GRUB 简单,但需要精确的分区表操作和 FAT32 文件系统支持。

下篇预告(365):候选方向——ext2 文件系统:inode、块组与目录项,或者 第一个用户态进程:从内核启动到 /sbin/init 的完整链路。你选哪个?

仓库https://github.com/golang12306/os-kernel-from-scratch


相关阅读

  • Windows BCD Store Format: 微软官方文档 MSBCDS
  • bootrec.exe 源码参考:ReactOS 项目 bootvid/bootsect.c
  • UEFI Spec:BIOS 模式启动部分(Compatibility Support Module)
  • Linux Kernel: block/partitions/msdos.c(MBR 分区解析)
  • https://github.com/zhangfuwen/wandos — Linux 内核教程

动手环节

想深入理解本文内容?动手实践是最好的方式:

今天的目标:在虚拟机里模拟 System Reserved 损坏,然后修复。

  1. 创建 Windows 虚拟机(MBR 模式)

    Bash
    # 用 QEMU 创建 MBR 模式的 Windows 虚拟机
    qemu-img create -f qcow2 win10-mbr.qcow2 50G
    # 安装时选择 MBR(不要选 GPT),确认有 System Reserved 分区
  2. 备份 System Reserved 的内容(Linux 里):

    Bash
    # 找到 System Reserved(/dev/sda1,大小约 100MB,FAT32)
    sudo mount -t fat /dev/sda1 /mnt/sysres -o ro
    tar -czf ~/sysres-backup.tar.gz -C /mnt/sysres Boot/ Recovery/
    ls -la ~/sysres-backup.tar.gz
  3. 模拟 BOOTMGR 损坏并修复

    Bash
    # 备份 boot sector
    sudo dd if=/dev/sda1 of=/tmp/sysres-boot.img bs=512 count=63
    
    # 损坏 boot sector(模拟错误修复)
    sudo dd if=/dev/zero of=/dev/sda1 bs=512 count=1
    
    # 用 WinPE 启动,运行:
    # bootsect /nt60 D: /mbr
    # bootrec /fixmbr
    # bootrec /rebuildbcd
  4. 用 bcdedit 创建自定义启动项

    Cmd
    bcdedit /copy {default} /d "Windows 10 No DEP"
    # 复制输出的 {identifier}
    bcdedit /set {identifier} nx AlwaysOff
    bcdedit /enum all
  5. 用 reagentc 管理 WinRE

    Cmd
    reagentc /info          # 查看当前 WinRE 状态
    reagentc /disable        # 临时关闭
    reagentc /enable         # 重新启用
    # 触发 WinRE:开机时强制关机 3

提示:在实际机器上操作前,务必先在虚拟机里实验。Windows MBR 启动的修复工具(bootrec、bootsect)都是写入磁盘的工具,操作失误可能破坏分区表。用虚拟机可以放心尝试。


仓库:https://github.com/golang12306/os-kernel-from-scratch

最后修改: 2024年9月24日

作者

评论

发表评论

您的邮箱地址不会被公开。