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