UEFI系统的启动过程(1)

UEFI系统的启动遵循UEFI平台初始化(PlatformInitialization)标准。UEFI系统从加电到关机可分为7个阶段:

SEC(安全验证)→PEI(EFI前期初始化)→DXE(驱动执行环境)

→BDS(启动设备选择)→TSL(操作系统加载前期)

→RT(Run Time)

→AL(系统灾难恢复期)

图1-2展示了UEFI系统从加电到关机的7个阶段(以图中竖线为界)。

前三个阶段是UEFI初始化阶段,DXE阶段结束后UEFI环境已经准备完毕。

BDS和TSL是操作系统加载器作为UEFI应用程序运行的阶段。

操作系统加载器调用ExitBootServices()服务后进入RT阶段,RT阶段包括操作系统加载器后期和操作系统运行期。

当系统硬件或操作系统出现严重错误不能继续正常运行时,固件会尝试修复错误,这时系统进入AL期。但PI规范和UEFI规范都没有规定AL期的行为。“?”号表示其行为由系统供应商自行定义。

1.SEC阶段

SEC(Security Phase)阶段是平台初始化的第一个阶段,计算机系统加电后进入这个阶段。

(1)SEC阶段的功能

UEFI系统开机或重启进入SEC阶段,从功能上说,它执行以下4种任务。

1)接收并处理系统启动和重启信号:系统加电信号、系统重启信号、系统运行过程中的严重异常信号。

2)初始化临时存储区域:系统运行在SEC阶段时,仅CPU和CPU内部资源被初始化,各种外部设备和内存都没有被初始化,因而系统需要一些临时RAM区域,用于代码和数据的存取,我们将之称为临时RAM,以示与内存的区别。这些临时RAM只能位于CPU内部。最常用的临时RAM是Cache,当Cache被配置为no-eviction模式时,可以作为内存使用,读命中时返回Cache中的数据,读缺失时不会向主存发出缺失事件;写命中时将数据写入Cahce,写缺失时不会向主存发出缺失事件,这种技术称为CAR(Cache As Ram)。

3)作为可信系统的根:作为取得对系统控制权的第一部分,SEC阶段是整个可信系统的根。SEC能被系统信任,以后的各个阶段才有被信任的基础。通常,SEC在将控制权转移给PEI之前,可以验证PEI。

4)传递系统参数给下一阶段(即PEI):SEC阶段的一切工作都是为PEI阶段做准备,最终SEC要把控制权转交给PEI,同时要将现阶段的成果汇报给PEI。汇报的手段就是将如下信息作为参数传递给PEI的入口函数。

系统当前状态,PEI可以根据这些状态判断系统的健康状况。

可启动固件(Boot Firmware Volume)的地址和大小。

临时RAM区域的地址和大小。

栈的地址和大小。

(2)SEC阶段执行流程

上面介绍了SEC的功能,下面再来看看SEC的执行流程,如图1-3所示。

UEFI系统的启动过程(2)

以临时RAM初始化为界,SEC的执行又分为两大部分:临时RAM生效之前称为Reset Vector阶段,临时RAM生效后调用SEC入口函数从而进入SEC功能区。

其中Reset Vector的执行流程如下。

1)进入固件入口。

2)从实模式转换到32位平坦模式(包含模式)。

3)定位固件中的BFV(Boot Firmware Volume)。

4)定位BFV中的SEC映像。

5)若是64位系统,从32位模式转换到64位模式。

6)调用SEC入口函数。

下面的代码描述了从固件入口Reset Vector到SEC入口函数的执行过程:

在Reset Vector部分,因为系统还没有RAM,因而不能使用基于栈的程序设计,所有的函数调用都使用jmp指令模拟。OneTimeCall是宏,用于模拟call指令。例如,宏调用OneTimeCall EarlyInit16,如图1-4所示。

进入SEC功能区后,首先利用CAR技术初始化栈,初始化IDT,初始化EFI_SEC_PEI_HAND_OFF,将控制权转交给PEI,并将EFI_SEC_PEI_HAND_OFF传递给PEI。

不同的硬件平台,SEC代码会有不同的实现方式,但大致执行过程相似。下面以OVMF(具体介绍参见第2章)为例,介绍SEC功能区的执行过程。

UEFI系统的启动过程(3)

2.PEI阶段

PEI(Pre-EFI Initialization)阶段资源仍然十分有限,内存到了PEI后期才被初始化,其主要功能是为DXE准备执行环境,将需要传递到DXE的信息组成HOB(Handoff Block)列表,最终将控制权转交到DXE手中。PEI执行流程如图1-5所示。

从功能上讲,PEI可分为以下两部分。

PEI 内核(PEI Foundation):负责PEI基础服务和流程。

PEIM(PEI Module)派遣器:主要功能是找出系统中的所有PEIM,并根据PEIM之间的依赖关系按顺序执行PEIM。PEI阶段对系统的初始化主要是由PEIM完成的。

