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