diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h index e82cf38db2..bd7e905099 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h @@ -54,7 +54,6 @@ Abstract: #include #include #include -#include #define STACK_SIZE 0x20000 #define BSP_STORE_SIZE 0x4000 @@ -73,16 +72,7 @@ PeiLoadFile ( ; EFI_STATUS -DxeIplAddEncapsulatedFirmwareVolumes ( - VOID - ) -; - -EFI_STATUS -DxeIplFindFirmwareVolumeInstance ( - IN OUT UINTN *Instance, - IN EFI_FV_FILETYPE SeachType, - OUT EFI_PEI_FV_HANDLE *VolumeHandle, +DxeIplFindDxeCore ( OUT EFI_PEI_FILE_HANDLE *FileHandle ) ; diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf index 898e67ed5a..b9b4b32aeb 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf @@ -78,13 +78,7 @@ DebugLib S3Lib RecoveryLib - PeiPiLib - -[Protocols] - gEfiCustomizedDecompressProtocolGuid # PROTOCOL SOMETIMES_PRODUCED - gEfiTianoDecompressProtocolGuid # PROTOCOL SOMETIMES_PRODUCED - gEfiDecompressProtocolGuid # PROTOCOL SOMETIMES_PRODUCED - + PerformanceLib [Ppis] gEfiPeiSecurityPpiGuid # PPI SOMETIMES_CONSUMED diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c index b7cadedd89..65d0e86d75 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c +++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c @@ -135,11 +135,11 @@ PeimInitializeDxeIpl ( } // - // Install FvFileLoader and DxeIpl PPIs. + // Install DxeIpl and Decompress PPIs. // Status = PeiServicesInstallPpi (mPpiList); - ASSERT_EFI_ERROR(Status); - + ASSERT_EFI_ERROR(Status); + return Status; } @@ -167,9 +167,7 @@ DxeLoadCore ( UINT64 DxeCoreSize; EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint; EFI_BOOT_MODE BootMode; - EFI_PEI_FV_HANDLE VolumeHandle; EFI_PEI_FILE_HANDLE FileHandle; - UINTN Instance; EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable; UINTN DataSize; EFI_MEMORY_TYPE_INFORMATION MemoryData [EfiMaxMemoryType + 1]; @@ -194,7 +192,7 @@ DxeLoadCore ( // Now should have a HOB with the DXE core w/ the old HOB destroyed // } - + Status = PeiServicesLocatePpi ( &gEfiPeiReadOnlyVariable2PpiGuid, 0, @@ -223,16 +221,12 @@ DxeLoadCore ( DataSize ); } - // - // If any FV contains an encapsulated FV extract that FV - // - DxeIplAddEncapsulatedFirmwareVolumes (); - + // // Look in all the FVs present in PEI and find the DXE Core // - Instance = 0; - Status = DxeIplFindFirmwareVolumeInstance (&Instance, EFI_FV_FILETYPE_DXE_CORE, &VolumeHandle, &FileHandle); + FileHandle = NULL; + Status = DxeIplFindDxeCore (&FileHandle); ASSERT_EFI_ERROR (Status); CopyMem(&DxeCoreFileName, &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name), sizeof (EFI_GUID)); @@ -297,171 +291,38 @@ DxeLoadCore ( return EFI_OUT_OF_RESOURCES; } - -STATIC -EFI_STATUS -GetFvAlignment ( - IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader, - OUT UINT32 *FvAlignment - ) -{ - // - // 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; -} - /** - 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; + Find DxeCore driver from all First Volumes. - Status = EFI_NOT_FOUND; - Index = 0; - - 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; - } - - // - // This new Firmware Volume comes from a firmware file within a firmware volume. - // Record the original Firmware Volume Name. - // - PeiServicesFfsGetVolumeInfo (&VolumeHandle, &VolumeInfo); - - PiLibInstallFvInfoPpi ( - NULL, - FvHeader, - (UINT32) FvHeader->FvLength, - &(VolumeInfo.FvName), - &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name) - ); - - // - // Inform HOB consumer phase, i.e. DXE core, the existance of this FV - // - BuildFvHob ( - (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, - FvHeader->FvLength - ); - - ASSERT_EFI_ERROR (Status); - - // - // 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, +DxeIplFindDxeCore ( OUT EFI_PEI_FILE_HANDLE *FileHandle ) { - EFI_STATUS Status; - EFI_STATUS VolumeStatus; + EFI_STATUS Status; + EFI_STATUS FileStatus; + UINTN Instance; + EFI_PEI_FV_HANDLE VolumeHandle; + + Instance = 0; + *FileHandle = NULL; do { - VolumeStatus = PeiServicesFfsFindNextVolume (*Instance, VolumeHandle); - if (!EFI_ERROR (VolumeStatus)) { - *FileHandle = NULL; - Status = PeiServicesFfsFindNextFile (SeachType, *VolumeHandle, FileHandle); - if (!EFI_ERROR (Status)) { - return Status; + Status = PeiServicesFfsFindNextVolume (Instance++, &VolumeHandle); + if (!EFI_ERROR (Status)) { + FileStatus = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, FileHandle); + if (!EFI_ERROR (FileStatus)) { + return FileStatus; } } - *Instance += 1; - } while (!EFI_ERROR (VolumeStatus)); + } while (!EFI_ERROR (Status)); - return VolumeStatus; + return EFI_NOT_FOUND; } /** @@ -646,10 +507,16 @@ CustomGuidedSectionExtract ( // // Allocate output buffer // - *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize)); + *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1); if (*OutputBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } + DEBUG ((EFI_D_INFO, "Customed Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer)); + // + // *OutputBuffer still is one section. Adjust *OutputBuffer offset, + // skip EFI section header to make section data at page alignment. + // + *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER)); } Status = ExtractGuidedSectionDecode ( @@ -728,13 +595,18 @@ Decompress ( return EFI_OUT_OF_RESOURCES; } // - // Allocate destination buffer + // Allocate destination buffer, extra one page for adjustment // - DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize)); + DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1); if (DstBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } // + // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header + // to make section data at page alignment. + // + DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER); + // // Call decompress function // Status = UefiDecompress ( @@ -751,18 +623,21 @@ Decompress ( } 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)); + DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1); if (DstBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } // + // Adjust DstBuffer offset, skip EFI section header + // to make section data at page alignment. + // + DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER); + // // stream is not actually compressed, just encapsulated. So just copy it. // CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize); diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c index 164c2c8746..5a140ed7bd 100644 --- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c +++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c @@ -30,7 +30,6 @@ InvokePeiCore ( VOID *Context2 ); - VOID DiscoverPeimsAndOrderWithApriori ( IN PEI_CORE_INSTANCE *Private, @@ -233,11 +232,13 @@ Returns: VOID *TopOfStack; PEI_CORE_PARAMETERS PeiCoreParameters; EFI_DEVICE_HANDLE_EXTENDED_DATA ExtendedData; + EFI_FV_FILE_INFO FvFileInfo; PeiServices = &Private->PS; PeimEntryPoint = NULL; PeimFileHandle = NULL; + EntryPoint = 0; if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) { // @@ -327,16 +328,28 @@ Returns: if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) { PeimNeedingDispatch = TRUE; } else { - Status = PeiLoadImage ( - PeiServices, - PeimFileHandle, - &EntryPoint, - &AuthenticationState - ); + Status = PeiFfsGetFileInfo (PeimFileHandle, &FvFileInfo); + ASSERT_EFI_ERROR (Status); + if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) { + // + // For Fv type file, Produce new FV PPI and FV hob + // + Status = ProcessFvFile (PeiServices, PeimFileHandle, &AuthenticationState); + } else { + // + // For PEIM driver, Load its entry point + // + Status = PeiLoadImage ( + PeiServices, + PeimFileHandle, + &EntryPoint, + &AuthenticationState + ); + } + if ((Status == EFI_SUCCESS)) { // - // The PEIM has its dependencies satisfied, and its entry point - // has been found, so invoke it. + // The PEIM has its dependencies satisfied, and is processed. // PERF_START (0, "PEIM", NULL, 0); @@ -355,12 +368,17 @@ Returns: // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED // Private->Fv[FvCount].PeimState[PeimCount]++; - + + if (FvFileInfo.FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) { + // + // Call the PEIM entry point for PEIM driver + // + PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint; + PeimEntryPoint (PeimFileHandle, PeiServices); + } // - // Call the PEIM entry point + // One module has been dispatched. // - PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint; - PeimEntryPoint (PeimFileHandle, PeiServices); PeimDispatchOnThisPass = TRUE; } @@ -572,8 +590,8 @@ Returns: --*/ { - EFI_STATUS Status; - VOID *DepexData; + EFI_STATUS Status; + VOID *DepexData; if (PeimCount < Private->AprioriCount) { // @@ -581,8 +599,16 @@ Returns: // return TRUE; } + + // + // Depex section not in the encapsulated section. + // + Status = PeiServicesFfsFindSectionData ( + EFI_SECTION_PEI_DEPEX, + FileHandle, + (VOID **)&DepexData + ); - Status = PeiServicesFfsFindSectionData (EFI_SECTION_PEI_DEPEX, FileHandle, (VOID **) &DepexData); if (EFI_ERROR (Status)) { // // If there is no DEPEX, assume the module can be executed @@ -675,3 +701,119 @@ InvokePeiCore ( ASSERT (FALSE); CpuDeadLoop (); } + +/** + Get Fv image from the FV type file, then install FV INFO ppi, Build FV hob. + + @param PeiServices Pointer to the PEI Core Services Table. + @param FileHandle File handle of a Fv type file. + @param AuthenticationState Pointer to attestation authentication state of image. + + + @retval EFI_NOT_FOUND FV image can't be found. + @retval EFI_SUCCESS Successfully to process it. + +**/ +EFI_STATUS +ProcessFvFile ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FvFileHandle, + OUT UINT32 *AuthenticationState + ) +{ + EFI_STATUS Status; + EFI_PEI_FV_HANDLE FvImageHandle; + EFI_FV_INFO FvImageInfo; + UINT32 FvAlignment; + VOID *FvBuffer; + EFI_PEI_HOB_POINTERS HobFv2; + + FvBuffer = NULL; + *AuthenticationState = 0; + + // + // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already + // been extracted. + // + HobFv2.Raw = GetHobList (); + while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) { + if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name), &HobFv2.FirmwareVolume2->FileName)) { + // + // this FILE has been dispatched, it will not be dispatched again. + // + return EFI_SUCCESS; + } + HobFv2.Raw = GET_NEXT_HOB (HobFv2); + } + + // + // Find FvImage in FvFile + // + Status = PeiFfsFindSectionData ( + (CONST EFI_PEI_SERVICES **) PeiServices, + EFI_SECTION_FIRMWARE_VOLUME_IMAGE, + FvFileHandle, + (VOID **)&FvImageHandle + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Collect FvImage Info. + // + Status = PeiFfsGetVolumeInfo (FvImageHandle, &FvImageInfo); + ASSERT_EFI_ERROR (Status); + // + // FvAlignment must be more than 8 bytes required by FvHeader structure. + // + FvAlignment = 1 << ((FvImageInfo.FvAttributes & EFI_FVB2_ALIGNMENT) >> 16); + if (FvAlignment < 8) { + FvAlignment = 8; + } + // + // Check FvImage + // + if ((UINTN) FvImageInfo.FvStart % FvAlignment != 0) { + FvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvImageInfo.FvSize), FvAlignment); + if (FvBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (FvBuffer, FvImageInfo.FvStart, (UINTN) FvImageInfo.FvSize); + // + // Update FvImageInfo after reload FvImage to new aligned memory + // + PeiFfsGetVolumeInfo ((EFI_PEI_FV_HANDLE) FvBuffer, &FvImageInfo); + } + + // + // Install FvPpi and Build FvHob + // + PiLibInstallFvInfoPpi ( + NULL, + FvImageInfo.FvStart, + (UINT32) FvImageInfo.FvSize, + &(FvImageInfo.FvName), + &(((EFI_FFS_FILE_HEADER*)FvFileHandle)->Name) + ); + + // + // Inform HOB consumer phase, i.e. DXE core, the existance of this FV + // + BuildFvHob ( + (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart, + FvImageInfo.FvSize + ); + // + // Makes the encapsulated volume show up in DXE phase to skip processing of + // encapsulated file again. + // + BuildFv2Hob ( + (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart, + FvImageInfo.FvSize, + &FvImageInfo.FvName, + &(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name) + ); + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Core/Pei/FwVol/FwVol.c b/MdeModulePkg/Core/Pei/FwVol/FwVol.c index 57b45d0fe0..621fb16f18 100644 --- a/MdeModulePkg/Core/Pei/FwVol/FwVol.c +++ b/MdeModulePkg/Core/Pei/FwVol/FwVol.c @@ -258,7 +258,8 @@ Returns: } } 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)) { + (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER) || + (FfsFileHeader->Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE)) { *FileHeader = FfsFileHeader; return EFI_SUCCESS; @@ -366,8 +367,15 @@ Returns: UINT8 FvCount; EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv; PEI_CORE_INSTANCE *PrivateData; + EFI_PEI_FILE_HANDLE FileHandle; + VOID *DepexData; + UINT32 AuthenticationStatus; + EFI_STATUS Status; - PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + FileHandle = NULL; + DepexData = NULL; + Status = EFI_SUCCESS; + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); if (PrivateData->FvCount >= FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) { ASSERT (FALSE); @@ -375,19 +383,53 @@ Returns: 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; - } - } + 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; - } - // - // Allways add to the All list - // - PrivateData->AllFv[PrivateData->AllFvCount++] = (EFI_PEI_FV_HANDLE)Fv->FvInfo; + // + // Only add FileSystem2 Fv to the All list + // + PrivateData->AllFv[PrivateData->AllFvCount++] = (EFI_PEI_FV_HANDLE)Fv->FvInfo; + + DEBUG ((EFI_D_INFO, "The %dth FvImage start address is 0x%10p and size is 0x%08x\n", PrivateData->AllFvCount, (VOID *) Fv->FvInfo, Fv->FvInfoSize)); + // + // Preprocess all FV type files in this new FileSystem2 Fv image + // + do { + Status = PeiFindFileEx ( + (EFI_PEI_FV_HANDLE)Fv->FvInfo, + NULL, + EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, + &FileHandle, + NULL + ); + if (!EFI_ERROR (Status)) { + Status = PeiFfsFindSectionData ( + (CONST EFI_PEI_SERVICES **) PeiServices, + EFI_SECTION_PEI_DEPEX, + FileHandle, + (VOID **)&DepexData + ); + if (!EFI_ERROR (Status)) { + if (!PeimDispatchReadiness (PeiServices, DepexData)) { + // + // Dependency is not satisfied. + // + continue; + } + } + // + // Process FvFile to install FvInfo ppi and build FvHob + // + ProcessFvFile (PeiServices, FileHandle, &AuthenticationStatus); + } + } while (FileHandle != NULL); + } return EFI_SUCCESS; } @@ -398,25 +440,21 @@ PeiFfsProcessSection ( IN EFI_SECTION_TYPE SectionType, IN EFI_COMMON_SECTION_HEADER *Section, IN UINTN SectionSize, - OUT VOID **OutputBuffer, - OUT UINTN *OutputSize, - OUT UINT32 *Authentication + OUT VOID **OutputBuffer ) /*++ Routine Description: Go through the file to search SectionType section, - when meeting an encapsuled section, search recursively. + when meeting an encapsuled section. Arguments: - PeiServices - Pointer to the PEI Core Services Table. + PeiServices - General purpose services available to every PEIM. 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 @@ -426,57 +464,94 @@ Returns: 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; + UINTN Index; + UINT32 Authentication; + PEI_CORE_INSTANCE *PrivateData; + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); *OutputBuffer = NULL; - ParsedLength = 0; + ParsedLength = 0; + Index = 0; + Status = EFI_NOT_FOUND; + PpiOutput = NULL; + PpiOutputSize = 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)) { + } else if ((Section->Type == EFI_SECTION_GUID_DEFINED) || (Section->Type == EFI_SECTION_COMPRESSION)) { + // + // Check the encapsulated section is extracted into the cache data. + // + for (Index = 0; Index < PrivateData->CacheSection.AllSectionCount; Index ++) { + if (Section == PrivateData->CacheSection.Section[Index]) { + PpiOutput = PrivateData->CacheSection.SectionData[Index]; + PpiOutputSize = PrivateData->CacheSection.SectionSize[Index]; + // + // Search section directly from the cache data. + // return PeiFfsProcessSection ( PeiServices, SectionType, PpiOutput, PpiOutputSize, - OutputBuffer, - OutputSize, - Authentication + OutputBuffer ); } } - } 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 - ); + + Status = EFI_NOT_FOUND; + if (Section->Type == EFI_SECTION_GUID_DEFINED) { + Status = PeiServicesLocatePpi ( + &((EFI_GUID_DEFINED_SECTION *)Section)->SectionDefinitionGuid, + 0, + NULL, + (VOID **) &GuidSectionPpi + ); if (!EFI_ERROR (Status)) { - return PeiFfsProcessSection ( - PeiServices, SectionType, PpiOutput, PpiOutputSize, OutputBuffer, OutputSize, Authentication - ); + Status = GuidSectionPpi->ExtractSection ( + GuidSectionPpi, + Section, + &PpiOutput, + &PpiOutputSize, + &Authentication + ); } + } else if (Section->Type == EFI_SECTION_COMPRESSION) { + Status = PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid, 0, NULL, (VOID **) &DecompressPpi); + if (!EFI_ERROR (Status)) { + Status = DecompressPpi->Decompress ( + DecompressPpi, + (CONST EFI_COMPRESSION_SECTION*) Section, + &PpiOutput, + &PpiOutputSize + ); + } + } + + if (!EFI_ERROR (Status)) { + // + // Update cache section data. + // + if (PrivateData->CacheSection.AllSectionCount < CACHE_SETION_MAX_NUMBER) { + PrivateData->CacheSection.AllSectionCount ++; + } + PrivateData->CacheSection.Section [PrivateData->CacheSection.SectionIndex] = Section; + PrivateData->CacheSection.SectionData [PrivateData->CacheSection.SectionIndex] = PpiOutput; + PrivateData->CacheSection.SectionSize [PrivateData->CacheSection.SectionIndex] = PpiOutputSize; + PrivateData->CacheSection.SectionIndex = (PrivateData->CacheSection.SectionIndex + 1)%CACHE_SETION_MAX_NUMBER; + + return PeiFfsProcessSection ( + PeiServices, + SectionType, + PpiOutput, + PpiOutputSize, + OutputBuffer + ); } } @@ -526,9 +601,6 @@ Returns: EFI_FFS_FILE_HEADER *FfsFileHeader; UINT32 FileSize; EFI_COMMON_SECTION_HEADER *Section; - UINTN OutputSize; - UINT32 AuthenticationStatus; - FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle); @@ -542,13 +614,11 @@ Returns: FileSize -= sizeof (EFI_FFS_FILE_HEADER); return PeiFfsProcessSection ( - PeiServices, + PeiServices, SectionType, Section, FileSize, - SectionData, - &OutputSize, - &AuthenticationStatus + SectionData ); } @@ -601,7 +671,7 @@ PeiFvFindNextVolume ( Routine Description: - Return the BFV location + Return the firmware volumes. BugBug -- Move this to the location of this code to where the other FV and FFS support code lives. @@ -761,21 +831,32 @@ Returns: --*/ { - EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FIRMWARE_VOLUME_HEADER FwVolHeader; EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo; if (VolumeInfo == NULL) { return EFI_INVALID_PARAMETER; } + + // + // VolumeHandle may not align at 8 byte, + // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte. + // So, Copy FvHeader into the local FvHeader structure. + // + CopyMem (&FwVolHeader, VolumeHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER)); + // + // Check Fv Image Signature + // + if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + VolumeInfo->FvAttributes = FwVolHeader.Attributes; + VolumeInfo->FvStart = (VOID *) VolumeHandle; + VolumeInfo->FvSize = FwVolHeader.FvLength; + CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID)); - 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); + if (FwVolHeader.ExtHeaderOffset != 0) { + FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)VolumeHandle) + 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 0c627c17b4..2c7e5846cb 100644 --- a/MdeModulePkg/Core/Pei/Image/Image.c +++ b/MdeModulePkg/Core/Pei/Image/Image.c @@ -241,7 +241,7 @@ Returns: // When Image has no reloc section, it can't be relocated into memory. // if (ImageContext.RelocationsStripped) { - DEBUG ((EFI_D_ERROR, "The image at 0x%08x without reloc section can't be loaded into memory", (UINTN) Pe32Data)); + DEBUG ((EFI_D_ERROR, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN) Pe32Data)); return EFI_INVALID_PARAMETER; } // diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMain.h index 61641b37e7..84d187ed97 100644 --- a/MdeModulePkg/Core/Pei/PeiMain.h +++ b/MdeModulePkg/Core/Pei/PeiMain.h @@ -53,6 +53,7 @@ Revision History #include #include #include +#include #include #include @@ -98,6 +99,15 @@ typedef struct { BOOLEAN ScanFv; } PEI_CORE_FV_HANDLE; +#define CACHE_SETION_MAX_NUMBER 0x10 +typedef struct { + EFI_COMMON_SECTION_HEADER* Section[CACHE_SETION_MAX_NUMBER]; + VOID* SectionData[CACHE_SETION_MAX_NUMBER]; + UINTN SectionSize[CACHE_SETION_MAX_NUMBER]; + UINTN AllSectionCount; + UINTN SectionIndex; +} CACHE_SECTION_DATA; + // // Pei Core private data structure instance // @@ -130,6 +140,7 @@ typedef struct{ UINTN SizeOfCacheAsRam; VOID *MaxTopOfCarHeap; EFI_PEI_PPI_DESCRIPTOR *XipLoadFile; + CACHE_SECTION_DATA CacheSection; } PEI_CORE_INSTANCE; // @@ -1379,4 +1390,23 @@ Returns: --*/ ; +/** + Get Fv image from the FV type file, then install FV INFO ppi, Build FV hob. + + @param PeiServices Pointer to the PEI Core Services Table. + @param FileHandle File handle of a Fv type file. + @param AuthenticationState Pointer to attestation authentication state of image. + + + @retval EFI_NOT_FOUND FV image can't be found. + @retval EFI_SUCCESS Successfully to process it. + +**/ +EFI_STATUS +ProcessFvFile ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FvFileHandle, + OUT UINT32 *AuthenticationState + ); + #endif diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf b/MdeModulePkg/Core/Pei/PeiMain.inf index 360f027b2a..0d58f9555a 100644 --- a/MdeModulePkg/Core/Pei/PeiMain.inf +++ b/MdeModulePkg/Core/Pei/PeiMain.inf @@ -81,6 +81,7 @@ MemoryAllocationLib CacheMaintenanceLib PeCoffLib + PeiPiLib [Guids] gPeiAprioriFileNameGuid @@ -103,6 +104,3 @@ [FeaturePcd.common] gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst - - -