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