}\r
}\r
\r
+/**\r
+ Migrate a PEIM from temporary RAM to permanent memory.\r
+\r
+ @param PeimFileHandle Pointer to the FFS file header of the image.\r
+ @param MigratedFileHandle Pointer to the FFS file header of the migrated image.\r
+\r
+ @retval EFI_SUCCESS Sucessfully migrated the PEIM to permanent memory.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MigratePeim (\r
+ IN EFI_PEI_FILE_HANDLE FileHandle,\r
+ IN EFI_PEI_FILE_HANDLE MigratedFileHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FFS_FILE_HEADER *FileHeader;\r
+ VOID *Pe32Data;\r
+ VOID *ImageAddress;\r
+ CHAR8 *AsciiString;\r
+ UINTN Index;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ FileHeader = (EFI_FFS_FILE_HEADER *) FileHandle;\r
+ ASSERT (!IS_FFS_FILE2 (FileHeader));\r
+\r
+ ImageAddress = NULL;\r
+ PeiGetPe32Data (MigratedFileHandle, &ImageAddress);\r
+ if (ImageAddress != NULL) {\r
+ DEBUG_CODE_BEGIN ();\r
+ AsciiString = PeCoffLoaderGetPdbPointer (ImageAddress);\r
+ for (Index = 0; AsciiString[Index] != 0; Index++) {\r
+ if (AsciiString[Index] == '\\' || AsciiString[Index] == '/') {\r
+ AsciiString = AsciiString + Index + 1;\r
+ Index = 0;\r
+ } else if (AsciiString[Index] == '.') {\r
+ AsciiString[Index] = 0;\r
+ }\r
+ }\r
+ DEBUG ((DEBUG_INFO, "%a", AsciiString));\r
+ DEBUG_CODE_END ();\r
+\r
+ Pe32Data = (VOID *) ((UINTN) ImageAddress - (UINTN) MigratedFileHandle + (UINTN) FileHandle);\r
+ Status = LoadAndRelocatePeCoffImageInPlace (Pe32Data, ImageAddress);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Migrate Status Code Callback function pointers inside an FV from temporary memory to permanent memory.\r
+\r
+ @param OrgFvHandle Address of FV handle in temporary memory.\r
+ @param FvHandle Address of FV handle in permanent memory.\r
+ @param FvSize Size of the FV.\r
+\r
+**/\r
+VOID\r
+ConvertStatusCodeCallbacks (\r
+ IN UINTN OrgFvHandle,\r
+ IN UINTN FvHandle,\r
+ IN UINTN FvSize\r
+ )\r
+{\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+ UINTN *NumberOfEntries;\r
+ UINTN *CallbackEntry;\r
+ UINTN Index;\r
+\r
+ Hob.Raw = GetFirstGuidHob (&gStatusCodeCallbackGuid);\r
+ while (Hob.Raw != NULL) {\r
+ NumberOfEntries = GET_GUID_HOB_DATA (Hob);\r
+ CallbackEntry = NumberOfEntries + 1;\r
+ for (Index = 0; Index < *NumberOfEntries; Index++) {\r
+ if (((VOID *) CallbackEntry[Index]) != NULL) {\r
+ if ((CallbackEntry[Index] >= OrgFvHandle) && (CallbackEntry[Index] < (OrgFvHandle + FvSize))) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "Migrating CallbackEntry[%Lu] from 0x%0*Lx to ",\r
+ (UINT64)Index,\r
+ (sizeof CallbackEntry[Index]) * 2,\r
+ (UINT64)CallbackEntry[Index]\r
+ ));\r
+ if (OrgFvHandle > FvHandle) {\r
+ CallbackEntry[Index] = CallbackEntry[Index] - (OrgFvHandle - FvHandle);\r
+ } else {\r
+ CallbackEntry[Index] = CallbackEntry[Index] + (FvHandle - OrgFvHandle);\r
+ }\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "0x%0*Lx\n",\r
+ (sizeof CallbackEntry[Index]) * 2,\r
+ (UINT64)CallbackEntry[Index]\r
+ ));\r
+ }\r
+ }\r
+ }\r
+ Hob.Raw = GET_NEXT_HOB (Hob);\r
+ Hob.Raw = GetNextGuidHob (&gStatusCodeCallbackGuid, Hob.Raw);\r
+ }\r
+}\r
+\r
+/**\r
+ Migrates SEC modules in the given firmware volume.\r
+\r
+ Migrating SECURITY_CORE files requires special treatment since they are not tracked for PEI dispatch.\r
+\r
+ This functioun should be called after the FV has been copied to its post-memory location and the PEI Core FV list has\r
+ been updated.\r
+\r
+ @param Private Pointer to the PeiCore's private data structure.\r
+ @param FvIndex The firmware volume index to migrate.\r
+ @param OrgFvHandle The handle to the firmware volume in temporary memory.\r
+\r
+ @retval EFI_SUCCESS SEC modules were migrated successfully\r
+ @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid.\r
+ @retval EFI_NOT_FOUND Can't find valid FFS header.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MigrateSecModulesInFv (\r
+ IN PEI_CORE_INSTANCE *Private,\r
+ IN UINTN FvIndex,\r
+ IN UINTN OrgFvHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STATUS FindFileStatus;\r
+ EFI_PEI_FILE_HANDLE MigratedFileHandle;\r
+ EFI_PEI_FILE_HANDLE FileHandle;\r
+ UINT32 SectionAuthenticationStatus;\r
+ UINT32 FileSize;\r
+ VOID *OrgPe32SectionData;\r
+ VOID *Pe32SectionData;\r
+ EFI_FFS_FILE_HEADER *FfsFileHeader;\r
+ EFI_COMMON_SECTION_HEADER *Section;\r
+ BOOLEAN IsFfs3Fv;\r
+ UINTN SectionInstance;\r
+\r
+ if (Private == NULL || FvIndex >= Private->FvCount) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ do {\r
+ FindFileStatus = PeiFfsFindNextFile (\r
+ GetPeiServicesTablePointer (),\r
+ EFI_FV_FILETYPE_SECURITY_CORE,\r
+ Private->Fv[FvIndex].FvHandle,\r
+ &MigratedFileHandle\r
+ );\r
+ if (!EFI_ERROR (FindFileStatus ) && MigratedFileHandle != NULL) {\r
+ FileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) MigratedFileHandle - (UINTN) Private->Fv[FvIndex].FvHandle + OrgFvHandle);\r
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *) MigratedFileHandle;\r
+\r
+ DEBUG ((DEBUG_VERBOSE, " Migrating SEC_CORE MigratedFileHandle at 0x%x.\n", (UINTN) MigratedFileHandle));\r
+ DEBUG ((DEBUG_VERBOSE, " FileHandle at 0x%x.\n", (UINTN) FileHandle));\r
+\r
+ IsFfs3Fv = CompareGuid (&Private->Fv[FvIndex].FvHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);\r
+ if (IS_FFS_FILE2 (FfsFileHeader)) {\r
+ ASSERT (FFS_FILE2_SIZE (FfsFileHeader) > 0x00FFFFFF);\r
+ if (!IsFfs3Fv) {\r
+ DEBUG ((DEBUG_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2));\r
+ FileSize = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);\r
+ } else {\r
+ Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));\r
+ FileSize = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER);\r
+ }\r
+\r
+ SectionInstance = 1;\r
+ SectionAuthenticationStatus = 0;\r
+ Status = ProcessSection (\r
+ GetPeiServicesTablePointer (),\r
+ EFI_SECTION_PE32,\r
+ &SectionInstance,\r
+ Section,\r
+ FileSize,\r
+ &Pe32SectionData,\r
+ &SectionAuthenticationStatus,\r
+ IsFfs3Fv\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ OrgPe32SectionData = (VOID *) ((UINTN) Pe32SectionData - (UINTN) MigratedFileHandle + (UINTN) FileHandle);\r
+ DEBUG ((DEBUG_VERBOSE, " PE32 section in migrated file at 0x%x.\n", (UINTN) Pe32SectionData));\r
+ DEBUG ((DEBUG_VERBOSE, " PE32 section in original file at 0x%x.\n", (UINTN) OrgPe32SectionData));\r
+ Status = LoadAndRelocatePeCoffImageInPlace (OrgPe32SectionData, Pe32SectionData);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ }\r
+ } while (!EFI_ERROR (FindFileStatus));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Migrates PEIMs in the given firmware volume.\r
+\r
+ @param Private Pointer to the PeiCore's private data structure.\r
+ @param FvIndex The firmware volume index to migrate.\r
+ @param OrgFvHandle The handle to the firmware volume in temporary memory.\r
+ @param FvHandle The handle to the firmware volume in permanent memory.\r
+\r
+ @retval EFI_SUCCESS The PEIMs in the FV were migrated successfully\r
+ @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MigratePeimsInFv (\r
+ IN PEI_CORE_INSTANCE *Private,\r
+ IN UINTN FvIndex,\r
+ IN UINTN OrgFvHandle,\r
+ IN UINTN FvHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ volatile UINTN FileIndex;\r
+ EFI_PEI_FILE_HANDLE MigratedFileHandle;\r
+ EFI_PEI_FILE_HANDLE FileHandle;\r
+\r
+ if (Private == NULL || FvIndex >= Private->FvCount) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Private->Fv[FvIndex].ScanFv) {\r
+ for (FileIndex = 0; FileIndex < Private->Fv[FvIndex].PeimCount; FileIndex++) {\r
+ if (Private->Fv[FvIndex].FvFileHandles[FileIndex] != NULL) {\r
+ FileHandle = Private->Fv[FvIndex].FvFileHandles[FileIndex];\r
+\r
+ MigratedFileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) FileHandle - OrgFvHandle + FvHandle);\r
+\r
+ DEBUG ((DEBUG_VERBOSE, " Migrating FileHandle %2d ", FileIndex));\r
+ Status = MigratePeim (FileHandle, MigratedFileHandle);\r
+ DEBUG ((DEBUG_VERBOSE, "\n"));\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ Private->Fv[FvIndex].FvFileHandles[FileIndex] = MigratedFileHandle;\r
+ if (FvIndex == Private->CurrentPeimFvCount) {\r
+ Private->CurrentFvFileHandles[FileIndex] = MigratedFileHandle;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Migrate FVs out of temporary RAM before the cache is flushed.\r
+\r
+ @param Private PeiCore's private data structure\r
+ @param SecCoreData Points to a data structure containing information about the PEI core's operating\r
+ environment, such as the size and location of temporary RAM, the stack location and\r
+ the BFV location.\r
+\r
+ @retval EFI_SUCCESS Succesfully migrated installed FVs from temporary RAM to permanent memory.\r
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EvacuateTempRam (\r
+ IN PEI_CORE_INSTANCE *Private,\r
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ volatile UINTN FvIndex;\r
+ volatile UINTN FvChildIndex;\r
+ UINTN ChildFvOffset;\r
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
+ EFI_FIRMWARE_VOLUME_HEADER *ChildFvHeader;\r
+ EFI_FIRMWARE_VOLUME_HEADER *MigratedFvHeader;\r
+ EFI_FIRMWARE_VOLUME_HEADER *MigratedChildFvHeader;\r
+\r
+ PEI_CORE_FV_HANDLE PeiCoreFvHandle;\r
+ EFI_PEI_CORE_FV_LOCATION_PPI *PeiCoreFvLocationPpi;\r
+\r
+ ASSERT (Private->PeiMemoryInstalled);\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "Beginning evacuation of content in temporary RAM.\n"));\r
+\r
+ //\r
+ // Migrate PPI Pointers of PEI_CORE from temporary memory to newly loaded PEI_CORE in permanent memory.\r
+ //\r
+ Status = PeiLocatePpi ((CONST EFI_PEI_SERVICES **) &Private->Ps, &gEfiPeiCoreFvLocationPpiGuid, 0, NULL, (VOID **) &PeiCoreFvLocationPpi);\r
+ if (!EFI_ERROR (Status) && (PeiCoreFvLocationPpi->PeiCoreFvLocation != NULL)) {\r
+ PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) PeiCoreFvLocationPpi->PeiCoreFvLocation;\r
+ } else {\r
+ PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) SecCoreData->BootFirmwareVolumeBase;\r
+ }\r
+ for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {\r
+ if (Private->Fv[FvIndex].FvHandle == PeiCoreFvHandle.FvHandle) {\r
+ PeiCoreFvHandle = Private->Fv[FvIndex];\r
+ break;\r
+ }\r
+ }\r
+ Status = EFI_SUCCESS;\r
+\r
+ ConvertPeiCorePpiPointers (Private, PeiCoreFvHandle);\r
+\r
+ for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {\r
+ FvHeader = Private->Fv[FvIndex].FvHeader;\r
+ ASSERT (FvHeader != NULL);\r
+ ASSERT (FvIndex < Private->FvCount);\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "FV[%02d] at 0x%x.\n", FvIndex, (UINTN) FvHeader));\r
+ if (\r
+ !(\r
+ ((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader >= Private->PhysicalMemoryBegin) &&\r
+ (((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader + (FvHeader->FvLength - 1)) < Private->FreePhysicalMemoryTop)\r
+ )\r
+ ) {\r
+ Status = PeiServicesAllocatePages (\r
+ EfiBootServicesCode,\r
+ EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength),\r
+ (EFI_PHYSICAL_ADDRESS *) &MigratedFvHeader\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ DEBUG ((\r
+ DEBUG_VERBOSE,\r
+ " Migrating FV[%d] from 0x%08X to 0x%08X\n",\r
+ FvIndex,\r
+ (UINTN) FvHeader,\r
+ (UINTN) MigratedFvHeader\r
+ ));\r
+\r
+ CopyMem (MigratedFvHeader, FvHeader, (UINTN) FvHeader->FvLength);\r
+\r
+ //\r
+ // Migrate any children for this FV now\r
+ //\r
+ for (FvChildIndex = FvIndex; FvChildIndex < Private->FvCount; FvChildIndex++) {\r
+ ChildFvHeader = Private->Fv[FvChildIndex].FvHeader;\r
+ if (\r
+ ((UINTN) ChildFvHeader > (UINTN) FvHeader) &&\r
+ (((UINTN) ChildFvHeader + ChildFvHeader->FvLength) < ((UINTN) FvHeader) + FvHeader->FvLength)\r
+ ) {\r
+ DEBUG ((DEBUG_VERBOSE, " Child FV[%02d] is being migrated.\n", FvChildIndex));\r
+ ChildFvOffset = (UINTN) ChildFvHeader - (UINTN) FvHeader;\r
+ DEBUG ((DEBUG_VERBOSE, " Child FV offset = 0x%x.\n", ChildFvOffset));\r
+ MigratedChildFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) MigratedFvHeader + ChildFvOffset);\r
+ Private->Fv[FvChildIndex].FvHeader = MigratedChildFvHeader;\r
+ Private->Fv[FvChildIndex].FvHandle = (EFI_PEI_FV_HANDLE) MigratedChildFvHeader;\r
+ DEBUG ((DEBUG_VERBOSE, " Child migrated FV header at 0x%x.\n", (UINTN) MigratedChildFvHeader));\r
+\r
+ Status = MigratePeimsInFv (Private, FvChildIndex, (UINTN) ChildFvHeader, (UINTN) MigratedChildFvHeader);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ ConvertPpiPointersFv (\r
+ Private,\r
+ (UINTN) ChildFvHeader,\r
+ (UINTN) MigratedChildFvHeader,\r
+ (UINTN) ChildFvHeader->FvLength - 1\r
+ );\r
+\r
+ ConvertStatusCodeCallbacks (\r
+ (UINTN) ChildFvHeader,\r
+ (UINTN) MigratedChildFvHeader,\r
+ (UINTN) ChildFvHeader->FvLength - 1\r
+ );\r
+\r
+ ConvertFvHob (Private, (UINTN) ChildFvHeader, (UINTN) MigratedChildFvHeader);\r
+ }\r
+ }\r
+ Private->Fv[FvIndex].FvHeader = MigratedFvHeader;\r
+ Private->Fv[FvIndex].FvHandle = (EFI_PEI_FV_HANDLE) MigratedFvHeader;\r
+\r
+ Status = MigratePeimsInFv (Private, FvIndex, (UINTN) FvHeader, (UINTN) MigratedFvHeader);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ ConvertPpiPointersFv (\r
+ Private,\r
+ (UINTN) FvHeader,\r
+ (UINTN) MigratedFvHeader,\r
+ (UINTN) FvHeader->FvLength - 1\r
+ );\r
+\r
+ ConvertStatusCodeCallbacks (\r
+ (UINTN) FvHeader,\r
+ (UINTN) MigratedFvHeader,\r
+ (UINTN) FvHeader->FvLength - 1\r
+ );\r
+\r
+ ConvertFvHob (Private, (UINTN) FvHeader, (UINTN) MigratedFvHeader);\r
+ }\r
+ }\r
+\r
+ RemoveFvHobsInTemporaryMemory (Private);\r
+\r
+ return Status;\r
+}\r
+\r
/**\r
Conduct PEIM dispatch.\r
\r
PeimFileHandle = NULL;\r
EntryPoint = 0;\r
\r
- if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {\r
+ if ((Private->PeiMemoryInstalled) &&\r
+ (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||\r
+ (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||\r
+ PcdGetBool (PcdShadowPeimOnS3Boot))\r
+ ) {\r
//\r
// Once real memory is available, shadow the RegisterForShadow modules. And meanwhile\r
// update the modules' status from PEIM_STATE_REGISTER_FOR_SHADOW to PEIM_STATE_DONE.\r
PeiCheckAndSwitchStack (SecCoreData, Private);\r
\r
if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISTER_FOR_SHADOW) && \\r
- (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {\r
+ (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||\r
+ (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||\r
+ PcdGetBool (PcdShadowPeimOnS3Boot))\r
+ ) {\r
//\r
// If memory is available we shadow images by default for performance reasons.\r
// We call the entry point a 2nd time so the module knows it's shadowed.\r
//\r
//PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);\r
- if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot)) {\r
+ if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot) &&\r
+ !PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {\r
//\r
// Load PEIM into Memory for Register for shadow PEIM.\r
//\r
//\r
// When Image has no reloc section, it can't be relocated into memory.\r
//\r
- if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) && ((!IsPeiModule) ||\r
- (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) || (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))) {\r
+ if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) &&\r
+ ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||\r
+ (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) ||\r
+ (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))\r
+ ) {\r
DEBUG ((EFI_D_INFO|EFI_D_LOAD, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN) Pe32Data));\r
}\r
\r
// On normal boot, PcdShadowPeimOnBoot decides whether load PEIM or PeiCore into memory.\r
// On S3 boot, PcdShadowPeimOnS3Boot decides whether load PEIM or PeiCore into memory.\r
//\r
- if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && ((!IsPeiModule) ||\r
- (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) || (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))) {\r
+ if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) &&\r
+ ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||\r
+ (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) ||\r
+ (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))\r
+ ) {\r
//\r
// Allocate more buffer to avoid buffer overflow.\r
//\r
return ReturnStatus;\r
}\r
\r
+/**\r
+ Loads and relocates a PE/COFF image in place.\r
+\r
+ @param Pe32Data The base address of the PE/COFF file that is to be loaded and relocated\r
+ @param ImageAddress The base address of the relocated PE/COFF image\r
+\r
+ @retval EFI_SUCCESS The file was loaded and relocated.\r
+ @retval Others The file not be loaded and error occurred.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadAndRelocatePeCoffImageInPlace (\r
+ IN VOID *Pe32Data,\r
+ IN VOID *ImageAddress\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
+\r
+ ZeroMem (&ImageContext, sizeof (ImageContext));\r
+ ImageContext.Handle = Pe32Data;\r
+ ImageContext.ImageRead = PeiImageRead;\r
+\r
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT_EFI_ERROR (Status);\r
+ return Status;\r
+ }\r
+\r
+ ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN) ImageAddress;\r
+\r
+ //\r
+ // Load the image in place\r
+ //\r
+ Status = PeCoffLoaderLoadImage (&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT_EFI_ERROR (Status);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Relocate the image in place\r
+ //\r
+ Status = PeCoffLoaderRelocateImage (&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT_EFI_ERROR (Status);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Flush the instruction cache so the image data is written before we execute it\r
+ //\r
+ if (ImageContext.ImageAddress != (EFI_PHYSICAL_ADDRESS)(UINTN) Pe32Data) {\r
+ InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Find the PE32 Data for an FFS file.\r
+\r
+ @param FileHandle Pointer to the FFS file header of the image.\r
+ @param Pe32Data Pointer to a (VOID *) PE32 Data pointer.\r
+\r
+ @retval EFI_SUCCESS Image is successfully loaded.\r
+ @retval EFI_NOT_FOUND Fail to locate PE32 Data.\r
+\r
+**/\r
+EFI_STATUS\r
+PeiGetPe32Data (\r
+ IN EFI_PEI_FILE_HANDLE FileHandle,\r
+ OUT VOID **Pe32Data\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SECTION_TYPE SearchType1;\r
+ EFI_SECTION_TYPE SearchType2;\r
+ UINT32 AuthenticationState;\r
+\r
+ *Pe32Data = NULL;\r
+\r
+ if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) {\r
+ SearchType1 = EFI_SECTION_TE;\r
+ SearchType2 = EFI_SECTION_PE32;\r
+ } else {\r
+ SearchType1 = EFI_SECTION_PE32;\r
+ SearchType2 = EFI_SECTION_TE;\r
+ }\r
+\r
+ //\r
+ // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst\r
+ // is true, TE will be searched first).\r
+ //\r
+ Status = PeiServicesFfsFindSectionData3 (\r
+ SearchType1,\r
+ 0,\r
+ FileHandle,\r
+ Pe32Data,\r
+ &AuthenticationState\r
+ );\r
+ //\r
+ // If we didn't find a first exe section, try to find the second exe section.\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ Status = PeiServicesFfsFindSectionData3 (\r
+ SearchType2,\r
+ 0,\r
+ FileHandle,\r
+ Pe32Data,\r
+ &AuthenticationState\r
+ );\r
+ }\r
+ return Status;\r
+}\r
+\r
/**\r
Loads a PEIM into memory for subsequent execution. If there are compressed\r
images or images that need to be relocated into memory for performance reasons,\r
Private->FreePhysicalMemoryTop = NewMemPagesBase;\r
}\r
\r
+/**\r
+ Removes any FV HOBs whose base address is not in PEI installed memory.\r
+\r
+ @param[in] Private Pointer to PeiCore's private data structure.\r
+\r
+**/\r
+VOID\r
+RemoveFvHobsInTemporaryMemory (\r
+ IN PEI_CORE_INSTANCE *Private\r
+ )\r
+{\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+ EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;\r
+\r
+ DEBUG ((DEBUG_INFO, "Removing FVs in FV HOB not already migrated to permanent memory.\n"));\r
+\r
+ for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {\r
+ 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) {\r
+ FirmwareVolumeHob = Hob.FirmwareVolume;\r
+ DEBUG ((DEBUG_INFO, " Found FV HOB.\n"));\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ " BA=%016lx L=%016lx\n",\r
+ FirmwareVolumeHob->BaseAddress,\r
+ FirmwareVolumeHob->Length\r
+ ));\r
+ if (\r
+ !(\r
+ ((EFI_PHYSICAL_ADDRESS) (UINTN) FirmwareVolumeHob->BaseAddress >= Private->PhysicalMemoryBegin) &&\r
+ (((EFI_PHYSICAL_ADDRESS) (UINTN) FirmwareVolumeHob->BaseAddress + (FirmwareVolumeHob->Length - 1)) < Private->FreePhysicalMemoryTop)\r
+ )\r
+ ) {\r
+ DEBUG ((DEBUG_INFO, " Removing FV HOB to an FV in T-RAM (was not migrated).\n"));\r
+ Hob.Header->HobType = EFI_HOB_TYPE_UNUSED;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Migrate the base address in firmware volume allocation HOBs\r
+ from temporary memory to PEI installed memory.\r
+\r
+ @param[in] PrivateData Pointer to PeiCore's private data structure.\r
+ @param[in] OrgFvHandle Address of FV Handle in temporary memory.\r
+ @param[in] FvHandle Address of FV Handle in permanent memory.\r
+\r
+**/\r
+VOID\r
+ConvertFvHob (\r
+ IN PEI_CORE_INSTANCE *PrivateData,\r
+ IN UINTN OrgFvHandle,\r
+ IN UINTN FvHandle\r
+ )\r
+{\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+ EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;\r
+ EFI_HOB_FIRMWARE_VOLUME2 *FirmwareVolume2Hob;\r
+ EFI_HOB_FIRMWARE_VOLUME3 *FirmwareVolume3Hob;\r
+\r
+ DEBUG ((DEBUG_INFO, "Converting FVs in FV HOB.\n"));\r
+\r
+ for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {\r
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {\r
+ FirmwareVolumeHob = Hob.FirmwareVolume;\r
+ if (FirmwareVolumeHob->BaseAddress == OrgFvHandle) {\r
+ FirmwareVolumeHob->BaseAddress = FvHandle;\r
+ }\r
+ } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV2) {\r
+ FirmwareVolume2Hob = Hob.FirmwareVolume2;\r
+ if (FirmwareVolume2Hob->BaseAddress == OrgFvHandle) {\r
+ FirmwareVolume2Hob->BaseAddress = FvHandle;\r
+ }\r
+ } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV3) {\r
+ FirmwareVolume3Hob = Hob.FirmwareVolume3;\r
+ if (FirmwareVolume3Hob->BaseAddress == OrgFvHandle) {\r
+ FirmwareVolume3Hob->BaseAddress = FvHandle;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
/**\r
Migrate MemoryBaseAddress in memory allocation HOBs\r
from the temporary memory to PEI installed memory.\r
IN VOID *DependencyExpression\r
);\r
\r
+/**\r
+ Migrate a PEIM from temporary RAM to permanent memory.\r
+\r
+ @param PeimFileHandle Pointer to the FFS file header of the image.\r
+ @param MigratedFileHandle Pointer to the FFS file header of the migrated image.\r
+\r
+ @retval EFI_SUCCESS Sucessfully migrated the PEIM to permanent memory.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MigratePeim (\r
+ IN EFI_PEI_FILE_HANDLE FileHandle,\r
+ IN EFI_PEI_FILE_HANDLE MigratedFileHandle\r
+ );\r
+\r
+/**\r
+ Migrate FVs out of temporary RAM before the cache is flushed.\r
+\r
+ @param Private PeiCore's private data structure\r
+ @param SecCoreData Points to a data structure containing information about the PEI core's operating\r
+ environment, such as the size and location of temporary RAM, the stack location and\r
+ the BFV location.\r
+\r
+ @retval EFI_SUCCESS Succesfully migrated installed FVs from temporary RAM to permanent memory.\r
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EvacuateTempRam (\r
+ IN PEI_CORE_INSTANCE *Private,\r
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData\r
+ );\r
+\r
/**\r
Conduct PEIM dispatch.\r
\r
IN PEI_CORE_INSTANCE *PrivateData\r
);\r
\r
+/**\r
+\r
+ Migrate Notify Pointers inside an FV from temporary memory to permanent memory.\r
+\r
+ @param PrivateData Pointer to PeiCore's private data structure.\r
+ @param OrgFvHandle Address of FV Handle in temporary memory.\r
+ @param FvHandle Address of FV Handle in permanent memory.\r
+ @param FvSize Size of the FV.\r
+\r
+**/\r
+VOID\r
+ConvertPpiPointersFv (\r
+ IN PEI_CORE_INSTANCE *PrivateData,\r
+ IN UINTN OrgFvHandle,\r
+ IN UINTN FvHandle,\r
+ IN UINTN FvSize\r
+ );\r
+\r
+/**\r
+\r
+ Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory.\r
+\r
+ @param PrivateData Pointer to PeiCore's private data structure.\r
+ @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory.\r
+\r
+**/\r
+VOID\r
+ConvertPeiCorePpiPointers (\r
+ IN PEI_CORE_INSTANCE *PrivateData,\r
+ PEI_CORE_FV_HANDLE CoreFvHandle\r
+ );\r
+\r
+/**\r
+\r
+ Dumps the PPI lists to debug output.\r
+\r
+ @param PrivateData Points to PeiCore's private instance data.\r
+\r
+**/\r
+VOID\r
+DumpPpiList (\r
+ IN PEI_CORE_INSTANCE *PrivateData\r
+ );\r
+\r
/**\r
\r
Install PPI services. It is implementation of EFI_PEI_SERVICE.InstallPpi.\r
IN OUT EFI_PEI_FILE_HANDLE *FileHandle\r
);\r
\r
+/**\r
+ Go through the file to search SectionType section.\r
+ Search within encapsulation sections (compression and GUIDed) recursively,\r
+ until the match section is found.\r
+\r
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
+ @param SectionType Filter to find only section of this type.\r
+ @param SectionInstance Pointer to the filter to find the specific instance of section.\r
+ @param Section From where to search.\r
+ @param SectionSize The file size to search.\r
+ @param OutputBuffer A pointer to the discovered section, if successful.\r
+ NULL if section not found.\r
+ @param AuthenticationStatus Updated upon return to point to the authentication status for this section.\r
+ @param IsFfs3Fv Indicates the FV format.\r
+\r
+ @return EFI_NOT_FOUND The match section is not found.\r
+ @return EFI_SUCCESS The match section is found.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessSection (\r
+ IN CONST EFI_PEI_SERVICES **PeiServices,\r
+ IN EFI_SECTION_TYPE SectionType,\r
+ IN OUT UINTN *SectionInstance,\r
+ IN EFI_COMMON_SECTION_HEADER *Section,\r
+ IN UINTN SectionSize,\r
+ OUT VOID **OutputBuffer,\r
+ OUT UINT32 *AuthenticationStatus,\r
+ IN BOOLEAN IsFfs3Fv\r
+ );\r
+\r
/**\r
Searches for the next matching section within the specified file.\r
\r
IN BOOLEAN TemporaryRamMigrated\r
);\r
\r
+/**\r
+ Removes any FV HOBs whose base address is not in PEI installed memory.\r
+\r
+ @param[in] Private Pointer to PeiCore's private data structure.\r
+\r
+**/\r
+VOID\r
+RemoveFvHobsInTemporaryMemory (\r
+ IN PEI_CORE_INSTANCE *Private\r
+ );\r
+\r
+/**\r
+ Migrate the base address in firmware volume allocation HOBs\r
+ from temporary memory to PEI installed memory.\r
+\r
+ @param[in] PrivateData Pointer to PeiCore's private data structure.\r
+ @param[in] OrgFvHandle Address of FV Handle in temporary memory.\r
+ @param[in] FvHandle Address of FV Handle in permanent memory.\r
+\r
+**/\r
+VOID\r
+ConvertFvHob (\r
+ IN PEI_CORE_INSTANCE *PrivateData,\r
+ IN UINTN OrgFvHandle,\r
+ IN UINTN FvHandle\r
+ );\r
+\r
/**\r
Migrate MemoryBaseAddress in memory allocation HOBs\r
from the temporary memory to PEI installed memory.\r
IN PEI_CORE_INSTANCE *OldCoreData\r
);\r
\r
+/**\r
+ Loads and relocates a PE/COFF image in place.\r
+\r
+ @param Pe32Data The base address of the PE/COFF file that is to be loaded and relocated\r
+ @param ImageAddress The base address of the relocated PE/COFF image\r
+\r
+ @retval EFI_SUCCESS The file was loaded and relocated\r
+ @retval Others The file not be loaded and error occurred.\r
+\r
+**/\r
+EFI_STATUS\r
+LoadAndRelocatePeCoffImageInPlace (\r
+ IN VOID *Pe32Data,\r
+ IN VOID *ImageAddress\r
+ );\r
+\r
+/**\r
+ Find the PE32 Data for an FFS file.\r
+\r
+ @param FileHandle Pointer to the FFS file header of the image.\r
+ @param Pe32Data Pointer to a (VOID *) PE32 Data pointer.\r
+\r
+ @retval EFI_SUCCESS Image is successfully loaded.\r
+ @retval EFI_NOT_FOUND Fail to locate PE32 Data.\r
+\r
+**/\r
+EFI_STATUS\r
+PeiGetPe32Data (\r
+ IN EFI_PEI_FILE_HANDLE FileHandle,\r
+ OUT VOID **Pe32Data\r
+ );\r
+\r
/**\r
The wrapper function of PeiLoadImageLoadImage().\r
\r
## CONSUMES ## UNDEFINED # Locate PPI\r
## CONSUMES ## GUID # Used to compare with FV's file system GUID and get the FV's file system format\r
gEfiFirmwareFileSystem3Guid\r
+ gStatusCodeCallbackGuid\r
\r
[Ppis]\r
gEfiPeiStatusCodePpiGuid ## SOMETIMES_CONSUMES # PeiReportStatusService is not ready if this PPI doesn't exist\r
gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnS3Boot ## CONSUMES\r
gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot ## CONSUMES\r
gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack ## CONSUMES\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES\r
\r
# [BootMode]\r
# S3_RESUME ## SOMETIMES_CONSUMES\r
// PEI Core and PEIMs to get high performance.\r
//\r
OldCoreData->ShadowedPeiCore = (PEICORE_FUNCTION_POINTER) (UINTN) PeiCore;\r
- if ((HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnS3Boot))\r
- || (HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnBoot))) {\r
+ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||\r
+ (HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnS3Boot)) ||\r
+ (HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnBoot))) {\r
OldCoreData->ShadowedPeiCore = ShadowPeiCore (OldCoreData);\r
}\r
\r
ProcessPpiListFromSec ((CONST EFI_PEI_SERVICES **) &PrivateData.Ps, PpiList);\r
}\r
} else {\r
+ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {\r
+ //\r
+ // When PcdMigrateTemporaryRamFirmwareVolumes is TRUE, alway shadow all\r
+ // PEIMs no matter the condition of PcdShadowPeimOnBoot and PcdShadowPeimOnS3Boot\r
+ //\r
+ DEBUG ((DEBUG_VERBOSE, "PPI lists before temporary RAM evacuation:\n"));\r
+ DumpPpiList (&PrivateData);\r
+\r
+ //\r
+ // Migrate installed content from Temporary RAM to Permanent RAM\r
+ //\r
+ EvacuateTempRam (&PrivateData, SecCoreData);\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "PPI lists after temporary RAM evacuation:\n"));\r
+ DumpPpiList (&PrivateData);\r
+ }\r
+\r
//\r
// Try to locate Temporary RAM Done Ppi.\r
//\r
}\r
}\r
\r
+/**\r
+\r
+ Migrate Notify Pointers inside an FV from temporary memory to permanent memory.\r
+\r
+ @param PrivateData Pointer to PeiCore's private data structure.\r
+ @param OrgFvHandle Address of FV Handle in temporary memory.\r
+ @param FvHandle Address of FV Handle in permanent memory.\r
+ @param FvSize Size of the FV.\r
+\r
+**/\r
+VOID\r
+ConvertPpiPointersFv (\r
+ IN PEI_CORE_INSTANCE *PrivateData,\r
+ IN UINTN OrgFvHandle,\r
+ IN UINTN FvHandle,\r
+ IN UINTN FvSize\r
+ )\r
+{\r
+ UINT8 Index;\r
+ UINTN Offset;\r
+ BOOLEAN OffsetPositive;\r
+ EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FvInfoPpi;\r
+ UINT8 GuidIndex;\r
+ EFI_GUID *Guid;\r
+ EFI_GUID *GuidCheckList[2];\r
+\r
+ GuidCheckList[0] = &gEfiPeiFirmwareVolumeInfoPpiGuid;\r
+ GuidCheckList[1] = &gEfiPeiFirmwareVolumeInfo2PpiGuid;\r
+\r
+ if (FvHandle > OrgFvHandle) {\r
+ OffsetPositive = TRUE;\r
+ Offset = FvHandle - OrgFvHandle;\r
+ } else {\r
+ OffsetPositive = FALSE;\r
+ Offset = OrgFvHandle - FvHandle;\r
+ }\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "Converting PPI pointers in FV.\n"));\r
+ DEBUG ((\r
+ DEBUG_VERBOSE,\r
+ " OrgFvHandle at 0x%08x. FvHandle at 0x%08x. FvSize = 0x%x\n",\r
+ (UINTN) OrgFvHandle,\r
+ (UINTN) FvHandle,\r
+ FvSize\r
+ ));\r
+ DEBUG ((\r
+ DEBUG_VERBOSE,\r
+ " OrgFvHandle range: 0x%08x - 0x%08x\n",\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize\r
+ ));\r
+\r
+ for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {\r
+ ConvertPointer (\r
+ (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ ConvertPointer (\r
+ (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ ConvertPointer (\r
+ (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Notify,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ }\r
+\r
+ for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {\r
+ ConvertPointer (\r
+ (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ ConvertPointer (\r
+ (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ ConvertPointer (\r
+ (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Notify,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ }\r
+\r
+ for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
+ ConvertPointer (\r
+ (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ ConvertPointer (\r
+ (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ ConvertPointer (\r
+ (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+\r
+ Guid = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid;\r
+ for (GuidIndex = 0; GuidIndex < ARRAY_SIZE (GuidCheckList); ++GuidIndex) {\r
+ //\r
+ // Don't use CompareGuid function here for performance reasons.\r
+ // Instead we compare the GUID as INT32 at a time and branch\r
+ // on the first failed comparison.\r
+ //\r
+ if ((((INT32 *)Guid)[0] == ((INT32 *)GuidCheckList[GuidIndex])[0]) &&\r
+ (((INT32 *)Guid)[1] == ((INT32 *)GuidCheckList[GuidIndex])[1]) &&\r
+ (((INT32 *)Guid)[2] == ((INT32 *)GuidCheckList[GuidIndex])[2]) &&\r
+ (((INT32 *)Guid)[3] == ((INT32 *)GuidCheckList[GuidIndex])[3])) {\r
+ FvInfoPpi = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi;\r
+ DEBUG ((DEBUG_VERBOSE, " FvInfo: %p -> ", FvInfoPpi->FvInfo));\r
+ if ((UINTN)FvInfoPpi->FvInfo == OrgFvHandle) {\r
+ ConvertPointer (\r
+ (VOID **)&FvInfoPpi->FvInfo,\r
+ OrgFvHandle,\r
+ OrgFvHandle + FvSize,\r
+ Offset,\r
+ OffsetPositive\r
+ );\r
+ DEBUG ((DEBUG_VERBOSE, "%p", FvInfoPpi->FvInfo));\r
+ }\r
+ DEBUG ((DEBUG_VERBOSE, "\n"));\r
+ break;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Dumps the PPI lists to debug output.\r
+\r
+ @param PrivateData Points to PeiCore's private instance data.\r
+\r
+**/\r
+VOID\r
+DumpPpiList (\r
+ IN PEI_CORE_INSTANCE *PrivateData\r
+ )\r
+{\r
+ DEBUG_CODE_BEGIN ();\r
+ UINTN Index;\r
+\r
+ if (PrivateData == NULL) {\r
+ return;\r
+ }\r
+\r
+ for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {\r
+ DEBUG ((\r
+ DEBUG_VERBOSE,\r
+ "CallbackNotify[%2d] {%g} at 0x%x (%a)\n",\r
+ Index,\r
+ PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,\r
+ (UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,\r
+ (\r
+ !(\r
+ ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&\r
+ (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)\r
+ )\r
+ ? "CAR" : "Post-Memory"\r
+ )\r
+ ));\r
+ }\r
+ for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {\r
+ DEBUG ((DEBUG_VERBOSE,\r
+ "DispatchNotify[%2d] {%g} at 0x%x (%a)\n",\r
+ Index,\r
+ PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,\r
+ (UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,\r
+ (\r
+ !(\r
+ ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw >=PrivateData->PhysicalMemoryBegin) &&\r
+ (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)\r
+ )\r
+ ? "CAR" : "Post-Memory"\r
+ )\r
+ ));\r
+ }\r
+ for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {\r
+ DEBUG ((DEBUG_VERBOSE,\r
+ "PPI[%2d] {%g} at 0x%x (%a)\n",\r
+ Index,\r
+ PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,\r
+ (UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,\r
+ (\r
+ !(\r
+ ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&\r
+ (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw) + sizeof (EFI_PEI_PPI_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)\r
+ )\r
+ ? "CAR" : "Post-Memory"\r
+ )\r
+ ));\r
+ }\r
+ DEBUG_CODE_END ();\r
+}\r
+\r
/**\r
\r
This function installs an interface in the PEI PPI database by GUID.\r
}\r
}\r
\r
+/**\r
+\r
+ Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory.\r
+\r
+ @param PrivateData Pointer to PeiCore's private data structure.\r
+ @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory.\r
+\r
+**/\r
+VOID\r
+ConvertPeiCorePpiPointers (\r
+ IN PEI_CORE_INSTANCE *PrivateData,\r
+ PEI_CORE_FV_HANDLE CoreFvHandle\r
+ )\r
+{\r
+ EFI_FV_FILE_INFO FileInfo;\r
+ EFI_PHYSICAL_ADDRESS OrgImageBase;\r
+ EFI_PHYSICAL_ADDRESS MigratedImageBase;\r
+ UINTN PeiCoreModuleSize;\r
+ EFI_PEI_FILE_HANDLE PeiCoreFileHandle;\r
+ VOID *PeiCoreImageBase;\r
+ VOID *PeiCoreEntryPoint;\r
+ EFI_STATUS Status;\r
+\r
+ PeiCoreFileHandle = NULL;\r
+\r
+ //\r
+ // Find the PEI Core in the BFV in temporary memory.\r
+ //\r
+ Status = CoreFvHandle.FvPpi->FindFileByType (\r
+ CoreFvHandle.FvPpi,\r
+ EFI_FV_FILETYPE_PEI_CORE,\r
+ CoreFvHandle.FvHandle,\r
+ &PeiCoreFileHandle\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = CoreFvHandle.FvPpi->GetFileInfo (CoreFvHandle.FvPpi, PeiCoreFileHandle, &FileInfo);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = PeiGetPe32Data (PeiCoreFileHandle, &PeiCoreImageBase);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Find PEI Core EntryPoint in the BFV in temporary memory.\r
+ //\r
+ Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, &PeiCoreEntryPoint);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ OrgImageBase = (UINTN) PeiCoreImageBase;\r
+ MigratedImageBase = (UINTN) _ModuleEntryPoint - ((UINTN) PeiCoreEntryPoint - (UINTN) PeiCoreImageBase);\r
+\r
+ //\r
+ // Size of loaded PEI_CORE in permanent memory.\r
+ //\r
+ PeiCoreModuleSize = (UINTN)FileInfo.BufferSize - ((UINTN) OrgImageBase - (UINTN) FileInfo.Buffer);\r
+\r
+ //\r
+ // Migrate PEI_CORE PPI pointers from temporary memory to newly\r
+ // installed PEI_CORE in permanent memory.\r
+ //\r
+ ConvertPpiPointersFv (PrivateData, (UINTN) OrgImageBase, (UINTN) MigratedImageBase, PeiCoreModuleSize);\r
+ }\r
+}\r
+\r