3. UEFI启动流程总览:从按下电源键到操作系统加载的完整路径

各位同学,今天我们来聊聊UEFI启动的完整路径。说白了,就是从你按下电源键那一刻起,到操作系统跑起来之前,这中间到底发生了什么。

我刚开始做UEFI开发时,总觉得这玩意儿就是个黑盒子。后来踩了不少坑,才慢慢把这条路径摸清楚。今天我就把这条路径拆开给你看,每个阶段干什么、谁负责、容易出什么问题,咱们一次讲透。

核心观点:UEFI启动不是一蹴而就的,它是一条流水线。每个阶段都有明确的职责边界,上一个阶段干完活,把接力棒交给下一个阶段。理解这条流水线,你就能定位90%的启动问题。

3.1 启动流程的七个阶段

UEFI规范把启动过程分成了七个阶段,用首字母缩写叫 SEC-PEI-DXE-BDS-TSL-RT-AL。嗯,这串字母看着有点吓人,但你记住一个规律就行:越靠前的阶段,代码越简单、环境越原始;越靠后的阶段,功能越丰富、越接近操作系统。

我习惯把这七个阶段分成三组来理解:

  • 硬件初始化组:SEC → PEI → DXE。负责把CPU、内存、芯片组这些基础硬件初始化好。
  • 启动策略组:BDS → TSL。负责决定从哪个设备启动、怎么加载操作系统。
  • 运行时组:RT → AL。负责把控制权交给操作系统,UEFI自己退居幕后。

下面这张图把整个流程串起来了,建议你多看几遍:

UEFI启动流程七阶段总览 UEFI 启动流程七阶段总览 SEC 安全验证 PEI 内存初始化 DXE 驱动执行 BDS 启动策略 TSL OS加载器 RT 运行时 硬件初始化组 启动策略组 运行时组 AL(AL = RT + OS) 操作系统接管控制权 关键说明: • SEC 到 DXE 阶段,CPU 处于实模式或保护模式早期,代码在 Flash 中直接执行 • BDS 阶段开始,UEFI 进入全功能模式,可以使用文件系统、网络协议等 • RT 阶段后,UEFI 服务缩减为运行时服务,只保留 ExitBootServices 等少数接口

3.2 各阶段职责详解

3.2.1 SEC阶段——安全验证与初始环境

SEC是第一个执行的阶段。这时候CPU刚复位,内存还没初始化,代码只能在CPU的Cache里运行。你想想看,连内存都没有,能干什么?

SEC的主要任务就三件事:

  • 验证Boot Firmware的完整性——检查固件有没有被篡改。我遇到过一台设备,SEC校验失败直接死循环,最后发现是Flash芯片坏了。
  • 建立临时内存——利用CPU的Cache作为RAM(CAR,Cache As RAM)。没有这一步,PEI阶段连栈都建不起来。
  • 找到PEI核心入口——把控制权交给PEI阶段。

避坑指南:我曾经在调试一块开发板时,SEC阶段总是卡住。后来发现是CAR配置错了——Cache大小没对齐,导致栈溢出。记住:CAR的大小必须是Cache Line的整数倍,通常是64字节对齐。

3.2.2 PEI阶段——内存初始化

PEI阶段的核心目标就一个:把内存(DRAM)初始化好。为什么这事儿这么重要?因为后面的DXE阶段需要大量内存来加载驱动,没有内存寸步难行。

PEI阶段的工作流程大致如下:

  1. PEI核心(PEI Core)被SEC加载,开始执行。
  2. PEI模块(PEIM)逐个执行,每个模块负责一小块硬件初始化。
  3. 最关键的是内存初始化模块——它会配置内存控制器、训练内存时序。
  4. 内存初始化完成后,PEI阶段把内存信息传递给DXE阶段。

这里有个细节:PEI阶段的代码仍然在Flash里执行,但有了CAR作为临时内存,可以调用函数、使用局部变量了。

注意:内存初始化是UEFI启动中最容易出问题的环节。我见过因为内存颗粒焊接不良导致PEI阶段反复重启的案例。如果你在调试时发现启动卡在PEI阶段,优先检查内存供电、时钟信号和时序参数。

3.2.3 DXE阶段——驱动执行

DXE阶段是UEFI启动中最热闹的阶段。内存有了,各种驱动开始粉墨登场。

