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