]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/FwVol/FwVol.c
3da90f95312d0172dac6721317e173859115a20c
[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 //
1456 // Build FV3 HOB with authentication status to be propagated to DXE.
1457 //
1458 BuildFv3Hob (
1459 (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,
1460 FvHeader->FvLength,
1461 AuthenticationStatus,
1462 TRUE,
1463 &ParentFvImageInfo.FvName,
1464 &FileInfo.FileName
1465 );
1466
1467 return EFI_SUCCESS;
1468 }
1469
1470 /**
1471 Process a firmware volume and create a volume handle.
1472
1473 Create a volume handle from the information in the buffer. For
1474 memory-mapped firmware volumes, Buffer and BufferSize refer to
1475 the start of the firmware volume and the firmware volume size.
1476 For non memory-mapped firmware volumes, this points to a
1477 buffer which contains the necessary information for creating
1478 the firmware volume handle. Normally, these values are derived
1479 from the EFI_FIRMWARE_VOLUME_INFO_PPI.
1480
1481
1482 @param This Points to this instance of the
1483 EFI_PEI_FIRMWARE_VOLUME_PPI.
1484 @param Buffer Points to the start of the buffer.
1485 @param BufferSize Size of the buffer.
1486 @param FvHandle Points to the returned firmware volume
1487 handle. The firmware volume handle must
1488 be unique within the system.
1489
1490 @retval EFI_SUCCESS Firmware volume handle created.
1491 @retval EFI_VOLUME_CORRUPTED Volume was corrupt.
1492
1493 **/
1494 EFI_STATUS
1495 EFIAPI
1496 PeiFfsFvPpiProcessVolume (
1497 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1498 IN VOID *Buffer,
1499 IN UINTN BufferSize,
1500 OUT EFI_PEI_FV_HANDLE *FvHandle
1501 )
1502 {
1503 EFI_STATUS Status;
1504
1505 ASSERT (FvHandle != NULL);
1506
1507 if (Buffer == NULL) {
1508 return EFI_VOLUME_CORRUPTED;
1509 }
1510
1511 //
1512 // The build-in EFI_PEI_FIRMWARE_VOLUME_PPI for FFS2/FFS3 support memory-mapped
1513 // FV image and the handle is pointed to Fv image's buffer.
1514 //
1515 *FvHandle = (EFI_PEI_FV_HANDLE) Buffer;
1516
1517 //
1518 // Do verify for given FV buffer.
1519 //
1520 Status = VerifyFv ((EFI_FIRMWARE_VOLUME_HEADER*) Buffer);
1521 if (EFI_ERROR(Status)) {
1522 DEBUG ((EFI_D_ERROR, "Fail to verify FV which address is 0x%11p", Buffer));
1523 return EFI_VOLUME_CORRUPTED;
1524 }
1525
1526 return EFI_SUCCESS;
1527 }
1528
1529 /**
1530 Finds the next file of the specified type.
1531
1532 This service enables PEI modules to discover additional firmware files.
1533 The FileHandle must be unique within the system.
1534
1535 @param This Points to this instance of the
1536 EFI_PEI_FIRMWARE_VOLUME_PPI.
1537 @param SearchType A filter to find only files of this type. Type
1538 EFI_FV_FILETYPE_ALL causes no filtering to be
1539 done.
1540 @param FvHandle Handle of firmware volume in which to
1541 search.
1542 @param FileHandle Points to the current handle from which to
1543 begin searching or NULL to start at the
1544 beginning of the firmware volume. Updated
1545 upon return to reflect the file found.
1546
1547 @retval EFI_SUCCESS The file was found.
1548 @retval EFI_NOT_FOUND The file was not found. FileHandle contains NULL.
1549
1550 **/
1551 EFI_STATUS
1552 EFIAPI
1553 PeiFfsFvPpiFindFileByType (
1554 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1555 IN EFI_FV_FILETYPE SearchType,
1556 IN EFI_PEI_FV_HANDLE FvHandle,
1557 IN OUT EFI_PEI_FILE_HANDLE *FileHandle
1558 )
1559 {
1560 return FindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL);
1561 }
1562
1563 /**
1564 Find a file within a volume by its name.
1565
1566 This service searches for files with a specific name, within
1567 either the specified firmware volume or all firmware volumes.
1568
1569 @param This Points to this instance of the
1570 EFI_PEI_FIRMWARE_VOLUME_PPI.
1571 @param FileName A pointer to the name of the file to find
1572 within the firmware volume.
1573 @param FvHandle Upon entry, the pointer to the firmware
1574 volume to search or NULL if all firmware
1575 volumes should be searched. Upon exit, the
1576 actual firmware volume in which the file was
1577 found.
1578 @param FileHandle Upon exit, points to the found file's
1579 handle or NULL if it could not be found.
1580
1581 @retval EFI_SUCCESS File was found.
1582 @retval EFI_NOT_FOUND File was not found.
1583 @retval EFI_INVALID_PARAMETER FvHandle or FileHandle or
1584 FileName was NULL.
1585
1586
1587 **/
1588 EFI_STATUS
1589 EFIAPI
1590 PeiFfsFvPpiFindFileByName (
1591 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1592 IN CONST EFI_GUID *FileName,
1593 IN EFI_PEI_FV_HANDLE *FvHandle,
1594 OUT EFI_PEI_FILE_HANDLE *FileHandle
1595 )
1596 {
1597 EFI_STATUS Status;
1598 PEI_CORE_INSTANCE *PrivateData;
1599 UINTN Index;
1600
1601 if ((FvHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {
1602 return EFI_INVALID_PARAMETER;
1603 }
1604
1605 if (*FvHandle != NULL) {
1606 Status = FindFileEx (*FvHandle, FileName, 0, FileHandle, NULL);
1607 if (Status == EFI_NOT_FOUND) {
1608 *FileHandle = NULL;
1609 }
1610 } else {
1611 //
1612 // If *FvHandle = NULL, so search all FV for given filename
1613 //
1614 Status = EFI_NOT_FOUND;
1615
1616 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer());
1617 for (Index = 0; Index < PrivateData->FvCount; Index ++) {
1618 //
1619 // Only search the FV which is associated with a EFI_PEI_FIRMWARE_VOLUME_PPI instance.
1620 //
1621 if (PrivateData->Fv[Index].FvPpi != NULL) {
1622 Status = FindFileEx (PrivateData->Fv[Index].FvHandle, FileName, 0, FileHandle, NULL);
1623 if (!EFI_ERROR (Status)) {
1624 *FvHandle = PrivateData->Fv[Index].FvHandle;
1625 break;
1626 }
1627 }
1628 }
1629 }
1630
1631 return Status;
1632 }
1633
1634 /**
1635 Returns information about a specific file.
1636
1637 This function returns information about a specific
1638 file, including its file name, type, attributes, starting
1639 address and size.
1640
1641 @param This Points to this instance of the
1642 EFI_PEI_FIRMWARE_VOLUME_PPI.
1643 @param FileHandle Handle of the file.
1644 @param FileInfo Upon exit, points to the file's
1645 information.
1646
1647 @retval EFI_SUCCESS File information returned.
1648 @retval EFI_INVALID_PARAMETER If FileHandle does not
1649 represent a valid file.
1650 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
1651
1652 **/
1653 EFI_STATUS
1654 EFIAPI
1655 PeiFfsFvPpiGetFileInfo (
1656 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1657 IN EFI_PEI_FILE_HANDLE FileHandle,
1658 OUT EFI_FV_FILE_INFO *FileInfo
1659 )
1660 {
1661 UINT8 FileState;
1662 UINT8 ErasePolarity;
1663 EFI_FFS_FILE_HEADER *FileHeader;
1664 PEI_CORE_FV_HANDLE *CoreFvHandle;
1665 PEI_FW_VOL_INSTANCE *FwVolInstance;
1666
1667 if ((FileHandle == NULL) || (FileInfo == NULL)) {
1668 return EFI_INVALID_PARAMETER;
1669 }
1670
1671 //
1672 // Retrieve the FirmwareVolume which the file resides in.
1673 //
1674 CoreFvHandle = FileHandleToVolume (FileHandle);
1675 if (CoreFvHandle == NULL) {
1676 return EFI_INVALID_PARAMETER;
1677 }
1678
1679 FwVolInstance = PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This);
1680
1681 if ((CoreFvHandle->FvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) != 0) {
1682 ErasePolarity = 1;
1683 } else {
1684 ErasePolarity = 0;
1685 }
1686
1687 //
1688 // Get FileState which is the highest bit of the State
1689 //
1690 FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle);
1691
1692 switch (FileState) {
1693 case EFI_FILE_DATA_VALID:
1694 case EFI_FILE_MARKED_FOR_UPDATE:
1695 break;
1696 default:
1697 return EFI_INVALID_PARAMETER;
1698 }
1699
1700 FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;
1701 if (IS_FFS_FILE2 (FileHeader)) {
1702 ASSERT (FFS_FILE2_SIZE (FileHeader) > 0x00FFFFFF);
1703 if (!FwVolInstance->IsFfs3Fv) {
1704 DEBUG ((EFI_D_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FileHeader->Name));
1705 return EFI_INVALID_PARAMETER;
1706 }
1707 FileInfo->BufferSize = FFS_FILE2_SIZE (FileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
1708 FileInfo->Buffer = (UINT8 *) FileHeader + sizeof (EFI_FFS_FILE_HEADER2);
1709 } else {
1710 FileInfo->BufferSize = FFS_FILE_SIZE (FileHeader) - sizeof (EFI_FFS_FILE_HEADER);
1711 FileInfo->Buffer = (UINT8 *) FileHeader + sizeof (EFI_FFS_FILE_HEADER);
1712 }
1713 CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID));
1714 FileInfo->FileType = FileHeader->Type;
1715 FileInfo->FileAttributes = FfsAttributes2FvFileAttributes (FileHeader->Attributes);
1716 if ((CoreFvHandle->FvHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) {
1717 FileInfo->FileAttributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED;
1718 }
1719 return EFI_SUCCESS;
1720 }
1721
1722 /**
1723 Returns information about a specific file.
1724
1725 This function returns information about a specific
1726 file, including its file name, type, attributes, starting
1727 address, size and authentication status.
1728
1729 @param This Points to this instance of the
1730 EFI_PEI_FIRMWARE_VOLUME_PPI.
1731 @param FileHandle Handle of the file.
1732 @param FileInfo Upon exit, points to the file's
1733 information.
1734
1735 @retval EFI_SUCCESS File information returned.
1736 @retval EFI_INVALID_PARAMETER If FileHandle does not
1737 represent a valid file.
1738 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
1739
1740 **/
1741 EFI_STATUS
1742 EFIAPI
1743 PeiFfsFvPpiGetFileInfo2 (
1744 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1745 IN EFI_PEI_FILE_HANDLE FileHandle,
1746 OUT EFI_FV_FILE_INFO2 *FileInfo
1747 )
1748 {
1749 EFI_STATUS Status;
1750 PEI_CORE_FV_HANDLE *CoreFvHandle;
1751
1752 if ((FileHandle == NULL) || (FileInfo == NULL)) {
1753 return EFI_INVALID_PARAMETER;
1754 }
1755
1756 //
1757 // Retrieve the FirmwareVolume which the file resides in.
1758 //
1759 CoreFvHandle = FileHandleToVolume (FileHandle);
1760 if (CoreFvHandle == NULL) {
1761 return EFI_INVALID_PARAMETER;
1762 }
1763
1764 Status = PeiFfsFvPpiGetFileInfo (This, FileHandle, (EFI_FV_FILE_INFO *) FileInfo);
1765 if (!EFI_ERROR (Status)) {
1766 FileInfo->AuthenticationStatus = CoreFvHandle->AuthenticationStatus;
1767 }
1768
1769 return Status;
1770 }
1771
1772 /**
1773 This function returns information about the firmware volume.
1774
1775 @param This Points to this instance of the
1776 EFI_PEI_FIRMWARE_VOLUME_PPI.
1777 @param FvHandle Handle to the firmware handle.
1778 @param VolumeInfo Points to the returned firmware volume
1779 information.
1780
1781 @retval EFI_SUCCESS Information returned successfully.
1782 @retval EFI_INVALID_PARAMETER FvHandle does not indicate a valid
1783 firmware volume or VolumeInfo is NULL.
1784
1785 **/
1786 EFI_STATUS
1787 EFIAPI
1788 PeiFfsFvPpiGetVolumeInfo (
1789 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1790 IN EFI_PEI_FV_HANDLE FvHandle,
1791 OUT EFI_FV_INFO *VolumeInfo
1792 )
1793 {
1794 EFI_FIRMWARE_VOLUME_HEADER FwVolHeader;
1795 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;
1796
1797 if ((VolumeInfo == NULL) || (FvHandle == NULL)) {
1798 return EFI_INVALID_PARAMETER;
1799 }
1800
1801 //
1802 // VolumeHandle may not align at 8 byte,
1803 // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte.
1804 // So, Copy FvHeader into the local FvHeader structure.
1805 //
1806 CopyMem (&FwVolHeader, FvHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
1807
1808 //
1809 // Check Fv Image Signature
1810 //
1811 if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {
1812 return EFI_INVALID_PARAMETER;
1813 }
1814
1815 ZeroMem (VolumeInfo, sizeof (EFI_FV_INFO));
1816 VolumeInfo->FvAttributes = FwVolHeader.Attributes;
1817 VolumeInfo->FvStart = (VOID *) FvHandle;
1818 VolumeInfo->FvSize = FwVolHeader.FvLength;
1819 CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID));
1820
1821 if (FwVolHeader.ExtHeaderOffset != 0) {
1822 FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)FvHandle) + FwVolHeader.ExtHeaderOffset);
1823 CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID));
1824 }
1825
1826 return EFI_SUCCESS;
1827 }
1828
1829 /**
1830 Find the next matching section in the firmware file.
1831
1832 This service enables PEI modules to discover sections
1833 of a given type within a valid file.
1834
1835 @param This Points to this instance of the
1836 EFI_PEI_FIRMWARE_VOLUME_PPI.
1837 @param SearchType A filter to find only sections of this
1838 type.
1839 @param FileHandle Handle of firmware file in which to
1840 search.
1841 @param SectionData Updated upon return to point to the
1842 section found.
1843
1844 @retval EFI_SUCCESS Section was found.
1845 @retval EFI_NOT_FOUND Section of the specified type was not
1846 found. SectionData contains NULL.
1847 **/
1848 EFI_STATUS
1849 EFIAPI
1850 PeiFfsFvPpiFindSectionByType (
1851 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1852 IN EFI_SECTION_TYPE SearchType,
1853 IN EFI_PEI_FILE_HANDLE FileHandle,
1854 OUT VOID **SectionData
1855 )
1856 {
1857 UINT32 AuthenticationStatus;
1858 return PeiFfsFvPpiFindSectionByType2 (This, SearchType, 0, FileHandle, SectionData, &AuthenticationStatus);
1859 }
1860
1861 /**
1862 Find the next matching section in the firmware file.
1863
1864 This service enables PEI modules to discover sections
1865 of a given instance and type within a valid file.
1866
1867 @param This Points to this instance of the
1868 EFI_PEI_FIRMWARE_VOLUME_PPI.
1869 @param SearchType A filter to find only sections of this
1870 type.
1871 @param SearchInstance A filter to find the specific instance
1872 of sections.
1873 @param FileHandle Handle of firmware file in which to
1874 search.
1875 @param SectionData Updated upon return to point to the
1876 section found.
1877 @param AuthenticationStatus Updated upon return to point to the
1878 authentication status for this section.
1879
1880 @retval EFI_SUCCESS Section was found.
1881 @retval EFI_NOT_FOUND Section of the specified type was not
1882 found. SectionData contains NULL.
1883 **/
1884 EFI_STATUS
1885 EFIAPI
1886 PeiFfsFvPpiFindSectionByType2 (
1887 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1888 IN EFI_SECTION_TYPE SearchType,
1889 IN UINTN SearchInstance,
1890 IN EFI_PEI_FILE_HANDLE FileHandle,
1891 OUT VOID **SectionData,
1892 OUT UINT32 *AuthenticationStatus
1893 )
1894 {
1895 EFI_STATUS Status;
1896 EFI_FFS_FILE_HEADER *FfsFileHeader;
1897 UINT32 FileSize;
1898 EFI_COMMON_SECTION_HEADER *Section;
1899 PEI_FW_VOL_INSTANCE *FwVolInstance;
1900 PEI_CORE_FV_HANDLE *CoreFvHandle;
1901 UINTN Instance;
1902 UINT32 ExtractedAuthenticationStatus;
1903
1904 if (SectionData == NULL) {
1905 return EFI_NOT_FOUND;
1906 }
1907
1908 FwVolInstance = PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This);
1909
1910 //
1911 // Retrieve the FirmwareVolume which the file resides in.
1912 //
1913 CoreFvHandle = FileHandleToVolume (FileHandle);
1914 if (CoreFvHandle == NULL) {
1915 return EFI_NOT_FOUND;
1916 }
1917
1918 FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);
1919
1920 if (IS_FFS_FILE2 (FfsFileHeader)) {
1921 ASSERT (FFS_FILE2_SIZE (FfsFileHeader) > 0x00FFFFFF);
1922 if (!FwVolInstance->IsFfs3Fv) {
1923 DEBUG ((EFI_D_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));
1924 return EFI_NOT_FOUND;
1925 }
1926 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
1927 FileSize = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
1928 } else {
1929 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));
1930 FileSize = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
1931 }
1932
1933 Instance = SearchInstance + 1;
1934 ExtractedAuthenticationStatus = 0;
1935 Status = ProcessSection (
1936 GetPeiServicesTablePointer (),
1937 SearchType,
1938 &Instance,
1939 Section,
1940 FileSize,
1941 SectionData,
1942 &ExtractedAuthenticationStatus,
1943 FwVolInstance->IsFfs3Fv
1944 );
1945 if (!EFI_ERROR (Status)) {
1946 //
1947 // Inherit the authentication status.
1948 //
1949 *AuthenticationStatus = ExtractedAuthenticationStatus | CoreFvHandle->AuthenticationStatus;
1950 }
1951 return Status;
1952 }
1953
1954 /**
1955 Convert the handle of FV to pointer of corresponding PEI_CORE_FV_HANDLE.
1956
1957 @param FvHandle The handle of a FV.
1958
1959 @retval NULL if can not find.
1960 @return Pointer of corresponding PEI_CORE_FV_HANDLE.
1961 **/
1962 PEI_CORE_FV_HANDLE *
1963 FvHandleToCoreHandle (
1964 IN EFI_PEI_FV_HANDLE FvHandle
1965 )
1966 {
1967 UINTN Index;
1968 PEI_CORE_INSTANCE *PrivateData;
1969
1970 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer());
1971 for (Index = 0; Index < PrivateData->FvCount; Index ++) {
1972 if (FvHandle == PrivateData->Fv[Index].FvHandle) {
1973 return &PrivateData->Fv[Index];
1974 }
1975 }
1976
1977 return NULL;
1978 }
1979
1980 /**
1981 Get instance of PEI_CORE_FV_HANDLE for next volume according to given index.
1982
1983 This routine also will install FvInfo ppi for FV hob in PI ways.
1984
1985 @param Private Pointer of PEI_CORE_INSTANCE
1986 @param Instance The index of FV want to be searched.
1987
1988 @return Instance of PEI_CORE_FV_HANDLE.
1989 **/
1990 PEI_CORE_FV_HANDLE *
1991 FindNextCoreFvHandle (
1992 IN PEI_CORE_INSTANCE *Private,
1993 IN UINTN Instance
1994 )
1995 {
1996 UINTN Index;
1997 BOOLEAN Match;
1998 EFI_HOB_FIRMWARE_VOLUME *FvHob;
1999
2000 //
2001 // Handle Framework FvHob and Install FvInfo Ppi for it.
2002 //
2003 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
2004 //
2005 // Loop to search the wanted FirmwareVolume which supports FFS
2006 //
2007 FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetFirstHob (EFI_HOB_TYPE_FV);
2008 while (FvHob != NULL) {
2009 //
2010 // Search whether FvHob has been installed into PeiCore's FV database.
2011 // If found, no need install new FvInfoPpi for it.
2012 //
2013 for (Index = 0, Match = FALSE; Index < Private->FvCount; Index++) {
2014 if ((EFI_PEI_FV_HANDLE)(UINTN)FvHob->BaseAddress == Private->Fv[Index].FvHeader) {
2015 Match = TRUE;
2016 break;
2017 }
2018 }
2019
2020 //
2021 // Search whether FvHob has been cached into PeiCore's Unknown FV database.
2022 // If found, no need install new FvInfoPpi for it.
2023 //
2024 if (!Match) {
2025 for (Index = 0; Index < Private->UnknownFvInfoCount; Index ++) {
2026 if ((UINTN)FvHob->BaseAddress == (UINTN)Private->UnknownFvInfo[Index].FvInfo) {
2027 Match = TRUE;
2028 break;
2029 }
2030 }
2031 }
2032
2033 //
2034 // If the Fv in FvHob has not been installed into PeiCore's FV database and has
2035 // not been cached into PeiCore's Unknown FV database, install a new FvInfoPpi
2036 // for it then PeiCore will dispatch it in callback of FvInfoPpi.
2037 //
2038 if (!Match) {
2039 PeiServicesInstallFvInfoPpi (
2040 &(((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvHob->BaseAddress)->FileSystemGuid),
2041 (VOID *)(UINTN)FvHob->BaseAddress,
2042 (UINT32)FvHob->Length,
2043 NULL,
2044 NULL
2045 );
2046 }
2047
2048 FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetNextHob (EFI_HOB_TYPE_FV, (VOID *)((UINTN)FvHob + FvHob->Header.HobLength));
2049 }
2050 }
2051
2052 ASSERT (Private->FvCount <= PcdGet32 (PcdPeiCoreMaxFvSupported));
2053 if (Instance >= Private->FvCount) {
2054 return NULL;
2055 }
2056
2057 return &Private->Fv[Instance];
2058 }
2059
2060 /**
2061 After PeiCore image is shadowed into permanent memory, all build-in FvPpi should
2062 be re-installed with the instance in permanent memory and all cached FvPpi pointers in
2063 PrivateData->Fv[] array should be fixed up to be pointed to the one in permanent
2064 memory.
2065
2066 @param PrivateData Pointer to PEI_CORE_INSTANCE.
2067 **/
2068 VOID
2069 PeiReinitializeFv (
2070 IN PEI_CORE_INSTANCE *PrivateData
2071 )
2072 {
2073 VOID *OldFfsFvPpi;
2074 EFI_PEI_PPI_DESCRIPTOR *OldDescriptor;
2075 UINTN Index;
2076 EFI_STATUS Status;
2077
2078 //
2079 // Locate old build-in Ffs2 EFI_PEI_FIRMWARE_VOLUME_PPI which
2080 // in flash.
2081 //
2082 Status = PeiServicesLocatePpi (
2083 &gEfiFirmwareFileSystem2Guid,
2084 0,
2085 &OldDescriptor,
2086 &OldFfsFvPpi
2087 );
2088 ASSERT_EFI_ERROR (Status);
2089
2090 //
2091 // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs2
2092 // which is shadowed from flash to permanent memory within PeiCore image.
2093 //
2094 Status = PeiServicesReInstallPpi (OldDescriptor, &mPeiFfs2FvPpiList);
2095 ASSERT_EFI_ERROR (Status);
2096
2097 //
2098 // Fixup all FvPpi pointers for the implementation in flash to permanent memory.
2099 //
2100 for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {
2101 if (PrivateData->Fv[Index].FvPpi == OldFfsFvPpi) {
2102 PrivateData->Fv[Index].FvPpi = &mPeiFfs2FwVol.Fv;
2103 }
2104 }
2105
2106 //
2107 // Locate old build-in Ffs3 EFI_PEI_FIRMWARE_VOLUME_PPI which
2108 // in flash.
2109 //
2110 Status = PeiServicesLocatePpi (
2111 &gEfiFirmwareFileSystem3Guid,
2112 0,
2113 &OldDescriptor,
2114 &OldFfsFvPpi
2115 );
2116 ASSERT_EFI_ERROR (Status);
2117
2118 //
2119 // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs3
2120 // which is shadowed from flash to permanent memory within PeiCore image.
2121 //
2122 Status = PeiServicesReInstallPpi (OldDescriptor, &mPeiFfs3FvPpiList);
2123 ASSERT_EFI_ERROR (Status);
2124
2125 //
2126 // Fixup all FvPpi pointers for the implementation in flash to permanent memory.
2127 //
2128 for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {
2129 if (PrivateData->Fv[Index].FvPpi == OldFfsFvPpi) {
2130 PrivateData->Fv[Index].FvPpi = &mPeiFfs3FwVol.Fv;
2131 }
2132 }
2133 }
2134
2135 /**
2136 Report the information for a new discoveried FV in unknown third-party format.
2137
2138 If the EFI_PEI_FIRMWARE_VOLUME_PPI has not been installed for third-party FV format, but
2139 the FV in this format has been discoveried, then this FV's information will be cached into
2140 PEI_CORE_INSTANCE's UnknownFvInfo array.
2141 Also a notification would be installed for unknown third-party FV format guid, if EFI_PEI_FIRMWARE_VOLUME_PPI
2142 is installed later by platform's PEIM, the original unknown third-party FV will be processed by
2143 using new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
2144
2145 @param PrivateData Point to instance of PEI_CORE_INSTANCE
2146 @param FvInfo2Ppi Point to FvInfo2 PPI.
2147
2148 @retval EFI_OUT_OF_RESOURCES The FV info array in PEI_CORE_INSTANCE has no more spaces.
2149 @retval EFI_SUCCESS Success to add the information for unknown FV.
2150 **/
2151 EFI_STATUS
2152 AddUnknownFormatFvInfo (
2153 IN PEI_CORE_INSTANCE *PrivateData,
2154 IN EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI *FvInfo2Ppi
2155 )
2156 {
2157 PEI_CORE_UNKNOW_FORMAT_FV_INFO *NewUnknownFv;
2158
2159 if (PrivateData->UnknownFvInfoCount + 1 >= PcdGet32 (PcdPeiCoreMaxFvSupported)) {
2160 return EFI_OUT_OF_RESOURCES;
2161 }
2162
2163 NewUnknownFv = &PrivateData->UnknownFvInfo[PrivateData->UnknownFvInfoCount];
2164 PrivateData->UnknownFvInfoCount ++;
2165
2166 CopyGuid (&NewUnknownFv->FvFormat, &FvInfo2Ppi->FvFormat);
2167 NewUnknownFv->FvInfo = FvInfo2Ppi->FvInfo;
2168 NewUnknownFv->FvInfoSize = FvInfo2Ppi->FvInfoSize;
2169 NewUnknownFv->AuthenticationStatus = FvInfo2Ppi->AuthenticationStatus;
2170 NewUnknownFv->NotifyDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
2171 NewUnknownFv->NotifyDescriptor.Guid = &NewUnknownFv->FvFormat;
2172 NewUnknownFv->NotifyDescriptor.Notify = ThirdPartyFvPpiNotifyCallback;
2173
2174 PeiServicesNotifyPpi (&NewUnknownFv->NotifyDescriptor);
2175 return EFI_SUCCESS;
2176 }
2177
2178 /**
2179 Find the FV information according to third-party FV format guid.
2180
2181 This routine also will remove the FV information found by given FV format guid from
2182 PrivateData->UnknownFvInfo[].
2183
2184 @param PrivateData Point to instance of PEI_CORE_INSTANCE
2185 @param Format Point to given FV format guid
2186 @param FvInfo On return, the pointer of FV information buffer
2187 @param FvInfoSize On return, the size of FV information buffer.
2188 @param AuthenticationStatus On return, the authentication status of FV information buffer.
2189
2190 @retval EFI_NOT_FOUND The FV is not found for new installed EFI_PEI_FIRMWARE_VOLUME_PPI
2191 @retval EFI_SUCCESS Success to find a FV which could be processed by new installed EFI_PEI_FIRMWARE_VOLUME_PPI.
2192 **/
2193 EFI_STATUS
2194 FindUnknownFormatFvInfo (
2195 IN PEI_CORE_INSTANCE *PrivateData,
2196 IN EFI_GUID *Format,
2197 OUT VOID **FvInfo,
2198 OUT UINT32 *FvInfoSize,
2199 OUT UINT32 *AuthenticationStatus
2200 )
2201 {
2202 UINTN Index;
2203 UINTN Index2;
2204
2205 Index = 0;
2206 for (; Index < PrivateData->UnknownFvInfoCount; Index ++) {
2207 if (CompareGuid (Format, &PrivateData->UnknownFvInfo[Index].FvFormat)) {
2208 break;
2209 }
2210 }
2211
2212 if (Index == PrivateData->UnknownFvInfoCount) {
2213 return EFI_NOT_FOUND;
2214 }
2215
2216 *FvInfo = PrivateData->UnknownFvInfo[Index].FvInfo;
2217 *FvInfoSize = PrivateData->UnknownFvInfo[Index].FvInfoSize;
2218 *AuthenticationStatus = PrivateData->UnknownFvInfo[Index].AuthenticationStatus;
2219
2220 //
2221 // Remove an entry from UnknownFvInfo array.
2222 //
2223 Index2 = Index + 1;
2224 for (;Index2 < PrivateData->UnknownFvInfoCount; Index2 ++, Index ++) {
2225 CopyMem (&PrivateData->UnknownFvInfo[Index], &PrivateData->UnknownFvInfo[Index2], sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO));
2226 }
2227 PrivateData->UnknownFvInfoCount --;
2228 return EFI_SUCCESS;
2229 }
2230
2231 /**
2232 Notification callback function for EFI_PEI_FIRMWARE_VOLUME_PPI.
2233
2234 When a EFI_PEI_FIRMWARE_VOLUME_PPI is installed to support new FV format, this
2235 routine is called to process all discoveried FVs in this format.
2236
2237 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
2238 @param NotifyDescriptor Address of the notification descriptor data structure.
2239 @param Ppi Address of the PPI that was installed.
2240
2241 @retval EFI_SUCCESS The notification callback is processed correctly.
2242 **/
2243 EFI_STATUS
2244 EFIAPI
2245 ThirdPartyFvPpiNotifyCallback (
2246 IN EFI_PEI_SERVICES **PeiServices,
2247 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
2248 IN VOID *Ppi
2249 )
2250 {
2251 PEI_CORE_INSTANCE *PrivateData;
2252 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
2253 VOID *FvInfo;
2254 UINT32 FvInfoSize;
2255 UINT32 AuthenticationStatus;
2256 EFI_STATUS Status;
2257 EFI_PEI_FV_HANDLE FvHandle;
2258 BOOLEAN IsProcessed;
2259 UINTN FvIndex;
2260 EFI_PEI_FILE_HANDLE FileHandle;
2261 VOID *DepexData;
2262 UINTN CurFvCount;
2263
2264 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
2265 FvPpi = (EFI_PEI_FIRMWARE_VOLUME_PPI*) Ppi;
2266
2267 do {
2268 Status = FindUnknownFormatFvInfo (PrivateData, NotifyDescriptor->Guid, &FvInfo, &FvInfoSize, &AuthenticationStatus);
2269 if (EFI_ERROR (Status)) {
2270 return EFI_SUCCESS;
2271 }
2272
2273 //
2274 // Process new found FV and get FV handle.
2275 //
2276 Status = FvPpi->ProcessVolume (FvPpi, FvInfo, FvInfoSize, &FvHandle);
2277 if (EFI_ERROR (Status)) {
2278 DEBUG ((EFI_D_ERROR, "Fail to process the FV 0x%p, FV may be corrupted!\n", FvInfo));
2279 continue;
2280 }
2281
2282 //
2283 // Check whether the FV has already been processed.
2284 //
2285 IsProcessed = FALSE;
2286 for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {
2287 if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {
2288 DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvInfo));
2289 IsProcessed = TRUE;
2290 break;
2291 }
2292 }
2293
2294 if (IsProcessed) {
2295 continue;
2296 }
2297
2298 if (PrivateData->FvCount >= PcdGet32 (PcdPeiCoreMaxFvSupported)) {
2299 DEBUG ((EFI_D_ERROR, "The number of Fv Images (%d) exceed the max supported FVs (%d) in Pei", PrivateData->FvCount + 1, PcdGet32 (PcdPeiCoreMaxFvSupported)));
2300 DEBUG ((EFI_D_ERROR, "PcdPeiCoreMaxFvSupported value need be reconfigurated in DSC"));
2301 ASSERT (FALSE);
2302 }
2303
2304 //
2305 // Update internal PEI_CORE_FV array.
2306 //
2307 PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) FvInfo;
2308 PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi;
2309 PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;
2310 PrivateData->Fv[PrivateData->FvCount].AuthenticationStatus = AuthenticationStatus;
2311 CurFvCount = PrivateData->FvCount;
2312 DEBUG ((
2313 EFI_D_INFO,
2314 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
2315 (UINT32) CurFvCount,
2316 (VOID *) FvInfo,
2317 FvInfoSize,
2318 FvHandle
2319 ));
2320 PrivateData->FvCount ++;
2321
2322 //
2323 // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
2324 //
2325 FileHandle = NULL;
2326 do {
2327 Status = FvPpi->FindFileByType (
2328 FvPpi,
2329 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
2330 FvHandle,
2331 &FileHandle
2332 );
2333 if (!EFI_ERROR (Status)) {
2334 Status = FvPpi->FindSectionByType (
2335 FvPpi,
2336 EFI_SECTION_PEI_DEPEX,
2337 FileHandle,
2338 (VOID**)&DepexData
2339 );
2340 if (!EFI_ERROR (Status)) {
2341 if (!PeimDispatchReadiness (PeiServices, DepexData)) {
2342 //
2343 // Dependency is not satisfied.
2344 //
2345 continue;
2346 }
2347 }
2348
2349 DEBUG ((EFI_D_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, CurFvCount, FvHandle));
2350 ProcessFvFile (PrivateData, &PrivateData->Fv[CurFvCount], FileHandle);
2351 }
2352 } while (FileHandle != NULL);
2353 } while (TRUE);
2354 }