2. 固件层:BIOS与UEFI的初始化与自检
好,咱们正式开始聊系统启动的第一棒——固件层。你按下电源键的那一刻,CPU 还是“裸奔”状态,内存里空空如也。谁来做第一个引路人?就是主板上的固件。早年是 BIOS,现在基本都换成了 UEFI。这两兄弟干的活本质差不多,但干活的方式天差地别。
我个人习惯把这一阶段称为“硬件的自我认知过程”。说白了,就是固件先把自己唤醒,然后挨个检查挂在总线上的设备,最后把控制权交给下一棒——引导加载程序。这个过程要是出问题,机器连“嘀”一声都没有,你连 BIOS 界面都进不去。
2.1 从加电到第一条指令
CPU 一上电,会去一个固定的物理地址取第一条指令。对于 x86 平台,这个地址是 0xFFFFFFF0,也就是所谓的 Reset Vector。这里存放的是一条跳转指令,直接跳到固件的入口代码。
嗯,这里要注意:这时候内存还没初始化,CPU 是怎么执行代码的?答案是 CPU 内部有一段隐藏的 SRAM,或者叫 Cache-as-RAM(CAR)技术。固件在早期阶段会把 CPU 的缓存当内存用,等内存控制器初始化好了,再切回真正的 DRAM。
2.2 BIOS 的 POST 流程
BIOS 的 POST(Power-On Self-Test)是一个线性、串行的过程。它不像 UEFI 那样可以并行,所以老机器启动慢是有原因的。我把它拆成几个关键步骤:
- CPU 初始化:设置 MSR(Model-Specific Registers),检测 CPU 型号、步进、缓存大小。
- 芯片组初始化:配置北桥(内存控制器)和南桥(I/O 控制器)的寄存器。
- 内存初始化:训练内存时序,做内存检测(Counting)。
- 设备枚举与检测:扫描 PCI 总线,给每个设备分配资源(IRQ、I/O 端口、MMIO)。
- Option ROM 执行:加载显卡、网卡等设备的扩展 ROM。
- 启动设备选择:按优先级扫描硬盘、光驱、U 盘,找到引导扇区。
你想想看,这每一步都是串行的。如果某个设备响应慢,整个启动就被卡住了。我记得有一次,一台服务器每次启动都要等 3 分钟,最后发现是南桥上挂了一个已经坏掉的 RAID 卡,BIOS 在枚举它的时候反复超时重试。
2.3 UEFI 的初始化与自检
UEFI 比 BIOS 先进在哪?说白了,它把固件做成了一个微型操作系统。它有自己的驱动程序模型、协议接口,甚至还能跑 Shell 脚本。UEFI 的初始化流程分为七个阶段,用字母表示:
| 阶段 | 全称 | 主要工作 |
|---|---|---|
| SEC | Security Phase | 安全验证,设置临时内存(CAR),验证固件签名 |
| PEI | Pre-EFI Initialization | 初始化内存控制器,发现内存,提供内存描述表 |
| DXE | Driver Execution Environment | 加载大部分设备驱动,枚举 PCI 设备,分配资源 |
| BDS | Boot Device Selection | 显示启动菜单,按策略选择启动设备 |
| TSL | Transient System Load | 加载引导加载程序(如 GRUB、Windows Boot Manager) |
| RT | Runtime | 操作系统接管,UEFI 进入运行时服务模式 |
| AL | After Life | 系统关机或重启时的清理工作 |
这里有个关键点:UEFI 的 DXE 阶段是并行的。多个驱动可以同时加载,所以 UEFI 启动比 BIOS 快得多。但并行也带来了调试的复杂性——你很难复现一个时序相关的 bug。
.efi 后缀的引导文件。如果你在 UEFI 模式下装系统,却把 ESP 分区格式化成 NTFS,那机器肯定起不来。
2.4 自检与错误处理
不管是 BIOS 还是 UEFI,自检过程中如果发现致命错误,都会通过某种方式通知你。BIOS 用蜂鸣器编码,UEFI 用屏幕上的错误码或 LED 灯。我整理了一份常见的 POST 错误码对照表:
| 蜂鸣次数 | BIOS 含义(AMI) | UEFI 错误码 | 可能原因 |
|---|---|---|---|
| 1 短 | 系统正常 | 无 | 一切正常 |
| 2 短 | 内存奇偶校验错误 | 0x00000001 | 内存条松动或损坏 |
| 3 短 | 基本内存错误 | 0x00000002 | 内存控制器故障 |
| 1 长 2 短 | 显卡错误 | 0x00000010 | 显卡未插好或供电不足 |
| 连续长鸣 | 内存未检测到 | 0x00000020 | 内存条未安装或接触不良 |
嗯,这里要提醒一句:现在的 UEFI 主板很多都取消了蜂鸣器,改用板载的 Debug LED 灯或者数码管显示十六进制代码。如果你手头没有 POST 卡,可以看看主板边缘有没有一排小灯,那比听声音靠谱多了。
2.5 固件层的核心逻辑图
下面这张图展示了从加电到引导加载程序之间的完整流程,以及 BIOS 与 UEFI 的路径对比:
2.6 实战:如何判断当前系统是 BIOS 还是 UEFI
你在排查启动问题时,第一步得搞清楚固件模式。我一般用下面几个方法:
- 查看 /sys/firmware/efi:在 Linux 下,如果存在
/sys/firmware/efi目录,说明是 UEFI 启动。否则就是传统 BIOS。 - 检查 dmesg 日志:执行
dmesg | grep -i "efi",如果有输出,就是 UEFI。 - 看分区表:UEFI 系统必须有一个 ESP 分区(通常是 FAT32,挂载在
/boot/efi)。BIOS 系统则没有。
2.7 固件层常见故障与排查
最后,聊几个我在项目中踩过的坑:
- 内存训练失败:换了新内存条后,机器反复重启三次才进系统。这是 UEFI 在做内存重新训练。如果一直卡住,可以尝试清空 CMOS 或手动设置内存频率。
- Secure Boot 导致无法引导:装了 Linux 后,启动时提示“Invalid signature detected”。进 BIOS 关掉 Secure Boot,或者给内核签名。
- 固件更新后变砖:我曾经手贱在 Windows 下刷了测试版 BIOS,结果重启后黑屏。后来用编程器夹子夹住固件芯片,重新烧录才救回来。所以,固件更新尽量在 BIOS 内置的更新工具里做,别在操作系统里搞。
嗯,固件层的内容差不多就这些。你只要记住:BIOS 是串行的老黄牛,UEFI 是并行的现代化系统。下一棒,引导加载程序会接过控制权,开始加载操作系统内核。但那是后面的事了,咱们先把固件这关过好。