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
- CPU_STACK_ALIGNMENT
;
266 TopOfStack
= (EFI_PHYSICAL_ADDRESS
) ALIGN_POINTER (TopOfStack
, CPU_STACK_ALIGNMENT
);
269 // Add architecture-specifc HOBs (including the BspStore HOB)
271 Status
= CreateArchSpecificHobs (&BspStore
);
272 ASSERT_EFI_ERROR (Status
);
275 // See if we are in crisis recovery
277 Status
= PeiServicesGetBootMode (&BootMode
);
278 if (!EFI_ERROR (Status
) && (BootMode
== BOOT_IN_RECOVERY_MODE
)) {
279 Status
= PeiServicesLocatePpi (
280 &gEfiPeiRecoveryModulePpiGuid
,
283 (VOID
**)&PeiRecovery
286 ASSERT_EFI_ERROR (Status
);
287 Status
= PeiRecovery
->LoadRecoveryCapsule (PeiServices
, PeiRecovery
);
288 if (EFI_ERROR (Status
)) {
289 DEBUG ((EFI_D_ERROR
, "Load Recovery Capsule Failed.(Status = %r)\n", Status
));
295 // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file
296 // The file found will be processed by PeiProcessFile: It will first be decompressed to
297 // a normal FV, then a corresponding FV type hob will be built.
299 Status
= PeiFindFile (
300 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
301 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
307 // Find the DXE Core in a Firmware Volume
309 Status
= PeiFindFile (
310 EFI_FV_FILETYPE_DXE_CORE
,
315 ASSERT_EFI_ERROR (Status
);
318 // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA \
319 // memory, it may be corrupted when copying FV to high-end memory
323 // Limit to 36 bits of addressing for debug. Should get it from CPU
325 PageTables
= CreateIdentityMappingPageTables (36);
329 // Load the DXE Core from a Firmware Volume
331 Status
= PeiLoadPeImage (
332 PeiEfiPeiPeCoffLoader
,
339 ASSERT_EFI_ERROR (Status
);
342 // Transfer control to the DXE Core
343 // The handoff state is simply a pointer to the HOB list
346 Status
= PeiServicesInstallPpi (&mPpiSignal
);
347 ASSERT_EFI_ERROR (Status
);
351 // Add HOB for the DXE Core
361 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
365 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
368 DEBUG ((EFI_D_INFO
, "DXE Core Entry\n"));
370 // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded.
371 // Call x64 drivers passing in single argument, a pointer to the HOBs.
375 (EFI_PHYSICAL_ADDRESS
)(UINTN
)(HobList
.Raw
),
382 // If we get here, then the DXE Core returned. This is an error
383 // Dxe Core should not return.
388 return EFI_OUT_OF_RESOURCES
;
394 IN UINT16 SectionType
,
395 OUT EFI_GUID
*FileName
,
402 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
403 described in the HOB list. Able to search in a compression set in a FFS file.
404 But only one level of compression is supported, that is, not able to search
405 in a compression set that is within another compression set.
409 Type - The Type of file to retrieve
411 SectionType - The type of section to retrieve from a file
413 FileName - The name of the file found in the Firmware Volume
415 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
419 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
420 the PE/COFF image is returned in Pe32Data
422 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
426 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
427 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
430 EFI_PEI_HOB_POINTERS Hob
;
434 FfsFileHeader
= NULL
;
436 Status
= EFI_SUCCESS
;
439 // For each Firmware Volume, look for a specified type
440 // of file and break out until no one is found
442 Hob
.Raw
= GetHobList ();
443 while ((Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
)) != NULL
) {
444 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (Hob
.FirmwareVolume
->BaseAddress
);
445 Status
= PeiServicesFfsFindNextFile (
450 if (!EFI_ERROR (Status
)) {
451 Status
= PeiProcessFile (
457 CopyMem (FileName
, &FfsFileHeader
->Name
, sizeof (EFI_GUID
));
458 if (!EFI_ERROR (Status
)) {
462 Hob
.Raw
= GET_NEXT_HOB (Hob
);
464 return EFI_NOT_FOUND
;
469 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
,
471 IN EFI_MEMORY_TYPE MemoryType
,
472 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
473 OUT UINT64
*ImageSize
,
474 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
480 Loads and relocates a PE/COFF image into memory.
484 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
486 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
488 ImageAddress - The base address of the relocated PE/COFF image
490 ImageSize - The size of the relocated PE/COFF image
492 EntryPoint - The entry point of the relocated PE/COFF image
496 EFI_SUCCESS - The file was loaded and relocated
497 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
502 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
503 EFI_PHYSICAL_ADDRESS MemoryBuffer
;
505 ZeroMem (&ImageContext
, sizeof (ImageContext
));
506 ImageContext
.Handle
= Pe32Data
;
507 Status
= GetImageReadFunction (&ImageContext
);
509 ASSERT_EFI_ERROR (Status
);
511 Status
= PeiEfiPeiPeCoffLoader
->GetImageInfo (PeiEfiPeiPeCoffLoader
, &ImageContext
);
512 if (EFI_ERROR (Status
)) {
516 // Allocate Memory for the image
519 // Allocate Memory for the image
521 PeiServicesAllocatePages (MemoryType
, EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
), &MemoryBuffer
);
522 ImageContext
.ImageAddress
= MemoryBuffer
;
523 ASSERT (ImageContext
.ImageAddress
!= 0);
526 // Load the image to our new buffer
529 Status
= PeiEfiPeiPeCoffLoader
->LoadImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
530 if (EFI_ERROR (Status
)) {
535 // Relocate the image in our new buffer
537 Status
= PeiEfiPeiPeCoffLoader
->RelocateImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
538 if (EFI_ERROR (Status
)) {
543 // Flush the instruction cache so the image data is written before we execute it
545 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
547 *ImageAddress
= ImageContext
.ImageAddress
;
548 *ImageSize
= ImageContext
.ImageSize
;
549 *EntryPoint
= ImageContext
.EntryPoint
;
556 IN EFI_FFS_FILE_HEADER
*DxeIplFileHeader
,
557 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
563 Shadow the DXE IPL to a different memory location. This occurs after permanent
564 memory has been discovered.
568 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
570 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
574 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
576 EFI_ ERROR - The shadow was unsuccessful.
582 UINTN OccupiedSectionLength
;
583 EFI_PHYSICAL_ADDRESS DxeIplAddress
;
585 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint
;
587 EFI_COMMON_SECTION_HEADER
*Section
;
589 Section
= (EFI_COMMON_SECTION_HEADER
*) (DxeIplFileHeader
+ 1);
591 while ((Section
->Type
!= EFI_SECTION_PE32
) && (Section
->Type
!= EFI_SECTION_TE
)) {
592 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
593 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
594 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
598 // Relocate DxeIpl into memory by using loadfile service
600 Status
= PeiLoadPeImage (
601 PeiEfiPeiPeCoffLoader
,
602 (VOID
*) (Section
+ 1),
609 if (Status
== EFI_SUCCESS
) {
611 // Install PeiInMemory to indicate the Dxeipl is shadowed
613 Status
= PeiServicesInstallPpi (&mPpiPeiInMemory
);
615 if (EFI_ERROR (Status
)) {
619 Status
= ((EFI_PEIM_ENTRY_POINT
) (UINTN
) DxeIplEntryPoint
) (DxeIplFileHeader
, GetPeiServicesTablePointer());
628 IN EFI_PEI_FV_FILE_LOADER_PPI
*This
,
629 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
630 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
631 OUT UINT64
*ImageSize
,
632 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
638 Given a pointer to an FFS file containing a PE32 image, get the
639 information on the PE32 image, and then "load" it so that it
644 This - pointer to our file loader protocol
645 FfsHeader - pointer to the FFS file header of the FFS file that
646 contains the PE32 image we want to load
647 ImageAddress - returned address where the PE32 image is loaded
648 ImageSize - returned size of the loaded PE32 image
649 EntryPoint - entry point to the loaded PE32 image
653 EFI_SUCCESS - The FFS file was successfully loaded.
654 EFI_ERROR - Unable to load the FFS file.
658 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
663 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
666 // Preprocess the FFS file to get a pointer to the PE32 information
667 // in the enclosed PE32 image.
669 Status
= PeiProcessFile (
676 if (EFI_ERROR (Status
)) {
680 // Load the PE image from the FFS file
682 Status
= PeiLoadPeImage (
683 PeiEfiPeiPeCoffLoader
,
696 IN UINT16 SectionType
,
697 IN EFI_FFS_FILE_HEADER
*FfsFileHeader
,
699 IN EFI_PEI_HOB_POINTERS
*OrigHob
707 SectionType - The type of section in the FFS file to process.
709 FfsFileHeader - Pointer to the FFS file to process, looking for the
710 specified SectionType
712 Pe32Data - returned pointer to the start of the PE32 image found
717 EFI_SUCCESS - found the PE32 section in the FFS file
723 DECOMPRESS_LIBRARY
*DecompressLibrary
;
725 UINT8
*ScratchBuffer
;
726 UINT32 DstBufferSize
;
727 UINT32 ScratchBufferSize
;
728 EFI_COMMON_SECTION_HEADER
*CmpSection
;
729 UINTN CmpSectionLength
;
730 UINTN OccupiedCmpSectionLength
;
733 EFI_COMMON_SECTION_HEADER
*Section
;
735 UINTN OccupiedSectionLength
;
737 EFI_GUID_DEFINED_SECTION
*GuidedSectionHeader
;
738 UINT32 AuthenticationStatus
;
739 EFI_PEI_SECTION_EXTRACTION_PPI
*SectionExtract
;
742 EFI_PEI_SECURITY_PPI
*Security
;
743 BOOLEAN StartCrisisRecovery
;
745 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
746 EFI_COMPRESSION_SECTION
*CompressionSection
;
749 Status
= PeiServicesFfsFindSectionData (
750 EFI_SECTION_COMPRESSION
,
756 // First process the compression section
758 if (!EFI_ERROR (Status
)) {
760 // Yes, there is a compression section, so extract the contents
761 // Decompress the image here
763 Section
= (EFI_COMMON_SECTION_HEADER
*) (UINTN
) (VOID
*) ((UINT8
*) (FfsFileHeader
) + (UINTN
) sizeof (EFI_FFS_FILE_HEADER
));
766 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
767 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
770 // Was the DXE Core file encapsulated in a GUID'd section?
772 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
774 // Locate the GUID'd Section Extractor
776 GuidedSectionHeader
= (VOID
*) (Section
+ 1);
779 // This following code constitutes the addition of the security model
783 // Set a default authenticatino state
785 AuthenticationStatus
= 0;
787 Status
= PeiServicesLocatePpi (
788 &gEfiPeiSectionExtractionPpiGuid
,
791 (VOID
**)&SectionExtract
794 if (EFI_ERROR (Status
)) {
798 // Verify Authentication State
800 CopyMem (&TempGuid
, Section
+ 1, sizeof (EFI_GUID
));
802 Status
= SectionExtract
->PeiGetSection (
803 GetPeiServicesTablePointer(),
805 (EFI_SECTION_TYPE
*) &SectionType
,
810 &AuthenticationStatus
813 if (EFI_ERROR (Status
)) {
817 // If not ask the Security PPI, if exists, for disposition
820 Status
= PeiServicesLocatePpi (
821 &gEfiPeiSecurityPpiGuid
,
826 if (EFI_ERROR (Status
)) {
830 Status
= Security
->AuthenticationState (
831 GetPeiServicesTablePointer(),
832 (struct _EFI_PEI_SECURITY_PPI
*) Security
,
833 AuthenticationStatus
,
838 if (EFI_ERROR (Status
)) {
842 // If there is a security violation, report to caller and have
843 // the upper-level logic possible engender a crisis recovery
845 if (StartCrisisRecovery
) {
846 return EFI_SECURITY_VIOLATION
;
850 if (Section
->Type
== EFI_SECTION_PE32
) {
852 // This is what we want
854 *Pe32Data
= (VOID
*) (Section
+ 1);
856 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
858 // This is a compression set, expand it
860 CompressionSection
= (EFI_COMPRESSION_SECTION
*) Section
;
862 switch (CompressionSection
->CompressionType
) {
863 case EFI_STANDARD_COMPRESSION
:
864 if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress
)) {
865 DecompressLibrary
= &gTianoDecompress
;
868 return EFI_NOT_FOUND
;
872 case EFI_CUSTOMIZED_COMPRESSION
:
874 // Load user customized compression protocol.
876 if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress
)) {
877 DecompressLibrary
= &gCustomDecompress
;
880 return EFI_NOT_FOUND
;
884 case EFI_NOT_COMPRESSED
:
887 // Need to support not compressed file
889 ASSERT_EFI_ERROR (Status
);
890 return EFI_NOT_FOUND
;
893 Status
= DecompressLibrary
->GetInfo (
894 (UINT8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
895 (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION
),
899 if (EFI_ERROR (Status
)) {
903 return EFI_NOT_FOUND
;
907 // Allocate scratch buffer
909 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
910 if (ScratchBuffer
== NULL
) {
911 return EFI_OUT_OF_RESOURCES
;
915 // Allocate destination buffer
917 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
918 if (DstBuffer
== NULL
) {
919 return EFI_OUT_OF_RESOURCES
;
923 // Call decompress function
925 Status
= DecompressLibrary
->Decompress (
926 (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
931 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) DstBuffer
;
932 if (CmpSection
->Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
934 // Firmware Volume Image in this Section
935 // Skip the section header to get FvHeader
937 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (CmpSection
+ 1);
939 if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
941 // Adjust Fv Base Address Alignment based on Align Attributes in Fv Header
945 // When FvImage support Alignment, we need to check whether
946 // its alignment is correct.
948 if (FvHeader
->Attributes
| EFI_FVB_ALIGNMENT_CAP
) {
951 // Calculate the mini alignment for this FvImage
953 FvAlignment
= 1 << (LowBitSet32 (FvHeader
->Attributes
>> 16) + 1);
956 // If current FvImage base address doesn't meet the its alignment,
957 // we need to reload this FvImage to another correct memory address.
959 if (((UINTN
) FvHeader
% FvAlignment
) != 0) {
960 DstBuffer
= AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN
) FvHeader
->FvLength
), FvAlignment
);
961 if (DstBuffer
== NULL
) {
962 return EFI_OUT_OF_RESOURCES
;
964 CopyMem (DstBuffer
, FvHeader
, (UINTN
) FvHeader
->FvLength
);
965 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) DstBuffer
;
969 // Build new FvHob for new decompressed Fv image.
971 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
, FvHeader
->FvLength
);
974 // Set the original FvHob to unused.
976 if (OrigHob
!= NULL
) {
977 OrigHob
->Header
->HobType
= EFI_HOB_TYPE_UNUSED
;
981 // when search FvImage Section return true.
983 if (SectionType
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
984 *Pe32Data
= (VOID
*) FvHeader
;
987 return EFI_NOT_FOUND
;
993 // Decompress successfully.
994 // Loop the decompressed data searching for expected section.
996 CmpFileData
= (VOID
*) DstBuffer
;
997 CmpFileSize
= DstBufferSize
;
999 CmpSectionLength
= *(UINT32
*) (CmpSection
->Size
) & 0x00ffffff;
1000 if (CmpSection
->Type
== EFI_SECTION_PE32
) {
1002 // This is what we want
1004 *Pe32Data
= (VOID
*) (CmpSection
+ 1);
1008 OccupiedCmpSectionLength
= GetOccupiedSize (CmpSectionLength
, 4);
1009 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) CmpSection
+ OccupiedCmpSectionLength
);
1010 } while (CmpSection
->Type
!= 0 && (UINTN
) ((UINT8
*) CmpSection
- (UINT8
*) CmpFileData
) < CmpFileSize
);
1013 // End of the decompression activity
1016 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
1017 FileSize
= FfsFileHeader
->Size
[0] & 0xFF;
1018 FileSize
+= (FfsFileHeader
->Size
[1] << 8) & 0xFF00;
1019 FileSize
+= (FfsFileHeader
->Size
[2] << 16) & 0xFF0000;
1020 FileSize
&= 0x00FFFFFF;
1021 } while (Section
->Type
!= 0 && (UINTN
) ((UINT8
*) Section
- (UINT8
*) FfsFileHeader
) < FileSize
);
1024 // search all sections (compression and non compression) in this FFS, don't
1025 // find expected section.
1027 return EFI_NOT_FOUND
;
1030 // For those FFS that doesn't contain compression section, directly search
1031 // PE or TE section in this FFS.
1034 Status
= PeiServicesFfsFindSectionData (
1040 if (EFI_ERROR (Status
)) {
1041 Status
= PeiServicesFfsFindSectionData (
1046 if (EFI_ERROR (Status
)) {
1052 *Pe32Data
= SectionData
;