UEFI-PEI 阶段的深层介绍 - 阿源

一、PEI Core 与 PEIMs

PEI Core:是PEI阶段的核心引擎,负责寻找,加载和执行各种PEIM。PEI Core首先首先运行一个小的固定的SEC阶段的代码,这段代码通常使用CPU缓存作为临时内存来运行。一旦找到并初始化了真正的系统内存,PEI核心就会把执行权交给永久内存管理器,从而结束使用CAR。

PEIMs:这些是实际执行硬件初始化任务的功能模块。执行芯片组、内存控制器、桥接器和核心主板组件的最低限度初始化。关键任务是初始化 DRAM,使其可用于后续的启动阶段。创建 Hand-Off Blocks (HOB) 列表,这是一个数据结构,用于保存所有已发现的硬件状态、配置信息和资源映射,并将这些信息传递给下一个启动阶段——DXE 阶段。

下面对这两部分的流程进行更具体的介绍:

PEI Core 主要是提供一个基本的执行环境然后找到并执行 PEIMs,它才是真正干活的。

关键职责 具体任务 对应的概念/API
A. 环境建立 在 SEC 阶段交接后,立即建立 PEI Core 自身的堆栈和数据结构(最初在 CAR 中)。 CAR (Cache As RAM)
B. 服务提供 提供 PEI 阶段的基本服务(如内存分配、HOB 创建)。 PEI Services Table
C. PEIM 调度 搜索固件存储空间 (FV) 以发现待执行的 PEIM 映像,并按顺序执行它们。 FV (Firmware Volume)
D. 内存转换 一旦 DRAM 被初始化,它将所有 PEI 结构从 CAR 迁移到永久内存中。 PeiServicesInstallPeiMemory()
E. 阶段交接 所有 PEIMs 执行完毕后,构建最终的 HOB 列表,并跳转到 DXE Core。 DXE IPL (Initial Program Load)

PEIMs 是实际的工作执行者,它们通过“提供 PPI”(PEIM-to-PEIM Interface)和“注册 Notify”机制来完成工作和进行协作。

PPI 和 Notify 是什么

关键职责 具体任务 对应的机制
A. 硬件初始化 初始化芯片组、时钟、电源管理等关键硬件。 PCHInitPeim, MemoryInitPeim
B. 资源发现 找到并配置系统内存 (DRAM),并报告给 PEI Core。 Memory Init PEIM
C. 数据发布 创建并安装 PPI (PEI Protocol Interface),让其他 PEIM 知道某个服务或数据已可用。 PeiServicesInstallPpi()
D. 阶段准备 收集硬件数据,创建 HOB,将配置信息传递给 DXE。 PeiServicesCreateHob()

伪代码:

