2. Legacy BIOS 详解:BIOS 自检 (POST)、主引导记录 (MBR)、分区表结构、启动流程

好,我们正式开始聊 Legacy BIOS。说实话,虽然现在 UEFI 是主流,但 Legacy 这套东西,你搞底层的一定得吃透。很多老设备、嵌入式系统、甚至某些安全启动场景,还在用它。我当年刚入行时,第一个项目就是调一块工控板的 BIOS,那会儿连 MBR 和 GPT 的区别都搞不太清楚,被 mentor 骂了好几次。嗯,今天我们就把它彻底讲明白。

2.1 BIOS 自检 (POST) —— 上电后的第一声啼哭

你按下电源键,CPU 复位,第一条指令从哪里来?

在 Legacy 体系里,CPU 上电后会直接跳转到 0xFFFFFFF0 这个地址。这个地址映射的是 BIOS ROM 的入口。说白了,BIOS 就是从这里开始接管系统的。

POST(Power-On Self Test)是 BIOS 做的第一件大事。它的核心任务就两个:检测硬件 和 初始化硬件。

POST 的主要检查项:

  • CPU:检查寄存器、缓存、是否支持必要指令集。我记得有一次遇到一块 CPU 的 L2 缓存坏了,POST 直接卡在 0xAA 代码上不动了。
  • 内存:做基本的读写测试。这里有个坑——有些 BIOS 只测前 64KB,后面的内存等操作系统去测。所以有时候你看到 POST 过了,进系统却蓝屏,可能就是内存后段有问题。
  • 芯片组:初始化南北桥(现在叫 PCH),配置内存控制器、PCI 总线等。
  • 显卡:如果是独立显卡,BIOS 会调用显卡的 Option ROM 来初始化它。你会看到屏幕闪一下,那就是显卡在干活。
  • 存储设备:检测硬盘、光驱、U 盘等。这时候 BIOS 会枚举 IDE/SATA 通道。
  • 键盘、鼠标等外设:基本 I/O 检查。

POST 过程中,如果检测到致命错误,BIOS 会通过 蜂鸣器 发出特定编码的响声。比如:

蜂鸣次数 含义
1 短 系统正常
1 长 2 短 显卡故障
连续长鸣 内存故障
无声音、无显示 CPU 或主板故障

我的经验: 如果你在调试时遇到 POST 卡住,别慌。看主板上的 Debug 灯 或者接一个 POST 卡(也叫诊断卡),上面会显示两位十六进制代码。比如代码 0xD0 通常表示 CPU 初始化失败,0x2A 表示显卡初始化。这比听蜂鸣器准多了。

2.2 主引导记录 (MBR) —— 硬盘的第一个扇区

POST 完成后,BIOS 会按照你设置的启动顺序,去尝试加载第一个可启动设备。如果是硬盘,它会读取硬盘的 第一个扇区(LBA 0,即 CHS 0/0/1)。这个扇区就是 MBR。

MBR 的大小固定为 512 字节。你别看它小,结构非常紧凑:

偏移地址 大小 内容
0x000 - 0x1BD 446 字节 第一阶段引导代码(Bootloader)
0x1BE - 0x1FD 64 字节 分区表(4 个主分区,每个 16 字节)
0x1FE - 0x1FF 2 字节 魔数(0x55AA)

这里有个关键点:0x55AA 这个魔数。BIOS 读到 MBR 后,会检查最后两个字节是不是 0x55AA。如果不是,它就认为这个硬盘不可启动,然后去试下一个设备。我曾经遇到过一块硬盘,分区表全乱了,但 0x55AA 还在,结果 BIOS 还是尝试去加载它,导致系统卡死。所以,这个魔数既是启动标志,也可能成为故障点。

2.3 分区表结构 —— 16 字节的乾坤

MBR 里的分区表只有 64 字节,最多容纳 4 个主分区。每个分区表项 16 字节,结构如下:

