]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/FwVol/FwVol.c
MdeModulePkg/SecurityPkg: Update TreePei to handle FvInfo2 and update FwVol of PeiCor...
[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
387208ab 4Copyright (c) 2006 - 2014, 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
387208ab 528 BOOLEAN IsFvInfo2;\r
b0d803fe 529 \r
288f9b38
LG
530 Status = EFI_SUCCESS;\r
531 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
b0d803fe 532\r
4140a663 533 if (PrivateData->FvCount >= FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {\r
534 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 535 DEBUG ((EFI_D_ERROR, "PcdPeiCoreMaxFvSupported value need be reconfigurated in DSC"));\r
b0d803fe 536 ASSERT (FALSE);\r
537 }\r
538\r
c7935105
SZ
539 if (CompareGuid (NotifyDescriptor->Guid, &gEfiPeiFirmwareVolumeInfo2PpiGuid)) {\r
540 //\r
541 // It is FvInfo2PPI.\r
542 //\r
543 CopyMem (&FvInfo2Ppi, Ppi, sizeof (EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI));\r
387208ab 544 IsFvInfo2 = TRUE;\r
c7935105
SZ
545 } else {\r
546 //\r
547 // It is FvInfoPPI.\r
548 //\r
549 CopyMem (&FvInfo2Ppi, Ppi, sizeof (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI));\r
550 FvInfo2Ppi.AuthenticationStatus = 0;\r
387208ab 551 IsFvInfo2 = FALSE;\r
c7935105 552 }\r
b0d803fe 553\r
97b2c9b5 554 //\r
3b428ade 555 // Locate the corresponding FV_PPI according to founded FV's format guid\r
97b2c9b5 556 //\r
3b428ade 557 Status = PeiServicesLocatePpi (\r
c7935105
SZ
558 &FvInfo2Ppi.FvFormat,\r
559 0,\r
3b428ade 560 NULL,\r
561 (VOID**)&FvPpi\r
562 );\r
563 if (!EFI_ERROR (Status)) {\r
564 //\r
565 // Process new found FV and get FV handle.\r
566 //\r
c7935105 567 Status = FvPpi->ProcessVolume (FvPpi, FvInfo2Ppi.FvInfo, FvInfo2Ppi.FvInfoSize, &FvHandle);\r
3b428ade 568 if (EFI_ERROR (Status)) {\r
dc6f9b35 569 DEBUG ((EFI_D_ERROR, "Fail to process new found FV, FV may be corrupted!\n"));\r
6a1ae84a 570 return Status;\r
571 }\r
dc6f9b35 572\r
573 //\r
574 // Check whether the FV has already been processed.\r
575 //\r
576 for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {\r
577 if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {\r
387208ab
SZ
578 if (IsFvInfo2 && (FvInfo2Ppi.AuthenticationStatus != PrivateData->Fv[FvIndex].AuthenticationStatus)) {\r
579 PrivateData->Fv[FvIndex].AuthenticationStatus = FvInfo2Ppi.AuthenticationStatus;\r
580 DEBUG ((EFI_D_INFO, "Update AuthenticationStatus of the %dth FV to 0x%x!\n", FvIndex, FvInfo2Ppi.AuthenticationStatus)); \r
581 }\r
c7935105 582 DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvInfo2Ppi.FvInfo));\r
dc6f9b35 583 return EFI_SUCCESS;\r
584 }\r
585 }\r
586\r
587 //\r
588 // Update internal PEI_CORE_FV array.\r
589 //\r
c7935105 590 PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) FvInfo2Ppi.FvInfo;\r
dc6f9b35 591 PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi;\r
592 PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;\r
c7935105 593 PrivateData->Fv[PrivateData->FvCount].AuthenticationStatus = FvInfo2Ppi.AuthenticationStatus;\r
dc6f9b35 594 DEBUG ((\r
595 EFI_D_INFO, \r
596 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n", \r
597 (UINT32) PrivateData->FvCount, \r
c7935105
SZ
598 (VOID *) FvInfo2Ppi.FvInfo, \r
599 FvInfo2Ppi.FvInfoSize,\r
dc6f9b35 600 FvHandle\r
601 )); \r
602 PrivateData->FvCount ++;\r
603\r
604 //\r
605 // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE \r
606 //\r
607 FileHandle = NULL;\r
608 do {\r
609 Status = FvPpi->FindFileByType (\r
610 FvPpi,\r
611 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
612 FvHandle,\r
613 &FileHandle\r
614 );\r
615 if (!EFI_ERROR (Status)) {\r
616 Status = FvPpi->FindSectionByType (\r
617 FvPpi,\r
618 EFI_SECTION_PEI_DEPEX,\r
619 FileHandle,\r
620 (VOID**)&DepexData\r
621 );\r
622 if (!EFI_ERROR (Status)) {\r
623 if (!PeimDispatchReadiness (PeiServices, DepexData)) {\r
624 //\r
625 // Dependency is not satisfied.\r
626 //\r
627 continue;\r
628 }\r
629 }\r
630 \r
631 DEBUG ((EFI_D_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, PrivateData->FvCount - 1, FvHandle));\r
c7935105 632 ProcessFvFile (PrivateData, &PrivateData->Fv[PrivateData->FvCount - 1], FileHandle);\r
dc6f9b35 633 }\r
634 } while (FileHandle != NULL);\r
3b428ade 635 } else {\r
c7935105 636 DEBUG ((EFI_D_ERROR, "Fail to process FV %p because no corresponding EFI_FIRMWARE_VOLUME_PPI is found!\n", FvInfo2Ppi.FvInfo));\r
6a1ae84a 637 \r
c7935105 638 AddUnknownFormatFvInfo (PrivateData, &FvInfo2Ppi);\r
288f9b38 639 }\r
3b428ade 640 \r
b0d803fe 641 return EFI_SUCCESS;\r
642}\r
643\r
8472f1f5
SZ
644/**\r
645 Verify the Guided Section GUID by checking if there is the Guided Section GUID HOB recorded the GUID itself.\r
646\r
647 @param GuidedSectionGuid The Guided Section GUID.\r
648 @param GuidedSectionExtraction A pointer to the pointer to the supported Guided Section Extraction Ppi\r
649 for the Guided Section.\r
650\r
651 @return TRUE The GuidedSectionGuid could be identified, and the pointer to\r
652 the Guided Section Extraction Ppi will be returned to *GuidedSectionExtraction.\r
653 @return FALSE The GuidedSectionGuid could not be identified, or \r
654 the Guided Section Extraction Ppi has not been installed yet.\r
655\r
656**/\r
657BOOLEAN\r
658VerifyGuidedSectionGuid (\r
659 IN EFI_GUID *GuidedSectionGuid,\r
660 OUT EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI **GuidedSectionExtraction\r
661 )\r
662{\r
663 EFI_PEI_HOB_POINTERS Hob;\r
664 EFI_GUID *GuidRecorded;\r
665 VOID *Interface;\r
666 EFI_STATUS Status;\r
667\r
668 //\r
669 // Check if there is the Guided Section GUID HOB recorded the GUID itself.\r
670 //\r
671 Hob.Raw = GetFirstGuidHob (GuidedSectionGuid);\r
672 if (Hob.Raw != NULL) {\r
673 GuidRecorded = (EFI_GUID *) GET_GUID_HOB_DATA (Hob);\r
674 if (CompareGuid (GuidRecorded, GuidedSectionGuid)) {\r
675 //\r
676 // Found the recorded GuidedSectionGuid.\r
677 //\r
678 Status = PeiServicesLocatePpi (GuidedSectionGuid, 0, NULL, (VOID **) &Interface);\r
679 if (!EFI_ERROR (Status) && Interface != NULL) {\r
680 //\r
681 // Found the supported Guided Section Extraction Ppi for the Guided Section.\r
682 //\r
683 *GuidedSectionExtraction = (EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *) Interface;\r
684 return TRUE;\r
685 }\r
686 return FALSE;\r
687 }\r
688 }\r
689\r
690 return FALSE;\r
691}\r
692\r
b1f6a7c6 693/**\r
ed299e3c
LG
694 Go through the file to search SectionType section. \r
695 Search within encapsulation sections (compression and GUIDed) recursively, \r
696 until the match section is found.\r
697 \r
3b428ade 698 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
699 @param SectionType Filter to find only section of this type.\r
c7935105 700 @param SectionInstance Pointer to the filter to find the specific instance of section.\r
3b428ade 701 @param Section From where to search.\r
702 @param SectionSize The file size to search.\r
703 @param OutputBuffer A pointer to the discovered section, if successful.\r
ed299e3c 704 NULL if section not found\r
c7935105 705 @param AuthenticationStatus Updated upon return to point to the authentication status for this section.\r
890e5417 706 @param IsFfs3Fv Indicates the FV format.\r
b1f6a7c6 707\r
ed299e3c
LG
708 @return EFI_NOT_FOUND The match section is not found.\r
709 @return EFI_SUCCESS The match section is found.\r
b1f6a7c6 710\r
711**/\r
b0d803fe 712EFI_STATUS\r
3b428ade 713ProcessSection (\r
b0d803fe 714 IN CONST EFI_PEI_SERVICES **PeiServices,\r
715 IN EFI_SECTION_TYPE SectionType,\r
c7935105 716 IN OUT UINTN *SectionInstance,\r
b0d803fe 717 IN EFI_COMMON_SECTION_HEADER *Section,\r
718 IN UINTN SectionSize,\r
890e5417 719 OUT VOID **OutputBuffer,\r
c7935105 720 OUT UINT32 *AuthenticationStatus,\r
890e5417 721 IN BOOLEAN IsFfs3Fv\r
b0d803fe 722 )\r
b0d803fe 723{\r
724 EFI_STATUS Status;\r
725 UINT32 SectionLength;\r
726 UINT32 ParsedLength;\r
b0d803fe 727 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *GuidSectionPpi;\r
b0d803fe 728 EFI_PEI_DECOMPRESS_PPI *DecompressPpi;\r
729 VOID *PpiOutput;\r
730 UINTN PpiOutputSize;\r
288f9b38
LG
731 UINTN Index;\r
732 UINT32 Authentication;\r
733 PEI_CORE_INSTANCE *PrivateData;\r
8472f1f5 734 EFI_GUID *SectionDefinitionGuid;\r
c7935105
SZ
735 BOOLEAN SectionCached;\r
736 VOID *TempOutputBuffer;\r
737 UINT32 TempAuthenticationStatus;\r
b0d803fe 738\r
288f9b38 739 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
b0d803fe 740 *OutputBuffer = NULL;\r
288f9b38
LG
741 ParsedLength = 0;\r
742 Index = 0;\r
743 Status = EFI_NOT_FOUND;\r
744 PpiOutput = NULL;\r
745 PpiOutputSize = 0;\r
b0d803fe 746 while (ParsedLength < SectionSize) {\r
890e5417
SZ
747\r
748 if (IS_SECTION2 (Section)) {\r
749 ASSERT (SECTION2_SIZE (Section) > 0x00FFFFFF);\r
750 if (!IsFfs3Fv) {\r
751 DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted section in a non-FFS3 formatted FV.\n"));\r
752 SectionLength = SECTION2_SIZE (Section);\r
753 //\r
754 // SectionLength is adjusted it is 4 byte aligned.\r
755 // Go to the next section\r
756 //\r
757 SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
758 ASSERT (SectionLength != 0);\r
759 ParsedLength += SectionLength;\r
760 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + SectionLength);\r
761 continue;\r
762 }\r
763 }\r
764\r
b0d803fe 765 if (Section->Type == SectionType) {\r
c7935105
SZ
766 //\r
767 // The type matches, so check the instance count to see if it's the one we want.\r
768 //\r
769 (*SectionInstance)--;\r
770 if (*SectionInstance == 0) {\r
771 //\r
772 // Got it!\r
773 //\r
774 if (IS_SECTION2 (Section)) {\r
775 *OutputBuffer = (VOID *)((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2));\r
776 } else {\r
777 *OutputBuffer = (VOID *)((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER));\r
778 }\r
779 return EFI_SUCCESS;\r
890e5417 780 } else {\r
c7935105
SZ
781 if (IS_SECTION2 (Section)) {\r
782 SectionLength = SECTION2_SIZE (Section);\r
783 } else {\r
784 SectionLength = SECTION_SIZE (Section);\r
785 }\r
786 //\r
787 // SectionLength is adjusted it is 4 byte aligned.\r
788 // Go to the next section\r
789 //\r
790 SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
791 ASSERT (SectionLength != 0);\r
792 ParsedLength += SectionLength;\r
793 Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);\r
794 continue;\r
890e5417 795 }\r
288f9b38
LG
796 } else if ((Section->Type == EFI_SECTION_GUID_DEFINED) || (Section->Type == EFI_SECTION_COMPRESSION)) {\r
797 //\r
798 // Check the encapsulated section is extracted into the cache data.\r
799 //\r
c7935105 800 SectionCached = FALSE;\r
288f9b38
LG
801 for (Index = 0; Index < PrivateData->CacheSection.AllSectionCount; Index ++) {\r
802 if (Section == PrivateData->CacheSection.Section[Index]) {\r
c7935105 803 SectionCached = TRUE;\r
288f9b38
LG
804 PpiOutput = PrivateData->CacheSection.SectionData[Index];\r
805 PpiOutputSize = PrivateData->CacheSection.SectionSize[Index];\r
c7935105 806 Authentication = PrivateData->CacheSection.AuthenticationStatus[Index];\r
288f9b38
LG
807 //\r
808 // Search section directly from the cache data.\r
809 //\r
c7935105
SZ
810 TempAuthenticationStatus = 0;\r
811 Status = ProcessSection (\r
812 PeiServices,\r
813 SectionType,\r
814 SectionInstance,\r
815 PpiOutput, \r
816 PpiOutputSize, \r
817 &TempOutputBuffer,\r
818 &TempAuthenticationStatus,\r
819 IsFfs3Fv\r
3b428ade 820 );\r
c7935105
SZ
821 if (!EFI_ERROR (Status)) {\r
822 *OutputBuffer = TempOutputBuffer;\r
823 *AuthenticationStatus = TempAuthenticationStatus | Authentication;\r
824 return EFI_SUCCESS;\r
825 }\r
b0d803fe 826 }\r
827 }\r
c7935105
SZ
828\r
829 //\r
830 // If SectionCached is TRUE, the section data has been cached and scanned.\r
831 //\r
832 if (!SectionCached) {\r
833 Status = EFI_NOT_FOUND;\r
834 Authentication = 0;\r
835 if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
836 if (IS_SECTION2 (Section)) {\r
837 SectionDefinitionGuid = &((EFI_GUID_DEFINED_SECTION2 *)Section)->SectionDefinitionGuid;\r
838 } else {\r
839 SectionDefinitionGuid = &((EFI_GUID_DEFINED_SECTION *)Section)->SectionDefinitionGuid;\r
840 }\r
841 if (VerifyGuidedSectionGuid (SectionDefinitionGuid, &GuidSectionPpi)) {\r
842 Status = GuidSectionPpi->ExtractSection (\r
843 GuidSectionPpi,\r
844 Section,\r
845 &PpiOutput,\r
846 &PpiOutputSize,\r
847 &Authentication\r
848 );\r
849 }\r
850 } else if (Section->Type == EFI_SECTION_COMPRESSION) {\r
851 Status = PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid, 0, NULL, (VOID **) &DecompressPpi);\r
852 if (!EFI_ERROR (Status)) {\r
853 Status = DecompressPpi->Decompress (\r
854 DecompressPpi,\r
855 (CONST EFI_COMPRESSION_SECTION*) Section,\r
856 &PpiOutput,\r
857 &PpiOutputSize\r
858 );\r
859 }\r
288f9b38 860 }\r
c7935105 861\r
288f9b38 862 if (!EFI_ERROR (Status)) {\r
c7935105
SZ
863 //\r
864 // Update cache section data.\r
865 //\r
866 if (PrivateData->CacheSection.AllSectionCount < CACHE_SETION_MAX_NUMBER) {\r
867 PrivateData->CacheSection.AllSectionCount ++;\r
868 }\r
869 PrivateData->CacheSection.Section [PrivateData->CacheSection.SectionIndex] = Section;\r
870 PrivateData->CacheSection.SectionData [PrivateData->CacheSection.SectionIndex] = PpiOutput;\r
871 PrivateData->CacheSection.SectionSize [PrivateData->CacheSection.SectionIndex] = PpiOutputSize;\r
872 PrivateData->CacheSection.AuthenticationStatus [PrivateData->CacheSection.SectionIndex] = Authentication;\r
873 PrivateData->CacheSection.SectionIndex = (PrivateData->CacheSection.SectionIndex + 1)%CACHE_SETION_MAX_NUMBER;\r
874\r
875 TempAuthenticationStatus = 0;\r
876 Status = ProcessSection (\r
877 PeiServices,\r
878 SectionType,\r
879 SectionInstance,\r
880 PpiOutput, \r
881 PpiOutputSize, \r
882 &TempOutputBuffer,\r
883 &TempAuthenticationStatus,\r
884 IsFfs3Fv\r
885 );\r
886 if (!EFI_ERROR (Status)) {\r
887 *OutputBuffer = TempOutputBuffer;\r
888 *AuthenticationStatus = TempAuthenticationStatus | Authentication;\r
889 return EFI_SUCCESS;\r
890 }\r
288f9b38 891 }\r
288f9b38 892 }\r
b0d803fe 893 }\r
894\r
890e5417
SZ
895 if (IS_SECTION2 (Section)) {\r
896 SectionLength = SECTION2_SIZE (Section);\r
897 } else {\r
898 SectionLength = SECTION_SIZE (Section);\r
899 }\r
b0d803fe 900 //\r
b0d803fe 901 // SectionLength is adjusted it is 4 byte aligned.\r
902 // Go to the next section\r
903 //\r
b0d803fe 904 SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
905 ASSERT (SectionLength != 0);\r
906 ParsedLength += SectionLength;\r
907 Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);\r
908 }\r
909 \r
910 return EFI_NOT_FOUND;\r
911}\r
912\r
192f6d4c 913\r
b1f6a7c6 914/**\r
3b428ade 915 Searches for the next matching section within the specified file.\r
b1f6a7c6 916\r
ed299e3c 917 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
b1f6a7c6 918 @param SectionType Filter to find only sections of this type.\r
919 @param FileHandle Pointer to the current file to search.\r
ed299e3c 920 @param SectionData A pointer to the discovered section, if successful.\r
b1f6a7c6 921 NULL if section not found\r
922\r
3b428ade 923 @retval EFI_NOT_FOUND The section was not found.\r
924 @retval EFI_SUCCESS The section was found.\r
b1f6a7c6 925\r
926**/\r
192f6d4c 927EFI_STATUS\r
928EFIAPI\r
929PeiFfsFindSectionData (\r
3b428ade 930 IN CONST EFI_PEI_SERVICES **PeiServices,\r
192f6d4c 931 IN EFI_SECTION_TYPE SectionType,\r
0c2b5da8 932 IN EFI_PEI_FILE_HANDLE FileHandle,\r
3b428ade 933 OUT VOID **SectionData\r
192f6d4c 934 )\r
192f6d4c 935{\r
3b428ade 936 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
937 \r
938 CoreFvHandle = FileHandleToVolume (FileHandle);\r
939 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {\r
940 return EFI_NOT_FOUND;\r
941 }\r
942 \r
943 return CoreFvHandle->FvPpi->FindSectionByType (CoreFvHandle->FvPpi, SectionType, FileHandle, SectionData);\r
192f6d4c 944}\r
945\r
c7935105
SZ
946/**\r
947 Searches for the next matching section within the specified file.\r
948\r
949 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
950 @param SectionType The value of the section type to find.\r
951 @param SectionInstance Section instance to find.\r
952 @param FileHandle Handle of the firmware file to search.\r
953 @param SectionData A pointer to the discovered section, if successful.\r
954 @param AuthenticationStatus A pointer to the authentication status for this section.\r
955\r
956 @retval EFI_SUCCESS The section was found.\r
957 @retval EFI_NOT_FOUND The section was not found.\r
958\r
959**/\r
960EFI_STATUS\r
961EFIAPI\r
962PeiFfsFindSectionData3 (\r
963 IN CONST EFI_PEI_SERVICES **PeiServices,\r
964 IN EFI_SECTION_TYPE SectionType,\r
965 IN UINTN SectionInstance,\r
966 IN EFI_PEI_FILE_HANDLE FileHandle,\r
967 OUT VOID **SectionData,\r
968 OUT UINT32 *AuthenticationStatus\r
969 )\r
970{\r
971 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
972 \r
973 CoreFvHandle = FileHandleToVolume (FileHandle);\r
974 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {\r
975 return EFI_NOT_FOUND;\r
976 }\r
977\r
978 if ((CoreFvHandle->FvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) &&\r
979 (CoreFvHandle->FvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION)) {\r
980 return CoreFvHandle->FvPpi->FindSectionByType2 (CoreFvHandle->FvPpi, SectionType, SectionInstance, FileHandle, SectionData, AuthenticationStatus);\r
981 }\r
982 //\r
983 // The old FvPpi doesn't support to find section by section instance\r
984 // and return authentication status, so return EFI_UNSUPPORTED.\r
985 //\r
986 return EFI_UNSUPPORTED;\r
987}\r
988\r
b1f6a7c6 989/**\r
3b428ade 990 Searches for the next matching file in the firmware volume.\r
b1f6a7c6 991\r
d73d93c3 992 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
b1f6a7c6 993 @param SearchType Filter to find only files of this type.\r
994 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.\r
aa75dfec 995 @param FvHandle Handle of firmware volume in which to search.\r
3b428ade 996 @param FileHandle On entry, points to the current handle from which to begin searching or NULL to start\r
997 at the beginning of the firmware volume. On exit, points the file handle of the next file\r
998 in the volume or NULL if there are no more files.\r
999\r
1000 @retval EFI_NOT_FOUND The file was not found.\r
1001 @retval EFI_NOT_FOUND The header checksum was not zero.\r
1002 @retval EFI_SUCCESS The file was found.\r
b1f6a7c6 1003\r
1004**/\r
192f6d4c 1005EFI_STATUS\r
1006EFIAPI\r
1007PeiFfsFindNextFile (\r
0c2b5da8 1008 IN CONST EFI_PEI_SERVICES **PeiServices,\r
1009 IN UINT8 SearchType,\r
3b428ade 1010 IN EFI_PEI_FV_HANDLE FvHandle,\r
0c2b5da8 1011 IN OUT EFI_PEI_FILE_HANDLE *FileHandle\r
192f6d4c 1012 )\r
192f6d4c 1013{\r
3b428ade 1014 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
1015 \r
1016 CoreFvHandle = FvHandleToCoreHandle (FvHandle);\r
1017 \r
2f016ba8 1018 //\r
1019 // To make backward compatiblity, if can not find corresponding the handle of FV\r
890e5417 1020 // then treat FV as build-in FFS2/FFS3 format and memory mapped FV that FV handle is pointed\r
2f016ba8 1021 // to the address of first byte of FV.\r
1022 //\r
1023 if ((CoreFvHandle == NULL) && FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {\r
1024 return FindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL);\r
1025 } \r
1026 \r
3b428ade 1027 if ((CoreFvHandle == NULL) || CoreFvHandle->FvPpi == NULL) {\r
1028 return EFI_NOT_FOUND;\r
1029 }\r
1030 \r
1031 return CoreFvHandle->FvPpi->FindFileByType (CoreFvHandle->FvPpi, SearchType, FvHandle, FileHandle);\r
192f6d4c 1032}\r
1033\r
b0d803fe 1034\r
b1f6a7c6 1035/**\r
ed299e3c 1036 Search the firmware volumes by index\r
b1f6a7c6 1037\r
ed299e3c 1038 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
3b428ade 1039 @param Instance This instance of the firmware volume to find. The value 0 is the Boot Firmware\r
1040 Volume (BFV).\r
1041 @param VolumeHandle On exit, points to the next volume handle or NULL if it does not exist.\r
b1f6a7c6 1042\r
3b428ade 1043 @retval EFI_INVALID_PARAMETER VolumeHandle is NULL\r
1044 @retval EFI_NOT_FOUND The volume was not found.\r
1045 @retval EFI_SUCCESS The volume was found.\r
b1f6a7c6 1046\r
1047**/\r
192f6d4c 1048EFI_STATUS \r
1049EFIAPI\r
3b428ade 1050PeiFfsFindNextVolume (\r
2a00326e 1051 IN CONST EFI_PEI_SERVICES **PeiServices,\r
192f6d4c 1052 IN UINTN Instance,\r
0c2b5da8 1053 IN OUT EFI_PEI_FV_HANDLE *VolumeHandle\r
192f6d4c 1054 )\r
192f6d4c 1055{\r
3b428ade 1056 PEI_CORE_INSTANCE *Private;\r
1057 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
1058 \r
3e4c5b49 1059 if (VolumeHandle == NULL) {\r
1060 return EFI_INVALID_PARAMETER;\r
1061 }\r
1062 \r
b0d803fe 1063 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
2a00326e 1064 \r
3b428ade 1065 CoreFvHandle = FindNextCoreFvHandle (Private, Instance);\r
1066 if (CoreFvHandle == NULL) {\r
1067 *VolumeHandle = NULL;\r
1068 return EFI_NOT_FOUND;\r
2a00326e 1069 }\r
3b428ade 1070 \r
1071 *VolumeHandle = CoreFvHandle->FvHandle;\r
1072 \r
b0d803fe 1073 return EFI_SUCCESS;\r
1074}\r
192f6d4c 1075\r
192f6d4c 1076\r
b1f6a7c6 1077/**\r
ed299e3c 1078 Find a file within a volume by its name.\r
b1f6a7c6 1079\r
ed299e3c
LG
1080 @param FileName A pointer to the name of the file to find within the firmware volume.\r
1081 @param VolumeHandle The firmware volume to search\r
1082 @param FileHandle Upon exit, points to the found file's handle \r
1083 or NULL if it could not be found.\r
b1f6a7c6 1084\r
ed299e3c
LG
1085 @retval EFI_SUCCESS File was found.\r
1086 @retval EFI_NOT_FOUND File was not found.\r
1087 @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or FileName was NULL.\r
b1f6a7c6 1088\r
b1f6a7c6 1089**/\r
b0d803fe 1090EFI_STATUS\r
1091EFIAPI \r
1092PeiFfsFindFileByName (\r
1093 IN CONST EFI_GUID *FileName,\r
1094 IN EFI_PEI_FV_HANDLE VolumeHandle,\r
1095 OUT EFI_PEI_FILE_HANDLE *FileHandle\r
1096 )\r
b0d803fe 1097{\r
3b428ade 1098 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
1099 \r
b0d803fe 1100 if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {\r
192f6d4c 1101 return EFI_INVALID_PARAMETER;\r
1102 }\r
3b428ade 1103 \r
1104 CoreFvHandle = FvHandleToCoreHandle (VolumeHandle);\r
1105 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {\r
1106 return EFI_NOT_FOUND;\r
b0d803fe 1107 }\r
3b428ade 1108 \r
1109 return CoreFvHandle->FvPpi->FindFileByName (CoreFvHandle->FvPpi, FileName, &VolumeHandle, FileHandle);\r
b0d803fe 1110}\r
1111\r
b1f6a7c6 1112/**\r
b1f6a7c6 1113 Returns information about a specific file.\r
1114\r
3b428ade 1115 @param FileHandle Handle of the file.\r
4237d40b 1116 @param FileInfo Upon exit, points to the file's information.\r
b1f6a7c6 1117\r
3b428ade 1118 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.\r
1119 @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file.\r
1120 @retval EFI_SUCCESS File information returned.\r
b1f6a7c6 1121\r
1122**/\r
b0d803fe 1123EFI_STATUS\r
1124EFIAPI \r
1125PeiFfsGetFileInfo (\r
1126 IN EFI_PEI_FILE_HANDLE FileHandle,\r
1127 OUT EFI_FV_FILE_INFO *FileInfo\r
1128 )\r
b0d803fe 1129{\r
3b428ade 1130 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
1131 \r
b0d803fe 1132 if ((FileHandle == NULL) || (FileInfo == NULL)) {\r
1133 return EFI_INVALID_PARAMETER;\r
1134 }\r
1135\r
1136 //\r
1137 // Retrieve the FirmwareVolume which the file resides in.\r
1138 //\r
3b428ade 1139 CoreFvHandle = FileHandleToVolume (FileHandle);\r
1140 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {\r
b0d803fe 1141 return EFI_INVALID_PARAMETER;\r
1142 }\r
1143\r
3b428ade 1144 return CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, FileHandle, FileInfo);\r
b0d803fe 1145}\r
1146\r
c7935105
SZ
1147/**\r
1148 Returns information about a specific file.\r
1149\r
1150 @param FileHandle Handle of the file.\r
1151 @param FileInfo Upon exit, points to the file's information.\r
1152\r
1153 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.\r
1154 @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file.\r
1155 @retval EFI_SUCCESS File information returned.\r
1156\r
1157**/\r
1158EFI_STATUS\r
1159EFIAPI \r
1160PeiFfsGetFileInfo2 (\r
1161 IN EFI_PEI_FILE_HANDLE FileHandle,\r
1162 OUT EFI_FV_FILE_INFO2 *FileInfo\r
1163 )\r
1164{\r
1165 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
1166 \r
1167 if ((FileHandle == NULL) || (FileInfo == NULL)) {\r
1168 return EFI_INVALID_PARAMETER;\r
1169 }\r
1170\r
1171 //\r
1172 // Retrieve the FirmwareVolume which the file resides in.\r
1173 //\r
1174 CoreFvHandle = FileHandleToVolume (FileHandle);\r
1175 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {\r
1176 return EFI_INVALID_PARAMETER;\r
1177 }\r
1178\r
1179 if ((CoreFvHandle->FvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) &&\r
1180 (CoreFvHandle->FvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION)) {\r
1181 return CoreFvHandle->FvPpi->GetFileInfo2 (CoreFvHandle->FvPpi, FileHandle, FileInfo);\r
1182 }\r
1183 //\r
1184 // The old FvPpi doesn't support to return file info with authentication status,\r
1185 // so return EFI_UNSUPPORTED.\r
1186 //\r
1187 return EFI_UNSUPPORTED;\r
1188}\r
b0d803fe 1189\r
b1f6a7c6 1190/**\r
3b428ade 1191 Returns information about the specified volume.\r
b1f6a7c6 1192\r
5a9403b8 1193 This function returns information about a specific firmware\r
1194 volume, including its name, type, attributes, starting address\r
1195 and size.\r
1196\r
1197 @param VolumeHandle Handle of the volume.\r
1198 @param VolumeInfo Upon exit, points to the volume's information.\r
1199\r
1200 @retval EFI_SUCCESS Volume information returned.\r
1201 @retval EFI_INVALID_PARAMETER If VolumeHandle does not represent a valid volume.\r
1202 @retval EFI_INVALID_PARAMETER If VolumeHandle is NULL.\r
1203 @retval EFI_SUCCESS Information successfully returned.\r
1204 @retval EFI_INVALID_PARAMETER The volume designated by the VolumeHandle is not available.\r
b1f6a7c6 1205\r
b1f6a7c6 1206**/\r
b0d803fe 1207EFI_STATUS\r
1208EFIAPI \r
1209PeiFfsGetVolumeInfo (\r
1210 IN EFI_PEI_FV_HANDLE VolumeHandle,\r
1211 OUT EFI_FV_INFO *VolumeInfo\r
1212 )\r
b0d803fe 1213{\r
3b428ade 1214 PEI_CORE_FV_HANDLE *CoreHandle;\r
1215 \r
8fdcc412 1216 if ((VolumeInfo == NULL) || (VolumeHandle == NULL)) {\r
b0d803fe 1217 return EFI_INVALID_PARAMETER;\r
192f6d4c 1218 }\r
288f9b38 1219 \r
3b428ade 1220 CoreHandle = FvHandleToCoreHandle (VolumeHandle);\r
1221 \r
1222 if ((CoreHandle == NULL) || (CoreHandle->FvPpi == NULL)) {\r
288f9b38
LG
1223 return EFI_INVALID_PARAMETER;\r
1224 }\r
3b428ade 1225 \r
1226 return CoreHandle->FvPpi->GetVolumeInfo (CoreHandle->FvPpi, VolumeHandle, VolumeInfo);\r
192f6d4c 1227}\r
b0d803fe 1228\r
4c6486b9 1229/**\r
c7935105 1230 Get Fv image from the FV type file, then install FV INFO(2) ppi, Build FV hob.\r
4c6486b9 1231\r
c7935105 1232 @param PrivateData PeiCore's private data structure\r
3b428ade 1233 @param ParentFvCoreHandle Pointer of EFI_CORE_FV_HANDLE to parent Fv image that contain this Fv image.\r
97b2c9b5 1234 @param ParentFvFileHandle File handle of a Fv type file that contain this Fv image.\r
4c6486b9 1235\r
1236 @retval EFI_NOT_FOUND FV image can't be found.\r
1237 @retval EFI_SUCCESS Successfully to process it.\r
1238 @retval EFI_OUT_OF_RESOURCES Can not allocate page when aligning FV image\r
c7935105 1239 @retval EFI_SECURITY_VIOLATION Image is illegal\r
4c6486b9 1240 @retval Others Can not find EFI_SECTION_FIRMWARE_VOLUME_IMAGE section\r
1241 \r
1242**/\r
1243EFI_STATUS\r
1244ProcessFvFile (\r
c7935105 1245 IN PEI_CORE_INSTANCE *PrivateData,\r
3b428ade 1246 IN PEI_CORE_FV_HANDLE *ParentFvCoreHandle,\r
1247 IN EFI_PEI_FILE_HANDLE ParentFvFileHandle\r
4c6486b9 1248 )\r
1249{\r
3b428ade 1250 EFI_STATUS Status;\r
1251 EFI_FV_INFO ParentFvImageInfo;\r
1252 UINT32 FvAlignment;\r
1253 VOID *NewFvBuffer;\r
1254 EFI_PEI_HOB_POINTERS HobPtr;\r
1255 EFI_PEI_FIRMWARE_VOLUME_PPI *ParentFvPpi;\r
1256 EFI_PEI_FV_HANDLE ParentFvHandle;\r
1257 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
1258 EFI_FV_FILE_INFO FileInfo;\r
b4d856a6 1259 UINT64 FvLength;\r
c7935105 1260 UINT32 AuthenticationStatus;\r
3b428ade 1261 \r
4c6486b9 1262 //\r
1263 // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already\r
1264 // been extracted.\r
1265 //\r
1266 HobPtr.Raw = GetHobList ();\r
1267 while ((HobPtr.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobPtr.Raw)) != NULL) {\r
97b2c9b5 1268 if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)ParentFvFileHandle)->Name), &HobPtr.FirmwareVolume2->FileName)) {\r
4c6486b9 1269 //\r
1270 // this FILE has been dispatched, it will not be dispatched again.\r
1271 //\r
3b428ade 1272 DEBUG ((EFI_D_INFO, "FV file %p has been dispatched!\r\n", ParentFvFileHandle));\r
4c6486b9 1273 return EFI_SUCCESS;\r
1274 }\r
1275 HobPtr.Raw = GET_NEXT_HOB (HobPtr);\r
1276 }\r
1277\r
3b428ade 1278 ParentFvHandle = ParentFvCoreHandle->FvHandle;\r
1279 ParentFvPpi = ParentFvCoreHandle->FvPpi;\r
1280 \r
4c6486b9 1281 //\r
1282 // Find FvImage in FvFile\r
1283 //\r
c7935105
SZ
1284 AuthenticationStatus = 0;\r
1285 if ((ParentFvPpi->Signature == EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE) &&\r
1286 (ParentFvPpi->Revision == EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION)) {\r
1287 Status = ParentFvPpi->FindSectionByType2 (\r
1288 ParentFvPpi,\r
1289 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
1290 0,\r
1291 ParentFvFileHandle,\r
1292 (VOID **)&FvHeader,\r
1293 &AuthenticationStatus\r
1294 );\r
1295 } else {\r
1296 Status = ParentFvPpi->FindSectionByType (\r
1297 ParentFvPpi,\r
1298 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
1299 ParentFvFileHandle,\r
1300 (VOID **)&FvHeader\r
1301 );\r
1302 }\r
4c6486b9 1303 if (EFI_ERROR (Status)) {\r
1304 return Status;\r
1305 }\r
97b2c9b5 1306\r
c7935105
SZ
1307 Status = VerifyPeim (PrivateData, ParentFvHandle, ParentFvFileHandle, AuthenticationStatus);\r
1308 if (Status == EFI_SECURITY_VIOLATION) {\r
1309 return Status;\r
1310 }\r
1311\r
97b2c9b5 1312 //\r
3837e91c
SZ
1313 // If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume\r
1314 // can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from\r
1315 // its initial linked location and maintain its alignment.\r
4c6486b9 1316 //\r
3837e91c
SZ
1317 if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) {\r
1318 //\r
1319 // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.\r
1320 //\r
1321 FvAlignment = 1 << ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ALIGNMENT) >> 16);\r
1322 if (FvAlignment < 8) {\r
1323 FvAlignment = 8;\r
1324 }\r
1325\r
1326 //\r
1327 // Check FvImage\r
1328 //\r
1329 if ((UINTN) FvHeader % FvAlignment != 0) {\r
1330 FvLength = ReadUnaligned64 (&FvHeader->FvLength);\r
1331 NewFvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvLength), FvAlignment);\r
1332 if (NewFvBuffer == NULL) {\r
1333 return EFI_OUT_OF_RESOURCES;\r
1334 }\r
1335 CopyMem (NewFvBuffer, FvHeader, (UINTN) FvLength);\r
1336 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) NewFvBuffer;\r
4c6486b9 1337 }\r
4c6486b9 1338 }\r
3837e91c 1339\r
3b428ade 1340 Status = ParentFvPpi->GetVolumeInfo (ParentFvPpi, ParentFvHandle, &ParentFvImageInfo);\r
1341 ASSERT_EFI_ERROR (Status);\r
1342 \r
1343 Status = ParentFvPpi->GetFileInfo (ParentFvPpi, ParentFvFileHandle, &FileInfo);\r
1344 ASSERT_EFI_ERROR (Status);\r
1345 \r
4c6486b9 1346 //\r
387208ab 1347 // Install FvInfo(2) Ppi\r
4c6486b9 1348 //\r
387208ab
SZ
1349 PeiServicesInstallFvInfoPpi (\r
1350 &FvHeader->FileSystemGuid,\r
1351 (VOID**) FvHeader,\r
1352 (UINT32) FvHeader->FvLength,\r
1353 &ParentFvImageInfo.FvName,\r
1354 &FileInfo.FileName\r
1355 );\r
1356\r
c7935105 1357 PeiServicesInstallFvInfo2Ppi (\r
3b428ade 1358 &FvHeader->FileSystemGuid,\r
1359 (VOID**) FvHeader,\r
1360 (UINT32) FvHeader->FvLength,\r
97b2c9b5 1361 &ParentFvImageInfo.FvName,\r
c7935105
SZ
1362 &FileInfo.FileName,\r
1363 AuthenticationStatus\r
4c6486b9 1364 );\r
1365\r
1366 //\r
1367 // Inform the extracted FvImage to Fv HOB consumer phase, i.e. DXE phase\r
4c6486b9 1368 //\r
223c22d8 1369 BuildFvHob (\r
3b428ade 1370 (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,\r
1371 FvHeader->FvLength\r
18fcd6a7 1372 );\r
4c6486b9 1373\r
1374 //\r
1375 // Makes the encapsulated volume show up in DXE phase to skip processing of\r
1376 // encapsulated file again.\r
1377 //\r
1378 BuildFv2Hob (\r
3b428ade 1379 (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,\r
1380 FvHeader->FvLength,\r
97b2c9b5 1381 &ParentFvImageInfo.FvName,\r
3b428ade 1382 &FileInfo.FileName\r
4c6486b9 1383 );\r
1384\r
1385 return EFI_SUCCESS;\r
1386}\r
1387\r
3b428ade 1388/**\r
1389 Process a firmware volume and create a volume handle.\r
1390\r
1391 Create a volume handle from the information in the buffer. For\r
1392 memory-mapped firmware volumes, Buffer and BufferSize refer to\r
1393 the start of the firmware volume and the firmware volume size.\r
1394 For non memory-mapped firmware volumes, this points to a\r
1395 buffer which contains the necessary information for creating\r
1396 the firmware volume handle. Normally, these values are derived\r
1397 from the EFI_FIRMWARE_VOLUME_INFO_PPI.\r
1398 \r
1399 \r
1400 @param This Points to this instance of the\r
1401 EFI_PEI_FIRMWARE_VOLUME_PPI.\r
1402 @param Buffer Points to the start of the buffer.\r
1403 @param BufferSize Size of the buffer.\r
1404 @param FvHandle Points to the returned firmware volume\r
1405 handle. The firmware volume handle must\r
1406 be unique within the system. \r
1407\r
1408 @retval EFI_SUCCESS Firmware volume handle created.\r
1409 @retval EFI_VOLUME_CORRUPTED Volume was corrupt.\r
1410\r
1411**/\r
1412EFI_STATUS\r
1413EFIAPI\r
890e5417 1414PeiFfsFvPpiProcessVolume (\r
3b428ade 1415 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,\r
1416 IN VOID *Buffer,\r
1417 IN UINTN BufferSize,\r
1418 OUT EFI_PEI_FV_HANDLE *FvHandle\r
1419 )\r
1420{\r
1421 EFI_STATUS Status;\r
3b428ade 1422 \r
dc6f9b35 1423 ASSERT (FvHandle != NULL);\r
1424 \r
1425 if (Buffer == NULL) {\r
1426 return EFI_VOLUME_CORRUPTED;\r
1427 }\r
3b428ade 1428 \r
1429 //\r
890e5417 1430 // The build-in EFI_PEI_FIRMWARE_VOLUME_PPI for FFS2/FFS3 support memory-mapped\r
3b428ade 1431 // FV image and the handle is pointed to Fv image's buffer.\r
1432 //\r
1433 *FvHandle = (EFI_PEI_FV_HANDLE) Buffer;\r
1434 \r
1435 //\r
1436 // Do verify for given FV buffer.\r
1437 //\r
1438 Status = VerifyFv ((EFI_FIRMWARE_VOLUME_HEADER*) Buffer);\r
1439 if (EFI_ERROR(Status)) {\r
1440 DEBUG ((EFI_D_ERROR, "Fail to verify FV which address is 0x%11p", Buffer));\r
1441 return EFI_VOLUME_CORRUPTED;\r
1442 }\r
1443\r
3b428ade 1444 return EFI_SUCCESS;\r
1445} \r
1446\r
1447/**\r
1448 Finds the next file of the specified type.\r
1449\r
1450 This service enables PEI modules to discover additional firmware files. \r
1451 The FileHandle must be unique within the system.\r
1452\r
1453 @param This Points to this instance of the\r
1454 EFI_PEI_FIRMWARE_VOLUME_PPI.\r
1455 @param SearchType A filter to find only files of this type. Type\r
1456 EFI_FV_FILETYPE_ALL causes no filtering to be\r
1457 done.\r
1458 @param FvHandle Handle of firmware volume in which to\r
1459 search.\r
1460 @param FileHandle Points to the current handle from which to\r
1461 begin searching or NULL to start at the\r
1462 beginning of the firmware volume. Updated\r
1463 upon return to reflect the file found.\r
1464\r
1465 @retval EFI_SUCCESS The file was found.\r
1466 @retval EFI_NOT_FOUND The file was not found. FileHandle contains NULL.\r
1467\r
1468**/\r
1469EFI_STATUS\r
1470EFIAPI\r
890e5417 1471PeiFfsFvPpiFindFileByType (\r
3b428ade 1472 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,\r
1473 IN EFI_FV_FILETYPE SearchType,\r
1474 IN EFI_PEI_FV_HANDLE FvHandle,\r
1475 IN OUT EFI_PEI_FILE_HANDLE *FileHandle\r
1476 )\r
1477{ \r
1478 return FindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL);\r
1479}\r
1480\r
1481/**\r
1482 Find a file within a volume by its name. \r
1483 \r
1484 This service searches for files with a specific name, within\r
1485 either the specified firmware volume or all firmware volumes.\r
1486\r
1487 @param This Points to this instance of the\r
1488 EFI_PEI_FIRMWARE_VOLUME_PPI.\r
1489 @param FileName A pointer to the name of the file to find\r
1490 within the firmware volume.\r
1491 @param FvHandle Upon entry, the pointer to the firmware\r
1492 volume to search or NULL if all firmware\r
1493 volumes should be searched. Upon exit, the\r
1494 actual firmware volume in which the file was\r
1495 found.\r
1496 @param FileHandle Upon exit, points to the found file's\r
1497 handle or NULL if it could not be found.\r
1498\r
1499 @retval EFI_SUCCESS File was found.\r
1500 @retval EFI_NOT_FOUND File was not found.\r
1501 @retval EFI_INVALID_PARAMETER FvHandle or FileHandle or\r
1502 FileName was NULL.\r
1503\r
1504\r
1505**/\r
1506EFI_STATUS\r
1507EFIAPI\r
890e5417 1508PeiFfsFvPpiFindFileByName (\r
3b428ade 1509 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,\r
1510 IN CONST EFI_GUID *FileName,\r
1511 IN EFI_PEI_FV_HANDLE *FvHandle,\r
1512 OUT EFI_PEI_FILE_HANDLE *FileHandle \r
1513 )\r
1514{\r
1515 EFI_STATUS Status;\r
1516 PEI_CORE_INSTANCE *PrivateData;\r
1517 UINTN Index;\r
1518 \r
1519 if ((FvHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {\r
1520 return EFI_INVALID_PARAMETER;\r
1521 }\r
1522 \r
1523 if (*FvHandle != NULL) {\r
1524 Status = FindFileEx (*FvHandle, FileName, 0, FileHandle, NULL);\r
1525 if (Status == EFI_NOT_FOUND) {\r
1526 *FileHandle = NULL;\r
1527 }\r
1528 } else { \r
1529 //\r
1530 // If *FvHandle = NULL, so search all FV for given filename\r
1531 //\r
1532 Status = EFI_NOT_FOUND;\r
1533 \r
1534 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer());\r
1535 for (Index = 0; Index < PrivateData->FvCount; Index ++) {\r
1536 //\r
1537 // Only search the FV which is associated with a EFI_PEI_FIRMWARE_VOLUME_PPI instance.\r
1538 //\r
1539 if (PrivateData->Fv[Index].FvPpi != NULL) {\r
1540 Status = FindFileEx (PrivateData->Fv[Index].FvHandle, FileName, 0, FileHandle, NULL);\r
1541 if (!EFI_ERROR (Status)) {\r
1542 *FvHandle = PrivateData->Fv[Index].FvHandle;\r
1c738c8f 1543 break;\r
3b428ade 1544 }\r
1545 }\r
1546 }\r
1547 }\r
1548 \r
1549 return Status; \r
1550} \r
1551\r
1552/**\r
1553 Returns information about a specific file.\r
1554\r
1555 This function returns information about a specific\r
1556 file, including its file name, type, attributes, starting\r
1557 address and size. \r
1558 \r
1559 @param This Points to this instance of the\r
1560 EFI_PEI_FIRMWARE_VOLUME_PPI.\r
1561 @param FileHandle Handle of the file.\r
1562 @param FileInfo Upon exit, points to the file's\r
1563 information.\r
1564\r
1565 @retval EFI_SUCCESS File information returned.\r
1566 @retval EFI_INVALID_PARAMETER If FileHandle does not\r
1567 represent a valid file.\r
1568 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.\r
1569 \r
1570**/ \r
1571EFI_STATUS\r
1572EFIAPI\r
890e5417 1573PeiFfsFvPpiGetFileInfo (\r
3b428ade 1574 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, \r
1575 IN EFI_PEI_FILE_HANDLE FileHandle, \r
1576 OUT EFI_FV_FILE_INFO *FileInfo\r
1577 )\r
1578{\r
1579 UINT8 FileState;\r
1580 UINT8 ErasePolarity;\r
1581 EFI_FFS_FILE_HEADER *FileHeader;\r
1582 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
890e5417
SZ
1583 PEI_FW_VOL_INSTANCE *FwVolInstance;\r
1584\r
3b428ade 1585 if ((FileHandle == NULL) || (FileInfo == NULL)) {\r
1586 return EFI_INVALID_PARAMETER;\r
1587 }\r
1588\r
1589 //\r
1590 // Retrieve the FirmwareVolume which the file resides in.\r
1591 //\r
1592 CoreFvHandle = FileHandleToVolume (FileHandle);\r
1593 if (CoreFvHandle == NULL) {\r
1594 return EFI_INVALID_PARAMETER;\r
1595 }\r
1596\r
890e5417
SZ
1597 FwVolInstance = PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This);\r
1598\r
4140a663 1599 if ((CoreFvHandle->FvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) != 0) {\r
3b428ade 1600 ErasePolarity = 1;\r
1601 } else {\r
1602 ErasePolarity = 0;\r
1603 }\r
1604\r
1605 //\r
1606 // Get FileState which is the highest bit of the State \r
1607 //\r
1608 FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle);\r
1609\r
1610 switch (FileState) {\r
1611 case EFI_FILE_DATA_VALID:\r
1612 case EFI_FILE_MARKED_FOR_UPDATE:\r
1613 break; \r
1614 default:\r
1615 return EFI_INVALID_PARAMETER;\r
1616 }\r
1617\r
1618 FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;\r
890e5417
SZ
1619 if (IS_FFS_FILE2 (FileHeader)) {\r
1620 ASSERT (FFS_FILE2_SIZE (FileHeader) > 0x00FFFFFF);\r
1621 if (!FwVolInstance->IsFfs3Fv) {\r
1622 DEBUG ((EFI_D_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FileHeader->Name));\r
1623 return EFI_INVALID_PARAMETER;\r
1624 }\r
1625 FileInfo->BufferSize = FFS_FILE2_SIZE (FileHeader) - sizeof (EFI_FFS_FILE_HEADER2);\r
1626 FileInfo->Buffer = (UINT8 *) FileHeader + sizeof (EFI_FFS_FILE_HEADER2);\r
1627 } else {\r
1628 FileInfo->BufferSize = FFS_FILE_SIZE (FileHeader) - sizeof (EFI_FFS_FILE_HEADER);\r
1629 FileInfo->Buffer = (UINT8 *) FileHeader + sizeof (EFI_FFS_FILE_HEADER);\r
1630 }\r
c7935105
SZ
1631 CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID));\r
1632 FileInfo->FileType = FileHeader->Type;\r
1633 FileInfo->FileAttributes = FfsAttributes2FvFileAttributes (FileHeader->Attributes);\r
1634 if ((CoreFvHandle->FvHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) {\r
1635 FileInfo->FileAttributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED;\r
1636 }\r
1637 return EFI_SUCCESS;\r
1638}\r
1639\r
1640/**\r
1641 Returns information about a specific file.\r
1642\r
1643 This function returns information about a specific\r
1644 file, including its file name, type, attributes, starting\r
1645 address, size and authentication status.\r
1646\r
1647 @param This Points to this instance of the\r
1648 EFI_PEI_FIRMWARE_VOLUME_PPI.\r
1649 @param FileHandle Handle of the file.\r
1650 @param FileInfo Upon exit, points to the file's\r
1651 information.\r
1652\r
1653 @retval EFI_SUCCESS File information returned.\r
1654 @retval EFI_INVALID_PARAMETER If FileHandle does not\r
1655 represent a valid file.\r
1656 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.\r
1657\r
1658**/\r
1659EFI_STATUS\r
1660EFIAPI\r
1661PeiFfsFvPpiGetFileInfo2 (\r
1662 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, \r
1663 IN EFI_PEI_FILE_HANDLE FileHandle, \r
1664 OUT EFI_FV_FILE_INFO2 *FileInfo\r
1665 )\r
1666{\r
1667 EFI_STATUS Status;\r
1668 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
1669\r
1670 if ((FileHandle == NULL) || (FileInfo == NULL)) {\r
1671 return EFI_INVALID_PARAMETER;\r
1672 }\r
1673\r
1674 //\r
1675 // Retrieve the FirmwareVolume which the file resides in.\r
1676 //\r
1677 CoreFvHandle = FileHandleToVolume (FileHandle);\r
1678 if (CoreFvHandle == NULL) {\r
1679 return EFI_INVALID_PARAMETER;\r
1680 }\r
1681\r
1682 Status = PeiFfsFvPpiGetFileInfo (This, FileHandle, (EFI_FV_FILE_INFO *) FileInfo);\r
1683 if (!EFI_ERROR (Status)) {\r
1684 FileInfo->AuthenticationStatus = CoreFvHandle->AuthenticationStatus;\r
1685 }\r
1686\r
1687 return Status;\r
1688}\r
1689\r
3b428ade 1690/**\r
1691 This function returns information about the firmware volume.\r
1692 \r
1693 @param This Points to this instance of the\r
1694 EFI_PEI_FIRMWARE_VOLUME_PPI.\r
1695 @param FvHandle Handle to the firmware handle.\r
1696 @param VolumeInfo Points to the returned firmware volume\r
1697 information.\r
1698\r
1699 @retval EFI_SUCCESS Information returned successfully.\r
1700 @retval EFI_INVALID_PARAMETER FvHandle does not indicate a valid\r
1701 firmware volume or VolumeInfo is NULL.\r
1702\r
1703**/ \r
1704EFI_STATUS\r
1705EFIAPI\r
890e5417 1706PeiFfsFvPpiGetVolumeInfo (\r
3b428ade 1707 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, \r
1708 IN EFI_PEI_FV_HANDLE FvHandle, \r
1709 OUT EFI_FV_INFO *VolumeInfo\r
1710 )\r
1711{\r
1712 EFI_FIRMWARE_VOLUME_HEADER FwVolHeader;\r
1713 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;\r
1714\r
8fdcc412 1715 if ((VolumeInfo == NULL) || (FvHandle == NULL)) {\r
3b428ade 1716 return EFI_INVALID_PARAMETER;\r
1717 }\r
1718 \r
1719 //\r
1720 // VolumeHandle may not align at 8 byte, \r
1721 // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte. \r
1722 // So, Copy FvHeader into the local FvHeader structure.\r
1723 //\r
1724 CopyMem (&FwVolHeader, FvHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
1725\r
1726 //\r
1727 // Check Fv Image Signature\r
1728 //\r
1729 if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {\r
1730 return EFI_INVALID_PARAMETER;\r
1731 }\r
1732\r
1733 ZeroMem (VolumeInfo, sizeof (EFI_FV_INFO));\r
1734 VolumeInfo->FvAttributes = FwVolHeader.Attributes;\r
1735 VolumeInfo->FvStart = (VOID *) FvHandle;\r
1736 VolumeInfo->FvSize = FwVolHeader.FvLength;\r
1737 CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID));\r
1738\r
1739 if (FwVolHeader.ExtHeaderOffset != 0) {\r
1740 FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)FvHandle) + FwVolHeader.ExtHeaderOffset);\r
1741 CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID));\r
1742 }\r
1743 \r
1744 return EFI_SUCCESS; \r
1745} \r
1746\r
1747/**\r
1748 Find the next matching section in the firmware file.\r
1749 \r
1750 This service enables PEI modules to discover sections\r
1751 of a given type within a valid file.\r
1752 \r
1753 @param This Points to this instance of the\r
1754 EFI_PEI_FIRMWARE_VOLUME_PPI.\r
1755 @param SearchType A filter to find only sections of this\r
1756 type.\r
1757 @param FileHandle Handle of firmware file in which to\r
1758 search.\r
890e5417 1759 @param SectionData Updated upon return to point to the\r
3b428ade 1760 section found.\r
1761 \r
1762 @retval EFI_SUCCESS Section was found.\r
1763 @retval EFI_NOT_FOUND Section of the specified type was not\r
1764 found. SectionData contains NULL.\r
1765**/\r
1766EFI_STATUS\r
1767EFIAPI\r
890e5417 1768PeiFfsFvPpiFindSectionByType (\r
3b428ade 1769 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,\r
1770 IN EFI_SECTION_TYPE SearchType,\r
1771 IN EFI_PEI_FILE_HANDLE FileHandle,\r
1772 OUT VOID **SectionData\r
1773 )\r
1774{\r
c7935105
SZ
1775 UINT32 AuthenticationStatus;\r
1776 return PeiFfsFvPpiFindSectionByType2 (This, SearchType, 0, FileHandle, SectionData, &AuthenticationStatus);\r
1777}\r
1778\r
1779/**\r
1780 Find the next matching section in the firmware file.\r
1781\r
1782 This service enables PEI modules to discover sections\r
1783 of a given instance and type within a valid file.\r
1784\r
1785 @param This Points to this instance of the\r
1786 EFI_PEI_FIRMWARE_VOLUME_PPI.\r
1787 @param SearchType A filter to find only sections of this\r
1788 type.\r
1789 @param SearchInstance A filter to find the specific instance\r
1790 of sections.\r
1791 @param FileHandle Handle of firmware file in which to\r
1792 search.\r
1793 @param SectionData Updated upon return to point to the\r
1794 section found.\r
1795 @param AuthenticationStatus Updated upon return to point to the\r
1796 authentication status for this section.\r
1797\r
1798 @retval EFI_SUCCESS Section was found.\r
1799 @retval EFI_NOT_FOUND Section of the specified type was not\r
1800 found. SectionData contains NULL.\r
1801**/\r
1802EFI_STATUS\r
1803EFIAPI\r
1804PeiFfsFvPpiFindSectionByType2 (\r
1805 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,\r
1806 IN EFI_SECTION_TYPE SearchType,\r
1807 IN UINTN SearchInstance,\r
1808 IN EFI_PEI_FILE_HANDLE FileHandle,\r
1809 OUT VOID **SectionData,\r
1810 OUT UINT32 *AuthenticationStatus\r
1811 )\r
1812{\r
1813 EFI_STATUS Status;\r
3b428ade 1814 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
1815 UINT32 FileSize;\r
1816 EFI_COMMON_SECTION_HEADER *Section;\r
890e5417 1817 PEI_FW_VOL_INSTANCE *FwVolInstance;\r
c7935105
SZ
1818 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
1819 UINTN Instance;\r
1820 UINT32 ExtractedAuthenticationStatus;\r
1821\r
1822 if (SectionData == NULL) {\r
1823 return EFI_NOT_FOUND;\r
1824 }\r
890e5417
SZ
1825\r
1826 FwVolInstance = PEI_FW_VOL_INSTANCE_FROM_FV_THIS (This);\r
1827\r
c7935105
SZ
1828 //\r
1829 // Retrieve the FirmwareVolume which the file resides in.\r
1830 //\r
1831 CoreFvHandle = FileHandleToVolume (FileHandle);\r
1832 if (CoreFvHandle == NULL) {\r
1833 return EFI_NOT_FOUND;\r
1834 }\r
1835\r
3b428ade 1836 FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);\r
1837\r
890e5417
SZ
1838 if (IS_FFS_FILE2 (FfsFileHeader)) {\r
1839 ASSERT (FFS_FILE2_SIZE (FfsFileHeader) > 0x00FFFFFF);\r
1840 if (!FwVolInstance->IsFfs3Fv) {\r
1841 DEBUG ((EFI_D_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));\r
1842 return EFI_NOT_FOUND;\r
1843 }\r
1844 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2));\r
1845 FileSize = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);\r
1846 } else {\r
1847 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));\r
1848 FileSize = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER);\r
1849 }\r
3b428ade 1850\r
c7935105
SZ
1851 Instance = SearchInstance + 1;\r
1852 ExtractedAuthenticationStatus = 0;\r
1853 Status = ProcessSection (\r
1854 GetPeiServicesTablePointer (),\r
1855 SearchType,\r
1856 &Instance,\r
1857 Section, \r
1858 FileSize, \r
1859 SectionData,\r
1860 &ExtractedAuthenticationStatus,\r
1861 FwVolInstance->IsFfs3Fv\r
1862 );\r
1863 if (!EFI_ERROR (Status)) {\r
1864 //\r
1865 // Inherit the authentication status.\r
1866 //\r
1867 *AuthenticationStatus = ExtractedAuthenticationStatus | CoreFvHandle->AuthenticationStatus;\r
1868 }\r
1869 return Status;\r
1870}\r
3b428ade 1871\r
1872/**\r
1873 Convert the handle of FV to pointer of corresponding PEI_CORE_FV_HANDLE.\r
1874 \r
1875 @param FvHandle The handle of a FV.\r
1876 \r
1877 @retval NULL if can not find.\r
1878 @return Pointer of corresponding PEI_CORE_FV_HANDLE. \r
1879**/\r
1880PEI_CORE_FV_HANDLE *\r
1881FvHandleToCoreHandle (\r
1882 IN EFI_PEI_FV_HANDLE FvHandle\r
1883 )\r
1884{\r
1885 UINTN Index;\r
1886 PEI_CORE_INSTANCE *PrivateData;\r
1887 \r
1888 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer()); \r
1889 for (Index = 0; Index < PrivateData->FvCount; Index ++) {\r
1890 if (FvHandle == PrivateData->Fv[Index].FvHandle) {\r
1891 return &PrivateData->Fv[Index];\r
1892 }\r
1893 }\r
1894 \r
1895 return NULL;\r
1896} \r
1897\r
1898/**\r
1899 Get instance of PEI_CORE_FV_HANDLE for next volume according to given index.\r
1900 \r
1901 This routine also will install FvInfo ppi for FV hob in PI ways.\r
1902 \r
1903 @param Private Pointer of PEI_CORE_INSTANCE\r
1904 @param Instance The index of FV want to be searched.\r
1905 \r
1906 @return Instance of PEI_CORE_FV_HANDLE.\r
1907**/\r
1908PEI_CORE_FV_HANDLE *\r
1909FindNextCoreFvHandle (\r
1910 IN PEI_CORE_INSTANCE *Private,\r
1911 IN UINTN Instance\r
1912 )\r
1913{\r
1914 UINTN Index;\r
1915 BOOLEAN Match;\r
1916 EFI_HOB_FIRMWARE_VOLUME *FvHob;\r
1917 \r
1918 //\r
1919 // Handle Framework FvHob and Install FvInfo Ppi for it.\r
1920 //\r
1921 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {\r
1922 //\r
1923 // Loop to search the wanted FirmwareVolume which supports FFS\r
1924 //\r
1925 FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetFirstHob (EFI_HOB_TYPE_FV);\r
1926 while (FvHob != NULL) {\r
20ead725 1927 //\r
1928 // Search whether FvHob has been installed into PeiCore's FV database.\r
1929 // If found, no need install new FvInfoPpi for it.\r
1930 //\r
3b428ade 1931 for (Index = 0, Match = FALSE; Index < Private->FvCount; Index++) {\r
1932 if ((EFI_PEI_FV_HANDLE)(UINTN)FvHob->BaseAddress == Private->Fv[Index].FvHeader) {\r
1933 Match = TRUE;\r
1934 break;\r
1935 }\r
1936 }\r
20ead725 1937 \r
3b428ade 1938 //\r
20ead725 1939 // Search whether FvHob has been cached into PeiCore's Unknown FV database.\r
1940 // If found, no need install new FvInfoPpi for it.\r
1941 //\r
1942 if (!Match) {\r
1943 for (Index = 0; Index < Private->UnknownFvInfoCount; Index ++) {\r
1944 if ((UINTN)FvHob->BaseAddress == (UINTN)Private->UnknownFvInfo[Index].FvInfo) {\r
1945 Match = TRUE;\r
1946 break;\r
1947 }\r
1948 }\r
1949 }\r
1950\r
1951 //\r
1952 // If the Fv in FvHob has not been installed into PeiCore's FV database and has\r
1953 // not been cached into PeiCore's Unknown FV database, install a new FvInfoPpi\r
1954 // for it then PeiCore will dispatch it in callback of FvInfoPpi.\r
3b428ade 1955 //\r
1956 if (!Match) {\r
1957 PeiServicesInstallFvInfoPpi (\r
1958 &(((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvHob->BaseAddress)->FileSystemGuid),\r
1959 (VOID *)(UINTN)FvHob->BaseAddress,\r
1960 (UINT32)FvHob->Length,\r
1961 NULL,\r
1962 NULL\r
1963 );\r
1964 }\r
20ead725 1965 \r
3b428ade 1966 FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetNextHob (EFI_HOB_TYPE_FV, (VOID *)((UINTN)FvHob + FvHob->Header.HobLength)); \r
1967 }\r
1968 }\r
1969\r
60cf9cfc 1970 ASSERT (Private->FvCount <= FixedPcdGet32 (PcdPeiCoreMaxFvSupported));\r
3b428ade 1971 if (Instance >= Private->FvCount) {\r
1972 return NULL;\r
1973 }\r
4c6486b9 1974\r
3b428ade 1975 return &Private->Fv[Instance];\r
1976} \r
8e0e40ed 1977\r
1978/**\r
1979 After PeiCore image is shadowed into permanent memory, all build-in FvPpi should\r
1980 be re-installed with the instance in permanent memory and all cached FvPpi pointers in \r
1981 PrivateData->Fv[] array should be fixed up to be pointed to the one in permenant\r
1982 memory.\r
1983 \r
1984 @param PrivateData Pointer to PEI_CORE_INSTANCE.\r
1985**/ \r
1986VOID\r
1987PeiReinitializeFv (\r
1988 IN PEI_CORE_INSTANCE *PrivateData\r
1989 )\r
1990{\r
890e5417 1991 VOID *OldFfsFvPpi;\r
7ec93917 1992 EFI_PEI_PPI_DESCRIPTOR *OldDescriptor;\r
1993 UINTN Index;\r
1994 EFI_STATUS Status;\r
1995\r
1996 //\r
1997 // Locate old build-in Ffs2 EFI_PEI_FIRMWARE_VOLUME_PPI which\r
1998 // in flash.\r
1999 //\r
2000 Status = PeiServicesLocatePpi (\r
2001 &gEfiFirmwareFileSystem2Guid,\r
2002 0,\r
2003 &OldDescriptor,\r
890e5417 2004 &OldFfsFvPpi\r
7ec93917 2005 );\r
2006 ASSERT_EFI_ERROR (Status);\r
2007\r
2008 //\r
2009 // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs2\r
2010 // which is shadowed from flash to permanent memory within PeiCore image.\r
2011 //\r
2012 Status = PeiServicesReInstallPpi (OldDescriptor, &mPeiFfs2FvPpiList);\r
2013 ASSERT_EFI_ERROR (Status);\r
890e5417 2014\r
7ec93917 2015 //\r
2016 // Fixup all FvPpi pointers for the implementation in flash to permanent memory.\r
2017 //\r
4140a663 2018 for (Index = 0; Index < FixedPcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {\r
890e5417
SZ
2019 if (PrivateData->Fv[Index].FvPpi == OldFfsFvPpi) {\r
2020 PrivateData->Fv[Index].FvPpi = &mPeiFfs2FwVol.Fv;\r
7ec93917 2021 }\r
2022 }\r
890e5417
SZ
2023\r
2024 //\r
2025 // Locate old build-in Ffs3 EFI_PEI_FIRMWARE_VOLUME_PPI which\r
2026 // in flash.\r
2027 //\r
2028 Status = PeiServicesLocatePpi (\r
2029 &gEfiFirmwareFileSystem3Guid,\r
2030 0,\r
2031 &OldDescriptor,\r
2032 &OldFfsFvPpi\r
2033 );\r
2034 ASSERT_EFI_ERROR (Status);\r
2035\r
2036 //\r
2037 // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs3\r
2038 // which is shadowed from flash to permanent memory within PeiCore image.\r
2039 //\r
2040 Status = PeiServicesReInstallPpi (OldDescriptor, &mPeiFfs3FvPpiList);\r
2041 ASSERT_EFI_ERROR (Status);\r
2042\r
2043 //\r
2044 // Fixup all FvPpi pointers for the implementation in flash to permanent memory.\r
2045 //\r
2046 for (Index = 0; Index < FixedPcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {\r
2047 if (PrivateData->Fv[Index].FvPpi == OldFfsFvPpi) {\r
2048 PrivateData->Fv[Index].FvPpi = &mPeiFfs3FwVol.Fv;\r
2049 }\r
2050 }\r
2051}\r
8e0e40ed 2052\r
f3358329 2053/**\r
2054 Report the information for a new discoveried FV in unknown third-party format.\r
2055 \r
2056 If the EFI_PEI_FIRMWARE_VOLUME_PPI has not been installed for third-party FV format, but\r
c7935105 2057 the FV in this format has been discoveried, then this FV's information will be cached into\r
f3358329 2058 PEI_CORE_INSTANCE's UnknownFvInfo array.\r
2059 Also a notification would be installed for unknown third-party FV format guid, if EFI_PEI_FIRMWARE_VOLUME_PPI\r
2060 is installed later by platform's PEIM, the original unknown third-party FV will be processed by\r
2061 using new installed EFI_PEI_FIRMWARE_VOLUME_PPI.\r
2062 \r
2063 @param PrivateData Point to instance of PEI_CORE_INSTANCE\r
c7935105 2064 @param FvInfo2Ppi Point to FvInfo2 PPI.\r
f3358329 2065 \r
2066 @retval EFI_OUT_OF_RESOURCES The FV info array in PEI_CORE_INSTANCE has no more spaces.\r
2067 @retval EFI_SUCCESS Success to add the information for unknown FV.\r
2068**/\r
2069EFI_STATUS\r
2070AddUnknownFormatFvInfo (\r
c7935105
SZ
2071 IN PEI_CORE_INSTANCE *PrivateData,\r
2072 IN EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI *FvInfo2Ppi\r
f3358329 2073 )\r
2074{\r
2075 PEI_CORE_UNKNOW_FORMAT_FV_INFO *NewUnknownFv;\r
2076 \r
60cf9cfc 2077 if (PrivateData->UnknownFvInfoCount + 1 >= FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {\r
f3358329 2078 return EFI_OUT_OF_RESOURCES;\r
2079 }\r
2080 \r
2081 NewUnknownFv = &PrivateData->UnknownFvInfo[PrivateData->UnknownFvInfoCount];\r
2082 PrivateData->UnknownFvInfoCount ++;\r
2083 \r
c7935105
SZ
2084 CopyGuid (&NewUnknownFv->FvFormat, &FvInfo2Ppi->FvFormat);\r
2085 NewUnknownFv->FvInfo = FvInfo2Ppi->FvInfo;\r
2086 NewUnknownFv->FvInfoSize = FvInfo2Ppi->FvInfoSize;\r
2087 NewUnknownFv->AuthenticationStatus = FvInfo2Ppi->AuthenticationStatus;\r
f3358329 2088 NewUnknownFv->NotifyDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
2089 NewUnknownFv->NotifyDescriptor.Guid = &NewUnknownFv->FvFormat;\r
2090 NewUnknownFv->NotifyDescriptor.Notify = ThirdPartyFvPpiNotifyCallback;\r
2091 \r
2092 PeiServicesNotifyPpi (&NewUnknownFv->NotifyDescriptor);\r
2093 return EFI_SUCCESS;\r
2094}\r
2095\r
2096/**\r
2097 Find the FV information according to third-party FV format guid.\r
2098 \r
2099 This routine also will remove the FV information found by given FV format guid from\r
2100 PrivateData->UnknownFvInfo[].\r
2101 \r
2102 @param PrivateData Point to instance of PEI_CORE_INSTANCE\r
2103 @param Format Point to given FV format guid\r
2104 @param FvInfo On return, the pointer of FV information buffer\r
2105 @param FvInfoSize On return, the size of FV information buffer.\r
c7935105 2106 @param AuthenticationStatus On return, the authentication status of FV information buffer.\r
f3358329 2107 \r
2108 @retval EFI_NOT_FOUND The FV is not found for new installed EFI_PEI_FIRMWARE_VOLUME_PPI\r
2109 @retval EFI_SUCCESS Success to find a FV which could be processed by new installed EFI_PEI_FIRMWARE_VOLUME_PPI.\r
2110**/\r
2111EFI_STATUS\r
2112FindUnknownFormatFvInfo (\r
2113 IN PEI_CORE_INSTANCE *PrivateData,\r
2114 IN EFI_GUID *Format,\r
2115 OUT VOID **FvInfo,\r
c7935105
SZ
2116 OUT UINT32 *FvInfoSize,\r
2117 OUT UINT32 *AuthenticationStatus\r
f3358329 2118 )\r
2119{\r
2120 UINTN Index;\r
2121 UINTN Index2;\r
2122\r
2123 Index = 0;\r
2124 for (; Index < PrivateData->UnknownFvInfoCount; Index ++) {\r
2125 if (CompareGuid (Format, &PrivateData->UnknownFvInfo[Index].FvFormat)) {\r
2126 break;\r
2127 }\r
2128 }\r
2129 \r
2130 if (Index == PrivateData->UnknownFvInfoCount) {\r
2131 return EFI_NOT_FOUND;\r
2132 }\r
2133 \r
2134 *FvInfo = PrivateData->UnknownFvInfo[Index].FvInfo;\r
2135 *FvInfoSize = PrivateData->UnknownFvInfo[Index].FvInfoSize;\r
c7935105 2136 *AuthenticationStatus = PrivateData->UnknownFvInfo[Index].AuthenticationStatus;\r
f3358329 2137 \r
2138 //\r
2139 // Remove an entry from UnknownFvInfo array.\r
2140 //\r
2141 Index2 = Index + 1;\r
2142 for (;Index2 < PrivateData->UnknownFvInfoCount; Index2 ++, Index ++) {\r
2143 CopyMem (&PrivateData->UnknownFvInfo[Index], &PrivateData->UnknownFvInfo[Index2], sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO));\r
2144 }\r
2145 PrivateData->UnknownFvInfoCount --;\r
2146 return EFI_SUCCESS;\r
2147} \r
2148\r
2149/**\r
2150 Notification callback function for EFI_PEI_FIRMWARE_VOLUME_PPI.\r
2151 \r
2152 When a EFI_PEI_FIRMWARE_VOLUME_PPI is installed to support new FV format, this \r
2153 routine is called to process all discoveried FVs in this format.\r
2154 \r
2155 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
2156 @param NotifyDescriptor Address of the notification descriptor data structure.\r
2157 @param Ppi Address of the PPI that was installed.\r
2158 \r
2159 @retval EFI_SUCCESS The notification callback is processed correctly.\r
2160**/\r
2161EFI_STATUS\r
2162EFIAPI\r
2163ThirdPartyFvPpiNotifyCallback (\r
2164 IN EFI_PEI_SERVICES **PeiServices,\r
2165 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
2166 IN VOID *Ppi\r
2167 )\r
2168{\r
2169 PEI_CORE_INSTANCE *PrivateData;\r
2170 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;\r
2171 VOID *FvInfo;\r
2172 UINT32 FvInfoSize;\r
c7935105 2173 UINT32 AuthenticationStatus;\r
f3358329 2174 EFI_STATUS Status;\r
2175 EFI_PEI_FV_HANDLE FvHandle;\r
2176 BOOLEAN IsProcessed;\r
2177 UINTN FvIndex;\r
2178 EFI_PEI_FILE_HANDLE FileHandle;\r
2179 VOID *DepexData; \r
2180 \r
2181 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
2182 FvPpi = (EFI_PEI_FIRMWARE_VOLUME_PPI*) Ppi;\r
2183 \r
2184 do {\r
c7935105 2185 Status = FindUnknownFormatFvInfo (PrivateData, NotifyDescriptor->Guid, &FvInfo, &FvInfoSize, &AuthenticationStatus);\r
f3358329 2186 if (EFI_ERROR (Status)) {\r
2187 return EFI_SUCCESS;\r
2188 }\r
2189 \r
2190 //\r
2191 // Process new found FV and get FV handle.\r
2192 //\r
2193 Status = FvPpi->ProcessVolume (FvPpi, FvInfo, FvInfoSize, &FvHandle);\r
2194 if (EFI_ERROR (Status)) {\r
2195 DEBUG ((EFI_D_ERROR, "Fail to process the FV 0x%p, FV may be corrupted!\n", FvInfo));\r
2196 continue;\r
2197 }\r
2198\r
2199 //\r
2200 // Check whether the FV has already been processed.\r
2201 //\r
2202 IsProcessed = FALSE;\r
2203 for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {\r
2204 if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {\r
2205 DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvInfo));\r
2206 IsProcessed = TRUE;\r
2207 break;\r
2208 }\r
2209 }\r
2210 \r
2211 if (IsProcessed) {\r
2212 continue;\r
2213 }\r
2214 \r
ccf0f68d 2215 if (PrivateData->FvCount >= FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {\r
2216 DEBUG ((EFI_D_ERROR, "The number of Fv Images (%d) exceed the max supported FVs (%d) in Pei", PrivateData->FvCount + 1, FixedPcdGet32 (PcdPeiCoreMaxFvSupported)));\r
2217 DEBUG ((EFI_D_ERROR, "PcdPeiCoreMaxFvSupported value need be reconfigurated in DSC"));\r
2218 ASSERT (FALSE);\r
2219 }\r
2220 \r
f3358329 2221 //\r
2222 // Update internal PEI_CORE_FV array.\r
2223 //\r
2224 PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) FvInfo;\r
2225 PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi;\r
2226 PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;\r
c7935105 2227 PrivateData->Fv[PrivateData->FvCount].AuthenticationStatus = AuthenticationStatus;\r
f3358329 2228 DEBUG ((\r
2229 EFI_D_INFO, \r
2230 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n", \r
2231 (UINT32) PrivateData->FvCount, \r
2232 (VOID *) FvInfo, \r
2233 FvInfoSize,\r
2234 FvHandle\r
2235 )); \r
2236 PrivateData->FvCount ++;\r
2237\r
2238 //\r
2239 // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE \r
2240 //\r
2241 FileHandle = NULL;\r
2242 do {\r
2243 Status = FvPpi->FindFileByType (\r
2244 FvPpi,\r
2245 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
2246 FvHandle,\r
2247 &FileHandle\r
2248 );\r
2249 if (!EFI_ERROR (Status)) {\r
2250 Status = FvPpi->FindSectionByType (\r
2251 FvPpi,\r
2252 EFI_SECTION_PEI_DEPEX,\r
2253 FileHandle,\r
2254 (VOID**)&DepexData\r
2255 );\r
2256 if (!EFI_ERROR (Status)) {\r
2257 if (!PeimDispatchReadiness (PeiServices, DepexData)) {\r
2258 //\r
2259 // Dependency is not satisfied.\r
2260 //\r
2261 continue;\r
2262 }\r
2263 }\r
2264 \r
2265 DEBUG ((EFI_D_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, PrivateData->FvCount - 1, FvHandle));\r
c7935105 2266 ProcessFvFile (PrivateData, &PrivateData->Fv[PrivateData->FvCount - 1], FileHandle);\r
f3358329 2267 }\r
2268 } while (FileHandle != NULL);\r
2269 } while (TRUE);\r
f3358329 2270}\r