// -------------------------------------------------------------------------
// 阶段 0: 接管和临时环境建立 (运行在 CAR/Cache As RAM)
// -------------------------------------------------------------------------
Function PeiCoreMain(SecCoreData, HandoffData)// 1. 设置 PEI Services TablePeiServicesTable = InitializePeiServicesTable()// 2. 初始化临时堆栈和临时堆 (基于CAR)InitializePeiCoreStack(SecCoreData.StackBase)InitializePeiTemporaryMemoryHeap() // 3. 创建第一个 HOB: Handoff Information HOBCreateHob(HOB_TYPE_HANDOFF, HandoffData)// 4. 初始化 PEIM 调度器PeimDispatcher = InitializePeimDispatcher()// 5. 开始 PEIM 主循环Call PeimExecutionLoop(PeimDispatcher, PeiServicesTable)// 6. 退出 PEI 阶段Call PeiCoreExit() End Function// -------------------------------------------------------------------------
// 阶段 1: PEIM 调度与执行主循环
// -------------------------------------------------------------------------
Function PeimExecutionLoop(Dispatcher, Services)// 循环条件: 只要在 Firmware Volume (FV) 中还能找到未执行的 PEIMWhile (Dispatcher.FindNextPeimImage() != NULL)CurrentPeim = Dispatcher.FindNextPeimImage()// 1. 加载 PEIM 代码CurrentPeim.Image = Services.FfsFindPeim(CurrentPeim.FilePath)// 2. 执行 PEIM 的入口点 (EntryPoint)// 实际的硬件初始化和 PPI 安装都在这里发生Status = CurrentPeim.EntryPoint(CurrentPeim.Image, Services)If (Status == EFI_SUCCESS)MarkPeimAsExecuted(CurrentPeim)// 3. 检查是否有内存初始化发生If (Services.IsMemoryInstalled() == TRUE)// 内存初始化 PEIM 已经运行,进入关键的转换流程Call PeimMemoryTransition() // 由于内存转换,代码和数据可能已被迁移,需要重新启动循环// 通常会重新设置 PEI Core 的环境指针Return // 退出当前循环,进入下一个 PEI 阶段End IfElseLog(ERROR, "PEIM failed to execute: " + CurrentPeim.Name)End IfEnd WhileEnd Function// -------------------------------------------------------------------------
// 阶段 2: 内存转换 (最关键的一步)
// -------------------------------------------------------------------------
Function PeimMemoryTransition()// 1. 发现新安装的永久内存信息ResourceHob = Services.GetHobByType(HOB_TYPE_RESOURCE_DESCRIPTOR)// 2. 告诉 PEI Services Table 内存已安装Services.PeiServicesInstallPeiMemory() // 3. 将 PEI Core 自身的数据、PEIMs 和 HOB 列表//    从临时的 CAR 空间迁移到新的永久内存中MigratePeiCoreDataToDRAM()// 4. 更新 Services Table 和所有 PEIMs 的指针UpdatePointersToNewDRAMLocations()// 5. 重新进入 PeimExecutionLoop,寻找需要二次执行的 PEIMs (Post-Memory PEIMs)Call PeimExecutionLoop(...)End Function// -------------------------------------------------------------------------
// 阶段 3: 退出 PEI 阶段
// -------------------------------------------------------------------------
Function PeiCoreExit()// 1. 确保所有 HOB 都已创建,生成最终的 HOB 列表FinalizeHobList()// 2. 查找并加载 DXE IPL PEIM (Initial Program Load)DxeIplPeim = FindPeim("DxeIpl.inf")// 3. 执行 DXE IPL PEIM,其工作是加载 DXE Core 映像//    并最终将控制权交给 DXE CoreDxeIplPeim.EntryPoint(HobListAddress) // 永远不会返回 (Never Returns), 因为控制权已转交给 DXE CoreEnd Function
  • PEI Core 负责整个流程的框架和调度(PeiCoreMain)。

  • PEIM 在 PeimExecutionLoop 中被加载和执行,完成实际的硬件配置,是真正干活的。

  • 内存转换是分水岭。 PeimMemoryTransition 标志着系统从使用 CPU 缓存运行(CAR)过渡到使用真正的 DRAM 内存。这是整个 PEI 阶段最关键的一步。

  • HOB 是最终阶段结果和目的。最终的 HOB 列表是 PEI 阶段工作的产物,作为参数传递给 DXE 阶段。

二、PEIMs 在 EDKII 中的体现

第一节中我们提到,PEI 会搜索固件卷(FV)中待执行的的 PEIM 镜像(Imaga),并按照顺序执行。这里可以先简单把 FV 理解为文件夹,文件夹中存放着特定的功能性程序,也就是 PEIM 镜像。下面举个例子介绍 PEIMs 在EDKII 工程中的形式。

在 EDKII 中,PEIM 本质上就是一个模块(Module),其通常被编译为.efi适用于 PEI 的 PE/COFF 可执行文件,且最终被放入 FV 中,一般是 FV/PEIFV 或 FV/MAINFV

