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