2 Pei Core Firmware File System service routines.
4 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyOnFvInfoList
= {
18 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
19 &gEfiPeiFirmwareVolumeInfoPpiGuid
,
20 FirmwareVolmeInfoPpiNotifyCallback
23 PEI_FW_VOL_INSTANCE mPeiFfs2FwVol
= {
27 PeiFfsFvPpiProcessVolume
,
28 PeiFfsFvPpiFindFileByType
,
29 PeiFfsFvPpiFindFileByName
,
30 PeiFfsFvPpiGetFileInfo
,
31 PeiFfsFvPpiGetVolumeInfo
,
32 PeiFfsFvPpiFindSectionByType
36 PEI_FW_VOL_INSTANCE mPeiFfs3FwVol
= {
40 PeiFfsFvPpiProcessVolume
,
41 PeiFfsFvPpiFindFileByType
,
42 PeiFfsFvPpiFindFileByName
,
43 PeiFfsFvPpiGetFileInfo
,
44 PeiFfsFvPpiGetVolumeInfo
,
45 PeiFfsFvPpiFindSectionByType
49 EFI_PEI_PPI_DESCRIPTOR mPeiFfs2FvPpiList
= {
50 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
51 &gEfiFirmwareFileSystem2Guid
,
55 EFI_PEI_PPI_DESCRIPTOR mPeiFfs3FvPpiList
= {
56 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
57 &gEfiFirmwareFileSystem3Guid
,
62 Required Alignment Alignment Value in FFS Alignment Value in
63 (bytes) Attributes Field Firmware Volume Interfaces
73 UINT8 mFvAttributes
[] = {0, 4, 7, 9, 10, 12, 15, 16};
76 Convert the FFS File Attributes to FV File Attributes
78 @param FfsAttributes The attributes of UINT8 type.
80 @return The attributes of EFI_FV_FILE_ATTRIBUTES
83 EFI_FV_FILE_ATTRIBUTES
84 FfsAttributes2FvFileAttributes (
85 IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes
89 EFI_FV_FILE_ATTRIBUTES FileAttribute
;
91 DataAlignment
= (UINT8
) ((FfsAttributes
& FFS_ATTRIB_DATA_ALIGNMENT
) >> 3);
92 ASSERT (DataAlignment
< 8);
94 FileAttribute
= (EFI_FV_FILE_ATTRIBUTES
) mFvAttributes
[DataAlignment
];
96 if ((FfsAttributes
& FFS_ATTRIB_FIXED
) == FFS_ATTRIB_FIXED
) {
97 FileAttribute
|= EFI_FV_FILE_ATTRIB_FIXED
;
100 return FileAttribute
;
104 Returns the file state set by the highest zero bit in the State field
106 @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY
107 in the Attributes field.
108 @param FfsHeader Pointer to FFS File Header.
110 @retval EFI_FFS_FILE_STATE File state is set by the highest none zero bit
111 in the header State field.
115 IN UINT8 ErasePolarity
,
116 IN EFI_FFS_FILE_HEADER
*FfsHeader
119 EFI_FFS_FILE_STATE FileState
;
120 EFI_FFS_FILE_STATE HighestBit
;
122 FileState
= FfsHeader
->State
;
124 if (ErasePolarity
!= 0) {
125 FileState
= (EFI_FFS_FILE_STATE
)~FileState
;
129 // Get file state set by its highest none zero bit.
132 while (HighestBit
!= 0 && (HighestBit
& FileState
) == 0) {
140 Calculates the checksum of the header of a file.
142 @param FileHeader Pointer to FFS File Header.
144 @return Checksum of the header.
145 Zero means the header is good.
146 Non-zero means the header is bad.
149 CalculateHeaderChecksum (
150 IN EFI_FFS_FILE_HEADER
*FileHeader
153 EFI_FFS_FILE_HEADER2 TestFileHeader
;
155 if (IS_FFS_FILE2 (FileHeader
)) {
156 CopyMem (&TestFileHeader
, FileHeader
, sizeof (EFI_FFS_FILE_HEADER2
));
158 // Ingore State and File field in FFS header.
160 TestFileHeader
.State
= 0;
161 TestFileHeader
.IntegrityCheck
.Checksum
.File
= 0;
163 return CalculateSum8 ((CONST UINT8
*) &TestFileHeader
, sizeof (EFI_FFS_FILE_HEADER2
));
165 CopyMem (&TestFileHeader
, FileHeader
, sizeof (EFI_FFS_FILE_HEADER
));
167 // Ingore State and File field in FFS header.
169 TestFileHeader
.State
= 0;
170 TestFileHeader
.IntegrityCheck
.Checksum
.File
= 0;
172 return CalculateSum8 ((CONST UINT8
*) &TestFileHeader
, sizeof (EFI_FFS_FILE_HEADER
));
177 Find FV handler according to FileHandle in that FV.
179 @param FileHandle Handle of file image
181 @return Pointer to instance of PEI_CORE_FV_HANDLE.
185 IN EFI_PEI_FILE_HANDLE FileHandle
189 PEI_CORE_INSTANCE
*PrivateData
;
190 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
192 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
194 for (Index
= 0; Index
< PrivateData
->FvCount
; Index
++) {
195 FwVolHeader
= PrivateData
->Fv
[Index
].FvHeader
;
196 if (((UINT64
) (UINTN
) FileHandle
> (UINT64
) (UINTN
) FwVolHeader
) && \
197 ((UINT64
) (UINTN
) FileHandle
<= ((UINT64
) (UINTN
) FwVolHeader
+ FwVolHeader
->FvLength
- 1))) {
198 return &PrivateData
->Fv
[Index
];
205 Given the input file pointer, search for the first matching file in the
206 FFS volume as defined by SearchType. The search starts from FileHeader inside
207 the Firmware Volume defined by FwVolHeader.
208 If SearchType is EFI_FV_FILETYPE_ALL, the first FFS file will return without check its file type.
209 If SearchType is PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE,
210 the first PEIM, or COMBINED PEIM or FV file type FFS file will return.
212 @param FvHandle Pointer to the FV header of the volume to search
213 @param FileName File name
214 @param SearchType Filter to find only files of this type.
215 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
216 @param FileHandle This parameter must point to a valid FFS volume.
217 @param AprioriFile Pointer to AprioriFile image in this FV if has
219 @return EFI_NOT_FOUND No files matching the search criteria were found
220 @retval EFI_SUCCESS Success to search given file
225 IN CONST EFI_PEI_FV_HANDLE FvHandle
,
226 IN CONST EFI_GUID
*FileName
, OPTIONAL
227 IN EFI_FV_FILETYPE SearchType
,
228 IN OUT EFI_PEI_FILE_HANDLE
*FileHandle
,
229 IN OUT EFI_PEI_FV_HANDLE
*AprioriFile OPTIONAL
232 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
233 EFI_FIRMWARE_VOLUME_EXT_HEADER
*FwVolExtHeader
;
234 EFI_FFS_FILE_HEADER
**FileHeader
;
235 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
237 UINT32 FileOccupiedSize
;
246 // Convert the handle of FV to FV header for memory-mapped firmware volume
248 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FvHandle
;
249 FileHeader
= (EFI_FFS_FILE_HEADER
**)FileHandle
;
251 IsFfs3Fv
= CompareGuid (&FwVolHeader
->FileSystemGuid
, &gEfiFirmwareFileSystem3Guid
);
253 FvLength
= FwVolHeader
->FvLength
;
254 if ((FwVolHeader
->Attributes
& EFI_FVB2_ERASE_POLARITY
) != 0) {
261 // If FileHeader is not specified (NULL) or FileName is not NULL,
262 // start with the first file in the firmware volume. Otherwise,
263 // start from the FileHeader.
265 if ((*FileHeader
== NULL
) || (FileName
!= NULL
)) {
266 if (FwVolHeader
->ExtHeaderOffset
!= 0) {
268 // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists.
270 FwVolExtHeader
= (EFI_FIRMWARE_VOLUME_EXT_HEADER
*) ((UINT8
*) FwVolHeader
+ FwVolHeader
->ExtHeaderOffset
);
271 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FwVolExtHeader
+ FwVolExtHeader
->ExtHeaderSize
);
272 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) ALIGN_POINTER (FfsFileHeader
, 8);
274 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*) FwVolHeader
+ FwVolHeader
->HeaderLength
);
277 if (IS_FFS_FILE2 (*FileHeader
)) {
279 DEBUG ((EFI_D_ERROR
, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &(*FileHeader
)->Name
));
281 FileLength
= FFS_FILE2_SIZE (*FileHeader
);
282 ASSERT (FileLength
> 0x00FFFFFF);
284 FileLength
= FFS_FILE_SIZE (*FileHeader
);
287 // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
289 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
290 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)*FileHeader
+ FileOccupiedSize
);
293 FileOffset
= (UINT32
) ((UINT8
*)FfsFileHeader
- (UINT8
*)FwVolHeader
);
294 ASSERT (FileOffset
<= 0xFFFFFFFF);
296 while (FileOffset
< (FvLength
- sizeof (EFI_FFS_FILE_HEADER
))) {
298 // Get FileState which is the highest bit of the State
300 FileState
= GetFileState (ErasePolarity
, FfsFileHeader
);
303 case EFI_FILE_HEADER_CONSTRUCTION
:
304 case EFI_FILE_HEADER_INVALID
:
305 if (IS_FFS_FILE2 (FfsFileHeader
)) {
307 DEBUG ((EFI_D_ERROR
, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader
->Name
));
309 FileOffset
+= sizeof (EFI_FFS_FILE_HEADER2
);
310 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
));
312 FileOffset
+= sizeof (EFI_FFS_FILE_HEADER
);
313 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
));
317 case EFI_FILE_DATA_VALID
:
318 case EFI_FILE_MARKED_FOR_UPDATE
:
319 if (CalculateHeaderChecksum (FfsFileHeader
) != 0) {
322 return EFI_NOT_FOUND
;
325 if (IS_FFS_FILE2 (FfsFileHeader
)) {
326 FileLength
= FFS_FILE2_SIZE (FfsFileHeader
);
327 ASSERT (FileLength
> 0x00FFFFFF);
328 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
330 DEBUG ((EFI_D_ERROR
, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader
->Name
));
331 FileOffset
+= FileOccupiedSize
;
332 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FfsFileHeader
+ FileOccupiedSize
);
336 FileLength
= FFS_FILE_SIZE (FfsFileHeader
);
337 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
340 DataCheckSum
= FFS_FIXED_CHECKSUM
;
341 if ((FfsFileHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) == FFS_ATTRIB_CHECKSUM
) {
342 if (IS_FFS_FILE2 (FfsFileHeader
)) {
343 DataCheckSum
= CalculateCheckSum8 ((CONST UINT8
*) FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
), FileLength
- sizeof(EFI_FFS_FILE_HEADER2
));
345 DataCheckSum
= CalculateCheckSum8 ((CONST UINT8
*) FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
), FileLength
- sizeof(EFI_FFS_FILE_HEADER
));
348 if (FfsFileHeader
->IntegrityCheck
.Checksum
.File
!= DataCheckSum
) {
351 return EFI_NOT_FOUND
;
354 if (FileName
!= NULL
) {
355 if (CompareGuid (&FfsFileHeader
->Name
, (EFI_GUID
*)FileName
)) {
356 *FileHeader
= FfsFileHeader
;
359 } else if (SearchType
== PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE
) {
360 if ((FfsFileHeader
->Type
== EFI_FV_FILETYPE_PEIM
) ||
361 (FfsFileHeader
->Type
== EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
) ||
362 (FfsFileHeader
->Type
== EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
)) {
364 *FileHeader
= FfsFileHeader
;
366 } else if (AprioriFile
!= NULL
) {
367 if (FfsFileHeader
->Type
== EFI_FV_FILETYPE_FREEFORM
) {
368 if (CompareGuid (&FfsFileHeader
->Name
, &gPeiAprioriFileNameGuid
)) {
369 *AprioriFile
= FfsFileHeader
;
373 } else if (((SearchType
== FfsFileHeader
->Type
) || (SearchType
== EFI_FV_FILETYPE_ALL
)) &&
374 (FfsFileHeader
->Type
!= EFI_FV_FILETYPE_FFS_PAD
)) {
375 *FileHeader
= FfsFileHeader
;
379 FileOffset
+= FileOccupiedSize
;
380 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ FileOccupiedSize
);
383 case EFI_FILE_DELETED
:
384 if (IS_FFS_FILE2 (FfsFileHeader
)) {
386 DEBUG ((EFI_D_ERROR
, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader
->Name
));
388 FileLength
= FFS_FILE2_SIZE (FfsFileHeader
);
389 ASSERT (FileLength
> 0x00FFFFFF);
391 FileLength
= FFS_FILE_SIZE (FfsFileHeader
);
393 FileOccupiedSize
= GET_OCCUPIED_SIZE(FileLength
, 8);
394 FileOffset
+= FileOccupiedSize
;
395 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ FileOccupiedSize
);
400 return EFI_NOT_FOUND
;
405 return EFI_NOT_FOUND
;
409 Initialize PeiCore Fv List.
411 @param PrivateData - Pointer to PEI_CORE_INSTANCE.
412 @param SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF.
416 IN PEI_CORE_INSTANCE
*PrivateData
,
417 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
421 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
422 EFI_PEI_FV_HANDLE FvHandle
;
423 EFI_FIRMWARE_VOLUME_HEADER
*BfvHeader
;
426 // Install FV_PPI for FFS2 file system.
428 PeiServicesInstallPpi (&mPeiFfs2FvPpiList
);
431 // Install FV_PPI for FFS3 file system.
433 PeiServicesInstallPpi (&mPeiFfs3FvPpiList
);
435 BfvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)SecCoreData
->BootFirmwareVolumeBase
;
438 // The FV_PPI in BFV's format should be installed.
440 Status
= PeiServicesLocatePpi (
441 &BfvHeader
->FileSystemGuid
,
446 ASSERT_EFI_ERROR (Status
);
451 FvPpi
->ProcessVolume (
453 SecCoreData
->BootFirmwareVolumeBase
,
454 (UINTN
)BfvHeader
->FvLength
,
459 // Update internal PEI_CORE_FV array.
461 PrivateData
->Fv
[PrivateData
->FvCount
].FvHeader
= BfvHeader
;
462 PrivateData
->Fv
[PrivateData
->FvCount
].FvPpi
= FvPpi
;
463 PrivateData
->Fv
[PrivateData
->FvCount
].FvHandle
= FvHandle
;
466 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
467 (UINT32
) PrivateData
->FvCount
,
472 PrivateData
->FvCount
++;
475 // Post a call-back for the FvInfoPPI services to expose
476 // additional Fvs to PeiCore.
478 Status
= PeiServicesNotifyPpi (&mNotifyOnFvInfoList
);
479 ASSERT_EFI_ERROR (Status
);
484 Process Firmware Volum Information once FvInfoPPI install.
485 The FV Info will be registered into PeiCore private data structure.
486 And search the inside FV image, if found, the new FV INFO PPI will be installed.
488 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
489 @param NotifyDescriptor Address of the notification descriptor data structure.
490 @param Ppi Address of the PPI that was installed.
492 @retval EFI_SUCCESS The FV Info is registered into PeiCore private data structure.
493 @return if not EFI_SUCESS, fail to verify FV.
498 FirmwareVolmeInfoPpiNotifyCallback (
499 IN EFI_PEI_SERVICES
**PeiServices
,
500 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
504 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*FvInfoPpi
;
505 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
506 PEI_CORE_INSTANCE
*PrivateData
;
508 EFI_PEI_FV_HANDLE FvHandle
;
510 EFI_PEI_FILE_HANDLE FileHandle
;
513 Status
= EFI_SUCCESS
;
514 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices
);
516 if (PrivateData
->FvCount
>= FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)) {
517 DEBUG ((EFI_D_ERROR
, "The number of Fv Images (%d) exceed the max supported FVs (%d) in Pei", PrivateData
->FvCount
+ 1, FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)));
518 DEBUG ((EFI_D_ERROR
, "PcdPeiCoreMaxFvSupported value need be reconfigurated in DSC"));
522 FvInfoPpi
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*)Ppi
;
525 // Locate the corresponding FV_PPI according to founded FV's format guid
527 Status
= PeiServicesLocatePpi (
528 &FvInfoPpi
->FvFormat
,
533 if (!EFI_ERROR (Status
)) {
535 // Process new found FV and get FV handle.
537 Status
= FvPpi
->ProcessVolume (FvPpi
, FvInfoPpi
->FvInfo
, FvInfoPpi
->FvInfoSize
, &FvHandle
);
538 if (EFI_ERROR (Status
)) {
539 DEBUG ((EFI_D_ERROR
, "Fail to process new found FV, FV may be corrupted!\n"));
544 // Check whether the FV has already been processed.
546 for (FvIndex
= 0; FvIndex
< PrivateData
->FvCount
; FvIndex
++) {
547 if (PrivateData
->Fv
[FvIndex
].FvHandle
== FvHandle
) {
548 DEBUG ((EFI_D_INFO
, "The Fv %p has already been processed!\n", FvInfoPpi
->FvInfo
));
554 // Update internal PEI_CORE_FV array.
556 PrivateData
->Fv
[PrivateData
->FvCount
].FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FvInfoPpi
->FvInfo
;
557 PrivateData
->Fv
[PrivateData
->FvCount
].FvPpi
= FvPpi
;
558 PrivateData
->Fv
[PrivateData
->FvCount
].FvHandle
= FvHandle
;
561 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
562 (UINT32
) PrivateData
->FvCount
,
563 (VOID
*) FvInfoPpi
->FvInfo
,
564 FvInfoPpi
->FvInfoSize
,
567 PrivateData
->FvCount
++;
570 // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
574 Status
= FvPpi
->FindFileByType (
576 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
580 if (!EFI_ERROR (Status
)) {
581 Status
= FvPpi
->FindSectionByType (
583 EFI_SECTION_PEI_DEPEX
,
587 if (!EFI_ERROR (Status
)) {
588 if (!PeimDispatchReadiness (PeiServices
, DepexData
)) {
590 // Dependency is not satisfied.
596 DEBUG ((EFI_D_INFO
, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle
, PrivateData
->FvCount
- 1, FvHandle
));
597 ProcessFvFile (&PrivateData
->Fv
[PrivateData
->FvCount
- 1], FileHandle
);
599 } while (FileHandle
!= NULL
);
601 DEBUG ((EFI_D_ERROR
, "Fail to process FV %p because no corresponding EFI_FIRMWARE_VOLUME_PPI is found!\n", FvInfoPpi
->FvInfo
));
603 AddUnknownFormatFvInfo (PrivateData
, &FvInfoPpi
->FvFormat
, FvInfoPpi
->FvInfo
, FvInfoPpi
->FvInfoSize
);
610 Verify the Guided Section GUID by checking if there is the Guided Section GUID HOB recorded the GUID itself.
612 @param GuidedSectionGuid The Guided Section GUID.
613 @param GuidedSectionExtraction A pointer to the pointer to the supported Guided Section Extraction Ppi
614 for the Guided Section.
616 @return TRUE The GuidedSectionGuid could be identified, and the pointer to
617 the Guided Section Extraction Ppi will be returned to *GuidedSectionExtraction.
618 @return FALSE The GuidedSectionGuid could not be identified, or
619 the Guided Section Extraction Ppi has not been installed yet.
623 VerifyGuidedSectionGuid (
624 IN EFI_GUID
*GuidedSectionGuid
,
625 OUT EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI
**GuidedSectionExtraction
628 EFI_PEI_HOB_POINTERS Hob
;
629 EFI_GUID
*GuidRecorded
;
634 // Check if there is the Guided Section GUID HOB recorded the GUID itself.
636 Hob
.Raw
= GetFirstGuidHob (GuidedSectionGuid
);
637 if (Hob
.Raw
!= NULL
) {
638 GuidRecorded
= (EFI_GUID
*) GET_GUID_HOB_DATA (Hob
);
639 if (CompareGuid (GuidRecorded
, GuidedSectionGuid
)) {
641 // Found the recorded GuidedSectionGuid.
643 Status
= PeiServicesLocatePpi (GuidedSectionGuid
, 0, NULL
, (VOID
**) &Interface
);
644 if (!EFI_ERROR (Status
) && Interface
!= NULL
) {
646 // Found the supported Guided Section Extraction Ppi for the Guided Section.
648 *GuidedSectionExtraction
= (EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI
*) Interface
;
659 Go through the file to search SectionType section.
660 Search within encapsulation sections (compression and GUIDed) recursively,
661 until the match section is found.
663 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
664 @param SectionType Filter to find only section of this type.
665 @param Section From where to search.
666 @param SectionSize The file size to search.
667 @param OutputBuffer A pointer to the discovered section, if successful.
668 NULL if section not found
669 @param IsFfs3Fv Indicates the FV format.
671 @return EFI_NOT_FOUND The match section is not found.
672 @return EFI_SUCCESS The match section is found.
677 IN CONST EFI_PEI_SERVICES
**PeiServices
,
678 IN EFI_SECTION_TYPE SectionType
,
679 IN EFI_COMMON_SECTION_HEADER
*Section
,
680 IN UINTN SectionSize
,
681 OUT VOID
**OutputBuffer
,
686 UINT32 SectionLength
;
688 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI
*GuidSectionPpi
;
689 EFI_PEI_DECOMPRESS_PPI
*DecompressPpi
;
693 UINT32 Authentication
;
694 PEI_CORE_INSTANCE
*PrivateData
;
695 EFI_GUID
*SectionDefinitionGuid
;
697 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices
);
698 *OutputBuffer
= NULL
;
701 Status
= EFI_NOT_FOUND
;
704 while (ParsedLength
< SectionSize
) {
706 if (IS_SECTION2 (Section
)) {
707 ASSERT (SECTION2_SIZE (Section
) > 0x00FFFFFF);
709 DEBUG ((EFI_D_ERROR
, "Found a FFS3 formatted section in a non-FFS3 formatted FV.\n"));
710 SectionLength
= SECTION2_SIZE (Section
);
712 // SectionLength is adjusted it is 4 byte aligned.
713 // Go to the next section
715 SectionLength
= GET_OCCUPIED_SIZE (SectionLength
, 4);
716 ASSERT (SectionLength
!= 0);
717 ParsedLength
+= SectionLength
;
718 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ SectionLength
);
723 if (Section
->Type
== SectionType
) {
724 if (IS_SECTION2 (Section
)) {
725 *OutputBuffer
= (VOID
*)((UINT8
*) Section
+ sizeof (EFI_COMMON_SECTION_HEADER2
));
727 *OutputBuffer
= (VOID
*)((UINT8
*) Section
+ sizeof (EFI_COMMON_SECTION_HEADER
));
730 } else if ((Section
->Type
== EFI_SECTION_GUID_DEFINED
) || (Section
->Type
== EFI_SECTION_COMPRESSION
)) {
732 // Check the encapsulated section is extracted into the cache data.
734 for (Index
= 0; Index
< PrivateData
->CacheSection
.AllSectionCount
; Index
++) {
735 if (Section
== PrivateData
->CacheSection
.Section
[Index
]) {
736 PpiOutput
= PrivateData
->CacheSection
.SectionData
[Index
];
737 PpiOutputSize
= PrivateData
->CacheSection
.SectionSize
[Index
];
739 // Search section directly from the cache data.
741 return ProcessSection (
752 Status
= EFI_NOT_FOUND
;
753 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
754 if (IS_SECTION2 (Section
)) {
755 SectionDefinitionGuid
= &((EFI_GUID_DEFINED_SECTION2
*)Section
)->SectionDefinitionGuid
;
757 SectionDefinitionGuid
= &((EFI_GUID_DEFINED_SECTION
*)Section
)->SectionDefinitionGuid
;
759 if (VerifyGuidedSectionGuid (SectionDefinitionGuid
, &GuidSectionPpi
)) {
760 Status
= GuidSectionPpi
->ExtractSection (
768 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
769 Status
= PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid
, 0, NULL
, (VOID
**) &DecompressPpi
);
770 if (!EFI_ERROR (Status
)) {
771 Status
= DecompressPpi
->Decompress (
773 (CONST EFI_COMPRESSION_SECTION
*) Section
,
780 if (!EFI_ERROR (Status
)) {
782 // Update cache section data.
784 if (PrivateData
->CacheSection
.AllSectionCount
< CACHE_SETION_MAX_NUMBER
) {
785 PrivateData
->CacheSection
.AllSectionCount
++;
787 PrivateData
->CacheSection
.Section
[PrivateData
->CacheSection
.SectionIndex
] = Section
;
788 PrivateData
->CacheSection
.SectionData
[PrivateData
->CacheSection
.SectionIndex
] = PpiOutput
;
789 PrivateData
->CacheSection
.SectionSize
[PrivateData
->CacheSection
.SectionIndex
] = PpiOutputSize
;
790 PrivateData
->CacheSection
.SectionIndex
= (PrivateData
->CacheSection
.SectionIndex
+ 1)%CACHE_SETION_MAX_NUMBER
;
792 return ProcessSection (
803 if (IS_SECTION2 (Section
)) {
804 SectionLength
= SECTION2_SIZE (Section
);
806 SectionLength
= SECTION_SIZE (Section
);
809 // SectionLength is adjusted it is 4 byte aligned.
810 // Go to the next section
812 SectionLength
= GET_OCCUPIED_SIZE (SectionLength
, 4);
813 ASSERT (SectionLength
!= 0);
814 ParsedLength
+= SectionLength
;
815 Section
= (EFI_COMMON_SECTION_HEADER
*)((UINT8
*)Section
+ SectionLength
);
818 return EFI_NOT_FOUND
;
823 Searches for the next matching section within the specified file.
825 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
826 @param SectionType Filter to find only sections of this type.
827 @param FileHandle Pointer to the current file to search.
828 @param SectionData A pointer to the discovered section, if successful.
829 NULL if section not found
831 @retval EFI_NOT_FOUND The section was not found.
832 @retval EFI_SUCCESS The section was found.
837 PeiFfsFindSectionData (
838 IN CONST EFI_PEI_SERVICES
**PeiServices
,
839 IN EFI_SECTION_TYPE SectionType
,
840 IN EFI_PEI_FILE_HANDLE FileHandle
,
841 OUT VOID
**SectionData
844 PEI_CORE_FV_HANDLE
*CoreFvHandle
;
846 CoreFvHandle
= FileHandleToVolume (FileHandle
);
847 if ((CoreFvHandle
== NULL
) || (CoreFvHandle
->FvPpi
== NULL
)) {
848 return EFI_NOT_FOUND
;
851 return CoreFvHandle
->FvPpi
->FindSectionByType (CoreFvHandle
->FvPpi
, SectionType
, FileHandle
, SectionData
);
855 Searches for the next matching file in the firmware volume.
857 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
858 @param SearchType Filter to find only files of this type.
859 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
860 @param FvHandle Handle of firmware volume in which to search.
861 @param FileHandle On entry, points to the current handle from which to begin searching or NULL to start
862 at the beginning of the firmware volume. On exit, points the file handle of the next file
863 in the volume or NULL if there are no more files.
865 @retval EFI_NOT_FOUND The file was not found.
866 @retval EFI_NOT_FOUND The header checksum was not zero.
867 @retval EFI_SUCCESS The file was found.
873 IN CONST EFI_PEI_SERVICES
**PeiServices
,
875 IN EFI_PEI_FV_HANDLE FvHandle
,
876 IN OUT EFI_PEI_FILE_HANDLE
*FileHandle
879 PEI_CORE_FV_HANDLE
*CoreFvHandle
;
881 CoreFvHandle
= FvHandleToCoreHandle (FvHandle
);
884 // To make backward compatiblity, if can not find corresponding the handle of FV
885 // then treat FV as build-in FFS2/FFS3 format and memory mapped FV that FV handle is pointed
886 // to the address of first byte of FV.
888 if ((CoreFvHandle
== NULL
) && FeaturePcdGet (PcdFrameworkCompatibilitySupport
)) {
889 return FindFileEx (FvHandle
, NULL
, SearchType
, FileHandle
, NULL
);
892 if ((CoreFvHandle
== NULL
) || CoreFvHandle
->FvPpi
== NULL
) {
893 return EFI_NOT_FOUND
;
896 return CoreFvHandle
->FvPpi
->FindFileByType (CoreFvHandle
->FvPpi
, SearchType
, FvHandle
, FileHandle
);
901 Search the firmware volumes by index
903 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
904 @param Instance This instance of the firmware volume to find. The value 0 is the Boot Firmware
906 @param VolumeHandle On exit, points to the next volume handle or NULL if it does not exist.
908 @retval EFI_INVALID_PARAMETER VolumeHandle is NULL
909 @retval EFI_NOT_FOUND The volume was not found.
910 @retval EFI_SUCCESS The volume was found.
915 PeiFfsFindNextVolume (
916 IN CONST EFI_PEI_SERVICES
**PeiServices
,
918 IN OUT EFI_PEI_FV_HANDLE
*VolumeHandle
921 PEI_CORE_INSTANCE
*Private
;
922 PEI_CORE_FV_HANDLE
*CoreFvHandle
;
924 if (VolumeHandle
== NULL
) {
925 return EFI_INVALID_PARAMETER
;
928 Private
= PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices
);
930 CoreFvHandle
= FindNextCoreFvHandle (Private
, Instance
);
931 if (CoreFvHandle
== NULL
) {
932 *VolumeHandle
= NULL
;
933 return EFI_NOT_FOUND
;
936 *VolumeHandle
= CoreFvHandle
->FvHandle
;
943 Find a file within a volume by its name.
945 @param FileName A pointer to the name of the file to find within the firmware volume.
946 @param VolumeHandle The firmware volume to search
947 @param FileHandle Upon exit, points to the found file's handle
948 or NULL if it could not be found.
950 @retval EFI_SUCCESS File was found.
951 @retval EFI_NOT_FOUND File was not found.
952 @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or FileName was NULL.
957 PeiFfsFindFileByName (
958 IN CONST EFI_GUID
*FileName
,
959 IN EFI_PEI_FV_HANDLE VolumeHandle
,
960 OUT EFI_PEI_FILE_HANDLE
*FileHandle
963 PEI_CORE_FV_HANDLE
*CoreFvHandle
;
965 if ((VolumeHandle
== NULL
) || (FileName
== NULL
) || (FileHandle
== NULL
)) {
966 return EFI_INVALID_PARAMETER
;
969 CoreFvHandle
= FvHandleToCoreHandle (VolumeHandle
);
970 if ((CoreFvHandle
== NULL
) || (CoreFvHandle
->FvPpi
== NULL
)) {
971 return EFI_NOT_FOUND
;
974 return CoreFvHandle
->FvPpi
->FindFileByName (CoreFvHandle
->FvPpi
, FileName
, &VolumeHandle
, FileHandle
);
978 Returns information about a specific file.
980 @param FileHandle Handle of the file.
981 @param FileInfo Upon exit, points to the file's information.
983 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
984 @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file.
985 @retval EFI_SUCCESS File information returned.
991 IN EFI_PEI_FILE_HANDLE FileHandle
,
992 OUT EFI_FV_FILE_INFO
*FileInfo
995 PEI_CORE_FV_HANDLE
*CoreFvHandle
;
997 if ((FileHandle
== NULL
) || (FileInfo
== NULL
)) {
998 return EFI_INVALID_PARAMETER
;
1002 // Retrieve the FirmwareVolume which the file resides in.
1004 CoreFvHandle
= FileHandleToVolume (FileHandle
);
1005 if ((CoreFvHandle
== NULL
) || (CoreFvHandle
->FvPpi
== NULL
)) {
1006 return EFI_INVALID_PARAMETER
;
1009 return CoreFvHandle
->FvPpi
->GetFileInfo (CoreFvHandle
->FvPpi
, FileHandle
, FileInfo
);
1014 Returns information about the specified volume.
1016 This function returns information about a specific firmware
1017 volume, including its name, type, attributes, starting address
1020 @param VolumeHandle Handle of the volume.
1021 @param VolumeInfo Upon exit, points to the volume's information.
1023 @retval EFI_SUCCESS Volume information returned.
1024 @retval EFI_INVALID_PARAMETER If VolumeHandle does not represent a valid volume.
1025 @retval EFI_INVALID_PARAMETER If VolumeHandle is NULL.
1026 @retval EFI_SUCCESS Information successfully returned.
1027 @retval EFI_INVALID_PARAMETER The volume designated by the VolumeHandle is not available.
1032 PeiFfsGetVolumeInfo (
1033 IN EFI_PEI_FV_HANDLE VolumeHandle
,
1034 OUT EFI_FV_INFO
*VolumeInfo
1037 PEI_CORE_FV_HANDLE
*CoreHandle
;
1039 if ((VolumeInfo
== NULL
) || (VolumeHandle
== NULL
)) {
1040 return EFI_INVALID_PARAMETER
;
1043 CoreHandle
= FvHandleToCoreHandle (VolumeHandle
);
1045 if ((CoreHandle
== NULL
) || (CoreHandle
->FvPpi
== NULL
)) {
1046 return EFI_INVALID_PARAMETER
;
1049 return CoreHandle
->FvPpi
->GetVolumeInfo (CoreHandle
->FvPpi
, VolumeHandle
, VolumeInfo
);
1053 Get Fv image from the FV type file, then install FV INFO ppi, Build FV hob.
1055 @param ParentFvCoreHandle Pointer of EFI_CORE_FV_HANDLE to parent Fv image that contain this Fv image.
1056 @param ParentFvFileHandle File handle of a Fv type file that contain this Fv image.
1058 @retval EFI_NOT_FOUND FV image can't be found.
1059 @retval EFI_SUCCESS Successfully to process it.
1060 @retval EFI_OUT_OF_RESOURCES Can not allocate page when aligning FV image
1061 @retval Others Can not find EFI_SECTION_FIRMWARE_VOLUME_IMAGE section
1066 IN PEI_CORE_FV_HANDLE
*ParentFvCoreHandle
,
1067 IN EFI_PEI_FILE_HANDLE ParentFvFileHandle
1071 EFI_FV_INFO ParentFvImageInfo
;
1074 EFI_PEI_HOB_POINTERS HobPtr
;
1075 EFI_PEI_FIRMWARE_VOLUME_PPI
*ParentFvPpi
;
1076 EFI_PEI_FV_HANDLE ParentFvHandle
;
1077 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
1078 EFI_FV_FILE_INFO FileInfo
;
1082 // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
1085 HobPtr
.Raw
= GetHobList ();
1086 while ((HobPtr
.Raw
= GetNextHob (EFI_HOB_TYPE_FV2
, HobPtr
.Raw
)) != NULL
) {
1087 if (CompareGuid (&(((EFI_FFS_FILE_HEADER
*)ParentFvFileHandle
)->Name
), &HobPtr
.FirmwareVolume2
->FileName
)) {
1089 // this FILE has been dispatched, it will not be dispatched again.
1091 DEBUG ((EFI_D_INFO
, "FV file %p has been dispatched!\r\n", ParentFvFileHandle
));
1094 HobPtr
.Raw
= GET_NEXT_HOB (HobPtr
);
1097 ParentFvHandle
= ParentFvCoreHandle
->FvHandle
;
1098 ParentFvPpi
= ParentFvCoreHandle
->FvPpi
;
1101 // Find FvImage in FvFile
1103 Status
= ParentFvPpi
->FindSectionByType (
1105 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
1110 if (EFI_ERROR (Status
)) {
1115 // FvAlignment must be more than 8 bytes required by FvHeader structure.
1117 FvAlignment
= 1 << ((ReadUnaligned32 (&FvHeader
->Attributes
) & EFI_FVB2_ALIGNMENT
) >> 16);
1118 if (FvAlignment
< 8) {
1125 if ((UINTN
) FvHeader
% FvAlignment
!= 0) {
1126 FvLength
= ReadUnaligned64 (&FvHeader
->FvLength
);
1127 NewFvBuffer
= AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32
) FvLength
), FvAlignment
);
1128 if (NewFvBuffer
== NULL
) {
1129 return EFI_OUT_OF_RESOURCES
;
1131 CopyMem (NewFvBuffer
, FvHeader
, (UINTN
) FvLength
);
1132 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) NewFvBuffer
;
1135 Status
= ParentFvPpi
->GetVolumeInfo (ParentFvPpi
, ParentFvHandle
, &ParentFvImageInfo
);
1136 ASSERT_EFI_ERROR (Status
);
1138 Status
= ParentFvPpi
->GetFileInfo (ParentFvPpi
, ParentFvFileHandle
, &FileInfo
);
1139 ASSERT_EFI_ERROR (Status
);
1142 // Install FvPpi and Build FvHob
1144 PeiServicesInstallFvInfoPpi (
1145 &FvHeader
->FileSystemGuid
,
1147 (UINT32
) FvHeader
->FvLength
,
1148 &ParentFvImageInfo
.FvName
,
1153 // Inform the extracted FvImage to Fv HOB consumer phase, i.e. DXE phase
1156 (EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
,
1161 // Makes the encapsulated volume show up in DXE phase to skip processing of
1162 // encapsulated file again.
1165 (EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
,
1167 &ParentFvImageInfo
.FvName
,
1175 Process a firmware volume and create a volume handle.
1177 Create a volume handle from the information in the buffer. For
1178 memory-mapped firmware volumes, Buffer and BufferSize refer to
1179 the start of the firmware volume and the firmware volume size.
1180 For non memory-mapped firmware volumes, this points to a
1181 buffer which contains the necessary information for creating
1182 the firmware volume handle. Normally, these values are derived
1183 from the EFI_FIRMWARE_VOLUME_INFO_PPI.
1186 @param This Points to this instance of the
1187 EFI_PEI_FIRMWARE_VOLUME_PPI.
1188 @param Buffer Points to the start of the buffer.
1189 @param BufferSize Size of the buffer.
1190 @param FvHandle Points to the returned firmware volume
1191 handle. The firmware volume handle must
1192 be unique within the system.
1194 @retval EFI_SUCCESS Firmware volume handle created.
1195 @retval EFI_VOLUME_CORRUPTED Volume was corrupt.
1200 PeiFfsFvPpiProcessVolume (
1201 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI
*This
,
1203 IN UINTN BufferSize
,
1204 OUT EFI_PEI_FV_HANDLE
*FvHandle
1209 ASSERT (FvHandle
!= NULL
);
1211 if (Buffer
== NULL
) {
1212 return EFI_VOLUME_CORRUPTED
;
1216 // The build-in EFI_PEI_FIRMWARE_VOLUME_PPI for FFS2/FFS3 support memory-mapped
1217 // FV image and the handle is pointed to Fv image's buffer.
1219 *FvHandle
= (EFI_PEI_FV_HANDLE
) Buffer
;
1222 // Do verify for given FV buffer.
1224 Status
= VerifyFv ((EFI_FIRMWARE_VOLUME_HEADER
*) Buffer
);
1225 if (EFI_ERROR(Status
)) {
1226 DEBUG ((EFI_D_ERROR
, "Fail to verify FV which address is 0x%11p", Buffer
));
1227 return EFI_VOLUME_CORRUPTED
;
1234 Finds the next file of the specified type.
1236 This service enables PEI modules to discover additional firmware files.
1237 The FileHandle must be unique within the system.
1239 @param This Points to this instance of the
1240 EFI_PEI_FIRMWARE_VOLUME_PPI.
1241 @param SearchType A filter to find only files of this type. Type
1242 EFI_FV_FILETYPE_ALL causes no filtering to be
1244 @param FvHandle Handle of firmware volume in which to
1246 @param FileHandle Points to the current handle from which to
1247 begin searching or NULL to start at the
1248 beginning of the firmware volume. Updated
1249 upon return to reflect the file found.
1251 @retval EFI_SUCCESS The file was found.
1252 @retval EFI_NOT_FOUND The file was not found. FileHandle contains NULL.
1257 PeiFfsFvPpiFindFileByType (
1258 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI
*This
,
1259 IN EFI_FV_FILETYPE SearchType
,
1260 IN EFI_PEI_FV_HANDLE FvHandle
,
1261 IN OUT EFI_PEI_FILE_HANDLE
*FileHandle
1264 return FindFileEx (FvHandle
, NULL
, SearchType
, FileHandle
, NULL
);
1268 Find a file within a volume by its name.
1270 This service searches for files with a specific name, within
1271 either the specified firmware volume or all firmware volumes.
1273 @param This Points to this instance of the
1274 EFI_PEI_FIRMWARE_VOLUME_PPI.
1275 @param FileName A pointer to the name of the file to find
1276 within the firmware volume.
1277 @param FvHandle Upon entry, the pointer to the firmware
1278 volume to search or NULL if all firmware
1279 volumes should be searched. Upon exit, the
1280 actual firmware volume in which the file was
1282 @param FileHandle Upon exit, points to the found file's
1283 handle or NULL if it could not be found.
1285 @retval EFI_SUCCESS File was found.
1286 @retval EFI_NOT_FOUND File was not found.
1287 @retval EFI_INVALID_PARAMETER FvHandle or FileHandle or
1294 PeiFfsFvPpiFindFileByName (
1295 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI
*This
,
1296 IN CONST EFI_GUID
*FileName
,
1297 IN EFI_PEI_FV_HANDLE
*FvHandle
,
1298 OUT EFI_PEI_FILE_HANDLE
*FileHandle
1302 PEI_CORE_INSTANCE
*PrivateData
;
1305 if ((FvHandle
== NULL
) || (FileName
== NULL
) || (FileHandle
== NULL
)) {
1306 return EFI_INVALID_PARAMETER
;
1309 if (*FvHandle
!= NULL
) {
1310 Status
= FindFileEx (*FvHandle
, FileName
, 0, FileHandle
, NULL
);
1311 if (Status
== EFI_NOT_FOUND
) {
1316 // If *FvHandle = NULL, so search all FV for given filename
1318 Status
= EFI_NOT_FOUND
;
1320 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer());
1321 for (Index
= 0; Index
< PrivateData
->FvCount
; Index
++) {
1323 // Only search the FV which is associated with a EFI_PEI_FIRMWARE_VOLUME_PPI instance.
1325 if (PrivateData
->Fv
[Index
].FvPpi
!= NULL
) {
1326 Status
= FindFileEx (PrivateData
->Fv
[Index
].FvHandle
, FileName
, 0, FileHandle
, NULL
);
1327 if (!EFI_ERROR (Status
)) {
1328 *FvHandle
= PrivateData
->Fv
[Index
].FvHandle
;
1339 Returns information about a specific file.
1341 This function returns information about a specific
1342 file, including its file name, type, attributes, starting
1345 @param This Points to this instance of the
1346 EFI_PEI_FIRMWARE_VOLUME_PPI.
1347 @param FileHandle Handle of the file.
1348 @param FileInfo Upon exit, points to the file's
1351 @retval EFI_SUCCESS File information returned.
1352 @retval EFI_INVALID_PARAMETER If FileHandle does not
1353 represent a valid file.
1354 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
1359 PeiFfsFvPpiGetFileInfo (
1360 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI
*This
,
1361 IN EFI_PEI_FILE_HANDLE FileHandle
,
1362 OUT EFI_FV_FILE_INFO
*FileInfo
1366 UINT8 ErasePolarity
;
1367 EFI_FFS_FILE_HEADER
*FileHeader
;
1368 PEI_CORE_FV_HANDLE
*CoreFvHandle
;
1369 PEI_FW_VOL_INSTANCE
*FwVolInstance
;
1371 if ((FileHandle
== NULL
) || (FileInfo
== NULL
)) {
1372 return EFI_INVALID_PARAMETER
;
1376 // Retrieve the FirmwareVolume which the file resides in.
1378 CoreFvHandle
= FileHandleToVolume (FileHandle
);
1379 if (CoreFvHandle
== NULL
) {
1380 return EFI_INVALID_PARAMETER
;
1383 FwVolInstance
= PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This
);
1385 if ((CoreFvHandle
->FvHeader
->Attributes
& EFI_FVB2_ERASE_POLARITY
) != 0) {
1392 // Get FileState which is the highest bit of the State
1394 FileState
= GetFileState (ErasePolarity
, (EFI_FFS_FILE_HEADER
*)FileHandle
);
1396 switch (FileState
) {
1397 case EFI_FILE_DATA_VALID
:
1398 case EFI_FILE_MARKED_FOR_UPDATE
:
1401 return EFI_INVALID_PARAMETER
;
1404 FileHeader
= (EFI_FFS_FILE_HEADER
*)FileHandle
;
1405 CopyMem (&FileInfo
->FileName
, &FileHeader
->Name
, sizeof(EFI_GUID
));
1406 FileInfo
->FileType
= FileHeader
->Type
;
1407 FileInfo
->FileAttributes
= FfsAttributes2FvFileAttributes (FileHeader
->Attributes
);
1408 if ((CoreFvHandle
->FvHeader
->Attributes
& EFI_FVB2_MEMORY_MAPPED
) == EFI_FVB2_MEMORY_MAPPED
) {
1409 FileInfo
->FileAttributes
|= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED
;
1411 if (IS_FFS_FILE2 (FileHeader
)) {
1412 ASSERT (FFS_FILE2_SIZE (FileHeader
) > 0x00FFFFFF);
1413 if (!FwVolInstance
->IsFfs3Fv
) {
1414 DEBUG ((EFI_D_ERROR
, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FileHeader
->Name
));
1415 return EFI_INVALID_PARAMETER
;
1417 FileInfo
->BufferSize
= FFS_FILE2_SIZE (FileHeader
) - sizeof (EFI_FFS_FILE_HEADER2
);
1418 FileInfo
->Buffer
= (UINT8
*) FileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
);
1420 FileInfo
->BufferSize
= FFS_FILE_SIZE (FileHeader
) - sizeof (EFI_FFS_FILE_HEADER
);
1421 FileInfo
->Buffer
= (UINT8
*) FileHeader
+ sizeof (EFI_FFS_FILE_HEADER
);
1427 This function returns information about the firmware volume.
1429 @param This Points to this instance of the
1430 EFI_PEI_FIRMWARE_VOLUME_PPI.
1431 @param FvHandle Handle to the firmware handle.
1432 @param VolumeInfo Points to the returned firmware volume
1435 @retval EFI_SUCCESS Information returned successfully.
1436 @retval EFI_INVALID_PARAMETER FvHandle does not indicate a valid
1437 firmware volume or VolumeInfo is NULL.
1442 PeiFfsFvPpiGetVolumeInfo (
1443 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI
*This
,
1444 IN EFI_PEI_FV_HANDLE FvHandle
,
1445 OUT EFI_FV_INFO
*VolumeInfo
1448 EFI_FIRMWARE_VOLUME_HEADER FwVolHeader
;
1449 EFI_FIRMWARE_VOLUME_EXT_HEADER
*FwVolExHeaderInfo
;
1451 if ((VolumeInfo
== NULL
) || (FvHandle
== NULL
)) {
1452 return EFI_INVALID_PARAMETER
;
1456 // VolumeHandle may not align at 8 byte,
1457 // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte.
1458 // So, Copy FvHeader into the local FvHeader structure.
1460 CopyMem (&FwVolHeader
, FvHandle
, sizeof (EFI_FIRMWARE_VOLUME_HEADER
));
1463 // Check Fv Image Signature
1465 if (FwVolHeader
.Signature
!= EFI_FVH_SIGNATURE
) {
1466 return EFI_INVALID_PARAMETER
;
1469 ZeroMem (VolumeInfo
, sizeof (EFI_FV_INFO
));
1470 VolumeInfo
->FvAttributes
= FwVolHeader
.Attributes
;
1471 VolumeInfo
->FvStart
= (VOID
*) FvHandle
;
1472 VolumeInfo
->FvSize
= FwVolHeader
.FvLength
;
1473 CopyMem (&VolumeInfo
->FvFormat
, &FwVolHeader
.FileSystemGuid
, sizeof(EFI_GUID
));
1475 if (FwVolHeader
.ExtHeaderOffset
!= 0) {
1476 FwVolExHeaderInfo
= (EFI_FIRMWARE_VOLUME_EXT_HEADER
*)(((UINT8
*)FvHandle
) + FwVolHeader
.ExtHeaderOffset
);
1477 CopyMem (&VolumeInfo
->FvName
, &FwVolExHeaderInfo
->FvName
, sizeof(EFI_GUID
));
1484 Find the next matching section in the firmware file.
1486 This service enables PEI modules to discover sections
1487 of a given type within a valid file.
1489 @param This Points to this instance of the
1490 EFI_PEI_FIRMWARE_VOLUME_PPI.
1491 @param SearchType A filter to find only sections of this
1493 @param FileHandle Handle of firmware file in which to
1495 @param SectionData Updated upon return to point to the
1498 @retval EFI_SUCCESS Section was found.
1499 @retval EFI_NOT_FOUND Section of the specified type was not
1500 found. SectionData contains NULL.
1504 PeiFfsFvPpiFindSectionByType (
1505 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI
*This
,
1506 IN EFI_SECTION_TYPE SearchType
,
1507 IN EFI_PEI_FILE_HANDLE FileHandle
,
1508 OUT VOID
**SectionData
1511 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
1513 EFI_COMMON_SECTION_HEADER
*Section
;
1514 PEI_FW_VOL_INSTANCE
*FwVolInstance
;
1516 FwVolInstance
= PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This
);
1518 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)(FileHandle
);
1520 if (IS_FFS_FILE2 (FfsFileHeader
)) {
1521 ASSERT (FFS_FILE2_SIZE (FfsFileHeader
) > 0x00FFFFFF);
1522 if (!FwVolInstance
->IsFfs3Fv
) {
1523 DEBUG ((EFI_D_ERROR
, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader
->Name
));
1524 return EFI_NOT_FOUND
;
1526 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
));
1527 FileSize
= FFS_FILE2_SIZE (FfsFileHeader
) - sizeof (EFI_FFS_FILE_HEADER2
);
1529 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
));
1530 FileSize
= FFS_FILE_SIZE (FfsFileHeader
) - sizeof (EFI_FFS_FILE_HEADER
);
1533 return ProcessSection (
1534 GetPeiServicesTablePointer (),
1539 FwVolInstance
->IsFfs3Fv
1544 Convert the handle of FV to pointer of corresponding PEI_CORE_FV_HANDLE.
1546 @param FvHandle The handle of a FV.
1548 @retval NULL if can not find.
1549 @return Pointer of corresponding PEI_CORE_FV_HANDLE.
1551 PEI_CORE_FV_HANDLE
*
1552 FvHandleToCoreHandle (
1553 IN EFI_PEI_FV_HANDLE FvHandle
1557 PEI_CORE_INSTANCE
*PrivateData
;
1559 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer());
1560 for (Index
= 0; Index
< PrivateData
->FvCount
; Index
++) {
1561 if (FvHandle
== PrivateData
->Fv
[Index
].FvHandle
) {
1562 return &PrivateData
->Fv
[Index
];
1570 Get instance of PEI_CORE_FV_HANDLE for next volume according to given index.
1572 This routine also will install FvInfo ppi for FV hob in PI ways.
1574 @param Private Pointer of PEI_CORE_INSTANCE
1575 @param Instance The index of FV want to be searched.
1577 @return Instance of PEI_CORE_FV_HANDLE.
1579 PEI_CORE_FV_HANDLE
*
1580 FindNextCoreFvHandle (
1581 IN PEI_CORE_INSTANCE
*Private
,
1587 EFI_HOB_FIRMWARE_VOLUME
*FvHob
;
1590 // Handle Framework FvHob and Install FvInfo Ppi for it.
1592 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport
)) {
1594 // Loop to search the wanted FirmwareVolume which supports FFS
1596 FvHob
= (EFI_HOB_FIRMWARE_VOLUME
*)GetFirstHob (EFI_HOB_TYPE_FV
);
1597 while (FvHob
!= NULL
) {
1599 // Search whether FvHob has been installed into PeiCore's FV database.
1600 // If found, no need install new FvInfoPpi for it.
1602 for (Index
= 0, Match
= FALSE
; Index
< Private
->FvCount
; Index
++) {
1603 if ((EFI_PEI_FV_HANDLE
)(UINTN
)FvHob
->BaseAddress
== Private
->Fv
[Index
].FvHeader
) {
1610 // Search whether FvHob has been cached into PeiCore's Unknown FV database.
1611 // If found, no need install new FvInfoPpi for it.
1614 for (Index
= 0; Index
< Private
->UnknownFvInfoCount
; Index
++) {
1615 if ((UINTN
)FvHob
->BaseAddress
== (UINTN
)Private
->UnknownFvInfo
[Index
].FvInfo
) {
1623 // If the Fv in FvHob has not been installed into PeiCore's FV database and has
1624 // not been cached into PeiCore's Unknown FV database, install a new FvInfoPpi
1625 // for it then PeiCore will dispatch it in callback of FvInfoPpi.
1628 PeiServicesInstallFvInfoPpi (
1629 &(((EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)FvHob
->BaseAddress
)->FileSystemGuid
),
1630 (VOID
*)(UINTN
)FvHob
->BaseAddress
,
1631 (UINT32
)FvHob
->Length
,
1637 FvHob
= (EFI_HOB_FIRMWARE_VOLUME
*)GetNextHob (EFI_HOB_TYPE_FV
, (VOID
*)((UINTN
)FvHob
+ FvHob
->Header
.HobLength
));
1641 ASSERT (Private
->FvCount
<= FixedPcdGet32 (PcdPeiCoreMaxFvSupported
));
1642 if (Instance
>= Private
->FvCount
) {
1646 return &Private
->Fv
[Instance
];
1650 After PeiCore image is shadowed into permanent memory, all build-in FvPpi should
1651 be re-installed with the instance in permanent memory and all cached FvPpi pointers in
1652 PrivateData->Fv[] array should be fixed up to be pointed to the one in permenant
1655 @param PrivateData Pointer to PEI_CORE_INSTANCE.
1659 IN PEI_CORE_INSTANCE
*PrivateData
1663 EFI_PEI_PPI_DESCRIPTOR
*OldDescriptor
;
1668 // Locate old build-in Ffs2 EFI_PEI_FIRMWARE_VOLUME_PPI which
1671 Status
= PeiServicesLocatePpi (
1672 &gEfiFirmwareFileSystem2Guid
,
1677 ASSERT_EFI_ERROR (Status
);
1680 // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs2
1681 // which is shadowed from flash to permanent memory within PeiCore image.
1683 Status
= PeiServicesReInstallPpi (OldDescriptor
, &mPeiFfs2FvPpiList
);
1684 ASSERT_EFI_ERROR (Status
);
1687 // Fixup all FvPpi pointers for the implementation in flash to permanent memory.
1689 for (Index
= 0; Index
< FixedPcdGet32 (PcdPeiCoreMaxFvSupported
); Index
++) {
1690 if (PrivateData
->Fv
[Index
].FvPpi
== OldFfsFvPpi
) {
1691 PrivateData
->Fv
[Index
].FvPpi
= &mPeiFfs2FwVol
.Fv
;
1696 // Locate old build-in Ffs3 EFI_PEI_FIRMWARE_VOLUME_PPI which
1699 Status
= PeiServicesLocatePpi (
1700 &gEfiFirmwareFileSystem3Guid
,
1705 ASSERT_EFI_ERROR (Status
);
1708 // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs3
1709 // which is shadowed from flash to permanent memory within PeiCore image.
1711 Status
= PeiServicesReInstallPpi (OldDescriptor
, &mPeiFfs3FvPpiList
);
1712 ASSERT_EFI_ERROR (Status
);
1715 // Fixup all FvPpi pointers for the implementation in flash to permanent memory.
1717 for (Index
= 0; Index
< FixedPcdGet32 (PcdPeiCoreMaxFvSupported
); Index
++) {
1718 if (PrivateData
->Fv
[Index
].FvPpi
== OldFfsFvPpi
) {
1719 PrivateData
->Fv
[Index
].FvPpi
= &mPeiFfs3FwVol
.Fv
;
1725 Report the information for a new discoveried FV in unknown third-party format.
1727 If the EFI_PEI_FIRMWARE_VOLUME_PPI has not been installed for third-party FV format, but
1728 the FV in this format has been discoveried, then this FV's information will be cached into
1729 PEI_CORE_INSTANCE's UnknownFvInfo array.
1730 Also a notification would be installed for unknown third-party FV format guid, if EFI_PEI_FIRMWARE_VOLUME_PPI
1731 is installed later by platform's PEIM, the original unknown third-party FV will be processed by
1732 using new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
1734 @param PrivateData Point to instance of PEI_CORE_INSTANCE
1735 @param Format Point to the unknown third-party format guid.
1736 @param FvInfo Point to FvInfo buffer.
1737 @param FvInfoSize The size of FvInfo buffer.
1739 @retval EFI_OUT_OF_RESOURCES The FV info array in PEI_CORE_INSTANCE has no more spaces.
1740 @retval EFI_SUCCESS Success to add the information for unknown FV.
1743 AddUnknownFormatFvInfo (
1744 IN PEI_CORE_INSTANCE
*PrivateData
,
1745 IN EFI_GUID
*Format
,
1747 IN UINT32 FvInfoSize
1750 PEI_CORE_UNKNOW_FORMAT_FV_INFO
*NewUnknownFv
;
1752 if (PrivateData
->UnknownFvInfoCount
+ 1 >= FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)) {
1753 return EFI_OUT_OF_RESOURCES
;
1756 NewUnknownFv
= &PrivateData
->UnknownFvInfo
[PrivateData
->UnknownFvInfoCount
];
1757 PrivateData
->UnknownFvInfoCount
++;
1759 CopyGuid (&NewUnknownFv
->FvFormat
, Format
);
1760 NewUnknownFv
->FvInfo
= FvInfo
;
1761 NewUnknownFv
->FvInfoSize
= FvInfoSize
;
1762 NewUnknownFv
->NotifyDescriptor
.Flags
= (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
);
1763 NewUnknownFv
->NotifyDescriptor
.Guid
= &NewUnknownFv
->FvFormat
;
1764 NewUnknownFv
->NotifyDescriptor
.Notify
= ThirdPartyFvPpiNotifyCallback
;
1766 PeiServicesNotifyPpi (&NewUnknownFv
->NotifyDescriptor
);
1771 Find the FV information according to third-party FV format guid.
1773 This routine also will remove the FV information found by given FV format guid from
1774 PrivateData->UnknownFvInfo[].
1776 @param PrivateData Point to instance of PEI_CORE_INSTANCE
1777 @param Format Point to given FV format guid
1778 @param FvInfo On return, the pointer of FV information buffer
1779 @param FvInfoSize On return, the size of FV information buffer.
1781 @retval EFI_NOT_FOUND The FV is not found for new installed EFI_PEI_FIRMWARE_VOLUME_PPI
1782 @retval EFI_SUCCESS Success to find a FV which could be processed by new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
1785 FindUnknownFormatFvInfo (
1786 IN PEI_CORE_INSTANCE
*PrivateData
,
1787 IN EFI_GUID
*Format
,
1789 OUT UINT32
*FvInfoSize
1796 for (; Index
< PrivateData
->UnknownFvInfoCount
; Index
++) {
1797 if (CompareGuid (Format
, &PrivateData
->UnknownFvInfo
[Index
].FvFormat
)) {
1802 if (Index
== PrivateData
->UnknownFvInfoCount
) {
1803 return EFI_NOT_FOUND
;
1806 *FvInfo
= PrivateData
->UnknownFvInfo
[Index
].FvInfo
;
1807 *FvInfoSize
= PrivateData
->UnknownFvInfo
[Index
].FvInfoSize
;
1810 // Remove an entry from UnknownFvInfo array.
1813 for (;Index2
< PrivateData
->UnknownFvInfoCount
; Index2
++, Index
++) {
1814 CopyMem (&PrivateData
->UnknownFvInfo
[Index
], &PrivateData
->UnknownFvInfo
[Index2
], sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO
));
1816 PrivateData
->UnknownFvInfoCount
--;
1821 Notification callback function for EFI_PEI_FIRMWARE_VOLUME_PPI.
1823 When a EFI_PEI_FIRMWARE_VOLUME_PPI is installed to support new FV format, this
1824 routine is called to process all discoveried FVs in this format.
1826 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
1827 @param NotifyDescriptor Address of the notification descriptor data structure.
1828 @param Ppi Address of the PPI that was installed.
1830 @retval EFI_SUCCESS The notification callback is processed correctly.
1834 ThirdPartyFvPpiNotifyCallback (
1835 IN EFI_PEI_SERVICES
**PeiServices
,
1836 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
1840 PEI_CORE_INSTANCE
*PrivateData
;
1841 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
1845 EFI_PEI_FV_HANDLE FvHandle
;
1846 BOOLEAN IsProcessed
;
1848 EFI_PEI_FILE_HANDLE FileHandle
;
1851 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices
);
1852 FvPpi
= (EFI_PEI_FIRMWARE_VOLUME_PPI
*) Ppi
;
1855 Status
= FindUnknownFormatFvInfo (PrivateData
, NotifyDescriptor
->Guid
, &FvInfo
, &FvInfoSize
);
1856 if (EFI_ERROR (Status
)) {
1861 // Process new found FV and get FV handle.
1863 Status
= FvPpi
->ProcessVolume (FvPpi
, FvInfo
, FvInfoSize
, &FvHandle
);
1864 if (EFI_ERROR (Status
)) {
1865 DEBUG ((EFI_D_ERROR
, "Fail to process the FV 0x%p, FV may be corrupted!\n", FvInfo
));
1870 // Check whether the FV has already been processed.
1872 IsProcessed
= FALSE
;
1873 for (FvIndex
= 0; FvIndex
< PrivateData
->FvCount
; FvIndex
++) {
1874 if (PrivateData
->Fv
[FvIndex
].FvHandle
== FvHandle
) {
1875 DEBUG ((EFI_D_INFO
, "The Fv %p has already been processed!\n", FvInfo
));
1885 if (PrivateData
->FvCount
>= FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)) {
1886 DEBUG ((EFI_D_ERROR
, "The number of Fv Images (%d) exceed the max supported FVs (%d) in Pei", PrivateData
->FvCount
+ 1, FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)));
1887 DEBUG ((EFI_D_ERROR
, "PcdPeiCoreMaxFvSupported value need be reconfigurated in DSC"));
1892 // Update internal PEI_CORE_FV array.
1894 PrivateData
->Fv
[PrivateData
->FvCount
].FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FvInfo
;
1895 PrivateData
->Fv
[PrivateData
->FvCount
].FvPpi
= FvPpi
;
1896 PrivateData
->Fv
[PrivateData
->FvCount
].FvHandle
= FvHandle
;
1899 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
1900 (UINT32
) PrivateData
->FvCount
,
1905 PrivateData
->FvCount
++;
1908 // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
1912 Status
= FvPpi
->FindFileByType (
1914 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
1918 if (!EFI_ERROR (Status
)) {
1919 Status
= FvPpi
->FindSectionByType (
1921 EFI_SECTION_PEI_DEPEX
,
1925 if (!EFI_ERROR (Status
)) {
1926 if (!PeimDispatchReadiness (PeiServices
, DepexData
)) {
1928 // Dependency is not satisfied.
1934 DEBUG ((EFI_D_INFO
, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle
, PrivateData
->FvCount
- 1, FvHandle
));
1935 ProcessFvFile (&PrivateData
->Fv
[PrivateData
->FvCount
- 1], FileHandle
);
1937 } while (FileHandle
!= NULL
);