From b0d803fe3e5c55a9a0c75bc90ccf40ebbbc9ffa3 Mon Sep 17 00:00:00 2001 From: klu2 Date: Mon, 24 Sep 2007 11:38:43 +0000 Subject: [PATCH] Merge branch of PI tree to main trunk git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3918 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c | 16 +- MdeModulePkg/Core/DxeIplPeim/DxeIpl.h | 27 +- MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 6 +- MdeModulePkg/Core/DxeIplPeim/DxeLoad.c | 1079 +++++++---------- MdeModulePkg/Core/Pei/Dependency/dependency.c | 21 +- MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c | 764 ++++++------ MdeModulePkg/Core/Pei/FwVol/FwVol.c | 600 +++++++-- MdeModulePkg/Core/Pei/Image/Image.c | 542 ++++++++- MdeModulePkg/Core/Pei/Memory/MemoryServices.c | 21 +- MdeModulePkg/Core/Pei/PeiMain.h | 271 ++++- MdeModulePkg/Core/Pei/PeiMain.inf | 17 +- MdeModulePkg/Core/Pei/PeiMain.msa | 5 - MdeModulePkg/Core/Pei/PeiMain/PeiMain.c | 54 +- MdeModulePkg/Core/Pei/Ppi/Ppi.c | 29 +- MdeModulePkg/Core/Pei/Reset/Reset.c | 2 +- MdeModulePkg/Core/Pei/Security/Security.c | 26 +- MdeModulePkg/MdeModulePkg.dec | 1 - MdeModulePkg/MdeModulePkg.dsc | 2 + MdePkg/Include/Library/HobLib.h | 24 + MdePkg/Include/Library/PeiPiLib.h | 30 + MdePkg/Include/Library/PeiServicesLib.h | 31 + .../Library/PeiServicesTablePointerLib.h | 6 + MdePkg/Include/Library/PiLib.h | 227 ++++ MdePkg/Include/Pi/PiPeiCis.h | 6 +- MdePkg/Library/DxePiLib/DxePiLib.c | 220 +++- MdePkg/Library/PeiPiLib/PeiPiLib.c | 67 + MdePkg/Library/PeiPiLib/PeiPiLib.inf | 50 + .../Library/PeiServicesLib/PeiServicesLib.c | 51 +- .../PeiServicesTablePointer.c | 9 + .../PeiServicesTablePointer.c | 9 + MdePkg/MdePkg.dsc | 1 + .../Nt32PeCoffLoaderLib/Nt32PeCoffLoader.c | 35 +- .../Nt32PeCoffLoaderLib.inf | 2 - Nt32Pkg/Nt32Pkg.dsc | 1 + 34 files changed, 2876 insertions(+), 1376 deletions(-) create mode 100644 MdePkg/Include/Library/PeiPiLib.h create mode 100644 MdePkg/Library/PeiPiLib/PeiPiLib.c create mode 100644 MdePkg/Library/PeiPiLib/PeiPiLib.inf diff --git a/MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c index c7b4cc3e12..da0555d8f9 100644 --- a/MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c +++ b/MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c @@ -490,7 +490,6 @@ Returns: CoreReleaseDispatcherLock (); - CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN, DriverEntry->ImageHandle); Status = CoreStartImage (DriverEntry->ImageHandle, NULL, NULL); CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END, DriverEntry->ImageHandle); @@ -814,25 +813,12 @@ Returns: --*/ { EFI_PEI_HOB_POINTERS HobFv2; - EFI_STATUS Status; - EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; - EFI_FIRMWARE_VOLUME_HEADER *FvHeader; - EFI_PHYSICAL_ADDRESS FvHeaderAddr; HobFv2.Raw = GetHobList (); while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) { if (CompareGuid (DriverName, &HobFv2.FirmwareVolume2->FileName)) { - Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **) &Fvb); - if (!EFI_ERROR (Status)) { - Status = Fvb->GetPhysicalAddress (Fvb, &FvHeaderAddr); - if (!EFI_ERROR (Status)) { - FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FvHeaderAddr; - if (CompareGuid (&FvHeader->FileSystemGuid, &HobFv2.FirmwareVolume2->FvName)) { - return TRUE; - } - } - } + return TRUE; } HobFv2.Raw = GET_NEXT_HOB (HobFv2); } diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h index 1907077ef2..3cd9ebac4c 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h @@ -32,6 +32,11 @@ Abstract: #include #include #include +#include +#include + +#include + #include #include #include @@ -67,14 +72,27 @@ PeiFindFile ( EFI_STATUS PeiLoadFile ( - IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader, - IN VOID *Pe32Data, + IN EFI_PEI_FILE_HANDLE FileHandle, OUT EFI_PHYSICAL_ADDRESS *ImageAddress, OUT UINT64 *ImageSize, OUT EFI_PHYSICAL_ADDRESS *EntryPoint ) ; +EFI_STATUS +DxeIplAddEncapsulatedFirmwareVolumes ( + VOID + ) +; + +EFI_STATUS +DxeIplFindFirmwareVolumeInstance ( + IN OUT UINTN *Instance, + IN EFI_FV_FILETYPE SeachType, + OUT EFI_PEI_FV_HANDLE *VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +; EFI_STATUS GetImageReadFunction ( @@ -133,9 +151,10 @@ PeiProcessFile ( EFI_STATUS EFIAPI PeimInitializeDxeIpl ( - IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_FILE_HANDLE FfsHandle, IN EFI_PEI_SERVICES **PeiServices - ); + ) +; #endif diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf index d76e904b8d..ff003e114b 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf @@ -58,8 +58,6 @@ MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - [LibraryClasses] PeCoffLib @@ -91,10 +89,10 @@ gEfiPeiS3ResumePpiGuid # PPI SOMETIMES_CONSUMED gEfiPeiRecoveryModulePpiGuid # PPI SOMETIMES_CONSUMED gEfiEndOfPeiSignalPpiGuid # PPI SOMETIMES_PRODUCED - gEfiPeiFvFileLoaderPpiGuid # PPI SOMETIMES_PRODUCED gEfiDxeIplPpiGuid # PPI SOMETIMES_PRODUCED gEfiPeiPeCoffLoaderGuid - + gEfiPeiDecompressPpiGuid + gEfiPeiFirmwareVolumeInfoPpiGuid [FeaturePcd.common] gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportCustomDecompress diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c index 32486a2e75..089e3bff66 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c +++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c @@ -1,6 +1,8 @@ -/*++ +/**@file + Last PEIM. + Responsibility of this module is to load the DXE Core from a Firmware Volume. -Copyright (c) 2006, Intel Corporation +Copyright (c) 2006 - 2007 Intel Corporation All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -9,23 +11,11 @@ http://opensource.org/licenses/bsd-license.php THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -Module Name: - - DxeLoad.c - -Abstract: - - Last PEIM. - Responsibility of this module is to load the DXE Core from a Firmware Volume. - ---*/ +**/ #include "DxeIpl.h" #include - -// porting note remove later -#include "FrameworkPei.h" -// end of remove later +#include EFI_STATUS CustomDecompressExtractSection ( @@ -36,6 +26,17 @@ CustomDecompressExtractSection ( OUT UINT32 *AuthenticationStatus ); +STATIC +EFI_STATUS +EFIAPI +Decompress ( + IN CONST EFI_PEI_DECOMPRESS_PPI *This, + IN CONST EFI_COMPRESSION_SECTION *InputSection, + OUT VOID **OutputBuffer, + OUT UINTN *OutputSize +); + + BOOLEAN gInMemory = FALSE; // @@ -46,24 +47,24 @@ static EFI_DXE_IPL_PPI mDxeIplPpi = { DxeLoadCore }; -static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi = { - DxeIplLoadFile +STATIC EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomDecompressExtractiongPpi = { + CustomDecompressExtractSection }; -static EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomDecompressExtractiongPpi = { - CustomDecompressExtractSection +STATIC EFI_PEI_DECOMPRESS_PPI mDecompressPpi = { + Decompress }; static EFI_PEI_PPI_DESCRIPTOR mPpiList[] = { { - EFI_PEI_PPI_DESCRIPTOR_PPI, - &gEfiPeiFvFileLoaderPpiGuid, - &mLoadFilePpi + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gEfiDxeIplPpiGuid, + &mDxeIplPpi }, { - (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), - &gEfiDxeIplPpiGuid, - &mDxeIplPpi + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiDecompressPpiGuid, + &mDecompressPpi } }; @@ -73,31 +74,30 @@ static EFI_PEI_PPI_DESCRIPTOR mPpiSignal = { NULL }; +STATIC EFI_PEI_FIRMWARE_VOLUME_INFO_PPI mFvInfoPpiTemplate = { + EFI_FIRMWARE_FILE_SYSTEM2_GUID, + NULL, + 0, //FvInfoSize + NULL, //ParentFvName + NULL //ParentFileName; +}; + +/** + Initializes the Dxe Ipl PPI + + @param FfsHandle The handle of FFS file. + @param PeiServices General purpose services available to + every PEIM. + @return EFI_SUCESS +*/ EFI_STATUS EFIAPI PeimInitializeDxeIpl ( - IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_FILE_HANDLE FfsHandle, IN EFI_PEI_SERVICES **PeiServices ) -/*++ - -Routine Description: - - Initializes the Dxe Ipl PPI - -Arguments: - - FfsHeader - Pointer to FFS file header - PeiServices - General purpose services available to every PEIM. - -Returns: - - EFI_SUCCESS - ---*/ { EFI_STATUS Status; - EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; EFI_BOOT_MODE BootMode; EFI_GUID **DecompressGuidList; UINT32 DecompressMethodNumber; @@ -106,56 +106,70 @@ Returns: Status = PeiServicesGetBootMode (&BootMode); ASSERT_EFI_ERROR (Status); - if (!gInMemory && (BootMode != BOOT_ON_S3_RESUME)) { - // - // The DxeIpl has not yet been shadowed - // - PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); + if (BootMode != BOOT_ON_S3_RESUME) { + Status = PeiServicesRegisterForShadow (FfsHandle); + if (Status == EFI_SUCCESS) { - // - // Shadow DxeIpl and then re-run its entry point - // - Status = ShadowDxeIpl (FfsHeader, PeiEfiPeiPeCoffLoader); - } else { - // - // Get custom decompress method guid list - // - DecompressGuidList = NULL; - DecompressMethodNumber = 0; - Status = CustomDecompressGetAlgorithms (DecompressGuidList, &DecompressMethodNumber); - if (Status == EFI_OUT_OF_RESOURCES) { + gInMemory = TRUE; + // + // EFI_SUCESS means the first time call register for shadow + // + return Status; + } else if (Status == EFI_ALREADY_STARTED) { + + + // + // Get custom decompress method guid list + // + DecompressGuidList = NULL; + DecompressMethodNumber = 0; + Status = CustomDecompressGetAlgorithms (DecompressGuidList, &DecompressMethodNumber); + if (Status == EFI_OUT_OF_RESOURCES) { DecompressGuidList = (EFI_GUID **) AllocatePages (EFI_SIZE_TO_PAGES (DecompressMethodNumber * sizeof (EFI_GUID *))); ASSERT (DecompressGuidList != NULL); Status = CustomDecompressGetAlgorithms (DecompressGuidList, &DecompressMethodNumber); - } - ASSERT_EFI_ERROR(Status); - - // - // Install custom decompress extraction guid ppi - // - if (DecompressMethodNumber > 0) { - GuidPpi = NULL; - GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePages (EFI_SIZE_TO_PAGES (DecompressMethodNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR))); - ASSERT (GuidPpi != NULL); - while (DecompressMethodNumber-- > 0) { - GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; - GuidPpi->Ppi = &mCustomDecompressExtractiongPpi; - GuidPpi->Guid = DecompressGuidList [DecompressMethodNumber]; - Status = PeiServicesInstallPpi (GuidPpi++); - ASSERT_EFI_ERROR(Status); } + ASSERT_EFI_ERROR(Status); + + // + // Install custom decompress extraction guid ppi + // + if (DecompressMethodNumber > 0) { + GuidPpi = NULL; + GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePages (EFI_SIZE_TO_PAGES (DecompressMethodNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR))); + ASSERT (GuidPpi != NULL); + while (DecompressMethodNumber-- > 0) { + GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + GuidPpi->Ppi = &mCustomDecompressExtractiongPpi; + GuidPpi->Guid = DecompressGuidList [DecompressMethodNumber]; + Status = PeiServicesInstallPpi (GuidPpi++); + ASSERT_EFI_ERROR(Status); + } + } + } else { + ASSERT_EFI_ERROR (FALSE); } - - // - // Install FvFileLoader and DxeIpl PPIs. - // - Status = PeiServicesInstallPpi (mPpiList); - ASSERT_EFI_ERROR(Status); } + // + // Install FvFileLoader and DxeIpl PPIs. + // + Status = PeiServicesInstallPpi (mPpiList); + ASSERT_EFI_ERROR(Status); + return Status; } +/** + Main entry point to last PEIM + + @param This Entry point for DXE IPL PPI + @param PeiServices General purpose services available to every PEIM. + @param HobList Address to the Pei HOB list + + @return EFI_SUCCESS DXE core was successfully loaded. + @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core. +**/ EFI_STATUS EFIAPI DxeLoadCore ( @@ -163,29 +177,9 @@ DxeLoadCore ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_HOB_POINTERS HobList ) -/*++ - -Routine Description: - - Main entry point to last PEIM - -Arguments: - This - Entry point for DXE IPL PPI - PeiServices - General purpose services available to every PEIM. - HobList - Address to the Pei HOB list - -Returns: - - EFI_SUCCESS - DEX core was successfully loaded. - EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core. - ---*/ { EFI_STATUS Status; EFI_GUID DxeCoreFileName; - EFI_GUID FirmwareFileName; - VOID *Pe32Data; - VOID *FvImageData; EFI_PHYSICAL_ADDRESS DxeCoreAddress; UINT64 DxeCoreSize; EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint; @@ -193,8 +187,9 @@ Returns: EFI_BOOT_MODE BootMode; EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery; EFI_PEI_S3_RESUME_PPI *S3Resume; - -// PERF_START (PeiServices, L"DxeIpl", NULL, 0); + EFI_PEI_FV_HANDLE VolumeHandle; + EFI_PEI_FILE_HANDLE FileHandle; + UINTN Instance; // // if in S3 Resume, restore configure @@ -237,42 +232,33 @@ Returns: // // Install the PEI Protocols that are shared between PEI and DXE // - PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *) GetPeCoffLoaderProtocol (); ASSERT (PeiEfiPeiPeCoffLoader != NULL); - + // - // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file - // The file found will be processed by PeiProcessFile: It will first be decompressed to - // a normal FV, then a corresponding FV type hob will be built. + // If any FV contains an encapsulated FV extract that FV // - Status = PeiFindFile ( - EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, - EFI_SECTION_FIRMWARE_VOLUME_IMAGE, - &FirmwareFileName, - &FvImageData - ); - + DxeIplAddEncapsulatedFirmwareVolumes (); + // - // Find the DXE Core in a Firmware Volume + // Look in all the FVs present in PEI and find the DXE Core // - Status = PeiFindFile ( - EFI_FV_FILETYPE_DXE_CORE, - EFI_SECTION_PE32, - &DxeCoreFileName, - &Pe32Data - ); + Instance = 0; + Status = DxeIplFindFirmwareVolumeInstance (&Instance, EFI_FV_FILETYPE_DXE_CORE, &VolumeHandle, &FileHandle); ASSERT_EFI_ERROR (Status); + CopyMem(&DxeCoreFileName, &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name), sizeof (EFI_GUID)); + // // Load the DXE Core from a Firmware Volume // Status = PeiLoadFile ( - PeiEfiPeiPeCoffLoader, - Pe32Data, - &DxeCoreAddress, - &DxeCoreSize, - &DxeCoreEntryPoint - ); + FileHandle, + &DxeCoreAddress, + &DxeCoreSize, + &DxeCoreEntryPoint + ); + ASSERT_EFI_ERROR (Status); // @@ -305,7 +291,6 @@ Returns: // Transfer control to the DXE Core // The handoff state is simply a pointer to the HOB list // - DEBUG ((EFI_D_INFO, "DXE Core Entry Point 0x%08x\n", (UINTN) DxeCoreEntryPoint)); HandOffToDxeCore (DxeCoreEntryPoint, HobList, &mPpiSignal); // @@ -318,124 +303,235 @@ Returns: return EFI_OUT_OF_RESOURCES; } + +STATIC EFI_STATUS -PeiFindFile ( - IN UINT8 Type, - IN EFI_SECTION_TYPE SectionType, - OUT EFI_GUID *FileName, - OUT VOID **Pe32Data +GetFvAlignment ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader, + OUT UINT32 *FvAlignment ) -/*++ - -Routine Description: - - Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes - described in the HOB list. Able to search in a compression set in a FFS file. - But only one level of compression is supported, that is, not able to search - in a compression set that is within another compression set. - -Arguments: +{ + // + // Because FvLength in FvHeader is UINT64 type, + // so FvHeader must meed at least 8 bytes alignment. + // Get the appropriate alignment requirement. + // + if ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) < EFI_FVB2_ALIGNMENT_8) { + return EFI_UNSUPPORTED; + } + + *FvAlignment = 1 << ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16); + return EFI_SUCCESS; +} - Type - The Type of file to retrieve +/** + Search EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE image and expand + as memory FV + + @return EFI_OUT_OF_RESOURCES There are no memory space to exstract FV + @return EFI_SUCESS Sucess to find the FV +**/ +EFI_STATUS +DxeIplAddEncapsulatedFirmwareVolumes ( + VOID + ) +{ + EFI_STATUS Status; + EFI_STATUS VolumeStatus; + UINTN Index; + EFI_FV_INFO VolumeInfo; + EFI_PEI_FV_HANDLE VolumeHandle; + EFI_PEI_FILE_HANDLE FileHandle; + UINT32 SectionLength; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_FIRMWARE_VOLUME_IMAGE_SECTION *SectionHeader; + VOID *DstBuffer; + UINT32 FvAlignment; + EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FvInfoPpi; + EFI_PEI_PPI_DESCRIPTOR *FvInfoPpiDescriptor; + + Status = EFI_NOT_FOUND; + Index = 0; - SectionType - The type of section to retrieve from a file + do { + VolumeStatus = DxeIplFindFirmwareVolumeInstance ( + &Index, + EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, + &VolumeHandle, + &FileHandle + ); + + if (!EFI_ERROR (VolumeStatus)) { + Status = PeiServicesFfsFindSectionData ( + EFI_SECTION_FIRMWARE_VOLUME_IMAGE, + (EFI_FFS_FILE_HEADER *)FileHandle, + (VOID **)&FvHeader + ); + + if (!EFI_ERROR (Status)) { + if (FvHeader->Signature == EFI_FVH_SIGNATURE) { + // + // Because FvLength in FvHeader is UINT64 type, + // so FvHeader must meed at least 8 bytes alignment. + // If current FvImage base address doesn't meet its alignment, + // we need to reload this FvImage to another correct memory address. + // + Status = GetFvAlignment(FvHeader, &FvAlignment); + if (EFI_ERROR(Status)) { + return Status; + } + if (((UINTN) FvHeader % FvAlignment) != 0) { + SectionHeader = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*)((UINTN)FvHeader - sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION)); + SectionLength = *(UINT32 *)SectionHeader->Size & 0x00FFFFFF; + + DstBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) SectionLength - sizeof (EFI_COMMON_SECTION_HEADER)), FvAlignment); + if (DstBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (DstBuffer, FvHeader, (UINTN) SectionLength - sizeof (EFI_COMMON_SECTION_HEADER)); + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer; + } - FileName - The name of the file found in the Firmware Volume + // + // This new Firmware Volume comes from a firmware file within a firmware volume. + // Record the original Firmware Volume Name. + // + PeiServicesFfsGetVolumeInfo (&VolumeHandle, &VolumeInfo); - Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume + // + // Prepare to install FirmwareVolumeInfo PPI to expose new FV to PeiCore. + // + FvInfoPpi = AllocateCopyPool (sizeof (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI), &mFvInfoPpiTemplate); + ASSERT(FvInfoPpi != NULL); + + FvInfoPpi->FvInfo = (VOID*)FvHeader; + FvInfoPpi->FvInfoSize = (UINT32)FvHeader->FvLength; + CopyMem ( + &FvInfoPpi->ParentFvName, + &(VolumeInfo.FvName), + sizeof (EFI_GUID) + ); + CopyMem ( + &FvInfoPpi->ParentFileName, + &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name), + sizeof (EFI_GUID) + ); -Returns: + FvInfoPpiDescriptor = AllocatePool (sizeof(EFI_PEI_PPI_DESCRIPTOR)); + ASSERT (FvInfoPpiDescriptor != NULL); + + FvInfoPpiDescriptor->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI|EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + FvInfoPpiDescriptor->Guid = &gEfiPeiFirmwareVolumeInfoPpiGuid; + FvInfoPpiDescriptor->Ppi = (VOID *) FvInfoPpi; - EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to - the PE/COFF image is returned in Pe32Data + Status = PeiServicesInstallPpi (FvInfoPpiDescriptor); + ASSERT_EFI_ERROR (Status); - EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List + // + // Makes the encapsulated volume show up in DXE phase to skip processing of + // encapsulated file again. + // + BuildFv2Hob ( + (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader, + FvHeader->FvLength, + &VolumeInfo.FvName, + &(((EFI_FFS_FILE_HEADER *)FileHandle)->Name) + ); + return Status; + } + } + } + } while (!EFI_ERROR (VolumeStatus)); + + return Status; +} ---*/ +/** + Find the First Volume that contains the first FileType. + + @param Instance The Fv instance. + @param SeachType The type of file to search. + @param VolumeHandle Pointer to Fv which contains the file to search. + @param FileHandle Pointer to FFS file to search. + + @return EFI_SUCESS Success to find the FFS in specificed FV + @return others Fail to find the FFS in specificed FV + */ +EFI_STATUS +DxeIplFindFirmwareVolumeInstance ( + IN OUT UINTN *Instance, + IN EFI_FV_FILETYPE SeachType, + OUT EFI_PEI_FV_HANDLE *VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) { - EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; - EFI_FFS_FILE_HEADER *FfsFileHeader; - EFI_STATUS Status; - EFI_PEI_HOB_POINTERS Hob; + EFI_STATUS Status; + EFI_STATUS VolumeStatus; - - FwVolHeader = NULL; - FfsFileHeader = NULL; - Status = EFI_SUCCESS; - - // - // For each Firmware Volume, look for a specified type - // of file and break out until no one is found - // - Hob.Raw = GetHobList (); - while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw)) != NULL) { - FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (Hob.FirmwareVolume->BaseAddress); - // - // Make sure the FV HOB does not get corrupted. - // - ASSERT (FwVolHeader->Signature == EFI_FVH_SIGNATURE); - - Status = PeiServicesFfsFindNextFile ( - Type, - (EFI_PEI_FV_HANDLE) FwVolHeader, - (EFI_PEI_FILE_HANDLE*) &FfsFileHeader - ); - if (!EFI_ERROR (Status)) { - Status = PeiProcessFile ( - SectionType, - FfsFileHeader, - Pe32Data, - &Hob - ); - CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID)); - // - // Find all Fv type ffs to get all FvImage and add them into FvHob - // - if (!EFI_ERROR (Status) && (Type != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE)) { - return EFI_SUCCESS; + do { + VolumeStatus = PeiServicesFfsFindNextVolume (*Instance, VolumeHandle); + if (!EFI_ERROR (VolumeStatus)) { + *FileHandle = NULL; + Status = PeiServicesFfsFindNextFile (SeachType, *VolumeHandle, FileHandle); + if (!EFI_ERROR (Status)) { + return Status; } } - Hob.Raw = GET_NEXT_HOB (Hob); - } - return EFI_NOT_FOUND; + *Instance += 1; + } while (!EFI_ERROR (VolumeStatus)); + + return VolumeStatus; } +/** + Loads and relocates a PE/COFF image into memory. + + @param FileHandle The image file handle + @param ImageAddress The base address of the relocated PE/COFF image + @param ImageSize The size of the relocated PE/COFF image + @param EntryPoint The entry point of the relocated PE/COFF image + + @return EFI_SUCCESS The file was loaded and relocated + @return EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file +**/ EFI_STATUS PeiLoadFile ( - IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader, - IN VOID *Pe32Data, + IN EFI_PEI_FILE_HANDLE FileHandle, OUT EFI_PHYSICAL_ADDRESS *ImageAddress, OUT UINT64 *ImageSize, OUT EFI_PHYSICAL_ADDRESS *EntryPoint ) -/*++ - -Routine Description: - - Loads and relocates a PE/COFF image into memory. - -Arguments: - - PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol - - Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated - - ImageAddress - The base address of the relocated PE/COFF image - - ImageSize - The size of the relocated PE/COFF image - - EntryPoint - The entry point of the relocated PE/COFF image - -Returns: +{ - EFI_SUCCESS - The file was loaded and relocated + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + VOID *Pe32Data; + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; - EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); + // + // First try to find the required section in this ffs file. + // + Status = PeiServicesFfsFindSectionData ( + EFI_SECTION_PE32, + FileHandle, + &Pe32Data + ); ---*/ -{ - EFI_STATUS Status; - PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + if (EFI_ERROR (Status)) { + Status = PeiServicesFfsFindSectionData ( + EFI_SECTION_TE, + FileHandle, + &Pe32Data + ); + } + + if (EFI_ERROR (Status)) { + // + // NO image types we support so exit. + // + return Status; + } ZeroMem (&ImageContext, sizeof (ImageContext)); ImageContext.Handle = Pe32Data; @@ -480,430 +576,6 @@ Returns: return EFI_SUCCESS; } -EFI_STATUS -ShadowDxeIpl ( - IN EFI_FFS_FILE_HEADER *DxeIplFileHeader, - IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader - ) -/*++ - -Routine Description: - - Shadow the DXE IPL to a different memory location. This occurs after permanent - memory has been discovered. - -Arguments: - - DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver - - PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol - -Returns: - - EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location. - - EFI_ ERROR - The shadow was unsuccessful. - - ---*/ -{ - UINTN SectionLength; - UINTN OccupiedSectionLength; - EFI_PHYSICAL_ADDRESS DxeIplAddress; - UINT64 DxeIplSize; - EFI_PHYSICAL_ADDRESS DxeIplEntryPoint; - EFI_STATUS Status; - EFI_COMMON_SECTION_HEADER *Section; - - Section = (EFI_COMMON_SECTION_HEADER *) (DxeIplFileHeader + 1); - - while ((Section->Type != EFI_SECTION_PE32) && (Section->Type != EFI_SECTION_TE)) { - SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff; - OccupiedSectionLength = GET_OCCUPIED_SIZE (SectionLength, 4); - Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength); - } - // - // Relocate DxeIpl into memory by using loadfile service - // - Status = PeiLoadFile ( - PeiEfiPeiPeCoffLoader, - (VOID *) (Section + 1), - &DxeIplAddress, - &DxeIplSize, - &DxeIplEntryPoint - ); - - if (Status == EFI_SUCCESS) { - // - // Set gInMemory global variable to TRUE to indicate the dxeipl is shadowed. - // - *(BOOLEAN *) ((UINTN) &gInMemory + (UINTN) DxeIplEntryPoint - (UINTN) _ModuleEntryPoint) = TRUE; - Status = ((EFI_PEIM_ENTRY_POINT2) (UINTN) DxeIplEntryPoint) ((EFI_PEI_FILE_HANDLE *) DxeIplFileHeader, GetPeiServicesTablePointer()); - } - - return Status; -} - -EFI_STATUS -EFIAPI -DxeIplLoadFile ( - IN EFI_PEI_FV_FILE_LOADER_PPI *This, - IN EFI_FFS_FILE_HEADER *FfsHeader, - OUT EFI_PHYSICAL_ADDRESS *ImageAddress, - OUT UINT64 *ImageSize, - OUT EFI_PHYSICAL_ADDRESS *EntryPoint - ) -/*++ - -Routine Description: - - Given a pointer to an FFS file containing a PE32 image, get the - information on the PE32 image, and then "load" it so that it - can be executed. - -Arguments: - - This - pointer to our file loader protocol - - FfsHeader - pointer to the FFS file header of the FFS file that - contains the PE32 image we want to load - - ImageAddress - returned address where the PE32 image is loaded - - ImageSize - returned size of the loaded PE32 image - - EntryPoint - entry point to the loaded PE32 image - -Returns: - - EFI_SUCCESS - The FFS file was successfully loaded. - - EFI_ERROR - Unable to load the FFS file. - ---*/ -{ - EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; - EFI_STATUS Status; - VOID *Pe32Data; - - Pe32Data = NULL; - PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); - - // - // Preprocess the FFS file to get a pointer to the PE32 information - // in the enclosed PE32 image. - // - Status = PeiProcessFile ( - EFI_SECTION_TE, - FfsHeader, - &Pe32Data, - NULL - ); - if (EFI_ERROR (Status)) { - Status = PeiProcessFile ( - EFI_SECTION_PE32, - FfsHeader, - &Pe32Data, - NULL - ); - - if (EFI_ERROR (Status)) { - return Status; - } - } - // - // Load the PE image from the FFS file - // - Status = PeiLoadFile ( - PeiEfiPeiPeCoffLoader, - Pe32Data, - ImageAddress, - ImageSize, - EntryPoint - ); - - return Status; -} - -EFI_STATUS -PeiProcessFile ( - IN EFI_SECTION_TYPE SectionType, - IN EFI_FFS_FILE_HEADER *FfsFileHeader, - OUT VOID **Pe32Data, - IN EFI_PEI_HOB_POINTERS *OrigHob - ) -/*++ - -Routine Description: - -Arguments: - - SectionType - The type of section in the FFS file to process. - - FfsFileHeader - Pointer to the FFS file to process, looking for the - specified SectionType - - Pe32Data - returned pointer to the start of the PE32 image found - in the FFS file. - -Returns: - - EFI_SUCCESS - found the PE32 section in the FFS file - ---*/ -{ - EFI_STATUS Status; - UINT8 *DstBuffer; - UINT8 *ScratchBuffer; - UINTN DstBufferSize; - UINT32 ScratchBufferSize; - EFI_COMMON_SECTION_HEADER *CmpSection; - UINTN CmpSectionLength; - UINTN OccupiedCmpSectionLength; - VOID *CmpFileData; - UINTN CmpFileSize; - EFI_COMMON_SECTION_HEADER *Section; - UINTN SectionLength; - UINTN OccupiedSectionLength; - UINTN FileSize; - EFI_FIRMWARE_VOLUME_HEADER *FvHeader; - EFI_COMPRESSION_SECTION *CompressionSection; - EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *SectionExtract; - UINT32 AuthenticationStatus; - - // - // First try to find the required section in this ffs file. - // - Status = PeiServicesFfsFindSectionData ( - SectionType, - FfsFileHeader, - Pe32Data - ); - if (!EFI_ERROR (Status)) { - return Status; - } - - // - // If not found, the required section may be in guided or compressed section. - // So, search guided or compressed section to process - // - Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER)); - FileSize = FfsFileHeader->Size[0] & 0xFF; - FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00; - FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000; - FileSize &= 0x00FFFFFF; - OccupiedSectionLength = 0; - - do { - // - // Initialize local variables. - // - DstBuffer = NULL; - DstBufferSize = 0; - - Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength); - SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff; - OccupiedSectionLength = GET_OCCUPIED_SIZE (SectionLength, 4); - - // - // Was the DXE Core file encapsulated in a GUID'd section? - // - if (Section->Type == EFI_SECTION_GUID_DEFINED) { - // - // Set a default authenticatino state - // - AuthenticationStatus = 0; - // - // Locate extract guid section ppi - // - Status = PeiServicesLocatePpi ( - (EFI_GUID *) (Section + 1), - 0, - NULL, - (VOID **)&SectionExtract - ); - - if (EFI_ERROR (Status)) { - // - // ignore the unknown guid section - // - continue; - } - // - // Extract the contents from guid section - // - Status = SectionExtract->ExtractSection ( - SectionExtract, - (VOID *) Section, - (VOID **) &DstBuffer, - &DstBufferSize, - &AuthenticationStatus - ); - - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Extract section content failed - %r\n", Status)); - return Status; - } - - // - // Todo check AuthenticationStatus and do the verify - // - } else if (Section->Type == EFI_SECTION_COMPRESSION) { - // - // This is a compression set, expand it - // - CompressionSection = (EFI_COMPRESSION_SECTION *) Section; - - switch (CompressionSection->CompressionType) { - case EFI_STANDARD_COMPRESSION: - // - // Load EFI standard compression. - // For compressed data, decompress them to dstbuffer. - // - Status = UefiDecompressGetInfo ( - (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), - (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION), - (UINT32 *) &DstBufferSize, - &ScratchBufferSize - ); - if (EFI_ERROR (Status)) { - // - // GetInfo failed - // - DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status)); - return EFI_NOT_FOUND; - } - // - // Allocate scratch buffer - // - ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize)); - if (ScratchBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - // - // Allocate destination buffer - // - DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize)); - if (DstBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - // - // Call decompress function - // - Status = UefiDecompress ( - (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), - DstBuffer, - ScratchBuffer - ); - if (EFI_ERROR (Status)) { - // - // Decompress failed - // - DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status)); - return EFI_NOT_FOUND; - } - break; - - // porting note the original branch for customized compress is removed, it should be change to use GUID compress - - case EFI_NOT_COMPRESSED: - // - // Allocate destination buffer - // - DstBufferSize = CompressionSection->UncompressedLength; - DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize)); - if (DstBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; - } - // - // stream is not actually compressed, just encapsulated. So just copy it. - // - CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize); - break; - - default: - // - // Don't support other unknown compression type. - // - ASSERT_EFI_ERROR (Status); - return EFI_NOT_FOUND; - } - } else { - // - // ignore other type sections - // - continue; - } - - // - // Extract contents from guided or compressed sections. - // Loop the decompressed data searching for expected section. - // - CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer; - CmpFileData = (VOID *) DstBuffer; - CmpFileSize = DstBufferSize; - do { - CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff; - if (CmpSection->Type == SectionType) { - // - // This is what we want - // - if (SectionType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) { - // - // Firmware Volume Image in this Section - // Skip the section header to get FvHeader - // - FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (CmpSection + 1); - - if (FvHeader->Signature == EFI_FVH_SIGNATURE) { - // - // Because FvLength in FvHeader is UINT64 type, - // so FvHeader must meed at least 8 bytes alignment. - // If current FvImage base address doesn't meet its alignment, - // we need to reload this FvImage to another correct memory address. - // - if (((UINTN) FvHeader % sizeof (UINT64)) != 0) { - CopyMem (DstBuffer, FvHeader, (UINTN) CmpSectionLength - sizeof (EFI_COMMON_SECTION_HEADER)); - FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer; - } - - // - // Build new FvHob for new decompressed Fv image. - // - BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength); - - // - // Set the original FvHob to unused. - // - if (OrigHob != NULL) { - OrigHob->Header->HobType = EFI_HOB_TYPE_UNUSED; - } - // - // return found FvImage data. - // - *Pe32Data = (VOID *) FvHeader; - return EFI_SUCCESS; - } - } else { - // - // direct return the found section. - // - *Pe32Data = (VOID *) (CmpSection + 1); - return EFI_SUCCESS; - } - } - OccupiedCmpSectionLength = GET_OCCUPIED_SIZE (CmpSectionLength, 4); - CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength); - } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize); - } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section + OccupiedSectionLength - (UINT8 *) FfsFileHeader) < FileSize); - - // - // search all sections (compression and non compression) in this FFS, don't - // find expected section. - // - return EFI_NOT_FOUND; -} - /** The ExtractSection() function processes the input section and returns a pointer to the section contents. If the section being @@ -1032,3 +704,114 @@ CustomDecompressExtractSection ( return EFI_SUCCESS; } + +STATIC +EFI_STATUS +EFIAPI +Decompress ( + IN CONST EFI_PEI_DECOMPRESS_PPI *This, + IN CONST EFI_COMPRESSION_SECTION *CompressionSection, + OUT VOID **OutputBuffer, + OUT UINTN *OutputSize + ) +{ + EFI_STATUS Status; + UINT8 *DstBuffer; + UINT8 *ScratchBuffer; + UINTN DstBufferSize; + UINT32 ScratchBufferSize; + EFI_COMMON_SECTION_HEADER *Section; + UINTN SectionLength; + + if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + Section = (EFI_COMMON_SECTION_HEADER *) CompressionSection; + SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff; + + // + // This is a compression set, expand it + // + switch (CompressionSection->CompressionType) { + case EFI_STANDARD_COMPRESSION: + // + // Load EFI standard compression. + // For compressed data, decompress them to dstbuffer. + // + Status = UefiDecompressGetInfo ( + (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), + (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION), + (UINT32 *) &DstBufferSize, + &ScratchBufferSize + ); + if (EFI_ERROR (Status)) { + // + // GetInfo failed + // + DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status)); + return EFI_NOT_FOUND; + } + // + // Allocate scratch buffer + // + ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize)); + if (ScratchBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Allocate destination buffer + // + DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize)); + if (DstBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Call decompress function + // + Status = UefiDecompress ( + (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), + DstBuffer, + ScratchBuffer + ); + if (EFI_ERROR (Status)) { + // + // Decompress failed + // + DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status)); + return EFI_NOT_FOUND; + } + break; + + // porting note the original branch for customized compress is removed, it should be change to use GUID compress + + case EFI_NOT_COMPRESSED: + // + // Allocate destination buffer + // + DstBufferSize = CompressionSection->UncompressedLength; + DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize)); + if (DstBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // stream is not actually compressed, just encapsulated. So just copy it. + // + CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize); + break; + + default: + // + // Don't support other unknown compression type. + // + ASSERT (FALSE); + return EFI_NOT_FOUND; + } + + *OutputSize = DstBufferSize; + *OutputBuffer = DstBuffer; + + return EFI_SUCCESS; +} + diff --git a/MdeModulePkg/Core/Pei/Dependency/dependency.c b/MdeModulePkg/Core/Pei/Dependency/dependency.c index c817a3d171..7ea840d23a 100644 --- a/MdeModulePkg/Core/Pei/Dependency/dependency.c +++ b/MdeModulePkg/Core/Pei/Dependency/dependency.c @@ -87,11 +87,10 @@ Returns: } -EFI_STATUS +BOOLEAN PeimDispatchReadiness ( IN EFI_PEI_SERVICES **PeiServices, - IN VOID *DependencyExpression, - OUT BOOLEAN *Runnable + IN VOID *DependencyExpression ) /*++ @@ -130,7 +129,6 @@ Returns: EVAL_STACK_ENTRY EvalStack[MAX_GRAMMAR_SIZE]; Iterator = DependencyExpression; - *Runnable = FALSE; StackPtr = &EvalStack[0]; @@ -149,7 +147,7 @@ Returns: // EvalStack on the push // if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) { - return EFI_INVALID_PARAMETER; + return FALSE; } // @@ -170,7 +168,7 @@ Returns: // did two POPs. // if (StackPtr < &EvalStack[2]) { - return EFI_INVALID_PARAMETER; + return FALSE; } // @@ -208,10 +206,9 @@ Returns: // an error in the dependency grammar, so return EFI_INVALID_PARAMETER. // if (StackPtr != &EvalStack[0]) { - return EFI_INVALID_PARAMETER; + return FALSE; } - *Runnable = IsPpiInstalled (PeiServices, StackPtr); - return EFI_SUCCESS; + return IsPpiInstalled (PeiServices, StackPtr); break; case (EFI_DEP_NOT): @@ -222,7 +219,7 @@ Returns: // did a POP. // if (StackPtr < &EvalStack[1]) { - return EFI_INVALID_PARAMETER; + return FALSE; } (StackPtr-1)->Result = (BOOLEAN) !IsPpiInstalled (PeiServices, (StackPtr-1)); (StackPtr-1)->Operator = NULL; @@ -235,7 +232,7 @@ Returns: // EvalStack on the push // if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) { - return EFI_INVALID_PARAMETER; + return FALSE; } // // Iterator has increased by 1 after we retrieve the operand, so here we @@ -255,7 +252,7 @@ Returns: // // The grammar should never arrive here // - return EFI_INVALID_PARAMETER; + return FALSE; break; } } diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c index 900e1d2d50..b9780a2c7b 100644 --- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c +++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c @@ -23,12 +23,6 @@ Revision History #include -STATIC -VOID * -TransferOldDataToNewDataRange ( - IN PEI_CORE_INSTANCE *PrivateData - ); - STATIC VOID InvokePeiCore ( @@ -36,11 +30,165 @@ InvokePeiCore ( VOID *Context2 ); -EFI_STATUS + +VOID +DiscoverPeimsAndOrderWithApriori ( + IN PEI_CORE_INSTANCE *Private, + IN EFI_PEI_FV_HANDLE VolumeHandle + ) +/*++ + +Routine Description: + + Discover all Peims and optional Apriori file in one FV. There is at most one + Apriori file in one FV. + +Arguments: + + Private - Pointer to the private data passed in from caller + VolumeHandle - Fv handle. +Returns: + + NONE + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_FV_HANDLE FileHandle; + EFI_PEI_FV_HANDLE AprioriFileHandle; + EFI_GUID *Apriori; + UINTN Index; + UINTN Index2; + UINTN PeimIndex; + UINTN PeimCount; + EFI_GUID *Guid; + EFI_PEI_FV_HANDLE TempFileHandles[PEI_CORE_MAX_PEIM_PER_FV]; + EFI_GUID FileGuid[PEI_CORE_MAX_PEIM_PER_FV]; + + // + // Walk the FV and find all the PEIMs and the Apriori file. + // + AprioriFileHandle = NULL; + Private->CurrentFvFileHandles[0] = NULL; + Guid = NULL; + FileHandle = NULL; + + // + // If the current Fv has been scanned, directly get its cachable record. + // + if (Private->Fv[Private->CurrentPeimFvCount].ScanFv) { + CopyMem (Private->CurrentFvFileHandles, Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, sizeof (Private->CurrentFvFileHandles)); + return; + } + + // + // Go ahead to scan this Fv, and cache FileHandles within it. + // + for (PeimCount = 0; PeimCount < PEI_CORE_MAX_PEIM_PER_FV; PeimCount++) { + Status = PeiFindFileEx ( + VolumeHandle, + NULL, + PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, + &FileHandle, + &AprioriFileHandle + ); + if (Status != EFI_SUCCESS) { + break; + } + + Private->CurrentFvFileHandles[PeimCount] = FileHandle; + } + + Private->AprioriCount = 0; + if (AprioriFileHandle != NULL) { + // + // Read the Apriori file + // + Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, &AprioriFileHandle, (VOID **) &Apriori); + if (!EFI_ERROR (Status)) { + // + // Calculate the number of PEIMs in the A Priori list + // + Private->AprioriCount = *(UINT32 *)(((EFI_FFS_FILE_HEADER *)AprioriFileHandle)->Size) & 0x00FFFFFF; + Private->AprioriCount -= sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_COMMON_SECTION_HEADER); + Private->AprioriCount /= sizeof (EFI_GUID); + + SetMem (FileGuid, sizeof (FileGuid), 0); + for (Index = 0; Index < PeimCount; Index++) { + // + // Make an array of file name guids that matches the FileHandle array so we can convert + // quickly from file name to file handle + // + CopyMem (&FileGuid[Index], &((EFI_FFS_FILE_HEADER *)Private->CurrentFvFileHandles[Index])->Name,sizeof(EFI_GUID)); + } + + // + // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file. + // Add avalible PEIMs in Apriori file into TempFileHandles array at first. + // + Index2 = 0; + for (Index = 0; Index2 < Private->AprioriCount; Index++) { + while (Index2 < Private->AprioriCount) { + Guid = ScanGuid (FileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2++]); + if (Guid != NULL) { + break; + } + } + if (Guid == NULL) { + break; + } + PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID); + TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex]; + + // + // Since we have copied the file handle we can remove it from this list. + // + Private->CurrentFvFileHandles[PeimIndex] = NULL; + } + + // + // Update valid Aprioricount + // + Private->AprioriCount = Index; + + // + // Add in any PEIMs not in the Apriori file + // + for (;Index < PeimCount; Index++) { + for (Index2 = 0; Index2 < PeimCount; Index2++) { + if (Private->CurrentFvFileHandles[Index2] != NULL) { + TempFileHandles[Index] = Private->CurrentFvFileHandles[Index2]; + Private->CurrentFvFileHandles[Index2] = NULL; + break; + } + } + } + // + //Index the end of array contains re-range Pei moudle. + // + TempFileHandles[Index] = NULL; + + // + // Private->CurrentFvFileHandles is currently in PEIM in the FV order. + // We need to update it to start with files in the A Priori list and + // then the remaining files in PEIM order. + // + CopyMem (Private->CurrentFvFileHandles, TempFileHandles, sizeof (Private->CurrentFvFileHandles)); + } + } + // + // Cache the current Fv File Handle. So that we don't have to scan the Fv again. + // Instead, we can retrieve the file handles within this Fv from cachable data. + // + Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE; + CopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles)); + +} + +VOID PeiDispatcher ( IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, - IN PEI_CORE_INSTANCE *PrivateData, - IN PEI_CORE_DISPATCH_DATA *DispatchData + IN PEI_CORE_INSTANCE *Private ) /*++ @@ -64,24 +212,78 @@ Returns: --*/ { - EFI_STATUS Status; - PEI_CORE_TEMP_POINTERS TempPtr; - BOOLEAN NextFvFound; - EFI_FIRMWARE_VOLUME_HEADER *NextFvAddress; - EFI_FIRMWARE_VOLUME_HEADER *DefaultFvAddress; - VOID *TopOfStack; - PEI_CORE_PARAMETERS PeiCoreParameters; - - // - // Debug data for uninstalled Peim list - // - EFI_GUID DebugFoundPeimList[32]; - EFI_DEVICE_HANDLE_EXTENDED_DATA ExtendedData; - - // - // save the Current FV Address so that we will not process it again if FindFv returns it later - // - DefaultFvAddress = DispatchData->BootFvAddress; + EFI_STATUS Status; + UINT32 Index1; + UINT32 Index2; + EFI_PEI_SERVICES **PeiServices; + VOID *PrivateInMem; + EFI_PEI_FV_HANDLE VolumeHandle; + EFI_PEI_FILE_HANDLE PeiCoreFileHandle; + EFI_PEI_FILE_HANDLE PeimFileHandle; + UINTN FvCount; + UINTN PeimCount; + UINT32 AuthenticationState; + EFI_PHYSICAL_ADDRESS EntryPoint; + EFI_PEIM_ENTRY_POINT PeimEntryPoint; + BOOLEAN PeimNeedingDispatch; + BOOLEAN PeimDispatchOnThisPass; + UINTN SaveCurrentPeimCount; + EFI_PEI_FILE_HANDLE SaveCurrentFileHandle; + VOID *TopOfStack; + PEI_CORE_PARAMETERS PeiCoreParameters; + EFI_DEVICE_HANDLE_EXTENDED_DATA ExtendedData; + + + PeiServices = &Private->PS; + PeimEntryPoint = NULL; + PeimFileHandle = NULL; + + if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) { + // + // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile + // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE. + // + SaveCurrentPeimCount = Private->CurrentPeimCount; + SaveCurrentFileHandle = Private->CurrentFileHandle; + + for (Index1 = 0;Index1 <= Private->CurrentPeimFvCount; Index1++) { + for (Index2 = 0; (Index2 < PEI_CORE_MAX_PEIM_PER_FV) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) { + if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) { + PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2]; + Status = PeiLoadImage ( + &Private->PS, + PeimFileHandle, + &EntryPoint, + &AuthenticationState + ); + if (Status == EFI_SUCCESS) { + // + // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE + // + Private->Fv[Index1].PeimState[Index2]++; + Private->CurrentFileHandle = PeimFileHandle; + Private->CurrentPeimCount = Index2; + // + // Call the PEIM entry point + // + PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint; + + PERF_START (0, "PEIM", NULL, 0); + PeimEntryPoint(PeimFileHandle, &Private->PS); + PERF_END (0, "PEIM", NULL, 0); + } + + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessNotifyList (Private); + } + } + } + Private->CurrentFileHandle = SaveCurrentFileHandle; + Private->CurrentPeimCount = SaveCurrentPeimCount; + } // // This is the main dispatch loop. It will search known FVs for PEIMs and @@ -91,69 +293,50 @@ Returns: // FV where PEIMs are found in the order their dependencies are also // satisfied, this dipatcher should run only once. // - for (;;) { - // - // This is the PEIM search loop. It will scan through all PEIMs it can find - // looking for PEIMs to dispatch, and will dipatch them if they have not - // already been dispatched and all of their dependencies are met. - // If no more PEIMs can be found in this pass through all known FVs, - // then it will break out of this loop. - // - for (;;) { + do { + PeimNeedingDispatch = FALSE; + PeimDispatchOnThisPass = FALSE; + + for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) { + Private->CurrentPeimFvCount = FvCount; + VolumeHandle = Private->Fv[FvCount].FvHeader; - Status = FindNextPeim ( - &PrivateData->PS, - DispatchData->CurrentFvAddress, - &DispatchData->CurrentPeimAddress - ); + if (Private->CurrentPeimCount == 0) { + // + // When going through each FV, at first, search Apriori file to + // reorder all PEIMs to ensure the PEIMs in Apriori file to get + // dispatch at first. + // + DiscoverPeimsAndOrderWithApriori (Private, VolumeHandle); + } // - // If we found a PEIM, check if it is dispatched. If so, go to the - // next PEIM. If not, dispatch it if its dependencies are satisfied. - // If its dependencies are not satisfied, go to the next PEIM. + // Start to dispatch all modules within the current Fv. // - if (Status == EFI_SUCCESS) { - - DEBUG_CODE_BEGIN (); - - // - // Fill list of found Peims for later list of those not installed - // - CopyMem ( - &DebugFoundPeimList[DispatchData->CurrentPeim], - &DispatchData->CurrentPeimAddress->Name, - sizeof (EFI_GUID) - ); - - DEBUG_CODE_END (); - - if (!Dispatched ( - DispatchData->CurrentPeim, - DispatchData->DispatchedPeimBitMap - )) { - if (DepexSatisfied (&PrivateData->PS, DispatchData->CurrentPeimAddress)) { + for (PeimCount = Private->CurrentPeimCount; + (PeimCount < PEI_CORE_MAX_PEIM_PER_FV) && (Private->CurrentFvFileHandles[PeimCount] != NULL); + PeimCount++) { + Private->CurrentPeimCount = PeimCount; + PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount]; + + if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) { + if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) { + PeimNeedingDispatch = TRUE; + } else { Status = PeiLoadImage ( - &PrivateData->PS, - DispatchData->CurrentPeimAddress, - &TempPtr.Raw + PeiServices, + PeimFileHandle, + &EntryPoint, + &AuthenticationState ); - if (Status == EFI_SUCCESS) { - + if ((Status == EFI_SUCCESS)) { // // The PEIM has its dependencies satisfied, and its entry point // has been found, so invoke it. // - PERF_START ( - (VOID *) (UINTN) (DispatchData->CurrentPeimAddress), - "PEIM", - NULL, - 0 - ); + PERF_START (0, "PEIM", NULL, 0); - // - // BUGBUG: Used to be EFI_PEI_REPORT_STATUS_CODE_CODE - // - ExtendedData.Handle = (EFI_HANDLE)DispatchData->CurrentPeimAddress; + ExtendedData.Handle = (EFI_HANDLE)PeimFileHandle; REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( EFI_PROGRESS_CODE, @@ -162,24 +345,19 @@ Returns: sizeof (ExtendedData) ); - // - // Is this a authentic image - // - Status = VerifyPeim ( - &PrivateData->PS, - DispatchData->CurrentPeimAddress - ); - - if (Status != EFI_SECURITY_VIOLATION) { + Status = VerifyPeim (Private, VolumeHandle, PeimFileHandle); + if (Status != EFI_SECURITY_VIOLATION && (AuthenticationState == 0)) { + // + // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED + // + Private->Fv[FvCount].PeimState[PeimCount]++; // - // BUGBUG: Before enable PI, we need cast EFI_FFS_FILE_HEADER* to EFI_PEI_FILE_HANDLE* - // Because we use new MdePkg's definition, but they are binary compatible in fact. + // Call the PEIM entry point // - Status = TempPtr.PeimEntry ( - (EFI_PEI_FILE_HANDLE*)DispatchData->CurrentPeimAddress, - &PrivateData->PS - ); + PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint; + PeimEntryPoint (PeimFileHandle, PeiServices); + PeimDispatchOnThisPass = TRUE; } REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( @@ -188,189 +366,146 @@ Returns: (VOID *)(&ExtendedData), sizeof (ExtendedData) ); + PERF_END (0, "PEIM", NULL, 0); + + } - PERF_END ((VOID *) (UINTN) (DispatchData->CurrentPeimAddress), "PEIM", NULL, 0); + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessNotifyList (Private); + + // + // If permanent memory was discovered and installed by this + // PEIM, shadow PEI Core and switch the stacks to the new memory. + // + if (Private->SwitchStackSignal) { // - // Mark the PEIM as dispatched so we don't attempt to run it again + // Make sure we don't retry the same PEIM that added memory // - SetDispatched ( - &PrivateData->PS, - DispatchData->CurrentPeim, - &DispatchData->DispatchedPeimBitMap - ); + Private->CurrentPeimCount++; // - // Process the Notify list and dispatch any notifies for - // newly installed PPIs. + // Migrate IDT from CAR into real memory, so after stack switches to + // the new memory, the caller can get memory version PeiServiceTable. // - ProcessNotifyList (&PrivateData->PS); + //MigrateIdtTable (PeiServices); + // + // Since we are at dispatch level, only the Core's private data + // is preserved, nobody else should have any data on the stack. + // So we need to copy PEI core instance data to memory. + // + PrivateInMem = AllocateCopyPool (sizeof (PEI_CORE_INSTANCE), Private); + ASSERT (PrivateInMem != NULL); // - // If real system memory was discovered and installed by this - // PEIM, switch the stacks to the new memory. Since we are - // at dispatch level, only the Core's private data is preserved, - // nobody else should have any data on the stack. + // Shadow PEI Core. When permanent memory is avaiable, shadow + // PEI Core and PEIMs to get high performance. // - if (PrivateData->SwitchStackSignal) { - // - // Adjust the top of stack to be aligned at CPU_STACK_ALIGNMENT - // - TopOfStack = (VOID *)((UINTN)PrivateData->StackBase + (UINTN)PrivateData->StackSize - CPU_STACK_ALIGNMENT); - TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); - - PeiCoreParameters.SecCoreData = SecCoreData; - PeiCoreParameters.PpiList = NULL; - PeiCoreParameters.Data = TransferOldDataToNewDataRange (PrivateData); - ASSERT (PeiCoreParameters.Data != 0); - - PeiSwitchStacks ( - InvokePeiCore, - (VOID*) (UINTN) PeiCore, - (VOID*) &PeiCoreParameters, - TopOfStack, - (VOID*)(UINTN)PrivateData->StackBase - ); - } + PeiCoreFileHandle = NULL; + // + // Find the PEI Core in the BFV + // + Status = PeiFindFileEx ( + (EFI_PEI_FV_HANDLE)Private->Fv[0].FvHeader, + NULL, + EFI_FV_FILETYPE_PEI_CORE, + &PeiCoreFileHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Shadow PEI Core into memory so it will run faster + // + Status = PeiLoadImage (PeiServices, PeiCoreFileHandle, &EntryPoint, &AuthenticationState); + ASSERT_EFI_ERROR (Status); + + // + // Switch to memory based stack and reenter PEI Core that has been + // shadowed to memory. + // + // + // Adjust the top of stack to be aligned at CPU_STACK_ALIGNMENT + // + TopOfStack = (VOID *)((UINTN)Private->StackBase + (UINTN)Private->StackSize - CPU_STACK_ALIGNMENT); + TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); + + PeiCoreParameters.SecCoreData = SecCoreData; + PeiCoreParameters.PpiList = NULL; + PeiCoreParameters.Data = PrivateInMem; + ASSERT (PeiCoreParameters.Data != 0); + + PeiSwitchStacks ( + InvokePeiCore, + (VOID*) (UINTN) PeiCore, + (VOID*) &PeiCoreParameters, + TopOfStack, + (VOID*)(UINTN)Private->StackBase + ); } - } - } - DispatchData->CurrentPeim++; - continue; - } else { - - // - // If we could not find another PEIM in the current FV, go try - // the FindFv PPI to look in other FVs for more PEIMs. If we can - // not locate the FindFv PPI, or if the FindFv PPI can not find - // anymore FVs, then exit the PEIM search loop. - // - if (DispatchData->FindFv == NULL) { - Status = PeiServicesLocatePpi ( - &gEfiFindFvPpiGuid, - 0, - NULL, - (VOID **)&DispatchData->FindFv - ); - if (Status != EFI_SUCCESS) { - break; - } - } - NextFvFound = FALSE; - while (!NextFvFound) { - Status = DispatchData->FindFv->FindFv ( - DispatchData->FindFv, - &PrivateData->PS, - &DispatchData->CurrentFv, - &NextFvAddress - ); - // - // if there is no next fv, get out of this loop of finding FVs - // - if (Status != EFI_SUCCESS) { - break; - } - // - // don't process the default Fv again. (we don't know the order in which the hobs were created) - // - if ((NextFvAddress != DefaultFvAddress) && - (NextFvAddress != DispatchData->CurrentFvAddress)) { + if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \ + (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) { + // + // If memory is availble 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); + PeimEntryPoint (PeimFileHandle, PeiServices); + //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0); + + // + // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE + // + Private->Fv[FvCount].PeimState[PeimCount]++; - // - // VerifyFv() is currently returns SUCCESS all the time, add code to it to - // actually verify the given FV - // - Status = VerifyFv (NextFvAddress); - if (Status == EFI_SUCCESS) { - NextFvFound = TRUE; - DispatchData->CurrentFvAddress = NextFvAddress; - DispatchData->CurrentPeimAddress = NULL; // - // current PRIM number (CurrentPeim) must continue as is, don't reset it here + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. // + ProcessNotifyList (Private); } } } - // - // if there is no next fv, get out of this loop of dispatching PEIMs - // - if (!NextFvFound) { - break; - } - // - // continue in the inner for(;;) loop with a new FV; - // } - } - // - // If all the PEIMs that we have found have been dispatched, then - // there is nothing left to dispatch and we don't need to go search - // through all PEIMs again. - // - if ((~(DispatchData->DispatchedPeimBitMap) & - ((1 << DispatchData->CurrentPeim)-1)) == 0) { - break; - } - - // - // Check if no more PEIMs that depex was satisfied - // - if (DispatchData->DispatchedPeimBitMap == DispatchData->PreviousPeimBitMap) { - break; + // + // We set to NULL here to optimize the 2nd entry to this routine after + // memory is found. This reprevents rescanning of the FV. We set to + // NULL here so we start at the begining of the next FV + // + Private->CurrentFileHandle = NULL; + Private->CurrentPeimCount = 0; + // + // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL + // + SetMem (Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles), 0); } // - // Case when Depex is not satisfied and has to traverse the list again + // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go + // through all the FV. // - DispatchData->CurrentPeim = 0; - DispatchData->CurrentPeimAddress = 0; - DispatchData->PreviousPeimBitMap = DispatchData->DispatchedPeimBitMap; + Private->CurrentPeimFvCount = 0; // - // don't go back to the loop without making sure that the CurrentFvAddress is the - // same as the 1st (or default) FV we started with. otherwise we will interpret the bimap wrongly and - // mess it up, always start processing the PEIMs from the default FV just like in the first time around. - // - DispatchData->CurrentFv = 0; - DispatchData->CurrentFvAddress = DefaultFvAddress; - } - - DEBUG_CODE_BEGIN (); + // PeimNeedingDispatch being TRUE means we found a PEIM that did not get + // dispatched. So we need to make another pass // - // Debug data for uninstalled Peim list + // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this + // pass. If we did not dispatch a PEIM there is no point in trying again + // as it will fail the next time too (nothing has changed). // - UINT32 DebugNotDispatchedBitmap; - UINT8 DebugFoundPeimPoint; + } while (PeimNeedingDispatch && PeimDispatchOnThisPass); - DebugFoundPeimPoint = 0; - // - // Get bitmap of Peims that were not dispatched, - // - - DebugNotDispatchedBitmap = ((DispatchData->DispatchedPeimBitMap) ^ ((1 << DispatchData->CurrentPeim)-1)); - // - // Scan bitmap of Peims not installed and print GUIDS - // - while (DebugNotDispatchedBitmap != 0) { - if ((DebugNotDispatchedBitmap & 1) != 0) { - DEBUG ((EFI_D_INFO, "WARNING -> InstallPpi: Not Installed: %g\n", - &DebugFoundPeimList[DebugFoundPeimPoint] - )); - } - DebugFoundPeimPoint++; - DebugNotDispatchedBitmap >>= 1; - } - - DEBUG_CODE_END (); - - return EFI_NOT_FOUND; } VOID InitializeDispatcherData ( - IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *PrivateData, IN PEI_CORE_INSTANCE *OldCoreData, IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData ) @@ -395,87 +530,19 @@ Returns: --*/ { - PEI_CORE_INSTANCE *PrivateData; - - PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); - if (OldCoreData == NULL) { - PrivateData->DispatchData.CurrentFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase; - PrivateData->DispatchData.BootFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase; - } else { - - // - // Current peim has been dispatched, but not count - // - PrivateData->DispatchData.CurrentPeim = (UINT8)(OldCoreData->DispatchData.CurrentPeim + 1); + PeiInitializeFv (PrivateData, SecCoreData); } return; } -BOOLEAN -Dispatched ( - IN UINT8 CurrentPeim, - IN UINT32 DispatchedPeimBitMap - ) -/*++ - -Routine Description: - - This routine checks to see if a particular PEIM has been dispatched during - the PEI core dispatch. - -Arguments: - CurrentPeim - The PEIM/FV in the bit array to check. - DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV. - -Returns: - TRUE - PEIM already dispatched - FALSE - Otherwise - ---*/ -{ - return (BOOLEAN)((DispatchedPeimBitMap & (1 << CurrentPeim)) != 0); -} - -VOID -SetDispatched ( - IN EFI_PEI_SERVICES **PeiServices, - IN UINT8 CurrentPeim, - OUT UINT32 *DispatchedPeimBitMap - ) -/*++ - -Routine Description: - - This routine sets a PEIM as having been dispatched once its entry - point has been invoked. - -Arguments: - - PeiServices - The PEI core services table. - CurrentPeim - The PEIM/FV in the bit array to check. - DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV. - -Returns: - None - ---*/ -{ - // - // Check if the total number of PEIMs exceed the bitmap. - // CurrentPeim is 0-based - // - ASSERT (CurrentPeim < (sizeof (*DispatchedPeimBitMap) * 8)); - *DispatchedPeimBitMap |= (1 << CurrentPeim); - return; -} - BOOLEAN DepexSatisfied ( - IN EFI_PEI_SERVICES **PeiServices, - IN VOID *CurrentPeimAddress + IN PEI_CORE_INSTANCE *Private, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINTN PeimCount ) /*++ @@ -495,59 +562,27 @@ Returns: --*/ { EFI_STATUS Status; - INT8 *DepexData; - BOOLEAN Runnable; - - Status = PeiServicesFfsFindSectionData ( - EFI_SECTION_PEI_DEPEX, - CurrentPeimAddress, - (VOID **)&DepexData - ); - // - // If there is no DEPEX, assume the module can be executed - // + VOID *DepexData; + + if (PeimCount < Private->AprioriCount) { + // + // If its in the A priori file then we set Depex to TRUE + // + return TRUE; + } + + Status = PeiServicesFfsFindSectionData (EFI_SECTION_PEI_DEPEX, FileHandle, (VOID **) &DepexData); if (EFI_ERROR (Status)) { + // + // If there is no DEPEX, assume the module can be executed + // return TRUE; } // // Evaluate a given DEPEX // - Status = PeimDispatchReadiness ( - PeiServices, - DepexData, - &Runnable - ); - - return Runnable; -} - -STATIC -VOID * -TransferOldDataToNewDataRange ( - IN PEI_CORE_INSTANCE *PrivateData - ) -/*++ - -Routine Description: - - This routine transfers the contents of the pre-permanent memory - PEI Core private data to a post-permanent memory data location. - -Arguments: - - PrivateData - Pointer to the current PEI Core private data pre-permanent memory - -Returns: - - Pointer to the PrivateData once the private data has been transferred to permanent memory - ---*/ -{ - // - //Build private HOB to PEI core to transfer old NEM-range data to new NEM-range - // - return BuildGuidDataHob (&gEfiPeiCorePrivateGuid, PrivateData, sizeof (PEI_CORE_INSTANCE)); + return PeimDispatchReadiness (&Private->PS, DepexData); } /** @@ -589,6 +624,7 @@ PeiRegisterForShadow ( return EFI_SUCCESS; } + /** This routine invoke the PeiCore's entry in new stack environment. @@ -627,7 +663,3 @@ InvokePeiCore ( // ASSERT_EFI_ERROR (FALSE); } - - - - diff --git a/MdeModulePkg/Core/Pei/FwVol/FwVol.c b/MdeModulePkg/Core/Pei/FwVol/FwVol.c index a5065632c3..958263b522 100644 --- a/MdeModulePkg/Core/Pei/FwVol/FwVol.c +++ b/MdeModulePkg/Core/Pei/FwVol/FwVol.c @@ -1,6 +1,6 @@ /*++ -Copyright (c) 2006, Intel Corporation +Copyright (c) 2006 - 2007, Intel Corporation All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -21,7 +21,14 @@ Abstract: #include -#define GETOCCUPIEDSIZE(ActualSize, Alignment) \ +STATIC EFI_PEI_NOTIFY_DESCRIPTOR mNotifyOnFvInfoList = { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiFirmwareVolumeInfoPpiGuid, + FirmwareVolmeInfoPpiNotifyCallback +}; + + +#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \ (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)) STATIC @@ -121,12 +128,37 @@ Bugbug: For PEI performance reason, we comments this code at this time. } STATIC +BOOLEAN +EFIAPI +PeiFileHandleToVolume ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PEI_FV_HANDLE *VolumeHandle + ) +{ + UINTN Index; + PEI_CORE_INSTANCE *PrivateData; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ()); + for (Index = 0; Index < PrivateData->FvCount; Index++) { + FwVolHeader = PrivateData->Fv[Index].FvHeader; + if (((UINT64) FileHandle > (UINT64) FwVolHeader ) && \ + ((UINT64) FileHandle <= ((UINT64) FwVolHeader + FwVolHeader->FvLength - 1))) { + *VolumeHandle = (EFI_PEI_FV_HANDLE)FwVolHeader; + return TRUE; + } + } + return FALSE; +} + + EFI_STATUS -PeiFfsFindNextFileEx ( - IN EFI_FV_FILETYPE SearchType, - IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, - IN OUT EFI_FFS_FILE_HEADER **FileHeader, - IN BOOLEAN Flag +PeiFindFileEx ( + IN CONST EFI_PEI_FV_HANDLE FvHandle, + IN CONST EFI_GUID *FileName, OPTIONAL + IN EFI_FV_FILETYPE SearchType, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle, + IN OUT EFI_PEI_FV_HANDLE *AprioriFile OPTIONAL ) /*++ @@ -144,53 +176,63 @@ Arguments: FileHeader - Pointer to the current file from which to begin searching. This pointer will be updated upon return to reflect the file found. Flag - Indicator for if this is for PEI Dispath search + Returns: EFI_NOT_FOUND - No files matching the search criteria were found EFI_SUCCESS --*/ { - EFI_FFS_FILE_HEADER *FfsFileHeader; - UINT32 FileLength; - UINT32 FileOccupiedSize; - UINT32 FileOffset; - UINT64 FvLength; - UINT8 ErasePolarity; - UINT8 FileState; - + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FFS_FILE_HEADER **FileHeader; + EFI_FFS_FILE_HEADER *FfsFileHeader; + EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo; + UINT32 FileLength; + UINT32 FileOccupiedSize; + UINT32 FileOffset; + UINT64 FvLength; + UINT8 ErasePolarity; + UINT8 FileState; + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvHandle; + FileHeader = (EFI_FFS_FILE_HEADER **)FileHandle; FvLength = FwVolHeader->FvLength; - if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) { + if (FwVolHeader->Attributes & EFI_FVB_ERASE_POLARITY) { ErasePolarity = 1; } else { ErasePolarity = 0; } // - // If FileHeader is not specified (NULL) start with the first file in the - // firmware volume. Otherwise, start from the FileHeader. + // If FileHeader is not specified (NULL) or FileName is not NULL, + // start with the first file in the firmware volume. Otherwise, + // start from the FileHeader. // - if (*FileHeader == NULL) { + if ((*FileHeader == NULL) || (FileName != NULL)) { FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength); + if (FwVolHeader->ExtHeaderOffset != 0) { + FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(((UINT8 *)FwVolHeader) + FwVolHeader->ExtHeaderOffset); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FwVolExHeaderInfo) + FwVolExHeaderInfo->ExtHeaderSize); + } } else { // // Length is 24 bits wide so mask upper 8 bits // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned. // FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF; - FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8); + FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8); FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize); } FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader); ASSERT (FileOffset <= 0xFFFFFFFF); - while (FileOffset < (FvLength - sizeof(EFI_FFS_FILE_HEADER))) { + while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) { // // Get FileState which is the highest bit of the State // FileState = GetFileState (ErasePolarity, FfsFileHeader); - switch (FileState) { case EFI_FILE_HEADER_INVALID: @@ -200,40 +242,44 @@ Returns: case EFI_FILE_DATA_VALID: case EFI_FILE_MARKED_FOR_UPDATE: - if (CalculateHeaderChecksum (FfsFileHeader) == 0) { - FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; - FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8); - if (Flag) { - if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) || - (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) { - - *FileHeader = FfsFileHeader; - - - return EFI_SUCCESS; - } - } else { - if ((SearchType == FfsFileHeader->Type) || - (SearchType == EFI_FV_FILETYPE_ALL)) { - - *FileHeader = FfsFileHeader; - - - return EFI_SUCCESS; - } - } - - FileOffset += FileOccupiedSize; - FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); - } else { + if (CalculateHeaderChecksum (FfsFileHeader) != 0) { ASSERT (FALSE); return EFI_NOT_FOUND; } + + FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8); + + if (FileName != NULL) { + if (CompareGuid (&FfsFileHeader->Name, (EFI_GUID*)FileName)) { + *FileHeader = FfsFileHeader; + return EFI_SUCCESS; + } + } else if (SearchType == PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE) { + if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) || + (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) { + + *FileHeader = FfsFileHeader; + return EFI_SUCCESS; + } else if (AprioriFile != NULL) { + if (FfsFileHeader->Type == EFI_FV_FILETYPE_FREEFORM) { + if (CompareGuid (&FfsFileHeader->Name, &gPeiAprioriFileNameGuid)) { + *AprioriFile = FfsFileHeader; + } + } + } + } else if ((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) { + *FileHeader = FfsFileHeader; + return EFI_SUCCESS; + } + + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); break; case EFI_FILE_DELETED: FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; - FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8); + FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8); FileOffset += FileOccupiedSize; FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); break; @@ -247,6 +293,206 @@ Returns: return EFI_NOT_FOUND; } +VOID +PeiInitializeFv ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ) +/*++ + +Routine Description: + + Initialize PeiCore Fv List. + +Arguments: + PrivateData - Pointer to PEI_CORE_INSTANCE. + SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF. + +Returns: + NONE + +--*/ +{ + EFI_STATUS Status; + // + // The BFV must be the first entry. The Core FV support is stateless + // The AllFV list has a single entry per FV in PEI. + // The Fv list only includes FV that PEIMs will be dispatched from and + // its File System Format is PI 1.0 definition. + // + PrivateData->FvCount = 1; + PrivateData->Fv[0].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase; + + PrivateData->AllFvCount = 1; + PrivateData->AllFv[0] = (EFI_PEI_FV_HANDLE)PrivateData->Fv[0].FvHeader; + + + // + // Post a call-back for the FvInfoPPI services to expose + // additional Fvs to PeiCore. + // + Status = PeiServicesNotifyPpi (&mNotifyOnFvInfoList); + ASSERT_EFI_ERROR (Status); + +} + +EFI_STATUS +EFIAPI +FirmwareVolmeInfoPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +/*++ + +Routine Description: + + Process Firmware Volum Information once FvInfoPPI install. + +Arguments: + + PeiServices - General purpose services available to every PEIM. + +Returns: + + Status - EFI_SUCCESS if the interface could be successfully + installed + +--*/ +{ + UINT8 FvCount; + EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv; + PEI_CORE_INSTANCE *PrivateData; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + if (PrivateData->FvCount >= PEI_CORE_MAX_FV_SUPPORTED) { + ASSERT (FALSE); + } + + Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *)Ppi; + + if (CompareGuid (&Fv->FvFormat, &gEfiFirmwareFileSystem2Guid)) { + for (FvCount = 0; FvCount < PrivateData->FvCount; FvCount ++) { + if ((UINTN)PrivateData->Fv[FvCount].FvHeader == (UINTN)Fv->FvInfo) { + return EFI_SUCCESS; + } + } + PrivateData->Fv[PrivateData->FvCount++].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Fv->FvInfo; + BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, (UINT64) Fv->FvInfoSize); + } + + // + // Allways add to the All list + // + PrivateData->AllFv[PrivateData->AllFvCount++] = (EFI_PEI_FV_HANDLE)Fv->FvInfo; + + return EFI_SUCCESS; +} + +EFI_STATUS +PeiFfsProcessSection ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_COMMON_SECTION_HEADER *Section, + IN UINTN SectionSize, + OUT VOID **OutputBuffer, + OUT UINTN *OutputSize, + OUT UINT32 *Authentication + ) +/*++ + +Routine Description: + + Go through the file to search SectionType section, + when meeting an encapsuled section, search recursively. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only section of this type. + Section - From where to search. + SectionSize - The file size to search. + OutputBuffer - Pointer to the section to search. + OutputSize - The size of the section to search. + Authentication - Authenticate the section. + +Returns: + EFI_STATUS + +--*/ +{ + EFI_STATUS Status; + UINT32 SectionLength; + UINT32 ParsedLength; + EFI_GUID_DEFINED_SECTION *GuidSection; + EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *GuidSectionPpi; + EFI_COMPRESSION_SECTION *CompressionSection; + EFI_PEI_DECOMPRESS_PPI *DecompressPpi; + VOID *PpiOutput; + UINTN PpiOutputSize; + + *OutputBuffer = NULL; + ParsedLength = 0; + while (ParsedLength < SectionSize) { + if (Section->Type == SectionType) { + *OutputBuffer = (VOID *)(Section + 1); + return EFI_SUCCESS; + } else if (Section->Type == EFI_SECTION_GUID_DEFINED) { + GuidSection = (EFI_GUID_DEFINED_SECTION *)Section; + Status = PeiServicesLocatePpi (&GuidSection->SectionDefinitionGuid, 0, NULL, (VOID **) &GuidSectionPpi); + if (!EFI_ERROR (Status)) { + Status = GuidSectionPpi->ExtractSection ( + GuidSectionPpi, + Section, + &PpiOutput, + &PpiOutputSize, + Authentication + ); + if (!EFI_ERROR (Status)) { + return PeiFfsProcessSection ( + PeiServices, + SectionType, + PpiOutput, + PpiOutputSize, + OutputBuffer, + OutputSize, + Authentication + ); + } + } + } else if (Section->Type == EFI_SECTION_COMPRESSION) { + CompressionSection = (EFI_COMPRESSION_SECTION *)Section; + Status = PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid, 0, NULL, (VOID **) &DecompressPpi); + if (!EFI_ERROR (Status)) { + Status = DecompressPpi->Decompress ( + DecompressPpi, + CompressionSection, + &PpiOutput, + &PpiOutputSize + ); + if (!EFI_ERROR (Status)) { + return PeiFfsProcessSection ( + PeiServices, SectionType, PpiOutput, PpiOutputSize, OutputBuffer, OutputSize, Authentication + ); + } + } + } + + // + // Size is 24 bits wide so mask upper 8 bits. + // SectionLength is adjusted it is 4 byte aligned. + // Go to the next section + // + SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF; + SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4); + ASSERT (SectionLength != 0); + ParsedLength += SectionLength; + Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength); + } + + return EFI_NOT_FOUND; +} + EFI_STATUS EFIAPI @@ -275,46 +521,33 @@ Returns: --*/ { - UINT32 FileSize; - EFI_COMMON_SECTION_HEADER *Section; - UINT32 SectionLength; - UINT32 ParsedLength; - EFI_FFS_FILE_HEADER *FfsFileHeader; + EFI_FFS_FILE_HEADER *FfsFileHeader; + UINT32 FileSize; + EFI_COMMON_SECTION_HEADER *Section; + UINTN OutputSize; + UINT32 AuthenticationStatus; + + + FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle); - FfsFileHeader = (EFI_FFS_FILE_HEADER *) FileHandle; - // // Size is 24 bits wide so mask upper 8 bits. - // Does not include FfsFileHeader header size + // Does not include FfsFileHeader header size // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned. // Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1); FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; - FileSize -= sizeof(EFI_FFS_FILE_HEADER); - - *SectionData = NULL; - ParsedLength = 0; - while (ParsedLength < FileSize) { - if (Section->Type == SectionType) { - *SectionData = (VOID *)(Section + 1); - - - return EFI_SUCCESS; - } - // - // Size is 24 bits wide so mask upper 8 bits. - // SectionLength is adjusted it is 4 byte aligned. - // Go to the next section - // - SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF; - SectionLength = GETOCCUPIEDSIZE (SectionLength, 4); - ASSERT (SectionLength != 0); - ParsedLength += SectionLength; - Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength); - } - - return EFI_NOT_FOUND; - + FileSize -= sizeof (EFI_FFS_FILE_HEADER); + + return PeiFfsProcessSection ( + PeiServices, + SectionType, + Section, + FileSize, + SectionData, + &OutputSize, + &AuthenticationStatus + ); } @@ -346,11 +579,12 @@ Returns: --*/ { - return PeiFfsFindNextFileEx ( - 0, - FwVolHeader, - PeimFileHeader, - TRUE + return PeiFindFileEx ( + (EFI_PEI_FV_HANDLE) FwVolHeader, + NULL, + EFI_FV_FILETYPE_PEIM, + (EFI_PEI_FILE_HANDLE *)PeimFileHeader, + NULL ); } @@ -387,20 +621,10 @@ Returns: --*/ { - EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; - EFI_FFS_FILE_HEADER **FileHeader; - - FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)VolumeHandle; - FileHeader = (EFI_FFS_FILE_HEADER **) FileHandle; - - return PeiFfsFindNextFileEx ( - SearchType, - FwVolHeader, - FileHeader, - FALSE - ); + return PeiFindFileEx (VolumeHandle, NULL, SearchType, FileHandle, NULL); } + EFI_STATUS EFIAPI PeiFvFindNextVolume ( @@ -433,52 +657,162 @@ Returns: --*/ { - PEI_CORE_INSTANCE *PrivateData; - EFI_STATUS Status; - EFI_PEI_FIND_FV_PPI *FindFvPpi; - UINT8 LocalInstance; - EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader; + PEI_CORE_INSTANCE *Private; - FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER **) VolumeHandle; + Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + if (VolumeHandle == NULL) { + return EFI_INVALID_PARAMETER; + } - LocalInstance = (UINT8) Instance; + if (Instance >= Private->AllFvCount) { + VolumeHandle = NULL; + return EFI_NOT_FOUND; + } - Status = EFI_SUCCESS; - PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + *VolumeHandle = Private->AllFv[Instance]; + return EFI_SUCCESS; +} - if (FwVolHeader == NULL) { +EFI_STATUS +EFIAPI +PeiFfsFindFileByName ( + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +/*++ + +Routine Description: + + Given the input VolumeHandle, search for the next matching name file. + +Arguments: + + FileName - File name to search. + VolumeHandle - The current FV to search. + FileHandle - Pointer to the file matching name in VolumeHandle. + - NULL if file not found +Returns: + EFI_STATUS + +--*/ +{ + EFI_STATUS Status; + if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) { return EFI_INVALID_PARAMETER; } + Status = PeiFindFileEx (VolumeHandle, FileName, 0, FileHandle, NULL); + if (Status == EFI_NOT_FOUND) { + *FileHandle = NULL; + } + return Status; +} + +EFI_STATUS +EFIAPI +PeiFfsGetFileInfo ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ) +/*++ + +Routine Description: - if (Instance == 0) { - *FwVolHeader = PrivateData->DispatchData.BootFvAddress; + Collect information of given file. +Arguments: + FileHandle - The handle to file. + FileInfo - Pointer to the file information. - return Status; +Returns: + EFI_STATUS + +--*/ +{ + UINT8 FileState; + UINT8 ErasePolarity; + EFI_FFS_FILE_HEADER *FileHeader; + EFI_PEI_FV_HANDLE VolumeHandle; + + if ((FileHandle == NULL) || (FileInfo == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Retrieve the FirmwareVolume which the file resides in. + // + if (!PeiFileHandleToVolume(FileHandle, &VolumeHandle)) { + return EFI_INVALID_PARAMETER; + } + + if (((EFI_FIRMWARE_VOLUME_HEADER*)VolumeHandle)->Attributes & EFI_FVB_ERASE_POLARITY) { + ErasePolarity = 1; } else { - // - // Locate all instances of FindFV - // Alternately, could use FV HOBs, but the PPI is cleaner - // - Status = PeiServicesLocatePpi ( - &gEfiFindFvPpiGuid, - 0, - NULL, - (VOID **)&FindFvPpi - ); - - if (Status != EFI_SUCCESS) { - Status = EFI_NOT_FOUND; - } else { - Status = FindFvPpi->FindFv ( - FindFvPpi, - (EFI_PEI_SERVICES **)PeiServices, - &LocalInstance, - FwVolHeader - ); + ErasePolarity = 0; + } + + // + // Get FileState which is the highest bit of the State + // + FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle); + switch (FileState) { + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + break; + default: + return EFI_INVALID_PARAMETER; } + + FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle; + CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID)); + FileInfo->FileType = FileHeader->Type; + FileInfo->FileAttributes = FileHeader->Attributes; + FileInfo->BufferSize = ((*(UINT32 *)FileHeader->Size) & 0x00FFFFFF) - sizeof (EFI_FFS_FILE_HEADER); + FileInfo->Buffer = (FileHeader + 1); + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ) +/*++ + +Routine Description: + + Collect information of given Fv Volume. + +Arguments: + VolumeHandle - The handle to Fv Volume. + VolumeInfo - The pointer to volume information. + +Returns: + EFI_STATUS + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo; + + if (VolumeInfo == NULL) { + return EFI_INVALID_PARAMETER; } - return Status; + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(VolumeHandle); + VolumeInfo->FvAttributes = FwVolHeader->Attributes; + VolumeInfo->FvStart = FwVolHeader; + VolumeInfo->FvSize = FwVolHeader->FvLength; + CopyMem (&VolumeInfo->FvFormat, &FwVolHeader->FileSystemGuid,sizeof(EFI_GUID)); + + if (FwVolHeader->ExtHeaderOffset != 0) { + FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)FwVolHeader) + FwVolHeader->ExtHeaderOffset); + CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID)); + } + return EFI_SUCCESS; } + diff --git a/MdeModulePkg/Core/Pei/Image/Image.c b/MdeModulePkg/Core/Pei/Image/Image.c index 202936869b..ebe79a6c50 100644 --- a/MdeModulePkg/Core/Pei/Image/Image.c +++ b/MdeModulePkg/Core/Pei/Image/Image.c @@ -21,13 +21,33 @@ Abstract: #include +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file +Arguments: + + FileHandle - The handle to the PE/COFF file + FileOffset - The offset, in bytes, into the file to read + ReadSize - The number of bytes to read from the file starting at FileOffset + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ EFI_STATUS -PeiLoadImage ( - IN EFI_PEI_SERVICES **PeiServices, - IN EFI_FFS_FILE_HEADER *PeimFileHeader, - OUT VOID **EntryPoint +PeiLoadImageLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL + OUT UINT64 *ImageSizeArg, OPTIONAL + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState ) /*++ @@ -37,9 +57,247 @@ Routine Description: Arguments: - PeiServices - The PEI core services table. - PeimFileHeader - Pointer to the FFS file header of the image. - EntryPoint - Pointer to entry point of specified image file for output. + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + ImageAddressArg - Pointer to PE/TE image. + ImageSizeArg - Size of PE/TE image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + Status - EFI_SUCCESS - Image is successfully loaded. + EFI_NOT_FOUND - Fail to locate necessary PPI + Others - Fail to load file. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiLoadImageLoadImageWrapper ( + IN CONST EFI_PEI_LOAD_FILE_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL + OUT UINT64 *ImageSizeArg, OPTIONAL + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + The wrapper function of PeiLoadImageLoadImage(). + +Arguments: + + This - Pointer to EFI_PEI_LOAD_FILE_PPI. + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + ImageAddressArg - Pointer to PE/TE image. + ImageSizeArg - Size of PE/TE image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + EFI_STATUS. + +--*/ +; + +STATIC EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi = { + PeiLoadImageLoadImageWrapper +}; + + +STATIC EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiLoadFilePpiGuid, + &mPeiLoadImagePpi +}; + +EFI_STATUS +EFIAPI +PeiImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + FileOffset - The offset, in bytes, into the file to read + ReadSize - The number of bytes to read from the file starting at FileOffset + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINTN Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetImageReadFunction ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Support routine to return the Image Read + +Arguments: + + PeiServices - PEI Services Table + + ImageContext - The context of the image being loaded + +Returns: + + EFI_SUCCESS - If Image function location is found + +--*/ +{ + VOID* MemoryBuffer; + + MemoryBuffer = AllocatePages (0x400 / EFI_PAGE_SIZE + 1); + ASSERT (MemoryBuffer != NULL); + + CopyMem (MemoryBuffer, (CONST VOID *) (UINTN) PeiImageRead, 0x400); + + ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +LoadAndRelocatePeCoffImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader, + IN VOID *Pe32Data, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +/*++ + +Routine Description: + + Loads and relocates a PE/COFF image into memory. + +Arguments: + + PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol + + Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated + + ImageAddress - The base address of the relocated PE/COFF image + + ImageSize - The size of the relocated PE/COFF image + + EntryPoint - The entry point of the relocated PE/COFF image + +Returns: + + EFI_SUCCESS - The file was loaded and relocated + + EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file + +--*/ +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + + ASSERT (PeiEfiPeiPeCoffLoader != NULL); + + ZeroMem (&ImageContext, sizeof (ImageContext)); + ImageContext.Handle = Pe32Data; + Status = GetImageReadFunction (&ImageContext); + + ASSERT_EFI_ERROR (Status); + + Status = PeiEfiPeiPeCoffLoader->GetImageInfo (PeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Allocate Memory for the image + // + ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize)); + ASSERT (ImageContext.ImageAddress != 0); + + // + // Load the image to our new buffer + // + Status = PeiEfiPeiPeCoffLoader->LoadImage (PeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Relocate the image in our new buffer + // + Status = PeiEfiPeiPeCoffLoader->RelocateImage (PeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Flush the instruction cache so the image data is written before we execute it + // + InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); + + *ImageAddress = ImageContext.ImageAddress; + *ImageSize = ImageContext.ImageSize; + *EntryPoint = ImageContext.EntryPoint; + + return EFI_SUCCESS; +} + +EFI_STATUS +PeiLoadImageLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL + OUT UINT64 *ImageSizeArg, OPTIONAL + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + Routine for loading file image. + +Arguments: + + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + ImageAddressArg - Pointer to PE/TE image. + ImageSizeArg - Size of PE/TE image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. Returns: @@ -51,55 +309,63 @@ Returns: { EFI_STATUS Status; VOID *Pe32Data; - EFI_PEI_FV_FILE_LOADER_PPI *FvLoadFilePpi; EFI_PHYSICAL_ADDRESS ImageAddress; UINT64 ImageSize; EFI_PHYSICAL_ADDRESS ImageEntryPoint; EFI_TE_IMAGE_HEADER *TEImageHeader; UINT16 Machine; + PEI_CORE_INSTANCE *Private; + VOID *EntryPointArg; - *EntryPoint = NULL; + *EntryPoint = 0; TEImageHeader = NULL; + ImageSize = 0; + *AuthenticationState = 0; // - // Try to find a PE32 section. + // Try to find a TE section. // Status = PeiServicesFfsFindSectionData ( - EFI_SECTION_PE32, - PeimFileHeader, + EFI_SECTION_TE, + FileHandle, &Pe32Data ); + if (!EFI_ERROR (Status)) { + TEImageHeader = (EFI_TE_IMAGE_HEADER *)Pe32Data; + } // // If we didn't find a PE32 section, try to find a TE section. // if (EFI_ERROR (Status)) { Status = PeiServicesFfsFindSectionData ( - EFI_SECTION_TE, - PeimFileHeader, - (VOID **) &TEImageHeader + EFI_SECTION_PE32, + FileHandle, + &Pe32Data ); - if (EFI_ERROR (Status) || TEImageHeader == NULL) { + if (EFI_ERROR (Status)) { // - // There was not a PE32 or a TE section, so assume that it's a Compressed section - // and use the LoadFile + // PEI core only carry the loader function fro TE and PE32 executables + // If this two section does not exist, just return. // - Status = PeiServicesLocatePpi ( - &gEfiPeiFvFileLoaderPpiGuid, - 0, - NULL, - (VOID **)&FvLoadFilePpi - ); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } + return Status; + } + } + + Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); - Status = FvLoadFilePpi->FvLoadFile ( - FvLoadFilePpi, - PeimFileHeader, - &ImageAddress, - &ImageSize, - &ImageEntryPoint - ); + if (Private->PeiMemoryInstalled && + (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) { + { + // + // If memory is installed, perform the shadow operations + // + Status = LoadAndRelocatePeCoffImage ( + Private->PeCoffLoader, + Pe32Data, + &ImageAddress, + &ImageSize, + &ImageEntryPoint + ); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; @@ -109,23 +375,28 @@ Returns: // Got the entry point from ImageEntryPoint and ImageStartAddress // Pe32Data = (VOID *) ((UINTN) ImageAddress); - *EntryPoint = (VOID *) ((UINTN) ImageEntryPoint); - } else { + *EntryPoint = ImageEntryPoint; + } + } else { + if (TEImageHeader != NULL) { // // Retrieve the entry point from the TE image header // ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) TEImageHeader; - *EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) + + ImageSize = 0; + *EntryPoint = (EFI_PHYSICAL_ADDRESS)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) + TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize); - } - } else { - // - // Retrieve the entry point from the PE/COFF image header - // - ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data; - Status = PeCoffLoaderGetEntryPoint (Pe32Data, EntryPoint); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; + } else { + // + // Retrieve the entry point from the PE/COFF image header + // + ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data; + ImageSize = 0; + Status = PeCoffLoaderGetEntryPoint (Pe32Data, &EntryPointArg); + *EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) EntryPointArg; + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } } } @@ -140,6 +411,14 @@ Returns: return EFI_UNSUPPORTED; } + if (ImageAddressArg != NULL) { + *ImageAddressArg = ImageAddress; + } + + if (ImageSizeArg != NULL) { + *ImageSizeArg = ImageSize; + } + // // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi // @@ -264,4 +543,175 @@ Returns: DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n")); return EFI_SUCCESS; + +} + + +EFI_STATUS +EFIAPI +PeiLoadImageLoadImageWrapper ( + IN CONST EFI_PEI_LOAD_FILE_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL + OUT UINT64 *ImageSizeArg, OPTIONAL + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + The wrapper function of PeiLoadImageLoadImage(). + +Arguments: + + This - Pointer to EFI_PEI_LOAD_FILE_PPI. + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + ImageAddressArg - Pointer to PE/TE image. + ImageSizeArg - Size of PE/TE image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + EFI_STATUS. + +--*/ +{ + return PeiLoadImageLoadImage ( + GetPeiServicesTablePointer (), + FileHandle, + ImageAddressArg, + ImageSizeArg, + EntryPoint, + AuthenticationState + ); } + +EFI_STATUS +PeiLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +/*++ + +Routine Description: + + Routine for load image file. + +Arguments: + + PeiServices - The PEI core services table. + FileHandle - Pointer to the FFS file header of the image. + EntryPoint - Pointer to entry point of specified image file for output. + AuthenticationState - Pointer to attestation authentication state of image. + +Returns: + + Status - EFI_SUCCESS - Image is successfully loaded. + EFI_NOT_FOUND - Fail to locate necessary PPI + Others - Fail to load file. + +--*/ +{ + EFI_STATUS PpiStatus; + EFI_STATUS Status; + UINTN Index; + EFI_PEI_LOAD_FILE_PPI *LoadFile; + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + + // + // If any instances of PEI_LOAD_FILE_PPI are installed, they are called. + // one at a time, until one reports EFI_SUCCESS. + // + Index = 0; + do { + PpiStatus = PeiServicesLocatePpi ( + &gEfiPeiLoadFilePpiGuid, + Index, + NULL, + (VOID **)&LoadFile + ); + if (!EFI_ERROR (PpiStatus)) { + Status = LoadFile->LoadFile ( + LoadFile, + FileHandle, + &ImageAddress, + &ImageSize, + EntryPoint, + AuthenticationState + ); + if (!EFI_ERROR (Status)) { + return Status; + } + } + Index++; + } while (!EFI_ERROR (PpiStatus)); + + // + // If no instances reports EFI_SUCCESS, then build-in support for + // the PE32+/TE XIP image format is used. + // + Status = PeiLoadImageLoadImage ( + PeiServices, + FileHandle, + NULL, + NULL, + EntryPoint, + AuthenticationState + ); + return Status; +} + + +VOID +InitializeImageServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Regitser PeCoffLoader to PeiCore PrivateData. And install + Pei Load File PPI. + +Arguments: + + PrivateData - Pointer to PEI_CORE_INSTANCE. + OldCoreData - Pointer to PEI_CORE_INSTANCE. + +Returns: + + NONE. + +--*/ +{ + // + // Always update PeCoffLoader pointer as PEI core itself may get + // shadowed into memory + // + PrivateData->PeCoffLoader = GetPeCoffLoaderProtocol (); + + if (OldCoreData == NULL) { + // + // The first time we are XIP (running from FLASH). We need to remember the + // FLASH address so we can reinstall the memory version that runs faster + // + PrivateData->XipLoadFile = &gPpiLoadFilePpiList; + PeiServicesInstallPpi (PrivateData->XipLoadFile); + } else { + // + // 2nd time we are running from memory so replace the XIP version with the + // new memory version. + // + PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList); + } +} + + + diff --git a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c index 49e9f7f552..0976e2cbdd 100644 --- a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c +++ b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c @@ -23,7 +23,7 @@ Abstract: VOID InitializeMemoryServices ( - IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *PrivateData, IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, IN PEI_CORE_INSTANCE *OldCoreData ) @@ -49,9 +49,6 @@ Returns: --*/ { - PEI_CORE_INSTANCE *PrivateData; - - PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); PrivateData->SwitchStackSignal = FALSE; if (OldCoreData == NULL) { @@ -64,6 +61,8 @@ Returns: DEBUG_CODE_BEGIN (); PrivateData->SizeOfCacheAsRam = SecCoreData->PeiTemporaryRamSize + SecCoreData->StackSize; PrivateData->MaxTopOfCarHeap = (VOID *) ((UINTN) PrivateData->BottomOfCarHeap + (UINTN) PrivateData->SizeOfCacheAsRam); + PrivateData->StackBase = (EFI_PHYSICAL_ADDRESS) (UINTN) SecCoreData->StackBase; + PrivateData->StackSize = (UINT64) SecCoreData->StackSize; DEBUG_CODE_END (); PrivateData->HobList.Raw = PrivateData->BottomOfCarHeap; @@ -73,23 +72,13 @@ Returns: (EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->BottomOfCarHeap, (UINTN) SecCoreData->PeiTemporaryRamSize ); - // - // Copy PeiServices from ROM to Cache in PrivateData - // - CopyMem (&(PrivateData->ServiceTableShadow), *PeiServices, sizeof (EFI_PEI_SERVICES)); // // Set PS to point to ServiceTableShadow in Cache // PrivateData->PS = &(PrivateData->ServiceTableShadow); - } else { - // - // Set PS to point to ServiceTableShadow in Cache one time after the - // stack switched to main memory - // - PrivateData->PS = &(PrivateData->ServiceTableShadow); -} - + } + return; } diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMain.h index 50fd40a00e..da0c0aa1af 100644 --- a/MdeModulePkg/Core/Pei/PeiMain.h +++ b/MdeModulePkg/Core/Pei/PeiMain.h @@ -29,11 +29,14 @@ Revision History #include #include #include -#include #include -#include #include -#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -43,11 +46,15 @@ Revision History #include #include #include +#include #include +#include #include #include - -extern EFI_GUID gEfiPeiCorePrivateGuid; +#include +#include +#include +#include #define PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE 0xff @@ -94,18 +101,6 @@ typedef struct { BOOLEAN ScanFv; } PEI_CORE_FV_HANDLE; -typedef struct { - UINT8 CurrentPeim; - UINT8 CurrentFv; - UINT32 DispatchedPeimBitMap; - UINT32 PreviousPeimBitMap; - EFI_FFS_FILE_HEADER *CurrentPeimAddress; - EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress; - EFI_FIRMWARE_VOLUME_HEADER *BootFvAddress; - EFI_PEI_FIND_FV_PPI *FindFv; -} PEI_CORE_DISPATCH_DATA; - - // // Pei Core private data structure instance // @@ -116,7 +111,6 @@ typedef struct{ UINTN Signature; EFI_PEI_SERVICES *PS; // Point to ServiceTableShadow PEI_PPI_DATABASE PpiData; - PEI_CORE_DISPATCH_DATA DispatchData; UINTN FvCount; PEI_CORE_FV_HANDLE Fv[PEI_CORE_MAX_FV_SUPPORTED]; EFI_PEI_FILE_HANDLE CurrentFvFileHandles[PEI_CORE_MAX_PEIM_PER_FV]; @@ -134,10 +128,12 @@ typedef struct{ VOID *BottomOfCarHeap; VOID *TopOfCarHeap; VOID *CpuIo; - EFI_PEI_SECURITY_PPI *PrivateSecurityPpi; + EFI_PEI_SECURITY2_PPI *PrivateSecurityPpi; EFI_PEI_SERVICES ServiceTableShadow; UINTN SizeOfCacheAsRam; VOID *MaxTopOfCarHeap; + EFI_PEI_PPI_DESCRIPTOR *XipLoadFile; + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeCoffLoader; } PEI_CORE_INSTANCE; // @@ -215,11 +211,10 @@ Returns: // Dispatcher support functions // -EFI_STATUS +BOOLEAN PeimDispatchReadiness ( IN EFI_PEI_SERVICES **PeiServices, - IN VOID *DependencyExpression, - IN OUT BOOLEAN *Runnable + IN VOID *DependencyExpression ) /*++ @@ -255,11 +250,10 @@ Returns: ; -EFI_STATUS +VOID PeiDispatcher ( IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, - IN PEI_CORE_INSTANCE *PrivateData, - IN PEI_CORE_DISPATCH_DATA *DispatchData + IN PEI_CORE_INSTANCE *PrivateData ) /*++ @@ -285,7 +279,7 @@ Returns: VOID InitializeDispatcherData ( - IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *PrivateData, IN PEI_CORE_INSTANCE *OldCoreData, IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData ) @@ -390,8 +384,9 @@ Returns: BOOLEAN DepexSatisfied ( - IN EFI_PEI_SERVICES **PeiServices, - IN VOID *CurrentPeimAddress + IN PEI_CORE_INSTANCE *Private, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINTN PeimCount ) /*++ @@ -448,7 +443,7 @@ Returns: // VOID InitializePpiServices ( - IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *PrivateData, IN PEI_CORE_INSTANCE *OldCoreData ) /*++ @@ -607,7 +602,7 @@ Returns: VOID ProcessNotifyList ( - IN EFI_PEI_SERVICES **PeiServices + IN PEI_CORE_INSTANCE *PrivateData ) /*++ @@ -626,7 +621,7 @@ Returns: VOID DispatchNotify ( - IN CONST EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *PrivateData, IN UINTN NotifyType, IN INTN InstallStartIndex, IN INTN InstallStopIndex, @@ -755,8 +750,9 @@ Returns: EFI_STATUS VerifyPeim ( - IN EFI_PEI_SERVICES **PeiServices, - IN EFI_FFS_FILE_HEADER *CurrentPeimAddress + IN PEI_CORE_INSTANCE *PrivateData, + IN EFI_PEI_FV_HANDLE VolumeHandle, + IN EFI_PEI_FILE_HANDLE FileHandle ) /*++ @@ -901,7 +897,7 @@ Returns: EFI_STATUS EFIAPI PeiFfsFindSectionData ( - IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_SERVICES **PeiServices, IN EFI_SECTION_TYPE SectionType, IN EFI_PEI_FILE_HANDLE FfsFileHeader, IN OUT VOID **SectionData @@ -964,7 +960,7 @@ Returns: // VOID InitializeMemoryServices ( - IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *PrivateData, IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, IN PEI_CORE_INSTANCE *OldCoreData ) @@ -1082,8 +1078,9 @@ Returns: EFI_STATUS PeiLoadImage ( IN EFI_PEI_SERVICES **PeiServices, - IN EFI_FFS_FILE_HEADER *PeimFileHeader, - OUT VOID **EntryPoint + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState ) /*++ @@ -1149,7 +1146,7 @@ Returns: EFI_STATUS EFIAPI PeiResetSystem ( - IN EFI_PEI_SERVICES **PeiServices + IN CONST EFI_PEI_SERVICES **PeiServices ) /*++ @@ -1171,6 +1168,148 @@ Returns: --*/ ; +VOID +PeiInitializeFv ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ) +/*++ + +Routine Description: + + Initialize PeiCore Fv List. + +Arguments: + PrivateData - Pointer to PEI_CORE_INSTANCE. + SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF. + +Returns: + NONE + +--*/ +; + +EFI_STATUS +EFIAPI +FirmwareVolmeInfoPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +/*++ + +Routine Description: + + Process Firmware Volum Information once FvInfoPPI install. + +Arguments: + + PeiServices - General purpose services available to every PEIM. + +Returns: + + Status - EFI_SUCCESS if the interface could be successfully + installed + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiFfsFindFileByName ( + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +/*++ + +Routine Description: + + Given the input VolumeHandle, search for the next matching name file. + +Arguments: + + FileName - File name to search. + VolumeHandle - The current FV to search. + FileHandle - Pointer to the file matching name in VolumeHandle. + - NULL if file not found +Returns: + EFI_STATUS + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiFfsGetFileInfo ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ) +/*++ + +Routine Description: + + Collect information of given file. + +Arguments: + FileHandle - The handle to file. + FileInfo - Pointer to the file information. + +Returns: + EFI_STATUS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ) +/*++ + +Routine Description: + + Collect information of given Fv Volume. + +Arguments: + VolumeHandle - The handle to Fv Volume. + VolumeInfo - The pointer to volume information. + +Returns: + EFI_STATUS + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiRegisterForShadow ( + IN EFI_PEI_FILE_HANDLE FileHandle + ) +/*++ + +Routine Description: + + This routine enable a PEIM to register itself to shadow when PEI Foundation + discovery permanent memory. + +Arguments: + FileHandle - File handle of a PEIM. + +Returns: + EFI_NOT_FOUND - The file handle doesn't point to PEIM itself. + EFI_ALREADY_STARTED - Indicate that the PEIM has been registered itself. + EFI_SUCCESS - Successfully to register itself. + +--*/ +; + + /** This routine enable a PEIM to register itself to shadow when PEI Foundation discovery permanent memory. @@ -1221,4 +1360,60 @@ PeiSwitchStacks ( IN VOID *NewBsp ); +EFI_STATUS +PeiFindFileEx ( + IN CONST EFI_PEI_FV_HANDLE FvHandle, + IN CONST EFI_GUID *FileName, OPTIONAL + IN EFI_FV_FILETYPE SearchType, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle, + IN OUT EFI_PEI_FV_HANDLE *AprioriFile OPTIONAL + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + FileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + Flag - Indicator for if this is for PEI Dispath search + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +; + +VOID +InitializeImageServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Regitser PeCoffLoader to PeiCore PrivateData. And install + Pei Load File PPI. + +Arguments: + + PrivateData - Pointer to PEI_CORE_INSTANCE. + OldCoreData - Pointer to PEI_CORE_INSTANCE. + +Returns: + + NONE. + +--*/ +; + #endif diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf b/MdeModulePkg/Core/Pei/PeiMain.inf index b8e188d5fb..7701696850 100644 --- a/MdeModulePkg/Core/Pei/PeiMain.inf +++ b/MdeModulePkg/Core/Pei/PeiMain.inf @@ -80,16 +80,27 @@ BaseLib PeiCoreEntryPoint DebugLib + MemoryAllocationLib + CacheMaintenanceLib + PeCoffLoaderLib + PeCoffLib [Guids] - gEfiPeiCorePrivateGuid # PRIVATE + gPeiAprioriFileNameGuid + gEfiFirmwareFileSystem2Guid + [Ppis] gEfiPeiSecurityPpiGuid # PPI_NOTIFY SOMETIMES_CONSUMED gEfiPeiStatusCodePpiGuid # PPI SOMETIMES_CONSUMED gEfiPeiResetPpiGuid # PPI SOMETIMES_CONSUMED gEfiDxeIplPpiGuid # PPI ALWAYS_CONSUMED - gEfiPeiFvFileLoaderPpiGuid # PPI ALWAYS_CONSUMED - gEfiFindFvPpiGuid # PPI ALWAYS_CONSUMED gEfiPeiMemoryDiscoveredPpiGuid # PPI ALWAYS_PRODUCED + gEfiPeiDecompressPpiGuid + gEfiPeiFirmwareVolumeInfoPpiGuid + gEfiPeiLoadFilePpiGuid + gEfiPeiSecurity2PpiGuid + +[BuildOptions.common] + MSFT:DEBUG_*_IA32_CC_FLAGS = /FAcs diff --git a/MdeModulePkg/Core/Pei/PeiMain.msa b/MdeModulePkg/Core/Pei/PeiMain.msa index b8873a8ab6..31ebc45621 100644 --- a/MdeModulePkg/Core/Pei/PeiMain.msa +++ b/MdeModulePkg/Core/Pei/PeiMain.msa @@ -102,11 +102,6 @@ gEfiPeiSecurityPpiGuid - - - gEfiPeiCorePrivateGuid - - EFI_SPECIFICATION_VERSION 0x00020000 EDK_RELEASE_VERSION 0x00020000 diff --git a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c index 250c7cf504..f8eb92e128 100644 --- a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c +++ b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c @@ -61,20 +61,21 @@ static EFI_PEI_SERVICES mPS = { PeiFfsFindNextFile, PeiFfsFindSectionData, - PeiInstallPeiMemory, + PeiInstallPeiMemory, PeiAllocatePages, PeiAllocatePool, (EFI_PEI_COPY_MEM)CopyMem, (EFI_PEI_SET_MEM)SetMem, PeiReportStatusCode, - PeiResetSystem, + NULL, NULL, - NULL, - NULL, - NULL, + + PeiFfsFindFileByName, + PeiFfsGetFileInfo, + PeiFfsGetVolumeInfo, PeiRegisterForShadow }; @@ -82,7 +83,7 @@ EFI_STATUS EFIAPI PeiCore ( IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, - IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpList, IN VOID *Data ) /*++ @@ -117,9 +118,10 @@ Returns: PEI_CORE_INSTANCE PrivateData; EFI_STATUS Status; PEI_CORE_TEMP_POINTERS TempPtr; - PEI_CORE_DISPATCH_DATA *DispatchData; UINT64 mTick; PEI_CORE_INSTANCE *OldCoreData; + EFI_PEI_CPU_IO_PPI *CpuIo; + EFI_PEI_PCI_CFG2_PPI *PciCfg; mTick = 0; OldCoreData = (PEI_CORE_INSTANCE *) Data; @@ -138,26 +140,31 @@ Returns: if (OldCoreData != NULL) { CopyMem (&PrivateData, OldCoreData, sizeof (PEI_CORE_INSTANCE)); + + CpuIo = (VOID*)PrivateData.ServiceTableShadow.CpuIo; + PciCfg = (VOID*)PrivateData.ServiceTableShadow.PciCfg; + + CopyMem (&PrivateData.ServiceTableShadow, &mPS, sizeof (mPS)); + + PrivateData.ServiceTableShadow.CpuIo = CpuIo; + PrivateData.ServiceTableShadow.PciCfg = PciCfg; } else { ZeroMem (&PrivateData, sizeof (PEI_CORE_INSTANCE)); + PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE; + CopyMem (&PrivateData.ServiceTableShadow, &mPS, sizeof (mPS)); } - PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE; - PrivateData.PS = &mPS; + PrivateData.PS = &PrivateData.ServiceTableShadow; // // Initialize libraries that the PeiCore is linked against - // BUGBUG: The FfsHeader is passed in as NULL. Do we look it up or remove it from the lib init? + // BUGBUG: The FileHandle is passed in as NULL. Do we look it up or remove it from the lib init? // ProcessLibraryConstructorList (NULL, &PrivateData.PS); - InitializeMemoryServices (&PrivateData.PS, SecCoreData, OldCoreData); + InitializeMemoryServices (&PrivateData, SecCoreData, OldCoreData); - InitializePpiServices (&PrivateData.PS, OldCoreData); - - InitializeSecurityServices (&PrivateData.PS, OldCoreData); - - InitializeDispatcherData (&PrivateData.PS, OldCoreData, SecCoreData); + InitializePpiServices (&PrivateData, OldCoreData); if (OldCoreData != NULL) { @@ -219,18 +226,25 @@ Returns: // // If SEC provided any PPI services to PEI, install them. // - if (PpiList != NULL) { - Status = PeiServicesInstallPpi (PpiList); + if (PpList != NULL) { + Status = PeiServicesInstallPpi (PpList); ASSERT_EFI_ERROR (Status); } } - DispatchData = &PrivateData.DispatchData; + InitializeSecurityServices (&PrivateData.PS, OldCoreData); + + InitializeDispatcherData (&PrivateData, OldCoreData, SecCoreData); + + // + // Install Pei Load File PPI. + // + InitializeImageServices (&PrivateData, OldCoreData); // // Call PEIM dispatcher // - PeiDispatcher (SecCoreData, &PrivateData, DispatchData); + PeiDispatcher (SecCoreData, &PrivateData); // // Check if InstallPeiMemory service was called. diff --git a/MdeModulePkg/Core/Pei/Ppi/Ppi.c b/MdeModulePkg/Core/Pei/Ppi/Ppi.c index e429b665a2..2ee45c44f7 100644 --- a/MdeModulePkg/Core/Pei/Ppi/Ppi.c +++ b/MdeModulePkg/Core/Pei/Ppi/Ppi.c @@ -25,7 +25,7 @@ Revision History VOID InitializePpiServices ( - IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *PrivateData, IN PEI_CORE_INSTANCE *OldCoreData ) /*++ @@ -45,11 +45,7 @@ Returns: --*/ { - PEI_CORE_INSTANCE *PrivateData; - if (OldCoreData == NULL) { - PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); - PrivateData->PpiData.NotifyListEnd = MAX_PPI_DESCRIPTORS-1; PrivateData->PpiData.DispatchListEnd = MAX_PPI_DESCRIPTORS-1; PrivateData->PpiData.LastDispatchedNotify = MAX_PPI_DESCRIPTORS-1; @@ -220,7 +216,7 @@ Returns: // Dispatch any callback level notifies for newly installed PPIs. // DispatchNotify ( - (CONST EFI_PEI_SERVICES **) PeiServices, + PrivateData, EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, LastCallbackInstall, PrivateData->PpiData.PpiListEnd, @@ -298,7 +294,7 @@ Returns: // Dispatch any callback level notifies for the newly installed PPI. // DispatchNotify ( - (CONST EFI_PEI_SERVICES **) PeiServices, + PrivateData, EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, Index, Index+1, @@ -496,7 +492,7 @@ Returns: // Dispatch any callback level notifies for all previously installed PPIs. // DispatchNotify ( - (CONST EFI_PEI_SERVICES **) PeiServices, + PrivateData, EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, 0, PrivateData->PpiData.PpiListEnd, @@ -511,7 +507,7 @@ Returns: VOID ProcessNotifyList ( - IN EFI_PEI_SERVICES **PeiServices + IN PEI_CORE_INSTANCE *PrivateData ) /*++ @@ -528,11 +524,7 @@ Returns: --*/ { - PEI_CORE_INSTANCE *PrivateData; INTN TempValue; - - PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); - while (TRUE) { // @@ -545,7 +537,7 @@ Returns: while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) { TempValue = PrivateData->PpiData.DispatchListEnd; DispatchNotify ( - (CONST EFI_PEI_SERVICES **) PeiServices, + PrivateData, EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, 0, PrivateData->PpiData.LastDispatchedInstall, @@ -566,7 +558,7 @@ Returns: while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) { TempValue = PrivateData->PpiData.PpiListEnd; DispatchNotify ( - (CONST EFI_PEI_SERVICES **) PeiServices, + PrivateData, EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, PrivateData->PpiData.LastDispatchedInstall, PrivateData->PpiData.PpiListEnd, @@ -585,7 +577,7 @@ Returns: VOID DispatchNotify ( - IN CONST EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *PrivateData, IN UINTN NotifyType, IN INTN InstallStartIndex, IN INTN InstallStopIndex, @@ -612,15 +604,12 @@ Returns: None --*/ { - PEI_CORE_INSTANCE *PrivateData; INTN Index1; INTN Index2; EFI_GUID *SearchGuid; EFI_GUID *CheckGuid; EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor; - PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); - // // Remember that Installs moves up and Notifies moves down. // @@ -645,7 +634,7 @@ Returns: None NotifyDescriptor->Notify )); NotifyDescriptor->Notify ( - (EFI_PEI_SERVICES **)PeiServices, + GetPeiServicesTablePointer (), NotifyDescriptor, (PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi ); diff --git a/MdeModulePkg/Core/Pei/Reset/Reset.c b/MdeModulePkg/Core/Pei/Reset/Reset.c index ef0ceb3b19..2788a0e161 100644 --- a/MdeModulePkg/Core/Pei/Reset/Reset.c +++ b/MdeModulePkg/Core/Pei/Reset/Reset.c @@ -26,7 +26,7 @@ Revision History EFI_STATUS EFIAPI PeiResetSystem ( - IN EFI_PEI_SERVICES **PeiServices + IN CONST EFI_PEI_SERVICES **PeiServices ) /*++ diff --git a/MdeModulePkg/Core/Pei/Security/Security.c b/MdeModulePkg/Core/Pei/Security/Security.c index 089995e529..8fda8bd055 100644 --- a/MdeModulePkg/Core/Pei/Security/Security.c +++ b/MdeModulePkg/Core/Pei/Security/Security.c @@ -32,7 +32,7 @@ SecurityPpiNotifyCallback ( static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = { EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, - &gEfiPeiSecurityPpiGuid, + &gEfiPeiSecurity2PpiGuid, SecurityPpiNotifyCallback }; @@ -101,15 +101,16 @@ Returns: // If there isn't a security PPI installed, use the one from notification // if (PrivateData->PrivateSecurityPpi == NULL) { - PrivateData->PrivateSecurityPpi = (EFI_PEI_SECURITY_PPI *)Ppi; + PrivateData->PrivateSecurityPpi = (EFI_PEI_SECURITY2_PPI *)Ppi; } return EFI_SUCCESS; } EFI_STATUS VerifyPeim ( - IN EFI_PEI_SERVICES **PeiServices, - IN EFI_FFS_FILE_HEADER *CurrentPeimAddress + IN PEI_CORE_INSTANCE *PrivateData, + IN EFI_PEI_FV_HANDLE VolumeHandle, + IN EFI_PEI_FILE_HANDLE FileHandle ) /*++ @@ -129,21 +130,15 @@ Returns: --*/ { - PEI_CORE_INSTANCE *PrivateData; EFI_STATUS Status; UINT32 AuthenticationStatus; - BOOLEAN StartCrisisRecovery; + BOOLEAN DeferExection; // // Set a default authentication state // AuthenticationStatus = 0; - // - // get security PPI instance from PEI private data - // - PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); - if (PrivateData->PrivateSecurityPpi == NULL) { Status = EFI_NOT_FOUND; } else { @@ -151,13 +146,14 @@ Returns: // Check to see if the image is OK // Status = PrivateData->PrivateSecurityPpi->AuthenticationState ( - PeiServices, + (CONST EFI_PEI_SERVICES **) &PrivateData->PS, PrivateData->PrivateSecurityPpi, AuthenticationStatus, - CurrentPeimAddress, - &StartCrisisRecovery + VolumeHandle, + FileHandle, + &DeferExection ); - if (StartCrisisRecovery) { + if (DeferExection) { Status = EFI_SECURITY_VIOLATION; } } diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 752ed16694..7d9f5a871c 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -62,7 +62,6 @@ gEfiShellFileGuid = { 0xC57AD6B7, 0x0515, 0x40A8, { 0x9D, 0x21, 0x55, 0x16, 0x52, 0x85, 0x4E, 0x37 }} gEfiFlashMapHobGuid = { 0xB091E7D2, 0x05A0, 0x4198, { 0x94, 0xF0, 0x74, 0xB7, 0xB8, 0xC5, 0x54, 0x59 }} gEfiStandardErrorDeviceGuid = { 0xD3B36F2D, 0xD551, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} - gEfiPeiCorePrivateGuid = { 0xd641a0f5, 0xcb7c, 0x4846, { 0xa3, 0x80, 0x1d, 0x01, 0xb4, 0xd9, 0xe3, 0xb9 }} gEfiPeiPeCoffLoaderGuid = { 0xD8117CFF, 0x94A6, 0x11D4, { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index f86444fd69..ee3bc9803a 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -71,6 +71,8 @@ ReportStatusCodeLib|IntelFrameworkModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PeCoffLoaderLib|MdeModulePkg/Library/PeiDxePeCoffLoaderLib/PeCoffLoaderLib.inf + [LibraryClasses.common.PEIM] HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf diff --git a/MdePkg/Include/Library/HobLib.h b/MdePkg/Include/Library/HobLib.h index 0e1555de10..50e0d10676 100644 --- a/MdePkg/Include/Library/HobLib.h +++ b/MdePkg/Include/Library/HobLib.h @@ -262,6 +262,30 @@ BuildFvHob ( ) ; +/** + Builds a EFI_HOB_TYPE_FV2 HOB. + + This function builds a EFI_HOB_TYPE_FV2 HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param FvName The name of the Firmware Volume. + @param FileName The name of the file. + +**/ +VOID +EFIAPI +BuildFv2Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN CONST EFI_GUID *FvName, + IN CONST EFI_GUID *FileName + ) +; + /** Builds a Capsule Volume HOB. diff --git a/MdePkg/Include/Library/PeiPiLib.h b/MdePkg/Include/Library/PeiPiLib.h new file mode 100644 index 0000000000..a34fd50c10 --- /dev/null +++ b/MdePkg/Include/Library/PeiPiLib.h @@ -0,0 +1,30 @@ +/** @file + MDE PI library functions and macros for PEI phase + + Copyright (c) 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PEI_PI_LIB_H__ +#define __PEI_PI_LIB_H__ + +#include + +VOID +EFIAPI +PeiPiLibBuildPiFvInfoPpi ( + IN EFI_PHYSICAL_ADDRESS FvStart, + IN UINT64 FvLength, + IN EFI_GUID *ParentFvName, + IN EFI_GUID *PraentFileName +); + +#endif + diff --git a/MdePkg/Include/Library/PeiServicesLib.h b/MdePkg/Include/Library/PeiServicesLib.h index 3d0deb9ba4..2d028239d7 100644 --- a/MdePkg/Include/Library/PeiServicesLib.h +++ b/MdePkg/Include/Library/PeiServicesLib.h @@ -293,4 +293,35 @@ PeiServicesResetSystem ( ); +EFI_STATUS +EFIAPI +PeiServicesFfsFindByName ( + IN CONST EFI_GUID *FileName, + IN CONST EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + + +EFI_STATUS +EFIAPI +PeiServicesFfsGetFileInfo ( + IN CONST EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ); + +EFI_STATUS +EFIAPI +PeiServicesFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ); + + +EFI_STATUS +EFIAPI +PeiServicesRegisterForShadow ( + IN EFI_PEI_FILE_HANDLE FileHandle + ); + + #endif diff --git a/MdePkg/Include/Library/PeiServicesTablePointerLib.h b/MdePkg/Include/Library/PeiServicesTablePointerLib.h index ede0337730..7a602f9041 100644 --- a/MdePkg/Include/Library/PeiServicesTablePointerLib.h +++ b/MdePkg/Include/Library/PeiServicesTablePointerLib.h @@ -30,5 +30,11 @@ GetPeiServicesTablePointer ( VOID ); +VOID +EFIAPI +SetPeiServicesTablePointer ( + EFI_PEI_SERVICES ** PeiServicesTablePointer + ); + #endif diff --git a/MdePkg/Include/Library/PiLib.h b/MdePkg/Include/Library/PiLib.h index d15a712678..8aaad25058 100644 --- a/MdePkg/Include/Library/PiLib.h +++ b/MdePkg/Include/Library/PiLib.h @@ -75,6 +75,233 @@ GetSectionFromFvFile ( ) ; +/** + Identify the device handle from which the Image is loaded from. As this device handle is passed to + GetSectionFromFv as the identifier for a Firmware Volume, an EFI_FIRMWARE_VOLUME2_PROTOCOL + protocol instance should be located succesfully by calling gBS->HandleProtocol (). + + This function locates the EFI_LOADED_IMAGE_PROTOCOL instance installed + on ImageHandle. It then returns EFI_LOADED_IMAGE_PROTOCOL.DeviceHandle. + + If ImageHandle is NULL, then ASSERT (); + If failed to locate a EFI_LOADED_IMAGE_PROTOCOL on ImageHandle, then ASSERT (); + + @param ImageHandle The firmware allocated handle for UEFI image. + + @retval EFI_HANDLE The device handle from which the Image is loaded from. + +**/ + +EFI_HANDLE +EFIAPI +ImageHandleToFvHandle ( + EFI_HANDLE ImageHandle + ) +; + +/** + Allocate and fill a buffer from the Firmware Section identified by a Firmware File GUID name and a Firmware + Section type and instance number from the any Firmware Volumes in the system. + + The function will read the first Firmware Section found sepcifed by NameGuid and SectionType from the + any Firmware Volume in the system. + + The search order for Firmware Volumes in the system is determistic but abitrary if no new Firmware Volume is installed + into the system. The search order for the section specified by SectionType within a Firmware File is defined by + EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection (). Please check Section 2.4 of Volume 3: Platform Initialization + Shared Architectural Elements for detailes. + + If SectionType is EFI_SECTION_TE, EFI_SECTION_TE will be used as Firmware Section type to read Firmware Section + data from the Firmware File. If no such section exists, EFI_SECTION_PE32 will be used as Firmware Section type to + read Firmware Section data from the Firmware File. If no such section specified is found to match , + EFI_NOT_FOUND is returned. + + The data and size is returned by Buffer and Size. The caller is responsible to free the Buffer allocated + by this function. This function can only be called at TPL_NOTIFY and below. + + If NameGuid is NULL, then ASSERT(); + If Buffer is NULL, then ASSERT(); + If Size is NULL, then ASSERT(). + + @param NameGuid The GUID name of a Firmware File. + @param SectionType The Firmware Section type. + @param Instance The instance number of Firmware Section to read from starting from 0. + @param Buffer On output, Buffer contains the the data read from the section in the Firmware File found. + @param Size On output, the size of Buffer. + + @retval EFI_SUCCESS The image is found and data and size is returned. + @retval EFI_NOT_FOUND The image specified by NameGuid and SectionType can't be found. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the output data buffer or complete the operations. + @retval EFI_DEVICE_ERROR A hardware error occurs during reading from the Firmware Volume. + @retval EFI_ACCESS_DENIED The firmware volume containing the searched Firmware File is configured to disallow reads. + + **/ + +EFI_STATUS +EFIAPI +GetSectionFromAnyFv ( + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT VOID **Buffer, + OUT UINTN *Size + ) +; + +/** + Allocate and fill a buffer from a Firmware Section identified by a Firmware File GUID name, a Firmware + Section type and instance number from the specified Firmware Volume. + + This functions first locate the EFI_FIRMWARE_VOLUME2_PROTOCOL protocol instance on FvHandle in order to + carry out the Firmware Volume read operation. The function then reads the Firmware Section found sepcifed + by NameGuid, SectionType and Instance. + + The search order for the section specified by SectionType within a Firmware File is defined by + EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection (). Please check Section 2.4 of Volume 3: Platform Initialization + Shared Architectural Elements for detailes. + + If SectionType is EFI_SECTION_TE, EFI_SECTION_TE will be used as Firmware Section type to read Firmware Section + data from the Firmware File. If no such section exists, EFI_SECTION_PE32 will be used as Firmware Section type to + read Firmware Section data from the Firmware File. If no such section specified is found to match , + EFI_NOT_FOUND is returned. + + The data and size is returned by Buffer and Size. The caller is responsible to free the Buffer allocated + by this function. This function can be only called at TPL_NOTIFY and below. + + If FvHandle is NULL, then ASSERT (); + If NameGuid is NULL, then ASSERT(); + If Buffer is NULL, then ASSERT(); + If Size is NULL, then ASSERT(). + + @param FvHandle The device handle that contains a instance of EFI_FIRMWARE_VOLUME2_PROTOCOL instance. + @param NameGuid The GUID name of a Firmware File. + @param SectionType The Firmware Section type. + @param Instance The instance number of Firmware Section to read from starting from 0. + @param Buffer On output, Buffer contains the the data read from the section in the Firmware File found. + @param Size On output, the size of Buffer. + + @retval EFI_SUCCESS The image is found and data and size is returned. + @retval EFI_UNSUPPORTED FvHandle does not support EFI_FIRMWARE_VOLUME2_PROTOCOL. + @retval EFI_NOT_FOUND The image specified by NameGuid and SectionType can't be found. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the output data buffer or complete the operations. + @retval EFI_DEVICE_ERROR A hardware error occurs during reading from the Firmware Volume. + @retval EFI_ACCESS_DENIED The firmware volume containing the searched Firmware File is configured to disallow reads. + + **/ + +EFI_STATUS +EFIAPI +GetSectionFromFv ( + IN EFI_HANDLE FvHandle, + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT VOID **Buffer, + OUT UINTN *Size + ) +; + +/** + Allocate and fill a buffer from a Firmware Section identified by a Firmware File GUID name, a Firmware + Section type and instance number from the same Firmware Volume with the caller's FFS. + + This functions first locates the EFI_FIRMWARE_VOLUME2_PROTOCOL protocol instance for same Firmrware Volume + which also contains the FFS of the caller in order to carry out the Firmware Volume read operation. + The function then reads the Firmware Section found sepcifed by NameGuid, SectionType and Instance. + + The search order for the section specified by SectionType within a Firmware File is defined by + EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection (). Please check Section 2.4 of Volume 3: Platform Initialization + Shared Architectural Elements for detailes. + + If SectionType is EFI_SECTION_TE, EFI_SECTION_TE will be used as Firmware Section type to read Firmware Section + data from the Firmware File. If no such section exists, EFI_SECTION_PE32 will be used as Firmware Section type to + read Firmware Section data from the Firmware File. If no such section specified is found to match , + EFI_NOT_FOUND is returned. + + The data and size is returned by Buffer and Size. The caller is responsible to free the Buffer allocated + by this function. This function can be only called at TPL_NOTIFY and below. + + If FvHandle is NULL, then ASSERT (); + If NameGuid is NULL, then ASSERT(); + If Buffer is NULL, then ASSERT(); + If Size is NULL, then ASSERT(). + + @param NameGuid The GUID name of a Firmware File. + @param SectionType The Firmware Section type. + @param Instance The instance number of Firmware Section to read from starting from 0. + @param Buffer On output, Buffer contains the the data read from the section in the Firmware File found. + @param Size On output, the size of Buffer. + + @retval EFI_SUCCESS The image is found and data and size is returned. + @retval EFI_UNSUPPORTED FvHandle does not support EFI_FIRMWARE_VOLUME2_PROTOCOL. + @retval EFI_NOT_FOUND The image specified by NameGuid and SectionType can't be found. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the output data buffer or complete the operations. + @retval EFI_DEVICE_ERROR A hardware error occurs during reading from the Firmware Volume. + @retval EFI_ACCESS_DENIED The firmware volume containing the searched Firmware File is configured to disallow reads. + + **/ + +EFI_STATUS +EFIAPI +GetSectionFromCurrentFv ( + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT VOID **Buffer, + OUT UINTN *Size + ) +; + + +/** + Allocate and fill a buffer from the first Firmware Section in the same Firmware File as the caller of this function. + + The function will read the first Firmware Section found sepcifed by NameGuid and SectionType from the + Firmware Volume specified by FvHandle. On this FvHandle, an EFI_FIRMWARE_VOLUME2_PROTOCOL protocol instance + should be located succesfully in order to carry out the Firmware Volume operations. + + The search order for the section type specified by SectionType in the Firmware File is using a depth-first + and left-to-right algorithm through all sections. The first section found to match SectionType will be returned. + + If SectionType is EFI_SECTION_PE32, EFI_SECTION_PE32 will be used as Firmware Section type + to read Firmware Section data from the Firmware File. If no such section exists, the function will try + to read a Firmware File named with NameGuid. If no such file exists, EFI_NOT_FOUND is returned. + + If SectionType is EFI_SECTION_TE, EFI_SECTION_TE will be used as Firmware Section type to read Firmware Section + data from the Firmware File. If no such section exists, EFI_SECTION_PE32 will be used as Firmware Section type to + read Firmware Section data from the Firmware File. If no such section exists, the function will try to read a Firmware + File named with NameGuid. If no such file exists, EFI_NOT_FOUND is returned. + + The data and size is returned by Buffer and Size. The caller is responsible to free the Buffer allocated + by this function. This function can only be called at TPL_NOTIFY and below. + + If FvHandle is NULL and WithinImage is TRUE, then ASSERT (); + If NameGuid is NULL, then ASSERT(); + If Buffer is NULL, then ASSERT(); + If Size is NULL, then ASSERT(). + + @param NameGuid The GUID name of a Firmware File. + @param SectionType The Firmware Section type. + @param Buffer On output, Buffer contains the the data read from the section in the Firmware File found. + @param Size On output, the size of Buffer. + + @retval EFI_SUCCESS The image is found and data and size is returned. + @retval EFI_NOT_FOUND The image specified by NameGuid and SectionType can't be found. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the output data buffer or complete the operations. + @retval EFI_DEVICE_ERROR A hardware error occurs during reading from the Firmware Volume. + @retval EFI_ACCESS_DENIED The firmware volume containing the searched Firmware File is configured to disallow reads. + + **/ + +EFI_STATUS +EFIAPI +GetSectionFromCurrentFfs ( + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT VOID **Buffer, + OUT UINTN *Size + ) +; #endif diff --git a/MdePkg/Include/Pi/PiPeiCis.h b/MdePkg/Include/Pi/PiPeiCis.h index 4d95c7fbd8..d75a79c6b7 100644 --- a/MdePkg/Include/Pi/PiPeiCis.h +++ b/MdePkg/Include/Pi/PiPeiCis.h @@ -51,8 +51,8 @@ typedef struct _EFI_PEI_NOTIFY_DESCRIPTOR EFI_PEI_NOTIFY_DESCRIPTOR; typedef EFI_STATUS (EFIAPI *EFI_PEIM_ENTRY_POINT2)( - IN EFI_PEI_FILE_HANDLE *FileHandle, - IN EFI_PEI_SERVICES **PeiServices + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices ); /** @@ -491,7 +491,7 @@ EFI_STATUS typedef EFI_STATUS (EFIAPI *EFI_PEI_RESET_SYSTEM) ( - IN EFI_PEI_SERVICES **PeiServices + IN CONST EFI_PEI_SERVICES **PeiServices ); /** diff --git a/MdePkg/Library/DxePiLib/DxePiLib.c b/MdePkg/Library/DxePiLib/DxePiLib.c index 3261e08ade..32e0337c19 100644 --- a/MdePkg/Library/DxePiLib/DxePiLib.c +++ b/MdePkg/Library/DxePiLib/DxePiLib.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -40,7 +41,7 @@ **/ STATIC EFI_STATUS -GetImageFromFv ( +InternalGetImageFromFv ( IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv, IN CONST EFI_GUID *NameGuid, IN EFI_SECTION_TYPE SectionType, @@ -193,7 +194,7 @@ GetSectionFromFvFile ( (VOID **) &ImageFv ); if (!EFI_ERROR (Status)) { - Status = GetImageFromFv (ImageFv, NameGuid, SectionType, Buffer, Size); + Status = InternalGetImageFromFv (ImageFv, NameGuid, SectionType, Buffer, Size); } } @@ -231,7 +232,7 @@ GetSectionFromFvFile ( continue; } - Status = GetImageFromFv (Fv, NameGuid, SectionType, Buffer, Size); + Status = InternalGetImageFromFv (Fv, NameGuid, SectionType, Buffer, Size); if (!EFI_ERROR (Status)) { goto Done; @@ -254,3 +255,216 @@ Done: return Status; } +EFI_HANDLE +EFIAPI +ImageHandleToFvHandle ( + EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + + ASSERT (ImageHandle != NULL); + + Status = gBS->HandleProtocol ( + (EFI_HANDLE *) ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + + ASSERT_EFI_ERROR (Status); + + return LoadedImage->DeviceHandle; + +} + +EFI_STATUS +EFIAPI +GetSectionFromAnyFv ( + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT VOID **Buffer, + OUT UINTN *Size + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + EFI_HANDLE FvHandle; + EFI_TPL OldTpl; + + // + // Search the FV that contain the caller's FFS first. + // FV builder can choose to build FFS into the this FV + // so that this implementation of GetSectionFromAnyFv + // will locate the FFS faster. + // + FvHandle = ImageHandleToFvHandle (gImageHandle); + Status = GetSectionFromFv ( + FvHandle, + NameGuid, + SectionType, + Instance, + Buffer, + Size + ); + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + HandleBuffer = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + for (Index = 0; Index < HandleCount; ++Index) { + // + // Skip the FV that contain the caller's FFS + // + if (HandleBuffer[Index] == FvHandle) { + continue; + } + + Status = GetSectionFromFv ( + HandleBuffer[Index], + NameGuid, + SectionType, + Instance, + Buffer, + Size + ); + + if (!EFI_ERROR (Status)) { + goto Done; + } + } + + if (Index == HandleCount) { + Status = EFI_NOT_FOUND; + } + +Done: + + gBS->RestoreTPL (OldTpl); + + if (HandleBuffer != NULL) { + FreePool(HandleBuffer); + } + return Status; + +} + +EFI_STATUS +EFIAPI +GetSectionFromFv ( + IN EFI_HANDLE FvHandle, + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT VOID **Buffer, + OUT UINTN *Size + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + UINT32 AuthenticationStatus; + + ASSERT (FvHandle != NULL); + + Status = gBS->HandleProtocol ( + FvHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Read desired section content in NameGuid file + // + *Buffer = NULL; + *Size = 0; + Status = Fv->ReadSection ( + Fv, + NameGuid, + SectionType, + 0, + Buffer, + Size, + &AuthenticationStatus + ); + + if (EFI_ERROR (Status) && (SectionType == EFI_SECTION_TE)) { + // + // Try reading PE32 section, if the required section is TE type + // + *Buffer = NULL; + *Size = 0; + Status = Fv->ReadSection ( + Fv, + NameGuid, + EFI_SECTION_PE32, + 0, + Buffer, + Size, + &AuthenticationStatus + ); + } + + return Status; +} + + +EFI_STATUS +EFIAPI +GetSectionFromCurrentFv ( + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT VOID **Buffer, + OUT UINTN *Size + ) +{ + return GetSectionFromFv( + ImageHandleToFvHandle(gImageHandle), + NameGuid, + SectionType, + Instance, + Buffer, + Size + ); +} + + + +EFI_STATUS +EFIAPI +GetSectionFromCurrentFfs ( + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT VOID **Buffer, + OUT UINTN *Size + ) +{ + return GetSectionFromFv( + ImageHandleToFvHandle(gImageHandle), + &gEfiCallerIdGuid, + SectionType, + Instance, + Buffer, + Size + ); +} + diff --git a/MdePkg/Library/PeiPiLib/PeiPiLib.c b/MdePkg/Library/PeiPiLib/PeiPiLib.c new file mode 100644 index 0000000000..49894dfe4d --- /dev/null +++ b/MdePkg/Library/PeiPiLib/PeiPiLib.c @@ -0,0 +1,67 @@ +/** @file + MDE PI library functions and macros for PEI phase + + Copyright (c) 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include + + +#include +#include +#include +#include + + +STATIC CONST EFI_PEI_FIRMWARE_VOLUME_INFO_PPI mFvInfoPpiTemplate = { + EFI_FIRMWARE_FILE_SYSTEM2_GUID, + NULL, + 0, //FvInfoSize + NULL, //ParentFvName + NULL //ParentFileName; +}; + +VOID +EFIAPI +PeiPiLibBuildPiFvInfoPpi ( + IN EFI_PHYSICAL_ADDRESS FvStart, + IN UINT64 FvLength, + IN EFI_GUID *ParentFvName, + IN EFI_GUID *ParentFileName + ) { + + EFI_STATUS Status; + EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FvInfoPpi; + EFI_PEI_PPI_DESCRIPTOR *FvInfoPpiDescriptor; + + FvInfoPpi = AllocateCopyPool (sizeof (*FvInfoPpi), &mFvInfoPpiTemplate); + ASSERT( FvInfoPpi != NULL); + + FvInfoPpi->FvInfo = (VOID *) (UINTN) FvStart; + FvInfoPpi->FvInfoSize = (UINT32) FvLength; + FvInfoPpi->ParentFvName = ParentFvName; + FvInfoPpi->ParentFileName = ParentFileName; + + + FvInfoPpiDescriptor = AllocatePool (sizeof(EFI_PEI_PPI_DESCRIPTOR)); + ASSERT (FvInfoPpiDescriptor != NULL); + + FvInfoPpiDescriptor->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + FvInfoPpiDescriptor->Guid = &gEfiPeiFirmwareVolumeInfoPpiGuid; + FvInfoPpiDescriptor->Ppi = (VOID *) FvInfoPpi; + Status = PeiServicesInstallPpi (FvInfoPpiDescriptor); + ASSERT_EFI_ERROR (Status); + + +} + diff --git a/MdePkg/Library/PeiPiLib/PeiPiLib.inf b/MdePkg/Library/PeiPiLib/PeiPiLib.inf new file mode 100644 index 0000000000..61e90612eb --- /dev/null +++ b/MdePkg/Library/PeiPiLib/PeiPiLib.inf @@ -0,0 +1,50 @@ +#/** @file +# Component description file library instance for PiLib for PEI phase. +# +# Library to abstract utility functions that is related to PI Specification. +# +# Copyright (c) 2007, Intel Corporation. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiPiLib + FILE_GUID = 6196FE81-4FA4-469a-B759-2C4DFE935B79 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = PiLib|PEIM + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + PeiPiLib.c + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + MemoryAllocationLib + DebugLib + +[Guids] + +[Ppis] + gEfiPeiFirmwareVolumeInfoPpiGuid + + + diff --git a/MdePkg/Library/PeiServicesLib/PeiServicesLib.c b/MdePkg/Library/PeiServicesLib/PeiServicesLib.c index c5b12be721..29aaaaa235 100644 --- a/MdePkg/Library/PeiServicesLib/PeiServicesLib.c +++ b/MdePkg/Library/PeiServicesLib/PeiServicesLib.c @@ -379,9 +379,58 @@ EFIAPI PeiServicesResetSystem ( VOID ) +{ + CONST EFI_PEI_SERVICES **PeiServices; + + PeiServices = (CONST EFI_PEI_SERVICES **) GetPeiServicesTablePointer (); + return (*PeiServices)->ResetSystem (PeiServices); +} + +EFI_STATUS +EFIAPI +PeiServicesRegisterForShadow ( + IN EFI_PEI_FILE_HANDLE FileHandle + ) { EFI_PEI_SERVICES **PeiServices; PeiServices = GetPeiServicesTablePointer (); - return (*PeiServices)->ResetSystem (PeiServices); + return (*PeiServices)->RegisterForShadow (FileHandle); } + +EFI_STATUS +EFIAPI +PeiServicesFfsGetFileInfo ( + IN CONST EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->FfsGetFileInfo (FileHandle, FileInfo); +} + + +EFI_STATUS +EFIAPI +PeiServicesFfsFindFileByName ( + IN CONST EFI_GUID *FileName, + IN CONST EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +{ + return (*GetPeiServicesTablePointer())->FfsFindFileByName (FileName, VolumeHandle, FileHandle); +} + + +EFI_STATUS +EFIAPI +PeiServicesFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ) +{ + return (*GetPeiServicesTablePointer())->FfsGetVolumeInfo (VolumeHandle, VolumeInfo); +} + diff --git a/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointer.c b/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointer.c index 49c233ce73..54a500a732 100644 --- a/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointer.c +++ b/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointer.c @@ -20,6 +20,15 @@ static EFI_PEI_SERVICES **gPeiServices; +VOID +EFIAPI +SetPeiServicesTablePointer ( + EFI_PEI_SERVICES **PeiServices + ) +{ + gPeiServices = PeiServices; +} + /** The function returns the pointer to PEI services. diff --git a/MdePkg/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointer.c b/MdePkg/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointer.c index d26a0be939..4c439ebd5f 100644 --- a/MdePkg/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointer.c +++ b/MdePkg/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointer.c @@ -22,6 +22,15 @@ #include #include +VOID +EFIAPI +SetPeiServicesTablePointer ( + IN EFI_PEI_SERVICES **PeiServices + ) +{ + AsmWriteMm7 ((UINT64)(UINTN)PeiServices); +} + /** The function returns the pointer to PeiServices. diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc index c7c8d97715..4f0e19dd6d 100644 --- a/MdePkg/MdePkg.dsc +++ b/MdePkg/MdePkg.dsc @@ -82,6 +82,7 @@ MdePkg/Library/PeiMemoryLib/PeiMemoryLib.inf MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + MdePkg/Library/PeiPiLib/PeiPiLib.inf MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf MdePkg/Library/PeiServicesLib/PeiServicesLib.inf MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf diff --git a/Nt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoader.c b/Nt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoader.c index 8eaa2aba43..3d5353b423 100644 --- a/Nt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoader.c +++ b/Nt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoader.c @@ -21,35 +21,30 @@ Abstract: --*/ #include +#include #include -#include +#include +#include -EFI_PEI_PE_COFF_LOADER_PROTOCOL *mPeiEfiPeiPeCoffLoader; +EFI_PEI_PE_COFF_LOADER_PROTOCOL *mPeiEfiPeiPeCoffLoader = NULL; -EFI_STATUS -EFIAPI -PeCoffLoaderConstructor ( - IN EFI_FFS_FILE_HEADER *FfsHeader, - IN EFI_PEI_SERVICES **PeiServices - ) -{ - EFI_STATUS Status; - - Status = (*PeiServices)->LocatePpi ( - PeiServices, - &gEfiPeiPeCoffLoaderGuid, - 0, - NULL, - &mPeiEfiPeiPeCoffLoader - ); - return Status; -} EFI_PEI_PE_COFF_LOADER_PROTOCOL * EFIAPI GetPeCoffLoaderProtocol ( ) { + EFI_STATUS Status; + + if (mPeiEfiPeiPeCoffLoader == NULL) { + Status = PeiServicesLocatePpi( + &gEfiPeiPeCoffLoaderGuid, + 0, + NULL, + (VOID **) &mPeiEfiPeiPeCoffLoader + ); + ASSERT_EFI_ERROR (Status); + } return mPeiEfiPeiPeCoffLoader; } diff --git a/Nt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.inf b/Nt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.inf index 04a0102919..d6a57b22b0 100644 --- a/Nt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.inf +++ b/Nt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.inf @@ -24,8 +24,6 @@ EDK_RELEASE_VERSION = 0x00020000 EFI_SPECIFICATION_VERSION = 0x00020000 - CONSTRUCTOR = PeCoffLoaderConstructor - # # The following information is for reference only and not required by the build tools. # diff --git a/Nt32Pkg/Nt32Pkg.dsc b/Nt32Pkg/Nt32Pkg.dsc index 01a725a8d8..98ed118f8b 100644 --- a/Nt32Pkg/Nt32Pkg.dsc +++ b/Nt32Pkg/Nt32Pkg.dsc @@ -145,6 +145,7 @@ PeCoffGetEntryPointLib|Nt32Pkg/Library/Nt32PeiPeCoffGetEntryPointLib/Nt32PeiPeCoffGetEntryPointLib.inf PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf DebugLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + PeCoffLoaderLib|Nt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.inf [LibraryClasses.common.DXE_RUNTIME_DRIVER] UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf -- 2.39.2