有关 EDKII 工程结构的介绍异步此博客。一般情况下,PEIM 的源代码位于某个 Package 的目录中,典型路径(以 MdeModulePkg 中的示例为例):

edk2/└── MdeModulePkg/└── Universal/└── PCD/└── Pei/├── Pcd.inf     ← PEIM 的 INF 文件(最重要)├── Pcd.c       ← 源码└── Pcd.h

➡️ 所有 PEIM 模块的特征是:INF 文件中有:

[Defines]MODULE_TYPE = PEIM

有关模块的概念后续会补充,前面章节中有关于MdeModulePkg的介绍以及单独编译某模块的方法,还有模块的配置描述文件inf文件的简单介绍,感兴趣可以移步!

PEIM 是如何被编译的呢?首先在 EDKII 工程中,我们最终的目的是编译某个平台的固件文件,比如虚拟机使用的 ovmf.fd,其平台描述文件位于OvmfPkg/OvmfPkgX64.dsc。具体内容点击此处在附录中有介绍。这个平台描述文件会定义哪些 PEIM 模块会被编译。fdf文件OvmfPkg/OvmfPkgX64.fdf描述了最终的固件镜像是如何布局的,因此PEIM 是否进入固件由平台 FDF 文件决定。

fdf文件的介绍后续会另外补充!

例如 OvmfPkgX64.dsc 内会有:

[MdeModulePkg/Universal/PCD/Pei/Pcd.inf]

只要在 .dsc 里被包含,构建系统就会编译它。

编译 ovmf 固件镜像时

build -a X64 -t GCC5 -p OvmfPkg/OvmfPkgX64.dsc

编译操作自动会:找到所有 INF(包括 PEIM),生成 .obj,链接出 PEIM 的 .efi(PEI 可执行)。

EDK II 的编译输出统一放在 Build/ 目录中。比如

Build/OvmfX64/DEBUG_GCC5/X64/MdeModulePkg/Universal/PCD/Pei/Pcd/OUTPUT/Pcd.efi

PEIM 在最终固件镜像(FV)里:

Build/OvmfX64/DEBUG_GCC5/FV/├── OVMF.fd├── OVMF_CODE.fd├── OVMF_VARS.fd└── PEIFV.Fv 			# efi 文件会被工具打包进 .FV 文件。

可以查看 FDF 文件,例如 OvmfPkgX64.fdf:

FV = PEIFV {INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
}

这表示 Pcd.inf (一个 PEIM)会放入该 Firmware Volume。

三、PEI Services Table 介绍

在 PEI Core 以及伪代码中涉及到 PEI Services Table 这里简单介绍一下。

PEI Services Table 本质上是一个指向一系列函数指针的结构体。它允许 PEIMs 访问底层 PEI Core 实现的服务,而无需知道这些服务的具体位置和内部细节。通俗来说就相当于执行具体任务的 PEIM 能够通过 PEI Services Table 调用 PEI Core 中的函数。

PEI Services Table 结构通常包含多个部分,其中最重要的就是核心服务辅助服务的指针:

  • 核心服务 (Core Services): 最基础的服务,在整个 PEI 阶段都可用。
    • AllocatePages / AllocatePool: 内存分配。
    • CreateHob: 创建 Hand-Off Block,将数据传递给 DXE。
    • InstallPpi: 安装 PPI (PEIM-to-PEIM Interface),用于 PEIM 间通信。
    • LocatePpi: 查找其他 PEIM 已经安装的 PPI。
  • 启动服务 (Boot Services): 与启动流程管理相关的服务。
    • FfsFindNextPeim: 用于在 Firmware Volume (FV) 中查找下一个要执行的 PEIM。
    • NotifyPpi: 注册一个通知函数,当某个 PPI 被安装时触发。

