}\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