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