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