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