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