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