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