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