PEI是在SEC阶段之后的下一个阶段。它实现了初始化内存(UEFI第二阶段)。
虽然SEC阶段对CPU和CPU内的资源进行了初始化,但是PEI阶段可用的资源依旧十分有限,该阶段对内存进行初始化,主要功能是为DXE阶段准备执行环境,将所需要传递给DXE的信息组成HOB(Hand Off Block)列表,最终将控制权转交到DXE。
整体流程
- PEI Image的入口函数位_ModuleEntryPoit,该函数最终调用PEI模块的入口函数PeiCore。
VOID EFIAPI PeiCore ( IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreDataPtr, IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, IN VOID *Data )
- 进入PeiCore后,先根据SEC阶段传入的信息初始化PS(PEI Core Service)。
// // Initialize PEI Core Services // InitializeMemoryServices (&PrivateData, SecCoreData, OldCoreData);
- 信息设置完成后,调用PeiDispatcher执行PEIM,准备HOB列表。
// // Call PEIM dispatcher // PeiDispatcher (SecCoreData, &PrivateData);
- 内存初始化。
- 内存初始化后,系统会发生栈切换并重新进入PeiCore,重新进入到PeiCore后使用的内存是我们熟悉的内存。
- 待所有PEIM执行完后,调用PeiServices的LocatePpi服务得到DXE IPL PPI的Entry服务,这个Entry服务实际上是DxeLoadCore,它找出DXE Image的入口函数,执行DXE Image的入口函数并将HOB列表传递给DXE。
// DXE IPL Status = TempPtr.DxeIpl->Entry ( TempPtr.DxeIpl, &PrivateData.Ps, PrivateData.HobList );
可见下图,理解整个PEI流程:
涉及单元及功能
- PEI内核(PEI Foundation):负责PEI基础服务和流程。
- PEIM(PEI Module):
① 可执行的二进制代码模块,封装着一些关于Processor、Chipset、device或者是平 台相关的一些功能。
② 每个PEIM都是一个独立的模块。通过PEIServices,PEIM可以调用PEI阶段(UEFI)提供的系统服务。通过调用这些服务,PEIM可以访问PEI内核。PEIM之间的的通信通过PPI(PEIM-to-PEIM Interfaces)完成。
③ PEI阶段对系统的初始化主要由PEIM完成。
3.PEI Dispatcher派遣器 :
① 找出系统中的所有PEIM,并根据PEIM之间的依赖关系按顺序执行PEIM。
具体调用的系统PEIM(PEI Module)
- CPU PEIM(提供CPU相关功能,如进行Cache设置、主频设置等)。
- 平台相关PEIM(初始化内存控制器、I/O控制器等)。
- 内存初始化PEIM(对内存进行初始化,此时内存才可用,之前使用的CPU模拟的临时内存)。
- 调用PEIServices得到DEX IPL PPI的Entry服务(即DEXLoadCore)。
注:PPI与DEX阶段的Protocol类似,每个PPI都是一个结构体,包含有函数指针和变量。每个PPI都有一个GUID。通过PEIServices的LocatePPI服务可以找到GUID对应的PPI实例。
PEI阶段的功能
初始化内存。为DXE阶段准备执行环境。
简单而言分为以下几点:
- 基本的Chipset初始化
- Memory Sizing
- BIOS Recovery
- S3 Resume
- 切换Stack到Memory (Disable CAR, Enable Cache)
- 启动DXEIPL(DXE Initial Program Loader)