summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg/Core
diff options
context:
space:
mode:
authorMichael Kubacki <michael.a.kubacki@intel.com>2019-04-12 06:46:02 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2020-07-28 01:43:16 +0000
commit9bedaec05b7b8ba9aee248361bb61a85a26726cb (patch)
tree7c839ee9dbbb28b077b4d656401aca2ff23aaae1 /MdeModulePkg/Core
parent1facb8fdef6389f390b66da6d8304f54cc93104a (diff)
downloadedk2-9bedaec05b7b8ba9aee248361bb61a85a26726cb.tar.gz
edk2-9bedaec05b7b8ba9aee248361bb61a85a26726cb.tar.bz2
edk2-9bedaec05b7b8ba9aee248361bb61a85a26726cb.zip
MdeModulePkg/PeiCore: Enable T-RAM evacuation in PeiCore (CVE-2019-11098)
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614 Introduces new changes to PeiCore to move the contents of temporary RAM visible to the PeiCore to permanent memory. This expands on pre-existing shadowing support in the PeiCore to perform the following additional actions: 1. Migrate pointers in PPIs installed in PeiCore to the permanent memory copy of PeiCore. 2. Copy all installed firmware volumes to permanent memory. 3. Relocate and fix up the PEIMs within the firmware volumes. 4. Convert all PPIs into the migrated firmware volume to the corresponding PPI address in the permanent memory location. This applies to PPIs and PEI notifications. 5. Convert all status code callbacks in the migrated firmware volume to the corresponding address in the permanent memory location. 6. Update the FV HOB to the corresponding firmware volume in permanent memory. 7. Use PcdMigrateTemporaryRamFirmwareVolumes to control if enable the feature or not. when disable the PCD, the EvacuateTempRam() will never be called. The function control flow as below: PeiCore() DumpPpiList() EvacuateTempRam() ConvertPeiCorePpiPointers() ConvertPpiPointersFv() MigratePeimsInFv() MigratePeim() PeiGetPe32Data() LoadAndRelocatePeCoffImageInPlace() MigrateSecModulesInFv() ConvertPpiPointersFv() ConvertStatusCodeCallbacks() ConvertFvHob() RemoveFvHobsInTemporaryMemory() DumpPpiList() Cc: Jian J Wang <jian.j.wang@intel.com> Cc: Hao A Wu <hao.a.wu@intel.com> Cc: Dandan Bi <dandan.bi@intel.com> Cc: Liming Gao <liming.gao@intel.com> Cc: Debkumar De <debkumar.de@intel.com> Cc: Harry Han <harry.han@intel.com> Cc: Catharine West <catharine.west@intel.com> Signed-off-by: Michael Kubacki <michael.a.kubacki@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> Acked-by: Laszlo Ersek <lersek@redhat.com>
Diffstat (limited to 'MdeModulePkg/Core')
-rw-r--r--MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c417
-rw-r--r--MdeModulePkg/Core/Pei/Image/Image.c130
-rw-r--r--MdeModulePkg/Core/Pei/Memory/MemoryServices.c82
-rw-r--r--MdeModulePkg/Core/Pei/PeiMain.h169
-rw-r--r--MdeModulePkg/Core/Pei/PeiMain.inf2
-rw-r--r--MdeModulePkg/Core/Pei/PeiMain/PeiMain.c22
-rw-r--r--MdeModulePkg/Core/Pei/Ppi/Ppi.c286
7 files changed, 1099 insertions, 9 deletions
diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
index 4c2eac1384..5bc0f8674d 100644
--- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
+++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
@@ -953,6 +953,409 @@ PeiCheckAndSwitchStack (
}
/**
+ Migrate a PEIM from temporary RAM to permanent memory.
+
+ @param PeimFileHandle Pointer to the FFS file header of the image.
+ @param MigratedFileHandle Pointer to the FFS file header of the migrated image.
+
+ @retval EFI_SUCCESS Sucessfully migrated the PEIM to permanent memory.
+
+**/
+EFI_STATUS
+EFIAPI
+MigratePeim (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN EFI_PEI_FILE_HANDLE MigratedFileHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_FFS_FILE_HEADER *FileHeader;
+ VOID *Pe32Data;
+ VOID *ImageAddress;
+ CHAR8 *AsciiString;
+ UINTN Index;
+
+ Status = EFI_SUCCESS;
+
+ FileHeader = (EFI_FFS_FILE_HEADER *) FileHandle;
+ ASSERT (!IS_FFS_FILE2 (FileHeader));
+
+ ImageAddress = NULL;
+ PeiGetPe32Data (MigratedFileHandle, &ImageAddress);
+ if (ImageAddress != NULL) {
+ DEBUG_CODE_BEGIN ();
+ AsciiString = PeCoffLoaderGetPdbPointer (ImageAddress);
+ for (Index = 0; AsciiString[Index] != 0; Index++) {
+ if (AsciiString[Index] == '\\' || AsciiString[Index] == '/') {
+ AsciiString = AsciiString + Index + 1;
+ Index = 0;
+ } else if (AsciiString[Index] == '.') {
+ AsciiString[Index] = 0;
+ }
+ }
+ DEBUG ((DEBUG_INFO, "%a", AsciiString));
+ DEBUG_CODE_END ();
+
+ Pe32Data = (VOID *) ((UINTN) ImageAddress - (UINTN) MigratedFileHandle + (UINTN) FileHandle);
+ Status = LoadAndRelocatePeCoffImageInPlace (Pe32Data, ImageAddress);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
+/**
+ Migrate Status Code Callback function pointers inside an FV from temporary memory to permanent memory.
+
+ @param OrgFvHandle Address of FV handle in temporary memory.
+ @param FvHandle Address of FV handle in permanent memory.
+ @param FvSize Size of the FV.
+
+**/
+VOID
+ConvertStatusCodeCallbacks (
+ IN UINTN OrgFvHandle,
+ IN UINTN FvHandle,
+ IN UINTN FvSize
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ UINTN *NumberOfEntries;
+ UINTN *CallbackEntry;
+ UINTN Index;
+
+ Hob.Raw = GetFirstGuidHob (&gStatusCodeCallbackGuid);
+ while (Hob.Raw != NULL) {
+ NumberOfEntries = GET_GUID_HOB_DATA (Hob);
+ CallbackEntry = NumberOfEntries + 1;
+ for (Index = 0; Index < *NumberOfEntries; Index++) {
+ if (((VOID *) CallbackEntry[Index]) != NULL) {
+ if ((CallbackEntry[Index] >= OrgFvHandle) && (CallbackEntry[Index] < (OrgFvHandle + FvSize))) {
+ DEBUG ((
+ DEBUG_INFO,
+ "Migrating CallbackEntry[%Lu] from 0x%0*Lx to ",
+ (UINT64)Index,
+ (sizeof CallbackEntry[Index]) * 2,
+ (UINT64)CallbackEntry[Index]
+ ));
+ if (OrgFvHandle > FvHandle) {
+ CallbackEntry[Index] = CallbackEntry[Index] - (OrgFvHandle - FvHandle);
+ } else {
+ CallbackEntry[Index] = CallbackEntry[Index] + (FvHandle - OrgFvHandle);
+ }
+ DEBUG ((
+ DEBUG_INFO,
+ "0x%0*Lx\n",
+ (sizeof CallbackEntry[Index]) * 2,
+ (UINT64)CallbackEntry[Index]
+ ));
+ }
+ }
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextGuidHob (&gStatusCodeCallbackGuid, Hob.Raw);
+ }
+}
+
+/**
+ Migrates SEC modules in the given firmware volume.
+
+ Migrating SECURITY_CORE files requires special treatment since they are not tracked for PEI dispatch.
+
+ This functioun should be called after the FV has been copied to its post-memory location and the PEI Core FV list has
+ been updated.
+
+ @param Private Pointer to the PeiCore's private data structure.
+ @param FvIndex The firmware volume index to migrate.
+ @param OrgFvHandle The handle to the firmware volume in temporary memory.
+
+ @retval EFI_SUCCESS SEC modules were migrated successfully
+ @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid.
+ @retval EFI_NOT_FOUND Can't find valid FFS header.
+
+**/
+EFI_STATUS
+EFIAPI
+MigrateSecModulesInFv (
+ IN PEI_CORE_INSTANCE *Private,
+ IN UINTN FvIndex,
+ IN UINTN OrgFvHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS FindFileStatus;
+ EFI_PEI_FILE_HANDLE MigratedFileHandle;
+ EFI_PEI_FILE_HANDLE FileHandle;
+ UINT32 SectionAuthenticationStatus;
+ UINT32 FileSize;
+ VOID *OrgPe32SectionData;
+ VOID *Pe32SectionData;
+ EFI_FFS_FILE_HEADER *FfsFileHeader;
+ EFI_COMMON_SECTION_HEADER *Section;
+ BOOLEAN IsFfs3Fv;
+ UINTN SectionInstance;
+
+ if (Private == NULL || FvIndex >= Private->FvCount) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ do {
+ FindFileStatus = PeiFfsFindNextFile (
+ GetPeiServicesTablePointer (),
+ EFI_FV_FILETYPE_SECURITY_CORE,
+ Private->Fv[FvIndex].FvHandle,
+ &MigratedFileHandle
+ );
+ if (!EFI_ERROR (FindFileStatus ) && MigratedFileHandle != NULL) {
+ FileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) MigratedFileHandle - (UINTN) Private->Fv[FvIndex].FvHandle + OrgFvHandle);
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *) MigratedFileHandle;
+
+ DEBUG ((DEBUG_VERBOSE, " Migrating SEC_CORE MigratedFileHandle at 0x%x.\n", (UINTN) MigratedFileHandle));
+ DEBUG ((DEBUG_VERBOSE, " FileHandle at 0x%x.\n", (UINTN) FileHandle));
+
+ IsFfs3Fv = CompareGuid (&Private->Fv[FvIndex].FvHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);
+ if (IS_FFS_FILE2 (FfsFileHeader)) {
+ ASSERT (FFS_FILE2_SIZE (FfsFileHeader) > 0x00FFFFFF);
+ if (!IsFfs3Fv) {
+ DEBUG ((DEBUG_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));
+ return EFI_NOT_FOUND;
+ }
+ Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
+ FileSize = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
+ } else {
+ Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));
+ FileSize = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
+ }
+
+ SectionInstance = 1;
+ SectionAuthenticationStatus = 0;
+ Status = ProcessSection (
+ GetPeiServicesTablePointer (),
+ EFI_SECTION_PE32,
+ &SectionInstance,
+ Section,
+ FileSize,
+ &Pe32SectionData,
+ &SectionAuthenticationStatus,
+ IsFfs3Fv
+ );
+
+ if (!EFI_ERROR (Status)) {
+ OrgPe32SectionData = (VOID *) ((UINTN) Pe32SectionData - (UINTN) MigratedFileHandle + (UINTN) FileHandle);
+ DEBUG ((DEBUG_VERBOSE, " PE32 section in migrated file at 0x%x.\n", (UINTN) Pe32SectionData));
+ DEBUG ((DEBUG_VERBOSE, " PE32 section in original file at 0x%x.\n", (UINTN) OrgPe32SectionData));
+ Status = LoadAndRelocatePeCoffImageInPlace (OrgPe32SectionData, Pe32SectionData);
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ } while (!EFI_ERROR (FindFileStatus));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Migrates PEIMs in the given firmware volume.
+
+ @param Private Pointer to the PeiCore's private data structure.
+ @param FvIndex The firmware volume index to migrate.
+ @param OrgFvHandle The handle to the firmware volume in temporary memory.
+ @param FvHandle The handle to the firmware volume in permanent memory.
+
+ @retval EFI_SUCCESS The PEIMs in the FV were migrated successfully
+ @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+MigratePeimsInFv (
+ IN PEI_CORE_INSTANCE *Private,
+ IN UINTN FvIndex,
+ IN UINTN OrgFvHandle,
+ IN UINTN FvHandle
+ )
+{
+ EFI_STATUS Status;
+ volatile UINTN FileIndex;
+ EFI_PEI_FILE_HANDLE MigratedFileHandle;
+ EFI_PEI_FILE_HANDLE FileHandle;
+
+ if (Private == NULL || FvIndex >= Private->FvCount) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Private->Fv[FvIndex].ScanFv) {
+ for (FileIndex = 0; FileIndex < Private->Fv[FvIndex].PeimCount; FileIndex++) {
+ if (Private->Fv[FvIndex].FvFileHandles[FileIndex] != NULL) {
+ FileHandle = Private->Fv[FvIndex].FvFileHandles[FileIndex];
+
+ MigratedFileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) FileHandle - OrgFvHandle + FvHandle);
+
+ DEBUG ((DEBUG_VERBOSE, " Migrating FileHandle %2d ", FileIndex));
+ Status = MigratePeim (FileHandle, MigratedFileHandle);
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+ ASSERT_EFI_ERROR (Status);
+
+ if (!EFI_ERROR (Status)) {
+ Private->Fv[FvIndex].FvFileHandles[FileIndex] = MigratedFileHandle;
+ if (FvIndex == Private->CurrentPeimFvCount) {
+ Private->CurrentFvFileHandles[FileIndex] = MigratedFileHandle;
+ }
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Migrate FVs out of temporary RAM before the cache is flushed.
+
+ @param Private PeiCore's private data structure
+ @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.
+
+ @retval EFI_SUCCESS Succesfully migrated installed FVs from temporary RAM to permanent memory.
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages.
+
+**/
+EFI_STATUS
+EFIAPI
+EvacuateTempRam (
+ IN PEI_CORE_INSTANCE *Private,
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
+ )
+{
+ EFI_STATUS Status;
+ volatile UINTN FvIndex;
+ volatile UINTN FvChildIndex;
+ UINTN ChildFvOffset;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *ChildFvHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *MigratedFvHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *MigratedChildFvHeader;
+
+ PEI_CORE_FV_HANDLE PeiCoreFvHandle;
+ EFI_PEI_CORE_FV_LOCATION_PPI *PeiCoreFvLocationPpi;
+
+ ASSERT (Private->PeiMemoryInstalled);
+
+ DEBUG ((DEBUG_VERBOSE, "Beginning evacuation of content in temporary RAM.\n"));
+
+ //
+ // Migrate PPI Pointers of PEI_CORE from temporary memory to newly loaded PEI_CORE in permanent memory.
+ //
+ Status = PeiLocatePpi ((CONST EFI_PEI_SERVICES **) &Private->Ps, &gEfiPeiCoreFvLocationPpiGuid, 0, NULL, (VOID **) &PeiCoreFvLocationPpi);
+ if (!EFI_ERROR (Status) && (PeiCoreFvLocationPpi->PeiCoreFvLocation != NULL)) {
+ PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) PeiCoreFvLocationPpi->PeiCoreFvLocation;
+ } else {
+ PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) SecCoreData->BootFirmwareVolumeBase;
+ }
+ for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {
+ if (Private->Fv[FvIndex].FvHandle == PeiCoreFvHandle.FvHandle) {
+ PeiCoreFvHandle = Private->Fv[FvIndex];
+ break;
+ }
+ }
+ Status = EFI_SUCCESS;
+
+ ConvertPeiCorePpiPointers (Private, PeiCoreFvHandle);
+
+ for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {
+ FvHeader = Private->Fv[FvIndex].FvHeader;
+ ASSERT (FvHeader != NULL);
+ ASSERT (FvIndex < Private->FvCount);
+
+ DEBUG ((DEBUG_VERBOSE, "FV[%02d] at 0x%x.\n", FvIndex, (UINTN) FvHeader));
+ if (
+ !(
+ ((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader >= Private->PhysicalMemoryBegin) &&
+ (((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader + (FvHeader->FvLength - 1)) < Private->FreePhysicalMemoryTop)
+ )
+ ) {
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength),
+ (EFI_PHYSICAL_ADDRESS *) &MigratedFvHeader
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((
+ DEBUG_VERBOSE,
+ " Migrating FV[%d] from 0x%08X to 0x%08X\n",
+ FvIndex,
+ (UINTN) FvHeader,
+ (UINTN) MigratedFvHeader
+ ));
+
+ CopyMem (MigratedFvHeader, FvHeader, (UINTN) FvHeader->FvLength);
+
+ //
+ // Migrate any children for this FV now
+ //
+ for (FvChildIndex = FvIndex; FvChildIndex < Private->FvCount; FvChildIndex++) {
+ ChildFvHeader = Private->Fv[FvChildIndex].FvHeader;
+ if (
+ ((UINTN) ChildFvHeader > (UINTN) FvHeader) &&
+ (((UINTN) ChildFvHeader + ChildFvHeader->FvLength) < ((UINTN) FvHeader) + FvHeader->FvLength)
+ ) {
+ DEBUG ((DEBUG_VERBOSE, " Child FV[%02d] is being migrated.\n", FvChildIndex));
+ ChildFvOffset = (UINTN) ChildFvHeader - (UINTN) FvHeader;
+ DEBUG ((DEBUG_VERBOSE, " Child FV offset = 0x%x.\n", ChildFvOffset));
+ MigratedChildFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) MigratedFvHeader + ChildFvOffset);
+ Private->Fv[FvChildIndex].FvHeader = MigratedChildFvHeader;
+ Private->Fv[FvChildIndex].FvHandle = (EFI_PEI_FV_HANDLE) MigratedChildFvHeader;
+ DEBUG ((DEBUG_VERBOSE, " Child migrated FV header at 0x%x.\n", (UINTN) MigratedChildFvHeader));
+
+ Status = MigratePeimsInFv (Private, FvChildIndex, (UINTN) ChildFvHeader, (UINTN) MigratedChildFvHeader);
+ ASSERT_EFI_ERROR (Status);
+
+ ConvertPpiPointersFv (
+ Private,
+ (UINTN) ChildFvHeader,
+ (UINTN) MigratedChildFvHeader,
+ (UINTN) ChildFvHeader->FvLength - 1
+ );
+
+ ConvertStatusCodeCallbacks (
+ (UINTN) ChildFvHeader,
+ (UINTN) MigratedChildFvHeader,
+ (UINTN) ChildFvHeader->FvLength - 1
+ );
+
+ ConvertFvHob (Private, (UINTN) ChildFvHeader, (UINTN) MigratedChildFvHeader);
+ }
+ }
+ Private->Fv[FvIndex].FvHeader = MigratedFvHeader;
+ Private->Fv[FvIndex].FvHandle = (EFI_PEI_FV_HANDLE) MigratedFvHeader;
+
+ Status = MigratePeimsInFv (Private, FvIndex, (UINTN) FvHeader, (UINTN) MigratedFvHeader);
+ ASSERT_EFI_ERROR (Status);
+
+ ConvertPpiPointersFv (
+ Private,
+ (UINTN) FvHeader,
+ (UINTN) MigratedFvHeader,
+ (UINTN) FvHeader->FvLength - 1
+ );
+
+ ConvertStatusCodeCallbacks (
+ (UINTN) FvHeader,
+ (UINTN) MigratedFvHeader,
+ (UINTN) FvHeader->FvLength - 1
+ );
+
+ ConvertFvHob (Private, (UINTN) FvHeader, (UINTN) MigratedFvHeader);
+ }
+ }
+
+ RemoveFvHobsInTemporaryMemory (Private);
+
+ return Status;
+}
+
+/**
Conduct PEIM dispatch.
@param SecCoreData Points to a data structure containing information about the PEI core's operating
@@ -988,7 +1391,11 @@ PeiDispatcher (
PeimFileHandle = NULL;
EntryPoint = 0;
- if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {
+ if ((Private->PeiMemoryInstalled) &&
+ (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
+ (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||
+ PcdGetBool (PcdShadowPeimOnS3Boot))
+ ) {
//
// Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
// update the modules' status from PEIM_STATE_REGISTER_FOR_SHADOW to PEIM_STATE_DONE.
@@ -1187,13 +1594,17 @@ PeiDispatcher (
PeiCheckAndSwitchStack (SecCoreData, Private);
if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISTER_FOR_SHADOW) && \
- (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {
+ (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
+ (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||
+ PcdGetBool (PcdShadowPeimOnS3Boot))
+ ) {
//
// If memory is available we shadow images by default for performance reasons.
// We call the entry point a 2nd time so the module knows it's shadowed.
//
//PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
- if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot)) {
+ if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot) &&
+ !PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
//
// Load PEIM into Memory for Register for shadow PEIM.
//
diff --git a/MdeModulePkg/Core/Pei/Image/Image.c b/MdeModulePkg/Core/Pei/Image/Image.c
index e3ee369933..1d15774527 100644
--- a/MdeModulePkg/Core/Pei/Image/Image.c
+++ b/MdeModulePkg/Core/Pei/Image/Image.c
@@ -328,8 +328,11 @@ LoadAndRelocatePeCoffImage (
//
// When Image has no reloc section, it can't be relocated into memory.
//
- if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) && ((!IsPeiModule) ||
- (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) || (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))) {
+ if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) &&
+ ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
+ (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) ||
+ (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))
+ ) {
DEBUG ((EFI_D_INFO|EFI_D_LOAD, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN) Pe32Data));
}
@@ -343,8 +346,11 @@ LoadAndRelocatePeCoffImage (
// On normal boot, PcdShadowPeimOnBoot decides whether load PEIM or PeiCore into memory.
// On S3 boot, PcdShadowPeimOnS3Boot decides whether load PEIM or PeiCore into memory.
//
- if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && ((!IsPeiModule) ||
- (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) || (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))) {
+ if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) &&
+ ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
+ (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) ||
+ (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))
+ ) {
//
// Allocate more buffer to avoid buffer overflow.
//
@@ -445,6 +451,122 @@ LoadAndRelocatePeCoffImage (
}
/**
+ Loads and relocates a PE/COFF image in place.
+
+ @param Pe32Data The base address of the PE/COFF file that is to be loaded and relocated
+ @param ImageAddress The base address of the relocated PE/COFF image
+
+ @retval EFI_SUCCESS The file was loaded and relocated.
+ @retval Others The file not be loaded and error occurred.
+
+**/
+EFI_STATUS
+LoadAndRelocatePeCoffImageInPlace (
+ IN VOID *Pe32Data,
+ IN VOID *ImageAddress
+ )
+{
+ EFI_STATUS Status;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+
+ ZeroMem (&ImageContext, sizeof (ImageContext));
+ ImageContext.Handle = Pe32Data;
+ ImageContext.ImageRead = PeiImageRead;
+
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN) ImageAddress;
+
+ //
+ // Load the image in place
+ //
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // Relocate the image in place
+ //
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // Flush the instruction cache so the image data is written before we execute it
+ //
+ if (ImageContext.ImageAddress != (EFI_PHYSICAL_ADDRESS)(UINTN) Pe32Data) {
+ InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
+ }
+
+ return Status;
+}
+
+/**
+ Find the PE32 Data for an FFS file.
+
+ @param FileHandle Pointer to the FFS file header of the image.
+ @param Pe32Data Pointer to a (VOID *) PE32 Data pointer.
+
+ @retval EFI_SUCCESS Image is successfully loaded.
+ @retval EFI_NOT_FOUND Fail to locate PE32 Data.
+
+**/
+EFI_STATUS
+PeiGetPe32Data (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ OUT VOID **Pe32Data
+ )
+{
+ EFI_STATUS Status;
+ EFI_SECTION_TYPE SearchType1;
+ EFI_SECTION_TYPE SearchType2;
+ UINT32 AuthenticationState;
+
+ *Pe32Data = NULL;
+
+ if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) {
+ SearchType1 = EFI_SECTION_TE;
+ SearchType2 = EFI_SECTION_PE32;
+ } else {
+ SearchType1 = EFI_SECTION_PE32;
+ SearchType2 = EFI_SECTION_TE;
+ }
+
+ //
+ // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
+ // is true, TE will be searched first).
+ //
+ Status = PeiServicesFfsFindSectionData3 (
+ SearchType1,
+ 0,
+ FileHandle,
+ Pe32Data,
+ &AuthenticationState
+ );
+ //
+ // If we didn't find a first exe section, try to find the second exe section.
+ //
+ if (EFI_ERROR (Status)) {
+ Status = PeiServicesFfsFindSectionData3 (
+ SearchType2,
+ 0,
+ FileHandle,
+ Pe32Data,
+ &AuthenticationState
+ );
+ }
+ return Status;
+}
+
+/**
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.
diff --git a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
index 6b3a64a811..9d933f0393 100644
--- a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
+++ b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
@@ -167,6 +167,88 @@ MigrateMemoryPages (
}
/**
+ Removes any FV HOBs whose base address is not in PEI installed memory.
+
+ @param[in] Private Pointer to PeiCore's private data structure.
+
+**/
+VOID
+RemoveFvHobsInTemporaryMemory (
+ IN PEI_CORE_INSTANCE *Private
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;
+
+ DEBUG ((DEBUG_INFO, "Removing FVs in FV HOB not already migrated to permanent memory.\n"));
+
+ for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV || GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV2 || GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV3) {
+ FirmwareVolumeHob = Hob.FirmwareVolume;
+ DEBUG ((DEBUG_INFO, " Found FV HOB.\n"));
+ DEBUG ((
+ DEBUG_INFO,
+ " BA=%016lx L=%016lx\n",
+ FirmwareVolumeHob->BaseAddress,
+ FirmwareVolumeHob->Length
+ ));
+ if (
+ !(
+ ((EFI_PHYSICAL_ADDRESS) (UINTN) FirmwareVolumeHob->BaseAddress >= Private->PhysicalMemoryBegin) &&
+ (((EFI_PHYSICAL_ADDRESS) (UINTN) FirmwareVolumeHob->BaseAddress + (FirmwareVolumeHob->Length - 1)) < Private->FreePhysicalMemoryTop)
+ )
+ ) {
+ DEBUG ((DEBUG_INFO, " Removing FV HOB to an FV in T-RAM (was not migrated).\n"));
+ Hob.Header->HobType = EFI_HOB_TYPE_UNUSED;
+ }
+ }
+ }
+}
+
+/**
+ Migrate the base address in firmware volume allocation HOBs
+ from temporary memory to PEI installed memory.
+
+ @param[in] PrivateData Pointer to PeiCore's private data structure.
+ @param[in] OrgFvHandle Address of FV Handle in temporary memory.
+ @param[in] FvHandle Address of FV Handle in permanent memory.
+
+**/
+VOID
+ConvertFvHob (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN UINTN OrgFvHandle,
+ IN UINTN FvHandle
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;
+ EFI_HOB_FIRMWARE_VOLUME2 *FirmwareVolume2Hob;
+ EFI_HOB_FIRMWARE_VOLUME3 *FirmwareVolume3Hob;
+
+ DEBUG ((DEBUG_INFO, "Converting FVs in FV HOB.\n"));
+
+ for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {
+ FirmwareVolumeHob = Hob.FirmwareVolume;
+ if (FirmwareVolumeHob->BaseAddress == OrgFvHandle) {
+ FirmwareVolumeHob->BaseAddress = FvHandle;
+ }
+ } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV2) {
+ FirmwareVolume2Hob = Hob.FirmwareVolume2;
+ if (FirmwareVolume2Hob->BaseAddress == OrgFvHandle) {
+ FirmwareVolume2Hob->BaseAddress = FvHandle;
+ }
+ } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV3) {
+ FirmwareVolume3Hob = Hob.FirmwareVolume3;
+ if (FirmwareVolume3Hob->BaseAddress == OrgFvHandle) {
+ FirmwareVolume3Hob->BaseAddress = FvHandle;
+ }
+ }
+ }
+}
+
+/**
Migrate MemoryBaseAddress in memory allocation HOBs
from the temporary memory to PEI installed memory.
diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMain.h
index 56b3bd8579..6d95a5d32c 100644
--- a/MdeModulePkg/Core/Pei/PeiMain.h
+++ b/MdeModulePkg/Core/Pei/PeiMain.h
@@ -395,6 +395,41 @@ PeimDispatchReadiness (
);
/**
+ Migrate a PEIM from temporary RAM to permanent memory.
+
+ @param PeimFileHandle Pointer to the FFS file header of the image.
+ @param MigratedFileHandle Pointer to the FFS file header of the migrated image.
+
+ @retval EFI_SUCCESS Sucessfully migrated the PEIM to permanent memory.
+
+**/
+EFI_STATUS
+EFIAPI
+MigratePeim (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN EFI_PEI_FILE_HANDLE MigratedFileHandle
+ );
+
+/**
+ Migrate FVs out of temporary RAM before the cache is flushed.
+
+ @param Private PeiCore's private data structure
+ @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.
+
+ @retval EFI_SUCCESS Succesfully migrated installed FVs from temporary RAM to permanent memory.
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages.
+
+**/
+EFI_STATUS
+EFIAPI
+EvacuateTempRam (
+ IN PEI_CORE_INSTANCE *Private,
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
+ );
+
+/**
Conduct PEIM dispatch.
@param SecCoreData Pointer to the data structure containing SEC to PEI handoff data
@@ -479,6 +514,50 @@ ConvertPpiPointers (
/**
+ Migrate Notify Pointers inside an FV from temporary memory to permanent memory.
+
+ @param PrivateData Pointer to PeiCore's private data structure.
+ @param OrgFvHandle Address of FV Handle in temporary memory.
+ @param FvHandle Address of FV Handle in permanent memory.
+ @param FvSize Size of the FV.
+
+**/
+VOID
+ConvertPpiPointersFv (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN UINTN OrgFvHandle,
+ IN UINTN FvHandle,
+ IN UINTN FvSize
+ );
+
+/**
+
+ Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory.
+
+ @param PrivateData Pointer to PeiCore's private data structure.
+ @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory.
+
+**/
+VOID
+ConvertPeiCorePpiPointers (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ PEI_CORE_FV_HANDLE CoreFvHandle
+ );
+
+/**
+
+ Dumps the PPI lists to debug output.
+
+ @param PrivateData Points to PeiCore's private instance data.
+
+**/
+VOID
+DumpPpiList (
+ IN PEI_CORE_INSTANCE *PrivateData
+ );
+
+/**
+
Install PPI services. It is implementation of EFI_PEI_SERVICE.InstallPpi.
@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
@@ -809,6 +888,37 @@ PeiFfsFindNextFile (
);
/**
+ Go through the file to search SectionType section.
+ Search within encapsulation sections (compression and GUIDed) recursively,
+ until the match section is found.
+
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
+ @param SectionType Filter to find only section of this type.
+ @param SectionInstance Pointer to the filter to find the specific instance of section.
+ @param Section From where to search.
+ @param SectionSize The file size to search.
+ @param OutputBuffer A pointer to the discovered section, if successful.
+ NULL if section not found.
+ @param AuthenticationStatus Updated upon return to point to the authentication status for this section.
+ @param IsFfs3Fv Indicates the FV format.
+
+ @return EFI_NOT_FOUND The match section is not found.
+ @return EFI_SUCCESS The match section is found.
+
+**/
+EFI_STATUS
+ProcessSection (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_SECTION_TYPE SectionType,
+ IN OUT UINTN *SectionInstance,
+ IN EFI_COMMON_SECTION_HEADER *Section,
+ IN UINTN SectionSize,
+ OUT VOID **OutputBuffer,
+ OUT UINT32 *AuthenticationStatus,
+ IN BOOLEAN IsFfs3Fv
+ );
+
+/**
Searches for the next matching section within the specified file.
@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
@@ -932,6 +1042,33 @@ MigrateMemoryPages (
);
/**
+ Removes any FV HOBs whose base address is not in PEI installed memory.
+
+ @param[in] Private Pointer to PeiCore's private data structure.
+
+**/
+VOID
+RemoveFvHobsInTemporaryMemory (
+ IN PEI_CORE_INSTANCE *Private
+ );
+
+/**
+ Migrate the base address in firmware volume allocation HOBs
+ from temporary memory to PEI installed memory.
+
+ @param[in] PrivateData Pointer to PeiCore's private data structure.
+ @param[in] OrgFvHandle Address of FV Handle in temporary memory.
+ @param[in] FvHandle Address of FV Handle in permanent memory.
+
+**/
+VOID
+ConvertFvHob (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN UINTN OrgFvHandle,
+ IN UINTN FvHandle
+ );
+
+/**
Migrate MemoryBaseAddress in memory allocation HOBs
from the temporary memory to PEI installed memory.
@@ -1250,6 +1387,38 @@ InitializeImageServices (
);
/**
+ Loads and relocates a PE/COFF image in place.
+
+ @param Pe32Data The base address of the PE/COFF file that is to be loaded and relocated
+ @param ImageAddress The base address of the relocated PE/COFF image
+
+ @retval EFI_SUCCESS The file was loaded and relocated
+ @retval Others The file not be loaded and error occurred.
+
+**/
+EFI_STATUS
+LoadAndRelocatePeCoffImageInPlace (
+ IN VOID *Pe32Data,
+ IN VOID *ImageAddress
+ );
+
+/**
+ Find the PE32 Data for an FFS file.
+
+ @param FileHandle Pointer to the FFS file header of the image.
+ @param Pe32Data Pointer to a (VOID *) PE32 Data pointer.
+
+ @retval EFI_SUCCESS Image is successfully loaded.
+ @retval EFI_NOT_FOUND Fail to locate PE32 Data.
+
+**/
+EFI_STATUS
+PeiGetPe32Data (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ OUT VOID **Pe32Data
+ );
+
+/**
The wrapper function of PeiLoadImageLoadImage().
@param This Pointer to EFI_PEI_LOAD_FILE_PPI.
diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf b/MdeModulePkg/Core/Pei/PeiMain.inf
index 6e25cc4023..5b36d516b3 100644
--- a/MdeModulePkg/Core/Pei/PeiMain.inf
+++ b/MdeModulePkg/Core/Pei/PeiMain.inf
@@ -76,6 +76,7 @@
## CONSUMES ## UNDEFINED # Locate PPI
## CONSUMES ## GUID # Used to compare with FV's file system GUID and get the FV's file system format
gEfiFirmwareFileSystem3Guid
+ gStatusCodeCallbackGuid
[Ppis]
gEfiPeiStatusCodePpiGuid ## SOMETIMES_CONSUMES # PeiReportStatusService is not ready if this PPI doesn't exist
@@ -109,6 +110,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnS3Boot ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES
# [BootMode]
# S3_RESUME ## SOMETIMES_CONSUMES
diff --git a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
index cca57c4c06..2ad08878d9 100644
--- a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
+++ b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
@@ -319,8 +319,9 @@ PeiCore (
// PEI Core and PEIMs to get high performance.
//
OldCoreData->ShadowedPeiCore = (PEICORE_FUNCTION_POINTER) (UINTN) PeiCore;
- if ((HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnS3Boot))
- || (HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnBoot))) {
+ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
+ (HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnS3Boot)) ||
+ (HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnBoot))) {
OldCoreData->ShadowedPeiCore = ShadowPeiCore (OldCoreData);
}
@@ -418,6 +419,23 @@ PeiCore (
ProcessPpiListFromSec ((CONST EFI_PEI_SERVICES **) &PrivateData.Ps, PpiList);
}
} else {
+ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
+ //
+ // When PcdMigrateTemporaryRamFirmwareVolumes is TRUE, alway shadow all
+ // PEIMs no matter the condition of PcdShadowPeimOnBoot and PcdShadowPeimOnS3Boot
+ //
+ DEBUG ((DEBUG_VERBOSE, "PPI lists before temporary RAM evacuation:\n"));
+ DumpPpiList (&PrivateData);
+
+ //
+ // Migrate installed content from Temporary RAM to Permanent RAM
+ //
+ EvacuateTempRam (&PrivateData, SecCoreData);
+
+ DEBUG ((DEBUG_VERBOSE, "PPI lists after temporary RAM evacuation:\n"));
+ DumpPpiList (&PrivateData);
+ }
+
//
// Try to locate Temporary RAM Done Ppi.
//
diff --git a/MdeModulePkg/Core/Pei/Ppi/Ppi.c b/MdeModulePkg/Core/Pei/Ppi/Ppi.c
index 1ffe718c47..541047d98a 100644
--- a/MdeModulePkg/Core/Pei/Ppi/Ppi.c
+++ b/MdeModulePkg/Core/Pei/Ppi/Ppi.c
@@ -200,6 +200,227 @@ ConvertPpiPointers (
/**
+ Migrate Notify Pointers inside an FV from temporary memory to permanent memory.
+
+ @param PrivateData Pointer to PeiCore's private data structure.
+ @param OrgFvHandle Address of FV Handle in temporary memory.
+ @param FvHandle Address of FV Handle in permanent memory.
+ @param FvSize Size of the FV.
+
+**/
+VOID
+ConvertPpiPointersFv (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN UINTN OrgFvHandle,
+ IN UINTN FvHandle,
+ IN UINTN FvSize
+ )
+{
+ UINT8 Index;
+ UINTN Offset;
+ BOOLEAN OffsetPositive;
+ EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FvInfoPpi;
+ UINT8 GuidIndex;
+ EFI_GUID *Guid;
+ EFI_GUID *GuidCheckList[2];
+
+ GuidCheckList[0] = &gEfiPeiFirmwareVolumeInfoPpiGuid;
+ GuidCheckList[1] = &gEfiPeiFirmwareVolumeInfo2PpiGuid;
+
+ if (FvHandle > OrgFvHandle) {
+ OffsetPositive = TRUE;
+ Offset = FvHandle - OrgFvHandle;
+ } else {
+ OffsetPositive = FALSE;
+ Offset = OrgFvHandle - FvHandle;
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "Converting PPI pointers in FV.\n"));
+ DEBUG ((
+ DEBUG_VERBOSE,
+ " OrgFvHandle at 0x%08x. FvHandle at 0x%08x. FvSize = 0x%x\n",
+ (UINTN) OrgFvHandle,
+ (UINTN) FvHandle,
+ FvSize
+ ));
+ DEBUG ((
+ DEBUG_VERBOSE,
+ " OrgFvHandle range: 0x%08x - 0x%08x\n",
+ OrgFvHandle,
+ OrgFvHandle + FvSize
+ ));
+
+ for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Notify,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ }
+
+ for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Notify,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ }
+
+ for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+
+ Guid = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid;
+ for (GuidIndex = 0; GuidIndex < ARRAY_SIZE (GuidCheckList); ++GuidIndex) {
+ //
+ // Don't use CompareGuid function here for performance reasons.
+ // Instead we compare the GUID as INT32 at a time and branch
+ // on the first failed comparison.
+ //
+ if ((((INT32 *)Guid)[0] == ((INT32 *)GuidCheckList[GuidIndex])[0]) &&
+ (((INT32 *)Guid)[1] == ((INT32 *)GuidCheckList[GuidIndex])[1]) &&
+ (((INT32 *)Guid)[2] == ((INT32 *)GuidCheckList[GuidIndex])[2]) &&
+ (((INT32 *)Guid)[3] == ((INT32 *)GuidCheckList[GuidIndex])[3])) {
+ FvInfoPpi = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi;
+ DEBUG ((DEBUG_VERBOSE, " FvInfo: %p -> ", FvInfoPpi->FvInfo));
+ if ((UINTN)FvInfoPpi->FvInfo == OrgFvHandle) {
+ ConvertPointer (
+ (VOID **)&FvInfoPpi->FvInfo,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ DEBUG ((DEBUG_VERBOSE, "%p", FvInfoPpi->FvInfo));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+ break;
+ }
+ }
+ }
+}
+
+/**
+
+ Dumps the PPI lists to debug output.
+
+ @param PrivateData Points to PeiCore's private instance data.
+
+**/
+VOID
+DumpPpiList (
+ IN PEI_CORE_INSTANCE *PrivateData
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ UINTN Index;
+
+ if (PrivateData == NULL) {
+ return;
+ }
+
+ for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "CallbackNotify[%2d] {%g} at 0x%x (%a)\n",
+ Index,
+ PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,
+ (UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,
+ (
+ !(
+ ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&
+ (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)
+ )
+ ? "CAR" : "Post-Memory"
+ )
+ ));
+ }
+ for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {
+ DEBUG ((DEBUG_VERBOSE,
+ "DispatchNotify[%2d] {%g} at 0x%x (%a)\n",
+ Index,
+ PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,
+ (UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,
+ (
+ !(
+ ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw >=PrivateData->PhysicalMemoryBegin) &&
+ (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)
+ )
+ ? "CAR" : "Post-Memory"
+ )
+ ));
+ }
+ for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {
+ DEBUG ((DEBUG_VERBOSE,
+ "PPI[%2d] {%g} at 0x%x (%a)\n",
+ Index,
+ PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,
+ (UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,
+ (
+ !(
+ ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&
+ (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw) + sizeof (EFI_PEI_PPI_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)
+ )
+ ? "CAR" : "Post-Memory"
+ )
+ ));
+ }
+ DEBUG_CODE_END ();
+}
+
+/**
+
This function installs an interface in the PEI PPI database by GUID.
The purpose of the service is to publish an interface that other parties
can use to call additional PEIMs.
@@ -830,3 +1051,68 @@ ProcessPpiListFromSec (
}
}
+/**
+
+ Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory.
+
+ @param PrivateData Pointer to PeiCore's private data structure.
+ @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory.
+
+**/
+VOID
+ConvertPeiCorePpiPointers (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ PEI_CORE_FV_HANDLE CoreFvHandle
+ )
+{
+ EFI_FV_FILE_INFO FileInfo;
+ EFI_PHYSICAL_ADDRESS OrgImageBase;
+ EFI_PHYSICAL_ADDRESS MigratedImageBase;
+ UINTN PeiCoreModuleSize;
+ EFI_PEI_FILE_HANDLE PeiCoreFileHandle;
+ VOID *PeiCoreImageBase;
+ VOID *PeiCoreEntryPoint;
+ EFI_STATUS Status;
+
+ PeiCoreFileHandle = NULL;
+
+ //
+ // Find the PEI Core in the BFV in temporary memory.
+ //
+ Status = CoreFvHandle.FvPpi->FindFileByType (
+ CoreFvHandle.FvPpi,
+ EFI_FV_FILETYPE_PEI_CORE,
+ CoreFvHandle.FvHandle,
+ &PeiCoreFileHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (!EFI_ERROR (Status)) {
+ Status = CoreFvHandle.FvPpi->GetFileInfo (CoreFvHandle.FvPpi, PeiCoreFileHandle, &FileInfo);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiGetPe32Data (PeiCoreFileHandle, &PeiCoreImageBase);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Find PEI Core EntryPoint in the BFV in temporary memory.
+ //
+ Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, &PeiCoreEntryPoint);
+ ASSERT_EFI_ERROR (Status);
+
+ OrgImageBase = (UINTN) PeiCoreImageBase;
+ MigratedImageBase = (UINTN) _ModuleEntryPoint - ((UINTN) PeiCoreEntryPoint - (UINTN) PeiCoreImageBase);
+
+ //
+ // Size of loaded PEI_CORE in permanent memory.
+ //
+ PeiCoreModuleSize = (UINTN)FileInfo.BufferSize - ((UINTN) OrgImageBase - (UINTN) FileInfo.Buffer);
+
+ //
+ // Migrate PEI_CORE PPI pointers from temporary memory to newly
+ // installed PEI_CORE in permanent memory.
+ //
+ ConvertPpiPointersFv (PrivateData, (UINTN) OrgImageBase, (UINTN) MigratedImageBase, PeiCoreModuleSize);
+ }
+}
+