偏移 大小 含义
0x00 1 字节 引导标志(0x80 表示可引导,0x00 表示不可引导)
0x01-0x03 3 字节 起始 CHS 地址
0x04 1 字节 分区类型(如 0x07 是 NTFS,0x83 是 Linux ext4)
0x05-0x07 3 字节 结束 CHS 地址
0x08-0x0B 4 字节 起始 LBA 地址(相对于磁盘开头)
0x0C-0x0F 4 字节 分区总扇区数

注意: MBR 分区表使用 32 位 LBA 地址,最大只能寻址 2TB 的磁盘空间。超过 2TB 的硬盘,如果你用 MBR 分区,多出来的空间就浪费了。这是 MBR 的硬伤,也是后来 GPT 出现的原因之一。

另外,如果你需要超过 4 个分区,就得用 扩展分区。扩展分区本身也是一个主分区,但它里面可以再划分多个逻辑分区。扩展分区的分区表项里,分区类型会标记为 0x05 或 0x0F。逻辑分区的信息则存储在扩展分区的第一个扇区里,形成一个链表结构。说实话,这个设计挺绕的,我当年第一次看扩展分区的结构时,画了半天图才理清楚。

2.4 启动流程 —— 从 BIOS 到操作系统

好,现在我们把整个流程串起来。Legacy BIOS 的启动流程,说白了就是一场接力赛:

  1. 上电 -> CPU 复位 -> 跳转到 BIOS 入口
  2. BIOS 执行 POST:检测并初始化硬件
  3. BIOS 枚举启动设备:按照 CMOS 中设置的启动顺序(硬盘、U 盘、光驱等)
  4. BIOS 读取设备的第一个扇区(MBR):检查 0x55AA 魔数
  5. BIOS 将 MBR 中的引导代码加载到内存 0x7C00 处,然后跳转执行
  6. MBR 引导代码解析分区表:找到标记为 可引导(0x80)的分区
  7. MBR 引导代码加载该分区的 卷引导记录(VBR):VBR 位于该分区的第一个扇区
  8. VBR 加载操作系统的引导管理器:比如 Windows 的 bootmgr,或者 Linux 的 GRUB stage 1.5
  9. 引导管理器加载操作系统内核:至此,BIOS 的任务完成,操作系统接管

下面这张图可以帮你更直观地理解整个流程:

Legacy BIOS 启动流程 Legacy BIOS 启动流程 1. 上电 / CPU 复位 2. BIOS POST 自检 3. 枚举启动设备 4. 读取 MBR (0x55AA) 5. 加载 VBR / 引导管理器 6. 加载操作系统内核 关键地址 BIOS 入口: 0xFFFFFFF0 MBR 加载地址: 0x7C00 MBR 魔数: 0x55AA 分区表: 偏移 0x1BE

我的经验: 在实际调试中,如果你发现系统卡在“Loading operating system...”或者“Missing operating system”这类提示,通常问题出在 MBR 或 VBR 上。我曾经遇到过一块硬盘,MBR 的 0x55AA 还在,但引导代码被病毒改写了,结果就是死活进不去系统。用 fdisk /mbr 或者 bootsect /nt60 这类工具重写 MBR 引导代码,往往能解决问题。

2.5 Legacy BIOS 的局限性

聊了这么多,你也看出来了,Legacy BIOS 这套体系虽然经典,但确实有些年头了。它的局限性很明显:

  • 2TB 磁盘限制:MBR 分区表用 32 位 LBA,最大 2TB。现在随便一块硬盘都 4TB、8TB,MBR 根本 hold 不住。
  • 只能 4 个主分区:虽然可以用扩展分区绕过去,但管理起来很麻烦,而且扩展分区本身也有性能问题。
  • 16 位实模式:BIOS 运行在 16 位实模式下,只能访问 1MB 内存。虽然可以通过保护模式切换来突破,但效率低,代码也复杂。
  • 启动慢:POST 过程是串行的,一个一个设备检测,很慢。而且 BIOS 的代码通常放在 ROM 里,读取速度也慢。
  • 没有图形界面:纯文本界面,用户交互体验差。你想想看,现在谁还愿意在蓝底白字的菜单里调启动顺序?
  • 安全性差:没有 Secure Boot 机制,MBR 可以被恶意软件轻易改写。我见过不少 CIH 病毒就是通过改写 MBR 来搞破坏的。