如上文中的伪代码所示,这个服务表在 PEI Core 启动时(在 SEC 阶段交接之后)被初始化,最初的实现可能非常精简,使用的都是临时内存(CAR/Cache As RAM)。当 PEI Core 加载并执行一个 PEIM 时,它会将 PEI Services Table 的地址作为参数传递给该 PEIM 的 EntryPoint 函数。伪代码如下,对应上文伪代码中的 41 行。

// PEIM Entry Point 函数的签名
Function PeimEntryPoint(IN PeiFileHandle,IN **PeiServicesTablePointer  // 这里的双指针指向服务表
)// PEIM 现在可以使用这个表来调用服务Status = PeiServicesTablePointer->CreateHob(...)Status = PeiServicesTablePointer->InstallPpi(...)
End Function

四、HOB的详细介绍,PEI 到 DXE阶段

HOB 的主要任务是将 PEI 阶段发现、初始化和配置的所有系统信息,以一种标准化的格式,安全可靠地传递给接下来运行的 DXE 阶段。PEI 阶段创建的 HOB 并不是一个单一的数据块,而是一个由多个独立 HOB 描述符串联而成的链表,称为 HOB 列表 (HOB List)

核心作用

  • 状态传递: 记录内存、CPU、芯片组等硬件的状态和配置。
  • 资源映射: 提供系统内存和 I/O 资源的详细布局,供 DXE 阶段的内存管理器和驱动程序使用。
  • 服务注册: 记录 PEI 阶段可能提供的某些特殊服务或数据。

每个 HOB 都是由一个标准化的 HOB 描述符头部 (EFI_HOB_GENERIC_HEADER) 开始,紧接着是该 HOB 特定类型的数据。

字段 描述
Type HOB 的类型(见下文)。
Length 整个 HOB 结构的长度(包括头部和数据)。
Reserved 保留字段。

HOB 列表中的每一个块都属于一个特定的类型,用于传递特定的信息。以下是几种最关键的 HOB 类型:

HOB 类型 (Type) 结构名称 (例如) 传递的信息
EFI_HOB_TYPE_RESOURCE_DESCRIPTOR EFI_HOB_RESOURCE_DESCRIPTOR 内存和 I/O 资源的详细列表。 这是 DXE 内存管理器建立内存映射的基础。
EFI_HOB_TYPE_MEMORY_ALLOCATION EFI_HOB_MEMORY_ALLOCATION 记录 PEI 阶段已分配的内存块(例如,用于存储 PEI 堆栈、PEI 核心、或特定的数据结构)。
EFI_HOB_TYPE_HANDOFF EFI_HOB_HANDOFF_INFO_TABLE 列表的第一个 HOB。 包含 PEI 和 DXE 之间的手递手信息,例如:启动模式、SEC 阶段的堆栈基址等。
EFI_HOB_TYPE_CPU EFI_HOB_CPU CPU 特定的信息,例如:CPU 的最大地址空间、处理器数量等。
EFI_HOB_TYPE_GUID_EXTENSION EFI_HOB_GUID_TYPE 允许平台或 OEM 定义自定义数据,通过 GUID 识别,用于传递非标准化的信息。

在 PEI 阶段,当一个 PEIM (PEI Module) 完成初始化或发现某个资源时,它会调用 PEI 服务表中的 API 来创建 HOB,将其添加到 HOB 列表的末尾。

主要的 HOB 创建服务是:

  • PeiServicesCreateHob(): 用于创建任何类型的 HOB。

  • PeiServicesInstallPeiMemory(): 专用于创建第一个内存资源 HOB,标志着永久内存初始化完成。

HOB 如何从 PEI 传递到 DXE,这是 HOB 机制的核心价值:

  1. PEI 结束: PEI 核心在完成所有 PEIM 的执行后,会调用 PeiCoreExitTransition() 函数。
  2. Handoff Block 准备: 在退出前,PEI 核心确保 HOB 列表已经最终化。
  3. 跳转到 DXE: PEI 核心最后会执行一个特殊的 PEIM,该 PEIM会加载 DXE 核心的映像,并使用特殊的跳转指令(通常是 JMPCALL)进入 DXE 阶段的入口点 (DxeCoreEntry)。
  4. 传递参数: 在跳转时,HOB 列表的起始地址会被作为参数(通常通过 CPU 寄存器)传递给 DXE 核心。

