4. 编写PEI阶段入口函数
任务目标
在UEFI平台初始化流程中,PEI阶段负责检测系统内存并传递HOB列表给DXE阶段。本案例实现一个最小可运行的PEI核心入口函数,完成PEI服务表(EFI_PEI_SERVICES)的初始化,并调用第一个PEIM(PEI模块)的入口函数。
核心实现
#include <PiPei.h>
#include <Library/DebugLib.h>
#include <Library/PeiServicesLib.h>
// 第一个PEIM的入口函数原型
typedef EFI_STATUS (*PEIM_ENTRY_POINT)(
IN EFI_FFS_FILE_HEADER *FfsHeader,
IN EFI_PEI_SERVICES **PeiServices
);
// 示例PEIM入口实现
EFI_STATUS
EFIAPI
FirstPeimEntry(
IN EFI_FFS_FILE_HEADER *FfsHeader,
IN EFI_PEI_SERVICES **PeiServices
)
{
DEBUG ((EFI_D_INFO, "First PEIM loaded successfully.\n"));
return EFI_SUCCESS;
}
// PEI服务表实例(最小必要字段)
EFI_PEI_SERVICES mPeiServices = {
{
PEI_SERVICES_SIGNATURE,
PEI_SERVICES_REVISION,
sizeof (EFI_PEI_SERVICES)
},
NULL, // InstallPpi
NULL, // ReInstallPpi
NULL, // LocatePpi
NULL, // NotifyPpi
NULL, // GetBootMode
NULL, // SetBootMode
NULL, // GetHobList
NULL, // CreateHob
NULL, // FfsFindNextFile
NULL, // FfsFindSectionData
NULL, // FfsFindFileByName
NULL, // FfsGetFileInfo
NULL, // FfsGetVolumeInfo
NULL, // RegisterForShadow
NULL, // ResetSystem
NULL // FfsProcessVolume
};
// PEI核心入口函数
EFI_STATUS
EFIAPI
PeiCoreEntryPoint(
IN EFI_PEI_FFS_PPI_PTR FfsPpiPtr,
IN EFI_PEI_PPI_DESCRIPTOR *BootModePpi,
IN VOID *PeiCorePrivate
)
{
EFI_STATUS Status;
PEIM_ENTRY_POINT PeimEntry;
EFI_FFS_FILE_HEADER *FfsHeader;
// 1. 初始化PEI服务表
// 实际固件中此处会填充完整服务函数指针
// 本最小实现仅设置签名与版本,确保服务表可被识别
DEBUG ((EFI_D_INFO, "PEI Core Entry Point.\n"));
// 2. 定位并调用第一个PEIM
// 实际场景中通过FfsFindNextFile遍历固件卷
// 此处直接使用静态定义的PEIM入口进行演示
FfsHeader = NULL; // 最小演示中不使用真实FFS文件头
PeimEntry = FirstPeimEntry;
Status = PeimEntry (FfsHeader, &mPeiServices);
ASSERT_EFI_ERROR (Status);
return EFI_SUCCESS;
}
编译与链接
本代码需在EDK2环境中编译,使用MdePkg和MdeModulePkg的库。在包的.dsc文件中添加:
[Components]
PeiCoreEntryPoint.inf
对应的.inf文件需声明PeiCoreEntryPoint.c以及依赖的PeiServicesLib和DebugLib。
验证方法
在模拟器(如EmulatorPkg)或真实平台中运行固件,观察串口输出。满足以下条件即判定通过:
- 串口打印
PEI Core Entry Point.,表明入口函数被正确调用; - 随后打印
First PEIM loaded successfully.,表明PEI服务表已初始化且第一个PEIM被成功调用; - 系统不崩溃、不进入死循环,能够继续后续启动流程。
若在调试器中单步执行,可在PeimEntry调用处设置断点,确认传入的PeiServices指针指向有效的服务表结构。