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.
26 #pragma warning( disable : 4305 )
29 BOOLEAN gInMemory
= FALSE
;
32 // Module Globals used in the DXE to PEI handoff
33 // These must be module globals, so the stack can be switched
35 static EFI_DXE_IPL_PPI mDxeIplPpi
= {
39 static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi
= {
43 static EFI_PEI_PPI_DESCRIPTOR mPpiLoadFile
= {
44 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
45 &gEfiPeiFvFileLoaderPpiGuid
,
49 static EFI_PEI_PPI_DESCRIPTOR mPpiList
= {
50 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
55 static EFI_PEI_PPI_DESCRIPTOR mPpiSignal
= {
56 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
57 &gEfiEndOfPeiSignalPpiGuid
,
61 GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gEfiDecompress
= {
62 UefiDecompressGetInfo
,
66 GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gTianoDecompress
= {
67 TianoDecompressGetInfo
,
71 GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gCustomDecompress
= {
72 CustomDecompressGetInfo
,
85 OccupiedSize
= ActualSize
;
86 while ((OccupiedSize
& (Alignment
- 1)) != 0) {
95 PeimInitializeDxeIpl (
96 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
97 IN EFI_PEI_SERVICES
**PeiServices
103 Initializes the Dxe Ipl PPI
107 FfsHeader - Pointer to FFS file header
108 PeiServices - General purpose services available to every PEIM.
117 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
118 EFI_BOOT_MODE BootMode
;
120 Status
= PeiServicesGetBootMode (&BootMode
);
122 ASSERT_EFI_ERROR (Status
);
124 if (!gInMemory
&& (BootMode
!= BOOT_ON_S3_RESUME
)) {
126 // The DxeIpl has not yet been shadowed
128 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
131 // Shadow DxeIpl and then re-run its entry point
133 Status
= ShadowDxeIpl (FfsHeader
, PeiEfiPeiPeCoffLoader
);
134 if (EFI_ERROR (Status
)) {
139 if (BootMode
!= BOOT_ON_S3_RESUME
) {
142 // Install LoadFile PPI
144 Status
= PeiServicesInstallPpi (&mPpiLoadFile
);
146 if (EFI_ERROR (Status
)) {
151 // Install DxeIpl PPI
153 Status
= PeiServicesInstallPpi (&mPpiList
);
155 if (EFI_ERROR (Status
)) {
167 IN EFI_DXE_IPL_PPI
*This
,
168 IN EFI_PEI_SERVICES
**PeiServices
,
169 IN EFI_PEI_HOB_POINTERS HobList
175 Main entry point to last PEIM
179 This - Entry point for DXE IPL PPI
180 PeiServices - General purpose services available to every PEIM.
181 HobList - Address to the Pei HOB list
185 EFI_SUCCESS - DEX core was successfully loaded.
186 EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core.
191 EFI_PHYSICAL_ADDRESS TopOfStack
;
192 EFI_PHYSICAL_ADDRESS BaseOfStack
;
193 EFI_PHYSICAL_ADDRESS BspStore
;
194 EFI_GUID DxeCoreFileName
;
195 EFI_GUID FirmwareFileName
;
196 VOID
*DxeCorePe32Data
;
198 EFI_PHYSICAL_ADDRESS DxeCoreAddress
;
200 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
;
201 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
202 EFI_BOOT_MODE BootMode
;
203 EFI_PEI_RECOVERY_MODULE_PPI
*PeiRecovery
;
204 EFI_PEI_S3_RESUME_PPI
*S3Resume
;
205 EFI_PHYSICAL_ADDRESS PageTables
;
210 Status
= EFI_SUCCESS
;
213 // if in S3 Resume, restore configure
215 Status
= PeiServicesGetBootMode (&BootMode
);
217 if (!EFI_ERROR (Status
) && (BootMode
== BOOT_ON_S3_RESUME
)) {
218 Status
= PeiServicesLocatePpi (
219 &gEfiPeiS3ResumePpiGuid
,
225 ASSERT_EFI_ERROR (Status
);
227 Status
= S3Resume
->S3RestoreConfig (PeiServices
);
229 ASSERT_EFI_ERROR (Status
);
232 Status
= EFI_SUCCESS
;
235 // Install the PEI Protocols that are shared between PEI and DXE
237 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
238 ASSERT (PeiEfiPeiPeCoffLoader
!= NULL
);
241 // Allocate 128KB for the Stack
243 PeiServicesAllocatePages (EfiBootServicesData
, EFI_SIZE_TO_PAGES (STACK_SIZE
), &BaseOfStack
);
244 ASSERT (BaseOfStack
!= 0);
247 // Compute the top of the stack we were allocated, which is used to load X64 dxe core.
248 // Pre-allocate a 32 bytes which confroms to x64 calling convention.
250 // The first four parameters to a function are passed in rcx, rdx, r8 and r9.
251 // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the
252 // register parameters is reserved on the stack, in case the called function
253 // wants to spill them; this is important if the function is variadic.
255 TopOfStack
= BaseOfStack
+ EFI_SIZE_TO_PAGES (STACK_SIZE
) * EFI_PAGE_SIZE
- 32;
258 // X64 Calling Conventions requires that the stack must be aligned to 16 bytes
260 TopOfStack
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) ALIGN_POINTER (TopOfStack
, 16);
263 // Add architecture-specifc HOBs (including the BspStore HOB)
265 Status
= CreateArchSpecificHobs (&BspStore
);
266 ASSERT_EFI_ERROR (Status
);
269 // See if we are in crisis recovery
271 Status
= PeiServicesGetBootMode (&BootMode
);
272 if (!EFI_ERROR (Status
) && (BootMode
== BOOT_IN_RECOVERY_MODE
)) {
273 Status
= PeiServicesLocatePpi (
274 &gEfiPeiRecoveryModulePpiGuid
,
277 (VOID
**)&PeiRecovery
280 ASSERT_EFI_ERROR (Status
);
281 Status
= PeiRecovery
->LoadRecoveryCapsule (PeiServices
, PeiRecovery
);
282 if (EFI_ERROR (Status
)) {
283 DEBUG ((EFI_D_ERROR
, "Load Recovery Capsule Failed.(Status = %r)\n", Status
));
289 // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file
290 // The file found will be processed by PeiProcessFile: It will first be decompressed to
291 // a normal FV, then a corresponding FV type hob will be built.
293 Status
= PeiFindFile (
294 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
295 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
301 // Find the DXE Core in a Firmware Volume
303 Status
= PeiFindFile (
304 EFI_FV_FILETYPE_DXE_CORE
,
309 ASSERT_EFI_ERROR (Status
);
312 // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA
313 // memory, it may be corrupted when copying FV to high-end memory
318 // Limit to 36 bits of addressing for debug. Should get it from CPU
320 PageTables
= CreateIdentityMappingPageTables (36);
324 // Load the DXE Core from a Firmware Volume
326 Status
= PeiLoadPeImage (
327 PeiEfiPeiPeCoffLoader
,
334 ASSERT_EFI_ERROR (Status
);
337 // Transfer control to the DXE Core
338 // The handoff state is simply a pointer to the HOB list
341 Status
= PeiServicesInstallPpi (&mPpiSignal
);
342 ASSERT_EFI_ERROR (Status
);
346 // Add HOB for the DXE Core
356 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
360 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
363 DEBUG ((EFI_D_INFO
, "DXE Core Entry\n"));
365 // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded.
366 // Call x64 drivers passing in single argument, a pointer to the HOBs.
370 (EFI_PHYSICAL_ADDRESS
)(UINTN
)(HobList
.Raw
),
377 // If we get here, then the DXE Core returned. This is an error
378 // Dxe Core should not return.
383 return EFI_OUT_OF_RESOURCES
;
389 IN UINT16 SectionType
,
390 OUT EFI_GUID
*FileName
,
397 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
398 described in the HOB list. Able to search in a compression set in a FFS file.
399 But only one level of compression is supported, that is, not able to search
400 in a compression set that is within another compression set.
404 Type - The Type of file to retrieve
406 SectionType - The type of section to retrieve from a file
408 FileName - The name of the file found in the Firmware Volume
410 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
414 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
415 the PE/COFF image is returned in Pe32Data
417 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
421 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
422 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
425 EFI_PEI_HOB_POINTERS Hob
;
429 FfsFileHeader
= NULL
;
431 Status
= EFI_SUCCESS
;
434 // For each Firmware Volume, look for a specified type
435 // of file and break out until no one is found
437 Hob
.Raw
= GetHobList ();
438 while ((Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
)) != NULL
) {
439 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (Hob
.FirmwareVolume
->BaseAddress
);
440 Status
= PeiServicesFfsFindNextFile (
445 if (!EFI_ERROR (Status
)) {
446 Status
= PeiProcessFile (
452 CopyMem (FileName
, &FfsFileHeader
->Name
, sizeof (EFI_GUID
));
453 if (!EFI_ERROR (Status
)) {
457 Hob
.Raw
= GET_NEXT_HOB (Hob
);
459 return EFI_NOT_FOUND
;
464 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
,
466 IN EFI_MEMORY_TYPE MemoryType
,
467 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
468 OUT UINT64
*ImageSize
,
469 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
475 Loads and relocates a PE/COFF image into memory.
479 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
481 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
483 ImageAddress - The base address of the relocated PE/COFF image
485 ImageSize - The size of the relocated PE/COFF image
487 EntryPoint - The entry point of the relocated PE/COFF image
491 EFI_SUCCESS - The file was loaded and relocated
492 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
497 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
498 EFI_PHYSICAL_ADDRESS MemoryBuffer
;
500 ZeroMem (&ImageContext
, sizeof (ImageContext
));
501 ImageContext
.Handle
= Pe32Data
;
502 Status
= GetImageReadFunction (&ImageContext
);
504 ASSERT_EFI_ERROR (Status
);
506 Status
= PeiEfiPeiPeCoffLoader
->GetImageInfo (PeiEfiPeiPeCoffLoader
, &ImageContext
);
507 if (EFI_ERROR (Status
)) {
511 // Allocate Memory for the image
514 // Allocate Memory for the image
516 PeiServicesAllocatePages (MemoryType
, EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
), &MemoryBuffer
);
517 ImageContext
.ImageAddress
= MemoryBuffer
;
518 ASSERT (ImageContext
.ImageAddress
!= 0);
521 // Load the image to our new buffer
524 Status
= PeiEfiPeiPeCoffLoader
->LoadImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
525 if (EFI_ERROR (Status
)) {
530 // Relocate the image in our new buffer
532 Status
= PeiEfiPeiPeCoffLoader
->RelocateImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
533 if (EFI_ERROR (Status
)) {
538 // Flush the instruction cache so the image data is written before we execute it
540 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
542 *ImageAddress
= ImageContext
.ImageAddress
;
543 *ImageSize
= ImageContext
.ImageSize
;
544 *EntryPoint
= ImageContext
.EntryPoint
;
551 IN EFI_FFS_FILE_HEADER
*DxeIplFileHeader
,
552 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
558 Shadow the DXE IPL to a different memory location. This occurs after permanent
559 memory has been discovered.
563 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
565 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
569 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
571 EFI_ ERROR - The shadow was unsuccessful.
577 UINTN OccupiedSectionLength
;
578 EFI_PHYSICAL_ADDRESS DxeIplAddress
;
580 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint
;
582 EFI_COMMON_SECTION_HEADER
*Section
;
584 Section
= (EFI_COMMON_SECTION_HEADER
*) (DxeIplFileHeader
+ 1);
586 while ((Section
->Type
!= EFI_SECTION_PE32
) && (Section
->Type
!= EFI_SECTION_TE
)) {
587 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
588 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
589 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
593 // Relocate DxeIpl into memory by using loadfile service
595 Status
= PeiLoadPeImage (
596 PeiEfiPeiPeCoffLoader
,
597 (VOID
*) (Section
+ 1),
604 if (Status
== EFI_SUCCESS
) {
606 // Set gInMemory global variable to TRUE to indicate the dxeipl is shadowed.
608 *(BOOLEAN
*) ((UINTN
) &gInMemory
+ (UINTN
) DxeIplEntryPoint
- (UINTN
) _ModuleEntryPoint
) = TRUE
;
609 Status
= ((EFI_PEIM_ENTRY_POINT
) (UINTN
) DxeIplEntryPoint
) (DxeIplFileHeader
, GetPeiServicesTablePointer());
618 IN EFI_PEI_FV_FILE_LOADER_PPI
*This
,
619 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
620 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
621 OUT UINT64
*ImageSize
,
622 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
628 Given a pointer to an FFS file containing a PE32 image, get the
629 information on the PE32 image, and then "load" it so that it
634 This - pointer to our file loader protocol
635 FfsHeader - pointer to the FFS file header of the FFS file that
636 contains the PE32 image we want to load
637 ImageAddress - returned address where the PE32 image is loaded
638 ImageSize - returned size of the loaded PE32 image
639 EntryPoint - entry point to the loaded PE32 image
643 EFI_SUCCESS - The FFS file was successfully loaded.
644 EFI_ERROR - Unable to load the FFS file.
648 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
653 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
656 // Preprocess the FFS file to get a pointer to the PE32 information
657 // in the enclosed PE32 image.
659 Status
= PeiProcessFile (
666 if (EFI_ERROR (Status
)) {
670 // Load the PE image from the FFS file
672 Status
= PeiLoadPeImage (
673 PeiEfiPeiPeCoffLoader
,
686 IN UINT16 SectionType
,
687 IN EFI_FFS_FILE_HEADER
*FfsFileHeader
,
689 IN EFI_PEI_HOB_POINTERS
*OrigHob
697 SectionType - The type of section in the FFS file to process.
699 FfsFileHeader - Pointer to the FFS file to process, looking for the
700 specified SectionType
702 Pe32Data - returned pointer to the start of the PE32 image found
707 EFI_SUCCESS - found the PE32 section in the FFS file
713 DECOMPRESS_LIBRARY
*DecompressLibrary
;
715 UINT8
*ScratchBuffer
;
716 UINT32 DstBufferSize
;
717 UINT32 ScratchBufferSize
;
718 EFI_COMMON_SECTION_HEADER
*CmpSection
;
719 UINTN CmpSectionLength
;
720 UINTN OccupiedCmpSectionLength
;
723 EFI_COMMON_SECTION_HEADER
*Section
;
725 UINTN OccupiedSectionLength
;
727 EFI_GUID_DEFINED_SECTION
*GuidedSectionHeader
;
728 UINT32 AuthenticationStatus
;
729 EFI_PEI_SECTION_EXTRACTION_PPI
*SectionExtract
;
732 EFI_PEI_SECURITY_PPI
*Security
;
733 BOOLEAN StartCrisisRecovery
;
735 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
736 EFI_COMPRESSION_SECTION
*CompressionSection
;
739 Status
= PeiServicesFfsFindSectionData (
740 EFI_SECTION_COMPRESSION
,
746 // First process the compression section
748 if (!EFI_ERROR (Status
)) {
750 // Yes, there is a compression section, so extract the contents
751 // Decompress the image here
753 Section
= (EFI_COMMON_SECTION_HEADER
*) (UINTN
) (VOID
*) ((UINT8
*) (FfsFileHeader
) + (UINTN
) sizeof (EFI_FFS_FILE_HEADER
));
756 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
757 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
760 // Was the DXE Core file encapsulated in a GUID'd section?
762 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
764 // Locate the GUID'd Section Extractor
766 GuidedSectionHeader
= (VOID
*) (Section
+ 1);
769 // This following code constitutes the addition of the security model
773 // Set a default authenticatino state
775 AuthenticationStatus
= 0;
777 Status
= PeiServicesLocatePpi (
778 &gEfiPeiSectionExtractionPpiGuid
,
781 (VOID
**)&SectionExtract
784 if (EFI_ERROR (Status
)) {
788 // Verify Authentication State
790 CopyMem (&TempGuid
, Section
+ 1, sizeof (EFI_GUID
));
792 Status
= SectionExtract
->PeiGetSection (
793 GetPeiServicesTablePointer(),
795 (EFI_SECTION_TYPE
*) &SectionType
,
800 &AuthenticationStatus
803 if (EFI_ERROR (Status
)) {
807 // If not ask the Security PPI, if exists, for disposition
810 Status
= PeiServicesLocatePpi (
811 &gEfiPeiSecurityPpiGuid
,
816 if (EFI_ERROR (Status
)) {
820 Status
= Security
->AuthenticationState (
821 GetPeiServicesTablePointer(),
822 (struct _EFI_PEI_SECURITY_PPI
*) Security
,
823 AuthenticationStatus
,
828 if (EFI_ERROR (Status
)) {
832 // If there is a security violation, report to caller and have
833 // the upper-level logic possible engender a crisis recovery
835 if (StartCrisisRecovery
) {
836 return EFI_SECURITY_VIOLATION
;
840 if (Section
->Type
== EFI_SECTION_PE32
) {
842 // This is what we want
844 *Pe32Data
= (VOID
*) (Section
+ 1);
846 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
848 // This is a compression set, expand it
850 CompressionSection
= (EFI_COMPRESSION_SECTION
*) Section
;
852 switch (CompressionSection
->CompressionType
) {
853 case EFI_STANDARD_COMPRESSION
:
854 if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress
)) {
855 DecompressLibrary
= &gTianoDecompress
;
858 return EFI_NOT_FOUND
;
862 case EFI_CUSTOMIZED_COMPRESSION
:
864 // Load user customized compression protocol.
866 if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress
)) {
867 DecompressLibrary
= &gCustomDecompress
;
870 return EFI_NOT_FOUND
;
874 case EFI_NOT_COMPRESSED
:
877 // Need to support not compressed file
879 ASSERT_EFI_ERROR (Status
);
880 return EFI_NOT_FOUND
;
883 Status
= DecompressLibrary
->GetInfo (
884 (UINT8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
885 (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION
),
889 if (EFI_ERROR (Status
)) {
893 return EFI_NOT_FOUND
;
897 // Allocate scratch buffer
899 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
900 if (ScratchBuffer
== NULL
) {
901 return EFI_OUT_OF_RESOURCES
;
905 // Allocate destination buffer
907 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
908 if (DstBuffer
== NULL
) {
909 return EFI_OUT_OF_RESOURCES
;
913 // Call decompress function
915 Status
= DecompressLibrary
->Decompress (
916 (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
921 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) DstBuffer
;
922 if (CmpSection
->Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
924 // Firmware Volume Image in this Section
925 // Skip the section header to get FvHeader
927 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (CmpSection
+ 1);
929 if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
931 // Adjust Fv Base Address Alignment based on Align Attributes in Fv Header
935 // When FvImage support Alignment, we need to check whether
936 // its alignment is correct.
938 if (FvHeader
->Attributes
| EFI_FVB_ALIGNMENT_CAP
) {
941 // Calculate the mini alignment for this FvImage
943 FvAlignment
= 1 << (LowBitSet32 (FvHeader
->Attributes
>> 16) + 1);
946 // If current FvImage base address doesn't meet the its alignment,
947 // we need to reload this FvImage to another correct memory address.
949 if (((UINTN
) FvHeader
% FvAlignment
) != 0) {
950 DstBuffer
= AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN
) FvHeader
->FvLength
), FvAlignment
);
951 if (DstBuffer
== NULL
) {
952 return EFI_OUT_OF_RESOURCES
;
954 CopyMem (DstBuffer
, FvHeader
, (UINTN
) FvHeader
->FvLength
);
955 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) DstBuffer
;
959 // Build new FvHob for new decompressed Fv image.
961 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
, FvHeader
->FvLength
);
964 // Set the original FvHob to unused.
966 if (OrigHob
!= NULL
) {
967 OrigHob
->Header
->HobType
= EFI_HOB_TYPE_UNUSED
;
971 // when search FvImage Section return true.
973 if (SectionType
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
974 *Pe32Data
= (VOID
*) FvHeader
;
977 return EFI_NOT_FOUND
;
983 // Decompress successfully.
984 // Loop the decompressed data searching for expected section.
986 CmpFileData
= (VOID
*) DstBuffer
;
987 CmpFileSize
= DstBufferSize
;
989 CmpSectionLength
= *(UINT32
*) (CmpSection
->Size
) & 0x00ffffff;
990 if (CmpSection
->Type
== EFI_SECTION_PE32
) {
992 // This is what we want
994 *Pe32Data
= (VOID
*) (CmpSection
+ 1);
998 OccupiedCmpSectionLength
= GetOccupiedSize (CmpSectionLength
, 4);
999 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) CmpSection
+ OccupiedCmpSectionLength
);
1000 } while (CmpSection
->Type
!= 0 && (UINTN
) ((UINT8
*) CmpSection
- (UINT8
*) CmpFileData
) < CmpFileSize
);
1003 // End of the decompression activity
1006 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
1007 FileSize
= FfsFileHeader
->Size
[0] & 0xFF;
1008 FileSize
+= (FfsFileHeader
->Size
[1] << 8) & 0xFF00;
1009 FileSize
+= (FfsFileHeader
->Size
[2] << 16) & 0xFF0000;
1010 FileSize
&= 0x00FFFFFF;
1011 } while (Section
->Type
!= 0 && (UINTN
) ((UINT8
*) Section
- (UINT8
*) FfsFileHeader
) < FileSize
);
1014 // search all sections (compression and non compression) in this FFS, don't
1015 // find expected section.
1017 return EFI_NOT_FOUND
;
1020 // For those FFS that doesn't contain compression section, directly search
1021 // PE or TE section in this FFS.
1024 Status
= PeiServicesFfsFindSectionData (
1030 if (EFI_ERROR (Status
)) {
1031 Status
= PeiServicesFfsFindSectionData (
1036 if (EFI_ERROR (Status
)) {
1042 *Pe32Data
= SectionData
;