DXE阶段的核心机制是:

  • DXE核心(DXE Core)启动,建立系统服务表(System Table)。
  • DXE驱动(DXE Driver)被逐个加载和执行。每个驱动负责初始化一个硬件设备,比如PCIe总线、USB控制器、SATA控制器等。
  • 驱动之间通过协议(Protocol)通信。比如一个驱动初始化了PCIe总线,就会安装一个PCIe IO协议,其他驱动可以通过这个协议访问PCIe设备。

我习惯把DXE阶段比作「搭积木」——每个驱动是一块积木,积木之间通过协议接口拼接。这种设计的好处是模块化,坏处是……嗯,如果某个驱动没装好,后面的积木就搭不上。

阶段 内存状态 代码执行位置 主要功能
SEC 无(使用CAR) Flash 安全验证、建立临时内存
PEI CAR + 逐步初始化DRAM Flash 内存初始化、硬件早期配置
DXE DRAM可用 Flash + DRAM 驱动加载、协议安装、硬件枚举
BDS DRAM可用 DRAM 启动策略选择、设备枚举
TSL DRAM可用 DRAM OS加载器执行
RT DRAM可用 DRAM 退出启动服务、移交控制权

3.2.4 BDS阶段——启动策略

BDS阶段是UEFI启动的「决策者」。DXE阶段把所有硬件都初始化好了,BDS阶段来决定:从哪个设备启动?

BDS的工作流程:

  1. 读取UEFI启动管理器(Boot Manager)的配置。
  2. 按照启动顺序(Boot Order)逐个尝试启动设备。
  3. 对于每个设备,查找其上的EFI系统分区(ESP),寻找可启动的EFI应用。
  4. 找到第一个可启动的应用后,加载并执行它。

这里有个常见的坑:启动顺序配置错了,系统就会从错误的设备启动。我曾经帮一个客户排查问题,他的服务器每次启动都进Shell而不是进系统,最后发现是Boot Order里Shell排在了硬盘前面。

3.2.5 TSL阶段——OS加载器

TSL阶段就是操作系统加载器(比如Windows的bootmgfw.efi、Linux的grubx64.efi)执行的阶段。

OS加载器会做几件事:

  • 调用UEFI的协议接口,读取文件系统、加载内核镜像。
  • 准备操作系统需要的启动参数。
  • 最后调用 ExitBootServices(),告诉UEFI:我要接管了,你可以退下了。

关键点:ExitBootServices() 是UEFI启动的分水岭。调用之前,UEFI还掌握着硬件控制权;调用之后,UEFI只保留运行时服务(RT Service),操作系统开始直接管理硬件。

3.2.6 RT阶段——运行时服务

RT阶段是UEFI的「退休生活」。操作系统接管后,UEFI的大部分服务都关闭了,只保留少数运行时服务:

  • SetVariable / GetVariable——读写UEFI变量(比如启动配置)。
  • GetTime / SetTime——读取和设置系统时间。
  • ResetSystem——重启或关机。

这些服务在操作系统运行期间仍然可用。比如你在Windows里修改启动顺序,实际上就是在调用UEFI的 SetVariable。

3.2.7 AL阶段——操作系统加载完成

AL阶段严格来说不算UEFI阶段了,它是操作系统完全加载后的状态。UEFI的使命到此结束,剩下的都是操作系统的事了。

3.3 各阶段的时间分布

在实际项目中,启动时间是个敏感指标。我统计过一些典型设备的启动时间分布:

阶段 典型耗时 优化空间
SEC 10-50ms 小(主要是硬件等待)
PEI 100-500ms 中(内存训练时间可优化)
DXE 200-2000ms 大(驱动加载顺序、并行化)
BDS 50-300ms 中(启动顺序、超时设置)
TSL 500-5000ms 大(OS加载器效率)

你看,DXE和TSL是耗时大户。如果你需要优化启动时间,优先从这两个阶段下手。

个人经验:我优化过一台嵌入式设备的启动时间,从12秒压到了3秒。主要手段是:DXE阶段把不必要的驱动延迟加载,BDS阶段缩短超时时间,TSL阶段用更轻量的OS加载器。每一步都不难,但组合起来效果惊人。

3.4 总结

UEFI启动流程,说白了就是一条从硬件到软件的接力赛。SEC起跑,PEI热身,DXE加速,BDS选方向,TSL冲刺,RT交接,AL冲线。

每个阶段都有明确的职责,也有常见的坑。你只要记住:越早的阶段越接近硬件,越晚的阶段越接近操作系统。遇到启动问题,先判断卡在哪个阶段,然后对症下药。