1. UEFI 概述:从 BIOS 到 UEFI 的演进之路

大家好,我是你们这门课的老朋友。今天咱们聊聊 UEFI——这个现代计算机启动时第一个见到的“大管家”。

说实话,我入行那会儿,大家还在跟传统 BIOS 打交道。那时候调试一个启动问题,经常要对着黑底白字的界面按 F2 进设置,改个硬盘模式还得重启两三次。后来 UEFI 普及了,我才发现,原来引导可以这么“现代化”。

1.1 UEFI 的起源与发展

UEFI 的全称是 Unified Extensible Firmware Interface,统一可扩展固件接口。它最早是 Intel 搞出来的,叫 EFI(Extensible Firmware Interface),目的是解决传统 BIOS 的各种“老毛病”。

我记得 2005 年左右,Intel 在安腾处理器平台上推出了 EFI 1.0 规范。那时候大家还不太买账,觉得 BIOS 够用了。但后来随着 64 位处理器、大容量硬盘、网络启动这些需求冒出来,BIOS 的 16 位实模式、1MB 寻址空间这些限制就成了“绊脚石”。

2005 年,Intel 把 EFI 规范交给了 UEFI 论坛管理,从此改名叫 UEFI。这个论坛现在成员可不少,Intel、AMD、Microsoft、Apple、HP、Dell 这些大厂都在里面。UEFI 2.0 规范在 2006 年发布,之后几乎每年都有更新。

现在 UEFI 已经发展到 2.10 版本了(2022 年发布)。你想想看,从最初的 1.0 到现在的 2.10,这中间经历了多少迭代?我手头还存着一份 2006 年的 UEFI 2.0 规范 PDF,翻出来看看,那时候的协议栈比现在简单多了。

关键里程碑:

  • 1998 年:Intel 启动 EFI 项目(代号“Tiano”)
  • 2005 年:EFI 1.10 发布,同年移交 UEFI 论坛
  • 2006 年:UEFI 2.0 规范发布,引入 Secure Boot 概念
  • 2012 年:Windows 8 强制要求 UEFI + Secure Boot
  • 2022 年:UEFI 2.10 规范发布,支持更多安全特性

1.2 UEFI 与传统 BIOS 的区别

很多人问我:“UEFI 和 BIOS 到底有啥不一样?”我一般会打个比方:BIOS 就像老式座机电话,只能打电话;UEFI 就像智能手机,能打电话、上网、装 App、还能跑图形界面。

咱们从几个核心维度对比一下:

对比维度 传统 BIOS UEFI
运行模式 16 位实模式 32/64 位保护模式 + 长模式
寻址空间 1MB(实际可用约 640KB) 理论可达 16EB(实际受硬件限制)
磁盘分区 MBR(最大 2TB,最多 4 个主分区) GPT(最大 9.4ZB,128 个分区)
启动速度 慢(逐扇区扫描引导) 快(直接加载 EFI 应用程序)
用户界面 文本菜单,键盘操作 支持图形界面,鼠标操作
扩展性 差(Option ROM 限制多) 好(UEFI Driver Model,可加载驱动)
网络支持 基本没有 原生支持 HTTP、iSCSI、PXE
安全特性 无 Secure Boot、Measured Boot

这里我特别想强调一点:UEFI 不是一个“操作系统”,它是一个固件接口规范。说白了,它定义了一套标准 API,让操作系统和硬件之间能“说同一种语言”。

个人经验: 我在一个嵌入式项目中遇到过 BIOS 的 1MB 限制问题。当时要在老主板上加载一个 1.2MB 的固件镜像,死活加载不进去。后来换成 UEFI 方案,直接分配 4MB 内存给固件,问题就解决了。嗯,从那以后我对 UEFI 的“大内存”优势印象特别深。

1.3 UEFI 的启动流程概览

