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
- sizeof (UINTN
));
265 // Add architecture-specifc HOBs (including the BspStore HOB)
267 Status
= CreateArchSpecificHobs (&BspStore
);
269 ASSERT_EFI_ERROR (Status
);
272 // Add HOB for the EFI Decompress Protocol
275 &gEfiDecompressProtocolGuid
,
276 (VOID
*)&gEfiDecompress
,
277 sizeof (gEfiDecompress
)
281 // Add HOB for the Tiano Decompress Protocol
284 &gEfiTianoDecompressProtocolGuid
,
285 (VOID
*)&gTianoDecompress
,
286 sizeof (gTianoDecompress
)
290 // Add HOB for the user customized Decompress Protocol
293 &gEfiCustomizedDecompressProtocolGuid
,
294 (VOID
*)&gCustomDecompress
,
295 sizeof (gCustomDecompress
)
299 // Add HOB for the PE/COFF Loader Protocol
302 &gEfiPeiPeCoffLoaderGuid
,
303 (VOID
*)&PeiEfiPeiPeCoffLoader
,
308 // See if we are in crisis recovery
310 Status
= PeiServicesGetBootMode (&BootMode
);
312 if (!EFI_ERROR (Status
) && (BootMode
== BOOT_IN_RECOVERY_MODE
)) {
314 Status
= PeiServicesLocatePpi (
315 &gEfiPeiRecoveryModulePpiGuid
,
318 (VOID
**)&PeiRecovery
321 ASSERT_EFI_ERROR (Status
);
322 Status
= PeiRecovery
->LoadRecoveryCapsule (PeiServices
, PeiRecovery
);
323 ASSERT_EFI_ERROR (Status
);
326 // Now should have a HOB with the DXE core w/ the old HOB destroyed
331 // Find the EFI_FV_FILETYPE_RAW type compressed Firmware Volume file in FTW spare block
332 // The file found will be processed by PeiProcessFile: It will first be decompressed to
333 // a normal FV, then a corresponding FV type hob will be built which is provided for DXE
334 // core to find and dispatch drivers in this FV. Because PeiProcessFile typically checks
335 // for EFI_FV_FILETYPE_DXE_CORE type file, in this condition we need not check returned
338 Status
= PeiFindFile (
346 // Find the DXE Core in a Firmware Volume
348 Status
= PeiFindFile (
349 EFI_FV_FILETYPE_DXE_CORE
,
355 ASSERT_EFI_ERROR (Status
);
358 // Load the DXE Core from a Firmware Volume
360 Status
= PeiLoadFile (
361 PeiEfiPeiPeCoffLoader
,
368 ASSERT_EFI_ERROR (Status
);
371 // Transfer control to the DXE Core
372 // The handoff state is simply a pointer to the HOB list
374 // PERF_END (PeiServices, L"DxeIpl", NULL, 0);
376 Status
= PeiServicesInstallPpi (&mPpiSignal
);
378 ASSERT_EFI_ERROR (Status
);
381 // Add HOB for the DXE Core
391 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
395 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
398 DEBUG ((EFI_D_INFO
, "DXE Core Entry\n"));
400 (SWITCH_STACK_ENTRY_POINT
)(UINTN
)DxeCoreEntryPoint
,
404 (VOID
*) (UINTN
) BspStore
408 // If we get here, then the DXE Core returned. This is an error
410 ASSERT_EFI_ERROR (Status
);
412 return EFI_OUT_OF_RESOURCES
;
418 IN UINT16 SectionType
,
419 OUT EFI_GUID
*FileName
,
426 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
427 described in the HOB list. Able to search in a compression set in a FFS file.
428 But only one level of compression is supported, that is, not able to search
429 in a compression set that is within another compression set.
433 Type - The Type of file to retrieve
435 SectionType - The type of section to retrieve from a file
437 FileName - The name of the file found in the Firmware Volume
439 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
443 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
444 the PE/COFF image is returned in Pe32Data
446 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
450 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
451 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
454 EFI_PEI_HOB_POINTERS Hob
;
458 FfsFileHeader
= NULL
;
462 // Foreach Firmware Volume, look for a specified type
463 // of file and break out when one is found
465 Hob
.Raw
= GetHobList ();
466 while ((Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
)) != NULL
) {
467 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (Hob
.FirmwareVolume
->BaseAddress
);
468 Status
= PeiServicesFfsFindNextFile (
473 if (!EFI_ERROR (Status
)) {
474 Status
= PeiProcessFile (
479 CopyMem (FileName
, &FfsFileHeader
->Name
, sizeof (EFI_GUID
));
482 Hob
.Raw
= GET_NEXT_HOB (Hob
);
484 return EFI_NOT_FOUND
;
489 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
,
491 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
492 OUT UINT64
*ImageSize
,
493 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
499 Loads and relocates a PE/COFF image into memory.
503 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
505 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
507 ImageAddress - The base address of the relocated PE/COFF image
509 ImageSize - The size of the relocated PE/COFF image
511 EntryPoint - The entry point of the relocated PE/COFF image
515 EFI_SUCCESS - The file was loaded and relocated
517 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
522 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
524 ZeroMem (&ImageContext
, sizeof (ImageContext
));
525 ImageContext
.Handle
= Pe32Data
;
526 Status
= GetImageReadFunction (&ImageContext
);
528 ASSERT_EFI_ERROR (Status
);
530 Status
= PeiEfiPeiPeCoffLoader
->GetImageInfo (PeiEfiPeiPeCoffLoader
, &ImageContext
);
531 if (EFI_ERROR (Status
)) {
535 // Allocate Memory for the image
537 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
));
538 ASSERT (ImageContext
.ImageAddress
!= 0);
541 // Load the image to our new buffer
543 Status
= PeiEfiPeiPeCoffLoader
->LoadImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
544 if (EFI_ERROR (Status
)) {
548 // Relocate the image in our new buffer
550 Status
= PeiEfiPeiPeCoffLoader
->RelocateImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
551 if (EFI_ERROR (Status
)) {
556 // Flush the instruction cache so the image data is written before we execute it
558 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
560 *ImageAddress
= ImageContext
.ImageAddress
;
561 *ImageSize
= ImageContext
.ImageSize
;
562 *EntryPoint
= ImageContext
.EntryPoint
;
569 IN EFI_FFS_FILE_HEADER
*DxeIplFileHeader
,
570 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
576 Shadow the DXE IPL to a different memory location. This occurs after permanent
577 memory has been discovered.
581 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
583 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
587 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
589 EFI_ ERROR - The shadow was unsuccessful.
595 UINTN OccupiedSectionLength
;
596 EFI_PHYSICAL_ADDRESS DxeIplAddress
;
598 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint
;
600 EFI_COMMON_SECTION_HEADER
*Section
;
602 Section
= (EFI_COMMON_SECTION_HEADER
*) (DxeIplFileHeader
+ 1);
604 while ((Section
->Type
!= EFI_SECTION_PE32
) && (Section
->Type
!= EFI_SECTION_TE
)) {
605 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
606 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
607 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
610 // Relocate DxeIpl into memory by using loadfile service
612 Status
= PeiLoadFile (
613 PeiEfiPeiPeCoffLoader
,
614 (VOID
*) (Section
+ 1),
620 if (Status
== EFI_SUCCESS
) {
622 // Install PeiInMemory to indicate the Dxeipl is shadowed
624 Status
= PeiServicesInstallPpi (&mPpiPeiInMemory
);
626 if (EFI_ERROR (Status
)) {
630 Status
= ((EFI_PEIM_ENTRY_POINT
) (UINTN
) DxeIplEntryPoint
) (DxeIplFileHeader
, GetPeiServicesTablePointer());
639 IN EFI_PEI_FV_FILE_LOADER_PPI
*This
,
640 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
641 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
642 OUT UINT64
*ImageSize
,
643 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
649 Given a pointer to an FFS file containing a PE32 image, get the
650 information on the PE32 image, and then "load" it so that it
655 This - pointer to our file loader protocol
657 FfsHeader - pointer to the FFS file header of the FFS file that
658 contains the PE32 image we want to load
660 ImageAddress - returned address where the PE32 image is loaded
662 ImageSize - returned size of the loaded PE32 image
664 EntryPoint - entry point to the loaded PE32 image
668 EFI_SUCCESS - The FFS file was successfully loaded.
670 EFI_ERROR - Unable to load the FFS file.
674 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
679 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
682 // Preprocess the FFS file to get a pointer to the PE32 information
683 // in the enclosed PE32 image.
685 Status
= PeiProcessFile (
691 if (EFI_ERROR (Status
)) {
695 // Load the PE image from the FFS file
697 Status
= PeiLoadFile (
698 PeiEfiPeiPeCoffLoader
,
710 IN UINT16 SectionType
,
711 IN OUT EFI_FFS_FILE_HEADER
**RealFfsFileHeader
,
720 SectionType - The type of section in the FFS file to process.
722 FfsFileHeader - Pointer to the FFS file to process, looking for the
723 specified SectionType
725 Pe32Data - returned pointer to the start of the PE32 image found
730 EFI_SUCCESS - found the PE32 section in the FFS file
736 DECOMPRESS_LIBRARY
*DecompressLibrary
;
738 UINT8
*ScratchBuffer
;
739 UINT32 DstBufferSize
;
740 UINT32 ScratchBufferSize
;
741 EFI_COMMON_SECTION_HEADER
*CmpSection
;
742 UINTN CmpSectionLength
;
743 UINTN OccupiedCmpSectionLength
;
746 EFI_COMMON_SECTION_HEADER
*Section
;
748 UINTN OccupiedSectionLength
;
750 EFI_GUID_DEFINED_SECTION
*GuidedSectionHeader
;
751 UINT32 AuthenticationStatus
;
752 EFI_PEI_SECTION_EXTRACTION_PPI
*SectionExtract
;
755 EFI_PEI_SECURITY_PPI
*Security
;
756 BOOLEAN StartCrisisRecovery
;
758 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
759 EFI_COMPRESSION_SECTION
*CompressionSection
;
760 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
762 FfsFileHeader
= *RealFfsFileHeader
;
764 Status
= PeiServicesFfsFindSectionData (
765 EFI_SECTION_COMPRESSION
,
771 // Upon finding a DXE Core file, see if there is first a compression section
773 if (!EFI_ERROR (Status
)) {
775 // Yes, there is a compression section, so extract the contents
776 // Decompress the image here
778 Section
= (EFI_COMMON_SECTION_HEADER
*) (UINTN
) (VOID
*) ((UINT8
*) (FfsFileHeader
) + (UINTN
) sizeof (EFI_FFS_FILE_HEADER
));
781 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
782 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
785 // Was the DXE Core file encapsulated in a GUID'd section?
787 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
789 // Locate the GUID'd Section Extractor
791 GuidedSectionHeader
= (VOID
*) (Section
+ 1);
794 // This following code constitutes the addition of the security model
798 // Set a default authenticatino state
800 AuthenticationStatus
= 0;
802 Status
= PeiServicesLocatePpi (
803 &gEfiPeiSectionExtractionPpiGuid
,
806 (VOID
**)&SectionExtract
809 if (EFI_ERROR (Status
)) {
813 // Verify Authentication State
815 CopyMem (&TempGuid
, Section
+ 1, sizeof (EFI_GUID
));
817 Status
= SectionExtract
->PeiGetSection (
818 GetPeiServicesTablePointer(),
820 (EFI_SECTION_TYPE
*) &SectionType
,
825 &AuthenticationStatus
828 if (EFI_ERROR (Status
)) {
832 // If not ask the Security PPI, if exists, for disposition
835 Status
= PeiServicesLocatePpi (
836 &gEfiPeiSecurityPpiGuid
,
841 if (EFI_ERROR (Status
)) {
845 Status
= Security
->AuthenticationState (
846 GetPeiServicesTablePointer(),
847 (struct _EFI_PEI_SECURITY_PPI
*) Security
,
848 AuthenticationStatus
,
853 if (EFI_ERROR (Status
)) {
857 // If there is a security violation, report to caller and have
858 // the upper-level logic possible engender a crisis recovery
860 if (StartCrisisRecovery
) {
861 return EFI_SECURITY_VIOLATION
;
865 if (Section
->Type
== EFI_SECTION_PE32
) {
867 // This is what we want
869 *Pe32Data
= (VOID
*) (Section
+ 1);
871 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
873 // This is a compression set, expand it
875 CompressionSection
= (EFI_COMPRESSION_SECTION
*) Section
;
877 switch (CompressionSection
->CompressionType
) {
878 case EFI_STANDARD_COMPRESSION
:
879 DecompressLibrary
= &gTianoDecompress
;
882 case EFI_CUSTOMIZED_COMPRESSION
:
884 // Load user customized compression protocol.
886 DecompressLibrary
= &gCustomDecompress
;
889 case EFI_NOT_COMPRESSED
:
892 // Need to support not compressed file
894 ASSERT_EFI_ERROR (Status
);
895 return EFI_NOT_FOUND
;
898 Status
= DecompressLibrary
->GetInfo (
899 (UINT8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
900 (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION
),
904 if (EFI_ERROR (Status
)) {
908 return EFI_NOT_FOUND
;
912 // Allocate scratch buffer
914 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
915 if (ScratchBuffer
== NULL
) {
916 return EFI_OUT_OF_RESOURCES
;
920 // Allocate destination buffer
922 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
923 if (DstBuffer
== NULL
) {
924 return EFI_OUT_OF_RESOURCES
;
928 // Call decompress function
930 Status
= DecompressLibrary
->Decompress (
931 (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
936 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) DstBuffer
;
937 if (CmpSection
->Type
== EFI_SECTION_RAW
) {
939 // Skip the section header and
940 // adjust the pointer alignment to 16
942 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (DstBuffer
+ 16);
944 if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
945 FfsFileHeader
= NULL
;
946 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
, FvHeader
->FvLength
);
947 Status
= PeiServicesFfsFindNextFile (
948 EFI_FV_FILETYPE_DXE_CORE
,
953 if (EFI_ERROR (Status
)) {
954 return EFI_NOT_FOUND
;
958 // Reture the FfsHeader that contain Pe32Data.
960 *RealFfsFileHeader
= FfsFileHeader
;
961 return PeiProcessFile (SectionType
, RealFfsFileHeader
, Pe32Data
);
965 // Decompress successfully.
966 // Loop the decompressed data searching for expected section.
968 CmpFileData
= (VOID
*) DstBuffer
;
969 CmpFileSize
= DstBufferSize
;
971 CmpSectionLength
= *(UINT32
*) (CmpSection
->Size
) & 0x00ffffff;
972 if (CmpSection
->Type
== EFI_SECTION_PE32
) {
974 // This is what we want
976 *Pe32Data
= (VOID
*) (CmpSection
+ 1);
980 OccupiedCmpSectionLength
= GetOccupiedSize (CmpSectionLength
, 4);
981 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) CmpSection
+ OccupiedCmpSectionLength
);
982 } while (CmpSection
->Type
!= 0 && (UINTN
) ((UINT8
*) CmpSection
- (UINT8
*) CmpFileData
) < CmpFileSize
);
985 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
986 FileSize
= FfsFileHeader
->Size
[0] & 0xFF;
987 FileSize
+= (FfsFileHeader
->Size
[1] << 8) & 0xFF00;
988 FileSize
+= (FfsFileHeader
->Size
[2] << 16) & 0xFF0000;
989 FileSize
&= 0x00FFFFFF;
990 } while (Section
->Type
!= 0 && (UINTN
) ((UINT8
*) Section
- (UINT8
*) FfsFileHeader
) < FileSize
);
993 // End of the decompression activity
997 Status
= PeiServicesFfsFindSectionData (
1003 if (EFI_ERROR (Status
)) {
1004 Status
= PeiServicesFfsFindSectionData (
1009 if (EFI_ERROR (Status
)) {
1015 *Pe32Data
= SectionData
;