2 Implementation of the 6 PEI Ffs (FV) APIs in library form.
4 This code only knows about a FV if it has a EFI_HOB_TYPE_FV entry in the HOB list
6 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <Library/ExtractGuidedSectionLib.h>
15 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
16 (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
19 Returns the highest bit set of the State field
21 @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY
22 in the Attributes field.
23 @param FfsHeader Pointer to FFS File Header
26 @retval the highest bit in the State field
32 IN UINT8 ErasePolarity
,
33 IN EFI_FFS_FILE_HEADER
*FfsHeader
36 EFI_FFS_FILE_STATE FileState
;
37 EFI_FFS_FILE_STATE HighestBit
;
39 FileState
= FfsHeader
->State
;
41 if (ErasePolarity
!= 0) {
42 FileState
= (EFI_FFS_FILE_STATE
) ~FileState
;
46 while (HighestBit
!= 0 && (HighestBit
& FileState
) == 0) {
54 Calculates the checksum of the header of a file.
55 The header is a zero byte checksum, so zero means header is good
57 @param FfsHeader Pointer to FFS File Header
59 @retval Checksum of the header
64 CalculateHeaderChecksum (
65 IN EFI_FFS_FILE_HEADER
*FileHeader
73 Ptr
= (UINT8
*)FileHeader
;
75 for (Index
= 0; Index
< sizeof (EFI_FFS_FILE_HEADER
) - 3; Index
+= 4) {
76 Sum
= (UINT8
)(Sum
+ Ptr
[Index
]);
77 Sum
= (UINT8
)(Sum
+ Ptr
[Index
+1]);
78 Sum
= (UINT8
)(Sum
+ Ptr
[Index
+2]);
79 Sum
= (UINT8
)(Sum
+ Ptr
[Index
+3]);
82 for ( ; Index
< sizeof (EFI_FFS_FILE_HEADER
); Index
++) {
83 Sum
= (UINT8
)(Sum
+ Ptr
[Index
]);
87 // State field (since this indicates the different state of file).
89 Sum
= (UINT8
)(Sum
- FileHeader
->State
);
91 // Checksum field of the file is not part of the header checksum.
93 Sum
= (UINT8
)(Sum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
99 Given a FileHandle return the VolumeHandle
101 @param FileHandle File handle to look up
102 @param VolumeHandle Match for FileHandle
104 @retval TRUE VolumeHandle is valid
111 IN EFI_PEI_FILE_HANDLE FileHandle
,
112 OUT EFI_PEI_FV_HANDLE
*VolumeHandle
115 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
116 EFI_PEI_HOB_POINTERS Hob
;
118 Hob
.Raw
= GetHobList ();
119 if (Hob
.Raw
== NULL
) {
124 Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
);
125 if (Hob
.Raw
!= NULL
) {
126 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)(Hob
.FirmwareVolume
->BaseAddress
);
127 if (((UINT64
)(UINTN
)FileHandle
> (UINT64
)(UINTN
)FwVolHeader
) && \
128 ((UINT64
)(UINTN
)FileHandle
<= ((UINT64
)(UINTN
)FwVolHeader
+ FwVolHeader
->FvLength
- 1)))
130 *VolumeHandle
= (EFI_PEI_FV_HANDLE
)FwVolHeader
;
134 Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, GET_NEXT_HOB (Hob
));
136 } while (Hob
.Raw
!= NULL
);
142 Given the input file pointer, search for the next matching file in the
143 FFS volume as defined by SearchType. The search starts from FileHeader inside
144 the Firmware Volume defined by FwVolHeader.
146 @param FileHandle File handle to look up
147 @param VolumeHandle Match for FileHandle
153 IN CONST EFI_PEI_FV_HANDLE FvHandle
,
154 IN CONST EFI_GUID
*FileName OPTIONAL
,
155 IN EFI_FV_FILETYPE SearchType
,
156 IN OUT EFI_PEI_FILE_HANDLE
*FileHandle
159 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
160 EFI_FFS_FILE_HEADER
**FileHeader
;
161 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
162 EFI_FIRMWARE_VOLUME_EXT_HEADER
*FwVolExHeaderInfo
;
164 UINT32 FileOccupiedSize
;
170 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)FvHandle
;
171 FileHeader
= (EFI_FFS_FILE_HEADER
**)FileHandle
;
173 FvLength
= FwVolHeader
->FvLength
;
174 if (FwVolHeader
->Attributes
& EFI_FVB2_ERASE_POLARITY
) {
181 // If FileHeader is not specified (NULL) or FileName is not NULL,
182 // start with the first file in the firmware volume. Otherwise,
183 // start from the FileHeader.
185 if ((*FileHeader
== NULL
) || (FileName
!= NULL
)) {
186 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FwVolHeader
+ FwVolHeader
->HeaderLength
);
187 if (FwVolHeader
->ExtHeaderOffset
!= 0) {
188 FwVolExHeaderInfo
= (EFI_FIRMWARE_VOLUME_EXT_HEADER
*)(((UINT8
*)FwVolHeader
) + FwVolHeader
->ExtHeaderOffset
);
189 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)(((UINT8
*)FwVolExHeaderInfo
) + FwVolExHeaderInfo
->ExtHeaderSize
);
193 // Length is 24 bits wide so mask upper 8 bits
194 // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
196 FileLength
= *(UINT32
*)(*FileHeader
)->Size
& 0x00FFFFFF;
197 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
198 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)*FileHeader
+ FileOccupiedSize
);
201 // FFS files begin with a header that is aligned on an 8-byte boundary
202 FfsFileHeader
= ALIGN_POINTER (FfsFileHeader
, 8);
204 FileOffset
= (UINT32
)((UINT8
*)FfsFileHeader
- (UINT8
*)FwVolHeader
);
205 ASSERT (FileOffset
<= 0xFFFFFFFF);
207 while (FileOffset
< (FvLength
- sizeof (EFI_FFS_FILE_HEADER
))) {
209 // Get FileState which is the highest bit of the State
211 FileState
= GetFileState (ErasePolarity
, FfsFileHeader
);
214 case EFI_FILE_HEADER_INVALID
:
215 FileOffset
+= sizeof (EFI_FFS_FILE_HEADER
);
216 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
));
219 case EFI_FILE_DATA_VALID
:
220 case EFI_FILE_MARKED_FOR_UPDATE
:
221 if (CalculateHeaderChecksum (FfsFileHeader
) != 0) {
224 return EFI_NOT_FOUND
;
227 FileLength
= *(UINT32
*)(FfsFileHeader
->Size
) & 0x00FFFFFF;
228 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
230 if (FileName
!= NULL
) {
231 if (CompareGuid (&FfsFileHeader
->Name
, (EFI_GUID
*)FileName
)) {
232 *FileHeader
= FfsFileHeader
;
235 } else if (((SearchType
== FfsFileHeader
->Type
) || (SearchType
== EFI_FV_FILETYPE_ALL
)) &&
236 (FfsFileHeader
->Type
!= EFI_FV_FILETYPE_FFS_PAD
))
238 *FileHeader
= FfsFileHeader
;
242 FileOffset
+= FileOccupiedSize
;
243 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ FileOccupiedSize
);
246 case EFI_FILE_DELETED
:
247 FileLength
= *(UINT32
*)(FfsFileHeader
->Size
) & 0x00FFFFFF;
248 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
249 FileOffset
+= FileOccupiedSize
;
250 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ FileOccupiedSize
);
255 return EFI_NOT_FOUND
;
260 return EFI_NOT_FOUND
;
264 Go through the file to search SectionType section,
265 when meeting an encapsuled section.
267 @param SectionType - Filter to find only section of this type.
268 @param SectionCheckHook - A hook which can check if the section is the target one.
269 @param Section - From where to search.
270 @param SectionSize - The file size to search.
271 @param OutputBuffer - Pointer to the section to search.
277 IN EFI_SECTION_TYPE SectionType
,
278 IN FFS_CHECK_SECTION_HOOK SectionCheckHook
,
279 IN EFI_COMMON_SECTION_HEADER
*Section
,
280 IN UINTN SectionSize
,
281 OUT VOID
**OutputBuffer
285 UINT32 SectionLength
;
287 EFI_COMPRESSION_SECTION
*CompressionSection
;
288 EFI_COMPRESSION_SECTION2
*CompressionSection2
;
289 UINT32 DstBufferSize
;
291 UINT32 ScratchBufferSize
;
293 UINT16 SectionAttribute
;
294 UINT32 AuthenticationStatus
;
295 CHAR8
*CompressedData
;
296 UINT32 CompressedDataLength
;
300 *OutputBuffer
= NULL
;
302 Status
= EFI_NOT_FOUND
;
303 while (ParsedLength
< SectionSize
) {
304 if (IS_SECTION2 (Section
)) {
305 ASSERT (SECTION2_SIZE (Section
) > 0x00FFFFFF);
308 if (Section
->Type
== SectionType
) {
309 if (SectionCheckHook
!= NULL
) {
310 Found
= SectionCheckHook (Section
) == EFI_SUCCESS
;
316 if (IS_SECTION2 (Section
)) {
317 *OutputBuffer
= (VOID
*)((UINT8
*)Section
+ sizeof (EFI_COMMON_SECTION_HEADER2
));
319 *OutputBuffer
= (VOID
*)((UINT8
*)Section
+ sizeof (EFI_COMMON_SECTION_HEADER
));
324 goto CheckNextSection
;
326 } else if ((Section
->Type
== EFI_SECTION_COMPRESSION
) || (Section
->Type
== EFI_SECTION_GUID_DEFINED
)) {
327 if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
328 if (IS_SECTION2 (Section
)) {
329 CompressionSection2
= (EFI_COMPRESSION_SECTION2
*)Section
;
330 SectionLength
= SECTION2_SIZE (Section
);
332 if (CompressionSection2
->CompressionType
!= EFI_STANDARD_COMPRESSION
) {
333 return EFI_UNSUPPORTED
;
336 CompressedData
= (CHAR8
*)((EFI_COMPRESSION_SECTION2
*)Section
+ 1);
337 CompressedDataLength
= SectionLength
- sizeof (EFI_COMPRESSION_SECTION2
);
339 CompressionSection
= (EFI_COMPRESSION_SECTION
*)Section
;
340 SectionLength
= SECTION_SIZE (Section
);
342 if (CompressionSection
->CompressionType
!= EFI_STANDARD_COMPRESSION
) {
343 return EFI_UNSUPPORTED
;
346 CompressedData
= (CHAR8
*)((EFI_COMPRESSION_SECTION
*)Section
+ 1);
347 CompressedDataLength
= SectionLength
- sizeof (EFI_COMPRESSION_SECTION
);
350 Status
= UefiDecompressGetInfo (
352 CompressedDataLength
,
356 } else if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
357 Status
= ExtractGuidedSectionGetInfo (
365 if (EFI_ERROR (Status
)) {
369 DEBUG ((DEBUG_ERROR
, "Decompress GetInfo Failed - %r\n", Status
));
370 return EFI_NOT_FOUND
;
374 // Allocate scratch buffer
376 ScratchBuffer
= (VOID
*)(UINTN
)AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
377 if (ScratchBuffer
== NULL
) {
378 return EFI_OUT_OF_RESOURCES
;
382 // Allocate destination buffer, extra one page for adjustment
384 DstBuffer
= (VOID
*)(UINTN
)AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
) + 1);
385 if (DstBuffer
== NULL
) {
386 return EFI_OUT_OF_RESOURCES
;
390 // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header
391 // to make section data at page alignment.
393 if (IS_SECTION2 (Section
)) {
394 DstBuffer
= (UINT8
*)DstBuffer
+ EFI_PAGE_SIZE
- sizeof (EFI_COMMON_SECTION_HEADER2
);
396 DstBuffer
= (UINT8
*)DstBuffer
+ EFI_PAGE_SIZE
- sizeof (EFI_COMMON_SECTION_HEADER
);
400 // Call decompress function
402 if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
403 if (IS_SECTION2 (Section
)) {
404 CompressedData
= (CHAR8
*)((EFI_COMPRESSION_SECTION2
*)Section
+ 1);
406 CompressedData
= (CHAR8
*)((EFI_COMPRESSION_SECTION
*)Section
+ 1);
409 Status
= UefiDecompress (
414 } else if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
415 Status
= ExtractGuidedSectionDecode (
419 &AuthenticationStatus
423 if (EFI_ERROR (Status
)) {
427 DEBUG ((DEBUG_ERROR
, "Decompress Failed - %r\n", Status
));
428 return EFI_NOT_FOUND
;
430 return FfsProcessSection (
441 if (IS_SECTION2 (Section
)) {
442 SectionLength
= SECTION2_SIZE (Section
);
444 SectionLength
= SECTION_SIZE (Section
);
448 // SectionLength is adjusted it is 4 byte aligned.
449 // Go to the next section
451 SectionLength
= GET_OCCUPIED_SIZE (SectionLength
, 4);
452 ASSERT (SectionLength
!= 0);
453 ParsedLength
+= SectionLength
;
454 Section
= (EFI_COMMON_SECTION_HEADER
*)((UINT8
*)Section
+ SectionLength
);
457 return EFI_NOT_FOUND
;
461 This service enables discovery sections of a given type within a valid FFS file.
463 @param SearchType The value of the section type to find.
464 @param FfsFileHeader A pointer to the file header that contains the set of sections to
466 @param SectionData A pointer to the discovered section, if successful.
468 @retval EFI_SUCCESS The section was found.
469 @retval EFI_NOT_FOUND The section was not found.
475 IN EFI_SECTION_TYPE SectionType
,
476 IN FFS_CHECK_SECTION_HOOK SectionCheckHook
,
477 IN EFI_PEI_FILE_HANDLE FileHandle
,
478 OUT VOID
**SectionData
481 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
483 EFI_COMMON_SECTION_HEADER
*Section
;
485 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)(FileHandle
);
488 // Size is 24 bits wide so mask upper 8 bits.
489 // Does not include FfsFileHeader header size
490 // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
492 Section
= (EFI_COMMON_SECTION_HEADER
*)(FfsFileHeader
+ 1);
493 FileSize
= *(UINT32
*)(FfsFileHeader
->Size
) & 0x00FFFFFF;
494 FileSize
-= sizeof (EFI_FFS_FILE_HEADER
);
496 return FfsProcessSection (
506 This service enables discovery of additional firmware files.
508 @param SearchType A filter to find files only of this type.
509 @param FwVolHeader Pointer to the firmware volume header of the volume to search.
510 This parameter must point to a valid FFS volume.
511 @param FileHeader Pointer to the current file from which to begin searching.
513 @retval EFI_SUCCESS The file was found.
514 @retval EFI_NOT_FOUND The file was not found.
515 @retval EFI_NOT_FOUND The header checksum was not zero.
522 IN EFI_PEI_FV_HANDLE VolumeHandle
,
523 IN OUT EFI_PEI_FILE_HANDLE
*FileHandle
526 return FindFileEx (VolumeHandle
, NULL
, SearchType
, FileHandle
);
530 This service enables discovery of additional firmware volumes.
532 @param Instance This instance of the firmware volume to find. The value 0 is the
533 Boot Firmware Volume (BFV).
534 @param FwVolHeader Pointer to the firmware volume header of the volume to return.
536 @retval EFI_SUCCESS The volume was found.
537 @retval EFI_NOT_FOUND The volume was not found.
544 IN OUT EFI_PEI_FV_HANDLE
*VolumeHandle
547 EFI_PEI_HOB_POINTERS Hob
;
549 Hob
.Raw
= GetHobList ();
550 if (Hob
.Raw
== NULL
) {
551 return EFI_NOT_FOUND
;
555 Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
);
556 if (Hob
.Raw
!= NULL
) {
557 if (Instance
-- == 0) {
558 *VolumeHandle
= (EFI_PEI_FV_HANDLE
)(UINTN
)(Hob
.FirmwareVolume
->BaseAddress
);
562 Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, GET_NEXT_HOB (Hob
));
564 } while (Hob
.Raw
!= NULL
);
566 return EFI_NOT_FOUND
;
570 Find a file in the volume by name
572 @param FileName A pointer to the name of the file to
573 find within the firmware volume.
575 @param VolumeHandle The firmware volume to search FileHandle
576 Upon exit, points to the found file's
577 handle or NULL if it could not be found.
579 @retval EFI_SUCCESS File was found.
581 @retval EFI_NOT_FOUND File was not found.
583 @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or
590 IN CONST EFI_GUID
*FileName
,
591 IN EFI_PEI_FV_HANDLE VolumeHandle
,
592 OUT EFI_PEI_FILE_HANDLE
*FileHandle
597 if ((VolumeHandle
== NULL
) || (FileName
== NULL
) || (FileHandle
== NULL
)) {
598 return EFI_INVALID_PARAMETER
;
601 Status
= FindFileEx (VolumeHandle
, FileName
, 0, FileHandle
);
602 if (Status
== EFI_NOT_FOUND
) {
610 Get information about the file by name.
612 @param FileHandle Handle of the file.
614 @param FileInfo Upon exit, points to the file's
617 @retval EFI_SUCCESS File information returned.
619 @retval EFI_INVALID_PARAMETER If FileHandle does not
620 represent a valid file.
622 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
628 IN EFI_PEI_FILE_HANDLE FileHandle
,
629 OUT EFI_FV_FILE_INFO
*FileInfo
634 EFI_FFS_FILE_HEADER
*FileHeader
;
635 EFI_PEI_FV_HANDLE VolumeHandle
;
637 if ((FileHandle
== NULL
) || (FileInfo
== NULL
)) {
638 return EFI_INVALID_PARAMETER
;
643 // Retrieve the FirmwareVolume which the file resides in.
645 if (!FileHandleToVolume (FileHandle
, &VolumeHandle
)) {
646 return EFI_INVALID_PARAMETER
;
649 if (((EFI_FIRMWARE_VOLUME_HEADER
*)VolumeHandle
)->Attributes
& EFI_FVB2_ERASE_POLARITY
) {
656 // Get FileState which is the highest bit of the State
658 FileState
= GetFileState (ErasePolarity
, (EFI_FFS_FILE_HEADER
*)FileHandle
);
661 case EFI_FILE_DATA_VALID
:
662 case EFI_FILE_MARKED_FOR_UPDATE
:
665 return EFI_INVALID_PARAMETER
;
668 FileHeader
= (EFI_FFS_FILE_HEADER
*)FileHandle
;
669 CopyMem (&FileInfo
->FileName
, &FileHeader
->Name
, sizeof (EFI_GUID
));
670 FileInfo
->FileType
= FileHeader
->Type
;
671 FileInfo
->FileAttributes
= FileHeader
->Attributes
;
672 FileInfo
->BufferSize
= ((*(UINT32
*)FileHeader
->Size
) & 0x00FFFFFF) - sizeof (EFI_FFS_FILE_HEADER
);
673 FileInfo
->Buffer
= (FileHeader
+ 1);
678 Get Information about the volume by name
680 @param VolumeHandle Handle of the volume.
682 @param VolumeInfo Upon exit, points to the volume's
685 @retval EFI_SUCCESS File information returned.
687 @retval EFI_INVALID_PARAMETER If FileHandle does not
688 represent a valid file.
690 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
696 IN EFI_PEI_FV_HANDLE VolumeHandle
,
697 OUT EFI_FV_INFO
*VolumeInfo
700 EFI_FIRMWARE_VOLUME_HEADER FwVolHeader
;
701 EFI_FIRMWARE_VOLUME_EXT_HEADER
*FwVolExHeaderInfo
;
703 if (VolumeInfo
== NULL
) {
704 return EFI_INVALID_PARAMETER
;
708 // VolumeHandle may not align at 8 byte,
709 // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte.
710 // So, Copy FvHeader into the local FvHeader structure.
712 CopyMem (&FwVolHeader
, VolumeHandle
, sizeof (EFI_FIRMWARE_VOLUME_HEADER
));
714 // Check Fv Image Signature
716 if (FwVolHeader
.Signature
!= EFI_FVH_SIGNATURE
) {
717 return EFI_INVALID_PARAMETER
;
720 VolumeInfo
->FvAttributes
= FwVolHeader
.Attributes
;
721 VolumeInfo
->FvStart
= (VOID
*)VolumeHandle
;
722 VolumeInfo
->FvSize
= FwVolHeader
.FvLength
;
723 CopyMem (&VolumeInfo
->FvFormat
, &FwVolHeader
.FileSystemGuid
, sizeof (EFI_GUID
));
725 if (FwVolHeader
.ExtHeaderOffset
!= 0) {
726 FwVolExHeaderInfo
= (EFI_FIRMWARE_VOLUME_EXT_HEADER
*)(((UINT8
*)VolumeHandle
) + FwVolHeader
.ExtHeaderOffset
);
727 CopyMem (&VolumeInfo
->FvName
, &FwVolExHeaderInfo
->FvName
, sizeof (EFI_GUID
));
734 Search through every FV until you find a file of type FileType
736 @param FileType File handle of a Fv type file.
737 @param Volumehandle On success Volume Handle of the match
738 @param FileHandle On success File Handle of the match
740 @retval EFI_NOT_FOUND FV image can't be found.
741 @retval EFI_SUCCESS Successfully found FileType
746 FfsAnyFvFindFirstFile (
747 IN EFI_FV_FILETYPE FileType
,
748 OUT EFI_PEI_FV_HANDLE
*VolumeHandle
,
749 OUT EFI_PEI_FILE_HANDLE
*FileHandle
756 // Search every FV for the DXE Core
762 Status
= FfsFindNextVolume (Instance
++, VolumeHandle
);
763 if (EFI_ERROR (Status
)) {
767 Status
= FfsFindNextFile (FileType
, *VolumeHandle
, FileHandle
);
768 if (!EFI_ERROR (Status
)) {
777 Get Fv image from the FV type file, then add FV & FV2 Hob.
779 @param FileHandle File handle of a Fv type file.
782 @retval EFI_NOT_FOUND FV image can't be found.
783 @retval EFI_SUCCESS Successfully to process it.
789 IN EFI_PEI_FILE_HANDLE FvFileHandle
793 EFI_PEI_FV_HANDLE FvImageHandle
;
794 EFI_FV_INFO FvImageInfo
;
797 EFI_PEI_HOB_POINTERS HobFv2
;
802 // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
805 HobFv2
.Raw
= GetHobList ();
806 while ((HobFv2
.Raw
= GetNextHob (EFI_HOB_TYPE_FV2
, HobFv2
.Raw
)) != NULL
) {
807 if (CompareGuid (&(((EFI_FFS_FILE_HEADER
*)FvFileHandle
)->Name
), &HobFv2
.FirmwareVolume2
->FileName
)) {
809 // this FILE has been dispatched, it will not be dispatched again.
814 HobFv2
.Raw
= GET_NEXT_HOB (HobFv2
);
818 // Find FvImage in FvFile
820 Status
= FfsFindSectionData (EFI_SECTION_FIRMWARE_VOLUME_IMAGE
, NULL
, FvFileHandle
, (VOID
**)&FvImageHandle
);
821 if (EFI_ERROR (Status
)) {
826 // Collect FvImage Info.
828 ZeroMem (&FvImageInfo
, sizeof (FvImageInfo
));
829 Status
= FfsGetVolumeInfo (FvImageHandle
, &FvImageInfo
);
830 ASSERT_EFI_ERROR (Status
);
833 // FvAlignment must be more than 8 bytes required by FvHeader structure.
835 FvAlignment
= 1 << ((FvImageInfo
.FvAttributes
& EFI_FVB2_ALIGNMENT
) >> 16);
836 if (FvAlignment
< 8) {
843 if ((UINTN
)FvImageInfo
.FvStart
% FvAlignment
!= 0) {
844 FvBuffer
= AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32
)FvImageInfo
.FvSize
), FvAlignment
);
845 if (FvBuffer
== NULL
) {
846 return EFI_OUT_OF_RESOURCES
;
849 CopyMem (FvBuffer
, FvImageInfo
.FvStart
, (UINTN
)FvImageInfo
.FvSize
);
851 // Update FvImageInfo after reload FvImage to new aligned memory
853 FfsGetVolumeInfo ((EFI_PEI_FV_HANDLE
)FvBuffer
, &FvImageInfo
);
857 // Inform HOB consumer phase, i.e. DXE core, the existence of this FV
859 BuildFvHob ((EFI_PHYSICAL_ADDRESS
)(UINTN
)FvImageInfo
.FvStart
, FvImageInfo
.FvSize
);
862 // Makes the encapsulated volume show up in DXE phase to skip processing of
863 // encapsulated file again.
866 (EFI_PHYSICAL_ADDRESS
)(UINTN
)FvImageInfo
.FvStart
,
869 &(((EFI_FFS_FILE_HEADER
*)FvFileHandle
)->Name
)