1.3 关键差异对比


1.3 关键差异对比

本节摘要:把 BIOS 与 UEFI 放在同一张桌子上对比,差异远不止界面新旧。本节沿三条主线展开:地址空间与磁盘布局、驱动与交互契约、信任的存续方式。结论先行——两者分属两个工程时代,BIOS 把兼容性当作最高纲领,UEFI 把可验证性当作第一原则。

阅读目标

读完这一节,请自查五项能力:能否默写出 8086 时代 1MB 空间的三块划分并说明每块的来历;能否推导 MBR 的 2.2TB 天花板从何而来、GPT 又如何拆掉它;能否把一次 INT 13h 调用与一次 Block I/O 协议调用逐参数对齐;能否解释 SEC→PEI→DXE 三级接力为什么天然构成信任链;能否脱稿向同事白板画出双列对比矩阵。

一、地址与磁盘:被历史钉死的 1MB,与被规范放开的 256TB

8086 的设计决定了此后二十余年的困局:20 根地址线,段寄存器左移四位与偏移相加,可表达的空间恰好 1MB。这个数字在 1981 年足够阔绰,到 1990 年代就成了镣铐。BIOS 只能在这个拥挤的空间里做文章,于是 PC 平台长年维持一幅奇特的地图——

  • 0x00000~0x9FFFF 共 640KB 归 DOS 与应用程序,即所谓 conventional memory;
  • 0xA0000~0xFFFFF 共 384KB 称为 UMA,被 VGA 帧 buffer、各扩展 ROM、ISA 板卡的 I/O 窗口切分殆尽;
  • 1MB 之上是 extended memory,访问它要么扳动 A20 gate,要么切进保护模式,DOS 时代还得靠 HIMEM.SYS 这类驱动搭桥。

这套分割带来两层后遗症。其一,实模式单个段至多 64KB,BIOS 扩展代码被迫拆成小段互相远跳,寄存器传参的约定既难维护也难审计,日后大量溢出类漏洞的根源都能追到此处。其二,磁盘侧同样保守:分区信息挤在 MBR 的 512 字节里,四个主分区表项、每项 16 字节、32 位 LBA,算术上封顶约 2.2TB。2005 年前后大容量盘上市,这条红线逼出了各种厂商私有的扩展方案,碎片化随之蔓延——BIOS 在存储这件事上,从摆渡人变成了拦路者。

UEFI 的答案很直接:不迁就历史。固件在 SEC 之后尽快切入保护模式乃至 IA-32e,主流平台提供 48 根地址线、约 256TB 的平坦空间,规范层面按 64 位规划。代码放哪里都行,驱动可装进任意物理页,调用全用指针,不存在段切换的开销与心智负担。

磁盘抽象同步换代。GPT 把表头放在 LBA1、把备份副本放在盘尾,每个分区表项 128 字节,容量与数量的理论上限足够用到大容量存储本身被淘汰。更进一步,GPT 不是孤立的格式,而是与启动路径绑定的:固件自带 GPT 解析器,认出 EFI 系统分区后直接把 .efi 文件当程序装载执行。BIOS 那条“读 MBR→跳引导扇区→引导扇区再去找下一级”的接力链条,每多一环就多一个被篡改的位置;UEFI 把链条截短成“固件直接取文件”,路径确定、结果可验证。

维度 传统 BIOS UEFI
CPU 模式 16 位实模式起跳,需模式切换舞蹈 直接进入保护/长模式
寻址上限 1MB(20 根地址线) 48 位总线约 256TB,规范 64 位
内存布局 常规/UMA/扩展三段割裂 平坦空间统一编址
分区方案 MBR,4 主分区,2.2TB 上限 GPT,备份表头,容量近乎无限
引导方式 MBR 链式跳转,逐级加载 固件直取 ESP 中的 efi 文件
配置存储 CMOS RAM 128 字节 SPI Flash 中的 GUID 变量

二、接口与驱动:从念咒语,到签合同

BIOS 对外提供能力的方式,是一张写死的中断向量表。操作系统想读盘,就往寄存器里塞好功能号与参数,触发 INT 13h,BIOS 在暗处干活,干完通过 CF 标志和 AH 回个结果。这份“合同”全部靠默记:参数顺序、段寄存器搭配、错误码含义,都约定在手册里而没有机器可读的形式。你想确认一次扩展读写是否真的原子、INT 10h 换模式时是否与别的核发生显示状态竞争?没有观测点,也无从验证。

