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