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