1 /** @file
2 Pei Core Firmware File System service routines.
3
4 Copyright (c) 2015 HP Development Company, L.P.
5 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "FwVol.h"
17
18 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyOnFvInfoList[] = {
19 {
20 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
21 &gEfiPeiFirmwareVolumeInfoPpiGuid,
22 FirmwareVolmeInfoPpiNotifyCallback
23 },
24 {
25 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
26 &gEfiPeiFirmwareVolumeInfo2PpiGuid,
27 FirmwareVolmeInfoPpiNotifyCallback
28 }
29 };
30
31 PEI_FW_VOL_INSTANCE mPeiFfs2FwVol = {
32 PEI_FW_VOL_SIGNATURE,
33 FALSE,
34 {
35 PeiFfsFvPpiProcessVolume,
36 PeiFfsFvPpiFindFileByType,
37 PeiFfsFvPpiFindFileByName,
38 PeiFfsFvPpiGetFileInfo,
39 PeiFfsFvPpiGetVolumeInfo,
40 PeiFfsFvPpiFindSectionByType,
41 PeiFfsFvPpiGetFileInfo2,
42 PeiFfsFvPpiFindSectionByType2,
43 EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE,
44 EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION
45 }
46 };
47
48 PEI_FW_VOL_INSTANCE mPeiFfs3FwVol = {
49 PEI_FW_VOL_SIGNATURE,
50 TRUE,
51 {
52 PeiFfsFvPpiProcessVolume,
53 PeiFfsFvPpiFindFileByType,
54 PeiFfsFvPpiFindFileByName,
55 PeiFfsFvPpiGetFileInfo,
56 PeiFfsFvPpiGetVolumeInfo,
57 PeiFfsFvPpiFindSectionByType,
58 PeiFfsFvPpiGetFileInfo2,
59 PeiFfsFvPpiFindSectionByType2,
60 EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE,
61 EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION
62 }
63 };
64
65 EFI_PEI_PPI_DESCRIPTOR mPeiFfs2FvPpiList = {
66 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
67 &gEfiFirmwareFileSystem2Guid,
68 &mPeiFfs2FwVol.Fv
69 };
70
71 EFI_PEI_PPI_DESCRIPTOR mPeiFfs3FvPpiList = {
72 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
73 &gEfiFirmwareFileSystem3Guid,
74 &mPeiFfs3FwVol.Fv
75 };
76
77 /**
78 Required Alignment Alignment Value in FFS Alignment Value in
79 (bytes) Attributes Field Firmware Volume Interfaces
80 1 0 0
81 16 1 4
82 128 2 7
83 512 3 9
84 1 KB 4 10
85 4 KB 5 12
86 32 KB 6 15
87 64 KB 7 16
88 **/
89 UINT8 mFvAttributes[] = {0, 4, 7, 9, 10, 12, 15, 16};
90
91 /**
92 Convert the FFS File Attributes to FV File Attributes
93
94 @param FfsAttributes The attributes of UINT8 type.
95
96 @return The attributes of EFI_FV_FILE_ATTRIBUTES
97
98 **/
99 EFI_FV_FILE_ATTRIBUTES
FfsAttributes2FvFileAttributes(IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes)100 FfsAttributes2FvFileAttributes (
101 IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes
102 )
103 {
104 UINT8 DataAlignment;
105 EFI_FV_FILE_ATTRIBUTES FileAttribute;
106
107 DataAlignment = (UINT8) ((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3);
108 ASSERT (DataAlignment < 8);
109
110 FileAttribute = (EFI_FV_FILE_ATTRIBUTES) mFvAttributes[DataAlignment];
111
112 if ((FfsAttributes & FFS_ATTRIB_FIXED) == FFS_ATTRIB_FIXED) {
113 FileAttribute |= EFI_FV_FILE_ATTRIB_FIXED;
114 }
115
116 return FileAttribute;
117 }
118
119 /**
120 Returns the file state set by the highest zero bit in the State field
121
122 @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY
123 in the Attributes field.
124 @param FfsHeader Pointer to FFS File Header.
125
126 @retval EFI_FFS_FILE_STATE File state is set by the highest none zero bit
127 in the header State field.
128 **/
129 EFI_FFS_FILE_STATE
GetFileState(IN UINT8 ErasePolarity,IN EFI_FFS_FILE_HEADER * FfsHeader)130 GetFileState(
131 IN UINT8 ErasePolarity,
132 IN EFI_FFS_FILE_HEADER *FfsHeader
133 )
134 {
135 EFI_FFS_FILE_STATE FileState;
136 EFI_FFS_FILE_STATE HighestBit;
137
138 FileState = FfsHeader->State;
139
140 if (ErasePolarity != 0) {
141 FileState = (EFI_FFS_FILE_STATE)~FileState;
142 }
143
144 //
145 // Get file state set by its highest none zero bit.
146 //
147 HighestBit = 0x80;
148 while (HighestBit != 0 && (HighestBit & FileState) == 0) {
149 HighestBit >>= 1;
150 }
151
152 return HighestBit;
153 }
154
155 /**
156 Calculates the checksum of the header of a file.
157
158 @param FileHeader Pointer to FFS File Header.
159
160 @return Checksum of the header.
161 Zero means the header is good.
162 Non-zero means the header is bad.
163 **/
164 UINT8
CalculateHeaderChecksum(IN EFI_FFS_FILE_HEADER * FileHeader)165 CalculateHeaderChecksum (
166 IN EFI_FFS_FILE_HEADER *FileHeader
167 )
168 {
169 EFI_FFS_FILE_HEADER2 TestFileHeader;
170
171 if (IS_FFS_FILE2 (FileHeader)) {
172 CopyMem (&TestFileHeader, FileHeader, sizeof (EFI_FFS_FILE_HEADER2));
173 //
174 // Ingore State and File field in FFS header.
175 //
176 TestFileHeader.State = 0;
177 TestFileHeader.IntegrityCheck.Checksum.File = 0;
178
179 return CalculateSum8 ((CONST UINT8 *) &TestFileHeader, sizeof (EFI_FFS_FILE_HEADER2));
180 } else {
181 CopyMem (&TestFileHeader, FileHeader, sizeof (EFI_FFS_FILE_HEADER));
182 //
183 // Ingore State and File field in FFS header.
184 //
185 TestFileHeader.State = 0;
186 TestFileHeader.IntegrityCheck.Checksum.File = 0;
187
188 return CalculateSum8 ((CONST UINT8 *) &TestFileHeader, sizeof (EFI_FFS_FILE_HEADER));
189 }
190 }
191
192 /**
193 Find FV handler according to FileHandle in that FV.
194
195 @param FileHandle Handle of file image
196
197 @return Pointer to instance of PEI_CORE_FV_HANDLE.
198 **/
199 PEI_CORE_FV_HANDLE*
FileHandleToVolume(IN EFI_PEI_FILE_HANDLE FileHandle)200 FileHandleToVolume (
201 IN EFI_PEI_FILE_HANDLE FileHandle
202 )
203 {
204 UINTN Index;
205 PEI_CORE_INSTANCE *PrivateData;
206 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
207 UINTN BestIndex;
208
209 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
210 BestIndex = PrivateData->FvCount;
211
212 //
213 // Find the best matched FV image that includes this FileHandle.
214 // FV may include the child FV, and they are in the same continuous space.
215 // If FileHandle is from the child FV, the updated logic can find its matched FV.
216 //
217 for (Index = 0; Index < PrivateData->FvCount; Index++) {
218 FwVolHeader = PrivateData->Fv[Index].FvHeader;
219 if (((UINT64) (UINTN) FileHandle > (UINT64) (UINTN) FwVolHeader ) && \
220 ((UINT64) (UINTN) FileHandle <= ((UINT64) (UINTN) FwVolHeader + FwVolHeader->FvLength - 1))) {
221 if (BestIndex == PrivateData->FvCount) {
222 BestIndex = Index;
223 } else {
224 if ((UINT64) (UINTN) PrivateData->Fv[BestIndex].FvHeader < (UINT64) (UINTN) FwVolHeader) {
225 BestIndex = Index;
226 }
227 }
228 }
229 }
230
231 if (BestIndex < PrivateData->FvCount) {
232 return &PrivateData->Fv[BestIndex];
233 }
234
235 return NULL;
236 }
237
238 /**
239 Given the input file pointer, search for the first matching file in the
240 FFS volume as defined by SearchType. The search starts from FileHeader inside
241 the Firmware Volume defined by FwVolHeader.
242 If SearchType is EFI_FV_FILETYPE_ALL, the first FFS file will return without check its file type.
243 If SearchType is PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE,
244 the first PEIM, or COMBINED PEIM or FV file type FFS file will return.
245
246 @param FvHandle Pointer to the FV header of the volume to search
247 @param FileName File name
248 @param SearchType Filter to find only files of this type.
249 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
250 @param FileHandle This parameter must point to a valid FFS volume.
251 @param AprioriFile Pointer to AprioriFile image in this FV if has
252
253 @return EFI_NOT_FOUND No files matching the search criteria were found
254 @retval EFI_SUCCESS Success to search given file
255
256 **/
257 EFI_STATUS
FindFileEx(IN CONST EFI_PEI_FV_HANDLE FvHandle,IN CONST EFI_GUID * FileName,OPTIONAL IN EFI_FV_FILETYPE SearchType,IN OUT EFI_PEI_FILE_HANDLE * FileHandle,IN OUT EFI_PEI_FILE_HANDLE * AprioriFile OPTIONAL)258 FindFileEx (
259 IN CONST EFI_PEI_FV_HANDLE FvHandle,
260 IN CONST EFI_GUID *FileName, OPTIONAL
261 IN EFI_FV_FILETYPE SearchType,
262 IN OUT EFI_PEI_FILE_HANDLE *FileHandle,
263 IN OUT EFI_PEI_FILE_HANDLE *AprioriFile OPTIONAL
264 )
265 {
266 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
267 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader;
268 EFI_FFS_FILE_HEADER **FileHeader;
269 EFI_FFS_FILE_HEADER *FfsFileHeader;
270 UINT32 FileLength;
271 UINT32 FileOccupiedSize;
272 UINT32 FileOffset;
273 UINT64 FvLength;
274 UINT8 ErasePolarity;
275 UINT8 FileState;
276 UINT8 DataCheckSum;
277 BOOLEAN IsFfs3Fv;
278
279 //
280 // Convert the handle of FV to FV header for memory-mapped firmware volume
281 //
282 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvHandle;
283 FileHeader = (EFI_FFS_FILE_HEADER **)FileHandle;
284
285 IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);
286
287 FvLength = FwVolHeader->FvLength;
288 if ((FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) != 0) {
289 ErasePolarity = 1;
290 } else {
291 ErasePolarity = 0;
292 }
293
294 //
295 // If FileHeader is not specified (NULL) or FileName is not NULL,
296 // start with the first file in the firmware volume. Otherwise,
297 // start from the FileHeader.
298 //
299 if ((*FileHeader == NULL) || (FileName != NULL)) {
300 if (FwVolHeader->ExtHeaderOffset != 0) {
301 //
302 // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists.
303 //
304 FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINT8 *) FwVolHeader + FwVolHeader->ExtHeaderOffset);
305 FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize);
306 FfsFileHeader = (EFI_FFS_FILE_HEADER *) ALIGN_POINTER (FfsFileHeader, 8);
307 } else {
308 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *) FwVolHeader + FwVolHeader->HeaderLength);
309 }
310 } else {
311 if (IS_FFS_FILE2 (*FileHeader)) {
312 if (!IsFfs3Fv) {
313 DEBUG ((EFI_D_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &(*FileHeader)->Name));
314 }
315 FileLength = FFS_FILE2_SIZE (*FileHeader);
316 ASSERT (FileLength > 0x00FFFFFF);
317 } else {
318 FileLength = FFS_FILE_SIZE (*FileHeader);
319 }
320 //
321 // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
322 //
323 FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
324 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize);
325 }
326
327 FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader);
328 ASSERT (FileOffset <= 0xFFFFFFFF);
329
330 while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {
331 //
332 // Get FileState which is the highest bit of the State
333 //
334 FileState = GetFileState (ErasePolarity, FfsFileHeader);
335 switch (FileState) {
336
337 case EFI_FILE_HEADER_CONSTRUCTION:
338 case EFI_FILE_HEADER_INVALID:
339 if (IS_FFS_FILE2 (FfsFileHeader)) {
340 if (!IsFfs3Fv) {
341 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));
342 }
343 FileOffset += sizeof (EFI_FFS_FILE_HEADER2);
344 FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
345 } else {
346 FileOffset += sizeof (EFI_FFS_FILE_HEADER);
347 FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));
348 }
349 break;
350
351 case EFI_FILE_DATA_VALID:
352 case EFI_FILE_MARKED_FOR_UPDATE:
353 if (CalculateHeaderChecksum (FfsFileHeader) != 0) {
354 ASSERT (FALSE);
355 *FileHeader = NULL;
356 return EFI_NOT_FOUND;
357 }
358
359 if (IS_FFS_FILE2 (FfsFileHeader)) {
360 FileLength = FFS_FILE2_SIZE (FfsFileHeader);
361 ASSERT (FileLength > 0x00FFFFFF);
362 FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
363 if (!IsFfs3Fv) {
364 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));
365 FileOffset += FileOccupiedSize;
366 FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + FileOccupiedSize);
367 break;
368 }
369 } else {
370 FileLength = FFS_FILE_SIZE (FfsFileHeader);
371 FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
372 }
373
374 DataCheckSum = FFS_FIXED_CHECKSUM;
375 if ((FfsFileHeader->Attributes & FFS_ATTRIB_CHECKSUM) == FFS_ATTRIB_CHECKSUM) {
376 if (IS_FFS_FILE2 (FfsFileHeader)) {
377 DataCheckSum = CalculateCheckSum8 ((CONST UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2), FileLength - sizeof(EFI_FFS_FILE_HEADER2));
378 } else {
379 DataCheckSum = CalculateCheckSum8 ((CONST UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER), FileLength - sizeof(EFI_FFS_FILE_HEADER));
380 }
381 }
382 if (FfsFileHeader->IntegrityCheck.Checksum.File != DataCheckSum) {
383 ASSERT (FALSE);
384 *FileHeader = NULL;
385 return EFI_NOT_FOUND;
386 }
387
388 if (FileName != NULL) {
389 if (CompareGuid (&FfsFileHeader->Name, (EFI_GUID*)FileName)) {
390 *FileHeader = FfsFileHeader;
391 return EFI_SUCCESS;
392 }
393 } else if (SearchType == PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE) {
394 if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) ||
395 (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER) ||
396 (FfsFileHeader->Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE)) {
397
398 *FileHeader = FfsFileHeader;
399 return EFI_SUCCESS;
400 } else if (AprioriFile != NULL) {
401 if (FfsFileHeader->Type == EFI_FV_FILETYPE_FREEFORM) {
402 if (CompareGuid (&FfsFileHeader->Name, &gPeiAprioriFileNameGuid)) {
403 *AprioriFile = FfsFileHeader;
404 }
405 }
406 }
407 } else if (((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) &&
408 (FfsFileHeader->Type != EFI_FV_FILETYPE_FFS_PAD)) {
409 *FileHeader = FfsFileHeader;
410 return EFI_SUCCESS;
411 }
412
413 FileOffset += FileOccupiedSize;
414 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
415 break;
416
417 case EFI_FILE_DELETED:
418 if (IS_FFS_FILE2 (FfsFileHeader)) {
419 if (!IsFfs3Fv) {
420 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));
421 }
422 FileLength = FFS_FILE2_SIZE (FfsFileHeader);
423 ASSERT (FileLength > 0x00FFFFFF);
424 } else {
425 FileLength = FFS_FILE_SIZE (FfsFileHeader);
426 }
427 FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);
428 FileOffset += FileOccupiedSize;
429 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
430 break;
431
432 default:
433 *FileHeader = NULL;
434 return EFI_NOT_FOUND;
435 }
436 }
437
438 *FileHeader = NULL;
439 return EFI_NOT_FOUND;
440 }
441
442 /**
443 Initialize PeiCore Fv List.
444
445 @param PrivateData - Pointer to PEI_CORE_INSTANCE.
446 @param SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF.
447 **/
448 VOID
PeiInitializeFv(IN PEI_CORE_INSTANCE * PrivateData,IN CONST EFI_SEC_PEI_HAND_OFF * SecCoreData)449 PeiInitializeFv (
450 IN PEI_CORE_INSTANCE *PrivateData,
451 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
452 )
453 {
454 EFI_STATUS Status;
455 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
456 EFI_PEI_FV_HANDLE FvHandle;
457 EFI_FIRMWARE_VOLUME_HEADER *BfvHeader;
458
459 //
460 // Install FV_PPI for FFS2 file system.
461 //
462 PeiServicesInstallPpi (&mPeiFfs2FvPpiList);
463
464 //
465 // Install FV_PPI for FFS3 file system.
466 //
467 PeiServicesInstallPpi (&mPeiFfs3FvPpiList);
468
469 BfvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;
470
471 //
472 // The FV_PPI in BFV's format should be installed.
473 //
474 Status = PeiServicesLocatePpi (
475 &BfvHeader->FileSystemGuid,
476 0,
477 NULL,
478 (VOID**)&FvPpi
479 );
480 ASSERT_EFI_ERROR (Status);
481
482 //
483 // Get handle of BFV
484 //
485 FvPpi->ProcessVolume (
486 FvPpi,
487 SecCoreData->BootFirmwareVolumeBase,
488 (UINTN)BfvHeader->FvLength,
489 &FvHandle
490 );
491
492 //
493 // Update internal PEI_CORE_FV array.
494 //
495 PrivateData->Fv[PrivateData->FvCount].FvHeader = BfvHeader;
496 PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi;
497 PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;
498 PrivateData->Fv[PrivateData->FvCount].AuthenticationStatus = 0;
499 DEBUG ((
500 EFI_D_INFO,
501 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
502 (UINT32) PrivateData->FvCount,
503 (VOID *) BfvHeader,
504 BfvHeader->FvLength,
505 FvHandle
506 ));
507 PrivateData->FvCount ++;
508
509 //
510 // Post a call-back for the FvInfoPPI and FvInfo2PPI services to expose
511 // additional Fvs to PeiCore.
512 //
513 Status = PeiServicesNotifyPpi (mNotifyOnFvInfoList);
514 ASSERT_EFI_ERROR (Status);
515
516 }
517
518 /**
519 Process Firmware Volum Information once FvInfoPPI or FvInfo2PPI install.
520 The FV Info will be registered into PeiCore private data structure.
521 And search the inside FV image, if found, the new FV INFO(2) PPI will be installed.
522
523 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
524 @param NotifyDescriptor Address of the notification descriptor data structure.
525 @param Ppi Address of the PPI that was installed.
526
527 @retval EFI_SUCCESS The FV Info is registered into PeiCore private data structure.
528 @return if not EFI_SUCESS, fail to verify FV.
529
530 **/
531 EFI_STATUS
532 EFIAPI
FirmwareVolmeInfoPpiNotifyCallback(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_NOTIFY_DESCRIPTOR * NotifyDescriptor,IN VOID * Ppi)533 FirmwareVolmeInfoPpiNotifyCallback (
534 IN EFI_PEI_SERVICES **PeiServices,
535 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
536 IN VOID *Ppi
537 )
538 {
539 EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI FvInfo2Ppi;
540 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
541 PEI_CORE_INSTANCE *PrivateData;
542 EFI_STATUS Status;
543 EFI_PEI_FV_HANDLE FvHandle;
544 UINTN FvIndex;
545 EFI_PEI_FILE_HANDLE FileHandle;
546 VOID *DepexData;
547 BOOLEAN IsFvInfo2;
548 UINTN CurFvCount;
549
550 Status = EFI_SUCCESS;
551 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
552
553 if (CompareGuid (NotifyDescriptor->Guid, &gEfiPeiFirmwareVolumeInfo2PpiGuid)) {
554 //
555 // It is FvInfo2PPI.
556 //
557 CopyMem (&FvInfo2Ppi, Ppi, sizeof (EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI));
558 IsFvInfo2 = TRUE;
559 } else {
560 //
561 // It is FvInfoPPI.
562 //
563 CopyMem (&FvInfo2Ppi, Ppi, sizeof (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI));
564 FvInfo2Ppi.AuthenticationStatus = 0;
565 IsFvInfo2 = FALSE;
566 }
567
568 if (CompareGuid (&FvInfo2Ppi.FvFormat, &gEfiFirmwareFileSystem2Guid)) {
569 //
570 // gEfiFirmwareFileSystem2Guid is specified for FvFormat, then here to check the
571 // FileSystemGuid pointed by FvInfo against gEfiFirmwareFileSystem2Guid to make sure
572 // FvInfo has the firmware file system 2 format.
573 //
574 // If the ASSERT really appears, FvFormat needs to be specified correctly, for example,
575 // gEfiFirmwareFileSystem3Guid can be used for firmware file system 3 format, or
576 // ((EFI_FIRMWARE_VOLUME_HEADER *) FvInfo)->FileSystemGuid can be just used for both
577 // firmware file system 2 and 3 format.
578 //
579 ASSERT (CompareGuid (&(((EFI_FIRMWARE_VOLUME_HEADER *) FvInfo2Ppi.FvInfo)->FileSystemGuid), &gEfiFirmwareFileSystem2Guid));
580 }
581
582 //
583 // Locate the corresponding FV_PPI according to founded FV's format guid
584 //
585 Status = PeiServicesLocatePpi (
586 &FvInfo2Ppi.FvFormat,
587 0,
588 NULL,
589 (VOID**)&FvPpi
590 );
591 if (!EFI_ERROR (Status)) {
592 //
593 // Process new found FV and get FV handle.
594 //
595 Status = FvPpi->ProcessVolume (FvPpi, FvInfo2Ppi.FvInfo, FvInfo2Ppi.FvInfoSize, &FvHandle);
596 if (EFI_ERROR (Status)) {
597 DEBUG ((EFI_D_ERROR, "Fail to process new found FV, FV may be corrupted!\n"));
598 return Status;
599 }
600
601 //
602 // Check whether the FV has already been processed.
603 //
604 for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {
605 if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {
606 if (IsFvInfo2 && (FvInfo2Ppi.AuthenticationStatus != PrivateData->Fv[FvIndex].AuthenticationStatus)) {
607 PrivateData->Fv[FvIndex].AuthenticationStatus = FvInfo2Ppi.AuthenticationStatus;
608 DEBUG ((EFI_D_INFO, "Update AuthenticationStatus of the %dth FV to 0x%x!\n", FvIndex, FvInfo2Ppi.AuthenticationStatus));
609 }
610 DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvInfo2Ppi.FvInfo));
611 return EFI_SUCCESS;
612 }
613 }
614
615 if (PrivateData->FvCount >= PcdGet32 (PcdPeiCoreMaxFvSupported)) {
616 DEBUG ((EFI_D_ERROR, "The number of Fv Images (%d) exceed the max supported FVs (%d) in Pei", PrivateData->FvCount + 1, PcdGet32 (PcdPeiCoreMaxFvSupported)));
617 DEBUG ((EFI_D_ERROR, "PcdPeiCoreMaxFvSupported value need be reconfigurated in DSC"));
618 ASSERT (FALSE);
619 }
620
621 //
622 // Update internal PEI_CORE_FV array.
623 //
624 PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) FvInfo2Ppi.FvInfo;
625 PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi;
626 PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;
627 PrivateData->Fv[PrivateData->FvCount].AuthenticationStatus = FvInfo2Ppi.AuthenticationStatus;
628 CurFvCount = PrivateData->FvCount;
629 DEBUG ((
630 EFI_D_INFO,
631 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
632 (UINT32) CurFvCount,
633 (VOID *) FvInfo2Ppi.FvInfo,
634 FvInfo2Ppi.FvInfoSize,
635 FvHandle
636 ));
637 PrivateData->FvCount ++;
638
639 //
640 // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
641 //
642 FileHandle = NULL;
643 do {
644 Status = FvPpi->FindFileByType (
645 FvPpi,
646 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
647 FvHandle,
648 &FileHandle
649 );
650 if (!EFI_ERROR (Status)) {
651 Status = FvPpi->FindSectionByType (
652 FvPpi,
653 EFI_SECTION_PEI_DEPEX,
654 FileHandle,
655 (VOID**)&DepexData
656 );
657 if (!EFI_ERROR (Status)) {
658 if (!PeimDispatchReadiness (PeiServices, DepexData)) {
659 //
660 // Dependency is not satisfied.
661 //
662 continue;
663 }
664 }
665
666 DEBUG ((EFI_D_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, CurFvCount, FvHandle));
667 ProcessFvFile (PrivateData, &PrivateData->Fv[CurFvCount], FileHandle);
668 }
669 } while (FileHandle != NULL);
670 } else {
671 DEBUG ((EFI_D_ERROR, "Fail to process FV %p because no corresponding EFI_FIRMWARE_VOLUME_PPI is found!\n", FvInfo2Ppi.FvInfo));
672
673 AddUnknownFormatFvInfo (PrivateData, &FvInfo2Ppi);
674 }
675
676 return EFI_SUCCESS;
677 }
678
679 /**
680 Verify the Guided Section GUID by checking if there is the Guided Section GUID HOB recorded the GUID itself.
681
682 @param GuidedSectionGuid The Guided Section GUID.
683 @param GuidedSectionExtraction A pointer to the pointer to the supported Guided Section Extraction Ppi
684 for the Guided Section.
685
686 @return TRUE The GuidedSectionGuid could be identified, and the pointer to
687 the Guided Section Extraction Ppi will be returned to *GuidedSectionExtraction.
688 @return FALSE The GuidedSectionGuid could not be identified, or
689 the Guided Section Extraction Ppi has not been installed yet.
690
691 **/
692 BOOLEAN
VerifyGuidedSectionGuid(IN EFI_GUID * GuidedSectionGuid,OUT EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI ** GuidedSectionExtraction)693 VerifyGuidedSectionGuid (
694 IN EFI_GUID *GuidedSectionGuid,
695 OUT EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI **GuidedSectionExtraction
696 )
697 {
698 EFI_PEI_HOB_POINTERS Hob;
699 EFI_GUID *GuidRecorded;
700 VOID *Interface;
701 EFI_STATUS Status;
702
703 //
704 // Check if there is the Guided Section GUID HOB recorded the GUID itself.
705 //
706 Hob.Raw = GetFirstGuidHob (GuidedSectionGuid);
707 if (Hob.Raw != NULL) {
708 GuidRecorded = (EFI_GUID *) GET_GUID_HOB_DATA (Hob);
709 if (CompareGuid (GuidRecorded, GuidedSectionGuid)) {
710 //
711 // Found the recorded GuidedSectionGuid.
712 //
713 Status = PeiServicesLocatePpi (GuidedSectionGuid, 0, NULL, (VOID **) &Interface);
714 if (!EFI_ERROR (Status) && Interface != NULL) {
715 //
716 // Found the supported Guided Section Extraction Ppi for the Guided Section.
717 //
718 *GuidedSectionExtraction = (EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *) Interface;
719 return TRUE;
720 }
721 return FALSE;
722 }
723 }
724
725 return FALSE;
726 }
727
728 /**
729 Go through the file to search SectionType section.
730 Search within encapsulation sections (compression and GUIDed) recursively,
731 until the match section is found.
732
733 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
734 @param SectionType Filter to find only section of this type.
735 @param SectionInstance Pointer to the filter to find the specific instance of section.
736 @param Section From where to search.
737 @param SectionSize The file size to search.
738 @param OutputBuffer A pointer to the discovered section, if successful.
739 NULL if section not found
740 @param AuthenticationStatus Updated upon return to point to the authentication status for this section.
741 @param IsFfs3Fv Indicates the FV format.
742
743 @return EFI_NOT_FOUND The match section is not found.
744 @return EFI_SUCCESS The match section is found.
745
746 **/
747 EFI_STATUS
ProcessSection(IN CONST EFI_PEI_SERVICES ** PeiServices,IN EFI_SECTION_TYPE SectionType,IN OUT UINTN * SectionInstance,IN EFI_COMMON_SECTION_HEADER * Section,IN UINTN SectionSize,OUT VOID ** OutputBuffer,OUT UINT32 * AuthenticationStatus,IN BOOLEAN IsFfs3Fv)748 ProcessSection (
749 IN CONST EFI_PEI_SERVICES **PeiServices,
750 IN EFI_SECTION_TYPE SectionType,
751 IN OUT UINTN *SectionInstance,
752 IN EFI_COMMON_SECTION_HEADER *Section,
753 IN UINTN SectionSize,
754 OUT VOID **OutputBuffer,
755 OUT UINT32 *AuthenticationStatus,
756 IN BOOLEAN IsFfs3Fv
757 )
758 {
759 EFI_STATUS Status;
760 UINT32 SectionLength;
761 UINT32 ParsedLength;
762 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *GuidSectionPpi;
763 EFI_PEI_DECOMPRESS_PPI *DecompressPpi;
764 VOID *PpiOutput;
765 UINTN PpiOutputSize;
766 UINTN Index;
767 UINT32 Authentication;
768 PEI_CORE_INSTANCE *PrivateData;
769 EFI_GUID *SectionDefinitionGuid;
770 BOOLEAN SectionCached;
771 VOID *TempOutputBuffer;
772 UINT32 TempAuthenticationStatus;
773 UINT16 GuidedSectionAttributes;
774
775 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
776 *OutputBuffer = NULL;
777 ParsedLength = 0;
778 Index = 0;
779 Status = EFI_NOT_FOUND;
780 PpiOutput = NULL;
781 PpiOutputSize = 0;
782 while (ParsedLength < SectionSize) {
783
784 if (IS_SECTION2 (Section)) {
785 ASSERT (SECTION2_SIZE (Section) > 0x00FFFFFF);
786 if (!IsFfs3Fv) {
787 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted section in a non-FFS3 formatted FV.\n"));
788 SectionLength = SECTION2_SIZE (Section);
789 //
790 // SectionLength is adjusted it is 4 byte aligned.
791 // Go to the next section
792 //
793 SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
794 ASSERT (SectionLength != 0);
795 ParsedLength += SectionLength;
796 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + SectionLength);
797 continue;
798 }
799 }
800
801 if (Section->Type == SectionType) {
802 //
803 // The type matches, so check the instance count to see if it's the one we want.
804 //
805 (*SectionInstance)--;
806 if (*SectionInstance == 0) {
807 //
808 // Got it!
809 //
810 if (IS_SECTION2 (Section)) {
811 *OutputBuffer = (VOID *)((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2));
812 } else {
813 *OutputBuffer = (VOID *)((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER));
814 }
815 return EFI_SUCCESS;
816 } else {
817 if (IS_SECTION2 (Section)) {
818 SectionLength = SECTION2_SIZE (Section);
819 } else {
820 SectionLength = SECTION_SIZE (Section);
821 }
822 //
823 // SectionLength is adjusted it is 4 byte aligned.
824 // Go to the next section
825 //
826 SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
827 ASSERT (SectionLength != 0);
828 ParsedLength += SectionLength;
829 Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
830 continue;
831 }
832 } else if ((Section->Type == EFI_SECTION_GUID_DEFINED) || (Section->Type == EFI_SECTION_COMPRESSION)) {
833 //
834 // Check the encapsulated section is extracted into the cache data.
835 //
836 SectionCached = FALSE;
837 for (Index = 0; Index < PrivateData->CacheSection.AllSectionCount; Index ++) {
838 if (Section == PrivateData->CacheSection.Section[Index]) {
839 SectionCached = TRUE;
840 PpiOutput = PrivateData->CacheSection.SectionData[Index];
841 PpiOutputSize = PrivateData->CacheSection.SectionSize[Index];
842 Authentication = PrivateData->CacheSection.AuthenticationStatus[Index];
843 //
844 // Search section directly from the cache data.
845 //
846 TempAuthenticationStatus = 0;
847 Status = ProcessSection (
848 PeiServices,
849 SectionType,
850 SectionInstance,
851 PpiOutput,
852 PpiOutputSize,
853 &TempOutputBuffer,
854 &TempAuthenticationStatus,
855 IsFfs3Fv
856 );
857 if (!EFI_ERROR (Status)) {
858 *OutputBuffer = TempOutputBuffer;
859 *AuthenticationStatus = TempAuthenticationStatus | Authentication;
860 return EFI_SUCCESS;
861 }
862 }
863 }
864
865 //
866 // If SectionCached is TRUE, the section data has been cached and scanned.
867 //
868 if (!SectionCached) {
869 Status = EFI_NOT_FOUND;
870 Authentication = 0;
871 if (Section->Type == EFI_SECTION_GUID_DEFINED) {
872 if (IS_SECTION2 (Section)) {
873 SectionDefinitionGuid = &((EFI_GUID_DEFINED_SECTION2 *)Section)->SectionDefinitionGuid;
874 GuidedSectionAttributes = ((EFI_GUID_DEFINED_SECTION2 *)Section)->Attributes;
875 } else {
876 SectionDefinitionGuid = &((EFI_GUID_DEFINED_SECTION *)Section)->SectionDefinitionGuid;
877 GuidedSectionAttributes = ((EFI_GUID_DEFINED_SECTION *)Section)->Attributes;
878 }
879 if (VerifyGuidedSectionGuid (SectionDefinitionGuid, &GuidSectionPpi)) {
880 Status = GuidSectionPpi->ExtractSection (
881 GuidSectionPpi,
882 Section,
883 &PpiOutput,
884 &PpiOutputSize,
885 &Authentication
886 );
887 } else if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {
888 //
889 // Figure out the proper authentication status for GUIDED section without processing required
890 //
891 Status = EFI_SUCCESS;
892 if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) == EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {
893 Authentication |= EFI_AUTH_STATUS_IMAGE_SIGNED | EFI_AUTH_STATUS_NOT_TESTED;
894 }
895 if (IS_SECTION2 (Section)) {
896 PpiOutputSize = SECTION2_SIZE (Section) - ((EFI_GUID_DEFINED_SECTION2 *) Section)->DataOffset;
897 PpiOutput = (UINT8 *) Section + ((EFI_GUID_DEFINED_SECTION2 *) Section)->DataOffset;
898 } else {
899 PpiOutputSize = SECTION_SIZE (Section) - ((EFI_GUID_DEFINED_SECTION *) Section)->DataOffset;
900 PpiOutput = (UINT8 *) Section + ((EFI_GUID_DEFINED_SECTION *) Section)->DataOffset;
901 }
902 }
903 } else if (Section->Type == EFI_SECTION_COMPRESSION) {
904 Status = PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid, 0, NULL, (VOID **) &DecompressPpi);
905 if (!EFI_ERROR (Status)) {
906 Status = DecompressPpi->Decompress (
907 DecompressPpi,
908 (CONST EFI_COMPRESSION_SECTION*) Section,
909 &PpiOutput,
910 &PpiOutputSize
911 );
912 }
913 }
914
915 if (!EFI_ERROR (Status)) {
916 //
917 // Update cache section data.
918 //
919 if (PrivateData->CacheSection.AllSectionCount < CACHE_SETION_MAX_NUMBER) {
920 PrivateData->CacheSection.AllSectionCount ++;
921 }
922 PrivateData->CacheSection.Section [PrivateData->CacheSection.SectionIndex] = Section;
923 PrivateData->CacheSection.SectionData [PrivateData->CacheSection.SectionIndex] = PpiOutput;
924 PrivateData->CacheSection.SectionSize [PrivateData->CacheSection.SectionIndex] = PpiOutputSize;
925 PrivateData->CacheSection.AuthenticationStatus [PrivateData->CacheSection.SectionIndex] = Authentication;
926 PrivateData->CacheSection.SectionIndex = (PrivateData->CacheSection.SectionIndex + 1)%CACHE_SETION_MAX_NUMBER;
927
928 TempAuthenticationStatus = 0;
929 Status = ProcessSection (
930 PeiServices,
931 SectionType,
932 SectionInstance,
933 PpiOutput,
934 PpiOutputSize,
935 &TempOutputBuffer,
936 &TempAuthenticationStatus,
937 IsFfs3Fv
938 );
939 if (!EFI_ERROR (Status)) {
940 *OutputBuffer = TempOutputBuffer;
941 *AuthenticationStatus = TempAuthenticationStatus | Authentication;
942 return EFI_SUCCESS;
943 }
944 }
945 }
946 }
947
948 if (IS_SECTION2 (Section)) {
949 SectionLength = SECTION2_SIZE (Section);
950 } else {
951 SectionLength = SECTION_SIZE (Section);
952 }
953 //
954 // SectionLength is adjusted it is 4 byte aligned.
955 // Go to the next section
956 //
957 SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
958 ASSERT (SectionLength != 0);
959 ParsedLength += SectionLength;
960 Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
961 }
962
963 return EFI_NOT_FOUND;
964 }
965
966
967 /**
968 Searches for the next matching section within the specified file.
969
970 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
971 @param SectionType Filter to find only sections of this type.
972 @param FileHandle Pointer to the current file to search.
973 @param SectionData A pointer to the discovered section, if successful.
974 NULL if section not found
975
976 @retval EFI_NOT_FOUND The section was not found.
977 @retval EFI_SUCCESS The section was found.
978
979 **/
980 EFI_STATUS
981 EFIAPI
PeiFfsFindSectionData(IN CONST EFI_PEI_SERVICES ** PeiServices,IN EFI_SECTION_TYPE SectionType,IN EFI_PEI_FILE_HANDLE FileHandle,OUT VOID ** SectionData)982 PeiFfsFindSectionData (
983 IN CONST EFI_PEI_SERVICES **PeiServices,
984 IN EFI_SECTION_TYPE SectionType,
985 IN EFI_PEI_FILE_HANDLE FileHandle,
986 OUT VOID **SectionData
987 )
988 {
989 PEI_CORE_FV_HANDLE *CoreFvHandle;
990
991 CoreFvHandle = FileHandleToVolume (FileHandle);
992 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
993 return EFI_NOT_FOUND;
994 }
995
996 return CoreFvHandle->FvPpi->FindSectionByType (CoreFvHandle->FvPpi, SectionType, FileHandle, SectionData);
997 }
998
999 /**
1000 Searches for the next matching section within the specified file.
1001
1002 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
1003 @param SectionType The value of the section type to find.
1004 @param SectionInstance Section instance to find.
1005 @param FileHandle Handle of the firmware file to search.
1006 @param SectionData A pointer to the discovered section, if successful.
1007 @param AuthenticationStatus A pointer to the authentication status for this section.
1008
1009 @retval EFI_SUCCESS The section was found.
1010 @retval EFI_NOT_FOUND The section was not found.
1011
1012 **/
1013 EFI_STATUS
1014 EFIAPI
PeiFfsFindSectionData3(IN CONST EFI_PEI_SERVICES ** PeiServices,IN EFI_SECTION_TYPE SectionType,IN UINTN SectionInstance,IN EFI_PEI_FILE_HANDLE FileHandle,OUT VOID ** SectionData,OUT UINT32 * AuthenticationStatus)1015 PeiFfsFindSectionData3 (
1016 IN CONST EFI_PEI_SERVICES **PeiServices,
1017 IN EFI_SECTION_TYPE SectionType,
1018 IN UINTN SectionInstance,
1019 IN EFI_PEI_FILE_HANDLE FileHandle,
1020 OUT VOID **SectionData,
1021 OUT UINT32 *AuthenticationStatus
1022 )
1023 {
1024 PEI_CORE_FV_HANDLE *CoreFvHandle;
1025
1026 CoreFvHandle = FileHandleToVolume (FileHandle);
1027 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
1028 return EFI_NOT_FOUND;
1029 }
1030
1031 if ((CoreFvHandle->FvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) &&
1032 (CoreFvHandle->FvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION)) {
1033 return CoreFvHandle->FvPpi->FindSectionByType2 (CoreFvHandle->FvPpi, SectionType, SectionInstance, FileHandle, SectionData, AuthenticationStatus);
1034 }
1035 //
1036 // The old FvPpi doesn't support to find section by section instance
1037 // and return authentication status, so return EFI_UNSUPPORTED.
1038 //
1039 return EFI_UNSUPPORTED;
1040 }
1041
1042 /**
1043 Searches for the next matching file in the firmware volume.
1044
1045 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
1046 @param SearchType Filter to find only files of this type.
1047 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
1048 @param FvHandle Handle of firmware volume in which to search.
1049 @param FileHandle On entry, points to the current handle from which to begin searching or NULL to start
1050 at the beginning of the firmware volume. On exit, points the file handle of the next file
1051 in the volume or NULL if there are no more files.
1052
1053 @retval EFI_NOT_FOUND The file was not found.
1054 @retval EFI_NOT_FOUND The header checksum was not zero.
1055 @retval EFI_SUCCESS The file was found.
1056
1057 **/
1058 EFI_STATUS
1059 EFIAPI
PeiFfsFindNextFile(IN CONST EFI_PEI_SERVICES ** PeiServices,IN UINT8 SearchType,IN EFI_PEI_FV_HANDLE FvHandle,IN OUT EFI_PEI_FILE_HANDLE * FileHandle)1060 PeiFfsFindNextFile (
1061 IN CONST EFI_PEI_SERVICES **PeiServices,
1062 IN UINT8 SearchType,
1063 IN EFI_PEI_FV_HANDLE FvHandle,
1064 IN OUT EFI_PEI_FILE_HANDLE *FileHandle
1065 )
1066 {
1067 PEI_CORE_FV_HANDLE *CoreFvHandle;
1068
1069 CoreFvHandle = FvHandleToCoreHandle (FvHandle);
1070
1071 //
1072 // To make backward compatiblity, if can not find corresponding the handle of FV
1073 // then treat FV as build-in FFS2/FFS3 format and memory mapped FV that FV handle is pointed
1074 // to the address of first byte of FV.
1075 //
1076 if ((CoreFvHandle == NULL) && FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
1077 return FindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL);
1078 }
1079
1080 if ((CoreFvHandle == NULL) || CoreFvHandle->FvPpi == NULL) {
1081 return EFI_NOT_FOUND;
1082 }
1083
1084 return CoreFvHandle->FvPpi->FindFileByType (CoreFvHandle->FvPpi, SearchType, FvHandle, FileHandle);
1085 }
1086
1087
1088 /**
1089 Search the firmware volumes by index
1090
1091 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
1092 @param Instance This instance of the firmware volume to find. The value 0 is the Boot Firmware
1093 Volume (BFV).
1094 @param VolumeHandle On exit, points to the next volume handle or NULL if it does not exist.
1095
1096 @retval EFI_INVALID_PARAMETER VolumeHandle is NULL
1097 @retval EFI_NOT_FOUND The volume was not found.
1098 @retval EFI_SUCCESS The volume was found.
1099
1100 **/
1101 EFI_STATUS
1102 EFIAPI
PeiFfsFindNextVolume(IN CONST EFI_PEI_SERVICES ** PeiServices,IN UINTN Instance,IN OUT EFI_PEI_FV_HANDLE * VolumeHandle)1103 PeiFfsFindNextVolume (
1104 IN CONST EFI_PEI_SERVICES **PeiServices,
1105 IN UINTN Instance,
1106 IN OUT EFI_PEI_FV_HANDLE *VolumeHandle
1107 )
1108 {
1109 PEI_CORE_INSTANCE *Private;
1110 PEI_CORE_FV_HANDLE *CoreFvHandle;
1111
1112 if (VolumeHandle == NULL) {
1113 return EFI_INVALID_PARAMETER;
1114 }
1115
1116 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
1117
1118 CoreFvHandle = FindNextCoreFvHandle (Private, Instance);
1119 if (CoreFvHandle == NULL) {
1120 *VolumeHandle = NULL;
1121 return EFI_NOT_FOUND;
1122 }
1123
1124 *VolumeHandle = CoreFvHandle->FvHandle;
1125
1126 return EFI_SUCCESS;
1127 }
1128
1129
1130 /**
1131 Find a file within a volume by its name.
1132
1133 @param FileName A pointer to the name of the file to find within the firmware volume.
1134 @param VolumeHandle The firmware volume to search
1135 @param FileHandle Upon exit, points to the found file's handle
1136 or NULL if it could not be found.
1137
1138 @retval EFI_SUCCESS File was found.
1139 @retval EFI_NOT_FOUND File was not found.
1140 @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or FileName was NULL.
1141
1142 **/
1143 EFI_STATUS
1144 EFIAPI
PeiFfsFindFileByName(IN CONST EFI_GUID * FileName,IN EFI_PEI_FV_HANDLE VolumeHandle,OUT EFI_PEI_FILE_HANDLE * FileHandle)1145 PeiFfsFindFileByName (
1146 IN CONST EFI_GUID *FileName,
1147 IN EFI_PEI_FV_HANDLE VolumeHandle,
1148 OUT EFI_PEI_FILE_HANDLE *FileHandle
1149 )
1150 {
1151 PEI_CORE_FV_HANDLE *CoreFvHandle;
1152
1153 if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {
1154 return EFI_INVALID_PARAMETER;
1155 }
1156
1157 CoreFvHandle = FvHandleToCoreHandle (VolumeHandle);
1158 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
1159 return EFI_NOT_FOUND;
1160 }
1161
1162 return CoreFvHandle->FvPpi->FindFileByName (CoreFvHandle->FvPpi, FileName, &VolumeHandle, FileHandle);
1163 }
1164
1165 /**
1166 Returns information about a specific file.
1167
1168 @param FileHandle Handle of the file.
1169 @param FileInfo Upon exit, points to the file's information.
1170
1171 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
1172 @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file.
1173 @retval EFI_SUCCESS File information returned.
1174
1175 **/
1176 EFI_STATUS
1177 EFIAPI
PeiFfsGetFileInfo(IN EFI_PEI_FILE_HANDLE FileHandle,OUT EFI_FV_FILE_INFO * FileInfo)1178 PeiFfsGetFileInfo (
1179 IN EFI_PEI_FILE_HANDLE FileHandle,
1180 OUT EFI_FV_FILE_INFO *FileInfo
1181 )
1182 {
1183 PEI_CORE_FV_HANDLE *CoreFvHandle;
1184
1185 if ((FileHandle == NULL) || (FileInfo == NULL)) {
1186 return EFI_INVALID_PARAMETER;
1187 }
1188
1189 //
1190 // Retrieve the FirmwareVolume which the file resides in.
1191 //
1192 CoreFvHandle = FileHandleToVolume (FileHandle);
1193 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
1194 return EFI_INVALID_PARAMETER;
1195 }
1196
1197 return CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, FileHandle, FileInfo);
1198 }
1199
1200 /**
1201 Returns information about a specific file.
1202
1203 @param FileHandle Handle of the file.
1204 @param FileInfo Upon exit, points to the file's information.
1205
1206 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
1207 @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file.
1208 @retval EFI_SUCCESS File information returned.
1209
1210 **/
1211 EFI_STATUS
1212 EFIAPI
PeiFfsGetFileInfo2(IN EFI_PEI_FILE_HANDLE FileHandle,OUT EFI_FV_FILE_INFO2 * FileInfo)1213 PeiFfsGetFileInfo2 (
1214 IN EFI_PEI_FILE_HANDLE FileHandle,
1215 OUT EFI_FV_FILE_INFO2 *FileInfo
1216 )
1217 {
1218 PEI_CORE_FV_HANDLE *CoreFvHandle;
1219
1220 if ((FileHandle == NULL) || (FileInfo == NULL)) {
1221 return EFI_INVALID_PARAMETER;
1222 }
1223
1224 //
1225 // Retrieve the FirmwareVolume which the file resides in.
1226 //
1227 CoreFvHandle = FileHandleToVolume (FileHandle);
1228 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
1229 return EFI_INVALID_PARAMETER;
1230 }
1231
1232 if ((CoreFvHandle->FvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) &&
1233 (CoreFvHandle->FvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION)) {
1234 return CoreFvHandle->FvPpi->GetFileInfo2 (CoreFvHandle->FvPpi, FileHandle, FileInfo);
1235 }
1236 //
1237 // The old FvPpi doesn't support to return file info with authentication status,
1238 // so return EFI_UNSUPPORTED.
1239 //
1240 return EFI_UNSUPPORTED;
1241 }
1242
1243 /**
1244 Returns information about the specified volume.
1245
1246 This function returns information about a specific firmware
1247 volume, including its name, type, attributes, starting address
1248 and size.
1249
1250 @param VolumeHandle Handle of the volume.
1251 @param VolumeInfo Upon exit, points to the volume's information.
1252
1253 @retval EFI_SUCCESS Volume information returned.
1254 @retval EFI_INVALID_PARAMETER If VolumeHandle does not represent a valid volume.
1255 @retval EFI_INVALID_PARAMETER If VolumeHandle is NULL.
1256 @retval EFI_SUCCESS Information successfully returned.
1257 @retval EFI_INVALID_PARAMETER The volume designated by the VolumeHandle is not available.
1258
1259 **/
1260 EFI_STATUS
1261 EFIAPI
PeiFfsGetVolumeInfo(IN EFI_PEI_FV_HANDLE VolumeHandle,OUT EFI_FV_INFO * VolumeInfo)1262 PeiFfsGetVolumeInfo (
1263 IN EFI_PEI_FV_HANDLE VolumeHandle,
1264 OUT EFI_FV_INFO *VolumeInfo
1265 )
1266 {
1267 PEI_CORE_FV_HANDLE *CoreHandle;
1268
1269 if ((VolumeInfo == NULL) || (VolumeHandle == NULL)) {
1270 return EFI_INVALID_PARAMETER;
1271 }
1272
1273 CoreHandle = FvHandleToCoreHandle (VolumeHandle);
1274
1275 if ((CoreHandle == NULL) || (CoreHandle->FvPpi == NULL)) {
1276 return EFI_INVALID_PARAMETER;
1277 }
1278
1279 return CoreHandle->FvPpi->GetVolumeInfo (CoreHandle->FvPpi, VolumeHandle, VolumeInfo);
1280 }
1281
1282 /**
1283 Get Fv image from the FV type file, then install FV INFO(2) ppi, Build FV hob.
1284
1285 @param PrivateData PeiCore's private data structure
1286 @param ParentFvCoreHandle Pointer of EFI_CORE_FV_HANDLE to parent Fv image that contain this Fv image.
1287 @param ParentFvFileHandle File handle of a Fv type file that contain this Fv image.
1288
1289 @retval EFI_NOT_FOUND FV image can't be found.
1290 @retval EFI_SUCCESS Successfully to process it.
1291 @retval EFI_OUT_OF_RESOURCES Can not allocate page when aligning FV image
1292 @retval EFI_SECURITY_VIOLATION Image is illegal
1293 @retval Others Can not find EFI_SECTION_FIRMWARE_VOLUME_IMAGE section
1294
1295 **/
1296 EFI_STATUS
ProcessFvFile(IN PEI_CORE_INSTANCE * PrivateData,IN PEI_CORE_FV_HANDLE * ParentFvCoreHandle,IN EFI_PEI_FILE_HANDLE ParentFvFileHandle)1297 ProcessFvFile (
1298 IN PEI_CORE_INSTANCE *PrivateData,
1299 IN PEI_CORE_FV_HANDLE *ParentFvCoreHandle,
1300 IN EFI_PEI_FILE_HANDLE ParentFvFileHandle
1301 )
1302 {
1303 EFI_STATUS Status;
1304 EFI_FV_INFO ParentFvImageInfo;
1305 UINT32 FvAlignment;
1306 VOID *NewFvBuffer;
1307 EFI_PEI_HOB_POINTERS HobPtr;
1308 EFI_PEI_FIRMWARE_VOLUME_PPI *ParentFvPpi;
1309 EFI_PEI_FV_HANDLE ParentFvHandle;
1310 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
1311 EFI_FV_FILE_INFO FileInfo;
1312 UINT64 FvLength;
1313 UINT32 AuthenticationStatus;
1314
1315 //
1316 // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
1317 // been extracted.
1318 //
1319 HobPtr.Raw = GetHobList ();
1320 while ((HobPtr.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobPtr.Raw)) != NULL) {
1321 if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)ParentFvFileHandle)->Name), &HobPtr.FirmwareVolume2->FileName)) {
1322 //
1323 // this FILE has been dispatched, it will not be dispatched again.
1324 //
1325 DEBUG ((EFI_D_INFO, "FV file %p has been dispatched!\r\n", ParentFvFileHandle));
1326 return EFI_SUCCESS;
1327 }
1328 HobPtr.Raw = GET_NEXT_HOB (HobPtr);
1329 }
1330
1331 ParentFvHandle = ParentFvCoreHandle->FvHandle;
1332 ParentFvPpi = ParentFvCoreHandle->FvPpi;
1333
1334 //
1335 // Find FvImage in FvFile
1336 //
1337 AuthenticationStatus = 0;
1338 if ((ParentFvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) &&
1339 (ParentFvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION)) {
1340 Status = ParentFvPpi->FindSectionByType2 (
1341 ParentFvPpi,
1342 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
1343 0,
1344 ParentFvFileHandle,
1345 (VOID **)&FvHeader,
1346 &AuthenticationStatus
1347 );
1348 } else {
1349 Status = ParentFvPpi->FindSectionByType (
1350 ParentFvPpi,
1351 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
1352 ParentFvFileHandle,
1353 (VOID **)&FvHeader
1354 );
1355 }
1356 if (EFI_ERROR (Status)) {
1357 return Status;
1358 }
1359
1360 Status = VerifyPeim (PrivateData, ParentFvHandle, ParentFvFileHandle, AuthenticationStatus);
1361 if (Status == EFI_SECURITY_VIOLATION) {
1362 return Status;
1363 }
1364
1365 //
1366 // If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume
1367 // can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from
1368 // its initial linked location and maintain its alignment.
1369 //
1370 if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) {
1371 //
1372 // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.
1373 //
1374 FvAlignment = 1 << ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ALIGNMENT) >> 16);
1375 if (FvAlignment < 8) {
1376 FvAlignment = 8;
1377 }
1378
1379 //
1380 // Check FvImage
1381 //
1382 if ((UINTN) FvHeader % FvAlignment != 0) {
1383 FvLength = ReadUnaligned64 (&FvHeader->FvLength);
1384 NewFvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvLength), FvAlignment);
1385 if (NewFvBuffer == NULL) {
1386 return EFI_OUT_OF_RESOURCES;
1387 }
1388 CopyMem (NewFvBuffer, FvHeader, (UINTN) FvLength);
1389 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) NewFvBuffer;
1390 }
1391 }
1392
1393 Status = ParentFvPpi->GetVolumeInfo (ParentFvPpi, ParentFvHandle, &ParentFvImageInfo);
1394 ASSERT_EFI_ERROR (Status);
1395
1396 Status = ParentFvPpi->GetFileInfo (ParentFvPpi, ParentFvFileHandle, &FileInfo);
1397 ASSERT_EFI_ERROR (Status);
1398
1399 //
1400 // Install FvInfo(2) Ppi
1401 // NOTE: FvInfo2 must be installed before FvInfo so that recursive processing of encapsulated
1402 // FVs inherit the proper AuthenticationStatus.
1403 //
1404 PeiServicesInstallFvInfo2Ppi(
1405 &FvHeader->FileSystemGuid,
1406 (VOID**)FvHeader,
1407 (UINT32)FvHeader->FvLength,
1408 &ParentFvImageInfo.FvName,
1409 &FileInfo.FileName,
1410 AuthenticationStatus
1411 );
1412
1413 PeiServicesInstallFvInfoPpi (
1414 &FvHeader->FileSystemGuid,
1415 (VOID**) FvHeader,
1416 (UINT32) FvHeader->FvLength,
1417 &ParentFvImageInfo.FvName,
1418 &FileInfo.FileName
1419 );
1420
1421 //
1422 // Inform the extracted FvImage to Fv HOB consumer phase, i.e. DXE phase
1423 //
1424 BuildFvHob (
1425 (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,
1426 FvHeader->FvLength
1427 );
1428
1429 //
1430 // Makes the encapsulated volume show up in DXE phase to skip processing of
1431 // encapsulated file again.
1432 //
1433 BuildFv2Hob (
1434 (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,
1435 FvHeader->FvLength,
1436 &ParentFvImageInfo.FvName,
1437 &FileInfo.FileName
1438 );
1439
1440 return EFI_SUCCESS;
1441 }
1442
1443 /**
1444 Process a firmware volume and create a volume handle.
1445
1446 Create a volume handle from the information in the buffer. For
1447 memory-mapped firmware volumes, Buffer and BufferSize refer to
1448 the start of the firmware volume and the firmware volume size.
1449 For non memory-mapped firmware volumes, this points to a
1450 buffer which contains the necessary information for creating
1451 the firmware volume handle. Normally, these values are derived
1452 from the EFI_FIRMWARE_VOLUME_INFO_PPI.
1453
1454
1455 @param This Points to this instance of the
1456 EFI_PEI_FIRMWARE_VOLUME_PPI.
1457 @param Buffer Points to the start of the buffer.
1458 @param BufferSize Size of the buffer.
1459 @param FvHandle Points to the returned firmware volume
1460 handle. The firmware volume handle must
1461 be unique within the system.
1462
1463 @retval EFI_SUCCESS Firmware volume handle created.
1464 @retval EFI_VOLUME_CORRUPTED Volume was corrupt.
1465
1466 **/
1467 EFI_STATUS
1468 EFIAPI
PeiFfsFvPpiProcessVolume(IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI * This,IN VOID * Buffer,IN UINTN BufferSize,OUT EFI_PEI_FV_HANDLE * FvHandle)1469 PeiFfsFvPpiProcessVolume (
1470 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1471 IN VOID *Buffer,
1472 IN UINTN BufferSize,
1473 OUT EFI_PEI_FV_HANDLE *FvHandle
1474 )
1475 {
1476 EFI_STATUS Status;
1477
1478 ASSERT (FvHandle != NULL);
1479
1480 if (Buffer == NULL) {
1481 return EFI_VOLUME_CORRUPTED;
1482 }
1483
1484 //
1485 // The build-in EFI_PEI_FIRMWARE_VOLUME_PPI for FFS2/FFS3 support memory-mapped
1486 // FV image and the handle is pointed to Fv image's buffer.
1487 //
1488 *FvHandle = (EFI_PEI_FV_HANDLE) Buffer;
1489
1490 //
1491 // Do verify for given FV buffer.
1492 //
1493 Status = VerifyFv ((EFI_FIRMWARE_VOLUME_HEADER*) Buffer);
1494 if (EFI_ERROR(Status)) {
1495 DEBUG ((EFI_D_ERROR, "Fail to verify FV which address is 0x%11p", Buffer));
1496 return EFI_VOLUME_CORRUPTED;
1497 }
1498
1499 return EFI_SUCCESS;
1500 }
1501
1502 /**
1503 Finds the next file of the specified type.
1504
1505 This service enables PEI modules to discover additional firmware files.
1506 The FileHandle must be unique within the system.
1507
1508 @param This Points to this instance of the
1509 EFI_PEI_FIRMWARE_VOLUME_PPI.
1510 @param SearchType A filter to find only files of this type. Type
1511 EFI_FV_FILETYPE_ALL causes no filtering to be
1512 done.
1513 @param FvHandle Handle of firmware volume in which to
1514 search.
1515 @param FileHandle Points to the current handle from which to
1516 begin searching or NULL to start at the
1517 beginning of the firmware volume. Updated
1518 upon return to reflect the file found.
1519
1520 @retval EFI_SUCCESS The file was found.
1521 @retval EFI_NOT_FOUND The file was not found. FileHandle contains NULL.
1522
1523 **/
1524 EFI_STATUS
1525 EFIAPI
PeiFfsFvPpiFindFileByType(IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI * This,IN EFI_FV_FILETYPE SearchType,IN EFI_PEI_FV_HANDLE FvHandle,IN OUT EFI_PEI_FILE_HANDLE * FileHandle)1526 PeiFfsFvPpiFindFileByType (
1527 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1528 IN EFI_FV_FILETYPE SearchType,
1529 IN EFI_PEI_FV_HANDLE FvHandle,
1530 IN OUT EFI_PEI_FILE_HANDLE *FileHandle
1531 )
1532 {
1533 return FindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL);
1534 }
1535
1536 /**
1537 Find a file within a volume by its name.
1538
1539 This service searches for files with a specific name, within
1540 either the specified firmware volume or all firmware volumes.
1541
1542 @param This Points to this instance of the
1543 EFI_PEI_FIRMWARE_VOLUME_PPI.
1544 @param FileName A pointer to the name of the file to find
1545 within the firmware volume.
1546 @param FvHandle Upon entry, the pointer to the firmware
1547 volume to search or NULL if all firmware
1548 volumes should be searched. Upon exit, the
1549 actual firmware volume in which the file was
1550 found.
1551 @param FileHandle Upon exit, points to the found file's
1552 handle or NULL if it could not be found.
1553
1554 @retval EFI_SUCCESS File was found.
1555 @retval EFI_NOT_FOUND File was not found.
1556 @retval EFI_INVALID_PARAMETER FvHandle or FileHandle or
1557 FileName was NULL.
1558
1559
1560 **/
1561 EFI_STATUS
1562 EFIAPI
PeiFfsFvPpiFindFileByName(IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI * This,IN CONST EFI_GUID * FileName,IN EFI_PEI_FV_HANDLE * FvHandle,OUT EFI_PEI_FILE_HANDLE * FileHandle)1563 PeiFfsFvPpiFindFileByName (
1564 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1565 IN CONST EFI_GUID *FileName,
1566 IN EFI_PEI_FV_HANDLE *FvHandle,
1567 OUT EFI_PEI_FILE_HANDLE *FileHandle
1568 )
1569 {
1570 EFI_STATUS Status;
1571 PEI_CORE_INSTANCE *PrivateData;
1572 UINTN Index;
1573
1574 if ((FvHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {
1575 return EFI_INVALID_PARAMETER;
1576 }
1577
1578 if (*FvHandle != NULL) {
1579 Status = FindFileEx (*FvHandle, FileName, 0, FileHandle, NULL);
1580 if (Status == EFI_NOT_FOUND) {
1581 *FileHandle = NULL;
1582 }
1583 } else {
1584 //
1585 // If *FvHandle = NULL, so search all FV for given filename
1586 //
1587 Status = EFI_NOT_FOUND;
1588
1589 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer());
1590 for (Index = 0; Index < PrivateData->FvCount; Index ++) {
1591 //
1592 // Only search the FV which is associated with a EFI_PEI_FIRMWARE_VOLUME_PPI instance.
1593 //
1594 if (PrivateData->Fv[Index].FvPpi != NULL) {
1595 Status = FindFileEx (PrivateData->Fv[Index].FvHandle, FileName, 0, FileHandle, NULL);
1596 if (!EFI_ERROR (Status)) {
1597 *FvHandle = PrivateData->Fv[Index].FvHandle;
1598 break;
1599 }
1600 }
1601 }
1602 }
1603
1604 return Status;
1605 }
1606
1607 /**
1608 Returns information about a specific file.
1609
1610 This function returns information about a specific
1611 file, including its file name, type, attributes, starting
1612 address and size.
1613
1614 @param This Points to this instance of the
1615 EFI_PEI_FIRMWARE_VOLUME_PPI.
1616 @param FileHandle Handle of the file.
1617 @param FileInfo Upon exit, points to the file's
1618 information.
1619
1620 @retval EFI_SUCCESS File information returned.
1621 @retval EFI_INVALID_PARAMETER If FileHandle does not
1622 represent a valid file.
1623 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
1624
1625 **/
1626 EFI_STATUS
1627 EFIAPI
PeiFfsFvPpiGetFileInfo(IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI * This,IN EFI_PEI_FILE_HANDLE FileHandle,OUT EFI_FV_FILE_INFO * FileInfo)1628 PeiFfsFvPpiGetFileInfo (
1629 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1630 IN EFI_PEI_FILE_HANDLE FileHandle,
1631 OUT EFI_FV_FILE_INFO *FileInfo
1632 )
1633 {
1634 UINT8 FileState;
1635 UINT8 ErasePolarity;
1636 EFI_FFS_FILE_HEADER *FileHeader;
1637 PEI_CORE_FV_HANDLE *CoreFvHandle;
1638 PEI_FW_VOL_INSTANCE *FwVolInstance;
1639
1640 if ((FileHandle == NULL) || (FileInfo == NULL)) {
1641 return EFI_INVALID_PARAMETER;
1642 }
1643
1644 //
1645 // Retrieve the FirmwareVolume which the file resides in.
1646 //
1647 CoreFvHandle = FileHandleToVolume (FileHandle);
1648 if (CoreFvHandle == NULL) {
1649 return EFI_INVALID_PARAMETER;
1650 }
1651
1652 FwVolInstance = PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This);
1653
1654 if ((CoreFvHandle->FvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) != 0) {
1655 ErasePolarity = 1;
1656 } else {
1657 ErasePolarity = 0;
1658 }
1659
1660 //
1661 // Get FileState which is the highest bit of the State
1662 //
1663 FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle);
1664
1665 switch (FileState) {
1666 case EFI_FILE_DATA_VALID:
1667 case EFI_FILE_MARKED_FOR_UPDATE:
1668 break;
1669 default:
1670 return EFI_INVALID_PARAMETER;
1671 }
1672
1673 FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;
1674 if (IS_FFS_FILE2 (FileHeader)) {
1675 ASSERT (FFS_FILE2_SIZE (FileHeader) > 0x00FFFFFF);
1676 if (!FwVolInstance->IsFfs3Fv) {
1677 DEBUG ((EFI_D_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FileHeader->Name));
1678 return EFI_INVALID_PARAMETER;
1679 }
1680 FileInfo->BufferSize = FFS_FILE2_SIZE (FileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
1681 FileInfo->Buffer = (UINT8 *) FileHeader + sizeof (EFI_FFS_FILE_HEADER2);
1682 } else {
1683 FileInfo->BufferSize = FFS_FILE_SIZE (FileHeader) - sizeof (EFI_FFS_FILE_HEADER);
1684 FileInfo->Buffer = (UINT8 *) FileHeader + sizeof (EFI_FFS_FILE_HEADER);
1685 }
1686 CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID));
1687 FileInfo->FileType = FileHeader->Type;
1688 FileInfo->FileAttributes = FfsAttributes2FvFileAttributes (FileHeader->Attributes);
1689 if ((CoreFvHandle->FvHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) {
1690 FileInfo->FileAttributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED;
1691 }
1692 return EFI_SUCCESS;
1693 }
1694
1695 /**
1696 Returns information about a specific file.
1697
1698 This function returns information about a specific
1699 file, including its file name, type, attributes, starting
1700 address, size and authentication status.
1701
1702 @param This Points to this instance of the
1703 EFI_PEI_FIRMWARE_VOLUME_PPI.
1704 @param FileHandle Handle of the file.
1705 @param FileInfo Upon exit, points to the file's
1706 information.
1707
1708 @retval EFI_SUCCESS File information returned.
1709 @retval EFI_INVALID_PARAMETER If FileHandle does not
1710 represent a valid file.
1711 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
1712
1713 **/
1714 EFI_STATUS
1715 EFIAPI
PeiFfsFvPpiGetFileInfo2(IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI * This,IN EFI_PEI_FILE_HANDLE FileHandle,OUT EFI_FV_FILE_INFO2 * FileInfo)1716 PeiFfsFvPpiGetFileInfo2 (
1717 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1718 IN EFI_PEI_FILE_HANDLE FileHandle,
1719 OUT EFI_FV_FILE_INFO2 *FileInfo
1720 )
1721 {
1722 EFI_STATUS Status;
1723 PEI_CORE_FV_HANDLE *CoreFvHandle;
1724
1725 if ((FileHandle == NULL) || (FileInfo == NULL)) {
1726 return EFI_INVALID_PARAMETER;
1727 }
1728
1729 //
1730 // Retrieve the FirmwareVolume which the file resides in.
1731 //
1732 CoreFvHandle = FileHandleToVolume (FileHandle);
1733 if (CoreFvHandle == NULL) {
1734 return EFI_INVALID_PARAMETER;
1735 }
1736
1737 Status = PeiFfsFvPpiGetFileInfo (This, FileHandle, (EFI_FV_FILE_INFO *) FileInfo);
1738 if (!EFI_ERROR (Status)) {
1739 FileInfo->AuthenticationStatus = CoreFvHandle->AuthenticationStatus;
1740 }
1741
1742 return Status;
1743 }
1744
1745 /**
1746 This function returns information about the firmware volume.
1747
1748 @param This Points to this instance of the
1749 EFI_PEI_FIRMWARE_VOLUME_PPI.
1750 @param FvHandle Handle to the firmware handle.
1751 @param VolumeInfo Points to the returned firmware volume
1752 information.
1753
1754 @retval EFI_SUCCESS Information returned successfully.
1755 @retval EFI_INVALID_PARAMETER FvHandle does not indicate a valid
1756 firmware volume or VolumeInfo is NULL.
1757
1758 **/
1759 EFI_STATUS
1760 EFIAPI
PeiFfsFvPpiGetVolumeInfo(IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI * This,IN EFI_PEI_FV_HANDLE FvHandle,OUT EFI_FV_INFO * VolumeInfo)1761 PeiFfsFvPpiGetVolumeInfo (
1762 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1763 IN EFI_PEI_FV_HANDLE FvHandle,
1764 OUT EFI_FV_INFO *VolumeInfo
1765 )
1766 {
1767 EFI_FIRMWARE_VOLUME_HEADER FwVolHeader;
1768 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;
1769
1770 if ((VolumeInfo == NULL) || (FvHandle == NULL)) {
1771 return EFI_INVALID_PARAMETER;
1772 }
1773
1774 //
1775 // VolumeHandle may not align at 8 byte,
1776 // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte.
1777 // So, Copy FvHeader into the local FvHeader structure.
1778 //
1779 CopyMem (&FwVolHeader, FvHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
1780
1781 //
1782 // Check Fv Image Signature
1783 //
1784 if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {
1785 return EFI_INVALID_PARAMETER;
1786 }
1787
1788 ZeroMem (VolumeInfo, sizeof (EFI_FV_INFO));
1789 VolumeInfo->FvAttributes = FwVolHeader.Attributes;
1790 VolumeInfo->FvStart = (VOID *) FvHandle;
1791 VolumeInfo->FvSize = FwVolHeader.FvLength;
1792 CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID));
1793
1794 if (FwVolHeader.ExtHeaderOffset != 0) {
1795 FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)FvHandle) + FwVolHeader.ExtHeaderOffset);
1796 CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID));
1797 }
1798
1799 return EFI_SUCCESS;
1800 }
1801
1802 /**
1803 Find the next matching section in the firmware file.
1804
1805 This service enables PEI modules to discover sections
1806 of a given type within a valid file.
1807
1808 @param This Points to this instance of the
1809 EFI_PEI_FIRMWARE_VOLUME_PPI.
1810 @param SearchType A filter to find only sections of this
1811 type.
1812 @param FileHandle Handle of firmware file in which to
1813 search.
1814 @param SectionData Updated upon return to point to the
1815 section found.
1816
1817 @retval EFI_SUCCESS Section was found.
1818 @retval EFI_NOT_FOUND Section of the specified type was not
1819 found. SectionData contains NULL.
1820 **/
1821 EFI_STATUS
1822 EFIAPI
PeiFfsFvPpiFindSectionByType(IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI * This,IN EFI_SECTION_TYPE SearchType,IN EFI_PEI_FILE_HANDLE FileHandle,OUT VOID ** SectionData)1823 PeiFfsFvPpiFindSectionByType (
1824 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1825 IN EFI_SECTION_TYPE SearchType,
1826 IN EFI_PEI_FILE_HANDLE FileHandle,
1827 OUT VOID **SectionData
1828 )
1829 {
1830 UINT32 AuthenticationStatus;
1831 return PeiFfsFvPpiFindSectionByType2 (This, SearchType, 0, FileHandle, SectionData, &AuthenticationStatus);
1832 }
1833
1834 /**
1835 Find the next matching section in the firmware file.
1836
1837 This service enables PEI modules to discover sections
1838 of a given instance and type within a valid file.
1839
1840 @param This Points to this instance of the
1841 EFI_PEI_FIRMWARE_VOLUME_PPI.
1842 @param SearchType A filter to find only sections of this
1843 type.
1844 @param SearchInstance A filter to find the specific instance
1845 of sections.
1846 @param FileHandle Handle of firmware file in which to
1847 search.
1848 @param SectionData Updated upon return to point to the
1849 section found.
1850 @param AuthenticationStatus Updated upon return to point to the
1851 authentication status for this section.
1852
1853 @retval EFI_SUCCESS Section was found.
1854 @retval EFI_NOT_FOUND Section of the specified type was not
1855 found. SectionData contains NULL.
1856 **/
1857 EFI_STATUS
1858 EFIAPI
PeiFfsFvPpiFindSectionByType2(IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI * This,IN EFI_SECTION_TYPE SearchType,IN UINTN SearchInstance,IN EFI_PEI_FILE_HANDLE FileHandle,OUT VOID ** SectionData,OUT UINT32 * AuthenticationStatus)1859 PeiFfsFvPpiFindSectionByType2 (
1860 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1861 IN EFI_SECTION_TYPE SearchType,
1862 IN UINTN SearchInstance,
1863 IN EFI_PEI_FILE_HANDLE FileHandle,
1864 OUT VOID **SectionData,
1865 OUT UINT32 *AuthenticationStatus
1866 )
1867 {
1868 EFI_STATUS Status;
1869 EFI_FFS_FILE_HEADER *FfsFileHeader;
1870 UINT32 FileSize;
1871 EFI_COMMON_SECTION_HEADER *Section;
1872 PEI_FW_VOL_INSTANCE *FwVolInstance;
1873 PEI_CORE_FV_HANDLE *CoreFvHandle;
1874 UINTN Instance;
1875 UINT32 ExtractedAuthenticationStatus;
1876
1877 if (SectionData == NULL) {
1878 return EFI_NOT_FOUND;
1879 }
1880
1881 FwVolInstance = PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This);
1882
1883 //
1884 // Retrieve the FirmwareVolume which the file resides in.
1885 //
1886 CoreFvHandle = FileHandleToVolume (FileHandle);
1887 if (CoreFvHandle == NULL) {
1888 return EFI_NOT_FOUND;
1889 }
1890
1891 FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);
1892
1893 if (IS_FFS_FILE2 (FfsFileHeader)) {
1894 ASSERT (FFS_FILE2_SIZE (FfsFileHeader) > 0x00FFFFFF);
1895 if (!FwVolInstance->IsFfs3Fv) {
1896 DEBUG ((EFI_D_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));
1897 return EFI_NOT_FOUND;
1898 }
1899 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
1900 FileSize = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
1901 } else {
1902 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));
1903 FileSize = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
1904 }
1905
1906 Instance = SearchInstance + 1;
1907 ExtractedAuthenticationStatus = 0;
1908 Status = ProcessSection (
1909 GetPeiServicesTablePointer (),
1910 SearchType,
1911 &Instance,
1912 Section,
1913 FileSize,
1914 SectionData,
1915 &ExtractedAuthenticationStatus,
1916 FwVolInstance->IsFfs3Fv
1917 );
1918 if (!EFI_ERROR (Status)) {
1919 //
1920 // Inherit the authentication status.
1921 //
1922 *AuthenticationStatus = ExtractedAuthenticationStatus | CoreFvHandle->AuthenticationStatus;
1923 }
1924 return Status;
1925 }
1926
1927 /**
1928 Convert the handle of FV to pointer of corresponding PEI_CORE_FV_HANDLE.
1929
1930 @param FvHandle The handle of a FV.
1931
1932 @retval NULL if can not find.
1933 @return Pointer of corresponding PEI_CORE_FV_HANDLE.
1934 **/
1935 PEI_CORE_FV_HANDLE *
FvHandleToCoreHandle(IN EFI_PEI_FV_HANDLE FvHandle)1936 FvHandleToCoreHandle (
1937 IN EFI_PEI_FV_HANDLE FvHandle
1938 )
1939 {
1940 UINTN Index;
1941 PEI_CORE_INSTANCE *PrivateData;
1942
1943 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer());
1944 for (Index = 0; Index < PrivateData->FvCount; Index ++) {
1945 if (FvHandle == PrivateData->Fv[Index].FvHandle) {
1946 return &PrivateData->Fv[Index];
1947 }
1948 }
1949
1950 return NULL;
1951 }
1952
1953 /**
1954 Get instance of PEI_CORE_FV_HANDLE for next volume according to given index.
1955
1956 This routine also will install FvInfo ppi for FV hob in PI ways.
1957
1958 @param Private Pointer of PEI_CORE_INSTANCE
1959 @param Instance The index of FV want to be searched.
1960
1961 @return Instance of PEI_CORE_FV_HANDLE.
1962 **/
1963 PEI_CORE_FV_HANDLE *
FindNextCoreFvHandle(IN PEI_CORE_INSTANCE * Private,IN UINTN Instance)1964 FindNextCoreFvHandle (
1965 IN PEI_CORE_INSTANCE *Private,
1966 IN UINTN Instance
1967 )
1968 {
1969 UINTN Index;
1970 BOOLEAN Match;
1971 EFI_HOB_FIRMWARE_VOLUME *FvHob;
1972
1973 //
1974 // Handle Framework FvHob and Install FvInfo Ppi for it.
1975 //
1976 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
1977 //
1978 // Loop to search the wanted FirmwareVolume which supports FFS
1979 //
1980 FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetFirstHob (EFI_HOB_TYPE_FV);
1981 while (FvHob != NULL) {
1982 //
1983 // Search whether FvHob has been installed into PeiCore's FV database.
1984 // If found, no need install new FvInfoPpi for it.
1985 //
1986 for (Index = 0, Match = FALSE; Index < Private->FvCount; Index++) {
1987 if ((EFI_PEI_FV_HANDLE)(UINTN)FvHob->BaseAddress == Private->Fv[Index].FvHeader) {
1988 Match = TRUE;
1989 break;
1990 }
1991 }
1992
1993 //
1994 // Search whether FvHob has been cached into PeiCore's Unknown FV database.
1995 // If found, no need install new FvInfoPpi for it.
1996 //
1997 if (!Match) {
1998 for (Index = 0; Index < Private->UnknownFvInfoCount; Index ++) {
1999 if ((UINTN)FvHob->BaseAddress == (UINTN)Private->UnknownFvInfo[Index].FvInfo) {
2000 Match = TRUE;
2001 break;
2002 }
2003 }
2004 }
2005
2006 //
2007 // If the Fv in FvHob has not been installed into PeiCore's FV database and has
2008 // not been cached into PeiCore's Unknown FV database, install a new FvInfoPpi
2009 // for it then PeiCore will dispatch it in callback of FvInfoPpi.
2010 //
2011 if (!Match) {
2012 PeiServicesInstallFvInfoPpi (
2013 &(((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvHob->BaseAddress)->FileSystemGuid),
2014 (VOID *)(UINTN)FvHob->BaseAddress,
2015 (UINT32)FvHob->Length,
2016 NULL,
2017 NULL
2018 );
2019 }
2020
2021 FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetNextHob (EFI_HOB_TYPE_FV, (VOID *)((UINTN)FvHob + FvHob->Header.HobLength));
2022 }
2023 }
2024
2025 ASSERT (Private->FvCount <= PcdGet32 (PcdPeiCoreMaxFvSupported));
2026 if (Instance >= Private->FvCount) {
2027 return NULL;
2028 }
2029
2030 return &Private->Fv[Instance];
2031 }
2032
2033 /**
2034 After PeiCore image is shadowed into permanent memory, all build-in FvPpi should
2035 be re-installed with the instance in permanent memory and all cached FvPpi pointers in
2036 PrivateData->Fv[] array should be fixed up to be pointed to the one in permanent
2037 memory.
2038
2039 @param PrivateData Pointer to PEI_CORE_INSTANCE.
2040 **/
2041 VOID
PeiReinitializeFv(IN PEI_CORE_INSTANCE * PrivateData)2042 PeiReinitializeFv (
2043 IN PEI_CORE_INSTANCE *PrivateData
2044 )
2045 {
2046 VOID *OldFfsFvPpi;
2047 EFI_PEI_PPI_DESCRIPTOR *OldDescriptor;
2048 UINTN Index;
2049 EFI_STATUS Status;
2050
2051 //
2052 // Locate old build-in Ffs2 EFI_PEI_FIRMWARE_VOLUME_PPI which
2053 // in flash.
2054 //
2055 Status = PeiServicesLocatePpi (
2056 &gEfiFirmwareFileSystem2Guid,
2057 0,
2058 &OldDescriptor,
2059 &OldFfsFvPpi
2060 );
2061 ASSERT_EFI_ERROR (Status);
2062
2063 //
2064 // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs2
2065 // which is shadowed from flash to permanent memory within PeiCore image.
2066 //
2067 Status = PeiServicesReInstallPpi (OldDescriptor, &mPeiFfs2FvPpiList);
2068 ASSERT_EFI_ERROR (Status);
2069
2070 //
2071 // Fixup all FvPpi pointers for the implementation in flash to permanent memory.
2072 //
2073 for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {
2074 if (PrivateData->Fv[Index].FvPpi == OldFfsFvPpi) {
2075 PrivateData->Fv[Index].FvPpi = &mPeiFfs2FwVol.Fv;
2076 }
2077 }
2078
2079 //
2080 // Locate old build-in Ffs3 EFI_PEI_FIRMWARE_VOLUME_PPI which
2081 // in flash.
2082 //
2083 Status = PeiServicesLocatePpi (
2084 &gEfiFirmwareFileSystem3Guid,
2085 0,
2086 &OldDescriptor,
2087 &OldFfsFvPpi
2088 );
2089 ASSERT_EFI_ERROR (Status);
2090
2091 //
2092 // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs3
2093 // which is shadowed from flash to permanent memory within PeiCore image.
2094 //
2095 Status = PeiServicesReInstallPpi (OldDescriptor, &mPeiFfs3FvPpiList);
2096 ASSERT_EFI_ERROR (Status);
2097
2098 //
2099 // Fixup all FvPpi pointers for the implementation in flash to permanent memory.
2100 //
2101 for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {
2102 if (PrivateData->Fv[Index].FvPpi == OldFfsFvPpi) {
2103 PrivateData->Fv[Index].FvPpi = &mPeiFfs3FwVol.Fv;
2104 }
2105 }
2106 }
2107
2108 /**
2109 Report the information for a new discoveried FV in unknown third-party format.
2110
2111 If the EFI_PEI_FIRMWARE_VOLUME_PPI has not been installed for third-party FV format, but
2112 the FV in this format has been discoveried, then this FV's information will be cached into
2113 PEI_CORE_INSTANCE's UnknownFvInfo array.
2114 Also a notification would be installed for unknown third-party FV format guid, if EFI_PEI_FIRMWARE_VOLUME_PPI
2115 is installed later by platform's PEIM, the original unknown third-party FV will be processed by
2116 using new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
2117
2118 @param PrivateData Point to instance of PEI_CORE_INSTANCE
2119 @param FvInfo2Ppi Point to FvInfo2 PPI.
2120
2121 @retval EFI_OUT_OF_RESOURCES The FV info array in PEI_CORE_INSTANCE has no more spaces.
2122 @retval EFI_SUCCESS Success to add the information for unknown FV.
2123 **/
2124 EFI_STATUS
AddUnknownFormatFvInfo(IN PEI_CORE_INSTANCE * PrivateData,IN EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI * FvInfo2Ppi)2125 AddUnknownFormatFvInfo (
2126 IN PEI_CORE_INSTANCE *PrivateData,
2127 IN EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI *FvInfo2Ppi
2128 )
2129 {
2130 PEI_CORE_UNKNOW_FORMAT_FV_INFO *NewUnknownFv;
2131
2132 if (PrivateData->UnknownFvInfoCount + 1 >= PcdGet32 (PcdPeiCoreMaxFvSupported)) {
2133 return EFI_OUT_OF_RESOURCES;
2134 }
2135
2136 NewUnknownFv = &PrivateData->UnknownFvInfo[PrivateData->UnknownFvInfoCount];
2137 PrivateData->UnknownFvInfoCount ++;
2138
2139 CopyGuid (&NewUnknownFv->FvFormat, &FvInfo2Ppi->FvFormat);
2140 NewUnknownFv->FvInfo = FvInfo2Ppi->FvInfo;
2141 NewUnknownFv->FvInfoSize = FvInfo2Ppi->FvInfoSize;
2142 NewUnknownFv->AuthenticationStatus = FvInfo2Ppi->AuthenticationStatus;
2143 NewUnknownFv->NotifyDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
2144 NewUnknownFv->NotifyDescriptor.Guid = &NewUnknownFv->FvFormat;
2145 NewUnknownFv->NotifyDescriptor.Notify = ThirdPartyFvPpiNotifyCallback;
2146
2147 PeiServicesNotifyPpi (&NewUnknownFv->NotifyDescriptor);
2148 return EFI_SUCCESS;
2149 }
2150
2151 /**
2152 Find the FV information according to third-party FV format guid.
2153
2154 This routine also will remove the FV information found by given FV format guid from
2155 PrivateData->UnknownFvInfo[].
2156
2157 @param PrivateData Point to instance of PEI_CORE_INSTANCE
2158 @param Format Point to given FV format guid
2159 @param FvInfo On return, the pointer of FV information buffer
2160 @param FvInfoSize On return, the size of FV information buffer.
2161 @param AuthenticationStatus On return, the authentication status of FV information buffer.
2162
2163 @retval EFI_NOT_FOUND The FV is not found for new installed EFI_PEI_FIRMWARE_VOLUME_PPI
2164 @retval EFI_SUCCESS Success to find a FV which could be processed by new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
2165 **/
2166 EFI_STATUS
FindUnknownFormatFvInfo(IN PEI_CORE_INSTANCE * PrivateData,IN EFI_GUID * Format,OUT VOID ** FvInfo,OUT UINT32 * FvInfoSize,OUT UINT32 * AuthenticationStatus)2167 FindUnknownFormatFvInfo (
2168 IN PEI_CORE_INSTANCE *PrivateData,
2169 IN EFI_GUID *Format,
2170 OUT VOID **FvInfo,
2171 OUT UINT32 *FvInfoSize,
2172 OUT UINT32 *AuthenticationStatus
2173 )
2174 {
2175 UINTN Index;
2176 UINTN Index2;
2177
2178 Index = 0;
2179 for (; Index < PrivateData->UnknownFvInfoCount; Index ++) {
2180 if (CompareGuid (Format, &PrivateData->UnknownFvInfo[Index].FvFormat)) {
2181 break;
2182 }
2183 }
2184
2185 if (Index == PrivateData->UnknownFvInfoCount) {
2186 return EFI_NOT_FOUND;
2187 }
2188
2189 *FvInfo = PrivateData->UnknownFvInfo[Index].FvInfo;
2190 *FvInfoSize = PrivateData->UnknownFvInfo[Index].FvInfoSize;
2191 *AuthenticationStatus = PrivateData->UnknownFvInfo[Index].AuthenticationStatus;
2192
2193 //
2194 // Remove an entry from UnknownFvInfo array.
2195 //
2196 Index2 = Index + 1;
2197 for (;Index2 < PrivateData->UnknownFvInfoCount; Index2 ++, Index ++) {
2198 CopyMem (&PrivateData->UnknownFvInfo[Index], &PrivateData->UnknownFvInfo[Index2], sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO));
2199 }
2200 PrivateData->UnknownFvInfoCount --;
2201 return EFI_SUCCESS;
2202 }
2203
2204 /**
2205 Notification callback function for EFI_PEI_FIRMWARE_VOLUME_PPI.
2206
2207 When a EFI_PEI_FIRMWARE_VOLUME_PPI is installed to support new FV format, this
2208 routine is called to process all discoveried FVs in this format.
2209
2210 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
2211 @param NotifyDescriptor Address of the notification descriptor data structure.
2212 @param Ppi Address of the PPI that was installed.
2213
2214 @retval EFI_SUCCESS The notification callback is processed correctly.
2215 **/
2216 EFI_STATUS
2217 EFIAPI
ThirdPartyFvPpiNotifyCallback(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_NOTIFY_DESCRIPTOR * NotifyDescriptor,IN VOID * Ppi)2218 ThirdPartyFvPpiNotifyCallback (
2219 IN EFI_PEI_SERVICES **PeiServices,
2220 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
2221 IN VOID *Ppi
2222 )
2223 {
2224 PEI_CORE_INSTANCE *PrivateData;
2225 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
2226 VOID *FvInfo;
2227 UINT32 FvInfoSize;
2228 UINT32 AuthenticationStatus;
2229 EFI_STATUS Status;
2230 EFI_PEI_FV_HANDLE FvHandle;
2231 BOOLEAN IsProcessed;
2232 UINTN FvIndex;
2233 EFI_PEI_FILE_HANDLE FileHandle;
2234 VOID *DepexData;
2235 UINTN CurFvCount;
2236
2237 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
2238 FvPpi = (EFI_PEI_FIRMWARE_VOLUME_PPI*) Ppi;
2239
2240 do {
2241 Status = FindUnknownFormatFvInfo (PrivateData, NotifyDescriptor->Guid, &FvInfo, &FvInfoSize, &AuthenticationStatus);
2242 if (EFI_ERROR (Status)) {
2243 return EFI_SUCCESS;
2244 }
2245
2246 //
2247 // Process new found FV and get FV handle.
2248 //
2249 Status = FvPpi->ProcessVolume (FvPpi, FvInfo, FvInfoSize, &FvHandle);
2250 if (EFI_ERROR (Status)) {
2251 DEBUG ((EFI_D_ERROR, "Fail to process the FV 0x%p, FV may be corrupted!\n", FvInfo));
2252 continue;
2253 }
2254
2255 //
2256 // Check whether the FV has already been processed.
2257 //
2258 IsProcessed = FALSE;
2259 for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {
2260 if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {
2261 DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvInfo));
2262 IsProcessed = TRUE;
2263 break;
2264 }
2265 }
2266
2267 if (IsProcessed) {
2268 continue;
2269 }
2270
2271 if (PrivateData->FvCount >= PcdGet32 (PcdPeiCoreMaxFvSupported)) {
2272 DEBUG ((EFI_D_ERROR, "The number of Fv Images (%d) exceed the max supported FVs (%d) in Pei", PrivateData->FvCount + 1, PcdGet32 (PcdPeiCoreMaxFvSupported)));
2273 DEBUG ((EFI_D_ERROR, "PcdPeiCoreMaxFvSupported value need be reconfigurated in DSC"));
2274 ASSERT (FALSE);
2275 }
2276
2277 //
2278 // Update internal PEI_CORE_FV array.
2279 //
2280 PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) FvInfo;
2281 PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi;
2282 PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;
2283 PrivateData->Fv[PrivateData->FvCount].AuthenticationStatus = AuthenticationStatus;
2284 CurFvCount = PrivateData->FvCount;
2285 DEBUG ((
2286 EFI_D_INFO,
2287 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
2288 (UINT32) CurFvCount,
2289 (VOID *) FvInfo,
2290 FvInfoSize,
2291 FvHandle
2292 ));
2293 PrivateData->FvCount ++;
2294
2295 //
2296 // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
2297 //
2298 FileHandle = NULL;
2299 do {
2300 Status = FvPpi->FindFileByType (
2301 FvPpi,
2302 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
2303 FvHandle,
2304 &FileHandle
2305 );
2306 if (!EFI_ERROR (Status)) {
2307 Status = FvPpi->FindSectionByType (
2308 FvPpi,
2309 EFI_SECTION_PEI_DEPEX,
2310 FileHandle,
2311 (VOID**)&DepexData
2312 );
2313 if (!EFI_ERROR (Status)) {
2314 if (!PeimDispatchReadiness (PeiServices, DepexData)) {
2315 //
2316 // Dependency is not satisfied.
2317 //
2318 continue;
2319 }
2320 }
2321
2322 DEBUG ((EFI_D_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, CurFvCount, FvHandle));
2323 ProcessFvFile (PrivateData, &PrivateData->Fv[CurFvCount], FileHandle);
2324 }
2325 } while (FileHandle != NULL);
2326 } while (TRUE);
2327 }
2328