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