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. Pre-allocate a 32 bytes
263 // for safety (PpisNeededByDxe and DxeCore).
265 TopOfStack
= BaseOfStack
+ EFI_SIZE_TO_PAGES (STACK_SIZE
) * EFI_PAGE_SIZE
- 32;
268 // Add architecture-specifc HOBs (including the BspStore HOB)
270 Status
= CreateArchSpecificHobs (&BspStore
);
271 ASSERT_EFI_ERROR (Status
);
274 // See if we are in crisis recovery
276 Status
= PeiServicesGetBootMode (&BootMode
);
277 if (!EFI_ERROR (Status
) && (BootMode
== BOOT_IN_RECOVERY_MODE
)) {
278 Status
= PeiServicesLocatePpi (
279 &gEfiPeiRecoveryModulePpiGuid
,
282 (VOID
**)&PeiRecovery
285 ASSERT_EFI_ERROR (Status
);
286 Status
= PeiRecovery
->LoadRecoveryCapsule (PeiServices
, PeiRecovery
);
287 if (EFI_ERROR (Status
)) {
288 DEBUG ((EFI_D_ERROR
, "Load Recovery Capsule Failed.(Status = %r)\n", Status
));
294 // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file
295 // The file found will be processed by PeiProcessFile: It will first be decompressed to
296 // a normal FV, then a corresponding FV type hob will be built.
298 Status
= PeiFindFile (
299 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
300 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
306 // Find the DXE Core in a Firmware Volume
308 Status
= PeiFindFile (
309 EFI_FV_FILETYPE_DXE_CORE
,
314 ASSERT_EFI_ERROR (Status
);
317 // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA \
318 // memory, it may be corrupted when copying FV to high-end memory
322 // Limit to 36 bits of addressing for debug. Should get it from CPU
324 PageTables
= CreateIdentityMappingPageTables (36);
328 // Load the DXE Core from a Firmware Volume
330 Status
= PeiLoadPeImage (
331 PeiEfiPeiPeCoffLoader
,
338 ASSERT_EFI_ERROR (Status
);
341 // Transfer control to the DXE Core
342 // The handoff state is simply a pointer to the HOB list
345 Status
= PeiServicesInstallPpi (&mPpiSignal
);
346 ASSERT_EFI_ERROR (Status
);
350 // Add HOB for the DXE Core
360 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
364 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
367 DEBUG ((EFI_D_INFO
, "DXE Core Entry\n"));
369 // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded.
370 // Call x64 drivers passing in single argument, a pointer to the HOBs.
374 (EFI_PHYSICAL_ADDRESS
)(UINTN
)(HobList
.Raw
),
381 // If we get here, then the DXE Core returned. This is an error
382 // Dxe Core should not return.
387 return EFI_OUT_OF_RESOURCES
;
393 IN UINT16 SectionType
,
394 OUT EFI_GUID
*FileName
,
401 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
402 described in the HOB list. Able to search in a compression set in a FFS file.
403 But only one level of compression is supported, that is, not able to search
404 in a compression set that is within another compression set.
408 Type - The Type of file to retrieve
410 SectionType - The type of section to retrieve from a file
412 FileName - The name of the file found in the Firmware Volume
414 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
418 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
419 the PE/COFF image is returned in Pe32Data
421 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
425 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
426 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
429 EFI_PEI_HOB_POINTERS Hob
;
433 FfsFileHeader
= NULL
;
435 Status
= EFI_SUCCESS
;
438 // For each Firmware Volume, look for a specified type
439 // of file and break out until no one is found
441 Hob
.Raw
= GetHobList ();
442 while ((Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
)) != NULL
) {
443 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (Hob
.FirmwareVolume
->BaseAddress
);
444 Status
= PeiServicesFfsFindNextFile (
449 if (!EFI_ERROR (Status
)) {
450 Status
= PeiProcessFile (
456 CopyMem (FileName
, &FfsFileHeader
->Name
, sizeof (EFI_GUID
));
457 if (!EFI_ERROR (Status
)) {
461 Hob
.Raw
= GET_NEXT_HOB (Hob
);
463 return EFI_NOT_FOUND
;
468 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
,
470 IN EFI_MEMORY_TYPE MemoryType
,
471 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
472 OUT UINT64
*ImageSize
,
473 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
479 Loads and relocates a PE/COFF image into memory.
483 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
485 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
487 ImageAddress - The base address of the relocated PE/COFF image
489 ImageSize - The size of the relocated PE/COFF image
491 EntryPoint - The entry point of the relocated PE/COFF image
495 EFI_SUCCESS - The file was loaded and relocated
496 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
501 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
502 EFI_PHYSICAL_ADDRESS MemoryBuffer
;
504 ZeroMem (&ImageContext
, sizeof (ImageContext
));
505 ImageContext
.Handle
= Pe32Data
;
506 Status
= GetImageReadFunction (&ImageContext
);
508 ASSERT_EFI_ERROR (Status
);
510 Status
= PeiEfiPeiPeCoffLoader
->GetImageInfo (PeiEfiPeiPeCoffLoader
, &ImageContext
);
511 if (EFI_ERROR (Status
)) {
515 // Allocate Memory for the image
518 // Allocate Memory for the image
520 PeiServicesAllocatePages (MemoryType
, EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
), &MemoryBuffer
);
521 ImageContext
.ImageAddress
= MemoryBuffer
;
522 ASSERT (ImageContext
.ImageAddress
!= 0);
525 // Load the image to our new buffer
528 Status
= PeiEfiPeiPeCoffLoader
->LoadImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
529 if (EFI_ERROR (Status
)) {
534 // Relocate the image in our new buffer
536 Status
= PeiEfiPeiPeCoffLoader
->RelocateImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
537 if (EFI_ERROR (Status
)) {
542 // Flush the instruction cache so the image data is written before we execute it
544 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
546 *ImageAddress
= ImageContext
.ImageAddress
;
547 *ImageSize
= ImageContext
.ImageSize
;
548 *EntryPoint
= ImageContext
.EntryPoint
;
555 IN EFI_FFS_FILE_HEADER
*DxeIplFileHeader
,
556 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
562 Shadow the DXE IPL to a different memory location. This occurs after permanent
563 memory has been discovered.
567 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
569 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
573 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
575 EFI_ ERROR - The shadow was unsuccessful.
581 UINTN OccupiedSectionLength
;
582 EFI_PHYSICAL_ADDRESS DxeIplAddress
;
584 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint
;
586 EFI_COMMON_SECTION_HEADER
*Section
;
588 Section
= (EFI_COMMON_SECTION_HEADER
*) (DxeIplFileHeader
+ 1);
590 while ((Section
->Type
!= EFI_SECTION_PE32
) && (Section
->Type
!= EFI_SECTION_TE
)) {
591 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
592 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
593 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
597 // Relocate DxeIpl into memory by using loadfile service
599 Status
= PeiLoadPeImage (
600 PeiEfiPeiPeCoffLoader
,
601 (VOID
*) (Section
+ 1),
608 if (Status
== EFI_SUCCESS
) {
610 // Install PeiInMemory to indicate the Dxeipl is shadowed
612 Status
= PeiServicesInstallPpi (&mPpiPeiInMemory
);
614 if (EFI_ERROR (Status
)) {
618 Status
= ((EFI_PEIM_ENTRY_POINT
) (UINTN
) DxeIplEntryPoint
) (DxeIplFileHeader
, GetPeiServicesTablePointer());
627 IN EFI_PEI_FV_FILE_LOADER_PPI
*This
,
628 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
629 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
630 OUT UINT64
*ImageSize
,
631 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
637 Given a pointer to an FFS file containing a PE32 image, get the
638 information on the PE32 image, and then "load" it so that it
643 This - pointer to our file loader protocol
644 FfsHeader - pointer to the FFS file header of the FFS file that
645 contains the PE32 image we want to load
646 ImageAddress - returned address where the PE32 image is loaded
647 ImageSize - returned size of the loaded PE32 image
648 EntryPoint - entry point to the loaded PE32 image
652 EFI_SUCCESS - The FFS file was successfully loaded.
653 EFI_ERROR - Unable to load the FFS file.
657 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
662 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
665 // Preprocess the FFS file to get a pointer to the PE32 information
666 // in the enclosed PE32 image.
668 Status
= PeiProcessFile (
675 if (EFI_ERROR (Status
)) {
679 // Load the PE image from the FFS file
681 Status
= PeiLoadPeImage (
682 PeiEfiPeiPeCoffLoader
,
695 IN UINT16 SectionType
,
696 IN EFI_FFS_FILE_HEADER
*FfsFileHeader
,
698 IN EFI_PEI_HOB_POINTERS
*OrigHob
706 SectionType - The type of section in the FFS file to process.
708 FfsFileHeader - Pointer to the FFS file to process, looking for the
709 specified SectionType
711 Pe32Data - returned pointer to the start of the PE32 image found
716 EFI_SUCCESS - found the PE32 section in the FFS file
722 DECOMPRESS_LIBRARY
*DecompressLibrary
;
724 UINT8
*ScratchBuffer
;
725 UINT32 DstBufferSize
;
726 UINT32 ScratchBufferSize
;
727 EFI_COMMON_SECTION_HEADER
*CmpSection
;
728 UINTN CmpSectionLength
;
729 UINTN OccupiedCmpSectionLength
;
732 EFI_COMMON_SECTION_HEADER
*Section
;
734 UINTN OccupiedSectionLength
;
736 EFI_GUID_DEFINED_SECTION
*GuidedSectionHeader
;
737 UINT32 AuthenticationStatus
;
738 EFI_PEI_SECTION_EXTRACTION_PPI
*SectionExtract
;
741 EFI_PEI_SECURITY_PPI
*Security
;
742 BOOLEAN StartCrisisRecovery
;
744 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
745 EFI_COMPRESSION_SECTION
*CompressionSection
;
748 Status
= PeiServicesFfsFindSectionData (
749 EFI_SECTION_COMPRESSION
,
755 // First process the compression section
757 if (!EFI_ERROR (Status
)) {
759 // Yes, there is a compression section, so extract the contents
760 // Decompress the image here
762 Section
= (EFI_COMMON_SECTION_HEADER
*) (UINTN
) (VOID
*) ((UINT8
*) (FfsFileHeader
) + (UINTN
) sizeof (EFI_FFS_FILE_HEADER
));
765 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
766 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
769 // Was the DXE Core file encapsulated in a GUID'd section?
771 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
773 // Locate the GUID'd Section Extractor
775 GuidedSectionHeader
= (VOID
*) (Section
+ 1);
778 // This following code constitutes the addition of the security model
782 // Set a default authenticatino state
784 AuthenticationStatus
= 0;
786 Status
= PeiServicesLocatePpi (
787 &gEfiPeiSectionExtractionPpiGuid
,
790 (VOID
**)&SectionExtract
793 if (EFI_ERROR (Status
)) {
797 // Verify Authentication State
799 CopyMem (&TempGuid
, Section
+ 1, sizeof (EFI_GUID
));
801 Status
= SectionExtract
->PeiGetSection (
802 GetPeiServicesTablePointer(),
804 (EFI_SECTION_TYPE
*) &SectionType
,
809 &AuthenticationStatus
812 if (EFI_ERROR (Status
)) {
816 // If not ask the Security PPI, if exists, for disposition
819 Status
= PeiServicesLocatePpi (
820 &gEfiPeiSecurityPpiGuid
,
825 if (EFI_ERROR (Status
)) {
829 Status
= Security
->AuthenticationState (
830 GetPeiServicesTablePointer(),
831 (struct _EFI_PEI_SECURITY_PPI
*) Security
,
832 AuthenticationStatus
,
837 if (EFI_ERROR (Status
)) {
841 // If there is a security violation, report to caller and have
842 // the upper-level logic possible engender a crisis recovery
844 if (StartCrisisRecovery
) {
845 return EFI_SECURITY_VIOLATION
;
849 if (Section
->Type
== EFI_SECTION_PE32
) {
851 // This is what we want
853 *Pe32Data
= (VOID
*) (Section
+ 1);
855 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
857 // This is a compression set, expand it
859 CompressionSection
= (EFI_COMPRESSION_SECTION
*) Section
;
861 switch (CompressionSection
->CompressionType
) {
862 case EFI_STANDARD_COMPRESSION
:
863 if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress
)) {
864 DecompressLibrary
= &gTianoDecompress
;
867 return EFI_NOT_FOUND
;
871 case EFI_CUSTOMIZED_COMPRESSION
:
873 // Load user customized compression protocol.
875 if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress
)) {
876 DecompressLibrary
= &gCustomDecompress
;
879 return EFI_NOT_FOUND
;
883 case EFI_NOT_COMPRESSED
:
886 // Need to support not compressed file
888 ASSERT_EFI_ERROR (Status
);
889 return EFI_NOT_FOUND
;
892 Status
= DecompressLibrary
->GetInfo (
893 (UINT8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
894 (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION
),
898 if (EFI_ERROR (Status
)) {
902 return EFI_NOT_FOUND
;
906 // Allocate scratch buffer
908 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
909 if (ScratchBuffer
== NULL
) {
910 return EFI_OUT_OF_RESOURCES
;
914 // Allocate destination buffer
916 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
917 if (DstBuffer
== NULL
) {
918 return EFI_OUT_OF_RESOURCES
;
922 // Call decompress function
924 Status
= DecompressLibrary
->Decompress (
925 (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
930 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) DstBuffer
;
931 if (CmpSection
->Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
933 // Firmware Volume Image in this Section
934 // Skip the section header to get FvHeader
936 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (CmpSection
+ 1);
938 if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
940 // Adjust Fv Base Address Alignment based on Align Attributes in Fv Header
944 // When FvImage support Alignment, we need to check whether
945 // its alignment is correct.
947 if (FvHeader
->Attributes
| EFI_FVB_ALIGNMENT_CAP
) {
950 // Calculate the mini alignment for this FvImage
952 FvAlignment
= 1 << (LowBitSet32 (FvHeader
->Attributes
>> 16) + 1);
955 // If current FvImage base address doesn't meet the its alignment,
956 // we need to reload this FvImage to another correct memory address.
958 if (((UINTN
) FvHeader
% FvAlignment
) != 0) {
959 DstBuffer
= AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN
) FvHeader
->FvLength
), FvAlignment
);
960 if (DstBuffer
== NULL
) {
961 return EFI_OUT_OF_RESOURCES
;
963 CopyMem (DstBuffer
, FvHeader
, (UINTN
) FvHeader
->FvLength
);
964 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) DstBuffer
;
968 // Build new FvHob for new decompressed Fv image.
970 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
, FvHeader
->FvLength
);
973 // Set the original FvHob to unused.
975 if (OrigHob
!= NULL
) {
976 OrigHob
->Header
->HobType
= EFI_HOB_TYPE_UNUSED
;
980 // when search FvImage Section return true.
982 if (SectionType
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
983 *Pe32Data
= (VOID
*) FvHeader
;
986 return EFI_NOT_FOUND
;
992 // Decompress successfully.
993 // Loop the decompressed data searching for expected section.
995 CmpFileData
= (VOID
*) DstBuffer
;
996 CmpFileSize
= DstBufferSize
;
998 CmpSectionLength
= *(UINT32
*) (CmpSection
->Size
) & 0x00ffffff;
999 if (CmpSection
->Type
== EFI_SECTION_PE32
) {
1001 // This is what we want
1003 *Pe32Data
= (VOID
*) (CmpSection
+ 1);
1007 OccupiedCmpSectionLength
= GetOccupiedSize (CmpSectionLength
, 4);
1008 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) CmpSection
+ OccupiedCmpSectionLength
);
1009 } while (CmpSection
->Type
!= 0 && (UINTN
) ((UINT8
*) CmpSection
- (UINT8
*) CmpFileData
) < CmpFileSize
);
1012 // End of the decompression activity
1015 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
1016 FileSize
= FfsFileHeader
->Size
[0] & 0xFF;
1017 FileSize
+= (FfsFileHeader
->Size
[1] << 8) & 0xFF00;
1018 FileSize
+= (FfsFileHeader
->Size
[2] << 16) & 0xFF0000;
1019 FileSize
&= 0x00FFFFFF;
1020 } while (Section
->Type
!= 0 && (UINTN
) ((UINT8
*) Section
- (UINT8
*) FfsFileHeader
) < FileSize
);
1023 // search all sections (compression and non compression) in this FFS, don't
1024 // find expected section.
1026 return EFI_NOT_FOUND
;
1029 // For those FFS that doesn't contain compression section, directly search
1030 // PE or TE section in this FFS.
1033 Status
= PeiServicesFfsFindSectionData (
1039 if (EFI_ERROR (Status
)) {
1040 Status
= PeiServicesFfsFindSectionData (
1045 if (EFI_ERROR (Status
)) {
1051 *Pe32Data
= SectionData
;