第一次进入PeiCore() 的时候,因为环境尚未准备好,所以很快就能执行到下面的代码:
//
// Call PEIM dispatcher
//
PeiDispatcher (SecCoreData, &PrivateData);
在这里会执行 PEIM的执行:
MdeModulePkg\Core\Pei\Dispatcher\Dispatcher.c
/**
Conduct PEIM dispatch.
@param SecCoreData Points to a data structure containing information about the PEI core's operating
environment, such as the size and location of temporary RAM, the stack location and
the BFV location.
@param Private Pointer to the private data passed in from caller
**/
VOID
PeiDispatcher (
IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
IN PEI_CORE_INSTANCE *Private
)
进去这个函数之后,因为刚开始内存并没有准备好,所以 (Private->PeiMemoryInstalled) 这个条件不会满足,会进入下面的do … while 循环。
//
// This is the main dispatch loop. It will search known FVs for PEIMs and
// attempt to dispatch them. If any PEIM gets dispatched through a single
// pass of the dispatcher, it will start over from the BFV again to see
// if any new PEIMs dependencies got satisfied. With a well ordered
// FV where PEIMs are found in the order their dependencies are also
// satisfied, this dispatcher should run only once.
//
跳转到DiscoverPeimsAndOrderWithApriori() 函数中
if (Private->CurrentPeimCount == 0) {
//
// When going through each FV, at first, search Apriori file to
// reorder all PEIMs to ensure the PEIMs in Apriori file to get
// dispatch at first.
//
DiscoverPeimsAndOrderWithApriori (Private, CoreFvHandle);
}
这个函数的作用是找到所有的 PEIM以及Apriori 文件。
/**
Discover all PEIMs and optional Apriori file in one FV. There is at most one
Apriori file in one FV.
@param Private Pointer to the private data passed in from caller
@param CoreFileHandle The instance of PEI_CORE_FV_HANDLE.
**/
VOID
DiscoverPeimsAndOrderWithApriori (
IN PEI_CORE_INSTANCE *Private,
IN PEI_CORE_FV_HANDLE *CoreFileHandle
)
函数中有一个 DEBUG 输出如下:
DEBUG ((
DEBUG_INFO,
"%a(): Found 0x%x PEI FFS files in the %dth FV\n",
__FUNCTION__,
PeimCount,
Private->CurrentPeimFvCount
));
对应的串口 Log 中有如下字样,就是说在找到了7个 PEIM
DiscoverPeimsAndOrderWithApriori(): Found 0x7 PEI FFS files in the 0th FV
为了更好的观测,加入代码,输出它找到的 PEIM 的 GUID:
for (Index = 0; Index < PeimCount; Index++) {
//
// Make an array of file name GUIDs that matches the FileHandle array so we can convert
// quickly from file name to file handle
//
Status = FvPpi->GetFileInfo (FvPpi, TempFileHandles[Index], &FileInfo);
ASSERT_EFI_ERROR (Status);
CopyMem (&TempFileGuid[Index], &FileInfo.FileName, sizeof(EFI_GUID));
DEBUG ((DEBUG_INFO , "%g\n", FileInfo.FileName));
}
然后可以在串口输出中看到多了如下的输出:
9B3ADA4F-AE56-4C24-8DEA-F03B7558AE50
A3610442-E69F-4DF3-82CA-2360C4031A23
9D225237-FA01-464C-A949-BAABC02D31D0
222C386D-5ABC-4FB4-B124-FBB82488ACF4
86D70125-BAA3-4296-A62F-602BEBBB9081
89E549B0-7CFE-449D-9BA3-10D8B2312D71
EDADEB9D-DDBA-48BD-9D22-C1C169C8C5C6
使用工具继续查看,可以将上面的GUID 和文件名对应起来:
GUID | 文件名 |
9B3ADA4F-AE56-4C24-8DEA-F03B7558AE50 | PcdPeim.efi |
A3610442-E69F-4DF3-82CA-2360C4031A23 | ReportStatusCodeRouterPei.efi |
9D225237-FA01-464C-A949-BAABC02D31D0 | StatusCodeHandlePei.efi |
222C386D-5ABC-4FB4-B124-FBB82488ACF4 | PlatformPei.efi |
86D70125-BAA3-4296-A62F-602BEBBB9081 | DxeIpl.efi |
89E549B0-7CFE-449D-9BA3-10D8B2312D71 | S3Resume2Pei.efi |
EDADEB9D-DDBA-48BD-9D22-C1C169C8C5C6 | CpuMpPei.efi |
特别注意,用工具我们能看到9个文件(模块),但是这里只提示找到7个。
接下来退出 DiscoverPeimsAndOrderWithApriori() 函数继续在PeiDispatcher 中执行
//
// Start to dispatch all modules within the current FV.
//
对于每一个 FFS文件,需要用DepexSatisfied()检查是否满足条件,如果满足会使用PeiLoadImage()
//
// For PEIM driver, Load its entry point
//
Status = PeiLoadImage (
PeiServices,
PeimFileHandle,
PEIM_STATE_NOT_DISPATCHED,
&EntryPoint,
&AuthenticationState
);
可以通过加入 Log 的方法证明这里调用的是位于\MdeModulePkg\Core\Pei\Image\Image.c 中的函数
/**
Routine to load image file for subsequent execution by LoadFile Ppi.
If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE
XIP image format is used.
@param PeiServices - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
@param FileHandle - Pointer to the FFS file header of the image.
@param PeimState - The dispatch state of the input PEIM handle.
@param EntryPoint - Pointer to entry point of specified image file for output.
@param AuthenticationState - Pointer to attestation authentication state of image.
@retval EFI_SUCCESS - Image is successfully loaded.
@retval EFI_NOT_FOUND - Fail to locate necessary PPI
@retval Others - Fail to load file.
**/
EFI_STATUS
PeiLoadImage (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_FILE_HANDLE FileHandle,
IN UINT8 PeimState,
OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
OUT UINT32 *AuthenticationState
)
其中通过如下调用来实现真正的加载:
Status = LoadFile->LoadFile (
LoadFile,
FileHandle,
&ImageAddress,
&ImageSize,
EntryPoint,
AuthenticationState
);
实际的 Load动作是通过处于同一个文件中的PeiLoadImageLoadImageWrapper() 来实现的,而这个函数中实际干活的是PeiLoadImageLoadImage() 函数:
/**
Loads a PEIM into memory for subsequent execution. If there are compressed
images or images that need to be relocated into memory for performance reasons,
this service performs that transformation.
@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
@param FileHandle Pointer to the FFS file header of the image.
@param ImageAddressArg Pointer to PE/TE image.
@param ImageSizeArg Size of PE/TE image.
@param EntryPoint Pointer to entry point of specified image file for output.
@param AuthenticationState - Pointer to attestation authentication state of image.
@retval EFI_SUCCESS Image is successfully loaded.
@retval EFI_NOT_FOUND Fail to locate necessary PPI.
@retval EFI_UNSUPPORTED Image Machine Type is not supported.
@retval EFI_WARN_BUFFER_TOO_SMALL
There is not enough heap to allocate the requested size.
This will not prevent the XIP image from being invoked.
**/
EFI_STATUS
PeiLoadImageLoadImage (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_FILE_HANDLE FileHandle,
OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL
OUT UINT64 *ImageSizeArg, OPTIONAL
OUT EFI_PHYSICAL_ADDRESS *EntryPoint,
OUT UINT32 *AuthenticationState
)
其中有2处使用 DEBUG 宏进行串口输出的代码(这里研究对象是 EDK2 202108,不同版本之间可能有差别)
DEBUG ((DEBUG_INFO, "Loading PEIM %g\n", FileHandle));
DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint));
因此串口 Log 中看到的如下字样:
Loading PEIM 9B3ADA4F-AE56-4C24-8DEA-F03B7558AE50
Loading PEIM at 0x0000083D120 EntryPoint=0x0000083D620 PcdPeim.efi
接下的部分串口 Log就是来自PcdPeim.efi。