2 Pei Core Firmware File System service routines.
4 Copyright (c) 2006 - 2011, 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 Returns the file state set by the highest zero bit in the State field
64 @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY
65 in the Attributes field.
66 @param FfsHeader Pointer to FFS File Header.
68 @retval EFI_FFS_FILE_STATE File state is set by the highest none zero bit
69 in the header State field.
73 IN UINT8 ErasePolarity
,
74 IN EFI_FFS_FILE_HEADER
*FfsHeader
77 EFI_FFS_FILE_STATE FileState
;
78 EFI_FFS_FILE_STATE HighestBit
;
80 FileState
= FfsHeader
->State
;
82 if (ErasePolarity
!= 0) {
83 FileState
= (EFI_FFS_FILE_STATE
)~FileState
;
87 // Get file state set by its highest none zero bit.
90 while (HighestBit
!= 0 && (HighestBit
& FileState
) == 0) {
98 Calculates the checksum of the header of a file.
100 @param FileHeader Pointer to FFS File Header.
102 @return Checksum of the header.
103 Zero means the header is good.
104 Non-zero means the header is bad.
107 CalculateHeaderChecksum (
108 IN EFI_FFS_FILE_HEADER
*FileHeader
111 EFI_FFS_FILE_HEADER2 TestFileHeader
;
113 if (IS_FFS_FILE2 (FileHeader
)) {
114 CopyMem (&TestFileHeader
, FileHeader
, sizeof (EFI_FFS_FILE_HEADER2
));
116 // Ingore State and File field in FFS header.
118 TestFileHeader
.State
= 0;
119 TestFileHeader
.IntegrityCheck
.Checksum
.File
= 0;
121 return CalculateSum8 ((CONST UINT8
*) &TestFileHeader
, sizeof (EFI_FFS_FILE_HEADER2
));
123 CopyMem (&TestFileHeader
, FileHeader
, sizeof (EFI_FFS_FILE_HEADER
));
125 // Ingore State and File field in FFS header.
127 TestFileHeader
.State
= 0;
128 TestFileHeader
.IntegrityCheck
.Checksum
.File
= 0;
130 return CalculateSum8 ((CONST UINT8
*) &TestFileHeader
, sizeof (EFI_FFS_FILE_HEADER
));
135 Find FV handler according to FileHandle in that FV.
137 @param FileHandle Handle of file image
139 @return Pointer to instance of PEI_CORE_FV_HANDLE.
143 IN EFI_PEI_FILE_HANDLE FileHandle
147 PEI_CORE_INSTANCE
*PrivateData
;
148 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
150 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
152 for (Index
= 0; Index
< PrivateData
->FvCount
; Index
++) {
153 FwVolHeader
= PrivateData
->Fv
[Index
].FvHeader
;
154 if (((UINT64
) (UINTN
) FileHandle
> (UINT64
) (UINTN
) FwVolHeader
) && \
155 ((UINT64
) (UINTN
) FileHandle
<= ((UINT64
) (UINTN
) FwVolHeader
+ FwVolHeader
->FvLength
- 1))) {
156 return &PrivateData
->Fv
[Index
];
163 Given the input file pointer, search for the first matching file in the
164 FFS volume as defined by SearchType. The search starts from FileHeader inside
165 the Firmware Volume defined by FwVolHeader.
166 If SearchType is EFI_FV_FILETYPE_ALL, the first FFS file will return without check its file type.
167 If SearchType is PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE,
168 the first PEIM, or COMBINED PEIM or FV file type FFS file will return.
170 @param FvHandle Pointer to the FV header of the volume to search
171 @param FileName File name
172 @param SearchType Filter to find only files of this type.
173 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
174 @param FileHandle This parameter must point to a valid FFS volume.
175 @param AprioriFile Pointer to AprioriFile image in this FV if has
177 @return EFI_NOT_FOUND No files matching the search criteria were found
178 @retval EFI_SUCCESS Success to search given file
183 IN CONST EFI_PEI_FV_HANDLE FvHandle
,
184 IN CONST EFI_GUID
*FileName
, OPTIONAL
185 IN EFI_FV_FILETYPE SearchType
,
186 IN OUT EFI_PEI_FILE_HANDLE
*FileHandle
,
187 IN OUT EFI_PEI_FV_HANDLE
*AprioriFile OPTIONAL
190 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
191 EFI_FFS_FILE_HEADER
**FileHeader
;
192 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
194 UINT32 FileOccupiedSize
;
203 // Convert the handle of FV to FV header for memory-mapped firmware volume
205 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FvHandle
;
206 FileHeader
= (EFI_FFS_FILE_HEADER
**)FileHandle
;
208 IsFfs3Fv
= CompareGuid (&FwVolHeader
->FileSystemGuid
, &gEfiFirmwareFileSystem3Guid
);
210 FvLength
= FwVolHeader
->FvLength
;
211 if ((FwVolHeader
->Attributes
& EFI_FVB2_ERASE_POLARITY
) != 0) {
218 // If FileHeader is not specified (NULL) or FileName is not NULL,
219 // start with the first file in the firmware volume. Otherwise,
220 // start from the FileHeader.
222 if ((*FileHeader
== NULL
) || (FileName
!= NULL
)) {
223 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FwVolHeader
+ FwVolHeader
->HeaderLength
);
225 if (IS_FFS_FILE2 (*FileHeader
)) {
227 DEBUG ((EFI_D_ERROR
, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &(*FileHeader
)->Name
));
229 FileLength
= FFS_FILE2_SIZE (*FileHeader
);
230 ASSERT (FileLength
> 0x00FFFFFF);
232 FileLength
= FFS_FILE_SIZE (*FileHeader
);
235 // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
237 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
238 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)*FileHeader
+ FileOccupiedSize
);
241 FileOffset
= (UINT32
) ((UINT8
*)FfsFileHeader
- (UINT8
*)FwVolHeader
);
242 ASSERT (FileOffset
<= 0xFFFFFFFF);
244 while (FileOffset
< (FvLength
- sizeof (EFI_FFS_FILE_HEADER
))) {
246 // Get FileState which is the highest bit of the State
248 FileState
= GetFileState (ErasePolarity
, FfsFileHeader
);
251 case EFI_FILE_HEADER_CONSTRUCTION
:
252 case EFI_FILE_HEADER_INVALID
:
253 if (IS_FFS_FILE2 (FfsFileHeader
)) {
255 DEBUG ((EFI_D_ERROR
, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader
->Name
));
257 FileOffset
+= sizeof (EFI_FFS_FILE_HEADER2
);
258 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
));
260 FileOffset
+= sizeof (EFI_FFS_FILE_HEADER
);
261 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
));
265 case EFI_FILE_DATA_VALID
:
266 case EFI_FILE_MARKED_FOR_UPDATE
:
267 if (CalculateHeaderChecksum (FfsFileHeader
) != 0) {
270 return EFI_NOT_FOUND
;
273 if (IS_FFS_FILE2 (FfsFileHeader
)) {
274 FileLength
= FFS_FILE2_SIZE (FfsFileHeader
);
275 ASSERT (FileLength
> 0x00FFFFFF);
276 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
278 DEBUG ((EFI_D_ERROR
, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader
->Name
));
279 FileOffset
+= FileOccupiedSize
;
280 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) ((UINT8
*) FfsFileHeader
+ FileOccupiedSize
);
284 FileLength
= FFS_FILE_SIZE (FfsFileHeader
);
285 FileOccupiedSize
= GET_OCCUPIED_SIZE (FileLength
, 8);
288 DataCheckSum
= FFS_FIXED_CHECKSUM
;
289 if ((FfsFileHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) == FFS_ATTRIB_CHECKSUM
) {
290 if (IS_FFS_FILE2 (FfsFileHeader
)) {
291 DataCheckSum
= CalculateCheckSum8 ((CONST UINT8
*) FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
), FileLength
- sizeof(EFI_FFS_FILE_HEADER2
));
293 DataCheckSum
= CalculateCheckSum8 ((CONST UINT8
*) FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
), FileLength
- sizeof(EFI_FFS_FILE_HEADER
));
296 if (FfsFileHeader
->IntegrityCheck
.Checksum
.File
!= DataCheckSum
) {
299 return EFI_NOT_FOUND
;
302 if (FileName
!= NULL
) {
303 if (CompareGuid (&FfsFileHeader
->Name
, (EFI_GUID
*)FileName
)) {
304 *FileHeader
= FfsFileHeader
;
307 } else if (SearchType
== PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE
) {
308 if ((FfsFileHeader
->Type
== EFI_FV_FILETYPE_PEIM
) ||
309 (FfsFileHeader
->Type
== EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
) ||
310 (FfsFileHeader
->Type
== EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
)) {
312 *FileHeader
= FfsFileHeader
;
314 } else if (AprioriFile
!= NULL
) {
315 if (FfsFileHeader
->Type
== EFI_FV_FILETYPE_FREEFORM
) {
316 if (CompareGuid (&FfsFileHeader
->Name
, &gPeiAprioriFileNameGuid
)) {
317 *AprioriFile
= FfsFileHeader
;
321 } else if (((SearchType
== FfsFileHeader
->Type
) || (SearchType
== EFI_FV_FILETYPE_ALL
)) &&
322 (FfsFileHeader
->Type
!= EFI_FV_FILETYPE_FFS_PAD
)) {
323 *FileHeader
= FfsFileHeader
;
327 FileOffset
+= FileOccupiedSize
;
328 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ FileOccupiedSize
);
331 case EFI_FILE_DELETED
:
332 if (IS_FFS_FILE2 (FfsFileHeader
)) {
334 DEBUG ((EFI_D_ERROR
, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader
->Name
));
336 FileLength
= FFS_FILE2_SIZE (FfsFileHeader
);
337 ASSERT (FileLength
> 0x00FFFFFF);
339 FileLength
= FFS_FILE_SIZE (FfsFileHeader
);
341 FileOccupiedSize
= GET_OCCUPIED_SIZE(FileLength
, 8);
342 FileOffset
+= FileOccupiedSize
;
343 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)((UINT8
*)FfsFileHeader
+ FileOccupiedSize
);
348 return EFI_NOT_FOUND
;
353 return EFI_NOT_FOUND
;
357 Initialize PeiCore Fv List.
359 @param PrivateData - Pointer to PEI_CORE_INSTANCE.
360 @param SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF.
364 IN PEI_CORE_INSTANCE
*PrivateData
,
365 IN CONST EFI_SEC_PEI_HAND_OFF
*SecCoreData
369 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
370 EFI_PEI_FV_HANDLE FvHandle
;
371 EFI_FIRMWARE_VOLUME_HEADER
*BfvHeader
;
374 // Install FV_PPI for FFS2 file system.
376 PeiServicesInstallPpi (&mPeiFfs2FvPpiList
);
379 // Install FV_PPI for FFS3 file system.
381 PeiServicesInstallPpi (&mPeiFfs3FvPpiList
);
383 BfvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)SecCoreData
->BootFirmwareVolumeBase
;
386 // The FV_PPI in BFV's format should be installed.
388 Status
= PeiServicesLocatePpi (
389 &BfvHeader
->FileSystemGuid
,
394 ASSERT_EFI_ERROR (Status
);
399 FvPpi
->ProcessVolume (
401 SecCoreData
->BootFirmwareVolumeBase
,
402 (UINTN
)BfvHeader
->FvLength
,
407 // Update internal PEI_CORE_FV array.
409 PrivateData
->Fv
[PrivateData
->FvCount
].FvHeader
= BfvHeader
;
410 PrivateData
->Fv
[PrivateData
->FvCount
].FvPpi
= FvPpi
;
411 PrivateData
->Fv
[PrivateData
->FvCount
].FvHandle
= FvHandle
;
414 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
415 (UINT32
) PrivateData
->FvCount
,
420 PrivateData
->FvCount
++;
423 // Post a call-back for the FvInfoPPI services to expose
424 // additional Fvs to PeiCore.
426 Status
= PeiServicesNotifyPpi (&mNotifyOnFvInfoList
);
427 ASSERT_EFI_ERROR (Status
);
432 Process Firmware Volum Information once FvInfoPPI install.
433 The FV Info will be registered into PeiCore private data structure.
434 And search the inside FV image, if found, the new FV INFO PPI will be installed.
436 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
437 @param NotifyDescriptor Address of the notification descriptor data structure.
438 @param Ppi Address of the PPI that was installed.
440 @retval EFI_SUCCESS The FV Info is registered into PeiCore private data structure.
441 @return if not EFI_SUCESS, fail to verify FV.
446 FirmwareVolmeInfoPpiNotifyCallback (
447 IN EFI_PEI_SERVICES
**PeiServices
,
448 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
452 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*FvInfoPpi
;
453 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
454 PEI_CORE_INSTANCE
*PrivateData
;
456 EFI_PEI_FV_HANDLE FvHandle
;
458 EFI_PEI_FILE_HANDLE FileHandle
;
461 Status
= EFI_SUCCESS
;
462 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices
);
464 if (PrivateData
->FvCount
>= FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)) {
465 DEBUG ((EFI_D_ERROR
, "The number of Fv Images (%d) exceed the max supported FVs (%d) in Pei", PrivateData
->FvCount
+ 1, FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)));
466 DEBUG ((EFI_D_ERROR
, "PcdPeiCoreMaxFvSupported value need be reconfigurated in DSC"));
470 FvInfoPpi
= (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI
*)Ppi
;
473 // Locate the corresponding FV_PPI according to founded FV's format guid
475 Status
= PeiServicesLocatePpi (
476 &FvInfoPpi
->FvFormat
,
481 if (!EFI_ERROR (Status
)) {
483 // Process new found FV and get FV handle.
485 Status
= FvPpi
->ProcessVolume (FvPpi
, FvInfoPpi
->FvInfo
, FvInfoPpi
->FvInfoSize
, &FvHandle
);
486 if (EFI_ERROR (Status
)) {
487 DEBUG ((EFI_D_ERROR
, "Fail to process new found FV, FV may be corrupted!\n"));
492 // Check whether the FV has already been processed.
494 for (FvIndex
= 0; FvIndex
< PrivateData
->FvCount
; FvIndex
++) {
495 if (PrivateData
->Fv
[FvIndex
].FvHandle
== FvHandle
) {
496 DEBUG ((EFI_D_INFO
, "The Fv %p has already been processed!\n", FvInfoPpi
->FvInfo
));
502 // Update internal PEI_CORE_FV array.
504 PrivateData
->Fv
[PrivateData
->FvCount
].FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FvInfoPpi
->FvInfo
;
505 PrivateData
->Fv
[PrivateData
->FvCount
].FvPpi
= FvPpi
;
506 PrivateData
->Fv
[PrivateData
->FvCount
].FvHandle
= FvHandle
;
509 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
510 (UINT32
) PrivateData
->FvCount
,
511 (VOID
*) FvInfoPpi
->FvInfo
,
512 FvInfoPpi
->FvInfoSize
,
515 PrivateData
->FvCount
++;
518 // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
522 Status
= FvPpi
->FindFileByType (
524 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
528 if (!EFI_ERROR (Status
)) {
529 Status
= FvPpi
->FindSectionByType (
531 EFI_SECTION_PEI_DEPEX
,
535 if (!EFI_ERROR (Status
)) {
536 if (!PeimDispatchReadiness (PeiServices
, DepexData
)) {
538 // Dependency is not satisfied.
544 DEBUG ((EFI_D_INFO
, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle
, PrivateData
->FvCount
- 1, FvHandle
));
545 ProcessFvFile (&PrivateData
->Fv
[PrivateData
->FvCount
- 1], FileHandle
);
547 } while (FileHandle
!= NULL
);
549 DEBUG ((EFI_D_ERROR
, "Fail to process FV %p because no corresponding EFI_FIRMWARE_VOLUME_PPI is found!\n", FvInfoPpi
->FvInfo
));
551 AddUnknownFormatFvInfo (PrivateData
, &FvInfoPpi
->FvFormat
, FvInfoPpi
->FvInfo
, FvInfoPpi
->FvInfoSize
);
558 Go through the file to search SectionType section.
559 Search within encapsulation sections (compression and GUIDed) recursively,
560 until the match section is found.
562 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
563 @param SectionType Filter to find only section of this type.
564 @param Section From where to search.
565 @param SectionSize The file size to search.
566 @param OutputBuffer A pointer to the discovered section, if successful.
567 NULL if section not found
568 @param IsFfs3Fv Indicates the FV format.
570 @return EFI_NOT_FOUND The match section is not found.
571 @return EFI_SUCCESS The match section is found.
576 IN CONST EFI_PEI_SERVICES
**PeiServices
,
577 IN EFI_SECTION_TYPE SectionType
,
578 IN EFI_COMMON_SECTION_HEADER
*Section
,
579 IN UINTN SectionSize
,
580 OUT VOID
**OutputBuffer
,
585 UINT32 SectionLength
;
587 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI
*GuidSectionPpi
;
588 EFI_PEI_DECOMPRESS_PPI
*DecompressPpi
;
592 UINT32 Authentication
;
593 PEI_CORE_INSTANCE
*PrivateData
;
595 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices
);
596 *OutputBuffer
= NULL
;
599 Status
= EFI_NOT_FOUND
;
602 while (ParsedLength
< SectionSize
) {
604 if (IS_SECTION2 (Section
)) {
605 ASSERT (SECTION2_SIZE (Section
) > 0x00FFFFFF);
607 DEBUG ((EFI_D_ERROR
, "Found a FFS3 formatted section in a non-FFS3 formatted FV.\n"));
608 SectionLength
= SECTION2_SIZE (Section
);
610 // SectionLength is adjusted it is 4 byte aligned.
611 // Go to the next section
613 SectionLength
= GET_OCCUPIED_SIZE (SectionLength
, 4);
614 ASSERT (SectionLength
!= 0);
615 ParsedLength
+= SectionLength
;
616 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) Section
+ SectionLength
);
621 if (Section
->Type
== SectionType
) {
622 if (IS_SECTION2 (Section
)) {
623 *OutputBuffer
= (VOID
*)((UINT8
*) Section
+ sizeof (EFI_COMMON_SECTION_HEADER2
));
625 *OutputBuffer
= (VOID
*)((UINT8
*) Section
+ sizeof (EFI_COMMON_SECTION_HEADER
));
628 } else if ((Section
->Type
== EFI_SECTION_GUID_DEFINED
) || (Section
->Type
== EFI_SECTION_COMPRESSION
)) {
630 // Check the encapsulated section is extracted into the cache data.
632 for (Index
= 0; Index
< PrivateData
->CacheSection
.AllSectionCount
; Index
++) {
633 if (Section
== PrivateData
->CacheSection
.Section
[Index
]) {
634 PpiOutput
= PrivateData
->CacheSection
.SectionData
[Index
];
635 PpiOutputSize
= PrivateData
->CacheSection
.SectionSize
[Index
];
637 // Search section directly from the cache data.
639 return ProcessSection (
650 Status
= EFI_NOT_FOUND
;
651 if (Section
->Type
== EFI_SECTION_GUID_DEFINED
) {
652 if (IS_SECTION2 (Section
)) {
653 Status
= PeiServicesLocatePpi (
654 &((EFI_GUID_DEFINED_SECTION2
*)Section
)->SectionDefinitionGuid
,
657 (VOID
**) &GuidSectionPpi
660 Status
= PeiServicesLocatePpi (
661 &((EFI_GUID_DEFINED_SECTION
*)Section
)->SectionDefinitionGuid
,
664 (VOID
**) &GuidSectionPpi
667 if (!EFI_ERROR (Status
)) {
668 Status
= GuidSectionPpi
->ExtractSection (
676 } else if (Section
->Type
== EFI_SECTION_COMPRESSION
) {
677 Status
= PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid
, 0, NULL
, (VOID
**) &DecompressPpi
);
678 if (!EFI_ERROR (Status
)) {
679 Status
= DecompressPpi
->Decompress (
681 (CONST EFI_COMPRESSION_SECTION
*) Section
,
688 if (!EFI_ERROR (Status
)) {
690 // Update cache section data.
692 if (PrivateData
->CacheSection
.AllSectionCount
< CACHE_SETION_MAX_NUMBER
) {
693 PrivateData
->CacheSection
.AllSectionCount
++;
695 PrivateData
->CacheSection
.Section
[PrivateData
->CacheSection
.SectionIndex
] = Section
;
696 PrivateData
->CacheSection
.SectionData
[PrivateData
->CacheSection
.SectionIndex
] = PpiOutput
;
697 PrivateData
->CacheSection
.SectionSize
[PrivateData
->CacheSection
.SectionIndex
] = PpiOutputSize
;
698 PrivateData
->CacheSection
.SectionIndex
= (PrivateData
->CacheSection
.SectionIndex
+ 1)%CACHE_SETION_MAX_NUMBER
;
700 return ProcessSection (
711 if (IS_SECTION2 (Section
)) {
712 SectionLength
= SECTION2_SIZE (Section
);
714 SectionLength
= SECTION_SIZE (Section
);
717 // SectionLength is adjusted it is 4 byte aligned.
718 // Go to the next section
720 SectionLength
= GET_OCCUPIED_SIZE (SectionLength
, 4);
721 ASSERT (SectionLength
!= 0);
722 ParsedLength
+= SectionLength
;
723 Section
= (EFI_COMMON_SECTION_HEADER
*)((UINT8
*)Section
+ SectionLength
);
726 return EFI_NOT_FOUND
;
731 Searches for the next matching section within the specified file.
733 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
734 @param SectionType Filter to find only sections of this type.
735 @param FileHandle Pointer to the current file to search.
736 @param SectionData A pointer to the discovered section, if successful.
737 NULL if section not found
739 @retval EFI_NOT_FOUND The section was not found.
740 @retval EFI_SUCCESS The section was found.
745 PeiFfsFindSectionData (
746 IN CONST EFI_PEI_SERVICES
**PeiServices
,
747 IN EFI_SECTION_TYPE SectionType
,
748 IN EFI_PEI_FILE_HANDLE FileHandle
,
749 OUT VOID
**SectionData
752 PEI_CORE_FV_HANDLE
*CoreFvHandle
;
754 CoreFvHandle
= FileHandleToVolume (FileHandle
);
755 if ((CoreFvHandle
== NULL
) || (CoreFvHandle
->FvPpi
== NULL
)) {
756 return EFI_NOT_FOUND
;
759 return CoreFvHandle
->FvPpi
->FindSectionByType (CoreFvHandle
->FvPpi
, SectionType
, FileHandle
, SectionData
);
763 Searches for the next matching file in the firmware volume.
765 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
766 @param SearchType Filter to find only files of this type.
767 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
768 @param FvHandle Handle of firmware volume in which to search.
769 @param FileHandle On entry, points to the current handle from which to begin searching or NULL to start
770 at the beginning of the firmware volume. On exit, points the file handle of the next file
771 in the volume or NULL if there are no more files.
773 @retval EFI_NOT_FOUND The file was not found.
774 @retval EFI_NOT_FOUND The header checksum was not zero.
775 @retval EFI_SUCCESS The file was found.
781 IN CONST EFI_PEI_SERVICES
**PeiServices
,
783 IN EFI_PEI_FV_HANDLE FvHandle
,
784 IN OUT EFI_PEI_FILE_HANDLE
*FileHandle
787 PEI_CORE_FV_HANDLE
*CoreFvHandle
;
789 CoreFvHandle
= FvHandleToCoreHandle (FvHandle
);
792 // To make backward compatiblity, if can not find corresponding the handle of FV
793 // then treat FV as build-in FFS2/FFS3 format and memory mapped FV that FV handle is pointed
794 // to the address of first byte of FV.
796 if ((CoreFvHandle
== NULL
) && FeaturePcdGet (PcdFrameworkCompatibilitySupport
)) {
797 return FindFileEx (FvHandle
, NULL
, SearchType
, FileHandle
, NULL
);
800 if ((CoreFvHandle
== NULL
) || CoreFvHandle
->FvPpi
== NULL
) {
801 return EFI_NOT_FOUND
;
804 return CoreFvHandle
->FvPpi
->FindFileByType (CoreFvHandle
->FvPpi
, SearchType
, FvHandle
, FileHandle
);
809 Search the firmware volumes by index
811 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
812 @param Instance This instance of the firmware volume to find. The value 0 is the Boot Firmware
814 @param VolumeHandle On exit, points to the next volume handle or NULL if it does not exist.
816 @retval EFI_INVALID_PARAMETER VolumeHandle is NULL
817 @retval EFI_NOT_FOUND The volume was not found.
818 @retval EFI_SUCCESS The volume was found.
823 PeiFfsFindNextVolume (
824 IN CONST EFI_PEI_SERVICES
**PeiServices
,
826 IN OUT EFI_PEI_FV_HANDLE
*VolumeHandle
829 PEI_CORE_INSTANCE
*Private
;
830 PEI_CORE_FV_HANDLE
*CoreFvHandle
;
832 if (VolumeHandle
== NULL
) {
833 return EFI_INVALID_PARAMETER
;
836 Private
= PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices
);
838 CoreFvHandle
= FindNextCoreFvHandle (Private
, Instance
);
839 if (CoreFvHandle
== NULL
) {
840 *VolumeHandle
= NULL
;
841 return EFI_NOT_FOUND
;
844 *VolumeHandle
= CoreFvHandle
->FvHandle
;
851 Find a file within a volume by its name.
853 @param FileName A pointer to the name of the file to find within the firmware volume.
854 @param VolumeHandle The firmware volume to search
855 @param FileHandle Upon exit, points to the found file's handle
856 or NULL if it could not be found.
858 @retval EFI_SUCCESS File was found.
859 @retval EFI_NOT_FOUND File was not found.
860 @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or FileName was NULL.
865 PeiFfsFindFileByName (
866 IN CONST EFI_GUID
*FileName
,
867 IN EFI_PEI_FV_HANDLE VolumeHandle
,
868 OUT EFI_PEI_FILE_HANDLE
*FileHandle
871 PEI_CORE_FV_HANDLE
*CoreFvHandle
;
873 if ((VolumeHandle
== NULL
) || (FileName
== NULL
) || (FileHandle
== NULL
)) {
874 return EFI_INVALID_PARAMETER
;
877 CoreFvHandle
= FvHandleToCoreHandle (VolumeHandle
);
878 if ((CoreFvHandle
== NULL
) || (CoreFvHandle
->FvPpi
== NULL
)) {
879 return EFI_NOT_FOUND
;
882 return CoreFvHandle
->FvPpi
->FindFileByName (CoreFvHandle
->FvPpi
, FileName
, &VolumeHandle
, FileHandle
);
886 Returns information about a specific file.
888 @param FileHandle Handle of the file.
889 @param FileInfo Upon exit, points to the file's information.
891 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
892 @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file.
893 @retval EFI_SUCCESS File information returned.
899 IN EFI_PEI_FILE_HANDLE FileHandle
,
900 OUT EFI_FV_FILE_INFO
*FileInfo
903 PEI_CORE_FV_HANDLE
*CoreFvHandle
;
905 if ((FileHandle
== NULL
) || (FileInfo
== NULL
)) {
906 return EFI_INVALID_PARAMETER
;
910 // Retrieve the FirmwareVolume which the file resides in.
912 CoreFvHandle
= FileHandleToVolume (FileHandle
);
913 if ((CoreFvHandle
== NULL
) || (CoreFvHandle
->FvPpi
== NULL
)) {
914 return EFI_INVALID_PARAMETER
;
917 return CoreFvHandle
->FvPpi
->GetFileInfo (CoreFvHandle
->FvPpi
, FileHandle
, FileInfo
);
922 Returns information about the specified volume.
924 This function returns information about a specific firmware
925 volume, including its name, type, attributes, starting address
928 @param VolumeHandle Handle of the volume.
929 @param VolumeInfo Upon exit, points to the volume's information.
931 @retval EFI_SUCCESS Volume information returned.
932 @retval EFI_INVALID_PARAMETER If VolumeHandle does not represent a valid volume.
933 @retval EFI_INVALID_PARAMETER If VolumeHandle is NULL.
934 @retval EFI_SUCCESS Information successfully returned.
935 @retval EFI_INVALID_PARAMETER The volume designated by the VolumeHandle is not available.
940 PeiFfsGetVolumeInfo (
941 IN EFI_PEI_FV_HANDLE VolumeHandle
,
942 OUT EFI_FV_INFO
*VolumeInfo
945 PEI_CORE_FV_HANDLE
*CoreHandle
;
947 if ((VolumeInfo
== NULL
) || (VolumeHandle
== NULL
)) {
948 return EFI_INVALID_PARAMETER
;
951 CoreHandle
= FvHandleToCoreHandle (VolumeHandle
);
953 if ((CoreHandle
== NULL
) || (CoreHandle
->FvPpi
== NULL
)) {
954 return EFI_INVALID_PARAMETER
;
957 return CoreHandle
->FvPpi
->GetVolumeInfo (CoreHandle
->FvPpi
, VolumeHandle
, VolumeInfo
);
961 Get Fv image from the FV type file, then install FV INFO ppi, Build FV hob.
963 @param ParentFvCoreHandle Pointer of EFI_CORE_FV_HANDLE to parent Fv image that contain this Fv image.
964 @param ParentFvFileHandle File handle of a Fv type file that contain this Fv image.
966 @retval EFI_NOT_FOUND FV image can't be found.
967 @retval EFI_SUCCESS Successfully to process it.
968 @retval EFI_OUT_OF_RESOURCES Can not allocate page when aligning FV image
969 @retval Others Can not find EFI_SECTION_FIRMWARE_VOLUME_IMAGE section
974 IN PEI_CORE_FV_HANDLE
*ParentFvCoreHandle
,
975 IN EFI_PEI_FILE_HANDLE ParentFvFileHandle
979 EFI_FV_INFO ParentFvImageInfo
;
982 EFI_PEI_HOB_POINTERS HobPtr
;
983 EFI_PEI_FIRMWARE_VOLUME_PPI
*ParentFvPpi
;
984 EFI_PEI_FV_HANDLE ParentFvHandle
;
985 EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
;
986 EFI_FV_FILE_INFO FileInfo
;
990 // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
993 HobPtr
.Raw
= GetHobList ();
994 while ((HobPtr
.Raw
= GetNextHob (EFI_HOB_TYPE_FV2
, HobPtr
.Raw
)) != NULL
) {
995 if (CompareGuid (&(((EFI_FFS_FILE_HEADER
*)ParentFvFileHandle
)->Name
), &HobPtr
.FirmwareVolume2
->FileName
)) {
997 // this FILE has been dispatched, it will not be dispatched again.
999 DEBUG ((EFI_D_INFO
, "FV file %p has been dispatched!\r\n", ParentFvFileHandle
));
1002 HobPtr
.Raw
= GET_NEXT_HOB (HobPtr
);
1005 ParentFvHandle
= ParentFvCoreHandle
->FvHandle
;
1006 ParentFvPpi
= ParentFvCoreHandle
->FvPpi
;
1009 // Find FvImage in FvFile
1011 Status
= ParentFvPpi
->FindSectionByType (
1013 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
1018 if (EFI_ERROR (Status
)) {
1023 // FvAlignment must be more than 8 bytes required by FvHeader structure.
1025 FvAlignment
= 1 << ((ReadUnaligned32 (&FvHeader
->Attributes
) & EFI_FVB2_ALIGNMENT
) >> 16);
1026 if (FvAlignment
< 8) {
1033 if ((UINTN
) FvHeader
% FvAlignment
!= 0) {
1034 FvLength
= ReadUnaligned64 (&FvHeader
->FvLength
);
1035 NewFvBuffer
= AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32
) FvLength
), FvAlignment
);
1036 if (NewFvBuffer
== NULL
) {
1037 return EFI_OUT_OF_RESOURCES
;
1039 CopyMem (NewFvBuffer
, FvHeader
, (UINTN
) FvLength
);
1040 FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) NewFvBuffer
;
1043 Status
= ParentFvPpi
->GetVolumeInfo (ParentFvPpi
, ParentFvHandle
, &ParentFvImageInfo
);
1044 ASSERT_EFI_ERROR (Status
);
1046 Status
= ParentFvPpi
->GetFileInfo (ParentFvPpi
, ParentFvFileHandle
, &FileInfo
);
1047 ASSERT_EFI_ERROR (Status
);
1050 // Install FvPpi and Build FvHob
1052 PeiServicesInstallFvInfoPpi (
1053 &FvHeader
->FileSystemGuid
,
1055 (UINT32
) FvHeader
->FvLength
,
1056 &ParentFvImageInfo
.FvName
,
1061 // Inform the extracted FvImage to Fv HOB consumer phase, i.e. DXE phase
1064 (EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
,
1069 // Makes the encapsulated volume show up in DXE phase to skip processing of
1070 // encapsulated file again.
1073 (EFI_PHYSICAL_ADDRESS
) (UINTN
) FvHeader
,
1075 &ParentFvImageInfo
.FvName
,
1083 Process a firmware volume and create a volume handle.
1085 Create a volume handle from the information in the buffer. For
1086 memory-mapped firmware volumes, Buffer and BufferSize refer to
1087 the start of the firmware volume and the firmware volume size.
1088 For non memory-mapped firmware volumes, this points to a
1089 buffer which contains the necessary information for creating
1090 the firmware volume handle. Normally, these values are derived
1091 from the EFI_FIRMWARE_VOLUME_INFO_PPI.
1094 @param This Points to this instance of the
1095 EFI_PEI_FIRMWARE_VOLUME_PPI.
1096 @param Buffer Points to the start of the buffer.
1097 @param BufferSize Size of the buffer.
1098 @param FvHandle Points to the returned firmware volume
1099 handle. The firmware volume handle must
1100 be unique within the system.
1102 @retval EFI_SUCCESS Firmware volume handle created.
1103 @retval EFI_VOLUME_CORRUPTED Volume was corrupt.
1108 PeiFfsFvPpiProcessVolume (
1109 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI
*This
,
1111 IN UINTN BufferSize
,
1112 OUT EFI_PEI_FV_HANDLE
*FvHandle
1117 ASSERT (FvHandle
!= NULL
);
1119 if (Buffer
== NULL
) {
1120 return EFI_VOLUME_CORRUPTED
;
1124 // The build-in EFI_PEI_FIRMWARE_VOLUME_PPI for FFS2/FFS3 support memory-mapped
1125 // FV image and the handle is pointed to Fv image's buffer.
1127 *FvHandle
= (EFI_PEI_FV_HANDLE
) Buffer
;
1130 // Do verify for given FV buffer.
1132 Status
= VerifyFv ((EFI_FIRMWARE_VOLUME_HEADER
*) Buffer
);
1133 if (EFI_ERROR(Status
)) {
1134 DEBUG ((EFI_D_ERROR
, "Fail to verify FV which address is 0x%11p", Buffer
));
1135 return EFI_VOLUME_CORRUPTED
;
1142 Finds the next file of the specified type.
1144 This service enables PEI modules to discover additional firmware files.
1145 The FileHandle must be unique within the system.
1147 @param This Points to this instance of the
1148 EFI_PEI_FIRMWARE_VOLUME_PPI.
1149 @param SearchType A filter to find only files of this type. Type
1150 EFI_FV_FILETYPE_ALL causes no filtering to be
1152 @param FvHandle Handle of firmware volume in which to
1154 @param FileHandle Points to the current handle from which to
1155 begin searching or NULL to start at the
1156 beginning of the firmware volume. Updated
1157 upon return to reflect the file found.
1159 @retval EFI_SUCCESS The file was found.
1160 @retval EFI_NOT_FOUND The file was not found. FileHandle contains NULL.
1165 PeiFfsFvPpiFindFileByType (
1166 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI
*This
,
1167 IN EFI_FV_FILETYPE SearchType
,
1168 IN EFI_PEI_FV_HANDLE FvHandle
,
1169 IN OUT EFI_PEI_FILE_HANDLE
*FileHandle
1172 return FindFileEx (FvHandle
, NULL
, SearchType
, FileHandle
, NULL
);
1176 Find a file within a volume by its name.
1178 This service searches for files with a specific name, within
1179 either the specified firmware volume or all firmware volumes.
1181 @param This Points to this instance of the
1182 EFI_PEI_FIRMWARE_VOLUME_PPI.
1183 @param FileName A pointer to the name of the file to find
1184 within the firmware volume.
1185 @param FvHandle Upon entry, the pointer to the firmware
1186 volume to search or NULL if all firmware
1187 volumes should be searched. Upon exit, the
1188 actual firmware volume in which the file was
1190 @param FileHandle Upon exit, points to the found file's
1191 handle or NULL if it could not be found.
1193 @retval EFI_SUCCESS File was found.
1194 @retval EFI_NOT_FOUND File was not found.
1195 @retval EFI_INVALID_PARAMETER FvHandle or FileHandle or
1202 PeiFfsFvPpiFindFileByName (
1203 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI
*This
,
1204 IN CONST EFI_GUID
*FileName
,
1205 IN EFI_PEI_FV_HANDLE
*FvHandle
,
1206 OUT EFI_PEI_FILE_HANDLE
*FileHandle
1210 PEI_CORE_INSTANCE
*PrivateData
;
1213 if ((FvHandle
== NULL
) || (FileName
== NULL
) || (FileHandle
== NULL
)) {
1214 return EFI_INVALID_PARAMETER
;
1217 if (*FvHandle
!= NULL
) {
1218 Status
= FindFileEx (*FvHandle
, FileName
, 0, FileHandle
, NULL
);
1219 if (Status
== EFI_NOT_FOUND
) {
1224 // If *FvHandle = NULL, so search all FV for given filename
1226 Status
= EFI_NOT_FOUND
;
1228 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer());
1229 for (Index
= 0; Index
< PrivateData
->FvCount
; Index
++) {
1231 // Only search the FV which is associated with a EFI_PEI_FIRMWARE_VOLUME_PPI instance.
1233 if (PrivateData
->Fv
[Index
].FvPpi
!= NULL
) {
1234 Status
= FindFileEx (PrivateData
->Fv
[Index
].FvHandle
, FileName
, 0, FileHandle
, NULL
);
1235 if (!EFI_ERROR (Status
)) {
1236 *FvHandle
= PrivateData
->Fv
[Index
].FvHandle
;
1247 Returns information about a specific file.
1249 This function returns information about a specific
1250 file, including its file name, type, attributes, starting
1253 @param This Points to this instance of the
1254 EFI_PEI_FIRMWARE_VOLUME_PPI.
1255 @param FileHandle Handle of the file.
1256 @param FileInfo Upon exit, points to the file's
1259 @retval EFI_SUCCESS File information returned.
1260 @retval EFI_INVALID_PARAMETER If FileHandle does not
1261 represent a valid file.
1262 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
1267 PeiFfsFvPpiGetFileInfo (
1268 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI
*This
,
1269 IN EFI_PEI_FILE_HANDLE FileHandle
,
1270 OUT EFI_FV_FILE_INFO
*FileInfo
1274 UINT8 ErasePolarity
;
1275 EFI_FFS_FILE_HEADER
*FileHeader
;
1276 PEI_CORE_FV_HANDLE
*CoreFvHandle
;
1277 PEI_FW_VOL_INSTANCE
*FwVolInstance
;
1279 if ((FileHandle
== NULL
) || (FileInfo
== NULL
)) {
1280 return EFI_INVALID_PARAMETER
;
1284 // Retrieve the FirmwareVolume which the file resides in.
1286 CoreFvHandle
= FileHandleToVolume (FileHandle
);
1287 if (CoreFvHandle
== NULL
) {
1288 return EFI_INVALID_PARAMETER
;
1291 FwVolInstance
= PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This
);
1293 if ((CoreFvHandle
->FvHeader
->Attributes
& EFI_FVB2_ERASE_POLARITY
) != 0) {
1300 // Get FileState which is the highest bit of the State
1302 FileState
= GetFileState (ErasePolarity
, (EFI_FFS_FILE_HEADER
*)FileHandle
);
1304 switch (FileState
) {
1305 case EFI_FILE_DATA_VALID
:
1306 case EFI_FILE_MARKED_FOR_UPDATE
:
1309 return EFI_INVALID_PARAMETER
;
1312 FileHeader
= (EFI_FFS_FILE_HEADER
*)FileHandle
;
1313 CopyMem (&FileInfo
->FileName
, &FileHeader
->Name
, sizeof(EFI_GUID
));
1314 FileInfo
->FileType
= FileHeader
->Type
;
1315 FileInfo
->FileAttributes
= FileHeader
->Attributes
;
1316 if (IS_FFS_FILE2 (FileHeader
)) {
1317 ASSERT (FFS_FILE2_SIZE (FileHeader
) > 0x00FFFFFF);
1318 if (!FwVolInstance
->IsFfs3Fv
) {
1319 DEBUG ((EFI_D_ERROR
, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FileHeader
->Name
));
1320 return EFI_INVALID_PARAMETER
;
1322 FileInfo
->BufferSize
= FFS_FILE2_SIZE (FileHeader
) - sizeof (EFI_FFS_FILE_HEADER2
);
1323 FileInfo
->Buffer
= (UINT8
*) FileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
);
1325 FileInfo
->BufferSize
= FFS_FILE_SIZE (FileHeader
) - sizeof (EFI_FFS_FILE_HEADER
);
1326 FileInfo
->Buffer
= (UINT8
*) FileHeader
+ sizeof (EFI_FFS_FILE_HEADER
);
1332 This function returns information about the firmware volume.
1334 @param This Points to this instance of the
1335 EFI_PEI_FIRMWARE_VOLUME_PPI.
1336 @param FvHandle Handle to the firmware handle.
1337 @param VolumeInfo Points to the returned firmware volume
1340 @retval EFI_SUCCESS Information returned successfully.
1341 @retval EFI_INVALID_PARAMETER FvHandle does not indicate a valid
1342 firmware volume or VolumeInfo is NULL.
1347 PeiFfsFvPpiGetVolumeInfo (
1348 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI
*This
,
1349 IN EFI_PEI_FV_HANDLE FvHandle
,
1350 OUT EFI_FV_INFO
*VolumeInfo
1353 EFI_FIRMWARE_VOLUME_HEADER FwVolHeader
;
1354 EFI_FIRMWARE_VOLUME_EXT_HEADER
*FwVolExHeaderInfo
;
1356 if ((VolumeInfo
== NULL
) || (FvHandle
== NULL
)) {
1357 return EFI_INVALID_PARAMETER
;
1361 // VolumeHandle may not align at 8 byte,
1362 // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte.
1363 // So, Copy FvHeader into the local FvHeader structure.
1365 CopyMem (&FwVolHeader
, FvHandle
, sizeof (EFI_FIRMWARE_VOLUME_HEADER
));
1368 // Check Fv Image Signature
1370 if (FwVolHeader
.Signature
!= EFI_FVH_SIGNATURE
) {
1371 return EFI_INVALID_PARAMETER
;
1374 ZeroMem (VolumeInfo
, sizeof (EFI_FV_INFO
));
1375 VolumeInfo
->FvAttributes
= FwVolHeader
.Attributes
;
1376 VolumeInfo
->FvStart
= (VOID
*) FvHandle
;
1377 VolumeInfo
->FvSize
= FwVolHeader
.FvLength
;
1378 CopyMem (&VolumeInfo
->FvFormat
, &FwVolHeader
.FileSystemGuid
, sizeof(EFI_GUID
));
1380 if (FwVolHeader
.ExtHeaderOffset
!= 0) {
1381 FwVolExHeaderInfo
= (EFI_FIRMWARE_VOLUME_EXT_HEADER
*)(((UINT8
*)FvHandle
) + FwVolHeader
.ExtHeaderOffset
);
1382 CopyMem (&VolumeInfo
->FvName
, &FwVolExHeaderInfo
->FvName
, sizeof(EFI_GUID
));
1389 Find the next matching section in the firmware file.
1391 This service enables PEI modules to discover sections
1392 of a given type within a valid file.
1394 @param This Points to this instance of the
1395 EFI_PEI_FIRMWARE_VOLUME_PPI.
1396 @param SearchType A filter to find only sections of this
1398 @param FileHandle Handle of firmware file in which to
1400 @param SectionData Updated upon return to point to the
1403 @retval EFI_SUCCESS Section was found.
1404 @retval EFI_NOT_FOUND Section of the specified type was not
1405 found. SectionData contains NULL.
1409 PeiFfsFvPpiFindSectionByType (
1410 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI
*This
,
1411 IN EFI_SECTION_TYPE SearchType
,
1412 IN EFI_PEI_FILE_HANDLE FileHandle
,
1413 OUT VOID
**SectionData
1416 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
1418 EFI_COMMON_SECTION_HEADER
*Section
;
1419 PEI_FW_VOL_INSTANCE
*FwVolInstance
;
1421 FwVolInstance
= PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This
);
1423 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)(FileHandle
);
1425 if (IS_FFS_FILE2 (FfsFileHeader
)) {
1426 ASSERT (FFS_FILE2_SIZE (FfsFileHeader
) > 0x00FFFFFF);
1427 if (!FwVolInstance
->IsFfs3Fv
) {
1428 DEBUG ((EFI_D_ERROR
, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader
->Name
));
1429 return EFI_NOT_FOUND
;
1431 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER2
));
1432 FileSize
= FFS_FILE2_SIZE (FfsFileHeader
) - sizeof (EFI_FFS_FILE_HEADER2
);
1434 Section
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) FfsFileHeader
+ sizeof (EFI_FFS_FILE_HEADER
));
1435 FileSize
= FFS_FILE_SIZE (FfsFileHeader
) - sizeof (EFI_FFS_FILE_HEADER
);
1438 return ProcessSection (
1439 GetPeiServicesTablePointer (),
1444 FwVolInstance
->IsFfs3Fv
1449 Convert the handle of FV to pointer of corresponding PEI_CORE_FV_HANDLE.
1451 @param FvHandle The handle of a FV.
1453 @retval NULL if can not find.
1454 @return Pointer of corresponding PEI_CORE_FV_HANDLE.
1456 PEI_CORE_FV_HANDLE
*
1457 FvHandleToCoreHandle (
1458 IN EFI_PEI_FV_HANDLE FvHandle
1462 PEI_CORE_INSTANCE
*PrivateData
;
1464 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer());
1465 for (Index
= 0; Index
< PrivateData
->FvCount
; Index
++) {
1466 if (FvHandle
== PrivateData
->Fv
[Index
].FvHandle
) {
1467 return &PrivateData
->Fv
[Index
];
1475 Get instance of PEI_CORE_FV_HANDLE for next volume according to given index.
1477 This routine also will install FvInfo ppi for FV hob in PI ways.
1479 @param Private Pointer of PEI_CORE_INSTANCE
1480 @param Instance The index of FV want to be searched.
1482 @return Instance of PEI_CORE_FV_HANDLE.
1484 PEI_CORE_FV_HANDLE
*
1485 FindNextCoreFvHandle (
1486 IN PEI_CORE_INSTANCE
*Private
,
1492 EFI_HOB_FIRMWARE_VOLUME
*FvHob
;
1495 // Handle Framework FvHob and Install FvInfo Ppi for it.
1497 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport
)) {
1499 // Loop to search the wanted FirmwareVolume which supports FFS
1501 FvHob
= (EFI_HOB_FIRMWARE_VOLUME
*)GetFirstHob (EFI_HOB_TYPE_FV
);
1502 while (FvHob
!= NULL
) {
1504 // Search whether FvHob has been installed into PeiCore's FV database.
1505 // If found, no need install new FvInfoPpi for it.
1507 for (Index
= 0, Match
= FALSE
; Index
< Private
->FvCount
; Index
++) {
1508 if ((EFI_PEI_FV_HANDLE
)(UINTN
)FvHob
->BaseAddress
== Private
->Fv
[Index
].FvHeader
) {
1515 // Search whether FvHob has been cached into PeiCore's Unknown FV database.
1516 // If found, no need install new FvInfoPpi for it.
1519 for (Index
= 0; Index
< Private
->UnknownFvInfoCount
; Index
++) {
1520 if ((UINTN
)FvHob
->BaseAddress
== (UINTN
)Private
->UnknownFvInfo
[Index
].FvInfo
) {
1528 // If the Fv in FvHob has not been installed into PeiCore's FV database and has
1529 // not been cached into PeiCore's Unknown FV database, install a new FvInfoPpi
1530 // for it then PeiCore will dispatch it in callback of FvInfoPpi.
1533 PeiServicesInstallFvInfoPpi (
1534 &(((EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)FvHob
->BaseAddress
)->FileSystemGuid
),
1535 (VOID
*)(UINTN
)FvHob
->BaseAddress
,
1536 (UINT32
)FvHob
->Length
,
1542 FvHob
= (EFI_HOB_FIRMWARE_VOLUME
*)GetNextHob (EFI_HOB_TYPE_FV
, (VOID
*)((UINTN
)FvHob
+ FvHob
->Header
.HobLength
));
1546 ASSERT (Private
->FvCount
<= FixedPcdGet32 (PcdPeiCoreMaxFvSupported
));
1547 if (Instance
>= Private
->FvCount
) {
1551 return &Private
->Fv
[Instance
];
1555 After PeiCore image is shadowed into permanent memory, all build-in FvPpi should
1556 be re-installed with the instance in permanent memory and all cached FvPpi pointers in
1557 PrivateData->Fv[] array should be fixed up to be pointed to the one in permenant
1560 @param PrivateData Pointer to PEI_CORE_INSTANCE.
1564 IN PEI_CORE_INSTANCE
*PrivateData
1568 EFI_PEI_PPI_DESCRIPTOR
*OldDescriptor
;
1573 // Locate old build-in Ffs2 EFI_PEI_FIRMWARE_VOLUME_PPI which
1576 Status
= PeiServicesLocatePpi (
1577 &gEfiFirmwareFileSystem2Guid
,
1582 ASSERT_EFI_ERROR (Status
);
1585 // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs2
1586 // which is shadowed from flash to permanent memory within PeiCore image.
1588 Status
= PeiServicesReInstallPpi (OldDescriptor
, &mPeiFfs2FvPpiList
);
1589 ASSERT_EFI_ERROR (Status
);
1592 // Fixup all FvPpi pointers for the implementation in flash to permanent memory.
1594 for (Index
= 0; Index
< FixedPcdGet32 (PcdPeiCoreMaxFvSupported
); Index
++) {
1595 if (PrivateData
->Fv
[Index
].FvPpi
== OldFfsFvPpi
) {
1596 PrivateData
->Fv
[Index
].FvPpi
= &mPeiFfs2FwVol
.Fv
;
1601 // Locate old build-in Ffs3 EFI_PEI_FIRMWARE_VOLUME_PPI which
1604 Status
= PeiServicesLocatePpi (
1605 &gEfiFirmwareFileSystem3Guid
,
1610 ASSERT_EFI_ERROR (Status
);
1613 // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs3
1614 // which is shadowed from flash to permanent memory within PeiCore image.
1616 Status
= PeiServicesReInstallPpi (OldDescriptor
, &mPeiFfs3FvPpiList
);
1617 ASSERT_EFI_ERROR (Status
);
1620 // Fixup all FvPpi pointers for the implementation in flash to permanent memory.
1622 for (Index
= 0; Index
< FixedPcdGet32 (PcdPeiCoreMaxFvSupported
); Index
++) {
1623 if (PrivateData
->Fv
[Index
].FvPpi
== OldFfsFvPpi
) {
1624 PrivateData
->Fv
[Index
].FvPpi
= &mPeiFfs3FwVol
.Fv
;
1630 Report the information for a new discoveried FV in unknown third-party format.
1632 If the EFI_PEI_FIRMWARE_VOLUME_PPI has not been installed for third-party FV format, but
1633 the FV in this format has been discoveried, then this FV's information will be cached into
1634 PEI_CORE_INSTANCE's UnknownFvInfo array.
1635 Also a notification would be installed for unknown third-party FV format guid, if EFI_PEI_FIRMWARE_VOLUME_PPI
1636 is installed later by platform's PEIM, the original unknown third-party FV will be processed by
1637 using new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
1639 @param PrivateData Point to instance of PEI_CORE_INSTANCE
1640 @param Format Point to the unknown third-party format guid.
1641 @param FvInfo Point to FvInfo buffer.
1642 @param FvInfoSize The size of FvInfo buffer.
1644 @retval EFI_OUT_OF_RESOURCES The FV info array in PEI_CORE_INSTANCE has no more spaces.
1645 @retval EFI_SUCCESS Success to add the information for unknown FV.
1648 AddUnknownFormatFvInfo (
1649 IN PEI_CORE_INSTANCE
*PrivateData
,
1650 IN EFI_GUID
*Format
,
1652 IN UINT32 FvInfoSize
1655 PEI_CORE_UNKNOW_FORMAT_FV_INFO
*NewUnknownFv
;
1657 if (PrivateData
->UnknownFvInfoCount
+ 1 >= FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)) {
1658 return EFI_OUT_OF_RESOURCES
;
1661 NewUnknownFv
= &PrivateData
->UnknownFvInfo
[PrivateData
->UnknownFvInfoCount
];
1662 PrivateData
->UnknownFvInfoCount
++;
1664 CopyGuid (&NewUnknownFv
->FvFormat
, Format
);
1665 NewUnknownFv
->FvInfo
= FvInfo
;
1666 NewUnknownFv
->FvInfoSize
= FvInfoSize
;
1667 NewUnknownFv
->NotifyDescriptor
.Flags
= (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
);
1668 NewUnknownFv
->NotifyDescriptor
.Guid
= &NewUnknownFv
->FvFormat
;
1669 NewUnknownFv
->NotifyDescriptor
.Notify
= ThirdPartyFvPpiNotifyCallback
;
1671 PeiServicesNotifyPpi (&NewUnknownFv
->NotifyDescriptor
);
1676 Find the FV information according to third-party FV format guid.
1678 This routine also will remove the FV information found by given FV format guid from
1679 PrivateData->UnknownFvInfo[].
1681 @param PrivateData Point to instance of PEI_CORE_INSTANCE
1682 @param Format Point to given FV format guid
1683 @param FvInfo On return, the pointer of FV information buffer
1684 @param FvInfoSize On return, the size of FV information buffer.
1686 @retval EFI_NOT_FOUND The FV is not found for new installed EFI_PEI_FIRMWARE_VOLUME_PPI
1687 @retval EFI_SUCCESS Success to find a FV which could be processed by new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
1690 FindUnknownFormatFvInfo (
1691 IN PEI_CORE_INSTANCE
*PrivateData
,
1692 IN EFI_GUID
*Format
,
1694 OUT UINT32
*FvInfoSize
1701 for (; Index
< PrivateData
->UnknownFvInfoCount
; Index
++) {
1702 if (CompareGuid (Format
, &PrivateData
->UnknownFvInfo
[Index
].FvFormat
)) {
1707 if (Index
== PrivateData
->UnknownFvInfoCount
) {
1708 return EFI_NOT_FOUND
;
1711 *FvInfo
= PrivateData
->UnknownFvInfo
[Index
].FvInfo
;
1712 *FvInfoSize
= PrivateData
->UnknownFvInfo
[Index
].FvInfoSize
;
1715 // Remove an entry from UnknownFvInfo array.
1718 for (;Index2
< PrivateData
->UnknownFvInfoCount
; Index2
++, Index
++) {
1719 CopyMem (&PrivateData
->UnknownFvInfo
[Index
], &PrivateData
->UnknownFvInfo
[Index2
], sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO
));
1721 PrivateData
->UnknownFvInfoCount
--;
1726 Notification callback function for EFI_PEI_FIRMWARE_VOLUME_PPI.
1728 When a EFI_PEI_FIRMWARE_VOLUME_PPI is installed to support new FV format, this
1729 routine is called to process all discoveried FVs in this format.
1731 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
1732 @param NotifyDescriptor Address of the notification descriptor data structure.
1733 @param Ppi Address of the PPI that was installed.
1735 @retval EFI_SUCCESS The notification callback is processed correctly.
1739 ThirdPartyFvPpiNotifyCallback (
1740 IN EFI_PEI_SERVICES
**PeiServices
,
1741 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
1745 PEI_CORE_INSTANCE
*PrivateData
;
1746 EFI_PEI_FIRMWARE_VOLUME_PPI
*FvPpi
;
1750 EFI_PEI_FV_HANDLE FvHandle
;
1751 BOOLEAN IsProcessed
;
1753 EFI_PEI_FILE_HANDLE FileHandle
;
1756 PrivateData
= PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices
);
1757 FvPpi
= (EFI_PEI_FIRMWARE_VOLUME_PPI
*) Ppi
;
1760 Status
= FindUnknownFormatFvInfo (PrivateData
, NotifyDescriptor
->Guid
, &FvInfo
, &FvInfoSize
);
1761 if (EFI_ERROR (Status
)) {
1766 // Process new found FV and get FV handle.
1768 Status
= FvPpi
->ProcessVolume (FvPpi
, FvInfo
, FvInfoSize
, &FvHandle
);
1769 if (EFI_ERROR (Status
)) {
1770 DEBUG ((EFI_D_ERROR
, "Fail to process the FV 0x%p, FV may be corrupted!\n", FvInfo
));
1775 // Check whether the FV has already been processed.
1777 IsProcessed
= FALSE
;
1778 for (FvIndex
= 0; FvIndex
< PrivateData
->FvCount
; FvIndex
++) {
1779 if (PrivateData
->Fv
[FvIndex
].FvHandle
== FvHandle
) {
1780 DEBUG ((EFI_D_INFO
, "The Fv %p has already been processed!\n", FvInfo
));
1790 if (PrivateData
->FvCount
>= FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)) {
1791 DEBUG ((EFI_D_ERROR
, "The number of Fv Images (%d) exceed the max supported FVs (%d) in Pei", PrivateData
->FvCount
+ 1, FixedPcdGet32 (PcdPeiCoreMaxFvSupported
)));
1792 DEBUG ((EFI_D_ERROR
, "PcdPeiCoreMaxFvSupported value need be reconfigurated in DSC"));
1797 // Update internal PEI_CORE_FV array.
1799 PrivateData
->Fv
[PrivateData
->FvCount
].FvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) FvInfo
;
1800 PrivateData
->Fv
[PrivateData
->FvCount
].FvPpi
= FvPpi
;
1801 PrivateData
->Fv
[PrivateData
->FvCount
].FvHandle
= FvHandle
;
1804 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
1805 (UINT32
) PrivateData
->FvCount
,
1810 PrivateData
->FvCount
++;
1813 // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
1817 Status
= FvPpi
->FindFileByType (
1819 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
1823 if (!EFI_ERROR (Status
)) {
1824 Status
= FvPpi
->FindSectionByType (
1826 EFI_SECTION_PEI_DEPEX
,
1830 if (!EFI_ERROR (Status
)) {
1831 if (!PeimDispatchReadiness (PeiServices
, DepexData
)) {
1833 // Dependency is not satisfied.
1839 DEBUG ((EFI_D_INFO
, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle
, PrivateData
->FvCount
- 1, FvHandle
));
1840 ProcessFvFile (&PrivateData
->Fv
[PrivateData
->FvCount
- 1], FileHandle
);
1842 } while (FileHandle
!= NULL
);