第一次进入PEICORE流程
检查 PEI Core 是否已迁移到内存中
与第一次进入不同,第二次进入PeiMain时OldCoreData != NULL,内存已可供 PEI Core 使用
C
if (OldCoreData->ShadowedPeiCore == NULL)
如果==NULL,去修复PrivateData
修复PrivateData
C
OldCoreData->Ps = &OldCoreData->ServiceTableShadow;
OldCoreData->CpuIo = &OldCoreData->ServiceTableShadow.CpuIo;
if (OldCoreData->HeapOffsetPositive) {
OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw + OldCoreData->HeapOffset);
if (OldCoreData->UnknownFvInfo != NULL) {
OldCoreData->UnknownFvInfo = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *)((UINT8 *)OldCoreData->UnknownFvInfo + OldCoreData->HeapOffset);
}
if (OldCoreData->CurrentFvFileHandles != NULL) {
OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->CurrentFvFileHandles + OldCoreData->HeapOffset);
}
if (OldCoreData->PpiData.PpiList.PpiPtrs != NULL) {
OldCoreData->PpiData.PpiList.PpiPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.PpiList.PpiPtrs + OldCoreData->HeapOffset);
}
if (OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs != NULL) {
OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.CallbackNotifyList.NotifyPtrs + OldCoreData->HeapOffset);
}
if (OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs != NULL) {
OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs = (PEI_PPI_LIST_POINTERS *)((UINT8 *)OldCoreData->PpiData.DispatchNotifyList.NotifyPtrs + OldCoreData->HeapOffset);
}
OldCoreData->Fv = (PEI_CORE_FV_HANDLE *)((UINT8 *)OldCoreData->Fv + OldCoreData->HeapOffset);
for (Index = 0; Index < OldCoreData->FvCount; Index++) {
if (OldCoreData->Fv[Index].PeimState != NULL) {
OldCoreData->Fv[Index].PeimState = (UINT8 *)OldCoreData->Fv[Index].PeimState + OldCoreData->HeapOffset;
}
if (OldCoreData->Fv[Index].FvFileHandles != NULL) {
OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->Fv[Index].FvFileHandles + OldCoreData->HeapOffset);
}
}
OldCoreData->TempFileGuid = (EFI_GUID *)((UINT8 *)OldCoreData->TempFileGuid + OldCoreData->HeapOffset);
OldCoreData->TempFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->TempFileHandles + OldCoreData->HeapOffset);
}
强制重新定位调度表
C
OldCoreData->DelayedDispatchTable = NULL;
修复 PEI Services 表指针
C
SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);
初始化PEI Core链接库
C
ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);
包含DEBUG串口和ACPI计时器
更新交接信息表
C
HandoffInformationTable = OldCoreData->HobList.HandoffInformationTable;
if (OldCoreData->HeapOffsetPositive) {
HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList + OldCoreData->HeapOffset;
} else {
HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList - OldCoreData->HeapOffset;
}
HandoffInformationTable->EfiMemoryTop = OldCoreData->PhysicalMemoryBegin + OldCoreData->PhysicalMemoryLength;
HandoffInformationTable->EfiMemoryBottom = OldCoreData->PhysicalMemoryBegin;
HandoffInformationTable->EfiFreeMemoryTop = OldCoreData->FreePhysicalMemoryTop;
HandoffInformationTable->EfiFreeMemoryBottom = HandoffInformationTable->EfiEndOfHobList + sizeof (EFI_HOB_GENERIC_HEADER);
包括HOB列表结束地址和内存映射信息
迁移内存分配 HOB 中的内存基地址
C
ConvertMemoryAllocationHobs (OldCoreData);
C
VOID
ConvertMemoryAllocationHobs (
IN PEI_CORE_INSTANCE *PrivateData
)
{
EFI_PEI_HOB_POINTERS Hob;
EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob;
EFI_PHYSICAL_ADDRESS OldMemPagesBase;
UINTN OldMemPagesSize;
if (PrivateData->MemoryPages.Size == 0) {
//
// No any memory page allocated in pre-memory phase.
//
return;
}
OldMemPagesBase = PrivateData->MemoryPages.Base;
OldMemPagesSize = PrivateData->MemoryPages.Size;
MemoryAllocationHob = NULL;
Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
while (Hob.Raw != NULL) {
MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *)Hob.Raw;
if ((MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress >= OldMemPagesBase) &&
(MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress < (OldMemPagesBase + OldMemPagesSize))
)
{
if (PrivateData->MemoryPages.OffsetPositive) {
MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress += PrivateData->MemoryPages.Offset;
} else {
MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress -= PrivateData->MemoryPages.Offset;
}
}
Hob.Raw = GET_NEXT_HOB (Hob);
Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
}
}
迁移 PPI 指针到内存中
C
ConvertPpiPointers (SecCoreData, OldCoreData);
C
VOID
ConvertPpiPointers (
IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
IN PEI_CORE_INSTANCE *PrivateData
)
{
UINT8 Index;
//
// Convert normal PPIs.
//
for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {
ConvertSinglePpiPointer (
SecCoreData,
PrivateData,
&PrivateData->PpiData.PpiList.PpiPtrs[Index]
);
}
//
// Convert Callback Notification PPIs.
//
for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {
ConvertSinglePpiPointer (
SecCoreData,
PrivateData,
&PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index]
);
}
//
// Convert Dispatch Notification PPIs.
//
for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {
ConvertSinglePpiPointer (
SecCoreData,
PrivateData,
&PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index]
);
}
}
在内存里分配连续区域
C
OldCoreData->PeiMemoryInstalled = TRUE;
if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
DEBUG ((DEBUG_VERBOSE, "Early Migration - PPI lists before temporary RAM evacuation:\n"));
DumpPpiList (OldCoreData);
//
// Migrate installed content from Temporary RAM to Permanent RAM at this
// stage when PEI core still runs from a cached location.
// FVs that doesn't contain PEI_CORE should be migrated here.
//
EvacuateTempRam (OldCoreData, SecCoreData);
DEBUG ((DEBUG_VERBOSE, "Early Migration - PPI lists after temporary RAM evacuation:\n"));
DumpPpiList (OldCoreData);
}
准备第三次进入PEICORE
C
OldCoreData->PeimDispatcherReenter = TRUE;
if ((PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) && (OldCoreData->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
//
// if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array.
// Every bit in the array indicate the status of the corresponding memory page available or not
//
OldCoreData->PeiCodeMemoryRangeUsageBitMap = AllocateZeroPool (((PcdGet32 (PcdLoadFixAddressPeiCodePageNumber)>>6) + 1)*sizeof (UINT64));
}
//
// Shadow PEI Core. When permanent memory is available, shadow
// PEI Core and PEIMs to get high performance.
//
OldCoreData->ShadowedPeiCore = (PEICORE_FUNCTION_POINTER)(UINTN)PeiCore;
if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
((HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME) && PcdGetBool (PcdShadowPeimOnS3Boot)) ||
((HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && PcdGetBool (PcdShadowPeimOnBoot)))
{
OldCoreData->ShadowedPeiCore = ShadowPeiCore (OldCoreData);
}
//
// PEI Core has now been shadowed to memory. Restart PEI Core in memory.
//
OldCoreData->ShadowedPeiCore (SecCoreData, PpiList, OldCoreData);
至此PEI Core 已经被映射到内存