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