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 mPpiList
[] = {
41 EFI_PEI_PPI_DESCRIPTOR_PPI
,
42 &gEfiPeiFvFileLoaderPpiGuid
,
46 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
52 static EFI_PEI_PPI_DESCRIPTOR mPpiSignal
= {
53 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
54 &gEfiEndOfPeiSignalPpiGuid
,
58 GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gEfiDecompress
= {
59 UefiDecompressGetInfo
,
63 GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gTianoDecompress
= {
64 TianoDecompressGetInfo
,
68 GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gCustomDecompress
= {
69 CustomDecompressGetInfo
,
75 PeimInitializeDxeIpl (
76 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
77 IN EFI_PEI_SERVICES
**PeiServices
83 Initializes the Dxe Ipl PPI
87 FfsHeader - Pointer to FFS file header
88 PeiServices - General purpose services available to every PEIM.
97 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
98 EFI_BOOT_MODE BootMode
;
100 Status
= PeiServicesGetBootMode (&BootMode
);
101 ASSERT_EFI_ERROR (Status
);
103 if (!gInMemory
&& (BootMode
!= BOOT_ON_S3_RESUME
)) {
105 // The DxeIpl has not yet been shadowed
107 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
110 // Shadow DxeIpl and then re-run its entry point
112 Status
= ShadowDxeIpl (FfsHeader
, PeiEfiPeiPeCoffLoader
);
115 // Install FvFileLoader and DxeIpl PPIs.
117 Status
= PeiServicesInstallPpi (mPpiList
);
118 ASSERT_EFI_ERROR(Status
);
127 IN EFI_DXE_IPL_PPI
*This
,
128 IN EFI_PEI_SERVICES
**PeiServices
,
129 IN EFI_PEI_HOB_POINTERS HobList
135 Main entry point to last PEIM
138 This - Entry point for DXE IPL PPI
139 PeiServices - General purpose services available to every PEIM.
140 HobList - Address to the Pei HOB list
144 EFI_SUCCESS - DEX core was successfully loaded.
145 EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core.
150 EFI_GUID DxeCoreFileName
;
151 EFI_GUID FirmwareFileName
;
154 EFI_PHYSICAL_ADDRESS DxeCoreAddress
;
156 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
;
157 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
158 EFI_BOOT_MODE BootMode
;
159 EFI_PEI_RECOVERY_MODULE_PPI
*PeiRecovery
;
160 EFI_PEI_S3_RESUME_PPI
*S3Resume
;
162 // PERF_START (PeiServices, L"DxeIpl", NULL, 0);
165 // if in S3 Resume, restore configure
167 Status
= PeiServicesGetBootMode (&BootMode
);
168 ASSERT_EFI_ERROR(Status
);
170 if (BootMode
== BOOT_ON_S3_RESUME
) {
171 Status
= PeiServicesLocatePpi (
172 &gEfiPeiS3ResumePpiGuid
,
177 ASSERT_EFI_ERROR (Status
);
179 Status
= S3Resume
->S3RestoreConfig (PeiServices
);
180 ASSERT_EFI_ERROR (Status
);
181 } else if (BootMode
== BOOT_IN_RECOVERY_MODE
) {
183 Status
= PeiServicesLocatePpi (
184 &gEfiPeiRecoveryModulePpiGuid
,
187 (VOID
**)&PeiRecovery
189 ASSERT_EFI_ERROR (Status
);
191 Status
= PeiRecovery
->LoadRecoveryCapsule (PeiServices
, PeiRecovery
);
192 if (EFI_ERROR (Status
)) {
193 DEBUG ((EFI_D_ERROR
, "Load Recovery Capsule Failed.(Status = %r)\n", Status
));
198 // Now should have a HOB with the DXE core w/ the old HOB destroyed
203 // Install the PEI Protocols that are shared between PEI and DXE
205 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
206 ASSERT (PeiEfiPeiPeCoffLoader
!= NULL
);
210 // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file
211 // The file found will be processed by PeiProcessFile: It will first be decompressed to
212 // a normal FV, then a corresponding FV type hob will be built.
214 Status
= PeiFindFile (
215 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
216 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
222 // Find the DXE Core in a Firmware Volume
224 Status
= PeiFindFile (
225 EFI_FV_FILETYPE_DXE_CORE
,
230 ASSERT_EFI_ERROR (Status
);
233 // Load the DXE Core from a Firmware Volume
235 Status
= PeiLoadFile (
236 PeiEfiPeiPeCoffLoader
,
242 ASSERT_EFI_ERROR (Status
);
245 // Transfer control to the DXE Core
246 // The handoff state is simply a pointer to the HOB list
249 Status
= PeiServicesInstallPpi (&mPpiSignal
);
250 ASSERT_EFI_ERROR (Status
);
253 // Add HOB for the DXE Core
263 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
267 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
270 if (FeaturePcdGet (PcdDxeIplBuildShareCodeHobs
)) {
271 if (FeaturePcdGet (PcdDxeIplSupportEfiDecompress
)) {
273 // Add HOB for the EFI Decompress Protocol
276 &gEfiDecompressProtocolGuid
,
277 (VOID
*)&gEfiDecompress
,
278 sizeof (gEfiDecompress
)
281 if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress
)) {
283 // Add HOB for the Tiano Decompress Protocol
286 &gEfiTianoDecompressProtocolGuid
,
287 (VOID
*)&gTianoDecompress
,
288 sizeof (gTianoDecompress
)
291 if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress
)) {
293 // Add HOB for the user customized Decompress Protocol
296 &gEfiCustomizedDecompressProtocolGuid
,
297 (VOID
*)&gCustomDecompress
,
298 sizeof (gCustomDecompress
)
303 // Add HOB for the PE/COFF Loader Protocol
306 &gEfiPeiPeCoffLoaderGuid
,
307 (VOID
*)&PeiEfiPeiPeCoffLoader
,
312 DEBUG ((EFI_D_INFO
, "DXE Core Entry Point 0x%08x\n", (UINTN
) DxeCoreEntryPoint
));
313 HandOffToDxeCore (DxeCoreEntryPoint
, HobList
);
315 // If we get here, then the DXE Core returned. This is an error
316 // Dxe Core should not return.
321 return EFI_OUT_OF_RESOURCES
;
327 IN UINT16 SectionType
,
328 OUT EFI_GUID
*FileName
,
335 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
336 described in the HOB list. Able to search in a compression set in a FFS file.
337 But only one level of compression is supported, that is, not able to search
338 in a compression set that is within another compression set.
342 Type - The Type of file to retrieve
344 SectionType - The type of section to retrieve from a file
346 FileName - The name of the file found in the Firmware Volume
348 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
352 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
353 the PE/COFF image is returned in Pe32Data
355 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
359 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
360 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
363 EFI_PEI_HOB_POINTERS Hob
;
367 FfsFileHeader
= NULL
;
369 Status
= EFI_SUCCESS
;
372 // For each Firmware Volume, look for a specified type
373 // of file and break out until no one is found
375 Hob
.Raw
= GetHobList ();
376 while ((Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
)) != NULL
) {
377 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (Hob
.FirmwareVolume
->BaseAddress
);
378 Status
= PeiServicesFfsFindNextFile (
383 if (!EFI_ERROR (Status
)) {
384 Status
= PeiProcessFile (
390 CopyMem (FileName
, &FfsFileHeader
->Name
, sizeof (EFI_GUID
));
391 if (!EFI_ERROR (Status
)) {
395 Hob
.Raw
= GET_NEXT_HOB (Hob
);
397 return EFI_NOT_FOUND
;
402 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
,
404 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
405 OUT UINT64
*ImageSize
,
406 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
412 Loads and relocates a PE/COFF image into memory.
416 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
418 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
420 ImageAddress - The base address of the relocated PE/COFF image
422 ImageSize - The size of the relocated PE/COFF image
424 EntryPoint - The entry point of the relocated PE/COFF image
428 EFI_SUCCESS - The file was loaded and relocated
430 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
435 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
437 ZeroMem (&ImageContext
, sizeof (ImageContext
));
438 ImageContext
.Handle
= Pe32Data
;
439 Status
= GetImageReadFunction (&ImageContext
);
441 ASSERT_EFI_ERROR (Status
);
443 Status
= PeiEfiPeiPeCoffLoader
->GetImageInfo (PeiEfiPeiPeCoffLoader
, &ImageContext
);
444 if (EFI_ERROR (Status
)) {
448 // Allocate Memory for the image
450 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
));
451 ASSERT (ImageContext
.ImageAddress
!= 0);
454 // Load the image to our new buffer
456 Status
= PeiEfiPeiPeCoffLoader
->LoadImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
457 if (EFI_ERROR (Status
)) {
461 // Relocate the image in our new buffer
463 Status
= PeiEfiPeiPeCoffLoader
->RelocateImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
464 if (EFI_ERROR (Status
)) {
469 // Flush the instruction cache so the image data is written before we execute it
471 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
473 *ImageAddress
= ImageContext
.ImageAddress
;
474 *ImageSize
= ImageContext
.ImageSize
;
475 *EntryPoint
= ImageContext
.EntryPoint
;
482 IN EFI_FFS_FILE_HEADER
*DxeIplFileHeader
,
483 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
489 Shadow the DXE IPL to a different memory location. This occurs after permanent
490 memory has been discovered.
494 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
496 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
500 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
502 EFI_ ERROR - The shadow was unsuccessful.
508 UINTN OccupiedSectionLength
;
509 EFI_PHYSICAL_ADDRESS DxeIplAddress
;
511 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint
;
513 EFI_COMMON_SECTION_HEADER
*Section
;
515 Section
= (EFI_COMMON_SECTION_HEADER
*) (DxeIplFileHeader
+ 1);
517 while ((Section
->Type
!= EFI_SECTION_PE32
) && (Section
->Type
!= EFI_SECTION_TE
)) {
518 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
519 OccupiedSectionLength
= GET_OCCUPIED_SIZE (SectionLength
, 4);
520 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
523 // Relocate DxeIpl into memory by using loadfile service
525 Status
= PeiLoadFile (
526 PeiEfiPeiPeCoffLoader
,
527 (VOID
*) (Section
+ 1),
533 if (Status
== EFI_SUCCESS
) {
535 // Set gInMemory global variable to TRUE to indicate the dxeipl is shadowed.
537 *(BOOLEAN
*) ((UINTN
) &gInMemory
+ (UINTN
) DxeIplEntryPoint
- (UINTN
) _ModuleEntryPoint
) = TRUE
;
538 Status
= ((EFI_PEIM_ENTRY_POINT
) (UINTN
) DxeIplEntryPoint
) (DxeIplFileHeader
, GetPeiServicesTablePointer());
547 IN EFI_PEI_FV_FILE_LOADER_PPI
*This
,
548 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
549 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
550 OUT UINT64
*ImageSize
,
551 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
557 Given a pointer to an FFS file containing a PE32 image, get the
558 information on the PE32 image, and then "load" it so that it
563 This - pointer to our file loader protocol
565 FfsHeader - pointer to the FFS file header of the FFS file that
566 contains the PE32 image we want to load
568 ImageAddress - returned address where the PE32 image is loaded
570 ImageSize - returned size of the loaded PE32 image
572 EntryPoint - entry point to the loaded PE32 image
576 EFI_SUCCESS - The FFS file was successfully loaded.
578 EFI_ERROR - Unable to load the FFS file.
582 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
587 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
590 // Preprocess the FFS file to get a pointer to the PE32 information
591 // in the enclosed PE32 image.
593 Status
= PeiProcessFile (
600 if (EFI_ERROR (Status
)) {
604 // Load the PE image from the FFS file
606 Status
= PeiLoadFile (
607 PeiEfiPeiPeCoffLoader
,
619 IN UINT16 SectionType
,
620 IN EFI_FFS_FILE_HEADER
*FfsFileHeader
,
622 IN EFI_PEI_HOB_POINTERS
*OrigHob
630 SectionType - The type of section in the FFS file to process.
632 FfsFileHeader - Pointer to the FFS file to process, looking for the
633 specified SectionType
635 Pe32Data - returned pointer to the start of the PE32 image found
640 EFI_SUCCESS - found the PE32 section in the FFS file
646 DECOMPRESS_LIBRARY
*DecompressLibrary
;
648 UINT8
*ScratchBuffer
;
649 UINT32 DstBufferSize
;
650 UINT32 ScratchBufferSize
;
651 EFI_COMMON_SECTION_HEADER
*CmpSection
;
652 UINTN CmpSectionLength
;
653 UINTN OccupiedCmpSectionLength
;
656 EFI_COMMON_SECTION_HEADER
*Section
;
658 UINTN OccupiedSectionLength
;
660 EFI_GUID_DEFINED_SECTION
*GuidedSectionHeader
;
661 UINT32 AuthenticationStatus
;
662 EFI_PEI_SECTION_EXTRACTION_PPI
*SectionExtract
;
665 EFI_PEI_SECURITY_PPI
*Security
;
666 BOOLEAN StartCrisisRecovery
;
668 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
669 EFI_COMPRESSION_SECTION
*CompressionSection
;
672 Status
= PeiServicesFfsFindSectionData (
673 EFI_SECTION_COMPRESSION
,
679 // First process the compression section
681 if (!EFI_ERROR (Status
)) {
683 // Yes, there is a compression section, so extract the contents
684 // Decompress the image here
686 Section
= (EFI_COMMON_SECTION_HEADER
*) (UINTN
) (VOID
*) ((UINT8
*) (FfsFileHeader
) + (UINTN
) sizeof (EFI_FFS_FILE_HEADER
));
689 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
690 OccupiedSectionLength
= GET_OCCUPIED_SIZE (SectionLength
, 4);
693 // Was the DXE Core file encapsulated in a GUID'd section?
695 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
697 // Locate the GUID'd Section Extractor
699 GuidedSectionHeader
= (VOID
*) (Section
+ 1);
702 // This following code constitutes the addition of the security model
706 // Set a default authenticatino state
708 AuthenticationStatus
= 0;
710 Status
= PeiServicesLocatePpi (
711 &gEfiPeiSectionExtractionPpiGuid
,
714 (VOID
**)&SectionExtract
717 if (EFI_ERROR (Status
)) {
721 // Verify Authentication State
723 CopyMem (&TempGuid
, Section
+ 1, sizeof (EFI_GUID
));
725 Status
= SectionExtract
->PeiGetSection (
726 GetPeiServicesTablePointer(),
728 (EFI_SECTION_TYPE
*) &SectionType
,
733 &AuthenticationStatus
736 if (EFI_ERROR (Status
)) {
740 // If not ask the Security PPI, if exists, for disposition
743 Status
= PeiServicesLocatePpi (
744 &gEfiPeiSecurityPpiGuid
,
749 if (EFI_ERROR (Status
)) {
753 Status
= Security
->AuthenticationState (
754 GetPeiServicesTablePointer(),
755 (struct _EFI_PEI_SECURITY_PPI
*) Security
,
756 AuthenticationStatus
,
761 if (EFI_ERROR (Status
)) {
765 // If there is a security violation, report to caller and have
766 // the upper-level logic possible engender a crisis recovery
768 if (StartCrisisRecovery
) {
769 return EFI_SECURITY_VIOLATION
;
773 if (Section
->Type
== EFI_SECTION_PE32
) {
775 // This is what we want
777 *Pe32Data
= (VOID
*) (Section
+ 1);
779 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
781 // This is a compression set, expand it
783 CompressionSection
= (EFI_COMPRESSION_SECTION
*) Section
;
785 switch (CompressionSection
->CompressionType
) {
786 case EFI_STANDARD_COMPRESSION
:
787 if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress
)) {
788 DecompressLibrary
= &gTianoDecompress
;
791 return EFI_NOT_FOUND
;
795 case EFI_CUSTOMIZED_COMPRESSION
:
797 // Load user customized compression protocol.
799 if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress
)) {
800 DecompressLibrary
= &gCustomDecompress
;
803 return EFI_NOT_FOUND
;
807 case EFI_NOT_COMPRESSED
:
810 // Need to support not compressed file
812 ASSERT_EFI_ERROR (Status
);
813 return EFI_NOT_FOUND
;
816 Status
= DecompressLibrary
->GetInfo (
817 (UINT8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
818 (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION
),
822 if (EFI_ERROR (Status
)) {
826 return EFI_NOT_FOUND
;
830 // Allocate scratch buffer
832 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
833 if (ScratchBuffer
== NULL
) {
834 return EFI_OUT_OF_RESOURCES
;
838 // Allocate destination buffer
840 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
841 if (DstBuffer
== NULL
) {
842 return EFI_OUT_OF_RESOURCES
;
846 // Call decompress function
848 Status
= DecompressLibrary
->Decompress (
849 (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
854 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) DstBuffer
;
855 if (CmpSection
->Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
857 // Firmware Volume Image in this Section
858 // Skip the section header to get FvHeader
860 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (CmpSection
+ 1);
862 if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
864 // Adjust Fv Base Address Alignment based on Align Attributes in Fv Header
868 // When FvImage support Alignment, we need to check whether
869 // its alignment is correct.
871 if (FvHeader
->Attributes
| EFI_FVB_ALIGNMENT_CAP
) {
874 // Calculate the mini alignment for this FvImage
876 FvAlignment
= 1 << (LowBitSet32 (FvHeader
->Attributes
>> 16) + 1);
879 // If current FvImage base address doesn't meet the its alignment,
880 // we need to reload this FvImage to another correct memory address.
882 if (((UINTN
) FvHeader
% FvAlignment
) != 0) {
883 DstBuffer
= AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN
) FvHeader
->FvLength
), FvAlignment
);
884 if (DstBuffer
== NULL
) {
885 return EFI_OUT_OF_RESOURCES
;
887 CopyMem (DstBuffer
, FvHeader
, (UINTN
) FvHeader
->FvLength
);
888 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) DstBuffer
;
892 // Build new FvHob for new decompressed Fv image.
894 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
, FvHeader
->FvLength
);
897 // Set the original FvHob to unused.
899 if (OrigHob
!= NULL
) {
900 OrigHob
->Header
->HobType
= EFI_HOB_TYPE_UNUSED
;
904 // when search FvImage Section return true.
906 if (SectionType
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
907 *Pe32Data
= (VOID
*) FvHeader
;
910 return EFI_NOT_FOUND
;
916 // Decompress successfully.
917 // Loop the decompressed data searching for expected section.
919 CmpFileData
= (VOID
*) DstBuffer
;
920 CmpFileSize
= DstBufferSize
;
922 CmpSectionLength
= *(UINT32
*) (CmpSection
->Size
) & 0x00ffffff;
923 if (CmpSection
->Type
== EFI_SECTION_PE32
) {
925 // This is what we want
927 *Pe32Data
= (VOID
*) (CmpSection
+ 1);
931 OccupiedCmpSectionLength
= GET_OCCUPIED_SIZE (CmpSectionLength
, 4);
932 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) CmpSection
+ OccupiedCmpSectionLength
);
933 } while (CmpSection
->Type
!= 0 && (UINTN
) ((UINT8
*) CmpSection
- (UINT8
*) CmpFileData
) < CmpFileSize
);
936 // End of the decompression activity
939 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
940 FileSize
= FfsFileHeader
->Size
[0] & 0xFF;
941 FileSize
+= (FfsFileHeader
->Size
[1] << 8) & 0xFF00;
942 FileSize
+= (FfsFileHeader
->Size
[2] << 16) & 0xFF0000;
943 FileSize
&= 0x00FFFFFF;
944 } while (Section
->Type
!= 0 && (UINTN
) ((UINT8
*) Section
- (UINT8
*) FfsFileHeader
) < FileSize
);
947 // search all sections (compression and non compression) in this FFS, don't
948 // find expected section.
950 return EFI_NOT_FOUND
;
953 // For those FFS that doesn't contain compression section, directly search
954 // PE or TE section in this FFS.
957 Status
= PeiServicesFfsFindSectionData (
963 if (EFI_ERROR (Status
)) {
964 Status
= PeiServicesFfsFindSectionData (
969 if (EFI_ERROR (Status
)) {
975 *Pe32Data
= SectionData
;