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 mPpiPeiInMemory
= {
56 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
61 static EFI_PEI_PPI_DESCRIPTOR mPpiSignal
= {
62 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
63 &gEfiEndOfPeiSignalPpiGuid
,
67 GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gEfiDecompress
= {
68 UefiDecompressGetInfo
,
72 GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gTianoDecompress
= {
73 TianoDecompressGetInfo
,
77 GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gCustomDecompress
= {
78 CustomDecompressGetInfo
,
91 OccupiedSize
= ActualSize
;
92 while ((OccupiedSize
& (Alignment
- 1)) != 0) {
101 PeimInitializeDxeIpl (
102 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
103 IN EFI_PEI_SERVICES
**PeiServices
109 Initializes the Dxe Ipl PPI
113 FfsHeader - Pointer to FFS file header
114 PeiServices - General purpose services available to every PEIM.
123 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
124 EFI_BOOT_MODE BootMode
;
126 Status
= PeiServicesGetBootMode (&BootMode
);
128 ASSERT_EFI_ERROR (Status
);
130 Status
= PeiServicesLocatePpi (
137 if (EFI_ERROR (Status
) && (BootMode
!= BOOT_ON_S3_RESUME
)) {
139 // The DxeIpl has not yet been shadowed
141 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
144 // Shadow DxeIpl and then re-run its entry point
146 Status
= ShadowDxeIpl (FfsHeader
, PeiEfiPeiPeCoffLoader
);
147 if (EFI_ERROR (Status
)) {
152 if (BootMode
!= BOOT_ON_S3_RESUME
) {
154 // The DxeIpl has been shadowed
159 // Install LoadFile PPI
161 Status
= PeiServicesInstallPpi (&mPpiLoadFile
);
163 if (EFI_ERROR (Status
)) {
168 // Install DxeIpl PPI
170 PeiServicesInstallPpi (&mPpiList
);
172 if (EFI_ERROR (Status
)) {
184 IN EFI_DXE_IPL_PPI
*This
,
185 IN EFI_PEI_SERVICES
**PeiServices
,
186 IN EFI_PEI_HOB_POINTERS HobList
192 Main entry point to last PEIM
196 This - Entry point for DXE IPL PPI
197 PeiServices - General purpose services available to every PEIM.
198 HobList - Address to the Pei HOB list
202 EFI_SUCCESS - DEX core was successfully loaded.
203 EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core.
208 EFI_PHYSICAL_ADDRESS TopOfStack
;
209 EFI_PHYSICAL_ADDRESS BaseOfStack
;
210 EFI_PHYSICAL_ADDRESS BspStore
;
211 EFI_GUID DxeCoreFileName
;
212 EFI_GUID FirmwareFileName
;
213 VOID
*DxeCorePe32Data
;
215 EFI_PHYSICAL_ADDRESS DxeCoreAddress
;
217 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
;
218 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
219 EFI_BOOT_MODE BootMode
;
220 EFI_PEI_RECOVERY_MODULE_PPI
*PeiRecovery
;
221 EFI_PEI_S3_RESUME_PPI
*S3Resume
;
222 EFI_PHYSICAL_ADDRESS PageTables
;
227 Status
= EFI_SUCCESS
;
230 // if in S3 Resume, restore configure
232 Status
= PeiServicesGetBootMode (&BootMode
);
234 if (!EFI_ERROR (Status
) && (BootMode
== BOOT_ON_S3_RESUME
)) {
235 Status
= PeiServicesLocatePpi (
236 &gEfiPeiS3ResumePpiGuid
,
242 ASSERT_EFI_ERROR (Status
);
244 Status
= S3Resume
->S3RestoreConfig (PeiServices
);
246 ASSERT_EFI_ERROR (Status
);
249 Status
= EFI_SUCCESS
;
252 // Install the PEI Protocols that are shared between PEI and DXE
254 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
255 ASSERT (PeiEfiPeiPeCoffLoader
!= NULL
);
258 // Allocate 128KB for the Stack
260 PeiServicesAllocatePages (EfiBootServicesData
, EFI_SIZE_TO_PAGES (STACK_SIZE
), &BaseOfStack
);
261 ASSERT (BaseOfStack
!= 0);
264 // Compute the top of the stack we were allocated, which is used to load X64 dxe core.
265 // Pre-allocate a 32 bytes which confroms to x64 calling convention.
267 // The first four parameters to a function are passed in rcx, rdx, r8 and r9.
268 // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the
269 // register parameters is reserved on the stack, in case the called function
270 // wants to spill them; this is important if the function is variadic.
272 TopOfStack
= BaseOfStack
+ EFI_SIZE_TO_PAGES (STACK_SIZE
) * EFI_PAGE_SIZE
- 32;
275 // X64 Calling Conventions requires that the stack must be aligned to 16 bytes
277 TopOfStack
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) ALIGN_POINTER (TopOfStack
, 16);
280 // Add architecture-specifc HOBs (including the BspStore HOB)
282 Status
= CreateArchSpecificHobs (&BspStore
);
283 ASSERT_EFI_ERROR (Status
);
286 // See if we are in crisis recovery
288 Status
= PeiServicesGetBootMode (&BootMode
);
289 if (!EFI_ERROR (Status
) && (BootMode
== BOOT_IN_RECOVERY_MODE
)) {
290 Status
= PeiServicesLocatePpi (
291 &gEfiPeiRecoveryModulePpiGuid
,
294 (VOID
**)&PeiRecovery
297 ASSERT_EFI_ERROR (Status
);
298 Status
= PeiRecovery
->LoadRecoveryCapsule (PeiServices
, PeiRecovery
);
299 if (EFI_ERROR (Status
)) {
300 DEBUG ((EFI_D_ERROR
, "Load Recovery Capsule Failed.(Status = %r)\n", Status
));
306 // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file
307 // The file found will be processed by PeiProcessFile: It will first be decompressed to
308 // a normal FV, then a corresponding FV type hob will be built.
310 Status
= PeiFindFile (
311 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
312 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
318 // Find the DXE Core in a Firmware Volume
320 Status
= PeiFindFile (
321 EFI_FV_FILETYPE_DXE_CORE
,
326 ASSERT_EFI_ERROR (Status
);
329 // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA
330 // memory, it may be corrupted when copying FV to high-end memory
335 // Limit to 36 bits of addressing for debug. Should get it from CPU
337 PageTables
= CreateIdentityMappingPageTables (36);
341 // Load the DXE Core from a Firmware Volume
343 Status
= PeiLoadPeImage (
344 PeiEfiPeiPeCoffLoader
,
351 ASSERT_EFI_ERROR (Status
);
354 // Transfer control to the DXE Core
355 // The handoff state is simply a pointer to the HOB list
358 Status
= PeiServicesInstallPpi (&mPpiSignal
);
359 ASSERT_EFI_ERROR (Status
);
363 // Add HOB for the DXE Core
373 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
377 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
380 DEBUG ((EFI_D_INFO
, "DXE Core Entry\n"));
382 // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded.
383 // Call x64 drivers passing in single argument, a pointer to the HOBs.
387 (EFI_PHYSICAL_ADDRESS
)(UINTN
)(HobList
.Raw
),
394 // If we get here, then the DXE Core returned. This is an error
395 // Dxe Core should not return.
400 return EFI_OUT_OF_RESOURCES
;
406 IN UINT16 SectionType
,
407 OUT EFI_GUID
*FileName
,
414 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
415 described in the HOB list. Able to search in a compression set in a FFS file.
416 But only one level of compression is supported, that is, not able to search
417 in a compression set that is within another compression set.
421 Type - The Type of file to retrieve
423 SectionType - The type of section to retrieve from a file
425 FileName - The name of the file found in the Firmware Volume
427 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
431 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
432 the PE/COFF image is returned in Pe32Data
434 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
438 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
439 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
442 EFI_PEI_HOB_POINTERS Hob
;
446 FfsFileHeader
= NULL
;
448 Status
= EFI_SUCCESS
;
451 // For each Firmware Volume, look for a specified type
452 // of file and break out until no one is found
454 Hob
.Raw
= GetHobList ();
455 while ((Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
)) != NULL
) {
456 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (Hob
.FirmwareVolume
->BaseAddress
);
457 Status
= PeiServicesFfsFindNextFile (
462 if (!EFI_ERROR (Status
)) {
463 Status
= PeiProcessFile (
469 CopyMem (FileName
, &FfsFileHeader
->Name
, sizeof (EFI_GUID
));
470 if (!EFI_ERROR (Status
)) {
474 Hob
.Raw
= GET_NEXT_HOB (Hob
);
476 return EFI_NOT_FOUND
;
481 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
,
483 IN EFI_MEMORY_TYPE MemoryType
,
484 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
485 OUT UINT64
*ImageSize
,
486 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
492 Loads and relocates a PE/COFF image into memory.
496 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
498 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
500 ImageAddress - The base address of the relocated PE/COFF image
502 ImageSize - The size of the relocated PE/COFF image
504 EntryPoint - The entry point of the relocated PE/COFF image
508 EFI_SUCCESS - The file was loaded and relocated
509 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
514 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
515 EFI_PHYSICAL_ADDRESS MemoryBuffer
;
517 ZeroMem (&ImageContext
, sizeof (ImageContext
));
518 ImageContext
.Handle
= Pe32Data
;
519 Status
= GetImageReadFunction (&ImageContext
);
521 ASSERT_EFI_ERROR (Status
);
523 Status
= PeiEfiPeiPeCoffLoader
->GetImageInfo (PeiEfiPeiPeCoffLoader
, &ImageContext
);
524 if (EFI_ERROR (Status
)) {
528 // Allocate Memory for the image
531 // Allocate Memory for the image
533 PeiServicesAllocatePages (MemoryType
, EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
), &MemoryBuffer
);
534 ImageContext
.ImageAddress
= MemoryBuffer
;
535 ASSERT (ImageContext
.ImageAddress
!= 0);
538 // Load the image to our new buffer
541 Status
= PeiEfiPeiPeCoffLoader
->LoadImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
542 if (EFI_ERROR (Status
)) {
547 // Relocate the image in our new buffer
549 Status
= PeiEfiPeiPeCoffLoader
->RelocateImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
550 if (EFI_ERROR (Status
)) {
555 // Flush the instruction cache so the image data is written before we execute it
557 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
559 *ImageAddress
= ImageContext
.ImageAddress
;
560 *ImageSize
= ImageContext
.ImageSize
;
561 *EntryPoint
= ImageContext
.EntryPoint
;
568 IN EFI_FFS_FILE_HEADER
*DxeIplFileHeader
,
569 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
575 Shadow the DXE IPL to a different memory location. This occurs after permanent
576 memory has been discovered.
580 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
582 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
586 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
588 EFI_ ERROR - The shadow was unsuccessful.
594 UINTN OccupiedSectionLength
;
595 EFI_PHYSICAL_ADDRESS DxeIplAddress
;
597 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint
;
599 EFI_COMMON_SECTION_HEADER
*Section
;
601 Section
= (EFI_COMMON_SECTION_HEADER
*) (DxeIplFileHeader
+ 1);
603 while ((Section
->Type
!= EFI_SECTION_PE32
) && (Section
->Type
!= EFI_SECTION_TE
)) {
604 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
605 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
606 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
610 // Relocate DxeIpl into memory by using loadfile service
612 Status
= PeiLoadPeImage (
613 PeiEfiPeiPeCoffLoader
,
614 (VOID
*) (Section
+ 1),
621 if (Status
== EFI_SUCCESS
) {
623 // Install PeiInMemory to indicate the Dxeipl is shadowed
625 Status
= PeiServicesInstallPpi (&mPpiPeiInMemory
);
627 if (EFI_ERROR (Status
)) {
631 Status
= ((EFI_PEIM_ENTRY_POINT
) (UINTN
) DxeIplEntryPoint
) (DxeIplFileHeader
, GetPeiServicesTablePointer());
640 IN EFI_PEI_FV_FILE_LOADER_PPI
*This
,
641 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
642 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
643 OUT UINT64
*ImageSize
,
644 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
650 Given a pointer to an FFS file containing a PE32 image, get the
651 information on the PE32 image, and then "load" it so that it
656 This - pointer to our file loader protocol
657 FfsHeader - pointer to the FFS file header of the FFS file that
658 contains the PE32 image we want to load
659 ImageAddress - returned address where the PE32 image is loaded
660 ImageSize - returned size of the loaded PE32 image
661 EntryPoint - entry point to the loaded PE32 image
665 EFI_SUCCESS - The FFS file was successfully loaded.
666 EFI_ERROR - Unable to load the FFS file.
670 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
675 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
678 // Preprocess the FFS file to get a pointer to the PE32 information
679 // in the enclosed PE32 image.
681 Status
= PeiProcessFile (
688 if (EFI_ERROR (Status
)) {
692 // Load the PE image from the FFS file
694 Status
= PeiLoadPeImage (
695 PeiEfiPeiPeCoffLoader
,
708 IN UINT16 SectionType
,
709 IN EFI_FFS_FILE_HEADER
*FfsFileHeader
,
711 IN EFI_PEI_HOB_POINTERS
*OrigHob
719 SectionType - The type of section in the FFS file to process.
721 FfsFileHeader - Pointer to the FFS file to process, looking for the
722 specified SectionType
724 Pe32Data - returned pointer to the start of the PE32 image found
729 EFI_SUCCESS - found the PE32 section in the FFS file
735 DECOMPRESS_LIBRARY
*DecompressLibrary
;
737 UINT8
*ScratchBuffer
;
738 UINT32 DstBufferSize
;
739 UINT32 ScratchBufferSize
;
740 EFI_COMMON_SECTION_HEADER
*CmpSection
;
741 UINTN CmpSectionLength
;
742 UINTN OccupiedCmpSectionLength
;
745 EFI_COMMON_SECTION_HEADER
*Section
;
747 UINTN OccupiedSectionLength
;
749 EFI_GUID_DEFINED_SECTION
*GuidedSectionHeader
;
750 UINT32 AuthenticationStatus
;
751 EFI_PEI_SECTION_EXTRACTION_PPI
*SectionExtract
;
754 EFI_PEI_SECURITY_PPI
*Security
;
755 BOOLEAN StartCrisisRecovery
;
757 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
758 EFI_COMPRESSION_SECTION
*CompressionSection
;
761 Status
= PeiServicesFfsFindSectionData (
762 EFI_SECTION_COMPRESSION
,
768 // First process the compression section
770 if (!EFI_ERROR (Status
)) {
772 // Yes, there is a compression section, so extract the contents
773 // Decompress the image here
775 Section
= (EFI_COMMON_SECTION_HEADER
*) (UINTN
) (VOID
*) ((UINT8
*) (FfsFileHeader
) + (UINTN
) sizeof (EFI_FFS_FILE_HEADER
));
778 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
779 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
782 // Was the DXE Core file encapsulated in a GUID'd section?
784 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
786 // Locate the GUID'd Section Extractor
788 GuidedSectionHeader
= (VOID
*) (Section
+ 1);
791 // This following code constitutes the addition of the security model
795 // Set a default authenticatino state
797 AuthenticationStatus
= 0;
799 Status
= PeiServicesLocatePpi (
800 &gEfiPeiSectionExtractionPpiGuid
,
803 (VOID
**)&SectionExtract
806 if (EFI_ERROR (Status
)) {
810 // Verify Authentication State
812 CopyMem (&TempGuid
, Section
+ 1, sizeof (EFI_GUID
));
814 Status
= SectionExtract
->PeiGetSection (
815 GetPeiServicesTablePointer(),
817 (EFI_SECTION_TYPE
*) &SectionType
,
822 &AuthenticationStatus
825 if (EFI_ERROR (Status
)) {
829 // If not ask the Security PPI, if exists, for disposition
832 Status
= PeiServicesLocatePpi (
833 &gEfiPeiSecurityPpiGuid
,
838 if (EFI_ERROR (Status
)) {
842 Status
= Security
->AuthenticationState (
843 GetPeiServicesTablePointer(),
844 (struct _EFI_PEI_SECURITY_PPI
*) Security
,
845 AuthenticationStatus
,
850 if (EFI_ERROR (Status
)) {
854 // If there is a security violation, report to caller and have
855 // the upper-level logic possible engender a crisis recovery
857 if (StartCrisisRecovery
) {
858 return EFI_SECURITY_VIOLATION
;
862 if (Section
->Type
== EFI_SECTION_PE32
) {
864 // This is what we want
866 *Pe32Data
= (VOID
*) (Section
+ 1);
868 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
870 // This is a compression set, expand it
872 CompressionSection
= (EFI_COMPRESSION_SECTION
*) Section
;
874 switch (CompressionSection
->CompressionType
) {
875 case EFI_STANDARD_COMPRESSION
:
876 if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress
)) {
877 DecompressLibrary
= &gTianoDecompress
;
880 return EFI_NOT_FOUND
;
884 case EFI_CUSTOMIZED_COMPRESSION
:
886 // Load user customized compression protocol.
888 if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress
)) {
889 DecompressLibrary
= &gCustomDecompress
;
892 return EFI_NOT_FOUND
;
896 case EFI_NOT_COMPRESSED
:
899 // Need to support not compressed file
901 ASSERT_EFI_ERROR (Status
);
902 return EFI_NOT_FOUND
;
905 Status
= DecompressLibrary
->GetInfo (
906 (UINT8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
907 (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION
),
911 if (EFI_ERROR (Status
)) {
915 return EFI_NOT_FOUND
;
919 // Allocate scratch buffer
921 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
922 if (ScratchBuffer
== NULL
) {
923 return EFI_OUT_OF_RESOURCES
;
927 // Allocate destination buffer
929 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
930 if (DstBuffer
== NULL
) {
931 return EFI_OUT_OF_RESOURCES
;
935 // Call decompress function
937 Status
= DecompressLibrary
->Decompress (
938 (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
943 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) DstBuffer
;
944 if (CmpSection
->Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
946 // Firmware Volume Image in this Section
947 // Skip the section header to get FvHeader
949 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (CmpSection
+ 1);
951 if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
953 // Adjust Fv Base Address Alignment based on Align Attributes in Fv Header
957 // When FvImage support Alignment, we need to check whether
958 // its alignment is correct.
960 if (FvHeader
->Attributes
| EFI_FVB_ALIGNMENT_CAP
) {
963 // Calculate the mini alignment for this FvImage
965 FvAlignment
= 1 << (LowBitSet32 (FvHeader
->Attributes
>> 16) + 1);
968 // If current FvImage base address doesn't meet the its alignment,
969 // we need to reload this FvImage to another correct memory address.
971 if (((UINTN
) FvHeader
% FvAlignment
) != 0) {
972 DstBuffer
= AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN
) FvHeader
->FvLength
), FvAlignment
);
973 if (DstBuffer
== NULL
) {
974 return EFI_OUT_OF_RESOURCES
;
976 CopyMem (DstBuffer
, FvHeader
, (UINTN
) FvHeader
->FvLength
);
977 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) DstBuffer
;
981 // Build new FvHob for new decompressed Fv image.
983 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
, FvHeader
->FvLength
);
986 // Set the original FvHob to unused.
988 if (OrigHob
!= NULL
) {
989 OrigHob
->Header
->HobType
= EFI_HOB_TYPE_UNUSED
;
993 // when search FvImage Section return true.
995 if (SectionType
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
996 *Pe32Data
= (VOID
*) FvHeader
;
999 return EFI_NOT_FOUND
;
1005 // Decompress successfully.
1006 // Loop the decompressed data searching for expected section.
1008 CmpFileData
= (VOID
*) DstBuffer
;
1009 CmpFileSize
= DstBufferSize
;
1011 CmpSectionLength
= *(UINT32
*) (CmpSection
->Size
) & 0x00ffffff;
1012 if (CmpSection
->Type
== EFI_SECTION_PE32
) {
1014 // This is what we want
1016 *Pe32Data
= (VOID
*) (CmpSection
+ 1);
1020 OccupiedCmpSectionLength
= GetOccupiedSize (CmpSectionLength
, 4);
1021 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) CmpSection
+ OccupiedCmpSectionLength
);
1022 } while (CmpSection
->Type
!= 0 && (UINTN
) ((UINT8
*) CmpSection
- (UINT8
*) CmpFileData
) < CmpFileSize
);
1025 // End of the decompression activity
1028 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
1029 FileSize
= FfsFileHeader
->Size
[0] & 0xFF;
1030 FileSize
+= (FfsFileHeader
->Size
[1] << 8) & 0xFF00;
1031 FileSize
+= (FfsFileHeader
->Size
[2] << 16) & 0xFF0000;
1032 FileSize
&= 0x00FFFFFF;
1033 } while (Section
->Type
!= 0 && (UINTN
) ((UINT8
*) Section
- (UINT8
*) FfsFileHeader
) < FileSize
);
1036 // search all sections (compression and non compression) in this FFS, don't
1037 // find expected section.
1039 return EFI_NOT_FOUND
;
1042 // For those FFS that doesn't contain compression section, directly search
1043 // PE or TE section in this FFS.
1046 Status
= PeiServicesFfsFindSectionData (
1052 if (EFI_ERROR (Status
)) {
1053 Status
= PeiServicesFfsFindSectionData (
1058 if (EFI_ERROR (Status
)) {
1064 *Pe32Data
= SectionData
;