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, which is used to load X64 dxe core.
263 // Pre-allocate a 32 bytes which confroms to 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 // X64 Calling Conventions requires that the stack must be aligned to 16 bytes
275 TopOfStack
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) ALIGN_POINTER (TopOfStack
, 16);
278 // Add architecture-specifc HOBs (including the BspStore HOB)
280 Status
= CreateArchSpecificHobs (&BspStore
);
281 ASSERT_EFI_ERROR (Status
);
284 // See if we are in crisis recovery
286 Status
= PeiServicesGetBootMode (&BootMode
);
287 if (!EFI_ERROR (Status
) && (BootMode
== BOOT_IN_RECOVERY_MODE
)) {
288 Status
= PeiServicesLocatePpi (
289 &gEfiPeiRecoveryModulePpiGuid
,
292 (VOID
**)&PeiRecovery
295 ASSERT_EFI_ERROR (Status
);
296 Status
= PeiRecovery
->LoadRecoveryCapsule (PeiServices
, PeiRecovery
);
297 if (EFI_ERROR (Status
)) {
298 DEBUG ((EFI_D_ERROR
, "Load Recovery Capsule Failed.(Status = %r)\n", Status
));
304 // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file
305 // The file found will be processed by PeiProcessFile: It will first be decompressed to
306 // a normal FV, then a corresponding FV type hob will be built.
308 Status
= PeiFindFile (
309 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
310 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
316 // Find the DXE Core in a Firmware Volume
318 Status
= PeiFindFile (
319 EFI_FV_FILETYPE_DXE_CORE
,
324 ASSERT_EFI_ERROR (Status
);
327 // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA
328 // memory, it may be corrupted when copying FV to high-end memory
333 // Limit to 36 bits of addressing for debug. Should get it from CPU
335 PageTables
= CreateIdentityMappingPageTables (36);
339 // Load the DXE Core from a Firmware Volume
341 Status
= PeiLoadPeImage (
342 PeiEfiPeiPeCoffLoader
,
349 ASSERT_EFI_ERROR (Status
);
352 // Transfer control to the DXE Core
353 // The handoff state is simply a pointer to the HOB list
356 Status
= PeiServicesInstallPpi (&mPpiSignal
);
357 ASSERT_EFI_ERROR (Status
);
361 // Add HOB for the DXE Core
371 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
375 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
378 DEBUG ((EFI_D_INFO
, "DXE Core Entry\n"));
380 // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded.
381 // Call x64 drivers passing in single argument, a pointer to the HOBs.
385 (EFI_PHYSICAL_ADDRESS
)(UINTN
)(HobList
.Raw
),
392 // If we get here, then the DXE Core returned. This is an error
393 // Dxe Core should not return.
398 return EFI_OUT_OF_RESOURCES
;
404 IN UINT16 SectionType
,
405 OUT EFI_GUID
*FileName
,
412 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
413 described in the HOB list. Able to search in a compression set in a FFS file.
414 But only one level of compression is supported, that is, not able to search
415 in a compression set that is within another compression set.
419 Type - The Type of file to retrieve
421 SectionType - The type of section to retrieve from a file
423 FileName - The name of the file found in the Firmware Volume
425 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
429 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
430 the PE/COFF image is returned in Pe32Data
432 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
436 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
437 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
440 EFI_PEI_HOB_POINTERS Hob
;
444 FfsFileHeader
= NULL
;
446 Status
= EFI_SUCCESS
;
449 // For each Firmware Volume, look for a specified type
450 // of file and break out until no one is found
452 Hob
.Raw
= GetHobList ();
453 while ((Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
)) != NULL
) {
454 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (Hob
.FirmwareVolume
->BaseAddress
);
455 Status
= PeiServicesFfsFindNextFile (
460 if (!EFI_ERROR (Status
)) {
461 Status
= PeiProcessFile (
467 CopyMem (FileName
, &FfsFileHeader
->Name
, sizeof (EFI_GUID
));
468 if (!EFI_ERROR (Status
)) {
472 Hob
.Raw
= GET_NEXT_HOB (Hob
);
474 return EFI_NOT_FOUND
;
479 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
,
481 IN EFI_MEMORY_TYPE MemoryType
,
482 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
483 OUT UINT64
*ImageSize
,
484 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
490 Loads and relocates a PE/COFF image into memory.
494 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
496 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
498 ImageAddress - The base address of the relocated PE/COFF image
500 ImageSize - The size of the relocated PE/COFF image
502 EntryPoint - The entry point of the relocated PE/COFF image
506 EFI_SUCCESS - The file was loaded and relocated
507 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
512 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
513 EFI_PHYSICAL_ADDRESS MemoryBuffer
;
515 ZeroMem (&ImageContext
, sizeof (ImageContext
));
516 ImageContext
.Handle
= Pe32Data
;
517 Status
= GetImageReadFunction (&ImageContext
);
519 ASSERT_EFI_ERROR (Status
);
521 Status
= PeiEfiPeiPeCoffLoader
->GetImageInfo (PeiEfiPeiPeCoffLoader
, &ImageContext
);
522 if (EFI_ERROR (Status
)) {
526 // Allocate Memory for the image
529 // Allocate Memory for the image
531 PeiServicesAllocatePages (MemoryType
, EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
), &MemoryBuffer
);
532 ImageContext
.ImageAddress
= MemoryBuffer
;
533 ASSERT (ImageContext
.ImageAddress
!= 0);
536 // Load the image to our new buffer
539 Status
= PeiEfiPeiPeCoffLoader
->LoadImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
540 if (EFI_ERROR (Status
)) {
545 // Relocate the image in our new buffer
547 Status
= PeiEfiPeiPeCoffLoader
->RelocateImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
548 if (EFI_ERROR (Status
)) {
553 // Flush the instruction cache so the image data is written before we execute it
555 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
557 *ImageAddress
= ImageContext
.ImageAddress
;
558 *ImageSize
= ImageContext
.ImageSize
;
559 *EntryPoint
= ImageContext
.EntryPoint
;
566 IN EFI_FFS_FILE_HEADER
*DxeIplFileHeader
,
567 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
573 Shadow the DXE IPL to a different memory location. This occurs after permanent
574 memory has been discovered.
578 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
580 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
584 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
586 EFI_ ERROR - The shadow was unsuccessful.
592 UINTN OccupiedSectionLength
;
593 EFI_PHYSICAL_ADDRESS DxeIplAddress
;
595 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint
;
597 EFI_COMMON_SECTION_HEADER
*Section
;
599 Section
= (EFI_COMMON_SECTION_HEADER
*) (DxeIplFileHeader
+ 1);
601 while ((Section
->Type
!= EFI_SECTION_PE32
) && (Section
->Type
!= EFI_SECTION_TE
)) {
602 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
603 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
604 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
608 // Relocate DxeIpl into memory by using loadfile service
610 Status
= PeiLoadPeImage (
611 PeiEfiPeiPeCoffLoader
,
612 (VOID
*) (Section
+ 1),
619 if (Status
== EFI_SUCCESS
) {
621 // Install PeiInMemory to indicate the Dxeipl is shadowed
623 Status
= PeiServicesInstallPpi (&mPpiPeiInMemory
);
625 if (EFI_ERROR (Status
)) {
629 Status
= ((EFI_PEIM_ENTRY_POINT
) (UINTN
) DxeIplEntryPoint
) (DxeIplFileHeader
, GetPeiServicesTablePointer());
638 IN EFI_PEI_FV_FILE_LOADER_PPI
*This
,
639 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
640 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
641 OUT UINT64
*ImageSize
,
642 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
648 Given a pointer to an FFS file containing a PE32 image, get the
649 information on the PE32 image, and then "load" it so that it
654 This - pointer to our file loader protocol
655 FfsHeader - pointer to the FFS file header of the FFS file that
656 contains the PE32 image we want to load
657 ImageAddress - returned address where the PE32 image is loaded
658 ImageSize - returned size of the loaded PE32 image
659 EntryPoint - entry point to the loaded PE32 image
663 EFI_SUCCESS - The FFS file was successfully loaded.
664 EFI_ERROR - Unable to load the FFS file.
668 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
673 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
676 // Preprocess the FFS file to get a pointer to the PE32 information
677 // in the enclosed PE32 image.
679 Status
= PeiProcessFile (
686 if (EFI_ERROR (Status
)) {
690 // Load the PE image from the FFS file
692 Status
= PeiLoadPeImage (
693 PeiEfiPeiPeCoffLoader
,
706 IN UINT16 SectionType
,
707 IN EFI_FFS_FILE_HEADER
*FfsFileHeader
,
709 IN EFI_PEI_HOB_POINTERS
*OrigHob
717 SectionType - The type of section in the FFS file to process.
719 FfsFileHeader - Pointer to the FFS file to process, looking for the
720 specified SectionType
722 Pe32Data - returned pointer to the start of the PE32 image found
727 EFI_SUCCESS - found the PE32 section in the FFS file
733 DECOMPRESS_LIBRARY
*DecompressLibrary
;
735 UINT8
*ScratchBuffer
;
736 UINT32 DstBufferSize
;
737 UINT32 ScratchBufferSize
;
738 EFI_COMMON_SECTION_HEADER
*CmpSection
;
739 UINTN CmpSectionLength
;
740 UINTN OccupiedCmpSectionLength
;
743 EFI_COMMON_SECTION_HEADER
*Section
;
745 UINTN OccupiedSectionLength
;
747 EFI_GUID_DEFINED_SECTION
*GuidedSectionHeader
;
748 UINT32 AuthenticationStatus
;
749 EFI_PEI_SECTION_EXTRACTION_PPI
*SectionExtract
;
752 EFI_PEI_SECURITY_PPI
*Security
;
753 BOOLEAN StartCrisisRecovery
;
755 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
756 EFI_COMPRESSION_SECTION
*CompressionSection
;
759 Status
= PeiServicesFfsFindSectionData (
760 EFI_SECTION_COMPRESSION
,
766 // First process the compression section
768 if (!EFI_ERROR (Status
)) {
770 // Yes, there is a compression section, so extract the contents
771 // Decompress the image here
773 Section
= (EFI_COMMON_SECTION_HEADER
*) (UINTN
) (VOID
*) ((UINT8
*) (FfsFileHeader
) + (UINTN
) sizeof (EFI_FFS_FILE_HEADER
));
776 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
777 OccupiedSectionLength
= GetOccupiedSize (SectionLength
, 4);
780 // Was the DXE Core file encapsulated in a GUID'd section?
782 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
784 // Locate the GUID'd Section Extractor
786 GuidedSectionHeader
= (VOID
*) (Section
+ 1);
789 // This following code constitutes the addition of the security model
793 // Set a default authenticatino state
795 AuthenticationStatus
= 0;
797 Status
= PeiServicesLocatePpi (
798 &gEfiPeiSectionExtractionPpiGuid
,
801 (VOID
**)&SectionExtract
804 if (EFI_ERROR (Status
)) {
808 // Verify Authentication State
810 CopyMem (&TempGuid
, Section
+ 1, sizeof (EFI_GUID
));
812 Status
= SectionExtract
->PeiGetSection (
813 GetPeiServicesTablePointer(),
815 (EFI_SECTION_TYPE
*) &SectionType
,
820 &AuthenticationStatus
823 if (EFI_ERROR (Status
)) {
827 // If not ask the Security PPI, if exists, for disposition
830 Status
= PeiServicesLocatePpi (
831 &gEfiPeiSecurityPpiGuid
,
836 if (EFI_ERROR (Status
)) {
840 Status
= Security
->AuthenticationState (
841 GetPeiServicesTablePointer(),
842 (struct _EFI_PEI_SECURITY_PPI
*) Security
,
843 AuthenticationStatus
,
848 if (EFI_ERROR (Status
)) {
852 // If there is a security violation, report to caller and have
853 // the upper-level logic possible engender a crisis recovery
855 if (StartCrisisRecovery
) {
856 return EFI_SECURITY_VIOLATION
;
860 if (Section
->Type
== EFI_SECTION_PE32
) {
862 // This is what we want
864 *Pe32Data
= (VOID
*) (Section
+ 1);
866 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
868 // This is a compression set, expand it
870 CompressionSection
= (EFI_COMPRESSION_SECTION
*) Section
;
872 switch (CompressionSection
->CompressionType
) {
873 case EFI_STANDARD_COMPRESSION
:
874 if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress
)) {
875 DecompressLibrary
= &gTianoDecompress
;
878 return EFI_NOT_FOUND
;
882 case EFI_CUSTOMIZED_COMPRESSION
:
884 // Load user customized compression protocol.
886 if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress
)) {
887 DecompressLibrary
= &gCustomDecompress
;
890 return EFI_NOT_FOUND
;
894 case EFI_NOT_COMPRESSED
:
897 // Need to support not compressed file
899 ASSERT_EFI_ERROR (Status
);
900 return EFI_NOT_FOUND
;
903 Status
= DecompressLibrary
->GetInfo (
904 (UINT8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
905 (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION
),
909 if (EFI_ERROR (Status
)) {
913 return EFI_NOT_FOUND
;
917 // Allocate scratch buffer
919 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
920 if (ScratchBuffer
== NULL
) {
921 return EFI_OUT_OF_RESOURCES
;
925 // Allocate destination buffer
927 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
928 if (DstBuffer
== NULL
) {
929 return EFI_OUT_OF_RESOURCES
;
933 // Call decompress function
935 Status
= DecompressLibrary
->Decompress (
936 (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
941 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) DstBuffer
;
942 if (CmpSection
->Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
944 // Firmware Volume Image in this Section
945 // Skip the section header to get FvHeader
947 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (CmpSection
+ 1);
949 if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
951 // Adjust Fv Base Address Alignment based on Align Attributes in Fv Header
955 // When FvImage support Alignment, we need to check whether
956 // its alignment is correct.
958 if (FvHeader
->Attributes
| EFI_FVB_ALIGNMENT_CAP
) {
961 // Calculate the mini alignment for this FvImage
963 FvAlignment
= 1 << (LowBitSet32 (FvHeader
->Attributes
>> 16) + 1);
966 // If current FvImage base address doesn't meet the its alignment,
967 // we need to reload this FvImage to another correct memory address.
969 if (((UINTN
) FvHeader
% FvAlignment
) != 0) {
970 DstBuffer
= AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN
) FvHeader
->FvLength
), FvAlignment
);
971 if (DstBuffer
== NULL
) {
972 return EFI_OUT_OF_RESOURCES
;
974 CopyMem (DstBuffer
, FvHeader
, (UINTN
) FvHeader
->FvLength
);
975 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) DstBuffer
;
979 // Build new FvHob for new decompressed Fv image.
981 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
, FvHeader
->FvLength
);
984 // Set the original FvHob to unused.
986 if (OrigHob
!= NULL
) {
987 OrigHob
->Header
->HobType
= EFI_HOB_TYPE_UNUSED
;
991 // when search FvImage Section return true.
993 if (SectionType
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
994 *Pe32Data
= (VOID
*) FvHeader
;
997 return EFI_NOT_FOUND
;
1003 // Decompress successfully.
1004 // Loop the decompressed data searching for expected section.
1006 CmpFileData
= (VOID
*) DstBuffer
;
1007 CmpFileSize
= DstBufferSize
;
1009 CmpSectionLength
= *(UINT32
*) (CmpSection
->Size
) & 0x00ffffff;
1010 if (CmpSection
->Type
== EFI_SECTION_PE32
) {
1012 // This is what we want
1014 *Pe32Data
= (VOID
*) (CmpSection
+ 1);
1018 OccupiedCmpSectionLength
= GetOccupiedSize (CmpSectionLength
, 4);
1019 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) CmpSection
+ OccupiedCmpSectionLength
);
1020 } while (CmpSection
->Type
!= 0 && (UINTN
) ((UINT8
*) CmpSection
- (UINT8
*) CmpFileData
) < CmpFileSize
);
1023 // End of the decompression activity
1026 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
1027 FileSize
= FfsFileHeader
->Size
[0] & 0xFF;
1028 FileSize
+= (FfsFileHeader
->Size
[1] << 8) & 0xFF00;
1029 FileSize
+= (FfsFileHeader
->Size
[2] << 16) & 0xFF0000;
1030 FileSize
&= 0x00FFFFFF;
1031 } while (Section
->Type
!= 0 && (UINTN
) ((UINT8
*) Section
- (UINT8
*) FfsFileHeader
) < FileSize
);
1034 // search all sections (compression and non compression) in this FFS, don't
1035 // find expected section.
1037 return EFI_NOT_FOUND
;
1040 // For those FFS that doesn't contain compression section, directly search
1041 // PE or TE section in this FFS.
1044 Status
= PeiServicesFfsFindSectionData (
1050 if (EFI_ERROR (Status
)) {
1051 Status
= PeiServicesFfsFindSectionData (
1056 if (EFI_ERROR (Status
)) {
1062 *Pe32Data
= SectionData
;