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