驱动这件事在 BIOS 世界里干脆不存在。硬件初始化代码被编死进 ROM,与具体芯片组、Super I/O、南桥型号共生。想让一台老机器认得 NVMe 盘?找厂商重编整份固件、走烧录更换流程,周期以月计。用户侧既装不了也换不了任何“BIOS 驱动”——固件即硬件,出厂即终点。

UEFI 把这套暗语换成了显式的类型化接口,即 Protocol:一组带完整签名的函数指针,挂在系统句柄数据库里供检索。拿块设备协议举例,一次读操作的入参包括协议实例指针、介质 ID、LBA、缓冲长度与输出 buffer,语义白纸黑字,边界一目了然。任何驱动只要实现并注册了该协议,任何应用都能按标准流程查到它、调用它——耦合被接口切断,组件可以替换、可以单独测试。

交互形态因此升级。UEFI Shell 是个货真价实的命令行环境:跑 .efi 程序、遍历协议、查设备树、手工挂驱动、dump 内存,样样能做,早已超出 BIOS Setup 那种“改改数值”的维修面板定位。Setup 界面本身也变了底座——图形输出协议撑起鼠标、多语言、高分屏,而不是靠 VGA 中断的模拟硬撑。

安全能力同样是接口模型的副产品。Secure Boot 能落地,靠的不是给启动文件套一层加密,而是整个装载流程走协议化验证:固件装载 .efi 前先取其签名,再对照密钥库逐级核对签名链与吊销记录。每一步都是可审计的协议交互,而不是“把一坨机器码加载进来然后祈祷”。

💡 关键直觉:可以把 UEFI 驱动模型理解成“固件里的微内核”。DXE Core 只保留调度、内存与协议发布/查找这几件核心事;网络栈、文件系统、TPM 访问、图形输出统统是独立编译、可签名、可按需装载的 .efi 模块。BIOS 是琥珀,UEFI 是雨林。

维度 BIOS 中断服务 UEFI Protocol
契约形式 中断号加寄存器约定,隐式默会 函数指针签名,显式声明
参数传递 寄存器(DL、CH、ES:BX 等) 命名参数加输出缓冲
错误处理 进位标志加 AH 错误码 规范化状态码
可发现性 固定中断号,无运行时枚举 句柄数据库动态发现
可扩展性 出厂固化,无法追加 efi 驱动按需加载与替换
可验证性 无签名机制 签名链逐级校验

三、信任模型:一锤子买卖,还是终身保修

最后一组差异藏在最深处:系统凭什么相信开机后执行的第一段代码之后的一切。BIOS 的做法是一锤子买卖——POST 里把 CPU、内存、显示做一轮粗检,然后把控制权抛给 MBR,自己功成身退。引导扇区后来有没有被人动过手脚、内核里是否潜伏 rootkit,它既看不见也管不着。像小区保安查过一次证件就永久下班,面对 Bootkit、恶意固件这类针对启动链的攻击,防御纵深为零。

UEFI 则把验证做成了贯穿始终的流水。固件执行被切进三个互相衔接又互相约束的阶段:SEC 阶段是 CPU 上电后最先跑的一小段代码,固化在处理器/芯片组内部,负责搭起最初的执行环境与临时 RAM,位置上不可覆盖,天然是信任链的第一环;PEI 阶段接手,在 SEC 铺好的安全上下文里点亮内存控制器与芯片组,模块本身可验签;DXE 阶段是主战场,装载并运行各 .efi 组件,维护句柄与协议数据库,Secure Boot 的校验逻辑在此启用——每一份 EFI 映像都要过 PK/KEK/db 签名链,任何一环核对失败即中止装载。

还有一块常被忽略:UEFI 运行时服务在 OS 起来之后仍驻留在受保护地址空间。哪怕内核被彻底攻陷,攻击者想改 dbx 吊销名单,也得拿出有效 KEK 签名,而 KEK 又被 PK 罩着。验证从按下电源键那刻起,一直延续到系统关机前。

产业侧早已按这个模型重整防线:微软 Device Guard、Intel Boot Guard、AMD 的平台密钥方案都是它的实现变体;MITRE ATT&CK 专门增设固件持久化技术条目,反证了固件层已是 APT 的必争之地,而 UEFI 的结构性验证是目前唯一的体系化对策。

