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