UEFI 的启动流程,说白了就是“从按下电源键到操作系统接管”的整个过程。我习惯把它分成几个阶段:

  1. SEC(Security Phase):安全验证阶段,检查固件完整性
  2. PEI(Pre-EFI Initialization):预初始化阶段,初始化 CPU、芯片组、内存
  3. DXE(Driver Execution Environment):驱动执行环境,加载各种设备驱动
  4. BDS(Boot Device Selection):启动设备选择,决定从哪个设备引导
  5. TSL(Transient System Load):临时系统加载,执行 Bootloader
  6. RT(Run Time):运行时阶段,操作系统接管后 UEFI 提供运行时服务

你可能会问:“为什么分这么多阶段?”其实每个阶段都有明确的分工。比如 PEI 阶段只做最基本的内存初始化,因为这时候连内存都还没好,代码只能在 CPU 缓存里跑。等内存好了,DXE 阶段才开始加载各种驱动。

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

UEFI 启动流程概览 UEFI 启动流程概览 SEC 安全验证 PEI 预初始化 DXE 驱动加载 BDS 设备选择 TSL Bootloader RT 运行时 各阶段说明: • SEC:验证固件完整性,建立安全信任根 • PEI:初始化 CPU、芯片组、内存(代码在缓存中运行) • DXE:加载设备驱动,创建 UEFI 协议栈 关键节点: • BDS:选择启动设备(硬盘、U盘、网络等) • TSL:加载 Bootloader(如 GRUB2、Windows Boot Manager) 时间轴(从按下电源键到操作系统接管): 电源开启 → SEC(毫秒级)→ PEI(毫秒级)→ DXE(秒级)→ BDS(毫秒级)→ TSL(秒级)→ RT(操作系统运行)

嗯,这里要注意:UEFI 启动流程不是线性的。比如 DXE 阶段可以并行加载多个驱动,不像 BIOS 那样一个一个来。这也是 UEFI 启动更快的原因之一。

避坑指南: 我曾经在一个项目中遇到 UEFI 启动卡在 DXE 阶段的问题。排查了半天,发现是一个第三方网卡驱动在 DXE 阶段加载时崩溃了。后来我养成了一个习惯:在开发 UEFI 驱动时,一定要在 DXE 入口函数里加调试输出,否则出了问题你根本不知道是哪个驱动挂了。

1.4 UEFI 的核心组件

UEFI 固件里包含几个关键组件,我简单列一下:

  • UEFI 固件:存储在 SPI Flash 中,包含 SEC/PEI/DXE 等阶段的代码
  • UEFI 变量:非易失性存储,用于保存配置信息(如启动顺序、Secure Boot 密钥)
  • UEFI 协议:接口定义,驱动之间通过协议通信(如 Block IO Protocol、Simple File System Protocol)
  • UEFI 应用程序:.efi 文件,在 UEFI Shell 或 BDS 阶段执行(如 Bootloader、诊断工具)
  • UEFI 驱动:.efi 文件,在 DXE 阶段加载,提供硬件抽象

我个人觉得,理解 UEFI 最好的方式就是把它当成一个“微型操作系统”。它有内存管理、任务调度、协议栈、文件系统支持,甚至还有自己的 Shell 环境。你可以在 UEFI Shell 里执行命令、加载驱动、运行应用程序——跟 Linux 终端差不多。

小技巧: 如果你手头有 UEFI 设备,可以在启动时按某个键(通常是 F2、Del、Esc)进入 UEFI 设置界面。有些主板还支持直接进入 UEFI Shell,那里可以执行 .efi 文件,对调试很有帮助。

1.5 为什么 UEFI 对 Bootloader 如此重要?

这个问题其实很简单:Bootloader 是 UEFI 的“客户”。UEFI 提供了一套标准接口,Bootloader 通过调用这些接口来加载操作系统内核。

举个例子,GRUB2 在 UEFI 平台上就是一个 .efi 文件。它利用 UEFI 提供的文件系统协议读取 /boot/grub/grub.cfg 配置文件,利用块 IO 协议读取内核镜像,利用 GOP(Graphics Output Protocol)显示图形界面。

没有 UEFI,Bootloader 就得自己实现这些功能——自己写硬盘驱动、文件系统驱动、显示驱动。那工作量可就大了去了。

所以,理解 UEFI 的启动流程、协议栈、内存布局,是写好 Bootloader 的前提。这也是为什么我把 UEFI 概述放在第一课的原因。