每个PEIM是一个独立的模块,模块的入口函数类型定义如下所示:

typedef EFI_STATUS(EFIAPI *EFI_PEIM_ENTRY_POINT2)(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES  **PeiServices);

通过PeiServices,PEIM可以使用PEI阶段提供的系统服务,通过这些系统服务,PEIM可以访问PEI内核。PEIM之间的通信通过PPI(PEIM-to-PEIM Interfaces)完成。

PPI与DXE阶段的Protocol类似,每个PPI是一个结构体,包含了函数指针和变量,例如:

struct _EFI_PEI_DECOMPRESS_PPI {EFI_PEI_DECOMPRESS_DECOMPRESS Decompress;}  
extern EFI_GUID   gEfiPeiDecompressPpiGuid; 

每个PPI都有一个GUID。根据GUID,通过PeiServices的LocatePpi服务可以得到GUID对应的PPI实例。

UEFI的一个重要特点是其模块化的设计。模块载入内存后生成Image。Image的入口函数为_ModuleEntryPoint。PEI也是一个模块,PEI Image的入口函数_ModuleEntryPoint,位于MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c。_ModuleEntryPoint最终调用PEI模块的入口函数PeiCore,位于MdeModulePkg/Core/Pei/PeiMain/PeiMain.c。进入PeiCore后,首先根据从SEC阶段传入的信息设置Pei Core Services,然后调用PeiDispatcher执行系统中的PEIM,当内存初始化后,系统会发生栈切换并重新进入PeiCore。重新进入PeiCore后使用的内存为我们所熟悉的内存。所有PEIM都执行完毕后,调用PeiServices的LocatePpi服务得到DXE IPL PPI,并调用DXE IPL PPI的Entry服务,这个Entry服务实际上是DxeLoadCore,它找出DXE Image的入口函数,执行DXE Image的入口函数并将HOB列表传递给DXE。

3.DXE阶段

DXE(Driver Execution Environment)阶段执行大部分系统初始化工作,进入此阶段时,内存已经可以被完全使用,因而此阶段可以进行大量的复杂工作。从程序设计的角度讲,DXE阶段与PEI阶段相似,执行流程如图1-6所示。

UEFI系统的启动过程(4)

与PEI类似,从功能上讲,DXE可分为以下两部分。

DXE内核:负责DXE基础服务和执行流程。

DXE派遣器:负责调度执行DXE 驱动,初始化系统设备。

DXE提供的基础服务包括系统表、启动服务、Run Time Services。

每个DXE驱动是一个独立的模块,模块入口函数类型定义为:

typedef EFI_STATUS(EFIAPI *EFI_IMAGE_ENTRY_POINT)(IN  EFI_HANDLE ImageHandle,  IN  EFI_SYSTEM_TABLE *SystemTable); 
 

DXE驱动之间通过Protocol通信。Protocol是一种特殊的结构体,每个Protocol对应一个GUID,利用系统BootServices的OpenProtocol,并根据GUID来打开对应的Protocol,进而使用这个Protocol提供的服务。

当所有的Driver都执行完毕后,系统完成初始化,DXE通过EFI_BDS_ARCH_PROTOCOL找到BDS并调用BDS的入口函数,从而进入BDS阶段。从本质上讲,BDS是一种特殊的DXE阶段的应用程序。

4.BDS阶段

BDS(Boot Device Selection)的主要功能是执行启动策略,其主要功能包括:

初始化控制台设备。

加载必要的设备驱动。

根据系统设置加载和执行启动项。

如果加载启动项失败,系统将重新执行DXE dispatcher以加载更多的驱动,然后重新尝试加载启动项。

BDS策略通过全局NVRAM变量配置。这些变量可以通过运行时服务的GetVariable()读取,通过SetVariable()设置。例如,变量BootOrder定义了启动顺序,变量Boot####定义了各个启动项(####为4个十六进制大写符号)。

用户选中某个启动项(或系统进入默认的启动项)后,OS Loader启动,系统进入TSL阶段。

5.TSL阶段

TSL(Transient System Load)是操作系统加载器(OS Loader)执行的第一阶段,在这一阶段OS Loader作为一个UEFI应用程序运行,系统资源仍然由UEFI内核控制。当启动服务的ExitBootServices()服务被调用后,系统进入Run Time阶段。

TSL阶段之所以称为临时系统,在于它存在的目的就是为操作系统加载器准备执行环境。虽然是临时系统,但其功能已经很强大,已经具备了操作系统的雏形,UEFI Shell是这个临时系统的人机交互界面。正常情况下,系统不会进入UEFI Shell,而是直接执行操作系统加载器,只有在用户干预下或操作系统加载器遇到严重错误时才会进入UEFI Shell。

6.RT阶段

