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