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.
24 #include <Ppi/GuidedSectionExtraction.h>
26 // porting note remove later
27 #include "FrameworkPei.h"
28 // end of remove later
31 CustomDecompressExtractSection (
32 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI
*This
,
33 IN CONST VOID
*InputSection
,
34 OUT VOID
**OutputBuffer
,
35 OUT UINTN
*OutputSize
,
36 OUT UINT32
*AuthenticationStatus
39 BOOLEAN gInMemory
= FALSE
;
42 // Module Globals used in the DXE to PEI handoff
43 // These must be module globals, so the stack can be switched
45 static EFI_DXE_IPL_PPI mDxeIplPpi
= {
49 static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi
= {
53 static EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomDecompressExtractiongPpi
= {
54 CustomDecompressExtractSection
57 static EFI_PEI_PPI_DESCRIPTOR mPpiList
[] = {
59 EFI_PEI_PPI_DESCRIPTOR_PPI
,
60 &gEfiPeiFvFileLoaderPpiGuid
,
64 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
70 static EFI_PEI_PPI_DESCRIPTOR mPpiSignal
= {
71 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
72 &gEfiEndOfPeiSignalPpiGuid
,
78 PeimInitializeDxeIpl (
79 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
80 IN EFI_PEI_SERVICES
**PeiServices
86 Initializes the Dxe Ipl PPI
90 FfsHeader - Pointer to FFS file header
91 PeiServices - General purpose services available to every PEIM.
100 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
101 EFI_BOOT_MODE BootMode
;
102 EFI_GUID
**DecompressGuidList
;
103 UINT32 DecompressMethodNumber
;
104 EFI_PEI_PPI_DESCRIPTOR
*GuidPpi
;
106 Status
= PeiServicesGetBootMode (&BootMode
);
107 ASSERT_EFI_ERROR (Status
);
109 if (!gInMemory
&& (BootMode
!= BOOT_ON_S3_RESUME
)) {
111 // The DxeIpl has not yet been shadowed
113 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
116 // Shadow DxeIpl and then re-run its entry point
118 Status
= ShadowDxeIpl (FfsHeader
, PeiEfiPeiPeCoffLoader
);
121 // Get custom decompress method guid list
123 DecompressGuidList
= NULL
;
124 DecompressMethodNumber
= 0;
125 Status
= CustomDecompressGetAlgorithms (DecompressGuidList
, &DecompressMethodNumber
);
126 if (Status
== EFI_OUT_OF_RESOURCES
) {
127 DecompressGuidList
= (EFI_GUID
**) AllocatePages (EFI_SIZE_TO_PAGES (DecompressMethodNumber
* sizeof (EFI_GUID
*)));
128 ASSERT (DecompressGuidList
!= NULL
);
129 Status
= CustomDecompressGetAlgorithms (DecompressGuidList
, &DecompressMethodNumber
);
131 ASSERT_EFI_ERROR(Status
);
134 // Install custom decompress extraction guid ppi
136 if (DecompressMethodNumber
> 0) {
138 GuidPpi
= (EFI_PEI_PPI_DESCRIPTOR
*) AllocatePages (EFI_SIZE_TO_PAGES (DecompressMethodNumber
* sizeof (EFI_PEI_PPI_DESCRIPTOR
)));
139 ASSERT (GuidPpi
!= NULL
);
140 while (DecompressMethodNumber
-- > 0) {
141 GuidPpi
->Flags
= EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
;
142 GuidPpi
->Ppi
= &mCustomDecompressExtractiongPpi
;
143 GuidPpi
->Guid
= DecompressGuidList
[DecompressMethodNumber
];
144 Status
= PeiServicesInstallPpi (GuidPpi
++);
145 ASSERT_EFI_ERROR(Status
);
150 // Install FvFileLoader and DxeIpl PPIs.
152 Status
= PeiServicesInstallPpi (mPpiList
);
153 ASSERT_EFI_ERROR(Status
);
162 IN EFI_DXE_IPL_PPI
*This
,
163 IN EFI_PEI_SERVICES
**PeiServices
,
164 IN EFI_PEI_HOB_POINTERS HobList
170 Main entry point to last PEIM
173 This - Entry point for DXE IPL PPI
174 PeiServices - General purpose services available to every PEIM.
175 HobList - Address to the Pei HOB list
179 EFI_SUCCESS - DEX core was successfully loaded.
180 EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core.
185 EFI_GUID DxeCoreFileName
;
186 EFI_GUID FirmwareFileName
;
189 EFI_PHYSICAL_ADDRESS DxeCoreAddress
;
191 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint
;
192 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
193 EFI_BOOT_MODE BootMode
;
194 EFI_PEI_RECOVERY_MODULE_PPI
*PeiRecovery
;
195 EFI_PEI_S3_RESUME_PPI
*S3Resume
;
197 // PERF_START (PeiServices, L"DxeIpl", NULL, 0);
200 // if in S3 Resume, restore configure
202 Status
= PeiServicesGetBootMode (&BootMode
);
203 ASSERT_EFI_ERROR(Status
);
205 if (BootMode
== BOOT_ON_S3_RESUME
) {
206 Status
= PeiServicesLocatePpi (
207 &gEfiPeiS3ResumePpiGuid
,
212 ASSERT_EFI_ERROR (Status
);
214 Status
= S3Resume
->S3RestoreConfig (PeiServices
);
215 ASSERT_EFI_ERROR (Status
);
216 } else if (BootMode
== BOOT_IN_RECOVERY_MODE
) {
218 Status
= PeiServicesLocatePpi (
219 &gEfiPeiRecoveryModulePpiGuid
,
222 (VOID
**)&PeiRecovery
224 ASSERT_EFI_ERROR (Status
);
226 Status
= PeiRecovery
->LoadRecoveryCapsule (PeiServices
, PeiRecovery
);
227 if (EFI_ERROR (Status
)) {
228 DEBUG ((EFI_D_ERROR
, "Load Recovery Capsule Failed.(Status = %r)\n", Status
));
233 // Now should have a HOB with the DXE core w/ the old HOB destroyed
238 // Install the PEI Protocols that are shared between PEI and DXE
240 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
241 ASSERT (PeiEfiPeiPeCoffLoader
!= NULL
);
244 // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file
245 // The file found will be processed by PeiProcessFile: It will first be decompressed to
246 // a normal FV, then a corresponding FV type hob will be built.
248 Status
= PeiFindFile (
249 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
250 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
256 // Find the DXE Core in a Firmware Volume
258 Status
= PeiFindFile (
259 EFI_FV_FILETYPE_DXE_CORE
,
264 ASSERT_EFI_ERROR (Status
);
267 // Load the DXE Core from a Firmware Volume
269 Status
= PeiLoadFile (
270 PeiEfiPeiPeCoffLoader
,
276 ASSERT_EFI_ERROR (Status
);
279 // Add HOB for the DXE Core
289 // Add HOB for the PE/COFF Loader Protocol
292 &gEfiPeiPeCoffLoaderGuid
,
293 (VOID
*)&PeiEfiPeiPeCoffLoader
,
297 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
301 EFI_SOFTWARE_PEI_MODULE
| EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
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 EFI_SECTION_TYPE 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
);
374 // Make sure the FV HOB does not get corrupted.
376 ASSERT (FwVolHeader
->Signature
== EFI_FVH_SIGNATURE
);
378 Status
= PeiServicesFfsFindNextFile (
383 if (!EFI_ERROR (Status
)) {
384 Status
= PeiProcessFile (
390 CopyMem (FileName
, &FfsFileHeader
->Name
, sizeof (EFI_GUID
));
392 // Find all Fv type ffs to get all FvImage and add them into FvHob
394 if (!EFI_ERROR (Status
) && (Type
!= EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
)) {
398 Hob
.Raw
= GET_NEXT_HOB (Hob
);
400 return EFI_NOT_FOUND
;
405 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
,
407 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
408 OUT UINT64
*ImageSize
,
409 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
415 Loads and relocates a PE/COFF image into memory.
419 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
421 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
423 ImageAddress - The base address of the relocated PE/COFF image
425 ImageSize - The size of the relocated PE/COFF image
427 EntryPoint - The entry point of the relocated PE/COFF image
431 EFI_SUCCESS - The file was loaded and relocated
433 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
438 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
440 ZeroMem (&ImageContext
, sizeof (ImageContext
));
441 ImageContext
.Handle
= Pe32Data
;
442 Status
= GetImageReadFunction (&ImageContext
);
444 ASSERT_EFI_ERROR (Status
);
446 Status
= PeiEfiPeiPeCoffLoader
->GetImageInfo (PeiEfiPeiPeCoffLoader
, &ImageContext
);
447 if (EFI_ERROR (Status
)) {
451 // Allocate Memory for the image
453 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32
) ImageContext
.ImageSize
));
454 ASSERT (ImageContext
.ImageAddress
!= 0);
457 // Load the image to our new buffer
459 Status
= PeiEfiPeiPeCoffLoader
->LoadImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
460 if (EFI_ERROR (Status
)) {
464 // Relocate the image in our new buffer
466 Status
= PeiEfiPeiPeCoffLoader
->RelocateImage (PeiEfiPeiPeCoffLoader
, &ImageContext
);
467 if (EFI_ERROR (Status
)) {
472 // Flush the instruction cache so the image data is written before we execute it
474 InvalidateInstructionCacheRange ((VOID
*)(UINTN
)ImageContext
.ImageAddress
, (UINTN
)ImageContext
.ImageSize
);
476 *ImageAddress
= ImageContext
.ImageAddress
;
477 *ImageSize
= ImageContext
.ImageSize
;
478 *EntryPoint
= ImageContext
.EntryPoint
;
485 IN EFI_FFS_FILE_HEADER
*DxeIplFileHeader
,
486 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
492 Shadow the DXE IPL to a different memory location. This occurs after permanent
493 memory has been discovered.
497 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver
499 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol
503 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.
505 EFI_ ERROR - The shadow was unsuccessful.
511 UINTN OccupiedSectionLength
;
512 EFI_PHYSICAL_ADDRESS DxeIplAddress
;
514 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint
;
516 EFI_COMMON_SECTION_HEADER
*Section
;
518 Section
= (EFI_COMMON_SECTION_HEADER
*) (DxeIplFileHeader
+ 1);
520 while ((Section
->Type
!= EFI_SECTION_PE32
) && (Section
->Type
!= EFI_SECTION_TE
)) {
521 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
522 OccupiedSectionLength
= GET_OCCUPIED_SIZE (SectionLength
, 4);
523 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
526 // Relocate DxeIpl into memory by using loadfile service
528 Status
= PeiLoadFile (
529 PeiEfiPeiPeCoffLoader
,
530 (VOID
*) (Section
+ 1),
536 if (Status
== EFI_SUCCESS
) {
538 // Set gInMemory global variable to TRUE to indicate the dxeipl is shadowed.
540 *(BOOLEAN
*) ((UINTN
) &gInMemory
+ (UINTN
) DxeIplEntryPoint
- (UINTN
) _ModuleEntryPoint
) = TRUE
;
541 Status
= ((EFI_PEIM_ENTRY_POINT
) (UINTN
) DxeIplEntryPoint
) ((EFI_PEI_FILE_HANDLE
*) DxeIplFileHeader
, GetPeiServicesTablePointer());
550 IN EFI_PEI_FV_FILE_LOADER_PPI
*This
,
551 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
552 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
553 OUT UINT64
*ImageSize
,
554 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
560 Given a pointer to an FFS file containing a PE32 image, get the
561 information on the PE32 image, and then "load" it so that it
566 This - pointer to our file loader protocol
568 FfsHeader - pointer to the FFS file header of the FFS file that
569 contains the PE32 image we want to load
571 ImageAddress - returned address where the PE32 image is loaded
573 ImageSize - returned size of the loaded PE32 image
575 EntryPoint - entry point to the loaded PE32 image
579 EFI_SUCCESS - The FFS file was successfully loaded.
581 EFI_ERROR - Unable to load the FFS file.
585 EFI_PEI_PE_COFF_LOADER_PROTOCOL
*PeiEfiPeiPeCoffLoader
;
590 PeiEfiPeiPeCoffLoader
= (EFI_PEI_PE_COFF_LOADER_PROTOCOL
*)GetPeCoffLoaderProtocol ();
593 // Preprocess the FFS file to get a pointer to the PE32 information
594 // in the enclosed PE32 image.
596 Status
= PeiProcessFile (
602 if (EFI_ERROR (Status
)) {
603 Status
= PeiProcessFile (
610 if (EFI_ERROR (Status
)) {
615 // Load the PE image from the FFS file
617 Status
= PeiLoadFile (
618 PeiEfiPeiPeCoffLoader
,
630 IN EFI_SECTION_TYPE SectionType
,
631 IN EFI_FFS_FILE_HEADER
*FfsFileHeader
,
633 IN EFI_PEI_HOB_POINTERS
*OrigHob
641 SectionType - The type of section in the FFS file to process.
643 FfsFileHeader - Pointer to the FFS file to process, looking for the
644 specified SectionType
646 Pe32Data - returned pointer to the start of the PE32 image found
651 EFI_SUCCESS - found the PE32 section in the FFS file
657 UINT8
*ScratchBuffer
;
659 UINT32 ScratchBufferSize
;
660 EFI_COMMON_SECTION_HEADER
*CmpSection
;
661 UINTN CmpSectionLength
;
662 UINTN OccupiedCmpSectionLength
;
665 EFI_COMMON_SECTION_HEADER
*Section
;
667 UINTN OccupiedSectionLength
;
669 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
670 EFI_COMPRESSION_SECTION
*CompressionSection
;
671 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI
*SectionExtract
;
672 UINT32 AuthenticationStatus
;
675 // First try to find the required section in this ffs file.
677 Status
= PeiServicesFfsFindSectionData (
682 if (!EFI_ERROR (Status
)) {
687 // If not found, the required section may be in guided or compressed section.
688 // So, search guided or compressed section to process
690 Section
= (EFI_COMMON_SECTION_HEADER
*) (UINTN
) (VOID
*) ((UINT8
*) (FfsFileHeader
) + (UINTN
) sizeof (EFI_FFS_FILE_HEADER
));
691 FileSize
= FfsFileHeader
->Size
[0] & 0xFF;
692 FileSize
+= (FfsFileHeader
->Size
[1] << 8) & 0xFF00;
693 FileSize
+= (FfsFileHeader
->Size
[2] << 16) & 0xFF0000;
694 FileSize
&= 0x00FFFFFF;
695 OccupiedSectionLength
= 0;
699 // Initialize local variables.
704 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ OccupiedSectionLength
);
705 SectionLength
= *(UINT32
*) (Section
->Size
) & 0x00ffffff;
706 OccupiedSectionLength
= GET_OCCUPIED_SIZE (SectionLength
, 4);
709 // Was the DXE Core file encapsulated in a GUID'd section?
711 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
713 // Set a default authenticatino state
715 AuthenticationStatus
= 0;
717 // Locate extract guid section ppi
719 Status
= PeiServicesLocatePpi (
720 (EFI_GUID
*) (Section
+ 1),
723 (VOID
**)&SectionExtract
726 if (EFI_ERROR (Status
)) {
728 // ignore the unknown guid section
733 // Extract the contents from guid section
735 Status
= SectionExtract
->ExtractSection (
738 (VOID
**) &DstBuffer
,
740 &AuthenticationStatus
743 if (EFI_ERROR (Status
)) {
744 DEBUG ((EFI_D_ERROR
, "Extract section content failed - %r\n", Status
));
749 // Todo check AuthenticationStatus and do the verify
751 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
753 // This is a compression set, expand it
755 CompressionSection
= (EFI_COMPRESSION_SECTION
*) Section
;
757 switch (CompressionSection
->CompressionType
) {
758 case EFI_STANDARD_COMPRESSION
:
760 // Load EFI standard compression.
761 // For compressed data, decompress them to dstbuffer.
763 Status
= UefiDecompressGetInfo (
764 (UINT8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
765 (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION
),
766 (UINT32
*) &DstBufferSize
,
769 if (EFI_ERROR (Status
)) {
773 DEBUG ((EFI_D_ERROR
, "Decompress GetInfo Failed - %r\n", Status
));
774 return EFI_NOT_FOUND
;
777 // Allocate scratch buffer
779 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
780 if (ScratchBuffer
== NULL
) {
781 return EFI_OUT_OF_RESOURCES
;
784 // Allocate destination buffer
786 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
787 if (DstBuffer
== NULL
) {
788 return EFI_OUT_OF_RESOURCES
;
791 // Call decompress function
793 Status
= UefiDecompress (
794 (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1),
798 if (EFI_ERROR (Status
)) {
802 DEBUG ((EFI_D_ERROR
, "Decompress Failed - %r\n", Status
));
803 return EFI_NOT_FOUND
;
807 // porting note the original branch for customized compress is removed, it should be change to use GUID compress
809 case EFI_NOT_COMPRESSED
:
811 // Allocate destination buffer
813 DstBufferSize
= CompressionSection
->UncompressedLength
;
814 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
));
815 if (DstBuffer
== NULL
) {
816 return EFI_OUT_OF_RESOURCES
;
819 // stream is not actually compressed, just encapsulated. So just copy it.
821 CopyMem (DstBuffer
, CompressionSection
+ 1, DstBufferSize
);
826 // Don't support other unknown compression type.
828 ASSERT_EFI_ERROR (Status
);
829 return EFI_NOT_FOUND
;
833 // ignore other type sections
839 // Extract contents from guided or compressed sections.
840 // Loop the decompressed data searching for expected section.
842 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) DstBuffer
;
843 CmpFileData
= (VOID
*) DstBuffer
;
844 CmpFileSize
= DstBufferSize
;
846 CmpSectionLength
= *(UINT32
*) (CmpSection
->Size
) & 0x00ffffff;
847 if (CmpSection
->Type
== SectionType
) {
849 // This is what we want
851 if (SectionType
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
853 // Firmware Volume Image in this Section
854 // Skip the section header to get FvHeader
856 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (CmpSection
+ 1);
858 if (FvHeader
->Signature
== EFI_FVH_SIGNATURE
) {
860 // Because FvLength in FvHeader is UINT64 type,
861 // so FvHeader must meed at least 8 bytes alignment.
862 // If current FvImage base address doesn't meet its alignment,
863 // we need to reload this FvImage to another correct memory address.
865 if (((UINTN
) FvHeader
% sizeof (UINT64
)) != 0) {
866 CopyMem (DstBuffer
, FvHeader
, (UINTN
) CmpSectionLength
- sizeof (EFI_COMMON_SECTION_HEADER
));
867 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) DstBuffer
;
871 // Build new FvHob for new decompressed Fv image.
873 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
, FvHeader
->FvLength
);
876 // Set the original FvHob to unused.
878 if (OrigHob
!= NULL
) {
879 OrigHob
->Header
->HobType
= EFI_HOB_TYPE_UNUSED
;
882 // return found FvImage data.
884 *Pe32Data
= (VOID
*) FvHeader
;
889 // direct return the found section.
891 *Pe32Data
= (VOID
*) (CmpSection
+ 1);
895 OccupiedCmpSectionLength
= GET_OCCUPIED_SIZE (CmpSectionLength
, 4);
896 CmpSection
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) CmpSection
+ OccupiedCmpSectionLength
);
897 } while (CmpSection
->Type
!= 0 && (UINTN
) ((UINT8
*) CmpSection
- (UINT8
*) CmpFileData
) < CmpFileSize
);
898 } while (Section
->Type
!= 0 && (UINTN
) ((UINT8
*) Section
+ OccupiedSectionLength
- (UINT8
*) FfsFileHeader
) < FileSize
);
901 // search all sections (compression and non compression) in this FFS, don't
902 // find expected section.
904 return EFI_NOT_FOUND
;
908 The ExtractSection() function processes the input section and
909 returns a pointer to the section contents. If the section being
910 extracted does not require processing (if the section
911 GuidedSectionHeader.Attributes has the
912 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
913 OutputBuffer is just updated to point to the start of the
914 section's contents. Otherwise, *Buffer must be allocated
915 from PEI permanent memory.
917 @param This Indicates the
918 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
919 Buffer containing the input GUIDed section to be
920 processed. OutputBuffer OutputBuffer is
921 allocated from PEI permanent memory and contains
922 the new section stream.
924 @param OutputSize A pointer to a caller-allocated
925 UINTN in which the size of *OutputBuffer
926 allocation is stored. If the function
927 returns anything other than EFI_SUCCESS,
928 the value of OutputSize is undefined.
930 @param AuthenticationStatus A pointer to a caller-allocated
931 UINT32 that indicates the
932 authentication status of the
933 output buffer. If the input
934 section's GuidedSectionHeader.
935 Attributes field has the
936 EFI_GUIDED_SECTION_AUTH_STATUS_VALID
938 AuthenticationStatus must return
939 zero. These bits reflect the
940 status of the extraction
941 operation. If the function
942 returns anything other than
943 EFI_SUCCESS, the value of
944 AuthenticationStatus is
947 @retval EFI_SUCCESS The InputSection was
948 successfully processed and the
949 section contents were returned.
951 @retval EFI_OUT_OF_RESOURCES The system has insufficient
952 resources to process the request.
954 @reteval EFI_INVALID_PARAMETER The GUID in InputSection does
955 not match this instance of the
956 GUIDed Section Extraction PPI.
959 CustomDecompressExtractSection (
960 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI
*This
,
961 IN CONST VOID
*InputSection
,
962 OUT VOID
**OutputBuffer
,
963 OUT UINTN
*OutputSize
,
964 OUT UINT32
*AuthenticationStatus
968 UINT8
*ScratchBuffer
;
970 UINT32 SectionLength
;
971 UINT32 DestinationSize
;
974 // Set authentic value to zero.
976 *AuthenticationStatus
= 0;
978 // Calculate Section data Size
980 SectionLength
= *(UINT32
*) (((EFI_COMMON_SECTION_HEADER
*) InputSection
)->Size
) & 0x00ffffff;
982 // Get compressed data information
984 Status
= CustomDecompressGetInfo (
985 (GUID
*) ((UINT8
*) InputSection
+ sizeof (EFI_COMMON_SECTION_HEADER
)),
986 (UINT8
*) InputSection
+ sizeof (EFI_GUID_DEFINED_SECTION
),
987 SectionLength
- sizeof (EFI_GUID_DEFINED_SECTION
),
991 if (EFI_ERROR (Status
)) {
995 DEBUG ((EFI_D_ERROR
, "Extract guided section Failed - %r\n", Status
));
1000 // Allocate scratch buffer
1002 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchSize
));
1003 if (ScratchBuffer
== NULL
) {
1004 return EFI_OUT_OF_RESOURCES
;
1007 // Allocate destination buffer
1009 *OutputSize
= (UINTN
) DestinationSize
;
1010 *OutputBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (*OutputSize
));
1011 if (*OutputBuffer
== NULL
) {
1012 return EFI_OUT_OF_RESOURCES
;
1016 // Call decompress function
1018 Status
= CustomDecompress (
1019 (GUID
*) ((UINT8
*) InputSection
+ sizeof (EFI_COMMON_SECTION_HEADER
)),
1020 (UINT8
*) InputSection
+ sizeof (EFI_GUID_DEFINED_SECTION
),
1025 if (EFI_ERROR (Status
)) {
1027 // Decompress failed
1029 DEBUG ((EFI_D_ERROR
, "Extract guided section Failed - %r\n", Status
));