1 /** @file
2   Pei Core Firmware File System service routines.
3 
4 Copyright (c) 2015 HP Development Company, L.P.
5 Copyright (c) 2006 - 2015, 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 
549   Status       = EFI_SUCCESS;
550   PrivateData  = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
551 
552   if (CompareGuid (NotifyDescriptor->Guid, &gEfiPeiFirmwareVolumeInfo2PpiGuid)) {
553     //
554     // It is FvInfo2PPI.
555     //
556     CopyMem (&FvInfo2Ppi, Ppi, sizeof (EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI));
557     IsFvInfo2 = TRUE;
558   } else {
559     //
560     // It is FvInfoPPI.
561     //
562     CopyMem (&FvInfo2Ppi, Ppi, sizeof (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI));
563     FvInfo2Ppi.AuthenticationStatus = 0;
564     IsFvInfo2 = FALSE;
565   }
566 
567   //
568   // Locate the corresponding FV_PPI according to founded FV's format guid
569   //
570   Status = PeiServicesLocatePpi (
571              &FvInfo2Ppi.FvFormat,
572              0,
573              NULL,
574              (VOID**)&FvPpi
575              );
576   if (!EFI_ERROR (Status)) {
577     //
578     // Process new found FV and get FV handle.
579     //
580     Status = FvPpi->ProcessVolume (FvPpi, FvInfo2Ppi.FvInfo, FvInfo2Ppi.FvInfoSize, &FvHandle);
581     if (EFI_ERROR (Status)) {
582       DEBUG ((EFI_D_ERROR, "Fail to process new found FV, FV may be corrupted!\n"));
583       return Status;
584     }
585 
586     //
587     // Check whether the FV has already been processed.
588     //
589     for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {
590       if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {
591         if (IsFvInfo2 && (FvInfo2Ppi.AuthenticationStatus != PrivateData->Fv[FvIndex].AuthenticationStatus)) {
592           PrivateData->Fv[FvIndex].AuthenticationStatus = FvInfo2Ppi.AuthenticationStatus;
593           DEBUG ((EFI_D_INFO, "Update AuthenticationStatus of the %dth FV to 0x%x!\n", FvIndex, FvInfo2Ppi.AuthenticationStatus));
594         }
595         DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvInfo2Ppi.FvInfo));
596         return EFI_SUCCESS;
597       }
598     }
599 
600     if (PrivateData->FvCount >= PcdGet32 (PcdPeiCoreMaxFvSupported)) {
601       DEBUG ((EFI_D_ERROR, "The number of Fv Images (%d) exceed the max supported FVs (%d) in Pei", PrivateData->FvCount + 1, PcdGet32 (PcdPeiCoreMaxFvSupported)));
602       DEBUG ((EFI_D_ERROR, "PcdPeiCoreMaxFvSupported value need be reconfigurated in DSC"));
603       ASSERT (FALSE);
604     }
605 
606     //
607     // Update internal PEI_CORE_FV array.
608     //
609     PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) FvInfo2Ppi.FvInfo;
610     PrivateData->Fv[PrivateData->FvCount].FvPpi    = FvPpi;
611     PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;
612     PrivateData->Fv[PrivateData->FvCount].AuthenticationStatus = FvInfo2Ppi.AuthenticationStatus;
613     DEBUG ((
614       EFI_D_INFO,
615       "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
616       (UINT32) PrivateData->FvCount,
617       (VOID *) FvInfo2Ppi.FvInfo,
618       FvInfo2Ppi.FvInfoSize,
619       FvHandle
620       ));
621     PrivateData->FvCount ++;
622 
623     //
624     // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
625     //
626     FileHandle = NULL;
627     do {
628       Status = FvPpi->FindFileByType (
629                         FvPpi,
630                         EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
631                         FvHandle,
632                         &FileHandle
633                        );
634       if (!EFI_ERROR (Status)) {
635         Status = FvPpi->FindSectionByType (
636                           FvPpi,
637                           EFI_SECTION_PEI_DEPEX,
638                           FileHandle,
639                           (VOID**)&DepexData
640                           );
641         if (!EFI_ERROR (Status)) {
642           if (!PeimDispatchReadiness (PeiServices, DepexData)) {
643             //
644             // Dependency is not satisfied.
645             //
646             continue;
647           }
648         }
649 
650         DEBUG ((EFI_D_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, PrivateData->FvCount - 1, FvHandle));
651         ProcessFvFile (PrivateData, &PrivateData->Fv[PrivateData->FvCount - 1], FileHandle);
652       }
653     } while (FileHandle != NULL);
654   } else {
655     DEBUG ((EFI_D_ERROR, "Fail to process FV %p because no corresponding EFI_FIRMWARE_VOLUME_PPI is found!\n", FvInfo2Ppi.FvInfo));
656 
657     AddUnknownFormatFvInfo (PrivateData, &FvInfo2Ppi);
658   }
659 
660   return EFI_SUCCESS;
661 }
662 
663 /**
664   Verify the Guided Section GUID by checking if there is the Guided Section GUID HOB recorded the GUID itself.
665 
666   @param GuidedSectionGuid          The Guided Section GUID.
667   @param GuidedSectionExtraction    A pointer to the pointer to the supported Guided Section Extraction Ppi
668                                     for the Guided Section.
669 
670   @return TRUE      The GuidedSectionGuid could be identified, and the pointer to
671                     the Guided Section Extraction Ppi will be returned to *GuidedSectionExtraction.
672   @return FALSE     The GuidedSectionGuid could not be identified, or
673                     the Guided Section Extraction Ppi has not been installed yet.
674 
675 **/
676 BOOLEAN
VerifyGuidedSectionGuid(IN EFI_GUID * GuidedSectionGuid,OUT EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI ** GuidedSectionExtraction)677 VerifyGuidedSectionGuid (
678   IN  EFI_GUID                                  *GuidedSectionGuid,
679   OUT EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI     **GuidedSectionExtraction
680   )
681 {
682   EFI_PEI_HOB_POINTERS  Hob;
683   EFI_GUID              *GuidRecorded;
684   VOID                  *Interface;
685   EFI_STATUS            Status;
686 
687   //
688   // Check if there is the Guided Section GUID HOB recorded the GUID itself.
689   //
690   Hob.Raw = GetFirstGuidHob (GuidedSectionGuid);
691   if (Hob.Raw != NULL) {
692     GuidRecorded = (EFI_GUID *) GET_GUID_HOB_DATA (Hob);
693     if (CompareGuid (GuidRecorded, GuidedSectionGuid)) {
694       //
695       // Found the recorded GuidedSectionGuid.
696       //
697       Status = PeiServicesLocatePpi (GuidedSectionGuid, 0, NULL, (VOID **) &Interface);
698       if (!EFI_ERROR (Status) && Interface != NULL) {
699         //
700         // Found the supported Guided Section Extraction Ppi for the Guided Section.
701         //
702         *GuidedSectionExtraction = (EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *) Interface;
703         return TRUE;
704       }
705       return FALSE;
706     }
707   }
708 
709   return FALSE;
710 }
711 
712 /**
713   Go through the file to search SectionType section.
714   Search within encapsulation sections (compression and GUIDed) recursively,
715   until the match section is found.
716 
717   @param PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
718   @param SectionType       Filter to find only section of this type.
719   @param SectionInstance   Pointer to the filter to find the specific instance of section.
720   @param Section           From where to search.
721   @param SectionSize       The file size to search.
722   @param OutputBuffer      A pointer to the discovered section, if successful.
723                            NULL if section not found
724   @param AuthenticationStatus Updated upon return to point to the authentication status for this section.
725   @param IsFfs3Fv          Indicates the FV format.
726 
727   @return EFI_NOT_FOUND    The match section is not found.
728   @return EFI_SUCCESS      The match section is found.
729 
730 **/
731 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)732 ProcessSection (
733   IN CONST EFI_PEI_SERVICES     **PeiServices,
734   IN EFI_SECTION_TYPE           SectionType,
735   IN OUT UINTN                  *SectionInstance,
736   IN EFI_COMMON_SECTION_HEADER  *Section,
737   IN UINTN                      SectionSize,
738   OUT VOID                      **OutputBuffer,
739   OUT UINT32                    *AuthenticationStatus,
740   IN BOOLEAN                    IsFfs3Fv
741   )
742 {
743   EFI_STATUS                              Status;
744   UINT32                                  SectionLength;
745   UINT32                                  ParsedLength;
746   EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI   *GuidSectionPpi;
747   EFI_PEI_DECOMPRESS_PPI                  *DecompressPpi;
748   VOID                                    *PpiOutput;
749   UINTN                                   PpiOutputSize;
750   UINTN                                   Index;
751   UINT32                                  Authentication;
752   PEI_CORE_INSTANCE                       *PrivateData;
753   EFI_GUID                                *SectionDefinitionGuid;
754   BOOLEAN                                 SectionCached;
755   VOID                                    *TempOutputBuffer;
756   UINT32                                  TempAuthenticationStatus;
757   UINT16                                  GuidedSectionAttributes;
758 
759   PrivateData   = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
760   *OutputBuffer = NULL;
761   ParsedLength  = 0;
762   Index         = 0;
763   Status        = EFI_NOT_FOUND;
764   PpiOutput     = NULL;
765   PpiOutputSize = 0;
766   while (ParsedLength < SectionSize) {
767 
768     if (IS_SECTION2 (Section)) {
769       ASSERT (SECTION2_SIZE (Section) > 0x00FFFFFF);
770       if (!IsFfs3Fv) {
771         DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted section in a non-FFS3 formatted FV.\n"));
772         SectionLength = SECTION2_SIZE (Section);
773         //
774         // SectionLength is adjusted it is 4 byte aligned.
775         // Go to the next section
776         //
777         SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
778         ASSERT (SectionLength != 0);
779         ParsedLength += SectionLength;
780         Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + SectionLength);
781         continue;
782       }
783     }
784 
785     if (Section->Type == SectionType) {
786       //
787       // The type matches, so check the instance count to see if it's the one we want.
788       //
789       (*SectionInstance)--;
790       if (*SectionInstance == 0) {
791         //
792         // Got it!
793         //
794         if (IS_SECTION2 (Section)) {
795           *OutputBuffer = (VOID *)((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2));
796         } else {
797           *OutputBuffer = (VOID *)((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER));
798         }
799         return EFI_SUCCESS;
800       } else {
801         if (IS_SECTION2 (Section)) {
802           SectionLength = SECTION2_SIZE (Section);
803         } else {
804           SectionLength = SECTION_SIZE (Section);
805         }
806         //
807         // SectionLength is adjusted it is 4 byte aligned.
808         // Go to the next section
809         //
810         SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
811         ASSERT (SectionLength != 0);
812         ParsedLength += SectionLength;
813         Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
814         continue;
815       }
816     } else if ((Section->Type == EFI_SECTION_GUID_DEFINED) || (Section->Type == EFI_SECTION_COMPRESSION)) {
817       //
818       // Check the encapsulated section is extracted into the cache data.
819       //
820       SectionCached = FALSE;
821       for (Index = 0; Index < PrivateData->CacheSection.AllSectionCount; Index ++) {
822         if (Section == PrivateData->CacheSection.Section[Index]) {
823           SectionCached = TRUE;
824           PpiOutput     = PrivateData->CacheSection.SectionData[Index];
825           PpiOutputSize = PrivateData->CacheSection.SectionSize[Index];
826           Authentication = PrivateData->CacheSection.AuthenticationStatus[Index];
827           //
828           // Search section directly from the cache data.
829           //
830           TempAuthenticationStatus = 0;
831           Status = ProcessSection (
832                      PeiServices,
833                      SectionType,
834                      SectionInstance,
835                      PpiOutput,
836                      PpiOutputSize,
837                      &TempOutputBuffer,
838                      &TempAuthenticationStatus,
839                      IsFfs3Fv
840                    );
841           if (!EFI_ERROR (Status)) {
842             *OutputBuffer = TempOutputBuffer;
843             *AuthenticationStatus = TempAuthenticationStatus | Authentication;
844             return EFI_SUCCESS;
845           }
846         }
847       }
848 
849       //
850       // If SectionCached is TRUE, the section data has been cached and scanned.
851       //
852       if (!SectionCached) {
853         Status = EFI_NOT_FOUND;
854         Authentication = 0;
855         if (Section->Type == EFI_SECTION_GUID_DEFINED) {
856           if (IS_SECTION2 (Section)) {
857             SectionDefinitionGuid   = &((EFI_GUID_DEFINED_SECTION2 *)Section)->SectionDefinitionGuid;
858             GuidedSectionAttributes = ((EFI_GUID_DEFINED_SECTION2 *)Section)->Attributes;
859           } else {
860             SectionDefinitionGuid   = &((EFI_GUID_DEFINED_SECTION *)Section)->SectionDefinitionGuid;
861             GuidedSectionAttributes = ((EFI_GUID_DEFINED_SECTION *)Section)->Attributes;
862           }
863           if (VerifyGuidedSectionGuid (SectionDefinitionGuid, &GuidSectionPpi)) {
864             Status = GuidSectionPpi->ExtractSection (
865                                        GuidSectionPpi,
866                                        Section,
867                                        &PpiOutput,
868                                        &PpiOutputSize,
869                                        &Authentication
870                                        );
871           } else if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {
872             //
873             // Figure out the proper authentication status for GUIDED section without processing required
874             //
875             Status = EFI_SUCCESS;
876             if ((GuidedSectionAttributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) == EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {
877               Authentication |= EFI_AUTH_STATUS_IMAGE_SIGNED | EFI_AUTH_STATUS_NOT_TESTED;
878             }
879             if (IS_SECTION2 (Section)) {
880               PpiOutputSize = SECTION2_SIZE (Section) - ((EFI_GUID_DEFINED_SECTION2 *) Section)->DataOffset;
881               PpiOutput     = (UINT8 *) Section + ((EFI_GUID_DEFINED_SECTION2 *) Section)->DataOffset;
882             } else {
883               PpiOutputSize = SECTION_SIZE (Section) - ((EFI_GUID_DEFINED_SECTION *) Section)->DataOffset;
884               PpiOutput     = (UINT8 *) Section + ((EFI_GUID_DEFINED_SECTION *) Section)->DataOffset;
885             }
886           }
887         } else if (Section->Type == EFI_SECTION_COMPRESSION) {
888           Status = PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid, 0, NULL, (VOID **) &DecompressPpi);
889           if (!EFI_ERROR (Status)) {
890             Status = DecompressPpi->Decompress (
891                                       DecompressPpi,
892                                       (CONST EFI_COMPRESSION_SECTION*) Section,
893                                       &PpiOutput,
894                                       &PpiOutputSize
895                                       );
896           }
897         }
898 
899         if (!EFI_ERROR (Status)) {
900           //
901           // Update cache section data.
902           //
903           if (PrivateData->CacheSection.AllSectionCount < CACHE_SETION_MAX_NUMBER) {
904             PrivateData->CacheSection.AllSectionCount ++;
905           }
906           PrivateData->CacheSection.Section [PrivateData->CacheSection.SectionIndex]     = Section;
907           PrivateData->CacheSection.SectionData [PrivateData->CacheSection.SectionIndex] = PpiOutput;
908           PrivateData->CacheSection.SectionSize [PrivateData->CacheSection.SectionIndex] = PpiOutputSize;
909           PrivateData->CacheSection.AuthenticationStatus [PrivateData->CacheSection.SectionIndex] = Authentication;
910           PrivateData->CacheSection.SectionIndex = (PrivateData->CacheSection.SectionIndex + 1)%CACHE_SETION_MAX_NUMBER;
911 
912           TempAuthenticationStatus = 0;
913           Status = ProcessSection (
914                      PeiServices,
915                      SectionType,
916                      SectionInstance,
917                      PpiOutput,
918                      PpiOutputSize,
919                      &TempOutputBuffer,
920                      &TempAuthenticationStatus,
921                      IsFfs3Fv
922                    );
923           if (!EFI_ERROR (Status)) {
924             *OutputBuffer = TempOutputBuffer;
925             *AuthenticationStatus = TempAuthenticationStatus | Authentication;
926             return EFI_SUCCESS;
927           }
928         }
929       }
930     }
931 
932     if (IS_SECTION2 (Section)) {
933       SectionLength = SECTION2_SIZE (Section);
934     } else {
935       SectionLength = SECTION_SIZE (Section);
936     }
937     //
938     // SectionLength is adjusted it is 4 byte aligned.
939     // Go to the next section
940     //
941     SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
942     ASSERT (SectionLength != 0);
943     ParsedLength += SectionLength;
944     Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
945   }
946 
947   return EFI_NOT_FOUND;
948 }
949 
950 
951 /**
952   Searches for the next matching section within the specified file.
953 
954   @param PeiServices     An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
955   @param SectionType     Filter to find only sections of this type.
956   @param FileHandle      Pointer to the current file to search.
957   @param SectionData     A pointer to the discovered section, if successful.
958                          NULL if section not found
959 
960   @retval EFI_NOT_FOUND  The section was not found.
961   @retval EFI_SUCCESS    The section was found.
962 
963 **/
964 EFI_STATUS
965 EFIAPI
PeiFfsFindSectionData(IN CONST EFI_PEI_SERVICES ** PeiServices,IN EFI_SECTION_TYPE SectionType,IN EFI_PEI_FILE_HANDLE FileHandle,OUT VOID ** SectionData)966 PeiFfsFindSectionData (
967   IN CONST EFI_PEI_SERVICES    **PeiServices,
968   IN     EFI_SECTION_TYPE      SectionType,
969   IN     EFI_PEI_FILE_HANDLE   FileHandle,
970   OUT VOID                     **SectionData
971   )
972 {
973   PEI_CORE_FV_HANDLE           *CoreFvHandle;
974 
975   CoreFvHandle = FileHandleToVolume (FileHandle);
976   if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
977     return EFI_NOT_FOUND;
978   }
979 
980   return CoreFvHandle->FvPpi->FindSectionByType (CoreFvHandle->FvPpi, SectionType, FileHandle, SectionData);
981 }
982 
983 /**
984   Searches for the next matching section within the specified file.
985 
986   @param  PeiServices           An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
987   @param  SectionType           The value of the section type to find.
988   @param  SectionInstance       Section instance to find.
989   @param  FileHandle            Handle of the firmware file to search.
990   @param  SectionData           A pointer to the discovered section, if successful.
991   @param  AuthenticationStatus  A pointer to the authentication status for this section.
992 
993   @retval EFI_SUCCESS      The section was found.
994   @retval EFI_NOT_FOUND    The section was not found.
995 
996 **/
997 EFI_STATUS
998 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)999 PeiFfsFindSectionData3 (
1000   IN CONST EFI_PEI_SERVICES    **PeiServices,
1001   IN     EFI_SECTION_TYPE      SectionType,
1002   IN     UINTN                 SectionInstance,
1003   IN     EFI_PEI_FILE_HANDLE   FileHandle,
1004   OUT VOID                     **SectionData,
1005   OUT UINT32                   *AuthenticationStatus
1006   )
1007 {
1008   PEI_CORE_FV_HANDLE           *CoreFvHandle;
1009 
1010   CoreFvHandle = FileHandleToVolume (FileHandle);
1011   if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
1012     return EFI_NOT_FOUND;
1013   }
1014 
1015   if ((CoreFvHandle->FvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) &&
1016       (CoreFvHandle->FvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION)) {
1017     return CoreFvHandle->FvPpi->FindSectionByType2 (CoreFvHandle->FvPpi, SectionType, SectionInstance, FileHandle, SectionData, AuthenticationStatus);
1018   }
1019   //
1020   // The old FvPpi doesn't support to find section by section instance
1021   // and return authentication status, so return EFI_UNSUPPORTED.
1022   //
1023   return EFI_UNSUPPORTED;
1024 }
1025 
1026 /**
1027   Searches for the next matching file in the firmware volume.
1028 
1029   @param PeiServices     An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
1030   @param SearchType      Filter to find only files of this type.
1031                          Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
1032   @param FvHandle        Handle of firmware volume in which to search.
1033   @param FileHandle      On entry, points to the current handle from which to begin searching or NULL to start
1034                          at the beginning of the firmware volume. On exit, points the file handle of the next file
1035                          in the volume or NULL if there are no more files.
1036 
1037   @retval EFI_NOT_FOUND  The file was not found.
1038   @retval EFI_NOT_FOUND  The header checksum was not zero.
1039   @retval EFI_SUCCESS    The file was found.
1040 
1041 **/
1042 EFI_STATUS
1043 EFIAPI
PeiFfsFindNextFile(IN CONST EFI_PEI_SERVICES ** PeiServices,IN UINT8 SearchType,IN EFI_PEI_FV_HANDLE FvHandle,IN OUT EFI_PEI_FILE_HANDLE * FileHandle)1044 PeiFfsFindNextFile (
1045   IN CONST EFI_PEI_SERVICES      **PeiServices,
1046   IN UINT8                       SearchType,
1047   IN EFI_PEI_FV_HANDLE           FvHandle,
1048   IN OUT EFI_PEI_FILE_HANDLE     *FileHandle
1049   )
1050 {
1051   PEI_CORE_FV_HANDLE      *CoreFvHandle;
1052 
1053   CoreFvHandle = FvHandleToCoreHandle (FvHandle);
1054 
1055   //
1056   // To make backward compatiblity, if can not find corresponding the handle of FV
1057   // then treat FV as build-in FFS2/FFS3 format and memory mapped FV that FV handle is pointed
1058   // to the address of first byte of FV.
1059   //
1060   if ((CoreFvHandle == NULL) && FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
1061     return FindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL);
1062   }
1063 
1064   if ((CoreFvHandle == NULL) || CoreFvHandle->FvPpi == NULL) {
1065     return EFI_NOT_FOUND;
1066   }
1067 
1068   return CoreFvHandle->FvPpi->FindFileByType (CoreFvHandle->FvPpi, SearchType, FvHandle, FileHandle);
1069 }
1070 
1071 
1072 /**
1073   Search the firmware volumes by index
1074 
1075   @param PeiServices     An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
1076   @param Instance        This instance of the firmware volume to find. The value 0 is the Boot Firmware
1077                          Volume (BFV).
1078   @param VolumeHandle    On exit, points to the next volume handle or NULL if it does not exist.
1079 
1080   @retval EFI_INVALID_PARAMETER  VolumeHandle is NULL
1081   @retval EFI_NOT_FOUND          The volume was not found.
1082   @retval EFI_SUCCESS            The volume was found.
1083 
1084 **/
1085 EFI_STATUS
1086 EFIAPI
PeiFfsFindNextVolume(IN CONST EFI_PEI_SERVICES ** PeiServices,IN UINTN Instance,IN OUT EFI_PEI_FV_HANDLE * VolumeHandle)1087 PeiFfsFindNextVolume (
1088   IN CONST EFI_PEI_SERVICES         **PeiServices,
1089   IN     UINTN                      Instance,
1090   IN OUT EFI_PEI_FV_HANDLE          *VolumeHandle
1091   )
1092 {
1093   PEI_CORE_INSTANCE  *Private;
1094   PEI_CORE_FV_HANDLE *CoreFvHandle;
1095 
1096   if (VolumeHandle == NULL) {
1097     return EFI_INVALID_PARAMETER;
1098   }
1099 
1100   Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
1101 
1102   CoreFvHandle = FindNextCoreFvHandle (Private, Instance);
1103   if (CoreFvHandle == NULL) {
1104     *VolumeHandle = NULL;
1105     return EFI_NOT_FOUND;
1106   }
1107 
1108   *VolumeHandle = CoreFvHandle->FvHandle;
1109 
1110   return EFI_SUCCESS;
1111 }
1112 
1113 
1114 /**
1115   Find a file within a volume by its name.
1116 
1117   @param FileName        A pointer to the name of the file to find within the firmware volume.
1118   @param VolumeHandle    The firmware volume to search
1119   @param FileHandle      Upon exit, points to the found file's handle
1120                          or NULL if it could not be found.
1121 
1122   @retval EFI_SUCCESS            File was found.
1123   @retval EFI_NOT_FOUND          File was not found.
1124   @retval EFI_INVALID_PARAMETER  VolumeHandle or FileHandle or FileName was NULL.
1125 
1126 **/
1127 EFI_STATUS
1128 EFIAPI
PeiFfsFindFileByName(IN CONST EFI_GUID * FileName,IN EFI_PEI_FV_HANDLE VolumeHandle,OUT EFI_PEI_FILE_HANDLE * FileHandle)1129 PeiFfsFindFileByName (
1130   IN  CONST EFI_GUID        *FileName,
1131   IN  EFI_PEI_FV_HANDLE     VolumeHandle,
1132   OUT EFI_PEI_FILE_HANDLE   *FileHandle
1133   )
1134 {
1135   PEI_CORE_FV_HANDLE            *CoreFvHandle;
1136 
1137   if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {
1138     return EFI_INVALID_PARAMETER;
1139   }
1140 
1141   CoreFvHandle = FvHandleToCoreHandle (VolumeHandle);
1142   if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
1143     return EFI_NOT_FOUND;
1144   }
1145 
1146   return CoreFvHandle->FvPpi->FindFileByName (CoreFvHandle->FvPpi, FileName, &VolumeHandle, FileHandle);
1147 }
1148 
1149 /**
1150   Returns information about a specific file.
1151 
1152   @param FileHandle       Handle of the file.
1153   @param FileInfo         Upon exit, points to the file's information.
1154 
1155   @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
1156   @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file.
1157   @retval EFI_SUCCESS           File information returned.
1158 
1159 **/
1160 EFI_STATUS
1161 EFIAPI
PeiFfsGetFileInfo(IN EFI_PEI_FILE_HANDLE FileHandle,OUT EFI_FV_FILE_INFO * FileInfo)1162 PeiFfsGetFileInfo (
1163   IN EFI_PEI_FILE_HANDLE  FileHandle,
1164   OUT EFI_FV_FILE_INFO    *FileInfo
1165   )
1166 {
1167   PEI_CORE_FV_HANDLE          *CoreFvHandle;
1168 
1169   if ((FileHandle == NULL) || (FileInfo == NULL)) {
1170     return EFI_INVALID_PARAMETER;
1171   }
1172 
1173   //
1174   // Retrieve the FirmwareVolume which the file resides in.
1175   //
1176   CoreFvHandle = FileHandleToVolume (FileHandle);
1177   if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
1178     return EFI_INVALID_PARAMETER;
1179   }
1180 
1181   return CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, FileHandle, FileInfo);
1182 }
1183 
1184 /**
1185   Returns information about a specific file.
1186 
1187   @param FileHandle       Handle of the file.
1188   @param FileInfo         Upon exit, points to the file's information.
1189 
1190   @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
1191   @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file.
1192   @retval EFI_SUCCESS           File information returned.
1193 
1194 **/
1195 EFI_STATUS
1196 EFIAPI
PeiFfsGetFileInfo2(IN EFI_PEI_FILE_HANDLE FileHandle,OUT EFI_FV_FILE_INFO2 * FileInfo)1197 PeiFfsGetFileInfo2 (
1198   IN EFI_PEI_FILE_HANDLE  FileHandle,
1199   OUT EFI_FV_FILE_INFO2   *FileInfo
1200   )
1201 {
1202   PEI_CORE_FV_HANDLE          *CoreFvHandle;
1203 
1204   if ((FileHandle == NULL) || (FileInfo == NULL)) {
1205     return EFI_INVALID_PARAMETER;
1206   }
1207 
1208   //
1209   // Retrieve the FirmwareVolume which the file resides in.
1210   //
1211   CoreFvHandle = FileHandleToVolume (FileHandle);
1212   if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
1213     return EFI_INVALID_PARAMETER;
1214   }
1215 
1216   if ((CoreFvHandle->FvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) &&
1217       (CoreFvHandle->FvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION)) {
1218     return CoreFvHandle->FvPpi->GetFileInfo2 (CoreFvHandle->FvPpi, FileHandle, FileInfo);
1219   }
1220   //
1221   // The old FvPpi doesn't support to return file info with authentication status,
1222   // so return EFI_UNSUPPORTED.
1223   //
1224   return EFI_UNSUPPORTED;
1225 }
1226 
1227 /**
1228   Returns information about the specified volume.
1229 
1230   This function returns information about a specific firmware
1231   volume, including its name, type, attributes, starting address
1232   and size.
1233 
1234   @param VolumeHandle   Handle of the volume.
1235   @param VolumeInfo     Upon exit, points to the volume's information.
1236 
1237   @retval EFI_SUCCESS             Volume information returned.
1238   @retval EFI_INVALID_PARAMETER   If VolumeHandle does not represent a valid volume.
1239   @retval EFI_INVALID_PARAMETER   If VolumeHandle is NULL.
1240   @retval EFI_SUCCESS             Information successfully returned.
1241   @retval EFI_INVALID_PARAMETER   The volume designated by the VolumeHandle is not available.
1242 
1243 **/
1244 EFI_STATUS
1245 EFIAPI
PeiFfsGetVolumeInfo(IN EFI_PEI_FV_HANDLE VolumeHandle,OUT EFI_FV_INFO * VolumeInfo)1246 PeiFfsGetVolumeInfo (
1247   IN EFI_PEI_FV_HANDLE  VolumeHandle,
1248   OUT EFI_FV_INFO       *VolumeInfo
1249   )
1250 {
1251   PEI_CORE_FV_HANDLE                     *CoreHandle;
1252 
1253   if ((VolumeInfo == NULL) || (VolumeHandle == NULL)) {
1254     return EFI_INVALID_PARAMETER;
1255   }
1256 
1257   CoreHandle = FvHandleToCoreHandle (VolumeHandle);
1258 
1259   if ((CoreHandle == NULL) || (CoreHandle->FvPpi == NULL)) {
1260     return EFI_INVALID_PARAMETER;
1261   }
1262 
1263   return CoreHandle->FvPpi->GetVolumeInfo (CoreHandle->FvPpi, VolumeHandle, VolumeInfo);
1264 }
1265 
1266 /**
1267   Get Fv image from the FV type file, then install FV INFO(2) ppi, Build FV hob.
1268 
1269   @param PrivateData          PeiCore's private data structure
1270   @param ParentFvCoreHandle   Pointer of EFI_CORE_FV_HANDLE to parent Fv image that contain this Fv image.
1271   @param ParentFvFileHandle   File handle of a Fv type file that contain this Fv image.
1272 
1273   @retval EFI_NOT_FOUND         FV image can't be found.
1274   @retval EFI_SUCCESS           Successfully to process it.
1275   @retval EFI_OUT_OF_RESOURCES  Can not allocate page when aligning FV image
1276   @retval EFI_SECURITY_VIOLATION Image is illegal
1277   @retval Others                Can not find EFI_SECTION_FIRMWARE_VOLUME_IMAGE section
1278 
1279 **/
1280 EFI_STATUS
ProcessFvFile(IN PEI_CORE_INSTANCE * PrivateData,IN PEI_CORE_FV_HANDLE * ParentFvCoreHandle,IN EFI_PEI_FILE_HANDLE ParentFvFileHandle)1281 ProcessFvFile (
1282   IN  PEI_CORE_INSTANCE           *PrivateData,
1283   IN  PEI_CORE_FV_HANDLE          *ParentFvCoreHandle,
1284   IN  EFI_PEI_FILE_HANDLE         ParentFvFileHandle
1285   )
1286 {
1287   EFI_STATUS                    Status;
1288   EFI_FV_INFO                   ParentFvImageInfo;
1289   UINT32                        FvAlignment;
1290   VOID                          *NewFvBuffer;
1291   EFI_PEI_HOB_POINTERS          HobPtr;
1292   EFI_PEI_FIRMWARE_VOLUME_PPI   *ParentFvPpi;
1293   EFI_PEI_FV_HANDLE             ParentFvHandle;
1294   EFI_FIRMWARE_VOLUME_HEADER    *FvHeader;
1295   EFI_FV_FILE_INFO              FileInfo;
1296   UINT64                        FvLength;
1297   UINT32                        AuthenticationStatus;
1298 
1299   //
1300   // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
1301   // been extracted.
1302   //
1303   HobPtr.Raw = GetHobList ();
1304   while ((HobPtr.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobPtr.Raw)) != NULL) {
1305     if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)ParentFvFileHandle)->Name), &HobPtr.FirmwareVolume2->FileName)) {
1306       //
1307       // this FILE has been dispatched, it will not be dispatched again.
1308       //
1309       DEBUG ((EFI_D_INFO, "FV file %p has been dispatched!\r\n", ParentFvFileHandle));
1310       return EFI_SUCCESS;
1311     }
1312     HobPtr.Raw = GET_NEXT_HOB (HobPtr);
1313   }
1314 
1315   ParentFvHandle = ParentFvCoreHandle->FvHandle;
1316   ParentFvPpi    = ParentFvCoreHandle->FvPpi;
1317 
1318   //
1319   // Find FvImage in FvFile
1320   //
1321   AuthenticationStatus = 0;
1322   if ((ParentFvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) &&
1323       (ParentFvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION)) {
1324     Status = ParentFvPpi->FindSectionByType2 (
1325                             ParentFvPpi,
1326                             EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
1327                             0,
1328                             ParentFvFileHandle,
1329                             (VOID **)&FvHeader,
1330                             &AuthenticationStatus
1331                             );
1332   } else {
1333     Status = ParentFvPpi->FindSectionByType (
1334                             ParentFvPpi,
1335                             EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
1336                             ParentFvFileHandle,
1337                             (VOID **)&FvHeader
1338                             );
1339   }
1340   if (EFI_ERROR (Status)) {
1341     return Status;
1342   }
1343 
1344   Status = VerifyPeim (PrivateData, ParentFvHandle, ParentFvFileHandle, AuthenticationStatus);
1345   if (Status == EFI_SECURITY_VIOLATION) {
1346     return Status;
1347   }
1348 
1349   //
1350   // If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume
1351   // can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from
1352   // its initial linked location and maintain its alignment.
1353   //
1354   if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) {
1355     //
1356     // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.
1357     //
1358     FvAlignment = 1 << ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ALIGNMENT) >> 16);
1359     if (FvAlignment < 8) {
1360       FvAlignment = 8;
1361     }
1362 
1363     //
1364     // Check FvImage
1365     //
1366     if ((UINTN) FvHeader % FvAlignment != 0) {
1367       FvLength    = ReadUnaligned64 (&FvHeader->FvLength);
1368       NewFvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvLength), FvAlignment);
1369       if (NewFvBuffer == NULL) {
1370         return EFI_OUT_OF_RESOURCES;
1371       }
1372       CopyMem (NewFvBuffer, FvHeader, (UINTN) FvLength);
1373       FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) NewFvBuffer;
1374     }
1375   }
1376 
1377   Status = ParentFvPpi->GetVolumeInfo (ParentFvPpi, ParentFvHandle, &ParentFvImageInfo);
1378   ASSERT_EFI_ERROR (Status);
1379 
1380   Status = ParentFvPpi->GetFileInfo (ParentFvPpi, ParentFvFileHandle, &FileInfo);
1381   ASSERT_EFI_ERROR (Status);
1382 
1383   //
1384   // Install FvInfo(2) Ppi
1385   // NOTE: FvInfo2 must be installed before FvInfo so that recursive processing of encapsulated
1386   // FVs inherit the proper AuthenticationStatus.
1387   //
1388   PeiServicesInstallFvInfo2Ppi(
1389     &FvHeader->FileSystemGuid,
1390     (VOID**)FvHeader,
1391     (UINT32)FvHeader->FvLength,
1392     &ParentFvImageInfo.FvName,
1393     &FileInfo.FileName,
1394     AuthenticationStatus
1395     );
1396 
1397   PeiServicesInstallFvInfoPpi (
1398     &FvHeader->FileSystemGuid,
1399     (VOID**) FvHeader,
1400     (UINT32) FvHeader->FvLength,
1401     &ParentFvImageInfo.FvName,
1402     &FileInfo.FileName
1403     );
1404 
1405   //
1406   // Inform the extracted FvImage to Fv HOB consumer phase, i.e. DXE phase
1407   //
1408   BuildFvHob (
1409     (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,
1410     FvHeader->FvLength
1411     );
1412 
1413   //
1414   // Makes the encapsulated volume show up in DXE phase to skip processing of
1415   // encapsulated file again.
1416   //
1417   BuildFv2Hob (
1418     (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,
1419     FvHeader->FvLength,
1420     &ParentFvImageInfo.FvName,
1421     &FileInfo.FileName
1422     );
1423 
1424   return EFI_SUCCESS;
1425 }
1426 
1427 /**
1428   Process a firmware volume and create a volume handle.
1429 
1430   Create a volume handle from the information in the buffer. For
1431   memory-mapped firmware volumes, Buffer and BufferSize refer to
1432   the start of the firmware volume and the firmware volume size.
1433   For non memory-mapped firmware volumes, this points to a
1434   buffer which contains the necessary information for creating
1435   the firmware volume handle. Normally, these values are derived
1436   from the EFI_FIRMWARE_VOLUME_INFO_PPI.
1437 
1438 
1439   @param This                   Points to this instance of the
1440                                 EFI_PEI_FIRMWARE_VOLUME_PPI.
1441   @param Buffer                 Points to the start of the buffer.
1442   @param BufferSize             Size of the buffer.
1443   @param FvHandle               Points to the returned firmware volume
1444                                 handle. The firmware volume handle must
1445                                 be unique within the system.
1446 
1447   @retval EFI_SUCCESS           Firmware volume handle created.
1448   @retval EFI_VOLUME_CORRUPTED  Volume was corrupt.
1449 
1450 **/
1451 EFI_STATUS
1452 EFIAPI
PeiFfsFvPpiProcessVolume(IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI * This,IN VOID * Buffer,IN UINTN BufferSize,OUT EFI_PEI_FV_HANDLE * FvHandle)1453 PeiFfsFvPpiProcessVolume (
1454   IN  CONST  EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1455   IN  VOID                               *Buffer,
1456   IN  UINTN                              BufferSize,
1457   OUT EFI_PEI_FV_HANDLE                  *FvHandle
1458   )
1459 {
1460   EFI_STATUS          Status;
1461 
1462   ASSERT (FvHandle != NULL);
1463 
1464   if (Buffer == NULL) {
1465     return EFI_VOLUME_CORRUPTED;
1466   }
1467 
1468   //
1469   // The build-in EFI_PEI_FIRMWARE_VOLUME_PPI for FFS2/FFS3 support memory-mapped
1470   // FV image and the handle is pointed to Fv image's buffer.
1471   //
1472   *FvHandle = (EFI_PEI_FV_HANDLE) Buffer;
1473 
1474   //
1475   // Do verify for given FV buffer.
1476   //
1477   Status = VerifyFv ((EFI_FIRMWARE_VOLUME_HEADER*) Buffer);
1478   if (EFI_ERROR(Status)) {
1479     DEBUG ((EFI_D_ERROR, "Fail to verify FV which address is 0x%11p", Buffer));
1480     return EFI_VOLUME_CORRUPTED;
1481   }
1482 
1483   return EFI_SUCCESS;
1484 }
1485 
1486 /**
1487   Finds the next file of the specified type.
1488 
1489   This service enables PEI modules to discover additional firmware files.
1490   The FileHandle must be unique within the system.
1491 
1492   @param This           Points to this instance of the
1493                         EFI_PEI_FIRMWARE_VOLUME_PPI.
1494   @param SearchType     A filter to find only files of this type. Type
1495                         EFI_FV_FILETYPE_ALL causes no filtering to be
1496                         done.
1497   @param FvHandle       Handle of firmware volume in which to
1498                         search.
1499   @param FileHandle     Points to the current handle from which to
1500                         begin searching or NULL to start at the
1501                         beginning of the firmware volume. Updated
1502                         upon return to reflect the file found.
1503 
1504   @retval EFI_SUCCESS   The file was found.
1505   @retval EFI_NOT_FOUND The file was not found. FileHandle contains NULL.
1506 
1507 **/
1508 EFI_STATUS
1509 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)1510 PeiFfsFvPpiFindFileByType (
1511   IN CONST  EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1512   IN        EFI_FV_FILETYPE             SearchType,
1513   IN        EFI_PEI_FV_HANDLE           FvHandle,
1514   IN OUT    EFI_PEI_FILE_HANDLE         *FileHandle
1515   )
1516 {
1517   return FindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL);
1518 }
1519 
1520 /**
1521   Find a file within a volume by its name.
1522 
1523   This service searches for files with a specific name, within
1524   either the specified firmware volume or all firmware volumes.
1525 
1526   @param This                   Points to this instance of the
1527                                 EFI_PEI_FIRMWARE_VOLUME_PPI.
1528   @param FileName               A pointer to the name of the file to find
1529                                 within the firmware volume.
1530   @param FvHandle               Upon entry, the pointer to the firmware
1531                                 volume to search or NULL if all firmware
1532                                 volumes should be searched. Upon exit, the
1533                                 actual firmware volume in which the file was
1534                                 found.
1535   @param FileHandle             Upon exit, points to the found file's
1536                                 handle or NULL if it could not be found.
1537 
1538   @retval EFI_SUCCESS           File was found.
1539   @retval EFI_NOT_FOUND         File was not found.
1540   @retval EFI_INVALID_PARAMETER FvHandle or FileHandle or
1541                                 FileName was NULL.
1542 
1543 
1544 **/
1545 EFI_STATUS
1546 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)1547 PeiFfsFvPpiFindFileByName (
1548   IN  CONST  EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1549   IN  CONST  EFI_GUID                    *FileName,
1550   IN  EFI_PEI_FV_HANDLE                  *FvHandle,
1551   OUT EFI_PEI_FILE_HANDLE                *FileHandle
1552   )
1553 {
1554   EFI_STATUS        Status;
1555   PEI_CORE_INSTANCE *PrivateData;
1556   UINTN             Index;
1557 
1558   if ((FvHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {
1559     return EFI_INVALID_PARAMETER;
1560   }
1561 
1562   if (*FvHandle != NULL) {
1563     Status = FindFileEx (*FvHandle, FileName, 0, FileHandle, NULL);
1564     if (Status == EFI_NOT_FOUND) {
1565       *FileHandle = NULL;
1566     }
1567   } else {
1568     //
1569     // If *FvHandle = NULL, so search all FV for given filename
1570     //
1571     Status = EFI_NOT_FOUND;
1572 
1573     PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer());
1574     for (Index = 0; Index < PrivateData->FvCount; Index ++) {
1575       //
1576       // Only search the FV which is associated with a EFI_PEI_FIRMWARE_VOLUME_PPI instance.
1577       //
1578       if (PrivateData->Fv[Index].FvPpi != NULL) {
1579         Status = FindFileEx (PrivateData->Fv[Index].FvHandle, FileName, 0, FileHandle, NULL);
1580         if (!EFI_ERROR (Status)) {
1581           *FvHandle = PrivateData->Fv[Index].FvHandle;
1582           break;
1583         }
1584       }
1585     }
1586   }
1587 
1588   return Status;
1589 }
1590 
1591 /**
1592   Returns information about a specific file.
1593 
1594   This function returns information about a specific
1595   file, including its file name, type, attributes, starting
1596   address and size.
1597 
1598   @param This                     Points to this instance of the
1599                                   EFI_PEI_FIRMWARE_VOLUME_PPI.
1600   @param FileHandle               Handle of the file.
1601   @param FileInfo                 Upon exit, points to the file's
1602                                   information.
1603 
1604   @retval EFI_SUCCESS             File information returned.
1605   @retval EFI_INVALID_PARAMETER   If FileHandle does not
1606                                   represent a valid file.
1607   @retval EFI_INVALID_PARAMETER   If FileInfo is NULL.
1608 
1609 **/
1610 EFI_STATUS
1611 EFIAPI
PeiFfsFvPpiGetFileInfo(IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI * This,IN EFI_PEI_FILE_HANDLE FileHandle,OUT EFI_FV_FILE_INFO * FileInfo)1612 PeiFfsFvPpiGetFileInfo (
1613   IN  CONST EFI_PEI_FIRMWARE_VOLUME_PPI   *This,
1614   IN        EFI_PEI_FILE_HANDLE           FileHandle,
1615   OUT       EFI_FV_FILE_INFO              *FileInfo
1616   )
1617 {
1618   UINT8                       FileState;
1619   UINT8                       ErasePolarity;
1620   EFI_FFS_FILE_HEADER         *FileHeader;
1621   PEI_CORE_FV_HANDLE          *CoreFvHandle;
1622   PEI_FW_VOL_INSTANCE         *FwVolInstance;
1623 
1624   if ((FileHandle == NULL) || (FileInfo == NULL)) {
1625     return EFI_INVALID_PARAMETER;
1626   }
1627 
1628   //
1629   // Retrieve the FirmwareVolume which the file resides in.
1630   //
1631   CoreFvHandle = FileHandleToVolume (FileHandle);
1632   if (CoreFvHandle == NULL) {
1633     return EFI_INVALID_PARAMETER;
1634   }
1635 
1636   FwVolInstance = PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This);
1637 
1638   if ((CoreFvHandle->FvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) != 0) {
1639     ErasePolarity = 1;
1640   } else {
1641     ErasePolarity = 0;
1642   }
1643 
1644   //
1645   // Get FileState which is the highest bit of the State
1646   //
1647   FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle);
1648 
1649   switch (FileState) {
1650     case EFI_FILE_DATA_VALID:
1651     case EFI_FILE_MARKED_FOR_UPDATE:
1652       break;
1653     default:
1654       return EFI_INVALID_PARAMETER;
1655     }
1656 
1657   FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;
1658   if (IS_FFS_FILE2 (FileHeader)) {
1659     ASSERT (FFS_FILE2_SIZE (FileHeader) > 0x00FFFFFF);
1660     if (!FwVolInstance->IsFfs3Fv) {
1661       DEBUG ((EFI_D_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FileHeader->Name));
1662       return EFI_INVALID_PARAMETER;
1663     }
1664     FileInfo->BufferSize = FFS_FILE2_SIZE (FileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
1665     FileInfo->Buffer = (UINT8 *) FileHeader + sizeof (EFI_FFS_FILE_HEADER2);
1666   } else {
1667     FileInfo->BufferSize = FFS_FILE_SIZE (FileHeader) - sizeof (EFI_FFS_FILE_HEADER);
1668     FileInfo->Buffer = (UINT8 *) FileHeader + sizeof (EFI_FFS_FILE_HEADER);
1669   }
1670   CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID));
1671   FileInfo->FileType = FileHeader->Type;
1672   FileInfo->FileAttributes = FfsAttributes2FvFileAttributes (FileHeader->Attributes);
1673   if ((CoreFvHandle->FvHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) {
1674     FileInfo->FileAttributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED;
1675   }
1676   return EFI_SUCCESS;
1677 }
1678 
1679 /**
1680   Returns information about a specific file.
1681 
1682   This function returns information about a specific
1683   file, including its file name, type, attributes, starting
1684   address, size and authentication status.
1685 
1686   @param This                     Points to this instance of the
1687                                   EFI_PEI_FIRMWARE_VOLUME_PPI.
1688   @param FileHandle               Handle of the file.
1689   @param FileInfo                 Upon exit, points to the file's
1690                                   information.
1691 
1692   @retval EFI_SUCCESS             File information returned.
1693   @retval EFI_INVALID_PARAMETER   If FileHandle does not
1694                                   represent a valid file.
1695   @retval EFI_INVALID_PARAMETER   If FileInfo is NULL.
1696 
1697 **/
1698 EFI_STATUS
1699 EFIAPI
PeiFfsFvPpiGetFileInfo2(IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI * This,IN EFI_PEI_FILE_HANDLE FileHandle,OUT EFI_FV_FILE_INFO2 * FileInfo)1700 PeiFfsFvPpiGetFileInfo2 (
1701   IN  CONST EFI_PEI_FIRMWARE_VOLUME_PPI   *This,
1702   IN        EFI_PEI_FILE_HANDLE           FileHandle,
1703   OUT       EFI_FV_FILE_INFO2             *FileInfo
1704   )
1705 {
1706   EFI_STATUS                  Status;
1707   PEI_CORE_FV_HANDLE          *CoreFvHandle;
1708 
1709   if ((FileHandle == NULL) || (FileInfo == NULL)) {
1710     return EFI_INVALID_PARAMETER;
1711   }
1712 
1713   //
1714   // Retrieve the FirmwareVolume which the file resides in.
1715   //
1716   CoreFvHandle = FileHandleToVolume (FileHandle);
1717   if (CoreFvHandle == NULL) {
1718     return EFI_INVALID_PARAMETER;
1719   }
1720 
1721   Status = PeiFfsFvPpiGetFileInfo (This, FileHandle, (EFI_FV_FILE_INFO *) FileInfo);
1722   if (!EFI_ERROR (Status)) {
1723     FileInfo->AuthenticationStatus = CoreFvHandle->AuthenticationStatus;
1724   }
1725 
1726   return Status;
1727 }
1728 
1729 /**
1730   This function returns information about the firmware volume.
1731 
1732   @param This                     Points to this instance of the
1733                                   EFI_PEI_FIRMWARE_VOLUME_PPI.
1734   @param FvHandle                 Handle to the firmware handle.
1735   @param VolumeInfo               Points to the returned firmware volume
1736                                   information.
1737 
1738   @retval EFI_SUCCESS             Information returned successfully.
1739   @retval EFI_INVALID_PARAMETER   FvHandle does not indicate a valid
1740                                   firmware volume or VolumeInfo is NULL.
1741 
1742 **/
1743 EFI_STATUS
1744 EFIAPI
PeiFfsFvPpiGetVolumeInfo(IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI * This,IN EFI_PEI_FV_HANDLE FvHandle,OUT EFI_FV_INFO * VolumeInfo)1745 PeiFfsFvPpiGetVolumeInfo (
1746   IN  CONST  EFI_PEI_FIRMWARE_VOLUME_PPI   *This,
1747   IN  EFI_PEI_FV_HANDLE                    FvHandle,
1748   OUT EFI_FV_INFO                          *VolumeInfo
1749   )
1750 {
1751   EFI_FIRMWARE_VOLUME_HEADER             FwVolHeader;
1752   EFI_FIRMWARE_VOLUME_EXT_HEADER         *FwVolExHeaderInfo;
1753 
1754   if ((VolumeInfo == NULL) || (FvHandle == NULL)) {
1755     return EFI_INVALID_PARAMETER;
1756   }
1757 
1758   //
1759   // VolumeHandle may not align at 8 byte,
1760   // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte.
1761   // So, Copy FvHeader into the local FvHeader structure.
1762   //
1763   CopyMem (&FwVolHeader, FvHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
1764 
1765   //
1766   // Check Fv Image Signature
1767   //
1768   if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {
1769     return EFI_INVALID_PARAMETER;
1770   }
1771 
1772   ZeroMem (VolumeInfo, sizeof (EFI_FV_INFO));
1773   VolumeInfo->FvAttributes  = FwVolHeader.Attributes;
1774   VolumeInfo->FvStart       = (VOID *) FvHandle;
1775   VolumeInfo->FvSize        = FwVolHeader.FvLength;
1776   CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID));
1777 
1778   if (FwVolHeader.ExtHeaderOffset != 0) {
1779     FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)FvHandle) + FwVolHeader.ExtHeaderOffset);
1780     CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID));
1781   }
1782 
1783   return EFI_SUCCESS;
1784 }
1785 
1786 /**
1787   Find the next matching section in the firmware file.
1788 
1789   This service enables PEI modules to discover sections
1790   of a given type within a valid file.
1791 
1792   @param This             Points to this instance of the
1793                           EFI_PEI_FIRMWARE_VOLUME_PPI.
1794   @param SearchType       A filter to find only sections of this
1795                           type.
1796   @param FileHandle       Handle of firmware file in which to
1797                           search.
1798   @param SectionData      Updated upon return to point to the
1799                           section found.
1800 
1801   @retval EFI_SUCCESS     Section was found.
1802   @retval EFI_NOT_FOUND   Section of the specified type was not
1803                           found. SectionData contains NULL.
1804 **/
1805 EFI_STATUS
1806 EFIAPI
PeiFfsFvPpiFindSectionByType(IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI * This,IN EFI_SECTION_TYPE SearchType,IN EFI_PEI_FILE_HANDLE FileHandle,OUT VOID ** SectionData)1807 PeiFfsFvPpiFindSectionByType (
1808   IN  CONST EFI_PEI_FIRMWARE_VOLUME_PPI    *This,
1809   IN        EFI_SECTION_TYPE               SearchType,
1810   IN        EFI_PEI_FILE_HANDLE            FileHandle,
1811   OUT VOID                                 **SectionData
1812   )
1813 {
1814   UINT32 AuthenticationStatus;
1815   return PeiFfsFvPpiFindSectionByType2 (This, SearchType, 0, FileHandle, SectionData, &AuthenticationStatus);
1816 }
1817 
1818 /**
1819   Find the next matching section in the firmware file.
1820 
1821   This service enables PEI modules to discover sections
1822   of a given instance and type within a valid file.
1823 
1824   @param This                   Points to this instance of the
1825                                 EFI_PEI_FIRMWARE_VOLUME_PPI.
1826   @param SearchType             A filter to find only sections of this
1827                                 type.
1828   @param SearchInstance         A filter to find the specific instance
1829                                 of sections.
1830   @param FileHandle             Handle of firmware file in which to
1831                                 search.
1832   @param SectionData            Updated upon return to point to the
1833                                 section found.
1834   @param AuthenticationStatus   Updated upon return to point to the
1835                                 authentication status for this section.
1836 
1837   @retval EFI_SUCCESS     Section was found.
1838   @retval EFI_NOT_FOUND   Section of the specified type was not
1839                           found. SectionData contains NULL.
1840 **/
1841 EFI_STATUS
1842 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)1843 PeiFfsFvPpiFindSectionByType2 (
1844   IN  CONST EFI_PEI_FIRMWARE_VOLUME_PPI    *This,
1845   IN        EFI_SECTION_TYPE               SearchType,
1846   IN        UINTN                          SearchInstance,
1847   IN        EFI_PEI_FILE_HANDLE            FileHandle,
1848   OUT VOID                                 **SectionData,
1849   OUT UINT32                               *AuthenticationStatus
1850   )
1851 {
1852   EFI_STATUS                              Status;
1853   EFI_FFS_FILE_HEADER                     *FfsFileHeader;
1854   UINT32                                  FileSize;
1855   EFI_COMMON_SECTION_HEADER               *Section;
1856   PEI_FW_VOL_INSTANCE                     *FwVolInstance;
1857   PEI_CORE_FV_HANDLE                      *CoreFvHandle;
1858   UINTN                                   Instance;
1859   UINT32                                  ExtractedAuthenticationStatus;
1860 
1861   if (SectionData == NULL) {
1862     return EFI_NOT_FOUND;
1863   }
1864 
1865   FwVolInstance = PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This);
1866 
1867   //
1868   // Retrieve the FirmwareVolume which the file resides in.
1869   //
1870   CoreFvHandle = FileHandleToVolume (FileHandle);
1871   if (CoreFvHandle == NULL) {
1872     return EFI_NOT_FOUND;
1873   }
1874 
1875   FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);
1876 
1877   if (IS_FFS_FILE2 (FfsFileHeader)) {
1878     ASSERT (FFS_FILE2_SIZE (FfsFileHeader) > 0x00FFFFFF);
1879     if (!FwVolInstance->IsFfs3Fv) {
1880       DEBUG ((EFI_D_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));
1881       return EFI_NOT_FOUND;
1882     }
1883     Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
1884     FileSize = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
1885   } else {
1886     Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));
1887     FileSize = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
1888   }
1889 
1890   Instance = SearchInstance + 1;
1891   ExtractedAuthenticationStatus = 0;
1892   Status = ProcessSection (
1893              GetPeiServicesTablePointer (),
1894              SearchType,
1895              &Instance,
1896              Section,
1897              FileSize,
1898              SectionData,
1899              &ExtractedAuthenticationStatus,
1900              FwVolInstance->IsFfs3Fv
1901              );
1902   if (!EFI_ERROR (Status)) {
1903     //
1904     // Inherit the authentication status.
1905     //
1906     *AuthenticationStatus = ExtractedAuthenticationStatus | CoreFvHandle->AuthenticationStatus;
1907   }
1908   return Status;
1909 }
1910 
1911 /**
1912   Convert the handle of FV to pointer of corresponding PEI_CORE_FV_HANDLE.
1913 
1914   @param FvHandle   The handle of a FV.
1915 
1916   @retval NULL if can not find.
1917   @return Pointer of corresponding PEI_CORE_FV_HANDLE.
1918 **/
1919 PEI_CORE_FV_HANDLE *
FvHandleToCoreHandle(IN EFI_PEI_FV_HANDLE FvHandle)1920 FvHandleToCoreHandle (
1921   IN EFI_PEI_FV_HANDLE  FvHandle
1922   )
1923 {
1924   UINTN             Index;
1925   PEI_CORE_INSTANCE *PrivateData;
1926 
1927   PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer());
1928   for (Index = 0; Index < PrivateData->FvCount; Index ++) {
1929     if (FvHandle == PrivateData->Fv[Index].FvHandle) {
1930       return &PrivateData->Fv[Index];
1931     }
1932   }
1933 
1934   return NULL;
1935 }
1936 
1937 /**
1938   Get instance of PEI_CORE_FV_HANDLE for next volume according to given index.
1939 
1940   This routine also will install FvInfo ppi for FV hob in PI ways.
1941 
1942   @param Private    Pointer of PEI_CORE_INSTANCE
1943   @param Instance   The index of FV want to be searched.
1944 
1945   @return Instance of PEI_CORE_FV_HANDLE.
1946 **/
1947 PEI_CORE_FV_HANDLE *
FindNextCoreFvHandle(IN PEI_CORE_INSTANCE * Private,IN UINTN Instance)1948 FindNextCoreFvHandle (
1949   IN PEI_CORE_INSTANCE  *Private,
1950   IN UINTN              Instance
1951   )
1952 {
1953   UINTN                    Index;
1954   BOOLEAN                  Match;
1955   EFI_HOB_FIRMWARE_VOLUME  *FvHob;
1956 
1957   //
1958   // Handle Framework FvHob and Install FvInfo Ppi for it.
1959   //
1960   if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
1961     //
1962     // Loop to search the wanted FirmwareVolume which supports FFS
1963     //
1964     FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetFirstHob (EFI_HOB_TYPE_FV);
1965     while (FvHob != NULL) {
1966       //
1967       // Search whether FvHob has been installed into PeiCore's FV database.
1968       // If found, no need install new FvInfoPpi for it.
1969       //
1970       for (Index = 0, Match = FALSE; Index < Private->FvCount; Index++) {
1971         if ((EFI_PEI_FV_HANDLE)(UINTN)FvHob->BaseAddress == Private->Fv[Index].FvHeader) {
1972           Match = TRUE;
1973           break;
1974         }
1975       }
1976 
1977       //
1978       // Search whether FvHob has been cached into PeiCore's Unknown FV database.
1979       // If found, no need install new FvInfoPpi for it.
1980       //
1981       if (!Match) {
1982         for (Index = 0; Index < Private->UnknownFvInfoCount; Index ++) {
1983           if ((UINTN)FvHob->BaseAddress == (UINTN)Private->UnknownFvInfo[Index].FvInfo) {
1984             Match = TRUE;
1985             break;
1986           }
1987         }
1988       }
1989 
1990       //
1991       // If the Fv in FvHob has not been installed into PeiCore's FV database and has
1992       // not been cached into PeiCore's Unknown FV database, install a new FvInfoPpi
1993       // for it then PeiCore will dispatch it in callback of FvInfoPpi.
1994       //
1995       if (!Match) {
1996         PeiServicesInstallFvInfoPpi (
1997           &(((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvHob->BaseAddress)->FileSystemGuid),
1998           (VOID *)(UINTN)FvHob->BaseAddress,
1999           (UINT32)FvHob->Length,
2000           NULL,
2001           NULL
2002           );
2003       }
2004 
2005       FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetNextHob (EFI_HOB_TYPE_FV, (VOID *)((UINTN)FvHob + FvHob->Header.HobLength));
2006     }
2007   }
2008 
2009   ASSERT (Private->FvCount <= PcdGet32 (PcdPeiCoreMaxFvSupported));
2010   if (Instance >= Private->FvCount) {
2011     return NULL;
2012   }
2013 
2014   return &Private->Fv[Instance];
2015 }
2016 
2017 /**
2018   After PeiCore image is shadowed into permanent memory, all build-in FvPpi should
2019   be re-installed with the instance in permanent memory and all cached FvPpi pointers in
2020   PrivateData->Fv[] array should be fixed up to be pointed to the one in permenant
2021   memory.
2022 
2023   @param PrivateData   Pointer to PEI_CORE_INSTANCE.
2024 **/
2025 VOID
PeiReinitializeFv(IN PEI_CORE_INSTANCE * PrivateData)2026 PeiReinitializeFv (
2027   IN  PEI_CORE_INSTANCE           *PrivateData
2028   )
2029 {
2030   VOID                    *OldFfsFvPpi;
2031   EFI_PEI_PPI_DESCRIPTOR  *OldDescriptor;
2032   UINTN                   Index;
2033   EFI_STATUS              Status;
2034 
2035   //
2036   // Locate old build-in Ffs2 EFI_PEI_FIRMWARE_VOLUME_PPI which
2037   // in flash.
2038   //
2039   Status = PeiServicesLocatePpi (
2040             &gEfiFirmwareFileSystem2Guid,
2041             0,
2042             &OldDescriptor,
2043             &OldFfsFvPpi
2044             );
2045   ASSERT_EFI_ERROR (Status);
2046 
2047   //
2048   // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs2
2049   // which is shadowed from flash to permanent memory within PeiCore image.
2050   //
2051   Status = PeiServicesReInstallPpi (OldDescriptor, &mPeiFfs2FvPpiList);
2052   ASSERT_EFI_ERROR (Status);
2053 
2054   //
2055   // Fixup all FvPpi pointers for the implementation in flash to permanent memory.
2056   //
2057   for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {
2058     if (PrivateData->Fv[Index].FvPpi == OldFfsFvPpi) {
2059       PrivateData->Fv[Index].FvPpi = &mPeiFfs2FwVol.Fv;
2060     }
2061   }
2062 
2063   //
2064   // Locate old build-in Ffs3 EFI_PEI_FIRMWARE_VOLUME_PPI which
2065   // in flash.
2066   //
2067   Status = PeiServicesLocatePpi (
2068              &gEfiFirmwareFileSystem3Guid,
2069              0,
2070              &OldDescriptor,
2071              &OldFfsFvPpi
2072              );
2073   ASSERT_EFI_ERROR (Status);
2074 
2075   //
2076   // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs3
2077   // which is shadowed from flash to permanent memory within PeiCore image.
2078   //
2079   Status = PeiServicesReInstallPpi (OldDescriptor, &mPeiFfs3FvPpiList);
2080   ASSERT_EFI_ERROR (Status);
2081 
2082   //
2083   // Fixup all FvPpi pointers for the implementation in flash to permanent memory.
2084   //
2085   for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {
2086     if (PrivateData->Fv[Index].FvPpi == OldFfsFvPpi) {
2087       PrivateData->Fv[Index].FvPpi = &mPeiFfs3FwVol.Fv;
2088     }
2089   }
2090 }
2091 
2092 /**
2093   Report the information for a new discoveried FV in unknown third-party format.
2094 
2095   If the EFI_PEI_FIRMWARE_VOLUME_PPI has not been installed for third-party FV format, but
2096   the FV in this format has been discoveried, then this FV's information will be cached into
2097   PEI_CORE_INSTANCE's UnknownFvInfo array.
2098   Also a notification would be installed for unknown third-party FV format guid, if EFI_PEI_FIRMWARE_VOLUME_PPI
2099   is installed later by platform's PEIM, the original unknown third-party FV will be processed by
2100   using new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
2101 
2102   @param PrivateData  Point to instance of PEI_CORE_INSTANCE
2103   @param FvInfo2Ppi   Point to FvInfo2 PPI.
2104 
2105   @retval EFI_OUT_OF_RESOURCES  The FV info array in PEI_CORE_INSTANCE has no more spaces.
2106   @retval EFI_SUCCESS           Success to add the information for unknown FV.
2107 **/
2108 EFI_STATUS
AddUnknownFormatFvInfo(IN PEI_CORE_INSTANCE * PrivateData,IN EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI * FvInfo2Ppi)2109 AddUnknownFormatFvInfo (
2110   IN PEI_CORE_INSTANCE                  *PrivateData,
2111   IN EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI  *FvInfo2Ppi
2112   )
2113 {
2114   PEI_CORE_UNKNOW_FORMAT_FV_INFO    *NewUnknownFv;
2115 
2116   if (PrivateData->UnknownFvInfoCount + 1 >= PcdGet32 (PcdPeiCoreMaxFvSupported)) {
2117     return EFI_OUT_OF_RESOURCES;
2118   }
2119 
2120   NewUnknownFv = &PrivateData->UnknownFvInfo[PrivateData->UnknownFvInfoCount];
2121   PrivateData->UnknownFvInfoCount ++;
2122 
2123   CopyGuid (&NewUnknownFv->FvFormat, &FvInfo2Ppi->FvFormat);
2124   NewUnknownFv->FvInfo     = FvInfo2Ppi->FvInfo;
2125   NewUnknownFv->FvInfoSize = FvInfo2Ppi->FvInfoSize;
2126   NewUnknownFv->AuthenticationStatus = FvInfo2Ppi->AuthenticationStatus;
2127   NewUnknownFv->NotifyDescriptor.Flags  = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
2128   NewUnknownFv->NotifyDescriptor.Guid   = &NewUnknownFv->FvFormat;
2129   NewUnknownFv->NotifyDescriptor.Notify = ThirdPartyFvPpiNotifyCallback;
2130 
2131   PeiServicesNotifyPpi (&NewUnknownFv->NotifyDescriptor);
2132   return EFI_SUCCESS;
2133 }
2134 
2135 /**
2136   Find the FV information according to third-party FV format guid.
2137 
2138   This routine also will remove the FV information found by given FV format guid from
2139   PrivateData->UnknownFvInfo[].
2140 
2141   @param PrivateData      Point to instance of PEI_CORE_INSTANCE
2142   @param Format           Point to given FV format guid
2143   @param FvInfo           On return, the pointer of FV information buffer
2144   @param FvInfoSize       On return, the size of FV information buffer.
2145   @param AuthenticationStatus On return, the authentication status of FV information buffer.
2146 
2147   @retval EFI_NOT_FOUND  The FV is not found for new installed EFI_PEI_FIRMWARE_VOLUME_PPI
2148   @retval EFI_SUCCESS    Success to find a FV which could be processed by new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
2149 **/
2150 EFI_STATUS
FindUnknownFormatFvInfo(IN PEI_CORE_INSTANCE * PrivateData,IN EFI_GUID * Format,OUT VOID ** FvInfo,OUT UINT32 * FvInfoSize,OUT UINT32 * AuthenticationStatus)2151 FindUnknownFormatFvInfo (
2152   IN  PEI_CORE_INSTANCE *PrivateData,
2153   IN  EFI_GUID          *Format,
2154   OUT VOID              **FvInfo,
2155   OUT UINT32            *FvInfoSize,
2156   OUT UINT32            *AuthenticationStatus
2157   )
2158 {
2159   UINTN Index;
2160   UINTN Index2;
2161 
2162   Index = 0;
2163   for (; Index < PrivateData->UnknownFvInfoCount; Index ++) {
2164     if (CompareGuid (Format, &PrivateData->UnknownFvInfo[Index].FvFormat)) {
2165       break;
2166     }
2167   }
2168 
2169   if (Index == PrivateData->UnknownFvInfoCount) {
2170     return EFI_NOT_FOUND;
2171   }
2172 
2173   *FvInfo     = PrivateData->UnknownFvInfo[Index].FvInfo;
2174   *FvInfoSize = PrivateData->UnknownFvInfo[Index].FvInfoSize;
2175   *AuthenticationStatus = PrivateData->UnknownFvInfo[Index].AuthenticationStatus;
2176 
2177   //
2178   // Remove an entry from UnknownFvInfo array.
2179   //
2180   Index2 = Index + 1;
2181   for (;Index2 < PrivateData->UnknownFvInfoCount; Index2 ++, Index ++) {
2182     CopyMem (&PrivateData->UnknownFvInfo[Index], &PrivateData->UnknownFvInfo[Index2], sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO));
2183   }
2184   PrivateData->UnknownFvInfoCount --;
2185   return EFI_SUCCESS;
2186 }
2187 
2188 /**
2189   Notification callback function for EFI_PEI_FIRMWARE_VOLUME_PPI.
2190 
2191   When a EFI_PEI_FIRMWARE_VOLUME_PPI is installed to support new FV format, this
2192   routine is called to process all discoveried FVs in this format.
2193 
2194   @param PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
2195   @param NotifyDescriptor  Address of the notification descriptor data structure.
2196   @param Ppi               Address of the PPI that was installed.
2197 
2198   @retval EFI_SUCCESS  The notification callback is processed correctly.
2199 **/
2200 EFI_STATUS
2201 EFIAPI
ThirdPartyFvPpiNotifyCallback(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_NOTIFY_DESCRIPTOR * NotifyDescriptor,IN VOID * Ppi)2202 ThirdPartyFvPpiNotifyCallback (
2203   IN EFI_PEI_SERVICES              **PeiServices,
2204   IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,
2205   IN VOID                          *Ppi
2206   )
2207 {
2208   PEI_CORE_INSTANCE            *PrivateData;
2209   EFI_PEI_FIRMWARE_VOLUME_PPI  *FvPpi;
2210   VOID                         *FvInfo;
2211   UINT32                       FvInfoSize;
2212   UINT32                       AuthenticationStatus;
2213   EFI_STATUS                   Status;
2214   EFI_PEI_FV_HANDLE            FvHandle;
2215   BOOLEAN                      IsProcessed;
2216   UINTN                        FvIndex;
2217   EFI_PEI_FILE_HANDLE          FileHandle;
2218   VOID                         *DepexData;
2219 
2220   PrivateData  = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
2221   FvPpi = (EFI_PEI_FIRMWARE_VOLUME_PPI*) Ppi;
2222 
2223   do {
2224     Status = FindUnknownFormatFvInfo (PrivateData, NotifyDescriptor->Guid, &FvInfo, &FvInfoSize, &AuthenticationStatus);
2225     if (EFI_ERROR (Status)) {
2226       return EFI_SUCCESS;
2227     }
2228 
2229     //
2230     // Process new found FV and get FV handle.
2231     //
2232     Status = FvPpi->ProcessVolume (FvPpi, FvInfo, FvInfoSize, &FvHandle);
2233     if (EFI_ERROR (Status)) {
2234       DEBUG ((EFI_D_ERROR, "Fail to process the FV 0x%p, FV may be corrupted!\n", FvInfo));
2235       continue;
2236     }
2237 
2238     //
2239     // Check whether the FV has already been processed.
2240     //
2241     IsProcessed = FALSE;
2242     for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {
2243       if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {
2244         DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvInfo));
2245         IsProcessed = TRUE;
2246         break;
2247       }
2248     }
2249 
2250     if (IsProcessed) {
2251       continue;
2252     }
2253 
2254     if (PrivateData->FvCount >= PcdGet32 (PcdPeiCoreMaxFvSupported)) {
2255       DEBUG ((EFI_D_ERROR, "The number of Fv Images (%d) exceed the max supported FVs (%d) in Pei", PrivateData->FvCount + 1, PcdGet32 (PcdPeiCoreMaxFvSupported)));
2256       DEBUG ((EFI_D_ERROR, "PcdPeiCoreMaxFvSupported value need be reconfigurated in DSC"));
2257       ASSERT (FALSE);
2258     }
2259 
2260     //
2261     // Update internal PEI_CORE_FV array.
2262     //
2263     PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) FvInfo;
2264     PrivateData->Fv[PrivateData->FvCount].FvPpi    = FvPpi;
2265     PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;
2266     PrivateData->Fv[PrivateData->FvCount].AuthenticationStatus = AuthenticationStatus;
2267     DEBUG ((
2268       EFI_D_INFO,
2269       "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
2270       (UINT32) PrivateData->FvCount,
2271       (VOID *) FvInfo,
2272       FvInfoSize,
2273       FvHandle
2274       ));
2275     PrivateData->FvCount ++;
2276 
2277     //
2278     // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
2279     //
2280     FileHandle = NULL;
2281     do {
2282       Status = FvPpi->FindFileByType (
2283                         FvPpi,
2284                         EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
2285                         FvHandle,
2286                         &FileHandle
2287                        );
2288       if (!EFI_ERROR (Status)) {
2289         Status = FvPpi->FindSectionByType (
2290                           FvPpi,
2291                           EFI_SECTION_PEI_DEPEX,
2292                           FileHandle,
2293                           (VOID**)&DepexData
2294                           );
2295         if (!EFI_ERROR (Status)) {
2296           if (!PeimDispatchReadiness (PeiServices, DepexData)) {
2297             //
2298             // Dependency is not satisfied.
2299             //
2300             continue;
2301           }
2302         }
2303 
2304         DEBUG ((EFI_D_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, PrivateData->FvCount - 1, FvHandle));
2305         ProcessFvFile (PrivateData, &PrivateData->Fv[PrivateData->FvCount - 1], FileHandle);
2306       }
2307     } while (FileHandle != NULL);
2308   } while (TRUE);
2309 }
2310