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