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