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