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 BOOLEAN gInMemory
= FALSE
;
28 // Module Globals used in the DXE to PEI handoff
29 // These must be module globals, so the stack can be switched
31 static EFI_DXE_IPL_PPI mDxeIplPpi
= {
35 static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi
= {
39 static EFI_PEI_PPI_DESCRIPTOR mPpiList
[] = {
41 EFI_PEI_PPI_DESCRIPTOR_PPI
,
42 &gEfiPeiFvFileLoaderPpiGuid
,
46 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
52 static EFI_PEI_PPI_DESCRIPTOR mPpiSignal
= {
53 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
54 &gEfiEndOfPeiSignalPpiGuid
,
58 GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gEfiDecompress
= {
59 UefiDecompressGetInfo
,
63 GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gTianoDecompress
= {
64 TianoDecompressGetInfo
,
68 GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gCustomDecompress
= {
69 CustomDecompressGetInfo
,
75 PeimInitializeDxeIpl (
76 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
77 IN EFI_PEI_SERVICES
**PeiServices
83 Initializes the Dxe Ipl PPI
87 FfsHeader - Pointer to FFS file header
88 PeiServices - General purpose services available to every PEIM.
97 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
98 EFI_BOOT_MODE BootMode
;
100 Status
= PeiServicesGetBootMode (&BootMode
);
101 ASSERT_EFI_ERROR (Status
);
103 if (!gInMemory
&& (BootMode
!= BOOT_ON_S3_RESUME
)) {
105 // The DxeIpl has not yet been shadowed
107 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
110 // Shadow DxeIpl and then re-run its entry point
112 Status
= ShadowDxeIpl (FfsHeader
, PeiEfiPeiPeCoffLoader
);
115 // Install FvFileLoader and DxeIpl PPIs.
117 Status
= PeiServicesInstallPpi (mPpiList
);
118 ASSERT_EFI_ERROR(Status
);
127 IN EFI_DXE_IPL_PPI
*This
,
128 IN EFI_PEI_SERVICES
**PeiServices
,
129 IN EFI_PEI_HOB_POINTERS HobList
135 Main entry point to last PEIM
138 This - Entry point for DXE IPL PPI
139 PeiServices - General purpose services available to every PEIM.
140 HobList - Address to the Pei HOB list
144 EFI_SUCCESS - DEX core was successfully loaded.
145 EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core.
150 EFI_GUID DxeCoreFileName
;
151 EFI_GUID FirmwareFileName
;
154 EFI_PHYSICAL_ADDRESS DxeCoreAddress
;
156 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
;
157 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
158 EFI_BOOT_MODE BootMode
;
159 EFI_PEI_RECOVERY_MODULE_PPI
*PeiRecovery
;
160 EFI_PEI_S3_RESUME_PPI
*S3Resume
;
162 // PERF_START (PeiServices, L"DxeIpl", NULL, 0);
165 // if in S3 Resume, restore configure
167 Status
= PeiServicesGetBootMode (&BootMode
);
168 ASSERT_EFI_ERROR(Status
);
170 if (BootMode
== BOOT_ON_S3_RESUME
) {
171 Status
= PeiServicesLocatePpi (
172 &gEfiPeiS3ResumePpiGuid
,
177 ASSERT_EFI_ERROR (Status
);
179 Status
= S3Resume
->S3RestoreConfig (PeiServices
);
180 ASSERT_EFI_ERROR (Status
);
181 } else if (BootMode
== BOOT_IN_RECOVERY_MODE
) {
183 Status
= PeiServicesLocatePpi (
184 &gEfiPeiRecoveryModulePpiGuid
,
187 (VOID
**)&PeiRecovery
189 ASSERT_EFI_ERROR (Status
);
191 Status
= PeiRecovery
->LoadRecoveryCapsule (PeiServices
, PeiRecovery
);
192 if (EFI_ERROR (Status
)) {
193 DEBUG ((EFI_D_ERROR
, "Load Recovery Capsule Failed.(Status = %r)\n", Status
));
198 // Now should have a HOB with the DXE core w/ the old HOB destroyed
203 // Install the PEI Protocols that are shared between PEI and DXE
205 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
206 ASSERT (PeiEfiPeiPeCoffLoader
!= NULL
);
210 // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file
211 // The file found will be processed by PeiProcessFile: It will first be decompressed to
212 // a normal FV, then a corresponding FV type hob will be built.
214 Status
= PeiFindFile (
215 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
216 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
222 // Find the DXE Core in a Firmware Volume
224 Status
= PeiFindFile (
225 EFI_FV_FILETYPE_DXE_CORE
,
230 ASSERT_EFI_ERROR (Status
);
233 // Load the DXE Core from a Firmware Volume
235 Status
= PeiLoadFile (
236 PeiEfiPeiPeCoffLoader
,
242 ASSERT_EFI_ERROR (Status
);
245 // Add HOB for the DXE Core
255 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
259 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
262 if (FeaturePcdGet (PcdDxeIplBuildShareCodeHobs
)) {
263 if (FeaturePcdGet (PcdDxeIplSupportEfiDecompress
)) {
265 // Add HOB for the EFI Decompress Protocol
268 &gEfiDecompressProtocolGuid
,
269 (VOID
*)&gEfiDecompress
,
270 sizeof (gEfiDecompress
)
273 if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress
)) {
275 // Add HOB for the Tiano Decompress Protocol
278 &gEfiTianoDecompressProtocolGuid
,
279 (VOID
*)&gTianoDecompress
,
280 sizeof (gTianoDecompress
)
283 if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress
)) {
285 // Add HOB for the user customized Decompress Protocol
288 &gEfiCustomizedDecompressProtocolGuid
,
289 (VOID
*)&gCustomDecompress
,
290 sizeof (gCustomDecompress
)
295 // Add HOB for the PE/COFF Loader Protocol
298 &gEfiPeiPeCoffLoaderGuid
,
299 (VOID
*)&PeiEfiPeiPeCoffLoader
,
305 // Transfer control to the DXE Core
306 // The handoff state is simply a pointer to the HOB list
309 DEBUG ((EFI_D_INFO
, "DXE Core Entry Point 0x%08x\n", (UINTN
) DxeCoreEntryPoint
));
310 HandOffToDxeCore (DxeCoreEntryPoint
, HobList
, &mPpiSignal
);
312 // If we get here, then the DXE Core returned. This is an error
313 // Dxe Core should not return.
318 return EFI_OUT_OF_RESOURCES
;
324 IN UINT16 SectionType
,
325 OUT EFI_GUID
*FileName
,
332 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes
333 described in the HOB list. Able to search in a compression set in a FFS file.
334 But only one level of compression is supported, that is, not able to search
335 in a compression set that is within another compression set.
339 Type - The Type of file to retrieve
341 SectionType - The type of section to retrieve from a file
343 FileName - The name of the file found in the Firmware Volume
345 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume
349 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to
350 the PE/COFF image is returned in Pe32Data
352 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List
356 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
357 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
359 EFI_PEI_HOB_POINTERS Hob
;
363 FfsFileHeader
= NULL
;
364 Status
= EFI_SUCCESS
;
367 // For each Firmware Volume, look for a specified type
368 // of file and break out until no one is found
370 Hob
.Raw
= GetHobList ();
371 while ((Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
)) != NULL
) {
372 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (Hob
.FirmwareVolume
->BaseAddress
);
373 Status
= PeiServicesFfsFindNextFile (
378 if (!EFI_ERROR (Status
)) {
379 Status
= PeiProcessFile (
385 CopyMem (FileName
, &FfsFileHeader
->Name
, sizeof (EFI_GUID
));
386 if (!EFI_ERROR (Status
)) {
390 Hob
.Raw
= GET_NEXT_HOB (Hob
);
392 return EFI_NOT_FOUND
;
397 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
,
399 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
400 OUT UINT64
*ImageSize
,
401 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
407 Loads and relocates a PE/COFF image into memory.
411 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
413 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
415 ImageAddress - The base address of the relocated PE/COFF image
417 ImageSize - The size of the relocated PE/COFF image
419 EntryPoint - The entry point of the relocated PE/COFF image
423 EFI_SUCCESS - The file was loaded and relocated
425 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
430 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
432 ZeroMem (&ImageContext
, sizeof (ImageContext
));
433 ImageContext
.Handle
= Pe32Data
;
434 Status
= GetImageReadFunction (&ImageContext
);
436 ASSERT_EFI_ERROR (Status
);
438 Status
= PeiEfiPeiPeCoffLoader
->GetImageInfo (PeiEfiPeiPeCoffLoader
, &ImageContext
);
439 if (EFI_ERROR (Status
)) {
443 // Allocate Memory for the image
445 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
));
446 ASSERT (ImageContext
.ImageAddress
!= 0);
449 // Load the image to our new buffer
451 Status
= PeiEfiPeiPeCoffLoader
->LoadImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
452 if (EFI_ERROR (Status
)) {
456 // Relocate the image in our new buffer
458 Status
= PeiEfiPeiPeCoffLoader
->RelocateImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
459 if (EFI_ERROR (Status
)) {
464 // Flush the instruction cache so the image data is written before we execute it
466 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
468 *ImageAddress
= ImageContext
.ImageAddress
;
469 *ImageSize
= ImageContext
.ImageSize
;
470 *EntryPoint
= ImageContext
.EntryPoint
;
477 IN EFI_FFS_FILE_HEADER
*DxeIplFileHeader
,
478 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
484 Shadow the DXE IPL to a different memory location. This occurs after permanent
485 memory has been discovered.
489 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
491 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
495 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
497 EFI_ ERROR - The shadow was unsuccessful.
503 UINTN OccupiedSectionLength
;
504 EFI_PHYSICAL_ADDRESS DxeIplAddress
;
506 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint
;
508 EFI_COMMON_SECTION_HEADER
*Section
;
510 Section
= (EFI_COMMON_SECTION_HEADER
*) (DxeIplFileHeader
+ 1);
512 while ((Section
->Type
!= EFI_SECTION_PE32
) && (Section
->Type
!= EFI_SECTION_TE
)) {
513 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
514 OccupiedSectionLength
= GET_OCCUPIED_SIZE (SectionLength
, 4);
515 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
518 // Relocate DxeIpl into memory by using loadfile service
520 Status
= PeiLoadFile (
521 PeiEfiPeiPeCoffLoader
,
522 (VOID
*) (Section
+ 1),
528 if (Status
== EFI_SUCCESS
) {
530 // Set gInMemory global variable to TRUE to indicate the dxeipl is shadowed.
532 *(BOOLEAN
*) ((UINTN
) &gInMemory
+ (UINTN
) DxeIplEntryPoint
- (UINTN
) _ModuleEntryPoint
) = TRUE
;
533 Status
= ((EFI_PEIM_ENTRY_POINT
) (UINTN
) DxeIplEntryPoint
) (DxeIplFileHeader
, GetPeiServicesTablePointer());
542 IN EFI_PEI_FV_FILE_LOADER_PPI
*This
,
543 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
544 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
545 OUT UINT64
*ImageSize
,
546 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
552 Given a pointer to an FFS file containing a PE32 image, get the
553 information on the PE32 image, and then "load" it so that it
558 This - pointer to our file loader protocol
560 FfsHeader - pointer to the FFS file header of the FFS file that
561 contains the PE32 image we want to load
563 ImageAddress - returned address where the PE32 image is loaded
565 ImageSize - returned size of the loaded PE32 image
567 EntryPoint - entry point to the loaded PE32 image
571 EFI_SUCCESS - The FFS file was successfully loaded.
573 EFI_ERROR - Unable to load the FFS file.
577 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
582 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
585 // Preprocess the FFS file to get a pointer to the PE32 information
586 // in the enclosed PE32 image.
588 Status
= PeiProcessFile (
595 if (EFI_ERROR (Status
)) {
599 // Load the PE image from the FFS file
601 Status
= PeiLoadFile (
602 PeiEfiPeiPeCoffLoader
,
614 IN UINT16 SectionType
,
615 IN EFI_FFS_FILE_HEADER
*FfsFileHeader
,
617 IN EFI_PEI_HOB_POINTERS
*OrigHob
625 SectionType - The type of section in the FFS file to process.
627 FfsFileHeader - Pointer to the FFS file to process, looking for the
628 specified SectionType
630 Pe32Data - returned pointer to the start of the PE32 image found
635 EFI_SUCCESS - found the PE32 section in the FFS file
641 DECOMPRESS_LIBRARY
*DecompressLibrary
;
643 UINT8
*ScratchBuffer
;
644 UINT32 DstBufferSize
;
645 UINT32 ScratchBufferSize
;
646 EFI_COMMON_SECTION_HEADER
*CmpSection
;
647 UINTN CmpSectionLength
;
648 UINTN OccupiedCmpSectionLength
;
651 EFI_COMMON_SECTION_HEADER
*Section
;
653 UINTN OccupiedSectionLength
;
655 UINT32 AuthenticationStatus
;
656 EFI_PEI_SECTION_EXTRACTION_PPI
*SectionExtract
;
659 EFI_PEI_SECURITY_PPI
*Security
;
660 BOOLEAN StartCrisisRecovery
;
662 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
663 EFI_COMPRESSION_SECTION
*CompressionSection
;
667 // Initialize local variables.
669 DecompressLibrary
= NULL
;
673 Status
= PeiServicesFfsFindSectionData (
674 EFI_SECTION_COMPRESSION
,
680 // First process the compression section
682 if (!EFI_ERROR (Status
)) {
684 // Yes, there is a compression section, so extract the contents
685 // Decompress the image here
687 Section
= (EFI_COMMON_SECTION_HEADER
*) (UINTN
) (VOID
*) ((UINT8
*) (FfsFileHeader
) + (UINTN
) sizeof (EFI_FFS_FILE_HEADER
));
690 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
691 OccupiedSectionLength
= GET_OCCUPIED_SIZE (SectionLength
, 4);
694 // Was the DXE Core file encapsulated in a GUID'd section?
696 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
699 // This following code constitutes the addition of the security model
703 // Set a default authenticatino state
705 AuthenticationStatus
= 0;
707 Status
= PeiServicesLocatePpi (
708 &gEfiPeiSectionExtractionPpiGuid
,
711 (VOID
**)&SectionExtract
714 if (EFI_ERROR (Status
)) {
718 // Verify Authentication State
720 CopyMem (&TempGuid
, Section
+ 1, sizeof (EFI_GUID
));
722 Status
= SectionExtract
->PeiGetSection (
723 GetPeiServicesTablePointer(),
725 (EFI_SECTION_TYPE
*) &SectionType
,
730 &AuthenticationStatus
733 if (EFI_ERROR (Status
)) {
737 // If not ask the Security PPI, if exists, for disposition
740 Status
= PeiServicesLocatePpi (
741 &gEfiPeiSecurityPpiGuid
,
746 if (EFI_ERROR (Status
)) {
750 Status
= Security
->AuthenticationState (
751 GetPeiServicesTablePointer(),
752 (struct _EFI_PEI_SECURITY_PPI
*) Security
,
753 AuthenticationStatus
,
758 if (EFI_ERROR (Status
)) {
762 // If there is a security violation, report to caller and have
763 // the upper-level logic possible engender a crisis recovery
765 if (StartCrisisRecovery
) {
766 return EFI_SECURITY_VIOLATION
;
770 if (Section
->Type
== EFI_SECTION_PE32
) {
772 // This is what we want
774 *Pe32Data
= (VOID
*) (Section
+ 1);
776 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
778 // This is a compression set, expand it
780 CompressionSection
= (EFI_COMPRESSION_SECTION
*) Section
;
782 switch (CompressionSection
->CompressionType
) {
783 case EFI_STANDARD_COMPRESSION
:
785 // Load EFI standard compression.
787 if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress
)) {
788 DecompressLibrary
= &gEfiDecompress
;
791 return EFI_NOT_FOUND
;
795 case EFI_CUSTOMIZED_COMPRESSION
:
797 // Load user customized compression.
799 if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress
)) {
800 DecompressLibrary
= &gCustomDecompress
;
803 return EFI_NOT_FOUND
;
807 case EFI_NOT_COMPRESSED
:
809 // Allocate destination buffer
811 DstBufferSize
= CompressionSection
->UncompressedLength
;
812 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
813 if (DstBuffer
== NULL
) {
814 return EFI_OUT_OF_RESOURCES
;
817 // stream is not actually compressed, just encapsulated. So just copy it.
819 CopyMem (DstBuffer
, CompressionSection
+ 1, DstBufferSize
);
824 // Don't support other unknown compression type.
826 ASSERT_EFI_ERROR (Status
);
827 return EFI_NOT_FOUND
;
830 if (CompressionSection
->CompressionType
!= EFI_NOT_COMPRESSED
) {
832 // For compressed data, decompress them to dstbuffer.
834 Status
= DecompressLibrary
->GetInfo (
835 (UINT8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
836 (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION
),
840 if (EFI_ERROR (Status
)) {
844 DEBUG ((EFI_D_ERROR
, "Decompress GetInfo Failed - %r\n", Status
));
845 return EFI_NOT_FOUND
;
849 // Allocate scratch buffer
851 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
852 if (ScratchBuffer
== NULL
) {
853 return EFI_OUT_OF_RESOURCES
;
857 // Allocate destination buffer
859 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
860 if (DstBuffer
== NULL
) {
861 return EFI_OUT_OF_RESOURCES
;
865 // Call decompress function
867 Status
= DecompressLibrary
->Decompress (
868 (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
872 if (EFI_ERROR (Status
)) {
876 DEBUG ((EFI_D_ERROR
, "Decompress Failed - %r\n", Status
));
877 return EFI_NOT_FOUND
;
881 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) DstBuffer
;
882 if (CmpSection
->Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
884 // Firmware Volume Image in this Section
885 // Skip the section header to get FvHeader
887 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (CmpSection
+ 1);
889 if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
891 // Adjust Fv Base Address Alignment based on Align Attributes in Fv Header
895 // When FvImage support Alignment, we need to check whether
896 // its alignment is correct.
898 if (FvHeader
->Attributes
| EFI_FVB_ALIGNMENT_CAP
) {
901 // Calculate the mini alignment for this FvImage
903 FvAlignment
= 1 << (LowBitSet32 (FvHeader
->Attributes
>> 16) + 1);
906 // If current FvImage base address doesn't meet the its alignment,
907 // we need to reload this FvImage to another correct memory address.
909 if (((UINTN
) FvHeader
% FvAlignment
) != 0) {
910 DstBuffer
= AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN
) FvHeader
->FvLength
), FvAlignment
);
911 if (DstBuffer
== NULL
) {
912 return EFI_OUT_OF_RESOURCES
;
914 CopyMem (DstBuffer
, FvHeader
, (UINTN
) FvHeader
->FvLength
);
915 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) DstBuffer
;
919 // Build new FvHob for new decompressed Fv image.
921 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
, FvHeader
->FvLength
);
924 // Set the original FvHob to unused.
926 if (OrigHob
!= NULL
) {
927 OrigHob
->Header
->HobType
= EFI_HOB_TYPE_UNUSED
;
931 // when search FvImage Section return true.
933 if (SectionType
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
934 *Pe32Data
= (VOID
*) FvHeader
;
937 return EFI_NOT_FOUND
;
942 // Decompress successfully.
943 // Loop the decompressed data searching for expected section.
945 CmpFileData
= (VOID
*) DstBuffer
;
946 CmpFileSize
= DstBufferSize
;
948 CmpSectionLength
= *(UINT32
*) (CmpSection
->Size
) & 0x00ffffff;
949 if (CmpSection
->Type
== EFI_SECTION_PE32
) {
951 // This is what we want
953 *Pe32Data
= (VOID
*) (CmpSection
+ 1);
957 OccupiedCmpSectionLength
= GET_OCCUPIED_SIZE (CmpSectionLength
, 4);
958 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) CmpSection
+ OccupiedCmpSectionLength
);
959 } while (CmpSection
->Type
!= 0 && (UINTN
) ((UINT8
*) CmpSection
- (UINT8
*) CmpFileData
) < CmpFileSize
);
962 // End of the decompression activity
965 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
966 FileSize
= FfsFileHeader
->Size
[0] & 0xFF;
967 FileSize
+= (FfsFileHeader
->Size
[1] << 8) & 0xFF00;
968 FileSize
+= (FfsFileHeader
->Size
[2] << 16) & 0xFF0000;
969 FileSize
&= 0x00FFFFFF;
970 } while (Section
->Type
!= 0 && (UINTN
) ((UINT8
*) Section
- (UINT8
*) FfsFileHeader
) < FileSize
);
973 // search all sections (compression and non compression) in this FFS, don't
974 // find expected section.
976 return EFI_NOT_FOUND
;
979 // For those FFS that doesn't contain compression section, directly search
980 // PE or TE section in this FFS.
983 Status
= PeiServicesFfsFindSectionData (
989 if (EFI_ERROR (Status
)) {
990 Status
= PeiServicesFfsFindSectionData (
995 if (EFI_ERROR (Status
)) {
1001 *Pe32Data
= SectionData
;