系统进入RT(Run Time)阶段后,系统的控制权从UEFI内核转交到OS Loader手中,UEFI占用的各种资源被回收到OS Loader,仅有UEFI运行时服务保留给OS Loader和OS使用。随着OS Loader的执行,OS最终取得对系统的控制权。

7.AL阶段

在RT阶段,如果系统(硬件或软件)遇到灾难性错误,系统固件需要提供错误处理和灾难恢复机制,这种机制运行在AL(After Life)阶段。UEFI和UEFI PI标准都没有定义此阶段的行为和规范。

(转)UEFI系统的启动过程相关推荐

  1. UEFI系统的启动过程

    UEFI系统的启动遵循UEFI平台初始化(PlatformInitialization)标准.UEFI系统从加电到关机可分为7个阶段: SEC(安全验证)→PEI(EFI前期初始化)→DXE(驱动执行 ...

  2. UEFI原理与编程实践--UEFI系统的启动过程

    看图粗略说一下: SEC: 安全验证阶段,这个阶段,需要用Assembly做一些 C 无法处理的工作,C语言无法处理CPU的特殊寄存器.让CPU进入Protected Mode(Flat Mode)的 ...

  3. Android系统的启动过程

    Android系统的启动过程可以简单地总结为以下几个流程: 加载BootLoader -> 初始化内核 -> 启动init进程 -> init进程fork出Zygote(孵化器)进程 ...

  4. Linux系统的启动过程

    下面是整个Linux系统的启动过程: Linux Boot Step Start BIOS ​ ​ grub/lilo ​ ​ Kernel boot ​ ​ init rc.sysinit ​ ​ ...

  5. linux启动过程剖析,分析Linux系统的启动过程

    导读 一直使用linux系统,却对系统启动过程及系统初始化和各种服务的启动不太清楚.今天终于搞明白整个是怎么一回事了.本来想自己写篇文章,刚好在网上看到一篇不错的介绍,很详细,就直接拿来了. Linu ...

  6. Linux系统的启动过程(转)

    下面是整个Linux系统的启动过程:   Linux Boot Step Start BIOS grub/lilo Kernel boot init rc.sysinit rc mingetty lo ...

  7. Android内核开发:图解Android系统的启动过程

    本文是<Android内核开发>系列的第六篇文章,前面的几篇文章介绍了Android内核开发相关的基础知识,包括:Android源码的下载.版本和分支介绍.编译和烧写等等,从本文起就要开始 ...

  8. linux服务器知识学习:了解Linux系统的启动过程

    linux启动时我们会看到许多启动信息. Linux系统的启动过程 其过程可以分为5个阶段: 内核的引导. 运行 init. 系统初始化. 建立终端 . 用户登录系统. 点击进入原文(图文版)地址 一 ...

  9. u盘版linux initramfs,探索Linux系统的启动过程

    阅读目录 引言 Linux启动过程概述 Grub加载Linux内核和initramfs 探索initramfs文件的方法 基于systemd的init系统 进入图形界面 这篇文章有点长,我花了大约两个 ...

最新文章

  1. 刘宇与小白健康:一个理想主义者的互联网“众包”实践
  2. poj 1664 放苹果 DPDFS
  3. wxWidgets:wxFontMapper类用法
  4. 【C语言项目】贪吃蛇游戏(上)
  5. FireBug实用指南
  6. LeetCode 968. 监控二叉树(DFS)
  7. Oracle下载 OPatch
  8. 数字图像处理之数字图像频率空间
  9. 学习python自动化测试的好处
  10. java 获取农历日期
  11. 2020年7月19日训练总结
  12. 谷歌浏览器离线安装crx插件方法
  13. 强化学习之贝尔曼方程
  14. 阻抗匹配50欧姆的由来
  15. 了解电子邮件:E-Mail从入门到精通
  16. 路由器的工作原理(计算机网络-网络层)
  17. 1、查询姓名中包含‘u’字母的员工记录2、同名去重3、字段计算
  18. moviepy第2天|对视频添加圆圈渐变大小的结尾及文字
  19. 使用Java生成带有下划线字体的文字
  20. 《网管员必读——网络应用》(第2版)试读样章下载

热门文章

  1. Java获取WiFi ssid_如何在Flutter中获取当前连接的wifi的wifi名称(SSID)
  2. HP2132打印机简易说明
  3. 记一次muse-ui 使用
  4. M480 EMAC驱动02-IP101G测试
  5. 计蒜客——恋爱纪念日(学习如何格式化打印日期)
  6. 好嗨呦 之 快速部署 Spring Boot 项目
  7. Docker 图片水印中文乱码显示为方框, 设置Docker容器字体
  8. 在.NET5 中读取Excel文件,评估下参加神秘献祭会的几位子民
  9. 微软官方原版WindowsXP Pro With Sp2简体中文VOL版
  10. OGL纹理之纹理过滤器和多级渐进纹理mipmap