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>
16 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
17 (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
21 Returns the highest bit set of the State field
23 @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY
24 in the Attributes field.
25 @param FfsHeader Pointer to FFS File Header
28 @retval the highest bit in the State field
34 IN UINT8 ErasePolarity
,
35 IN EFI_FFS_FILE_HEADER
*FfsHeader
38 EFI_FFS_FILE_STATE FileState
;
39 EFI_FFS_FILE_STATE HighestBit
;
41 FileState
= FfsHeader
->State
;
43 if (ErasePolarity
!= 0) {
44 FileState
= (EFI_FFS_FILE_STATE
)~FileState
;
48 while (HighestBit
!= 0 && (HighestBit
& FileState
) == 0) {
57 Calculates the checksum of the header of a file.
58 The header is a zero byte checksum, so zero means header is good
60 @param FfsHeader Pointer to FFS File Header
62 @retval Checksum of the header
67 CalculateHeaderChecksum (
68 IN EFI_FFS_FILE_HEADER
*FileHeader
76 Ptr
= (UINT8
*)FileHeader
;
78 for (Index
= 0; Index
< sizeof(EFI_FFS_FILE_HEADER
) - 3; Index
+= 4) {
79 Sum
= (UINT8
)(Sum
+ Ptr
[Index
]);
80 Sum
= (UINT8
)(Sum
+ Ptr
[Index
+1]);
81 Sum
= (UINT8
)(Sum
+ Ptr
[Index
+2]);
82 Sum
= (UINT8
)(Sum
+ Ptr
[Index
+3]);
85 for (; Index
< sizeof(EFI_FFS_FILE_HEADER
); Index
++) {
86 Sum
= (UINT8
)(Sum
+ Ptr
[Index
]);
90 // State field (since this indicates the different state of file).
92 Sum
= (UINT8
)(Sum
- FileHeader
->State
);
94 // Checksum field of the file is not part of the header checksum.
96 Sum
= (UINT8
)(Sum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
103 Given a FileHandle return the VolumeHandle
105 @param FileHandle File handle to look up
106 @param VolumeHandle Match for FileHandle
108 @retval TRUE VolumeHandle is valid
115 IN EFI_PEI_FILE_HANDLE FileHandle
,
116 OUT EFI_PEI_FV_HANDLE
*VolumeHandle
119 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
120 EFI_PEI_HOB_POINTERS Hob
;
122 Hob
.Raw
= GetHobList ();
123 if (Hob
.Raw
== NULL
) {
128 Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
);
129 if (Hob
.Raw
!= NULL
) {
130 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)(Hob
.FirmwareVolume
->BaseAddress
);
131 if (((UINT64
) (UINTN
) FileHandle
> (UINT64
) (UINTN
) FwVolHeader
) && \
132 ((UINT64
) (UINTN
) FileHandle
<= ((UINT64
) (UINTN
) FwVolHeader
+ FwVolHeader
->FvLength
- 1))) {
133 *VolumeHandle
= (EFI_PEI_FV_HANDLE
)FwVolHeader
;
137 Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, GET_NEXT_HOB (Hob
));
139 } while (Hob
.Raw
!= NULL
);
147 Given the input file pointer, search for the next matching file in the
148 FFS volume as defined by SearchType. The search starts from FileHeader inside
149 the Firmware Volume defined by FwVolHeader.
151 @param FileHandle File handle to look up
152 @param VolumeHandle Match for FileHandle
158 IN CONST EFI_PEI_FV_HANDLE FvHandle
,
159 IN CONST EFI_GUID
*FileName
, OPTIONAL
160 IN EFI_FV_FILETYPE SearchType
,
161 IN OUT EFI_PEI_FILE_HANDLE
*FileHandle
164 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
165 EFI_FFS_FILE_HEADER
**FileHeader
;
166 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
167 EFI_FIRMWARE_VOLUME_EXT_HEADER
*FwVolExHeaderInfo
;
169 UINT32 FileOccupiedSize
;
175 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)FvHandle
;
176 FileHeader
= (EFI_FFS_FILE_HEADER
**)FileHandle
;
178 FvLength
= FwVolHeader
->FvLength
;
179 if (FwVolHeader
->Attributes
& EFI_FVB2_ERASE_POLARITY
) {
186 // If FileHeader is not specified (NULL) or FileName is not NULL,
187 // start with the first file in the firmware volume. Otherwise,
188 // start from the FileHeader.
190 if ((*FileHeader
== NULL
) || (FileName
!= NULL
)) {
191 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FwVolHeader
+ FwVolHeader
->HeaderLength
);
192 if (FwVolHeader
->ExtHeaderOffset
!= 0) {
193 FwVolExHeaderInfo
= (EFI_FIRMWARE_VOLUME_EXT_HEADER
*)(((UINT8
*)FwVolHeader
) + FwVolHeader
->ExtHeaderOffset
);
194 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)(((UINT8
*)FwVolExHeaderInfo
) + FwVolExHeaderInfo
->ExtHeaderSize
);
198 // Length is 24 bits wide so mask upper 8 bits
199 // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
201 FileLength
= *(UINT32
*)(*FileHeader
)->Size
& 0x00FFFFFF;
202 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
203 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)*FileHeader
+ FileOccupiedSize
);
206 // FFS files begin with a header that is aligned on an 8-byte boundary
207 FfsFileHeader
= ALIGN_POINTER (FfsFileHeader
, 8);
209 FileOffset
= (UINT32
) ((UINT8
*)FfsFileHeader
- (UINT8
*)FwVolHeader
);
210 ASSERT (FileOffset
<= 0xFFFFFFFF);
212 while (FileOffset
< (FvLength
- sizeof (EFI_FFS_FILE_HEADER
))) {
214 // Get FileState which is the highest bit of the State
216 FileState
= GetFileState (ErasePolarity
, FfsFileHeader
);
220 case EFI_FILE_HEADER_INVALID
:
221 FileOffset
+= sizeof(EFI_FFS_FILE_HEADER
);
222 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ sizeof(EFI_FFS_FILE_HEADER
));
225 case EFI_FILE_DATA_VALID
:
226 case EFI_FILE_MARKED_FOR_UPDATE
:
227 if (CalculateHeaderChecksum (FfsFileHeader
) != 0) {
230 return EFI_NOT_FOUND
;
233 FileLength
= *(UINT32
*)(FfsFileHeader
->Size
) & 0x00FFFFFF;
234 FileOccupiedSize
= GET_OCCUPIED_SIZE(FileLength
, 8);
236 if (FileName
!= NULL
) {
237 if (CompareGuid (&FfsFileHeader
->Name
, (EFI_GUID
*)FileName
)) {
238 *FileHeader
= FfsFileHeader
;
241 } else if (((SearchType
== FfsFileHeader
->Type
) || (SearchType
== EFI_FV_FILETYPE_ALL
)) &&
242 (FfsFileHeader
->Type
!= EFI_FV_FILETYPE_FFS_PAD
)) {
243 *FileHeader
= FfsFileHeader
;
247 FileOffset
+= FileOccupiedSize
;
248 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ FileOccupiedSize
);
251 case EFI_FILE_DELETED
:
252 FileLength
= *(UINT32
*)(FfsFileHeader
->Size
) & 0x00FFFFFF;
253 FileOccupiedSize
= GET_OCCUPIED_SIZE(FileLength
, 8);
254 FileOffset
+= FileOccupiedSize
;
255 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ FileOccupiedSize
);
260 return EFI_NOT_FOUND
;
266 return EFI_NOT_FOUND
;
271 Go through the file to search SectionType section,
272 when meeting an encapsuled section.
274 @param SectionType - Filter to find only section of this type.
275 @param Section - From where to search.
276 @param SectionSize - The file size to search.
277 @param OutputBuffer - Pointer to the section to search.
283 IN EFI_SECTION_TYPE SectionType
,
284 IN EFI_COMMON_SECTION_HEADER
*Section
,
285 IN UINTN SectionSize
,
286 OUT VOID
**OutputBuffer
290 UINT32 SectionLength
;
292 EFI_COMPRESSION_SECTION
*CompressionSection
;
293 EFI_COMPRESSION_SECTION2
*CompressionSection2
;
294 UINT32 DstBufferSize
;
296 UINT32 ScratchBufferSize
;
298 UINT16 SectionAttribute
;
299 UINT32 AuthenticationStatus
;
300 CHAR8
*CompressedData
;
301 UINTN CompressedDataLength
;
304 *OutputBuffer
= NULL
;
306 Status
= EFI_NOT_FOUND
;
307 while (ParsedLength
< SectionSize
) {
308 if (IS_SECTION2 (Section
)) {
309 ASSERT (SECTION2_SIZE (Section
) > 0x00FFFFFF);
312 if (Section
->Type
== SectionType
) {
313 if (IS_SECTION2 (Section
)) {
314 *OutputBuffer
= (VOID
*)((UINT8
*) Section
+ sizeof (EFI_COMMON_SECTION_HEADER2
));
316 *OutputBuffer
= (VOID
*)((UINT8
*) Section
+ sizeof (EFI_COMMON_SECTION_HEADER
));
320 } else if ((Section
->Type
== EFI_SECTION_COMPRESSION
) || (Section
->Type
== EFI_SECTION_GUID_DEFINED
)) {
322 if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
323 if (IS_SECTION2 (Section
)) {
324 CompressionSection2
= (EFI_COMPRESSION_SECTION2
*) Section
;
325 SectionLength
= SECTION2_SIZE (Section
);
327 if (CompressionSection2
->CompressionType
!= EFI_STANDARD_COMPRESSION
) {
328 return EFI_UNSUPPORTED
;
331 CompressedData
= (CHAR8
*) ((EFI_COMPRESSION_SECTION2
*) Section
+ 1);
332 CompressedDataLength
= (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION2
);
334 CompressionSection
= (EFI_COMPRESSION_SECTION
*) Section
;
335 SectionLength
= SECTION_SIZE (Section
);
337 if (CompressionSection
->CompressionType
!= EFI_STANDARD_COMPRESSION
) {
338 return EFI_UNSUPPORTED
;
341 CompressedData
= (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1);
342 CompressedDataLength
= (UINT32
) SectionLength
- sizeof (EFI_COMPRESSION_SECTION
);
345 Status
= UefiDecompressGetInfo (
347 CompressedDataLength
,
351 } else if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
352 Status
= ExtractGuidedSectionGetInfo (
360 if (EFI_ERROR (Status
)) {
364 DEBUG ((EFI_D_ERROR
, "Decompress GetInfo Failed - %r\n", Status
));
365 return EFI_NOT_FOUND
;
368 // Allocate scratch buffer
370 ScratchBuffer
= (VOID
*)(UINTN
)AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
371 if (ScratchBuffer
== NULL
) {
372 return EFI_OUT_OF_RESOURCES
;
375 // Allocate destination buffer, extra one page for adjustment
377 DstBuffer
= (VOID
*)(UINTN
)AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
) + 1);
378 if (DstBuffer
== NULL
) {
379 return EFI_OUT_OF_RESOURCES
;
382 // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header
383 // to make section data at page alignment.
385 if (IS_SECTION2 (Section
))
386 DstBuffer
= (UINT8
*)DstBuffer
+ EFI_PAGE_SIZE
- sizeof (EFI_COMMON_SECTION_HEADER2
);
388 DstBuffer
= (UINT8
*)DstBuffer
+ EFI_PAGE_SIZE
- sizeof (EFI_COMMON_SECTION_HEADER
);
390 // Call decompress function
392 if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
393 if (IS_SECTION2 (Section
)) {
394 CompressedData
= (CHAR8
*) ((EFI_COMPRESSION_SECTION2
*) Section
+ 1);
397 CompressedData
= (CHAR8
*) ((EFI_COMPRESSION_SECTION
*) Section
+ 1);
400 Status
= UefiDecompress (
405 } else if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
406 Status
= ExtractGuidedSectionDecode (
410 &AuthenticationStatus
414 if (EFI_ERROR (Status
)) {
418 DEBUG ((EFI_D_ERROR
, "Decompress Failed - %r\n", Status
));
419 return EFI_NOT_FOUND
;
421 return FfsProcessSection (
430 if (IS_SECTION2 (Section
)) {
431 SectionLength
= SECTION2_SIZE (Section
);
433 SectionLength
= SECTION_SIZE (Section
);
436 // SectionLength is adjusted it is 4 byte aligned.
437 // Go to the next section
439 SectionLength
= GET_OCCUPIED_SIZE (SectionLength
, 4);
440 ASSERT (SectionLength
!= 0);
441 ParsedLength
+= SectionLength
;
442 Section
= (EFI_COMMON_SECTION_HEADER
*)((UINT8
*)Section
+ SectionLength
);
445 return EFI_NOT_FOUND
;
451 This service enables discovery sections of a given type within a valid FFS file.
453 @param SearchType The value of the section type to find.
454 @param FfsFileHeader A pointer to the file header that contains the set of sections to
456 @param SectionData A pointer to the discovered section, if successful.
458 @retval EFI_SUCCESS The section was found.
459 @retval EFI_NOT_FOUND The section was not found.
465 IN EFI_SECTION_TYPE SectionType
,
466 IN EFI_PEI_FILE_HANDLE FileHandle
,
467 OUT VOID
**SectionData
470 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
472 EFI_COMMON_SECTION_HEADER
*Section
;
474 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)(FileHandle
);
477 // Size is 24 bits wide so mask upper 8 bits.
478 // Does not include FfsFileHeader header size
479 // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
481 Section
= (EFI_COMMON_SECTION_HEADER
*)(FfsFileHeader
+ 1);
482 FileSize
= *(UINT32
*)(FfsFileHeader
->Size
) & 0x00FFFFFF;
483 FileSize
-= sizeof (EFI_FFS_FILE_HEADER
);
485 return FfsProcessSection (
499 This service enables discovery of additional firmware files.
501 @param SearchType A filter to find files only of this type.
502 @param FwVolHeader Pointer to the firmware volume header of the volume to search.
503 This parameter must point to a valid FFS volume.
504 @param FileHeader Pointer to the current file from which to begin searching.
506 @retval EFI_SUCCESS The file was found.
507 @retval EFI_NOT_FOUND The file was not found.
508 @retval EFI_NOT_FOUND The header checksum was not zero.
515 IN EFI_PEI_FV_HANDLE VolumeHandle
,
516 IN OUT EFI_PEI_FILE_HANDLE
*FileHandle
519 return FindFileEx (VolumeHandle
, NULL
, SearchType
, FileHandle
);
524 This service enables discovery of additional firmware volumes.
526 @param Instance This instance of the firmware volume to find. The value 0 is the
527 Boot Firmware Volume (BFV).
528 @param FwVolHeader Pointer to the firmware volume header of the volume to return.
530 @retval EFI_SUCCESS The volume was found.
531 @retval EFI_NOT_FOUND The volume was not found.
538 IN OUT EFI_PEI_FV_HANDLE
*VolumeHandle
541 EFI_PEI_HOB_POINTERS Hob
;
544 Hob
.Raw
= GetHobList ();
545 if (Hob
.Raw
== NULL
) {
546 return EFI_NOT_FOUND
;
550 Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, Hob
.Raw
);
551 if (Hob
.Raw
!= NULL
) {
552 if (Instance
-- == 0) {
553 *VolumeHandle
= (EFI_PEI_FV_HANDLE
)(UINTN
)(Hob
.FirmwareVolume
->BaseAddress
);
557 Hob
.Raw
= GetNextHob (EFI_HOB_TYPE_FV
, GET_NEXT_HOB (Hob
));
559 } while (Hob
.Raw
!= NULL
);
561 return EFI_NOT_FOUND
;
567 Find a file in the volume by name
569 @param FileName A pointer to the name of the file to
570 find within the firmware volume.
572 @param VolumeHandle The firmware volume to search FileHandle
573 Upon exit, points to the found file's
574 handle or NULL if it could not be found.
576 @retval EFI_SUCCESS File was found.
578 @retval EFI_NOT_FOUND File was not found.
580 @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or
587 IN CONST EFI_GUID
*FileName
,
588 IN EFI_PEI_FV_HANDLE VolumeHandle
,
589 OUT EFI_PEI_FILE_HANDLE
*FileHandle
593 if ((VolumeHandle
== NULL
) || (FileName
== NULL
) || (FileHandle
== NULL
)) {
594 return EFI_INVALID_PARAMETER
;
596 Status
= FindFileEx (VolumeHandle
, FileName
, 0, FileHandle
);
597 if (Status
== EFI_NOT_FOUND
) {
607 Get information about the file by name.
609 @param FileHandle Handle of the file.
611 @param FileInfo Upon exit, points to the file's
614 @retval EFI_SUCCESS File information returned.
616 @retval EFI_INVALID_PARAMETER If FileHandle does not
617 represent a valid file.
619 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
625 IN EFI_PEI_FILE_HANDLE FileHandle
,
626 OUT EFI_FV_FILE_INFO
*FileInfo
631 EFI_FFS_FILE_HEADER
*FileHeader
;
632 EFI_PEI_FV_HANDLE VolumeHandle
;
634 if ((FileHandle
== NULL
) || (FileInfo
== NULL
)) {
635 return EFI_INVALID_PARAMETER
;
640 // Retrieve the FirmwareVolume which the file resides in.
642 if (!FileHandleToVolume(FileHandle
, &VolumeHandle
)) {
643 return EFI_INVALID_PARAMETER
;
646 if (((EFI_FIRMWARE_VOLUME_HEADER
*)VolumeHandle
)->Attributes
& EFI_FVB2_ERASE_POLARITY
) {
653 // Get FileState which is the highest bit of the State
655 FileState
= GetFileState (ErasePolarity
, (EFI_FFS_FILE_HEADER
*)FileHandle
);
658 case EFI_FILE_DATA_VALID
:
659 case EFI_FILE_MARKED_FOR_UPDATE
:
662 return EFI_INVALID_PARAMETER
;
665 FileHeader
= (EFI_FFS_FILE_HEADER
*)FileHandle
;
666 CopyMem (&FileInfo
->FileName
, &FileHeader
->Name
, sizeof(EFI_GUID
));
667 FileInfo
->FileType
= FileHeader
->Type
;
668 FileInfo
->FileAttributes
= FileHeader
->Attributes
;
669 FileInfo
->BufferSize
= ((*(UINT32
*)FileHeader
->Size
) & 0x00FFFFFF) - sizeof (EFI_FFS_FILE_HEADER
);
670 FileInfo
->Buffer
= (FileHeader
+ 1);
676 Get Information about the volume by name
678 @param VolumeHandle Handle of the volume.
680 @param VolumeInfo Upon exit, points to the volume's
683 @retval EFI_SUCCESS File information returned.
685 @retval EFI_INVALID_PARAMETER If FileHandle does not
686 represent a valid file.
688 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
694 IN EFI_PEI_FV_HANDLE VolumeHandle
,
695 OUT EFI_FV_INFO
*VolumeInfo
698 EFI_FIRMWARE_VOLUME_HEADER FwVolHeader
;
699 EFI_FIRMWARE_VOLUME_EXT_HEADER
*FwVolExHeaderInfo
;
701 if (VolumeInfo
== NULL
) {
702 return EFI_INVALID_PARAMETER
;
706 // VolumeHandle may not align at 8 byte,
707 // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte.
708 // So, Copy FvHeader into the local FvHeader structure.
710 CopyMem (&FwVolHeader
, VolumeHandle
, sizeof (EFI_FIRMWARE_VOLUME_HEADER
));
712 // Check Fv Image Signature
714 if (FwVolHeader
.Signature
!= EFI_FVH_SIGNATURE
) {
715 return EFI_INVALID_PARAMETER
;
717 VolumeInfo
->FvAttributes
= FwVolHeader
.Attributes
;
718 VolumeInfo
->FvStart
= (VOID
*) VolumeHandle
;
719 VolumeInfo
->FvSize
= FwVolHeader
.FvLength
;
720 CopyMem (&VolumeInfo
->FvFormat
, &FwVolHeader
.FileSystemGuid
, sizeof(EFI_GUID
));
722 if (FwVolHeader
.ExtHeaderOffset
!= 0) {
723 FwVolExHeaderInfo
= (EFI_FIRMWARE_VOLUME_EXT_HEADER
*)(((UINT8
*)VolumeHandle
) + FwVolHeader
.ExtHeaderOffset
);
724 CopyMem (&VolumeInfo
->FvName
, &FwVolExHeaderInfo
->FvName
, sizeof(EFI_GUID
));
732 Search through every FV until you find a file of type FileType
734 @param FileType File handle of a Fv type file.
735 @param Volumehandle On success Volume Handle of the match
736 @param FileHandle On success File Handle of the match
738 @retval EFI_NOT_FOUND FV image can't be found.
739 @retval EFI_SUCCESS Successfully found FileType
744 FfsAnyFvFindFirstFile (
745 IN EFI_FV_FILETYPE FileType
,
746 OUT EFI_PEI_FV_HANDLE
*VolumeHandle
,
747 OUT EFI_PEI_FILE_HANDLE
*FileHandle
754 // Search every FV for the DXE Core
761 Status
= FfsFindNextVolume (Instance
++, VolumeHandle
);
762 if (EFI_ERROR (Status
))
767 Status
= FfsFindNextFile (FileType
, *VolumeHandle
, FileHandle
);
768 if (!EFI_ERROR (Status
))
780 Get Fv image from the FV type file, then add FV & FV2 Hob.
782 @param FileHandle File handle of a Fv type file.
785 @retval EFI_NOT_FOUND FV image can't be found.
786 @retval EFI_SUCCESS Successfully to process it.
792 IN EFI_PEI_FILE_HANDLE FvFileHandle
796 EFI_PEI_FV_HANDLE FvImageHandle
;
797 EFI_FV_INFO FvImageInfo
;
800 EFI_PEI_HOB_POINTERS HobFv2
;
806 // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
809 HobFv2
.Raw
= GetHobList ();
810 while ((HobFv2
.Raw
= GetNextHob (EFI_HOB_TYPE_FV2
, HobFv2
.Raw
)) != NULL
) {
811 if (CompareGuid (&(((EFI_FFS_FILE_HEADER
*)FvFileHandle
)->Name
), &HobFv2
.FirmwareVolume2
->FileName
)) {
813 // this FILE has been dispatched, it will not be dispatched again.
817 HobFv2
.Raw
= GET_NEXT_HOB (HobFv2
);
821 // Find FvImage in FvFile
823 Status
= FfsFindSectionData (EFI_SECTION_FIRMWARE_VOLUME_IMAGE
, FvFileHandle
, (VOID
**)&FvImageHandle
);
824 if (EFI_ERROR (Status
)) {
829 // Collect FvImage Info.
831 ZeroMem (&FvImageInfo
, sizeof (FvImageInfo
));
832 Status
= FfsGetVolumeInfo (FvImageHandle
, &FvImageInfo
);
833 ASSERT_EFI_ERROR (Status
);
836 // FvAlignment must be more than 8 bytes required by FvHeader structure.
838 FvAlignment
= 1 << ((FvImageInfo
.FvAttributes
& EFI_FVB2_ALIGNMENT
) >> 16);
839 if (FvAlignment
< 8) {
846 if ((UINTN
) FvImageInfo
.FvStart
% FvAlignment
!= 0) {
847 FvBuffer
= AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32
) FvImageInfo
.FvSize
), FvAlignment
);
848 if (FvBuffer
== NULL
) {
849 return EFI_OUT_OF_RESOURCES
;
851 CopyMem (FvBuffer
, FvImageInfo
.FvStart
, (UINTN
) FvImageInfo
.FvSize
);
853 // Update FvImageInfo after reload FvImage to new aligned memory
855 FfsGetVolumeInfo ((EFI_PEI_FV_HANDLE
) FvBuffer
, &FvImageInfo
);
860 // Inform HOB consumer phase, i.e. DXE core, the existence of this FV
862 BuildFvHob ((EFI_PHYSICAL_ADDRESS
) (UINTN
) FvImageInfo
.FvStart
, FvImageInfo
.FvSize
);
865 // Makes the encapsulated volume show up in DXE phase to skip processing of
866 // encapsulated file again.
869 (EFI_PHYSICAL_ADDRESS
) (UINTN
) FvImageInfo
.FvStart
,
872 &(((EFI_FFS_FILE_HEADER
*)FvFileHandle
)->Name
)