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)或真实平台中运行固件,观察串口输出。满足以下条件即判定通过:

  1. 串口打印PEI Core Entry Point.,表明入口函数被正确调用;
  2. 随后打印First PEIM loaded successfully.,表明PEI服务表已初始化且第一个PEIM被成功调用;
  3. 系统不崩溃、不进入死循环,能够继续后续启动流程。

若在调试器中单步执行,可在PeimEntry调用处设置断点,确认传入的PeiServices指针指向有效的服务表结构。