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
,
402 (VOID
*) (UINTN
) BspStore
,
407 // If we get here, then the DXE Core returned. This is an error
409 ASSERT_EFI_ERROR (Status
);
411 return EFI_OUT_OF_RESOURCES
;
417 IN UINT16 SectionType
,
418 OUT EFI_GUID
*FileName
,
425 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
426 described in the HOB list. Able to search in a compression set in a FFS file.
427 But only one level of compression is supported, that is, not able to search
428 in a compression set that is within another compression set.
432 Type - The Type of file to retrieve
434 SectionType - The type of section to retrieve from a file
436 FileName - The name of the file found in the Firmware Volume
438 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
442 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
443 the PE/COFF image is returned in Pe32Data
445 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
449 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
450 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
453 EFI_PEI_HOB_POINTERS Hob
;
457 FfsFileHeader
= NULL
;
461 // Foreach Firmware Volume, look for a specified type
462 // of file and break out when one is found
464 Hob
.Raw
= GetHobList ();
465 while ((Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
)) != NULL
) {
466 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (Hob
.FirmwareVolume
->BaseAddress
);
467 Status
= PeiServicesFfsFindNextFile (
472 if (!EFI_ERROR (Status
)) {
473 Status
= PeiProcessFile (
478 CopyMem (FileName
, &FfsFileHeader
->Name
, sizeof (EFI_GUID
));
481 Hob
.Raw
= GET_NEXT_HOB (Hob
);
483 return EFI_NOT_FOUND
;
488 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
,
490 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
491 OUT UINT64
*ImageSize
,
492 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
498 Loads and relocates a PE/COFF image into memory.
502 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
504 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
506 ImageAddress - The base address of the relocated PE/COFF image
508 ImageSize - The size of the relocated PE/COFF image
510 EntryPoint - The entry point of the relocated PE/COFF image
514 EFI_SUCCESS - The file was loaded and relocated
516 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
521 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
523 ZeroMem (&ImageContext
, sizeof (ImageContext
));
524 ImageContext
.Handle
= Pe32Data
;
525 Status
= GetImageReadFunction (&ImageContext
);
527 ASSERT_EFI_ERROR (Status
);
529 Status
= PeiEfiPeiPeCoffLoader
->GetImageInfo (PeiEfiPeiPeCoffLoader
, &ImageContext
);
530 if (EFI_ERROR (Status
)) {
534 // Allocate Memory for the image
536 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
));
537 ASSERT (ImageContext
.ImageAddress
!= 0);
540 // Load the image to our new buffer
542 Status
= PeiEfiPeiPeCoffLoader
->LoadImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
543 if (EFI_ERROR (Status
)) {
547 // Relocate the image in our new buffer
549 Status
= PeiEfiPeiPeCoffLoader
->RelocateImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
550 if (EFI_ERROR (Status
)) {
555 // Flush the instruction cache so the image data is written before we execute it
557 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
559 *ImageAddress
= ImageContext
.ImageAddress
;
560 *ImageSize
= ImageContext
.ImageSize
;
561 *EntryPoint
= ImageContext
.EntryPoint
;
568 IN EFI_FFS_FILE_HEADER
*DxeIplFileHeader
,
569 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
575 Shadow the DXE IPL to a different memory location. This occurs after permanent
576 memory has been discovered.
580 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
582 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
586 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
588 EFI_ ERROR - The shadow was unsuccessful.
594 UINTN OccupiedSectionLength
;
595 EFI_PHYSICAL_ADDRESS DxeIplAddress
;
597 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint
;
599 EFI_COMMON_SECTION_HEADER
*Section
;
601 Section
= (EFI_COMMON_SECTION_HEADER
*) (DxeIplFileHeader
+ 1);
603 while ((Section
->Type
!= EFI_SECTION_PE32
) && (Section
->Type
!= EFI_SECTION_TE
)) {
604 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
605 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
606 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
609 // Relocate DxeIpl into memory by using loadfile service
611 Status
= PeiLoadFile (
612 PeiEfiPeiPeCoffLoader
,
613 (VOID
*) (Section
+ 1),
619 if (Status
== EFI_SUCCESS
) {
621 // Install PeiInMemory to indicate the Dxeipl is shadowed
623 Status
= PeiServicesInstallPpi (&mPpiPeiInMemory
);
625 if (EFI_ERROR (Status
)) {
629 Status
= ((EFI_PEIM_ENTRY_POINT
) (UINTN
) DxeIplEntryPoint
) (DxeIplFileHeader
, GetPeiServicesTablePointer());
638 IN EFI_PEI_FV_FILE_LOADER_PPI
*This
,
639 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
640 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
641 OUT UINT64
*ImageSize
,
642 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
648 Given a pointer to an FFS file containing a PE32 image, get the
649 information on the PE32 image, and then "load" it so that it
654 This - pointer to our file loader protocol
656 FfsHeader - pointer to the FFS file header of the FFS file that
657 contains the PE32 image we want to load
659 ImageAddress - returned address where the PE32 image is loaded
661 ImageSize - returned size of the loaded PE32 image
663 EntryPoint - entry point to the loaded PE32 image
667 EFI_SUCCESS - The FFS file was successfully loaded.
669 EFI_ERROR - Unable to load the FFS file.
673 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
678 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
681 // Preprocess the FFS file to get a pointer to the PE32 information
682 // in the enclosed PE32 image.
684 Status
= PeiProcessFile (
690 if (EFI_ERROR (Status
)) {
694 // Load the PE image from the FFS file
696 Status
= PeiLoadFile (
697 PeiEfiPeiPeCoffLoader
,
709 IN UINT16 SectionType
,
710 IN OUT EFI_FFS_FILE_HEADER
**RealFfsFileHeader
,
719 SectionType - The type of section in the FFS file to process.
721 FfsFileHeader - Pointer to the FFS file to process, looking for the
722 specified SectionType
724 Pe32Data - returned pointer to the start of the PE32 image found
729 EFI_SUCCESS - found the PE32 section in the FFS file
735 DECOMPRESS_LIBRARY
*DecompressLibrary
;
737 UINT8
*ScratchBuffer
;
738 UINT32 DstBufferSize
;
739 UINT32 ScratchBufferSize
;
740 EFI_COMMON_SECTION_HEADER
*CmpSection
;
741 UINTN CmpSectionLength
;
742 UINTN OccupiedCmpSectionLength
;
745 EFI_COMMON_SECTION_HEADER
*Section
;
747 UINTN OccupiedSectionLength
;
749 EFI_GUID_DEFINED_SECTION
*GuidedSectionHeader
;
750 UINT32 AuthenticationStatus
;
751 EFI_PEI_SECTION_EXTRACTION_PPI
*SectionExtract
;
754 EFI_PEI_SECURITY_PPI
*Security
;
755 BOOLEAN StartCrisisRecovery
;
757 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
758 EFI_COMPRESSION_SECTION
*CompressionSection
;
759 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
761 FfsFileHeader
= *RealFfsFileHeader
;
763 Status
= PeiServicesFfsFindSectionData (
764 EFI_SECTION_COMPRESSION
,
770 // Upon finding a DXE Core file, see if there is first a compression section
772 if (!EFI_ERROR (Status
)) {
774 // Yes, there is a compression section, so extract the contents
775 // Decompress the image here
777 Section
= (EFI_COMMON_SECTION_HEADER
*) (UINTN
) (VOID
*) ((UINT8
*) (FfsFileHeader
) + (UINTN
) sizeof (EFI_FFS_FILE_HEADER
));
780 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
781 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
784 // Was the DXE Core file encapsulated in a GUID'd section?
786 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
788 // Locate the GUID'd Section Extractor
790 GuidedSectionHeader
= (VOID
*) (Section
+ 1);
793 // This following code constitutes the addition of the security model
797 // Set a default authenticatino state
799 AuthenticationStatus
= 0;
801 Status
= PeiServicesLocatePpi (
802 &gEfiPeiSectionExtractionPpiGuid
,
805 (VOID
**)&SectionExtract
808 if (EFI_ERROR (Status
)) {
812 // Verify Authentication State
814 CopyMem (&TempGuid
, Section
+ 1, sizeof (EFI_GUID
));
816 Status
= SectionExtract
->PeiGetSection (
817 GetPeiServicesTablePointer(),
819 (EFI_SECTION_TYPE
*) &SectionType
,
824 &AuthenticationStatus
827 if (EFI_ERROR (Status
)) {
831 // If not ask the Security PPI, if exists, for disposition
834 Status
= PeiServicesLocatePpi (
835 &gEfiPeiSecurityPpiGuid
,
840 if (EFI_ERROR (Status
)) {
844 Status
= Security
->AuthenticationState (
845 GetPeiServicesTablePointer(),
846 (struct _EFI_PEI_SECURITY_PPI
*) Security
,
847 AuthenticationStatus
,
852 if (EFI_ERROR (Status
)) {
856 // If there is a security violation, report to caller and have
857 // the upper-level logic possible engender a crisis recovery
859 if (StartCrisisRecovery
) {
860 return EFI_SECURITY_VIOLATION
;
864 if (Section
->Type
== EFI_SECTION_PE32
) {
866 // This is what we want
868 *Pe32Data
= (VOID
*) (Section
+ 1);
870 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
872 // This is a compression set, expand it
874 CompressionSection
= (EFI_COMPRESSION_SECTION
*) Section
;
876 switch (CompressionSection
->CompressionType
) {
877 case EFI_STANDARD_COMPRESSION
:
878 DecompressLibrary
= &gTianoDecompress
;
881 case EFI_CUSTOMIZED_COMPRESSION
:
883 // Load user customized compression protocol.
885 DecompressLibrary
= &gCustomDecompress
;
888 case EFI_NOT_COMPRESSED
:
891 // Need to support not compressed file
893 ASSERT_EFI_ERROR (Status
);
894 return EFI_NOT_FOUND
;
897 Status
= DecompressLibrary
->GetInfo (
898 (UINT8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
899 (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION
),
903 if (EFI_ERROR (Status
)) {
907 return EFI_NOT_FOUND
;
911 // Allocate scratch buffer
913 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
914 if (ScratchBuffer
== NULL
) {
915 return EFI_OUT_OF_RESOURCES
;
919 // Allocate destination buffer
921 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
922 if (DstBuffer
== NULL
) {
923 return EFI_OUT_OF_RESOURCES
;
927 // Call decompress function
929 Status
= DecompressLibrary
->Decompress (
930 (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
935 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) DstBuffer
;
936 if (CmpSection
->Type
== EFI_SECTION_RAW
) {
938 // Skip the section header and
939 // adjust the pointer alignment to 16
941 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (DstBuffer
+ 16);
943 if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
944 FfsFileHeader
= NULL
;
945 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
, FvHeader
->FvLength
);
946 Status
= PeiServicesFfsFindNextFile (
947 EFI_FV_FILETYPE_DXE_CORE
,
952 if (EFI_ERROR (Status
)) {
953 return EFI_NOT_FOUND
;
957 // Reture the FfsHeader that contain Pe32Data.
959 *RealFfsFileHeader
= FfsFileHeader
;
960 return PeiProcessFile (SectionType
, RealFfsFileHeader
, Pe32Data
);
964 // Decompress successfully.
965 // Loop the decompressed data searching for expected section.
967 CmpFileData
= (VOID
*) DstBuffer
;
968 CmpFileSize
= DstBufferSize
;
970 CmpSectionLength
= *(UINT32
*) (CmpSection
->Size
) & 0x00ffffff;
971 if (CmpSection
->Type
== EFI_SECTION_PE32
) {
973 // This is what we want
975 *Pe32Data
= (VOID
*) (CmpSection
+ 1);
979 OccupiedCmpSectionLength
= GetOccupiedSize (CmpSectionLength
, 4);
980 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) CmpSection
+ OccupiedCmpSectionLength
);
981 } while (CmpSection
->Type
!= 0 && (UINTN
) ((UINT8
*) CmpSection
- (UINT8
*) CmpFileData
) < CmpFileSize
);
984 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
985 FileSize
= FfsFileHeader
->Size
[0] & 0xFF;
986 FileSize
+= (FfsFileHeader
->Size
[1] << 8) & 0xFF00;
987 FileSize
+= (FfsFileHeader
->Size
[2] << 16) & 0xFF0000;
988 FileSize
&= 0x00FFFFFF;
989 } while (Section
->Type
!= 0 && (UINTN
) ((UINT8
*) Section
- (UINT8
*) FfsFileHeader
) < FileSize
);
992 // End of the decompression activity
996 Status
= PeiServicesFfsFindSectionData (
1002 if (EFI_ERROR (Status
)) {
1003 Status
= PeiServicesFfsFindSectionData (
1008 if (EFI_ERROR (Status
)) {
1014 *Pe32Data
= SectionData
;