3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Responsibility of this module is to load the DXE Core from a Firmware Volume.
25 #pragma warning( disable : 4305 )
27 BOOLEAN gInMemory
= FALSE
;
32 #define EFI_PPI_NEEDED_BY_DXE \
34 0x4d37da42, 0x3a0c, 0x4eda, 0xb9, 0xeb, 0xbc, 0x0e, 0x1d, 0xb4, 0x71, 0x3b \
36 EFI_GUID mPpiNeededByDxeGuid
= EFI_PPI_NEEDED_BY_DXE
;
39 // Module Globals used in the DXE to PEI handoff
40 // These must be module globals, so the stack can be switched
42 static EFI_DXE_IPL_PPI mDxeIplPpi
= {
46 static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi
= {
50 static EFI_PEI_PPI_DESCRIPTOR mPpiLoadFile
= {
51 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
52 &gEfiPeiFvFileLoaderPpiGuid
,
56 static EFI_PEI_PPI_DESCRIPTOR mPpiList
= {
57 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
62 static EFI_PEI_PPI_DESCRIPTOR mPpiPeiInMemory
= {
63 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
68 static EFI_PEI_PPI_DESCRIPTOR mPpiSignal
= {
69 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
70 &gEfiEndOfPeiSignalPpiGuid
,
74 DECOMPRESS_LIBRARY gEfiDecompress
= {
75 UefiDecompressGetInfo
,
79 DECOMPRESS_LIBRARY gTianoDecompress
= {
80 TianoDecompressGetInfo
,
84 DECOMPRESS_LIBRARY gCustomDecompress
= {
85 CustomDecompressGetInfo
,
98 OccupiedSize
= ActualSize
;
99 while ((OccupiedSize
& (Alignment
- 1)) != 0) {
108 PeimInitializeDxeIpl (
109 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
110 IN EFI_PEI_SERVICES
**PeiServices
116 Initializes the Dxe Ipl PPI
120 FfsHeader - Pointer to FFS file header
121 PeiServices - General purpose services available to every PEIM.
130 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
131 EFI_BOOT_MODE BootMode
;
133 Status
= PeiServicesGetBootMode (&BootMode
);
135 ASSERT_EFI_ERROR (Status
);
137 Status
= PeiServicesLocatePpi (
144 if (EFI_ERROR (Status
) && (BootMode
!= BOOT_ON_S3_RESUME
)) {
146 // The DxeIpl has not yet been shadowed
148 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
151 // Shadow DxeIpl and then re-run its entry point
153 Status
= ShadowDxeIpl (FfsHeader
, PeiEfiPeiPeCoffLoader
);
154 if (EFI_ERROR (Status
)) {
159 if (BootMode
!= BOOT_ON_S3_RESUME
) {
161 // The DxeIpl has been shadowed
166 // Install LoadFile PPI
168 Status
= PeiServicesInstallPpi (&mPpiLoadFile
);
170 if (EFI_ERROR (Status
)) {
175 // Install DxeIpl PPI
177 PeiServicesInstallPpi (&mPpiList
);
179 if (EFI_ERROR (Status
)) {
191 IN EFI_DXE_IPL_PPI
*This
,
192 IN EFI_PEI_SERVICES
**PeiServices
,
193 IN EFI_PEI_HOB_POINTERS HobList
199 Main entry point to last PEIM
203 This - Entry point for DXE IPL PPI
204 PeiServices - General purpose services available to every PEIM.
205 HobList - Address to the Pei HOB list
209 EFI_SUCCESS - DEX core was successfully loaded.
210 EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core.
215 EFI_PHYSICAL_ADDRESS TopOfStack
;
216 EFI_PHYSICAL_ADDRESS BaseOfStack
;
217 EFI_PHYSICAL_ADDRESS BspStore
;
218 EFI_GUID DxeCoreFileName
;
219 VOID
*DxeCorePe32Data
;
220 EFI_PHYSICAL_ADDRESS DxeCoreAddress
;
222 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
;
223 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
224 EFI_BOOT_MODE BootMode
;
225 EFI_PEI_RECOVERY_MODULE_PPI
*PeiRecovery
;
226 EFI_PEI_S3_RESUME_PPI
*S3Resume
;
227 EFI_PHYSICAL_ADDRESS PageTables
;
232 Status
= EFI_SUCCESS
;
235 // if in S3 Resume, restore configure
237 Status
= PeiServicesGetBootMode (&BootMode
);
239 if (!EFI_ERROR (Status
) && (BootMode
== BOOT_ON_S3_RESUME
)) {
240 Status
= PeiServicesLocatePpi (
241 &gEfiPeiS3ResumePpiGuid
,
247 ASSERT_EFI_ERROR (Status
);
249 Status
= S3Resume
->S3RestoreConfig (PeiServices
);
251 ASSERT_EFI_ERROR (Status
);
254 Status
= EFI_SUCCESS
;
257 // Install the PEI Protocols that are shared between PEI and DXE
259 #ifdef EFI_NT_EMULATOR
260 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
261 ASSERT (PeiEfiPeiPeCoffLoader
!= NULL
);
263 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderX64Protocol ();
267 Status
= InstallEfiPeiPeCoffLoader64 (PeiServices
, &PeiEfiPeiPeCoffLoader
, NULL
);
268 ASSERT_EFI_ERROR (Status
);
271 // Allocate 128KB for the Stack
273 PeiServicesAllocatePages (EfiBootServicesData
, EFI_SIZE_TO_PAGES (STACK_SIZE
), &BaseOfStack
);
274 ASSERT (BaseOfStack
!= 0);
277 // Compute the top of the stack we were allocated. Pre-allocate a 32 bytes
278 // for safety (PpisNeededByDxe and DxeCore).
280 TopOfStack
= BaseOfStack
+ EFI_SIZE_TO_PAGES (STACK_SIZE
) * EFI_PAGE_SIZE
- 32;
283 // Add architecture-specifc HOBs (including the BspStore HOB)
285 Status
= CreateArchSpecificHobs (&BspStore
);
286 ASSERT_EFI_ERROR (Status
);
289 // See if we are in crisis recovery
291 Status
= PeiServicesGetBootMode (&BootMode
);
292 if (!EFI_ERROR (Status
) && (BootMode
== BOOT_IN_RECOVERY_MODE
)) {
293 Status
= PeiServicesLocatePpi (
294 &gEfiPeiRecoveryModulePpiGuid
,
297 (VOID
**)&PeiRecovery
300 ASSERT_EFI_ERROR (Status
);
301 Status
= PeiRecovery
->LoadRecoveryCapsule (PeiServices
, PeiRecovery
);
302 ASSERT_EFI_ERROR (Status
);
306 // Find the DXE Core in a Firmware Volume
308 Status
= PeiFindFile (
309 EFI_FV_FILETYPE_DXE_CORE
,
314 ASSERT_EFI_ERROR (Status
);
317 // Transfer control to the DXE Core
318 // The handoff state is simply a pointer to the HOB list
320 // PEI_PERF_END (PeiServices, L"DxeIpl", NULL, 0);
322 Status
= PeiServicesInstallPpi (&mPpiSignal
);
323 ASSERT_EFI_ERROR (Status
);
326 // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA \
327 // memory, it may be corrupted when copying FV to high-end memory
331 // Limit to 36 bits of addressing for debug. Should get it from CPU
333 PageTables
= CreateIdentityMappingPageTables (36);
337 // Load the DXE Core from a Firmware Volume
339 Status
= PeiLoadx64File (
340 PeiEfiPeiPeCoffLoader
,
347 ASSERT_EFI_ERROR (Status
);
351 // Add HOB for the DXE Core
361 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
365 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
368 DEBUG ((EFI_D_INFO
, "DXE Core Entry\n"));
370 // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded.
371 // Call x64 drivers passing in single argument, a pointer to the HOBs.
375 (EFI_PHYSICAL_ADDRESS
)(UINTN
)(HobList
.Raw
),
382 // If we get here, then the DXE Core returned. This is an error
384 ASSERT_EFI_ERROR (Status
);
386 return EFI_OUT_OF_RESOURCES
;
392 IN UINT16 SectionType
,
393 OUT EFI_GUID
*FileName
,
400 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
401 described in the HOB list. Able to search in a compression set in a FFS file.
402 But only one level of compression is supported, that is, not able to search
403 in a compression set that is within another compression set.
407 Type - The Type of file to retrieve
409 SectionType - The type of section to retrieve from a file
411 FileName - The name of the file found in the Firmware Volume
413 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
417 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
418 the PE/COFF image is returned in Pe32Data
420 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
424 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
425 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
428 EFI_PEI_HOB_POINTERS Hob
;
432 FfsFileHeader
= NULL
;
436 // Foreach Firmware Volume, look for a specified type
437 // of file and break out when one is found
439 Hob
.Raw
= GetHobList ();
440 while ((Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
)) != NULL
) {
441 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (Hob
.FirmwareVolume
->BaseAddress
);
442 Status
= PeiServicesFfsFindNextFile (
447 if (!EFI_ERROR (Status
)) {
448 Status
= PeiProcessFile (
453 CopyMem (FileName
, &FfsFileHeader
->Name
, sizeof (EFI_GUID
));
456 Hob
.Raw
= GET_NEXT_HOB (Hob
);
458 return EFI_NOT_FOUND
;
463 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
,
465 IN EFI_MEMORY_TYPE MemoryType
,
466 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
467 OUT UINT64
*ImageSize
,
468 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
474 Loads and relocates a PE/COFF image into memory.
478 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
480 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
482 ImageAddress - The base address of the relocated PE/COFF image
484 ImageSize - The size of the relocated PE/COFF image
486 EntryPoint - The entry point of the relocated PE/COFF image
490 EFI_SUCCESS - The file was loaded and relocated
491 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
496 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
497 EFI_PHYSICAL_ADDRESS MemoryBuffer
;
499 ZeroMem (&ImageContext
, sizeof (ImageContext
));
500 ImageContext
.Handle
= Pe32Data
;
501 Status
= GetImageReadFunction (&ImageContext
);
503 ASSERT_EFI_ERROR (Status
);
505 Status
= PeiEfiPeiPeCoffLoader
->GetImageInfo (PeiEfiPeiPeCoffLoader
, &ImageContext
);
506 if (EFI_ERROR (Status
)) {
510 // Allocate Memory for the image
513 // Allocate Memory for the image
515 PeiServicesAllocatePages (MemoryType
, EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
), &MemoryBuffer
);
516 ImageContext
.ImageAddress
= MemoryBuffer
;
517 ASSERT (ImageContext
.ImageAddress
!= 0);
520 // Load the image to our new buffer
523 Status
= PeiEfiPeiPeCoffLoader
->LoadImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
524 if (EFI_ERROR (Status
)) {
529 // Relocate the image in our new buffer
531 Status
= PeiEfiPeiPeCoffLoader
->RelocateImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
532 if (EFI_ERROR (Status
)) {
537 // Flush the instruction cache so the image data is written before we execute it
539 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
541 *ImageAddress
= ImageContext
.ImageAddress
;
542 *ImageSize
= ImageContext
.ImageSize
;
543 *EntryPoint
= ImageContext
.EntryPoint
;
550 IN EFI_FFS_FILE_HEADER
*DxeIplFileHeader
,
551 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
557 Shadow the DXE IPL to a different memory location. This occurs after permanent
558 memory has been discovered.
562 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
564 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
568 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
570 EFI_ ERROR - The shadow was unsuccessful.
576 UINTN OccupiedSectionLength
;
577 EFI_PHYSICAL_ADDRESS DxeIplAddress
;
579 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint
;
581 EFI_COMMON_SECTION_HEADER
*Section
;
583 Section
= (EFI_COMMON_SECTION_HEADER
*) (DxeIplFileHeader
+ 1);
585 while ((Section
->Type
!= EFI_SECTION_PE32
) && (Section
->Type
!= EFI_SECTION_TE
)) {
586 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
587 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
588 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
592 // Relocate DxeIpl into memory by using loadfile service
594 Status
= PeiLoadx64File (
595 PeiEfiPeiPeCoffLoader
,
596 (VOID
*) (Section
+ 1),
603 if (Status
== EFI_SUCCESS
) {
605 // Install PeiInMemory to indicate the Dxeipl is shadowed
607 Status
= PeiServicesInstallPpi (&mPpiPeiInMemory
);
609 if (EFI_ERROR (Status
)) {
613 Status
= ((EFI_PEIM_ENTRY_POINT
) (UINTN
) DxeIplEntryPoint
) (DxeIplFileHeader
, GetPeiServicesTablePointer());
622 IN EFI_PEI_FV_FILE_LOADER_PPI
*This
,
623 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
624 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
625 OUT UINT64
*ImageSize
,
626 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
632 Given a pointer to an FFS file containing a PE32 image, get the
633 information on the PE32 image, and then "load" it so that it
638 This - pointer to our file loader protocol
639 FfsHeader - pointer to the FFS file header of the FFS file that
640 contains the PE32 image we want to load
641 ImageAddress - returned address where the PE32 image is loaded
642 ImageSize - returned size of the loaded PE32 image
643 EntryPoint - entry point to the loaded PE32 image
647 EFI_SUCCESS - The FFS file was successfully loaded.
648 EFI_ERROR - Unable to load the FFS file.
652 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
657 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
660 // Preprocess the FFS file to get a pointer to the PE32 information
661 // in the enclosed PE32 image.
663 Status
= PeiProcessFile (
669 if (EFI_ERROR (Status
)) {
673 // Load the PE image from the FFS file
675 Status
= PeiLoadx64File (
676 PeiEfiPeiPeCoffLoader
,
689 IN UINT16 SectionType
,
690 IN OUT EFI_FFS_FILE_HEADER
**RealFfsFileHeader
,
699 SectionType - The type of section in the FFS file to process.
701 FfsFileHeader - Pointer to the FFS file to process, looking for the
702 specified SectionType
704 Pe32Data - returned pointer to the start of the PE32 image found
709 EFI_SUCCESS - found the PE32 section in the FFS file
715 DECOMPRESS_LIBRARY
*DecompressLibrary
;
717 UINT8
*ScratchBuffer
;
718 UINT32 DstBufferSize
;
719 UINT32 ScratchBufferSize
;
720 EFI_COMMON_SECTION_HEADER
*CmpSection
;
721 UINTN CmpSectionLength
;
722 UINTN OccupiedCmpSectionLength
;
725 EFI_COMMON_SECTION_HEADER
*Section
;
727 UINTN OccupiedSectionLength
;
729 EFI_GUID_DEFINED_SECTION
*GuidedSectionHeader
;
730 UINT32 AuthenticationStatus
;
731 EFI_PEI_SECTION_EXTRACTION_PPI
*SectionExtract
;
734 EFI_PEI_SECURITY_PPI
*Security
;
735 BOOLEAN StartCrisisRecovery
;
737 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
738 EFI_COMPRESSION_SECTION
*CompressionSection
;
739 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
741 FfsFileHeader
= *RealFfsFileHeader
;
743 Status
= PeiServicesFfsFindSectionData (
744 EFI_SECTION_COMPRESSION
,
750 // Upon finding a DXE Core file, see if there is first a compression section
752 if (!EFI_ERROR (Status
)) {
754 // Yes, there is a compression section, so extract the contents
755 // Decompress the image here
757 Section
= (EFI_COMMON_SECTION_HEADER
*) (UINTN
) (VOID
*) ((UINT8
*) (FfsFileHeader
) + (UINTN
) sizeof (EFI_FFS_FILE_HEADER
));
760 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
761 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
764 // Was the DXE Core file encapsulated in a GUID'd section?
766 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
768 // Locate the GUID'd Section Extractor
770 GuidedSectionHeader
= (VOID
*) (Section
+ 1);
773 // This following code constitutes the addition of the security model
777 // Set a default authenticatino state
779 AuthenticationStatus
= 0;
781 Status
= PeiServicesLocatePpi (
782 &gEfiPeiSectionExtractionPpiGuid
,
785 (VOID
**)&SectionExtract
788 if (EFI_ERROR (Status
)) {
792 // Verify Authentication State
794 CopyMem (&TempGuid
, Section
+ 1, sizeof (EFI_GUID
));
796 Status
= SectionExtract
->PeiGetSection (
797 GetPeiServicesTablePointer(),
799 (EFI_SECTION_TYPE
*) &SectionType
,
804 &AuthenticationStatus
807 if (EFI_ERROR (Status
)) {
811 // If not ask the Security PPI, if exists, for disposition
814 Status
= PeiServicesLocatePpi (
815 &gEfiPeiSecurityPpiGuid
,
820 if (EFI_ERROR (Status
)) {
824 Status
= Security
->AuthenticationState (
825 GetPeiServicesTablePointer(),
826 (struct _EFI_PEI_SECURITY_PPI
*) Security
,
827 AuthenticationStatus
,
832 if (EFI_ERROR (Status
)) {
836 // If there is a security violation, report to caller and have
837 // the upper-level logic possible engender a crisis recovery
839 if (StartCrisisRecovery
) {
840 return EFI_SECURITY_VIOLATION
;
844 if (Section
->Type
== EFI_SECTION_PE32
) {
846 // This is what we want
848 *Pe32Data
= (VOID
*) (Section
+ 1);
850 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
852 // This is a compression set, expand it
854 CompressionSection
= (EFI_COMPRESSION_SECTION
*) Section
;
856 switch (CompressionSection
->CompressionType
) {
857 case EFI_STANDARD_COMPRESSION
:
858 DecompressLibrary
= &gTianoDecompress
;
861 case EFI_CUSTOMIZED_COMPRESSION
:
863 // Load user customized compression protocol.
865 DecompressLibrary
= &gCustomDecompress
;
868 case EFI_NOT_COMPRESSED
:
871 // Need to support not compressed file
873 ASSERT_EFI_ERROR (Status
);
874 return EFI_NOT_FOUND
;
877 Status
= DecompressLibrary
->GetInfo (
878 (UINT8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
879 (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION
),
883 if (EFI_ERROR (Status
)) {
887 return EFI_NOT_FOUND
;
891 // Allocate scratch buffer
893 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
894 if (ScratchBuffer
== NULL
) {
895 return EFI_OUT_OF_RESOURCES
;
899 // Allocate destination buffer
901 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
902 if (DstBuffer
== NULL
) {
903 return EFI_OUT_OF_RESOURCES
;
907 // Call decompress function
909 Status
= DecompressLibrary
->Decompress (
910 (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
915 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) DstBuffer
;
916 if (CmpSection
->Type
== EFI_SECTION_RAW
) {
918 // Skip the section header and
919 // adjust the pointer alignment to 16
921 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (DstBuffer
+ 16);
923 if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
924 FfsFileHeader
= NULL
;
925 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
, FvHeader
->FvLength
);
926 Status
= PeiServicesFfsFindNextFile (
927 EFI_FV_FILETYPE_DXE_CORE
,
932 if (EFI_ERROR (Status
)) {
933 return EFI_NOT_FOUND
;
937 // Reture the FfsHeader that contain Pe32Data.
939 *RealFfsFileHeader
= FfsFileHeader
;
940 return PeiProcessFile (SectionType
, RealFfsFileHeader
, Pe32Data
);
944 // Decompress successfully.
945 // Loop the decompressed data searching for expected section.
947 CmpFileData
= (VOID
*) DstBuffer
;
948 CmpFileSize
= DstBufferSize
;
950 CmpSectionLength
= *(UINT32
*) (CmpSection
->Size
) & 0x00ffffff;
951 if (CmpSection
->Type
== EFI_SECTION_PE32
) {
953 // This is what we want
955 *Pe32Data
= (VOID
*) (CmpSection
+ 1);
959 OccupiedCmpSectionLength
= GetOccupiedSize (CmpSectionLength
, 4);
960 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) CmpSection
+ OccupiedCmpSectionLength
);
961 } while (CmpSection
->Type
!= 0 && (UINTN
) ((UINT8
*) CmpSection
- (UINT8
*) CmpFileData
) < CmpFileSize
);
964 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
965 FileSize
= FfsFileHeader
->Size
[0] & 0xFF;
966 FileSize
+= (FfsFileHeader
->Size
[1] << 8) & 0xFF00;
967 FileSize
+= (FfsFileHeader
->Size
[2] << 16) & 0xFF0000;
968 FileSize
&= 0x00FFFFFF;
969 } while (Section
->Type
!= 0 && (UINTN
) ((UINT8
*) Section
- (UINT8
*) FfsFileHeader
) < FileSize
);
972 // End of the decompression activity
976 Status
= PeiServicesFfsFindSectionData (
982 if (EFI_ERROR (Status
)) {
983 Status
= PeiServicesFfsFindSectionData (
988 if (EFI_ERROR (Status
)) {
994 *Pe32Data
= SectionData
;