DXE 阶段如何使用 HOB。DXE 核心是 HOB 列表的主要消费者

  1. 初始化 DXE 核心: DXE 核心的入口点接收到 HOB 列表的地址。它首先解析这个列表,建立其内存管理器
  2. 建立内存映射: 它利用 EFI_HOB_TYPE_RESOURCE_DESCRIPTOR HOB 中包含的内存信息,来建立自己的内存映射,区分可用内存和已占用内存。
  3. 提取配置信息: DXE 驱动和 DXE 服务可以使用 EfiGetSystemConfigurationTable() 或直接遍历 HOB 列表来查找特定的配置信息或自定义数据。
  4. 销毁(逻辑上): 一旦 DXE 核心完成了初始化并建立了自己的资源管理机制,HOB 列表的历史使命就完成了。它所占据的内存通常会被重新声明为 DXE 阶段可用的系统内存。

Steady Progress

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/970514.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

01组-选题与需求分析报告

博客链接:https://www.cnblogs.com/Cindy051010/p/19244480 一、团队集结 1.1 介绍每位组员擅长的编程技术、拟担任的软工角色及拟完成的任务分工等,内容形式不限(3分)成员 擅长的编程技术 软工角色 任务分工龙玉凤…

软工第二次团队作业

成群结队第二次团队作业 原型设计+概要设计作业总览项目 内容作业所属课程 软件工程作业要求 作业要求作业目标 完成项目原型设计与概要设计,形成交互原型、UML模型、数据库结构,并制定开发计划与分工安排。团队名称…

2025市政管道/家装管材优质厂家最新TOP5推荐:云南昆明荣德福领衔,优质PVC管道/管材品牌,聚焦排水家庭/市政管等场景

随着国内基础设施建设与城镇化进程的快速推进,市政管道、家装管材及PVC管道市场需求持续攀升。本榜单基于技术研发实力、区域市场覆盖、产品质量控制、服务网络密度四大维度,结合2025年《中国塑料管道行业发展报告》…

251120

251120惩罚源源不断,欲望肆意横生,没有尽头和终点,忘掉初心和起点,气喘吁吁,作茧自缚。

2025家装管材及市政管道厂家怎么选?昆明荣德福,从PVC管材到排水家装/市政管,静音防堵+安装便捷,绿色建材认证+规模化产能实力上榜

随着城市化进程的加速和居民生活品质的提升,优质的管材产品在建筑工程与家居装修中的重要性日益凸显。无论是城市供排水系统的安全运行,还是家庭用水的健康保障,都离不开高品质管材的支撑。在2025年的管材市场中,昆…

20232419 2025-2026-1 《网络与系统攻防技术》实验六实验报告

1.实验内容 本实践目标是掌握metasploit的用法。要对主机进行前期渗透、Vsftpd源码包后门漏洞(21端口)、SambaMS-RPC Shell命令注入漏洞(端口139)、Java RMI SERVER命令执行漏洞(1099端口)以及PHP CGI参数执行注…

22年副省daan

1、根据“给定资料1”,请你谈谈B公司的案例为企业科技创新提供了哪些启示。(10分) 要求:分析全⾯,条理清晰,不超过200字。 2、根据“给定资料2”,请你谈谈G省在推进粮⻝产业发展中遇到了哪些问题,并逐⼀说明这…

20251119 之所思 - 人生如梦

20251119 之所思做的好的事情:1. Nov 17th因为加班太晚,洗完澡已经接近一点半,然后整个晚上就失眠了,熬到早上五点半,想到继续熬也痛苦,然后起床开始跑步,第一次在完全天黑的情况开始跑步,然后看到了天慢慢的…

11.119

今天上了离散数学,学了新知识

2025最新云南旅行社TOP5推荐:深耕昆明等云南全域,自驾游 + 本地游 + 个性化定制,解锁深度体验引领个性化旅游新体验

随着旅游市场的蓬勃发展,个性化、定制化旅游需求日益增长,选择一家优质的旅行社成为游客出行的关键。本榜单基于服务质量、线路创新、客户满意度、安全保障四大维度,结合《2025中国旅游行业发展报告》及游客真实反馈…

第30天(中等题 二分查找)

打卡第三十天 2道中等题题目:思路:因为正方形中心固定,所以边长越大,包括的点也就越多。问题转换为求正方形的最大边长。若正方形的边长为2r,则所有横坐标的绝对值小于等于 r,且纵坐标的绝对值也小于等于 r 的点…

2025云南旅行社首选——中青国旅“用心陪着你”,定制游+自驾游杜绝套路,纯净体验

随着大众旅游消费升级与个性化出行需求的日益增长,选择专业可靠的旅行社成为提升旅行体验的关键。在2025年云南旅游市场中,云南中青国际旅行社(集团)有限公司(简称“中青国旅”)凭借深厚的品牌积淀与全方位的服务…

Debian 12/13可用的华宇拼音输入法

在 铜豌豆Linux 看到了 华宇拼音输入法,Windows下我一直用它,很好用。 在Debian 12下装不上,需要libqt4-declarative,和Qt5啥的冲突。 下载了libqt4-declarative-4.8.7-alt26.x86_64.rpm 1.1MB, apt download com…

拆解一个真实电商项目:微服务架构中的服务治理与性能优化

基于真实电商场景,深入解析微服务架构设计。涵盖Nacos服务治理、Ribbon负载均衡、分布式缓存等核心技术,剖析单体到分布式的演进逻辑。从架构演变到组件选型,从服务拆分到性能调优,讲解分布式系统设计中的常见问题…

VB6版Dll文件注册器 - 开源研究系列文章 - 个人小作品

VB6版Dll文件注册器 - 开源研究系列文章 - 个人小作品Posted on 2025-11-20 00:00 lzhdim 阅读(0) 评论(0) 收藏 举报 这次继续整理和重构VB6的一些小作品。这个小作品是一个Dll文件进行注册的小应用。主要…

win10里面的中文输入法在左上角的带有绿色箭头

知乎:求教怎么关闭win10里面的中文输入法在左上角的带有绿色箭头的候选框? win11用户, 在编辑文字的时候发现自己输入法的框跑到电脑左上角去了,没有跟随着我们的打字光标,这要怎么办? B站也有人发这个问题 : mo…

[Flink] Apache Stream Park : 一站式的流处理计算开发运管平台

1 概述:Apache Stream Park Apache Stream Park在实时处理领域,Apache Spark™ 和 Apache Flink 代表着巨大的进步,尤其是 Flink,它被广泛视为下一代大数据流计算引擎,而我们在使用 Apache Flink 和 Apache Spark…

linux . profile修改

在 Linux 系统中,.profile 文件是用户登录时执行的初始化脚本,通常位于 ~/.profile 或 ~/.bash_profile(取决于使用的 shell,如 bash 或 zsh)。修改 .profile 文件可以自定义用户登录时的行为,比如设置环境变量、…

linux -xr

您提到的“linux -xr”可能是输入错误或不完整的命令。让我为您解释几个可能的含义:1. linux -xr(可能的错误输入)如果您是想输入 ls -xr,那么: ls -xr-x:递归地处理文件,即对目录中的文件进行排序。 -r:反转排…

linux echo gt;命令

在 Linux 中,echo 是一个用于输出字符串的命令,而 > 是一个重定向操作符,用于将命令的输出重定向到指定的文件。 命令解释: echo + #引号 + hello + #引号 + > file.txtecho + #引号 + hello + #引…