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 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 // Add architecture-specifc HOBs (including the BspStore HOB)
275 Status
= CreateArchSpecificHobs (&BspStore
);
276 ASSERT_EFI_ERROR (Status
);
279 // See if we are in crisis recovery
281 Status
= PeiServicesGetBootMode (&BootMode
);
282 if (!EFI_ERROR (Status
) && (BootMode
== BOOT_IN_RECOVERY_MODE
)) {
283 Status
= PeiServicesLocatePpi (
284 &gEfiPeiRecoveryModulePpiGuid
,
287 (VOID
**)&PeiRecovery
290 ASSERT_EFI_ERROR (Status
);
291 Status
= PeiRecovery
->LoadRecoveryCapsule (PeiServices
, PeiRecovery
);
292 if (EFI_ERROR (Status
)) {
293 DEBUG ((EFI_D_ERROR
, "Load Recovery Capsule Failed.(Status = %r)\n", Status
));
299 // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file
300 // The file found will be processed by PeiProcessFile: It will first be decompressed to
301 // a normal FV, then a corresponding FV type hob will be built.
303 Status
= PeiFindFile (
304 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
305 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
311 // Find the DXE Core in a Firmware Volume
313 Status
= PeiFindFile (
314 EFI_FV_FILETYPE_DXE_CORE
,
319 ASSERT_EFI_ERROR (Status
);
322 // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA \
323 // memory, it may be corrupted when copying FV to high-end memory
327 // Limit to 36 bits of addressing for debug. Should get it from CPU
329 PageTables
= CreateIdentityMappingPageTables (36);
333 // Load the DXE Core from a Firmware Volume
335 Status
= PeiLoadPeImage (
336 PeiEfiPeiPeCoffLoader
,
343 ASSERT_EFI_ERROR (Status
);
346 // Transfer control to the DXE Core
347 // The handoff state is simply a pointer to the HOB list
350 Status
= PeiServicesInstallPpi (&mPpiSignal
);
351 ASSERT_EFI_ERROR (Status
);
355 // Add HOB for the DXE Core
365 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
369 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
372 DEBUG ((EFI_D_INFO
, "DXE Core Entry\n"));
374 // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded.
375 // Call x64 drivers passing in single argument, a pointer to the HOBs.
379 (EFI_PHYSICAL_ADDRESS
)(UINTN
)(HobList
.Raw
),
386 // If we get here, then the DXE Core returned. This is an error
387 // Dxe Core should not return.
392 return EFI_OUT_OF_RESOURCES
;
398 IN UINT16 SectionType
,
399 OUT EFI_GUID
*FileName
,
406 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
407 described in the HOB list. Able to search in a compression set in a FFS file.
408 But only one level of compression is supported, that is, not able to search
409 in a compression set that is within another compression set.
413 Type - The Type of file to retrieve
415 SectionType - The type of section to retrieve from a file
417 FileName - The name of the file found in the Firmware Volume
419 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
423 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
424 the PE/COFF image is returned in Pe32Data
426 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
430 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
431 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
434 EFI_PEI_HOB_POINTERS Hob
;
438 FfsFileHeader
= NULL
;
440 Status
= EFI_SUCCESS
;
443 // For each Firmware Volume, look for a specified type
444 // of file and break out until no one is found
446 Hob
.Raw
= GetHobList ();
447 while ((Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
)) != NULL
) {
448 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (Hob
.FirmwareVolume
->BaseAddress
);
449 Status
= PeiServicesFfsFindNextFile (
454 if (!EFI_ERROR (Status
)) {
455 Status
= PeiProcessFile (
461 CopyMem (FileName
, &FfsFileHeader
->Name
, sizeof (EFI_GUID
));
462 if (!EFI_ERROR (Status
)) {
466 Hob
.Raw
= GET_NEXT_HOB (Hob
);
468 return EFI_NOT_FOUND
;
473 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
,
475 IN EFI_MEMORY_TYPE MemoryType
,
476 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
477 OUT UINT64
*ImageSize
,
478 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
484 Loads and relocates a PE/COFF image into memory.
488 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
490 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
492 ImageAddress - The base address of the relocated PE/COFF image
494 ImageSize - The size of the relocated PE/COFF image
496 EntryPoint - The entry point of the relocated PE/COFF image
500 EFI_SUCCESS - The file was loaded and relocated
501 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
506 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
507 EFI_PHYSICAL_ADDRESS MemoryBuffer
;
509 ZeroMem (&ImageContext
, sizeof (ImageContext
));
510 ImageContext
.Handle
= Pe32Data
;
511 Status
= GetImageReadFunction (&ImageContext
);
513 ASSERT_EFI_ERROR (Status
);
515 Status
= PeiEfiPeiPeCoffLoader
->GetImageInfo (PeiEfiPeiPeCoffLoader
, &ImageContext
);
516 if (EFI_ERROR (Status
)) {
520 // Allocate Memory for the image
523 // Allocate Memory for the image
525 PeiServicesAllocatePages (MemoryType
, EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
), &MemoryBuffer
);
526 ImageContext
.ImageAddress
= MemoryBuffer
;
527 ASSERT (ImageContext
.ImageAddress
!= 0);
530 // Load the image to our new buffer
533 Status
= PeiEfiPeiPeCoffLoader
->LoadImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
534 if (EFI_ERROR (Status
)) {
539 // Relocate the image in our new buffer
541 Status
= PeiEfiPeiPeCoffLoader
->RelocateImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
542 if (EFI_ERROR (Status
)) {
547 // Flush the instruction cache so the image data is written before we execute it
549 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
551 *ImageAddress
= ImageContext
.ImageAddress
;
552 *ImageSize
= ImageContext
.ImageSize
;
553 *EntryPoint
= ImageContext
.EntryPoint
;
560 IN EFI_FFS_FILE_HEADER
*DxeIplFileHeader
,
561 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
567 Shadow the DXE IPL to a different memory location. This occurs after permanent
568 memory has been discovered.
572 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
574 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
578 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
580 EFI_ ERROR - The shadow was unsuccessful.
586 UINTN OccupiedSectionLength
;
587 EFI_PHYSICAL_ADDRESS DxeIplAddress
;
589 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint
;
591 EFI_COMMON_SECTION_HEADER
*Section
;
593 Section
= (EFI_COMMON_SECTION_HEADER
*) (DxeIplFileHeader
+ 1);
595 while ((Section
->Type
!= EFI_SECTION_PE32
) && (Section
->Type
!= EFI_SECTION_TE
)) {
596 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
597 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
598 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
602 // Relocate DxeIpl into memory by using loadfile service
604 Status
= PeiLoadPeImage (
605 PeiEfiPeiPeCoffLoader
,
606 (VOID
*) (Section
+ 1),
613 if (Status
== EFI_SUCCESS
) {
615 // Install PeiInMemory to indicate the Dxeipl is shadowed
617 Status
= PeiServicesInstallPpi (&mPpiPeiInMemory
);
619 if (EFI_ERROR (Status
)) {
623 Status
= ((EFI_PEIM_ENTRY_POINT
) (UINTN
) DxeIplEntryPoint
) (DxeIplFileHeader
, GetPeiServicesTablePointer());
632 IN EFI_PEI_FV_FILE_LOADER_PPI
*This
,
633 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
634 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
635 OUT UINT64
*ImageSize
,
636 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
642 Given a pointer to an FFS file containing a PE32 image, get the
643 information on the PE32 image, and then "load" it so that it
648 This - pointer to our file loader protocol
649 FfsHeader - pointer to the FFS file header of the FFS file that
650 contains the PE32 image we want to load
651 ImageAddress - returned address where the PE32 image is loaded
652 ImageSize - returned size of the loaded PE32 image
653 EntryPoint - entry point to the loaded PE32 image
657 EFI_SUCCESS - The FFS file was successfully loaded.
658 EFI_ERROR - Unable to load the FFS file.
662 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
667 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
670 // Preprocess the FFS file to get a pointer to the PE32 information
671 // in the enclosed PE32 image.
673 Status
= PeiProcessFile (
680 if (EFI_ERROR (Status
)) {
684 // Load the PE image from the FFS file
686 Status
= PeiLoadPeImage (
687 PeiEfiPeiPeCoffLoader
,
700 IN UINT16 SectionType
,
701 IN EFI_FFS_FILE_HEADER
*FfsFileHeader
,
703 IN EFI_PEI_HOB_POINTERS
*OrigHob
711 SectionType - The type of section in the FFS file to process.
713 FfsFileHeader - Pointer to the FFS file to process, looking for the
714 specified SectionType
716 Pe32Data - returned pointer to the start of the PE32 image found
721 EFI_SUCCESS - found the PE32 section in the FFS file
727 DECOMPRESS_LIBRARY
*DecompressLibrary
;
729 UINT8
*ScratchBuffer
;
730 UINT32 DstBufferSize
;
731 UINT32 ScratchBufferSize
;
732 EFI_COMMON_SECTION_HEADER
*CmpSection
;
733 UINTN CmpSectionLength
;
734 UINTN OccupiedCmpSectionLength
;
737 EFI_COMMON_SECTION_HEADER
*Section
;
739 UINTN OccupiedSectionLength
;
741 EFI_GUID_DEFINED_SECTION
*GuidedSectionHeader
;
742 UINT32 AuthenticationStatus
;
743 EFI_PEI_SECTION_EXTRACTION_PPI
*SectionExtract
;
746 EFI_PEI_SECURITY_PPI
*Security
;
747 BOOLEAN StartCrisisRecovery
;
749 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
750 EFI_COMPRESSION_SECTION
*CompressionSection
;
753 Status
= PeiServicesFfsFindSectionData (
754 EFI_SECTION_COMPRESSION
,
760 // First process the compression section
762 if (!EFI_ERROR (Status
)) {
764 // Yes, there is a compression section, so extract the contents
765 // Decompress the image here
767 Section
= (EFI_COMMON_SECTION_HEADER
*) (UINTN
) (VOID
*) ((UINT8
*) (FfsFileHeader
) + (UINTN
) sizeof (EFI_FFS_FILE_HEADER
));
770 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
771 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
774 // Was the DXE Core file encapsulated in a GUID'd section?
776 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
778 // Locate the GUID'd Section Extractor
780 GuidedSectionHeader
= (VOID
*) (Section
+ 1);
783 // This following code constitutes the addition of the security model
787 // Set a default authenticatino state
789 AuthenticationStatus
= 0;
791 Status
= PeiServicesLocatePpi (
792 &gEfiPeiSectionExtractionPpiGuid
,
795 (VOID
**)&SectionExtract
798 if (EFI_ERROR (Status
)) {
802 // Verify Authentication State
804 CopyMem (&TempGuid
, Section
+ 1, sizeof (EFI_GUID
));
806 Status
= SectionExtract
->PeiGetSection (
807 GetPeiServicesTablePointer(),
809 (EFI_SECTION_TYPE
*) &SectionType
,
814 &AuthenticationStatus
817 if (EFI_ERROR (Status
)) {
821 // If not ask the Security PPI, if exists, for disposition
824 Status
= PeiServicesLocatePpi (
825 &gEfiPeiSecurityPpiGuid
,
830 if (EFI_ERROR (Status
)) {
834 Status
= Security
->AuthenticationState (
835 GetPeiServicesTablePointer(),
836 (struct _EFI_PEI_SECURITY_PPI
*) Security
,
837 AuthenticationStatus
,
842 if (EFI_ERROR (Status
)) {
846 // If there is a security violation, report to caller and have
847 // the upper-level logic possible engender a crisis recovery
849 if (StartCrisisRecovery
) {
850 return EFI_SECURITY_VIOLATION
;
854 if (Section
->Type
== EFI_SECTION_PE32
) {
856 // This is what we want
858 *Pe32Data
= (VOID
*) (Section
+ 1);
860 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
862 // This is a compression set, expand it
864 CompressionSection
= (EFI_COMPRESSION_SECTION
*) Section
;
866 switch (CompressionSection
->CompressionType
) {
867 case EFI_STANDARD_COMPRESSION
:
868 if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress
)) {
869 DecompressLibrary
= &gTianoDecompress
;
872 return EFI_NOT_FOUND
;
876 case EFI_CUSTOMIZED_COMPRESSION
:
878 // Load user customized compression protocol.
880 if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress
)) {
881 DecompressLibrary
= &gCustomDecompress
;
884 return EFI_NOT_FOUND
;
888 case EFI_NOT_COMPRESSED
:
891 // Need to support not compressed file
893 ASSERT_EFI_ERROR (Status
);
894 return EFI_NOT_FOUND
;
897 Status
= DecompressLibrary
->GetInfo (
898 (UINT8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
899 (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION
),
903 if (EFI_ERROR (Status
)) {
907 return EFI_NOT_FOUND
;
911 // Allocate scratch buffer
913 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
914 if (ScratchBuffer
== NULL
) {
915 return EFI_OUT_OF_RESOURCES
;
919 // Allocate destination buffer
921 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
922 if (DstBuffer
== NULL
) {
923 return EFI_OUT_OF_RESOURCES
;
927 // Call decompress function
929 Status
= DecompressLibrary
->Decompress (
930 (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
935 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) DstBuffer
;
936 if (CmpSection
->Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
938 // Firmware Volume Image in this Section
939 // Skip the section header to get FvHeader
941 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (CmpSection
+ 1);
943 if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
945 // Adjust Fv Base Address Alignment based on Align Attributes in Fv Header
949 // When FvImage support Alignment, we need to check whether
950 // its alignment is correct.
952 if (FvHeader
->Attributes
| EFI_FVB_ALIGNMENT_CAP
) {
955 // Calculate the mini alignment for this FvImage
957 FvAlignment
= 1 << (LowBitSet32 (FvHeader
->Attributes
>> 16) + 1);
960 // If current FvImage base address doesn't meet the its alignment,
961 // we need to reload this FvImage to another correct memory address.
963 if (((UINTN
) FvHeader
% FvAlignment
) != 0) {
964 DstBuffer
= AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN
) FvHeader
->FvLength
), FvAlignment
);
965 if (DstBuffer
== NULL
) {
966 return EFI_OUT_OF_RESOURCES
;
968 CopyMem (DstBuffer
, FvHeader
, (UINTN
) FvHeader
->FvLength
);
969 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) DstBuffer
;
973 // Build new FvHob for new decompressed Fv image.
975 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
, FvHeader
->FvLength
);
978 // Set the original FvHob to unused.
980 if (OrigHob
!= NULL
) {
981 OrigHob
->Header
->HobType
= EFI_HOB_TYPE_UNUSED
;
985 // when search FvImage Section return true.
987 if (SectionType
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
988 *Pe32Data
= (VOID
*) FvHeader
;
991 return EFI_NOT_FOUND
;
997 // Decompress successfully.
998 // Loop the decompressed data searching for expected section.
1000 CmpFileData
= (VOID
*) DstBuffer
;
1001 CmpFileSize
= DstBufferSize
;
1003 CmpSectionLength
= *(UINT32
*) (CmpSection
->Size
) & 0x00ffffff;
1004 if (CmpSection
->Type
== EFI_SECTION_PE32
) {
1006 // This is what we want
1008 *Pe32Data
= (VOID
*) (CmpSection
+ 1);
1012 OccupiedCmpSectionLength
= GetOccupiedSize (CmpSectionLength
, 4);
1013 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) CmpSection
+ OccupiedCmpSectionLength
);
1014 } while (CmpSection
->Type
!= 0 && (UINTN
) ((UINT8
*) CmpSection
- (UINT8
*) CmpFileData
) < CmpFileSize
);
1017 // End of the decompression activity
1020 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
1021 FileSize
= FfsFileHeader
->Size
[0] & 0xFF;
1022 FileSize
+= (FfsFileHeader
->Size
[1] << 8) & 0xFF00;
1023 FileSize
+= (FfsFileHeader
->Size
[2] << 16) & 0xFF0000;
1024 FileSize
&= 0x00FFFFFF;
1025 } while (Section
->Type
!= 0 && (UINTN
) ((UINT8
*) Section
- (UINT8
*) FfsFileHeader
) < FileSize
);
1028 // search all sections (compression and non compression) in this FFS, don't
1029 // find expected section.
1031 return EFI_NOT_FOUND
;
1034 // For those FFS that doesn't contain compression section, directly search
1035 // PE or TE section in this FFS.
1038 Status
= PeiServicesFfsFindSectionData (
1044 if (EFI_ERROR (Status
)) {
1045 Status
= PeiServicesFfsFindSectionData (
1050 if (EFI_ERROR (Status
)) {
1056 *Pe32Data
= SectionData
;