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 BOOLEAN gInMemory
= FALSE
;
28 // Module Globals used in the DXE to PEI handoff
29 // These must be module globals, so the stack can be switched
31 static EFI_DXE_IPL_PPI mDxeIplPpi
= {
35 static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi
= {
39 static EFI_PEI_PPI_DESCRIPTOR mPpiLoadFile
= {
40 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
41 &gEfiPeiFvFileLoaderPpiGuid
,
45 static EFI_PEI_PPI_DESCRIPTOR mPpiList
= {
46 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
51 static EFI_PEI_PPI_DESCRIPTOR mPpiPeiInMemory
= {
52 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
57 static EFI_PEI_PPI_DESCRIPTOR mPpiSignal
= {
58 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
59 &gEfiEndOfPeiSignalPpiGuid
,
63 DECOMPRESS_LIBRARY gEfiDecompress
= {
64 UefiDecompressGetInfo
,
68 DECOMPRESS_LIBRARY gTianoDecompress
= {
69 TianoDecompressGetInfo
,
73 DECOMPRESS_LIBRARY gCustomDecompress
= {
74 CustomDecompressGetInfo
,
87 OccupiedSize
= ActualSize
;
88 while ((OccupiedSize
& (Alignment
- 1)) != 0) {
97 PeimInitializeDxeIpl (
98 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
99 IN EFI_PEI_SERVICES
**PeiServices
105 Initializes the Dxe Ipl PPI
109 FfsHeader - Pointer to FFS file header
110 PeiServices - General purpose services available to every PEIM.
119 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
120 EFI_BOOT_MODE BootMode
;
122 Status
= PeiServicesGetBootMode (&BootMode
);
124 ASSERT_EFI_ERROR (Status
);
126 Status
= PeiServicesLocatePpi (
133 if (EFI_ERROR (Status
) && (BootMode
!= BOOT_ON_S3_RESUME
)) {
135 // The DxeIpl has not yet been shadowed
137 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
140 // Shadow DxeIpl and then re-run its entry point
142 Status
= ShadowDxeIpl (FfsHeader
, PeiEfiPeiPeCoffLoader
);
143 if (EFI_ERROR (Status
)) {
148 if (BootMode
!= BOOT_ON_S3_RESUME
) {
150 // The DxeIpl has been shadowed
155 // Install LoadFile PPI
157 Status
= PeiServicesInstallPpi (&mPpiLoadFile
);
159 if (EFI_ERROR (Status
)) {
164 // Install DxeIpl PPI
166 PeiServicesInstallPpi (&mPpiList
);
168 if (EFI_ERROR (Status
)) {
180 IN EFI_DXE_IPL_PPI
*This
,
181 IN EFI_PEI_SERVICES
**PeiServices
,
182 IN EFI_PEI_HOB_POINTERS HobList
188 Main entry point to last PEIM
191 This - Entry point for DXE IPL PPI
192 PeiServices - General purpose services available to every PEIM.
193 HobList - Address to the Pei HOB list
197 EFI_SUCCESS - DEX core was successfully loaded.
198 EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core.
205 EFI_PHYSICAL_ADDRESS BspStore
;
206 EFI_GUID DxeCoreFileName
;
207 EFI_GUID FirmwareFileName
;
209 EFI_PHYSICAL_ADDRESS DxeCoreAddress
;
211 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
;
212 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
213 EFI_BOOT_MODE BootMode
;
214 EFI_PEI_RECOVERY_MODULE_PPI
*PeiRecovery
;
215 EFI_PEI_S3_RESUME_PPI
*S3Resume
;
217 // PERF_START (PeiServices, L"DxeIpl", NULL, 0);
221 Status
= EFI_SUCCESS
;
224 // if in S3 Resume, restore configure
226 Status
= PeiServicesGetBootMode (&BootMode
);
228 if (!EFI_ERROR (Status
) && (BootMode
== BOOT_ON_S3_RESUME
)) {
229 Status
= PeiServicesLocatePpi (
230 &gEfiPeiS3ResumePpiGuid
,
236 ASSERT_EFI_ERROR (Status
);
238 Status
= S3Resume
->S3RestoreConfig (PeiServices
);
240 ASSERT_EFI_ERROR (Status
);
243 Status
= EFI_SUCCESS
;
246 // Install the PEI Protocols that are shared between PEI and DXE
248 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
249 ASSERT (PeiEfiPeiPeCoffLoader
!= NULL
);
253 // Allocate 128KB for the Stack
255 BaseOfStack
= AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE
));
256 ASSERT (BaseOfStack
!= NULL
);
259 // Compute the top of the stack we were allocated. Pre-allocate a UINTN
262 TopOfStack
= (VOID
*)((UINTN
)BaseOfStack
+ EFI_SIZE_TO_PAGES (STACK_SIZE
) * EFI_PAGE_SIZE
- CPU_STACK_ALIGNMENT
);
263 TopOfStack
= ALIGN_POINTER (TopOfStack
, CPU_STACK_ALIGNMENT
);
266 // Add architecture-specifc HOBs (including the BspStore HOB)
268 Status
= CreateArchSpecificHobs (&BspStore
);
270 ASSERT_EFI_ERROR (Status
);
273 // Add HOB for the EFI Decompress Protocol
276 &gEfiDecompressProtocolGuid
,
277 (VOID
*)&gEfiDecompress
,
278 sizeof (gEfiDecompress
)
282 // Add HOB for the Tiano Decompress Protocol
285 &gEfiTianoDecompressProtocolGuid
,
286 (VOID
*)&gTianoDecompress
,
287 sizeof (gTianoDecompress
)
291 // Add HOB for the user customized Decompress Protocol
294 &gEfiCustomizedDecompressProtocolGuid
,
295 (VOID
*)&gCustomDecompress
,
296 sizeof (gCustomDecompress
)
300 // Add HOB for the PE/COFF Loader Protocol
303 &gEfiPeiPeCoffLoaderGuid
,
304 (VOID
*)&PeiEfiPeiPeCoffLoader
,
309 // See if we are in crisis recovery
311 Status
= PeiServicesGetBootMode (&BootMode
);
313 if (!EFI_ERROR (Status
) && (BootMode
== BOOT_IN_RECOVERY_MODE
)) {
315 Status
= PeiServicesLocatePpi (
316 &gEfiPeiRecoveryModulePpiGuid
,
319 (VOID
**)&PeiRecovery
322 ASSERT_EFI_ERROR (Status
);
323 Status
= PeiRecovery
->LoadRecoveryCapsule (PeiServices
, PeiRecovery
);
324 if (EFI_ERROR (Status
)) {
325 DEBUG ((EFI_D_ERROR
, "Load Recovery Capsule Failed.(Status = %r)\n", Status
));
330 // Now should have a HOB with the DXE core w/ the old HOB destroyed
335 // Find the EFI_FV_FILETYPE_RAW type compressed Firmware Volume file in FTW spare block
336 // The file found will be processed by PeiProcessFile: It will first be decompressed to
337 // a normal FV, then a corresponding FV type hob will be built which is provided for DXE
338 // core to find and dispatch drivers in this FV. Because PeiProcessFile typically checks
339 // for EFI_FV_FILETYPE_DXE_CORE type file, in this condition we need not check returned
342 Status
= PeiFindFile (
350 // Find the DXE Core in a Firmware Volume
352 Status
= PeiFindFile (
353 EFI_FV_FILETYPE_DXE_CORE
,
359 ASSERT_EFI_ERROR (Status
);
362 // Load the DXE Core from a Firmware Volume
364 Status
= PeiLoadFile (
365 PeiEfiPeiPeCoffLoader
,
372 ASSERT_EFI_ERROR (Status
);
375 // Transfer control to the DXE Core
376 // The handoff state is simply a pointer to the HOB list
379 Status
= PeiServicesInstallPpi (&mPpiSignal
);
381 ASSERT_EFI_ERROR (Status
);
384 // Add HOB for the DXE Core
394 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
398 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
401 DEBUG ((EFI_D_INFO
, "DXE Core Entry\n"));
403 (SWITCH_STACK_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
,
407 (VOID
*) (UINTN
) BspStore
411 // If we get here, then the DXE Core returned. This is an error
412 // Dxe Core should not return.
417 return EFI_OUT_OF_RESOURCES
;
423 IN UINT16 SectionType
,
424 OUT EFI_GUID
*FileName
,
431 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
432 described in the HOB list. Able to search in a compression set in a FFS file.
433 But only one level of compression is supported, that is, not able to search
434 in a compression set that is within another compression set.
438 Type - The Type of file to retrieve
440 SectionType - The type of section to retrieve from a file
442 FileName - The name of the file found in the Firmware Volume
444 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
448 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
449 the PE/COFF image is returned in Pe32Data
451 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
455 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
456 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
459 EFI_PEI_HOB_POINTERS Hob
;
463 FfsFileHeader
= NULL
;
467 // Foreach Firmware Volume, look for a specified type
468 // of file and break out when one is found
470 Hob
.Raw
= GetHobList ();
471 while ((Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
)) != NULL
) {
472 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (Hob
.FirmwareVolume
->BaseAddress
);
473 Status
= PeiServicesFfsFindNextFile (
478 if (!EFI_ERROR (Status
)) {
479 Status
= PeiProcessFile (
484 CopyMem (FileName
, &FfsFileHeader
->Name
, sizeof (EFI_GUID
));
487 Hob
.Raw
= GET_NEXT_HOB (Hob
);
489 return EFI_NOT_FOUND
;
494 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
,
496 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
497 OUT UINT64
*ImageSize
,
498 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
504 Loads and relocates a PE/COFF image into memory.
508 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
510 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
512 ImageAddress - The base address of the relocated PE/COFF image
514 ImageSize - The size of the relocated PE/COFF image
516 EntryPoint - The entry point of the relocated PE/COFF image
520 EFI_SUCCESS - The file was loaded and relocated
522 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
527 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
529 ZeroMem (&ImageContext
, sizeof (ImageContext
));
530 ImageContext
.Handle
= Pe32Data
;
531 Status
= GetImageReadFunction (&ImageContext
);
533 ASSERT_EFI_ERROR (Status
);
535 Status
= PeiEfiPeiPeCoffLoader
->GetImageInfo (PeiEfiPeiPeCoffLoader
, &ImageContext
);
536 if (EFI_ERROR (Status
)) {
540 // Allocate Memory for the image
542 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
));
543 ASSERT (ImageContext
.ImageAddress
!= 0);
546 // Load the image to our new buffer
548 Status
= PeiEfiPeiPeCoffLoader
->LoadImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
549 if (EFI_ERROR (Status
)) {
553 // Relocate the image in our new buffer
555 Status
= PeiEfiPeiPeCoffLoader
->RelocateImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
556 if (EFI_ERROR (Status
)) {
561 // Flush the instruction cache so the image data is written before we execute it
563 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
565 *ImageAddress
= ImageContext
.ImageAddress
;
566 *ImageSize
= ImageContext
.ImageSize
;
567 *EntryPoint
= ImageContext
.EntryPoint
;
574 IN EFI_FFS_FILE_HEADER
*DxeIplFileHeader
,
575 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
581 Shadow the DXE IPL to a different memory location. This occurs after permanent
582 memory has been discovered.
586 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
588 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
592 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
594 EFI_ ERROR - The shadow was unsuccessful.
600 UINTN OccupiedSectionLength
;
601 EFI_PHYSICAL_ADDRESS DxeIplAddress
;
603 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint
;
605 EFI_COMMON_SECTION_HEADER
*Section
;
607 Section
= (EFI_COMMON_SECTION_HEADER
*) (DxeIplFileHeader
+ 1);
609 while ((Section
->Type
!= EFI_SECTION_PE32
) && (Section
->Type
!= EFI_SECTION_TE
)) {
610 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
611 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
612 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
615 // Relocate DxeIpl into memory by using loadfile service
617 Status
= PeiLoadFile (
618 PeiEfiPeiPeCoffLoader
,
619 (VOID
*) (Section
+ 1),
625 if (Status
== EFI_SUCCESS
) {
627 // Install PeiInMemory to indicate the Dxeipl is shadowed
629 Status
= PeiServicesInstallPpi (&mPpiPeiInMemory
);
631 if (EFI_ERROR (Status
)) {
635 Status
= ((EFI_PEIM_ENTRY_POINT
) (UINTN
) DxeIplEntryPoint
) (DxeIplFileHeader
, GetPeiServicesTablePointer());
644 IN EFI_PEI_FV_FILE_LOADER_PPI
*This
,
645 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
646 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
647 OUT UINT64
*ImageSize
,
648 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
654 Given a pointer to an FFS file containing a PE32 image, get the
655 information on the PE32 image, and then "load" it so that it
660 This - pointer to our file loader protocol
662 FfsHeader - pointer to the FFS file header of the FFS file that
663 contains the PE32 image we want to load
665 ImageAddress - returned address where the PE32 image is loaded
667 ImageSize - returned size of the loaded PE32 image
669 EntryPoint - entry point to the loaded PE32 image
673 EFI_SUCCESS - The FFS file was successfully loaded.
675 EFI_ERROR - Unable to load the FFS file.
679 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
684 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
687 // Preprocess the FFS file to get a pointer to the PE32 information
688 // in the enclosed PE32 image.
690 Status
= PeiProcessFile (
696 if (EFI_ERROR (Status
)) {
700 // Load the PE image from the FFS file
702 Status
= PeiLoadFile (
703 PeiEfiPeiPeCoffLoader
,
715 IN UINT16 SectionType
,
716 IN OUT EFI_FFS_FILE_HEADER
**RealFfsFileHeader
,
725 SectionType - The type of section in the FFS file to process.
727 FfsFileHeader - Pointer to the FFS file to process, looking for the
728 specified SectionType
730 Pe32Data - returned pointer to the start of the PE32 image found
735 EFI_SUCCESS - found the PE32 section in the FFS file
741 DECOMPRESS_LIBRARY
*DecompressLibrary
;
743 UINT8
*ScratchBuffer
;
744 UINT32 DstBufferSize
;
745 UINT32 ScratchBufferSize
;
746 EFI_COMMON_SECTION_HEADER
*CmpSection
;
747 UINTN CmpSectionLength
;
748 UINTN OccupiedCmpSectionLength
;
751 EFI_COMMON_SECTION_HEADER
*Section
;
753 UINTN OccupiedSectionLength
;
755 EFI_GUID_DEFINED_SECTION
*GuidedSectionHeader
;
756 UINT32 AuthenticationStatus
;
757 EFI_PEI_SECTION_EXTRACTION_PPI
*SectionExtract
;
760 EFI_PEI_SECURITY_PPI
*Security
;
761 BOOLEAN StartCrisisRecovery
;
763 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
764 EFI_COMPRESSION_SECTION
*CompressionSection
;
765 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
767 FfsFileHeader
= *RealFfsFileHeader
;
769 Status
= PeiServicesFfsFindSectionData (
770 EFI_SECTION_COMPRESSION
,
776 // Upon finding a DXE Core file, see if there is first a compression section
778 if (!EFI_ERROR (Status
)) {
780 // Yes, there is a compression section, so extract the contents
781 // Decompress the image here
783 Section
= (EFI_COMMON_SECTION_HEADER
*) (UINTN
) (VOID
*) ((UINT8
*) (FfsFileHeader
) + (UINTN
) sizeof (EFI_FFS_FILE_HEADER
));
786 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
787 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
790 // Was the DXE Core file encapsulated in a GUID'd section?
792 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
794 // Locate the GUID'd Section Extractor
796 GuidedSectionHeader
= (VOID
*) (Section
+ 1);
799 // This following code constitutes the addition of the security model
803 // Set a default authenticatino state
805 AuthenticationStatus
= 0;
807 Status
= PeiServicesLocatePpi (
808 &gEfiPeiSectionExtractionPpiGuid
,
811 (VOID
**)&SectionExtract
814 if (EFI_ERROR (Status
)) {
818 // Verify Authentication State
820 CopyMem (&TempGuid
, Section
+ 1, sizeof (EFI_GUID
));
822 Status
= SectionExtract
->PeiGetSection (
823 GetPeiServicesTablePointer(),
825 (EFI_SECTION_TYPE
*) &SectionType
,
830 &AuthenticationStatus
833 if (EFI_ERROR (Status
)) {
837 // If not ask the Security PPI, if exists, for disposition
840 Status
= PeiServicesLocatePpi (
841 &gEfiPeiSecurityPpiGuid
,
846 if (EFI_ERROR (Status
)) {
850 Status
= Security
->AuthenticationState (
851 GetPeiServicesTablePointer(),
852 (struct _EFI_PEI_SECURITY_PPI
*) Security
,
853 AuthenticationStatus
,
858 if (EFI_ERROR (Status
)) {
862 // If there is a security violation, report to caller and have
863 // the upper-level logic possible engender a crisis recovery
865 if (StartCrisisRecovery
) {
866 return EFI_SECURITY_VIOLATION
;
870 if (Section
->Type
== EFI_SECTION_PE32
) {
872 // This is what we want
874 *Pe32Data
= (VOID
*) (Section
+ 1);
876 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
878 // This is a compression set, expand it
880 CompressionSection
= (EFI_COMPRESSION_SECTION
*) Section
;
882 switch (CompressionSection
->CompressionType
) {
883 case EFI_STANDARD_COMPRESSION
:
884 DecompressLibrary
= &gTianoDecompress
;
887 case EFI_CUSTOMIZED_COMPRESSION
:
889 // Load user customized compression protocol.
891 DecompressLibrary
= &gCustomDecompress
;
894 case EFI_NOT_COMPRESSED
:
897 // Need to support not compressed file
899 ASSERT_EFI_ERROR (Status
);
900 return EFI_NOT_FOUND
;
903 Status
= DecompressLibrary
->GetInfo (
904 (UINT8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
905 (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION
),
909 if (EFI_ERROR (Status
)) {
913 return EFI_NOT_FOUND
;
917 // Allocate scratch buffer
919 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
920 if (ScratchBuffer
== NULL
) {
921 return EFI_OUT_OF_RESOURCES
;
925 // Allocate destination buffer
927 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
928 if (DstBuffer
== NULL
) {
929 return EFI_OUT_OF_RESOURCES
;
933 // Call decompress function
935 Status
= DecompressLibrary
->Decompress (
936 (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
941 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) DstBuffer
;
942 if (CmpSection
->Type
== EFI_SECTION_RAW
) {
944 // Skip the section header and
945 // adjust the pointer alignment to 16
947 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (DstBuffer
+ 16);
949 if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
950 FfsFileHeader
= NULL
;
951 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
, FvHeader
->FvLength
);
952 Status
= PeiServicesFfsFindNextFile (
953 EFI_FV_FILETYPE_DXE_CORE
,
958 if (EFI_ERROR (Status
)) {
959 return EFI_NOT_FOUND
;
963 // Reture the FfsHeader that contain Pe32Data.
965 *RealFfsFileHeader
= FfsFileHeader
;
966 return PeiProcessFile (SectionType
, RealFfsFileHeader
, Pe32Data
);
970 // Decompress successfully.
971 // Loop the decompressed data searching for expected section.
973 CmpFileData
= (VOID
*) DstBuffer
;
974 CmpFileSize
= DstBufferSize
;
976 CmpSectionLength
= *(UINT32
*) (CmpSection
->Size
) & 0x00ffffff;
977 if (CmpSection
->Type
== EFI_SECTION_PE32
) {
979 // This is what we want
981 *Pe32Data
= (VOID
*) (CmpSection
+ 1);
985 OccupiedCmpSectionLength
= GetOccupiedSize (CmpSectionLength
, 4);
986 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) CmpSection
+ OccupiedCmpSectionLength
);
987 } while (CmpSection
->Type
!= 0 && (UINTN
) ((UINT8
*) CmpSection
- (UINT8
*) CmpFileData
) < CmpFileSize
);
990 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
991 FileSize
= FfsFileHeader
->Size
[0] & 0xFF;
992 FileSize
+= (FfsFileHeader
->Size
[1] << 8) & 0xFF00;
993 FileSize
+= (FfsFileHeader
->Size
[2] << 16) & 0xFF0000;
994 FileSize
&= 0x00FFFFFF;
995 } while (Section
->Type
!= 0 && (UINTN
) ((UINT8
*) Section
- (UINT8
*) FfsFileHeader
) < FileSize
);
998 // End of the decompression activity
1002 Status
= PeiServicesFfsFindSectionData (
1008 if (EFI_ERROR (Status
)) {
1009 Status
= PeiServicesFfsFindSectionData (
1014 if (EFI_ERROR (Status
)) {
1020 *Pe32Data
= SectionData
;