UEFI EDK2固件开发与BIOS调试 - 第1节

1.1 BIOS 的定义与核心角色

BIOS(Basic Input/Output System,基本输入输出系统)是计算机系统中运行在裸机硬件之上的第一层固件代码。它位于主板上的闪存芯片中,在 CPU 复位后最先执行,负责初始化硬件、加载操作系统引导程序,并为操作系统提供最底层的硬件抽象接口。

核心定义:BIOS 是固化在 ROM/Flash 中的固件,是硬件与操作系统之间的桥梁,也是计算机启动过程中第一个被执行的软件。

BIOS 在计算机系统中的五大功能

功能 说明 典型操作
POST(上电自检) 检测 CPU、内存、芯片组、I/O 设备等关键部件是否正常 读取 CMOS 配置,检查内存容量,验证校验和
硬件初始化 将芯片组、寄存器、中断控制器、定时器等设置为已知工作状态 配置 MTRR、设置 APIC、初始化 PCI 总线
中断服务 提供 INT 10h(视频)、INT 13h(磁盘)、INT 16h(键盘)等软件中断 实模式下通过中断向量表(IVT)调用
引导加载 按引导顺序查找可启动设备,加载引导扇区到内存并跳转执行 读取 MBR/GPT,执行 BootLoader
运行时服务 为操作系统提供固件级别的配置读写、电源管理等接口 SMBIOS 表、ACPI 表、CMOS 读写

1.2 BIOS 的历史演变:从 IBM PC BIOS 到 UEFI

1.2.1 IBM PC BIOS 时代(1981–1990s)

1981 年 IBM 推出第一台个人电脑 IBM 5150,其主板上搭载了 8KB 的 BIOS 固件,由 IBM 工程师编写,存储在 ROM 芯片中。该 BIOS 提供了基本的键盘、显示器、磁盘和串口驱动,并通过 INT 中断供 DOS 调用。由于 IBM 公开了 BIOS 接口规范但未开放源码,催生了 Phoenix、AMI、Award 等第三方 BIOS 厂商通过“净室实现”开发兼容 BIOS。

关键转折:IBM PC BIOS 的封闭性反而催生了兼容 BIOS 产业,使得 x86 兼容机生态得以爆发式增长。

1.2.2 传统 BIOS 的局限与扩展(1990s–2000s)

随着硬件复杂度提升,传统 BIOS 的 16 位实模式、1MB 地址空间限制、MBR 分区表(最大 2TB)、缓慢的初始化速度等问题日益突出。业界通过 ACPI(高级配置与电源接口)、SMBIOS、PnP(即插即用)等扩展标准来弥补不足,但架构层面的瓶颈无法根本解决。

局限 具体表现 影响
16 位实模式 只能访问 1MB 地址空间,代码效率低 初始化大型内存和 64 位设备困难
MBR 限制 分区表仅 64 字节,最大支持 2TB 磁盘 无法引导大容量存储设备
缺少统一驱动模型 Option ROM 碎片化,兼容性问题多 显卡、网卡等扩展卡初始化复杂
启动速度慢 串行初始化,缺乏并行能力 从按下电源到进入系统需数十秒

1.2.3 UEFI 的诞生与普及(2000s–至今)

Intel 在 1998 年启动 EFI(Extensible Firmware Interface) 项目,最初面向 Itanium 架构。2005 年 UEFI 论坛成立,将 EFI 标准化为 UEFI(Unified Extensible Firmware Interface)。UEFI 彻底抛弃了传统 BIOS 的 16 位实模式,采用 32/64 位保护模式、C 语言编程接口、GPT 分区表、网络引导、安全启动(Secure Boot)等现代特性。目前主流 PC、服务器、嵌入式设备均已采用 UEFI 固件。

注意:UEFI 并非传统 BIOS 的简单升级,而是一个全新的固件接口规范。业界常说的“UEFI BIOS”是一种习惯称呼,严格来说 UEFI 是固件接口标准,BIOS 是传统实现方式。

1.3 BIOS 与 UEFI 架构对比

传统 BIOS 与 UEFI 架构对比 传统 BIOS 架构 16 位实模式(1MB 地址空间) 汇编语言编写,代码可读性差 MBR 分区表(≤2TB) Option ROM 碎片化,无标准驱动模型 串行初始化,启动速度慢 UEFI 架构 32/64 位保护模式,大地址空间 C 语言编程,模块化设计 GPT 分区表(支持 >2TB) 统一驱动模型(UEFI Driver) 并行初始化,支持网络引导/安全启动

1.4 BIOS/UEFI 在系统启动流程中的位置

从按下电源按钮到操作系统加载完成,BIOS/UEFI 固件承担了以下关键步骤:

  1. CPU 复位:CPU 从复位向量(传统 BIOS 为 FFFF:FFF0,UEFI 为 Reset Vector)取指执行。
  2. 早期初始化:设置 CPU 模式、缓存、内存控制器,从 Flash 中解压固件代码。
  3. 硬件枚举与配置:检测 CPU、内存、芯片组、PCI 总线、存储设备等。
  4. POST 自检:验证关键硬件是否正常,异常时通过蜂鸣码或屏幕代码报错。
  5. 引导设备选择:按配置的引导顺序(硬盘、U 盘、网络、光驱等)查找可启动设备。
  6. 加载引导程序:传统 BIOS 读取 MBR 中的引导代码;UEFI 读取 ESP 分区中的 EFI 应用程序。
  7. 移交控制权:跳转到引导程序入口,固件任务完成。
开发视角:BIOS/UEFI 开发者的工作覆盖上述 1–6 步,包括芯片级初始化、硬件抽象层(HAL)、驱动框架、用户界面(Setup)、ACPI/SMBIOS 表生成等。

1.5 为什么 BIOS 开发仍然重要

尽管 UEFI 已成为主流,但 BIOS 开发知识在以下场景中依然不可或缺:

  • 嵌入式系统:大量 ARM/x86 嵌入式平台仍使用定制化 BIOS 或 U-Boot 等类 BIOS 固件。
  • 固件安全:理解 BIOS 启动流程是分析 Bootkit、Secure Boot 绕过、固件漏洞的基础。
  • 硬件验证:芯片验证工程师需要编写 POST 代码来测试新 CPU/芯片组。
  • 兼容性维护:老旧系统维护、工业控制设备、特殊军用计算机仍需传统 BIOS 支持。
  • UEFI 底层开发:UEFI 的 PEI(EFI 前初始化)阶段仍包含大量类似传统 BIOS 的硬件操作逻辑。
学习路径建议:从传统 BIOS 的实模式汇编、中断调用、CMOS 操作入手,再过渡到 UEFI 的 C 语言驱动模型、Protocol 机制、EDK II 框架,是固件开发最扎实的进阶路线。