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