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