⚠️ 常见坑:对比时别只盯理论模型。现实中的 UEFI 设备为兼容旧系统和双系统,普遍预装微软证书与主流 Linux 发行版证书,还留着 CSM 这个向后兼容通道——防火墙上留着窗是商业取舍。生产环境应关闭 CSM,并定期收紧 db 里的证书集合。

四、差异背后:两种工程哲学

三条线索汇拢,分野其实只有一个:BIOS 是工业时代的兼容性工程,追求不动、能跑、别出事;UEFI 是数字时代的可信性工程,追求可组合、可验证、可持续演进。前者的信任寄托在厂商与物理封装上,后者的信任建立在开放规范与密码学契约上。

这层范式迁移的外溢远大于启动本身:虚拟化平台借 SMM 做安全监控,机密计算拿 TCG 2.0 当可信执行环境的起点,连现代沙箱设计里“明确接口、解耦实现”的思路,都与 Protocol 机制一脉相承。

本节速览

  • 地址:三段割裂的 1MB 对平坦的 48 位空间;段偏移协作是安全隐患的老巢。
  • 磁盘:MBR 的 512B/4 项/2.2TB 对 GPT 的 128B 条目/盘尾备份;启动由链式接力变成固件直取。
  • 接口:寄存器默会约定对显式函数签名;错误从 CF/AH 变成规范状态码;发现机制从无到有。
  • 信任:一次性门卫对 SEC/PEI/DXE 加运行时服务的全程验证。
  • 纵深:OS 沦陷后策略变量仍受 KEK/PK 保护,验证覆盖运行期。
  • 一句话结论:参数差异是表象,实质是信任主权从封闭黑箱迁移到开放契约。

第一章到此完成“概念—历史—对比”的闭环。下一章钻进机器内部,按时间轴拆一遍从加电自检到操作系统接管的全过程。

五、两条验证命令:三秒钟分辨机器走的是哪条路

对比表背得再熟,不如在自己机器上敲一条命令。UEFI 启动的 Linux 会把 EFI 变量挂成 sysfs 下的 efivars 目录,传统 BIOS 启动则根本没有这套接口:

# UEFI 启动的机器 $ ls /sys/firmware/efi efivars fw_platform_size fw_vendor runtime runtime-map systab tpm2_log $ cat /sys/firmware/efi/fw_platform_size 64 $ cat /sys/firmware/efi/fw_vendor AMI # 传统 BIOS(Legacy/CSM)启动的同一台机器 $ ls /sys/firmware/efi ls: cannot access '/sys/firmware/efi': No such file or directory

fw_platform_size 为 64 说明 CPU 进入 OS 加载器时处于 64 位长模式,这正是 UFEI "先设好执行环境再交接"的直接证据;BIOS 交接时只会把 CPU 留在 16 位实模式,加载器还得自己开 A20、切保护模式。

差异的另一半在交接数据结构上。BIOS 时代的引导扇区约定是死板的 512 字节、末尾 0x55AA;UEFI 交接的则是 EFI_HANDOFF_PROTOCOL 里成体系的表指针。两种约定并排看:

/* 传统 BIOS 约定:引导扇区最后两字节的魔数,加载到 0x7C00 执行 */ /* 用 xxd 看一个 syslinux MBR 的结尾 */ $ xxd -s 510 -l 2 mbr.bin 000001fe: 55aa U. /* UEFI 约定:OS 加载器入口收到的 EFI_SYSTEM_TABLE 指针(EDK2 头文件节选) */ typedef struct { CHAR16 *FirmwareVendor; /* 如 L"AMI" */ UINT32 FirmwareRevision; EFI_TABLE_HEADER Hdr; EFI_HANDLE ConsoleInHandle; EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; EFI_RUNTIME_SERVICES *RuntimeServices; EFI_BOOT_SERVICES *BootServices; UINTN NumberOfTableEntries; EFI_CONFIGURATION_TABLE *ConfigurationTable; /* ACPI/SMBIOS 表入口 */ } EFI_SYSTEM_TABLE;

一边是两个字节的自证,一边是带 CRC32 校验头、串联 ACPI 与 SMBIOS 入口的整套目录,第 2 章的启动流程差异在这组对照里已经埋下伏笔。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U