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
;
30 // Module Globals used in the DXE to PEI handoff
31 // These must be module globals, so the stack can be switched
33 static EFI_DXE_IPL_PPI mDxeIplPpi
= {
37 static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi
= {
41 static EFI_PEI_PPI_DESCRIPTOR mPpiLoadFile
= {
42 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
43 &gEfiPeiFvFileLoaderPpiGuid
,
47 static EFI_PEI_PPI_DESCRIPTOR mPpiList
= {
48 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
53 static EFI_PEI_PPI_DESCRIPTOR mPpiPeiInMemory
= {
54 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
59 static EFI_PEI_PPI_DESCRIPTOR mPpiSignal
= {
60 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
61 &gEfiEndOfPeiSignalPpiGuid
,
65 GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gEfiDecompress
= {
66 UefiDecompressGetInfo
,
70 GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gTianoDecompress
= {
71 TianoDecompressGetInfo
,
75 GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gCustomDecompress
= {
76 CustomDecompressGetInfo
,
89 OccupiedSize
= ActualSize
;
90 while ((OccupiedSize
& (Alignment
- 1)) != 0) {
99 PeimInitializeDxeIpl (
100 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
101 IN EFI_PEI_SERVICES
**PeiServices
107 Initializes the Dxe Ipl PPI
111 FfsHeader - Pointer to FFS file header
112 PeiServices - General purpose services available to every PEIM.
121 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
122 EFI_BOOT_MODE BootMode
;
124 Status
= PeiServicesGetBootMode (&BootMode
);
126 ASSERT_EFI_ERROR (Status
);
128 Status
= PeiServicesLocatePpi (
135 if (EFI_ERROR (Status
) && (BootMode
!= BOOT_ON_S3_RESUME
)) {
137 // The DxeIpl has not yet been shadowed
139 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
142 // Shadow DxeIpl and then re-run its entry point
144 Status
= ShadowDxeIpl (FfsHeader
, PeiEfiPeiPeCoffLoader
);
145 if (EFI_ERROR (Status
)) {
150 if (BootMode
!= BOOT_ON_S3_RESUME
) {
152 // The DxeIpl has been shadowed
157 // Install LoadFile PPI
159 Status
= PeiServicesInstallPpi (&mPpiLoadFile
);
161 if (EFI_ERROR (Status
)) {
166 // Install DxeIpl PPI
168 PeiServicesInstallPpi (&mPpiList
);
170 if (EFI_ERROR (Status
)) {
182 IN EFI_DXE_IPL_PPI
*This
,
183 IN EFI_PEI_SERVICES
**PeiServices
,
184 IN EFI_PEI_HOB_POINTERS HobList
190 Main entry point to last PEIM
194 This - Entry point for DXE IPL PPI
195 PeiServices - General purpose services available to every PEIM.
196 HobList - Address to the Pei HOB list
200 EFI_SUCCESS - DEX core was successfully loaded.
201 EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core.
206 EFI_PHYSICAL_ADDRESS TopOfStack
;
207 EFI_PHYSICAL_ADDRESS BaseOfStack
;
208 EFI_PHYSICAL_ADDRESS BspStore
;
209 EFI_GUID DxeCoreFileName
;
210 EFI_GUID FirmwareFileName
;
211 VOID
*DxeCorePe32Data
;
213 EFI_PHYSICAL_ADDRESS DxeCoreAddress
;
215 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
;
216 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
217 EFI_BOOT_MODE BootMode
;
218 EFI_PEI_RECOVERY_MODULE_PPI
*PeiRecovery
;
219 EFI_PEI_S3_RESUME_PPI
*S3Resume
;
220 EFI_PHYSICAL_ADDRESS PageTables
;
225 Status
= EFI_SUCCESS
;
228 // if in S3 Resume, restore configure
230 Status
= PeiServicesGetBootMode (&BootMode
);
232 if (!EFI_ERROR (Status
) && (BootMode
== BOOT_ON_S3_RESUME
)) {
233 Status
= PeiServicesLocatePpi (
234 &gEfiPeiS3ResumePpiGuid
,
240 ASSERT_EFI_ERROR (Status
);
242 Status
= S3Resume
->S3RestoreConfig (PeiServices
);
244 ASSERT_EFI_ERROR (Status
);
247 Status
= EFI_SUCCESS
;
250 // Install the PEI Protocols that are shared between PEI and DXE
252 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
253 ASSERT (PeiEfiPeiPeCoffLoader
!= NULL
);
256 // Allocate 128KB for the Stack
258 PeiServicesAllocatePages (EfiBootServicesData
, EFI_SIZE_TO_PAGES (STACK_SIZE
), &BaseOfStack
);
259 ASSERT (BaseOfStack
!= 0);
262 // Compute the top of the stack we were allocated, which is used to load X64 dxe core.
263 // Pre-allocate a 32 bytes which confroms to x64 calling convention.
265 // The first four parameters to a function are passed in rcx, rdx, r8 and r9.
266 // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the
267 // register parameters is reserved on the stack, in case the called function
268 // wants to spill them; this is important if the function is variadic.
270 TopOfStack
= BaseOfStack
+ EFI_SIZE_TO_PAGES (STACK_SIZE
) * EFI_PAGE_SIZE
- 32;
273 // X64 Calling Conventions requires that the stack must be aligned to 16 bytes
275 TopOfStack
= (EFI_PHYSICAL_ADDRESS
) ALIGN_POINTER (TopOfStack
, 16);
278 // Add architecture-specifc HOBs (including the BspStore HOB)
280 Status
= CreateArchSpecificHobs (&BspStore
);
281 ASSERT_EFI_ERROR (Status
);
284 // See if we are in crisis recovery
286 Status
= PeiServicesGetBootMode (&BootMode
);
287 if (!EFI_ERROR (Status
) && (BootMode
== BOOT_IN_RECOVERY_MODE
)) {
288 Status
= PeiServicesLocatePpi (
289 &gEfiPeiRecoveryModulePpiGuid
,
292 (VOID
**)&PeiRecovery
295 ASSERT_EFI_ERROR (Status
);
296 Status
= PeiRecovery
->LoadRecoveryCapsule (PeiServices
, PeiRecovery
);
297 if (EFI_ERROR (Status
)) {
298 DEBUG ((EFI_D_ERROR
, "Load Recovery Capsule Failed.(Status = %r)\n", Status
));
304 // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file
305 // The file found will be processed by PeiProcessFile: It will first be decompressed to
306 // a normal FV, then a corresponding FV type hob will be built.
308 Status
= PeiFindFile (
309 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
310 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
316 // Find the DXE Core in a Firmware Volume
318 Status
= PeiFindFile (
319 EFI_FV_FILETYPE_DXE_CORE
,
324 ASSERT_EFI_ERROR (Status
);
327 // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA \
328 // memory, it may be corrupted when copying FV to high-end memory
332 // Limit to 36 bits of addressing for debug. Should get it from CPU
334 PageTables
= CreateIdentityMappingPageTables (36);
338 // Load the DXE Core from a Firmware Volume
340 Status
= PeiLoadPeImage (
341 PeiEfiPeiPeCoffLoader
,
348 ASSERT_EFI_ERROR (Status
);
351 // Transfer control to the DXE Core
352 // The handoff state is simply a pointer to the HOB list
355 Status
= PeiServicesInstallPpi (&mPpiSignal
);
356 ASSERT_EFI_ERROR (Status
);
360 // Add HOB for the DXE Core
370 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
374 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
377 DEBUG ((EFI_D_INFO
, "DXE Core Entry\n"));
379 // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded.
380 // Call x64 drivers passing in single argument, a pointer to the HOBs.
384 (EFI_PHYSICAL_ADDRESS
)(UINTN
)(HobList
.Raw
),
391 // If we get here, then the DXE Core returned. This is an error
392 // Dxe Core should not return.
397 return EFI_OUT_OF_RESOURCES
;
403 IN UINT16 SectionType
,
404 OUT EFI_GUID
*FileName
,
411 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
412 described in the HOB list. Able to search in a compression set in a FFS file.
413 But only one level of compression is supported, that is, not able to search
414 in a compression set that is within another compression set.
418 Type - The Type of file to retrieve
420 SectionType - The type of section to retrieve from a file
422 FileName - The name of the file found in the Firmware Volume
424 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
428 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
429 the PE/COFF image is returned in Pe32Data
431 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
435 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
436 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
439 EFI_PEI_HOB_POINTERS Hob
;
443 FfsFileHeader
= NULL
;
445 Status
= EFI_SUCCESS
;
448 // For each Firmware Volume, look for a specified type
449 // of file and break out until no one is found
451 Hob
.Raw
= GetHobList ();
452 while ((Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
)) != NULL
) {
453 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (Hob
.FirmwareVolume
->BaseAddress
);
454 Status
= PeiServicesFfsFindNextFile (
459 if (!EFI_ERROR (Status
)) {
460 Status
= PeiProcessFile (
466 CopyMem (FileName
, &FfsFileHeader
->Name
, sizeof (EFI_GUID
));
467 if (!EFI_ERROR (Status
)) {
471 Hob
.Raw
= GET_NEXT_HOB (Hob
);
473 return EFI_NOT_FOUND
;
478 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
,
480 IN EFI_MEMORY_TYPE MemoryType
,
481 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
482 OUT UINT64
*ImageSize
,
483 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
489 Loads and relocates a PE/COFF image into memory.
493 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
495 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
497 ImageAddress - The base address of the relocated PE/COFF image
499 ImageSize - The size of the relocated PE/COFF image
501 EntryPoint - The entry point of the relocated PE/COFF image
505 EFI_SUCCESS - The file was loaded and relocated
506 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
511 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
512 EFI_PHYSICAL_ADDRESS MemoryBuffer
;
514 ZeroMem (&ImageContext
, sizeof (ImageContext
));
515 ImageContext
.Handle
= Pe32Data
;
516 Status
= GetImageReadFunction (&ImageContext
);
518 ASSERT_EFI_ERROR (Status
);
520 Status
= PeiEfiPeiPeCoffLoader
->GetImageInfo (PeiEfiPeiPeCoffLoader
, &ImageContext
);
521 if (EFI_ERROR (Status
)) {
525 // Allocate Memory for the image
528 // Allocate Memory for the image
530 PeiServicesAllocatePages (MemoryType
, EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
), &MemoryBuffer
);
531 ImageContext
.ImageAddress
= MemoryBuffer
;
532 ASSERT (ImageContext
.ImageAddress
!= 0);
535 // Load the image to our new buffer
538 Status
= PeiEfiPeiPeCoffLoader
->LoadImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
539 if (EFI_ERROR (Status
)) {
544 // Relocate the image in our new buffer
546 Status
= PeiEfiPeiPeCoffLoader
->RelocateImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
547 if (EFI_ERROR (Status
)) {
552 // Flush the instruction cache so the image data is written before we execute it
554 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
556 *ImageAddress
= ImageContext
.ImageAddress
;
557 *ImageSize
= ImageContext
.ImageSize
;
558 *EntryPoint
= ImageContext
.EntryPoint
;
565 IN EFI_FFS_FILE_HEADER
*DxeIplFileHeader
,
566 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
572 Shadow the DXE IPL to a different memory location. This occurs after permanent
573 memory has been discovered.
577 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
579 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
583 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
585 EFI_ ERROR - The shadow was unsuccessful.
591 UINTN OccupiedSectionLength
;
592 EFI_PHYSICAL_ADDRESS DxeIplAddress
;
594 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint
;
596 EFI_COMMON_SECTION_HEADER
*Section
;
598 Section
= (EFI_COMMON_SECTION_HEADER
*) (DxeIplFileHeader
+ 1);
600 while ((Section
->Type
!= EFI_SECTION_PE32
) && (Section
->Type
!= EFI_SECTION_TE
)) {
601 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
602 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
603 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
607 // Relocate DxeIpl into memory by using loadfile service
609 Status
= PeiLoadPeImage (
610 PeiEfiPeiPeCoffLoader
,
611 (VOID
*) (Section
+ 1),
618 if (Status
== EFI_SUCCESS
) {
620 // Install PeiInMemory to indicate the Dxeipl is shadowed
622 Status
= PeiServicesInstallPpi (&mPpiPeiInMemory
);
624 if (EFI_ERROR (Status
)) {
628 Status
= ((EFI_PEIM_ENTRY_POINT
) (UINTN
) DxeIplEntryPoint
) (DxeIplFileHeader
, GetPeiServicesTablePointer());
637 IN EFI_PEI_FV_FILE_LOADER_PPI
*This
,
638 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
639 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
640 OUT UINT64
*ImageSize
,
641 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
647 Given a pointer to an FFS file containing a PE32 image, get the
648 information on the PE32 image, and then "load" it so that it
653 This - pointer to our file loader protocol
654 FfsHeader - pointer to the FFS file header of the FFS file that
655 contains the PE32 image we want to load
656 ImageAddress - returned address where the PE32 image is loaded
657 ImageSize - returned size of the loaded PE32 image
658 EntryPoint - entry point to the loaded PE32 image
662 EFI_SUCCESS - The FFS file was successfully loaded.
663 EFI_ERROR - Unable to load the FFS file.
667 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
672 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
675 // Preprocess the FFS file to get a pointer to the PE32 information
676 // in the enclosed PE32 image.
678 Status
= PeiProcessFile (
685 if (EFI_ERROR (Status
)) {
689 // Load the PE image from the FFS file
691 Status
= PeiLoadPeImage (
692 PeiEfiPeiPeCoffLoader
,
705 IN UINT16 SectionType
,
706 IN EFI_FFS_FILE_HEADER
*FfsFileHeader
,
708 IN EFI_PEI_HOB_POINTERS
*OrigHob
716 SectionType - The type of section in the FFS file to process.
718 FfsFileHeader - Pointer to the FFS file to process, looking for the
719 specified SectionType
721 Pe32Data - returned pointer to the start of the PE32 image found
726 EFI_SUCCESS - found the PE32 section in the FFS file
732 DECOMPRESS_LIBRARY
*DecompressLibrary
;
734 UINT8
*ScratchBuffer
;
735 UINT32 DstBufferSize
;
736 UINT32 ScratchBufferSize
;
737 EFI_COMMON_SECTION_HEADER
*CmpSection
;
738 UINTN CmpSectionLength
;
739 UINTN OccupiedCmpSectionLength
;
742 EFI_COMMON_SECTION_HEADER
*Section
;
744 UINTN OccupiedSectionLength
;
746 EFI_GUID_DEFINED_SECTION
*GuidedSectionHeader
;
747 UINT32 AuthenticationStatus
;
748 EFI_PEI_SECTION_EXTRACTION_PPI
*SectionExtract
;
751 EFI_PEI_SECURITY_PPI
*Security
;
752 BOOLEAN StartCrisisRecovery
;
754 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
755 EFI_COMPRESSION_SECTION
*CompressionSection
;
758 Status
= PeiServicesFfsFindSectionData (
759 EFI_SECTION_COMPRESSION
,
765 // First process the compression section
767 if (!EFI_ERROR (Status
)) {
769 // Yes, there is a compression section, so extract the contents
770 // Decompress the image here
772 Section
= (EFI_COMMON_SECTION_HEADER
*) (UINTN
) (VOID
*) ((UINT8
*) (FfsFileHeader
) + (UINTN
) sizeof (EFI_FFS_FILE_HEADER
));
775 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
776 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
779 // Was the DXE Core file encapsulated in a GUID'd section?
781 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
783 // Locate the GUID'd Section Extractor
785 GuidedSectionHeader
= (VOID
*) (Section
+ 1);
788 // This following code constitutes the addition of the security model
792 // Set a default authenticatino state
794 AuthenticationStatus
= 0;
796 Status
= PeiServicesLocatePpi (
797 &gEfiPeiSectionExtractionPpiGuid
,
800 (VOID
**)&SectionExtract
803 if (EFI_ERROR (Status
)) {
807 // Verify Authentication State
809 CopyMem (&TempGuid
, Section
+ 1, sizeof (EFI_GUID
));
811 Status
= SectionExtract
->PeiGetSection (
812 GetPeiServicesTablePointer(),
814 (EFI_SECTION_TYPE
*) &SectionType
,
819 &AuthenticationStatus
822 if (EFI_ERROR (Status
)) {
826 // If not ask the Security PPI, if exists, for disposition
829 Status
= PeiServicesLocatePpi (
830 &gEfiPeiSecurityPpiGuid
,
835 if (EFI_ERROR (Status
)) {
839 Status
= Security
->AuthenticationState (
840 GetPeiServicesTablePointer(),
841 (struct _EFI_PEI_SECURITY_PPI
*) Security
,
842 AuthenticationStatus
,
847 if (EFI_ERROR (Status
)) {
851 // If there is a security violation, report to caller and have
852 // the upper-level logic possible engender a crisis recovery
854 if (StartCrisisRecovery
) {
855 return EFI_SECURITY_VIOLATION
;
859 if (Section
->Type
== EFI_SECTION_PE32
) {
861 // This is what we want
863 *Pe32Data
= (VOID
*) (Section
+ 1);
865 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
867 // This is a compression set, expand it
869 CompressionSection
= (EFI_COMPRESSION_SECTION
*) Section
;
871 switch (CompressionSection
->CompressionType
) {
872 case EFI_STANDARD_COMPRESSION
:
873 if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress
)) {
874 DecompressLibrary
= &gTianoDecompress
;
877 return EFI_NOT_FOUND
;
881 case EFI_CUSTOMIZED_COMPRESSION
:
883 // Load user customized compression protocol.
885 if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress
)) {
886 DecompressLibrary
= &gCustomDecompress
;
889 return EFI_NOT_FOUND
;
893 case EFI_NOT_COMPRESSED
:
896 // Need to support not compressed file
898 ASSERT_EFI_ERROR (Status
);
899 return EFI_NOT_FOUND
;
902 Status
= DecompressLibrary
->GetInfo (
903 (UINT8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
904 (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION
),
908 if (EFI_ERROR (Status
)) {
912 return EFI_NOT_FOUND
;
916 // Allocate scratch buffer
918 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
919 if (ScratchBuffer
== NULL
) {
920 return EFI_OUT_OF_RESOURCES
;
924 // Allocate destination buffer
926 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
927 if (DstBuffer
== NULL
) {
928 return EFI_OUT_OF_RESOURCES
;
932 // Call decompress function
934 Status
= DecompressLibrary
->Decompress (
935 (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
940 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) DstBuffer
;
941 if (CmpSection
->Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
943 // Firmware Volume Image in this Section
944 // Skip the section header to get FvHeader
946 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (CmpSection
+ 1);
948 if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
950 // Adjust Fv Base Address Alignment based on Align Attributes in Fv Header
954 // When FvImage support Alignment, we need to check whether
955 // its alignment is correct.
957 if (FvHeader
->Attributes
| EFI_FVB_ALIGNMENT_CAP
) {
960 // Calculate the mini alignment for this FvImage
962 FvAlignment
= 1 << (LowBitSet32 (FvHeader
->Attributes
>> 16) + 1);
965 // If current FvImage base address doesn't meet the its alignment,
966 // we need to reload this FvImage to another correct memory address.
968 if (((UINTN
) FvHeader
% FvAlignment
) != 0) {
969 DstBuffer
= AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN
) FvHeader
->FvLength
), FvAlignment
);
970 if (DstBuffer
== NULL
) {
971 return EFI_OUT_OF_RESOURCES
;
973 CopyMem (DstBuffer
, FvHeader
, (UINTN
) FvHeader
->FvLength
);
974 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) DstBuffer
;
978 // Build new FvHob for new decompressed Fv image.
980 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
, FvHeader
->FvLength
);
983 // Set the original FvHob to unused.
985 if (OrigHob
!= NULL
) {
986 OrigHob
->Header
->HobType
= EFI_HOB_TYPE_UNUSED
;
990 // when search FvImage Section return true.
992 if (SectionType
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
993 *Pe32Data
= (VOID
*) FvHeader
;
996 return EFI_NOT_FOUND
;
1002 // Decompress successfully.
1003 // Loop the decompressed data searching for expected section.
1005 CmpFileData
= (VOID
*) DstBuffer
;
1006 CmpFileSize
= DstBufferSize
;
1008 CmpSectionLength
= *(UINT32
*) (CmpSection
->Size
) & 0x00ffffff;
1009 if (CmpSection
->Type
== EFI_SECTION_PE32
) {
1011 // This is what we want
1013 *Pe32Data
= (VOID
*) (CmpSection
+ 1);
1017 OccupiedCmpSectionLength
= GetOccupiedSize (CmpSectionLength
, 4);
1018 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) CmpSection
+ OccupiedCmpSectionLength
);
1019 } while (CmpSection
->Type
!= 0 && (UINTN
) ((UINT8
*) CmpSection
- (UINT8
*) CmpFileData
) < CmpFileSize
);
1022 // End of the decompression activity
1025 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
1026 FileSize
= FfsFileHeader
->Size
[0] & 0xFF;
1027 FileSize
+= (FfsFileHeader
->Size
[1] << 8) & 0xFF00;
1028 FileSize
+= (FfsFileHeader
->Size
[2] << 16) & 0xFF0000;
1029 FileSize
&= 0x00FFFFFF;
1030 } while (Section
->Type
!= 0 && (UINTN
) ((UINT8
*) Section
- (UINT8
*) FfsFileHeader
) < FileSize
);
1033 // search all sections (compression and non compression) in this FFS, don't
1034 // find expected section.
1036 return EFI_NOT_FOUND
;
1039 // For those FFS that doesn't contain compression section, directly search
1040 // PE or TE section in this FFS.
1043 Status
= PeiServicesFfsFindSectionData (
1049 if (EFI_ERROR (Status
)) {
1050 Status
= PeiServicesFfsFindSectionData (
1055 if (EFI_ERROR (Status
)) {
1061 *Pe32Data
= SectionData
;