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