]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/FwVol/FwVol.c
Fix ICC toolchain build break.
[mirror_edk2.git] / MdeModulePkg / Core / Pei / FwVol / FwVol.c
CommitLineData
615c6dd0 1/** @file\r
b1f6a7c6 2 Pei Core Firmware File System service routines.\r
3 \r
3b428ade 4Copyright (c) 2006 - 2009, Intel Corporation \r
192f6d4c 5All rights reserved. This program and the accompanying materials \r
6are licensed and made available under the terms and conditions of the BSD License \r
7which accompanies this distribution. The full text of the license may be found at \r
8http://opensource.org/licenses/bsd-license.php \r
9 \r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12\r
615c6dd0 13**/\r
192f6d4c 14\r
3b428ade 15#include "FwVol.h"\r
192f6d4c 16\r
fe1e36e5 17EFI_PEI_NOTIFY_DESCRIPTOR mNotifyOnFvInfoList = {\r
b0d803fe 18 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
19 &gEfiPeiFirmwareVolumeInfoPpiGuid,\r
20 FirmwareVolmeInfoPpiNotifyCallback \r
21};\r
22\r
3b428ade 23EFI_PEI_FIRMWARE_VOLUME_PPI mPeiFfs2FvPpi = {\r
24 PeiFfs2FvPpiProcessVolume,\r
25 PeiFfs2FvPpiFindFileByType,\r
26 PeiFfs2FvPpiFindFileByName,\r
27 PeiFfs2FvPpiGetFileInfo,\r
28 PeiFfs2FvPpiGetVolumeInfo,\r
29 PeiFfs2FvPpiFindSectionByType\r
30};\r
31 \r
32EFI_PEI_PPI_DESCRIPTOR mPeiFfs2FvPpiList = {\r
33 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
34 &gEfiFirmwareFileSystem2Guid,\r
35 &mPeiFfs2FvPpi\r
36};\r
37 \r
b1f6a7c6 38/**\r
ed299e3c 39 Returns the file state set by the highest zero bit in the State field\r
192f6d4c 40\r
b1f6a7c6 41 @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY\r
42 in the Attributes field.\r
43 @param FfsHeader Pointer to FFS File Header.\r
192f6d4c 44\r
ed299e3c
LG
45 @retval EFI_FFS_FILE_STATE File state is set by the highest none zero bit \r
46 in the header State field.\r
b1f6a7c6 47**/\r
48EFI_FFS_FILE_STATE\r
49GetFileState(\r
50 IN UINT8 ErasePolarity,\r
51 IN EFI_FFS_FILE_HEADER *FfsHeader\r
52 )\r
192f6d4c 53{\r
54 EFI_FFS_FILE_STATE FileState;\r
55 EFI_FFS_FILE_STATE HighestBit;\r
56\r
57 FileState = FfsHeader->State;\r
58\r
59 if (ErasePolarity != 0) {\r
60 FileState = (EFI_FFS_FILE_STATE)~FileState;\r
61 }\r
ed299e3c
LG
62 \r
63 //\r
64 // Get file state set by its highest none zero bit.\r
65 //\r
192f6d4c 66 HighestBit = 0x80;\r
67 while (HighestBit != 0 && (HighestBit & FileState) == 0) {\r
68 HighestBit >>= 1;\r
69 }\r
70\r
71 return HighestBit;\r
72} \r
73\r
b1f6a7c6 74/**\r
75 Calculates the checksum of the header of a file.\r
76\r
77 @param FileHeader Pointer to FFS File Header.\r
78\r
79 @return Checksum of the header.\r
b1f6a7c6 80 Zero means the header is good.\r
81 Non-zero means the header is bad.\r
82**/\r
192f6d4c 83UINT8\r
84CalculateHeaderChecksum (\r
85 IN EFI_FFS_FILE_HEADER *FileHeader\r
86 )\r
192f6d4c 87{\r
ed299e3c 88 EFI_FFS_FILE_HEADER TestFileHeader;\r
192f6d4c 89 \r
ed299e3c 90 CopyMem (&TestFileHeader, FileHeader, sizeof (EFI_FFS_FILE_HEADER));\r
192f6d4c 91 //\r
ed299e3c 92 // Ingore State and File field in FFS header.\r
192f6d4c 93 //\r
ed299e3c
LG
94 TestFileHeader.State = 0;\r
95 TestFileHeader.IntegrityCheck.Checksum.File = 0;\r
192f6d4c 96\r
ed299e3c 97 return CalculateSum8 ((CONST UINT8 *) &TestFileHeader, sizeof (EFI_FFS_FILE_HEADER));\r
192f6d4c 98}\r
99\r
b1f6a7c6 100/**\r
3b428ade 101 Find FV handler according to FileHandle in that FV.\r
b1f6a7c6 102\r
103 @param FileHandle Handle of file image\r
3b428ade 104 \r
105 @return Pointer to instance of PEI_CORE_FV_HANDLE.\r
b1f6a7c6 106**/\r
3b428ade 107PEI_CORE_FV_HANDLE*\r
108FileHandleToVolume (\r
109 IN EFI_PEI_FILE_HANDLE FileHandle\r
b0d803fe 110 )\r
111{\r
112 UINTN Index;\r
113 PEI_CORE_INSTANCE *PrivateData;\r
114 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
115\r
116 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());\r
3b428ade 117 \r
b0d803fe 118 for (Index = 0; Index < PrivateData->FvCount; Index++) {\r
119 FwVolHeader = PrivateData->Fv[Index].FvHeader;\r
67a58d0f 120 if (((UINT64) (UINTN) FileHandle > (UINT64) (UINTN) FwVolHeader ) && \\r
121 ((UINT64) (UINTN) FileHandle <= ((UINT64) (UINTN) FwVolHeader + FwVolHeader->FvLength - 1))) {\r
3b428ade 122 return &PrivateData->Fv[Index];\r
b0d803fe 123 }\r
124 }\r
3b428ade 125 return NULL;\r
b0d803fe 126}\r
127\r
b1f6a7c6 128/**\r
ed299e3c 129 Given the input file pointer, search for the first matching file in the\r
b1f6a7c6 130 FFS volume as defined by SearchType. The search starts from FileHeader inside\r
131 the Firmware Volume defined by FwVolHeader.\r
ed299e3c
LG
132 If SearchType is EFI_FV_FILETYPE_ALL, the first FFS file will return without check its file type.\r
133 If SearchType is PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, \r
134 the first PEIM, or COMBINED PEIM or FV file type FFS file will return. \r
b1f6a7c6 135\r
136 @param FvHandle Pointer to the FV header of the volume to search\r
137 @param FileName File name\r
138 @param SearchType Filter to find only files of this type.\r
139 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.\r
140 @param FileHandle This parameter must point to a valid FFS volume.\r
141 @param AprioriFile Pointer to AprioriFile image in this FV if has\r
b0d803fe 142\r
b1f6a7c6 143 @return EFI_NOT_FOUND No files matching the search criteria were found\r
144 @retval EFI_SUCCESS Success to search given file\r
145\r
146**/\r
192f6d4c 147EFI_STATUS\r
3b428ade 148FindFileEx (\r
b0d803fe 149 IN CONST EFI_PEI_FV_HANDLE FvHandle,\r
150 IN CONST EFI_GUID *FileName, OPTIONAL\r
151 IN EFI_FV_FILETYPE SearchType,\r
152 IN OUT EFI_PEI_FILE_HANDLE *FileHandle,\r
153 IN OUT EFI_PEI_FV_HANDLE *AprioriFile OPTIONAL\r
192f6d4c 154 )\r
192f6d4c 155{\r
b0d803fe 156 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
157 EFI_FFS_FILE_HEADER **FileHeader;\r
158 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
b0d803fe 159 UINT32 FileLength;\r
160 UINT32 FileOccupiedSize;\r
161 UINT32 FileOffset;\r
162 UINT64 FvLength;\r
163 UINT8 ErasePolarity;\r
164 UINT8 FileState;\r
3b428ade 165 \r
166 //\r
167 // Convert the handle of FV to FV header for memory-mapped firmware volume\r
168 //\r
169 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvHandle;\r
b0d803fe 170 FileHeader = (EFI_FFS_FILE_HEADER **)FileHandle;\r
192f6d4c 171\r
172 FvLength = FwVolHeader->FvLength;\r
d976bf31 173 if ((FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) != 0) {\r
192f6d4c 174 ErasePolarity = 1;\r
175 } else {\r
176 ErasePolarity = 0;\r
177 }\r
178 \r
179 //\r
b0d803fe 180 // If FileHeader is not specified (NULL) or FileName is not NULL,\r
181 // start with the first file in the firmware volume. Otherwise,\r
182 // start from the FileHeader.\r
192f6d4c 183 //\r
b0d803fe 184 if ((*FileHeader == NULL) || (FileName != NULL)) {\r
192f6d4c 185 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);\r
186 } else {\r
187 //\r
188 // Length is 24 bits wide so mask upper 8 bits\r
189 // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.\r
190 //\r
191 FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF;\r
b0d803fe 192 FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);\r
192f6d4c 193 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize);\r
194 }\r
e98cd821 195 \r
192f6d4c 196 FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader);\r
197 ASSERT (FileOffset <= 0xFFFFFFFF);\r
e98cd821 198\r
b0d803fe 199 while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {\r
192f6d4c 200 //\r
201 // Get FileState which is the highest bit of the State \r
202 //\r
203 FileState = GetFileState (ErasePolarity, FfsFileHeader);\r
192f6d4c 204 switch (FileState) {\r
205\r
206 case EFI_FILE_HEADER_INVALID:\r
40f26b8f 207 FileOffset += sizeof(EFI_FFS_FILE_HEADER);\r
208 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER));\r
192f6d4c 209 break;\r
210 \r
211 case EFI_FILE_DATA_VALID:\r
212 case EFI_FILE_MARKED_FOR_UPDATE:\r
b0d803fe 213 if (CalculateHeaderChecksum (FfsFileHeader) != 0) {\r
192f6d4c 214 ASSERT (FALSE);\r
e98cd821 215 *FileHeader = NULL;\r
192f6d4c 216 return EFI_NOT_FOUND;\r
217 }\r
b0d803fe 218\r
40f26b8f 219 FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
b0d803fe 220 FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);\r
221\r
222 if (FileName != NULL) {\r
223 if (CompareGuid (&FfsFileHeader->Name, (EFI_GUID*)FileName)) {\r
224 *FileHeader = FfsFileHeader;\r
225 return EFI_SUCCESS;\r
226 }\r
227 } else if (SearchType == PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE) {\r
228 if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) || \r
288f9b38
LG
229 (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER) ||\r
230 (FfsFileHeader->Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE)) { \r
b0d803fe 231 \r
232 *FileHeader = FfsFileHeader;\r
233 return EFI_SUCCESS;\r
234 } else if (AprioriFile != NULL) {\r
235 if (FfsFileHeader->Type == EFI_FV_FILETYPE_FREEFORM) {\r
236 if (CompareGuid (&FfsFileHeader->Name, &gPeiAprioriFileNameGuid)) {\r
237 *AprioriFile = FfsFileHeader;\r
238 } \r
239 } \r
240 }\r
7e181f2f 241 } else if (((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) && \r
242 (FfsFileHeader->Type != EFI_FV_FILETYPE_FFS_PAD)) { \r
b0d803fe 243 *FileHeader = FfsFileHeader;\r
244 return EFI_SUCCESS;\r
245 }\r
246\r
40f26b8f 247 FileOffset += FileOccupiedSize; \r
248 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);\r
192f6d4c 249 break;\r
250 \r
251 case EFI_FILE_DELETED:\r
40f26b8f 252 FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
253 FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);\r
254 FileOffset += FileOccupiedSize;\r
255 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);\r
192f6d4c 256 break;\r
257\r
258 default:\r
e98cd821 259 *FileHeader = NULL;\r
192f6d4c 260 return EFI_NOT_FOUND;\r
192f6d4c 261 } \r
262 }\r
e98cd821
LG
263 \r
264 *FileHeader = NULL;\r
192f6d4c 265 return EFI_NOT_FOUND; \r
266}\r
267\r
b1f6a7c6 268/**\r
b1f6a7c6 269 Initialize PeiCore Fv List.\r
270\r
b1f6a7c6 271 @param PrivateData - Pointer to PEI_CORE_INSTANCE.\r
272 @param SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF.\r
b1f6a7c6 273**/\r
b0d803fe 274VOID \r
275PeiInitializeFv (\r
276 IN PEI_CORE_INSTANCE *PrivateData,\r
277 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData\r
278 )\r
b0d803fe 279{\r
3b428ade 280 EFI_STATUS Status;\r
281 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;\r
282 EFI_PEI_FV_HANDLE FvHandle;\r
283 EFI_FIRMWARE_VOLUME_HEADER *BfvHeader;\r
284 \r
b0d803fe 285 //\r
3b428ade 286 // Install FV_PPI for FFS2 file system.\r
b0d803fe 287 //\r
3b428ade 288 PeiServicesInstallPpi (&mPeiFfs2FvPpiList);\r
289 \r
290 BfvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;\r
291 \r
292 //\r
293 // The FV_PPI in BFV's format should be installed.\r
294 //\r
295 Status = PeiServicesLocatePpi (\r
296 &BfvHeader->FileSystemGuid,\r
297 0,\r
298 NULL,\r
299 (VOID**)&FvPpi\r
300 );\r
301 ASSERT_EFI_ERROR (Status);\r
302 \r
303 //\r
304 // Get handle of BFV\r
305 //\r
306 FvPpi->ProcessVolume (\r
307 FvPpi, \r
308 SecCoreData->BootFirmwareVolumeBase,\r
309 (UINTN)BfvHeader->FvLength,\r
310 &FvHandle\r
311 );\r
dc6f9b35 312\r
313 //\r
314 // Update internal PEI_CORE_FV array.\r
315 //\r
316 PrivateData->Fv[PrivateData->FvCount].FvHeader = BfvHeader;\r
317 PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi;\r
318 PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;\r
319 DEBUG ((\r
320 EFI_D_INFO, \r
321 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n", \r
322 (UINT32) PrivateData->FvCount, \r
323 (VOID *) BfvHeader, \r
324 BfvHeader->FvLength,\r
325 FvHandle\r
326 )); \r
327 PrivateData->FvCount ++;\r
328 \r
b0d803fe 329 //\r
330 // Post a call-back for the FvInfoPPI services to expose\r
331 // additional Fvs to PeiCore.\r
332 //\r
333 Status = PeiServicesNotifyPpi (&mNotifyOnFvInfoList);\r
334 ASSERT_EFI_ERROR (Status);\r
335\r
336}\r
3b428ade 337 \r
b1f6a7c6 338/**\r
339 Process Firmware Volum Information once FvInfoPPI install.\r
ed299e3c
LG
340 The FV Info will be registered into PeiCore private data structure.\r
341 And search the inside FV image, if found, the new FV INFO PPI will be installed.\r
b1f6a7c6 342\r
ed299e3c 343 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
731bd38e 344 @param NotifyDescriptor Address of the notification descriptor data structure.\r
345 @param Ppi Address of the PPI that was installed.\r
b1f6a7c6 346\r
ed299e3c 347 @retval EFI_SUCCESS The FV Info is registered into PeiCore private data structure.\r
6a1ae84a 348 @return if not EFI_SUCESS, fail to verify FV.\r
b1f6a7c6 349\r
350**/\r
b0d803fe 351EFI_STATUS\r
352EFIAPI\r
353FirmwareVolmeInfoPpiNotifyCallback (\r
354 IN EFI_PEI_SERVICES **PeiServices,\r
355 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
356 IN VOID *Ppi\r
357 )\r
b0d803fe 358{\r
3b428ade 359 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FvInfoPpi;\r
360 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;\r
b0d803fe 361 PEI_CORE_INSTANCE *PrivateData;\r
288f9b38 362 EFI_STATUS Status;\r
3b428ade 363 EFI_PEI_FV_HANDLE FvHandle;\r
364 UINTN FvIndex;\r
dc6f9b35 365 EFI_PEI_FILE_HANDLE FileHandle;\r
366 VOID *DepexData;\r
b0d803fe 367 \r
288f9b38
LG
368 Status = EFI_SUCCESS;\r
369 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
b0d803fe 370\r
177aabe6 371 if (PrivateData->FvCount >= FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {\r
97b2c9b5
LG
372 DEBUG ((EFI_D_ERROR, "The number of Fv Images (%d) exceed the max supported FVs (%d) in Pei", PrivateData->FvCount + 1, FixedPcdGet32 (PcdPeiCoreMaxFvSupported)));\r
373 DEBUG ((EFI_D_ERROR, "PcdPeiCoreMaxFvSupported value need be reconfigurated in DSC"));\r
b0d803fe 374 ASSERT (FALSE);\r
375 }\r
376\r
3b428ade 377 FvInfoPpi = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *)Ppi;\r
b0d803fe 378\r
97b2c9b5 379 //\r
3b428ade 380 // Locate the corresponding FV_PPI according to founded FV's format guid\r
97b2c9b5 381 //\r
3b428ade 382 Status = PeiServicesLocatePpi (\r
383 &FvInfoPpi->FvFormat, \r
384 0, \r
385 NULL,\r
386 (VOID**)&FvPpi\r
387 );\r
388 if (!EFI_ERROR (Status)) {\r
389 //\r
390 // Process new found FV and get FV handle.\r
391 //\r
392 Status = FvPpi->ProcessVolume (FvPpi, FvInfoPpi->FvInfo, FvInfoPpi->FvInfoSize, &FvHandle);\r
393 if (EFI_ERROR (Status)) {\r
dc6f9b35 394 DEBUG ((EFI_D_ERROR, "Fail to process new found FV, FV may be corrupted!\n"));\r
6a1ae84a 395 return Status;\r
396 }\r
dc6f9b35 397\r
398 //\r
399 // Check whether the FV has already been processed.\r
400 //\r
401 for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {\r
402 if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {\r
403 DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvInfoPpi->FvInfo));\r
404 return EFI_SUCCESS;\r
405 }\r
406 }\r
407\r
408 //\r
409 // Update internal PEI_CORE_FV array.\r
410 //\r
411 PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) FvInfoPpi->FvInfo;\r
412 PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi;\r
413 PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;\r
414 DEBUG ((\r
415 EFI_D_INFO, \r
416 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n", \r
417 (UINT32) PrivateData->FvCount, \r
418 (VOID *) FvInfoPpi->FvInfo, \r
419 FvInfoPpi->FvInfoSize,\r
420 FvHandle\r
421 )); \r
422 PrivateData->FvCount ++;\r
423\r
424 //\r
425 // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE \r
426 //\r
427 FileHandle = NULL;\r
428 do {\r
429 Status = FvPpi->FindFileByType (\r
430 FvPpi,\r
431 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
432 FvHandle,\r
433 &FileHandle\r
434 );\r
435 if (!EFI_ERROR (Status)) {\r
436 Status = FvPpi->FindSectionByType (\r
437 FvPpi,\r
438 EFI_SECTION_PEI_DEPEX,\r
439 FileHandle,\r
440 (VOID**)&DepexData\r
441 );\r
442 if (!EFI_ERROR (Status)) {\r
443 if (!PeimDispatchReadiness (PeiServices, DepexData)) {\r
444 //\r
445 // Dependency is not satisfied.\r
446 //\r
447 continue;\r
448 }\r
449 }\r
450 \r
451 DEBUG ((EFI_D_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, PrivateData->FvCount - 1, FvHandle));\r
452 ProcessFvFile (&PrivateData->Fv[PrivateData->FvCount - 1], FileHandle);\r
453 }\r
454 } while (FileHandle != NULL);\r
3b428ade 455 } else {\r
456 DEBUG ((EFI_D_ERROR, "Fail to process FV %p because no corresponding EFI_FIRMWARE_VOLUME_PPI is found!\n", FvInfoPpi->FvInfo));\r
6a1ae84a 457 \r
3b428ade 458 //\r
459 // If can not find EFI_FIRMWARE_VOLUME_PPI to process firmware to get FvHandle, \r
460 // use the address of FV buffer as its handle.\r
461 //\r
462 FvHandle = FvInfoPpi->FvInfo;\r
288f9b38 463 \r
288f9b38 464 //\r
3b428ade 465 // Check whether the FV has already been processed.\r
288f9b38 466 //\r
3b428ade 467 for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {\r
468 if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {\r
469 DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvHandle));\r
470 return EFI_SUCCESS;\r
288f9b38 471 }\r
3b428ade 472 } \r
473 \r
474 PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) FvInfoPpi->FvInfo;\r
475 PrivateData->Fv[PrivateData->FvCount].FvPpi = NULL;\r
476 PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;\r
477 PrivateData->FvCount ++;\r
288f9b38 478 }\r
3b428ade 479 \r
b0d803fe 480 return EFI_SUCCESS;\r
481}\r
482\r
b1f6a7c6 483/**\r
ed299e3c
LG
484 Go through the file to search SectionType section. \r
485 Search within encapsulation sections (compression and GUIDed) recursively, \r
486 until the match section is found.\r
487 \r
3b428ade 488 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
489 @param SectionType Filter to find only section of this type.\r
490 @param Section From where to search.\r
491 @param SectionSize The file size to search.\r
492 @param OutputBuffer A pointer to the discovered section, if successful.\r
ed299e3c 493 NULL if section not found\r
b1f6a7c6 494\r
ed299e3c
LG
495 @return EFI_NOT_FOUND The match section is not found.\r
496 @return EFI_SUCCESS The match section is found.\r
b1f6a7c6 497\r
498**/\r
b0d803fe 499EFI_STATUS\r
3b428ade 500ProcessSection (\r
b0d803fe 501 IN CONST EFI_PEI_SERVICES **PeiServices,\r
502 IN EFI_SECTION_TYPE SectionType,\r
503 IN EFI_COMMON_SECTION_HEADER *Section,\r
504 IN UINTN SectionSize,\r
288f9b38 505 OUT VOID **OutputBuffer\r
b0d803fe 506 )\r
b0d803fe 507{\r
508 EFI_STATUS Status;\r
509 UINT32 SectionLength;\r
510 UINT32 ParsedLength;\r
b0d803fe 511 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *GuidSectionPpi;\r
b0d803fe 512 EFI_PEI_DECOMPRESS_PPI *DecompressPpi;\r
513 VOID *PpiOutput;\r
514 UINTN PpiOutputSize;\r
288f9b38
LG
515 UINTN Index;\r
516 UINT32 Authentication;\r
517 PEI_CORE_INSTANCE *PrivateData;\r
b0d803fe 518\r
288f9b38 519 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
b0d803fe 520 *OutputBuffer = NULL;\r
288f9b38
LG
521 ParsedLength = 0;\r
522 Index = 0;\r
523 Status = EFI_NOT_FOUND;\r
524 PpiOutput = NULL;\r
525 PpiOutputSize = 0;\r
b0d803fe 526 while (ParsedLength < SectionSize) {\r
527 if (Section->Type == SectionType) {\r
528 *OutputBuffer = (VOID *)(Section + 1);\r
529 return EFI_SUCCESS;\r
288f9b38
LG
530 } else if ((Section->Type == EFI_SECTION_GUID_DEFINED) || (Section->Type == EFI_SECTION_COMPRESSION)) {\r
531 //\r
532 // Check the encapsulated section is extracted into the cache data.\r
533 //\r
534 for (Index = 0; Index < PrivateData->CacheSection.AllSectionCount; Index ++) {\r
535 if (Section == PrivateData->CacheSection.Section[Index]) {\r
536 PpiOutput = PrivateData->CacheSection.SectionData[Index];\r
537 PpiOutputSize = PrivateData->CacheSection.SectionSize[Index];\r
538 //\r
539 // Search section directly from the cache data.\r
540 //\r
3b428ade 541 return ProcessSection (\r
542 PeiServices,\r
543 SectionType, \r
544 PpiOutput, \r
545 PpiOutputSize, \r
546 OutputBuffer \r
547 );\r
b0d803fe 548 }\r
549 }\r
288f9b38
LG
550 \r
551 Status = EFI_NOT_FOUND;\r
552 if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
553 Status = PeiServicesLocatePpi (\r
554 &((EFI_GUID_DEFINED_SECTION *)Section)->SectionDefinitionGuid, \r
555 0, \r
556 NULL, \r
557 (VOID **) &GuidSectionPpi\r
558 );\r
b0d803fe 559 if (!EFI_ERROR (Status)) {\r
288f9b38 560 Status = GuidSectionPpi->ExtractSection (\r
3b428ade 561 GuidSectionPpi,\r
562 Section,\r
563 &PpiOutput,\r
564 &PpiOutputSize,\r
565 &Authentication\r
566 );\r
288f9b38
LG
567 }\r
568 } else if (Section->Type == EFI_SECTION_COMPRESSION) {\r
569 Status = PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid, 0, NULL, (VOID **) &DecompressPpi);\r
570 if (!EFI_ERROR (Status)) {\r
571 Status = DecompressPpi->Decompress (\r
572 DecompressPpi,\r
573 (CONST EFI_COMPRESSION_SECTION*) Section,\r
574 &PpiOutput,\r
575 &PpiOutputSize\r
576 );\r
b0d803fe 577 }\r
578 }\r
288f9b38
LG
579 \r
580 if (!EFI_ERROR (Status)) {\r
581 //\r
582 // Update cache section data.\r
583 //\r
584 if (PrivateData->CacheSection.AllSectionCount < CACHE_SETION_MAX_NUMBER) {\r
585 PrivateData->CacheSection.AllSectionCount ++;\r
586 }\r
587 PrivateData->CacheSection.Section [PrivateData->CacheSection.SectionIndex] = Section;\r
588 PrivateData->CacheSection.SectionData [PrivateData->CacheSection.SectionIndex] = PpiOutput;\r
589 PrivateData->CacheSection.SectionSize [PrivateData->CacheSection.SectionIndex] = PpiOutputSize;\r
590 PrivateData->CacheSection.SectionIndex = (PrivateData->CacheSection.SectionIndex + 1)%CACHE_SETION_MAX_NUMBER;\r
591 \r
3b428ade 592 return ProcessSection (\r
593 PeiServices,\r
594 SectionType, \r
595 PpiOutput, \r
596 PpiOutputSize, \r
597 OutputBuffer \r
598 );\r
288f9b38 599 }\r
b0d803fe 600 }\r
601\r
602 //\r
603 // Size is 24 bits wide so mask upper 8 bits. \r
604 // SectionLength is adjusted it is 4 byte aligned.\r
605 // Go to the next section\r
606 //\r
607 SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;\r
608 SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
609 ASSERT (SectionLength != 0);\r
610 ParsedLength += SectionLength;\r
611 Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);\r
612 }\r
613 \r
614 return EFI_NOT_FOUND;\r
615}\r
616\r
192f6d4c 617\r
b1f6a7c6 618/**\r
3b428ade 619 Searches for the next matching section within the specified file.\r
b1f6a7c6 620\r
ed299e3c 621 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
b1f6a7c6 622 @param SectionType Filter to find only sections of this type.\r
623 @param FileHandle Pointer to the current file to search.\r
ed299e3c 624 @param SectionData A pointer to the discovered section, if successful.\r
b1f6a7c6 625 NULL if section not found\r
626\r
3b428ade 627 @retval EFI_NOT_FOUND The section was not found.\r
628 @retval EFI_SUCCESS The section was found.\r
b1f6a7c6 629\r
630**/\r
192f6d4c 631EFI_STATUS\r
632EFIAPI\r
633PeiFfsFindSectionData (\r
3b428ade 634 IN CONST EFI_PEI_SERVICES **PeiServices,\r
192f6d4c 635 IN EFI_SECTION_TYPE SectionType,\r
0c2b5da8 636 IN EFI_PEI_FILE_HANDLE FileHandle,\r
3b428ade 637 OUT VOID **SectionData\r
192f6d4c 638 )\r
192f6d4c 639{\r
3b428ade 640 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
641 \r
642 CoreFvHandle = FileHandleToVolume (FileHandle);\r
643 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {\r
644 return EFI_NOT_FOUND;\r
645 }\r
646 \r
647 return CoreFvHandle->FvPpi->FindSectionByType (CoreFvHandle->FvPpi, SectionType, FileHandle, SectionData);\r
192f6d4c 648}\r
649\r
b1f6a7c6 650/**\r
3b428ade 651 Searches for the next matching file in the firmware volume.\r
b1f6a7c6 652\r
d73d93c3 653 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
b1f6a7c6 654 @param SearchType Filter to find only files of this type.\r
655 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.\r
3b428ade 656 @param VolumeHandle Handle of firmware volume in which to search.\r
657 @param FileHandle On entry, points to the current handle from which to begin searching or NULL to start\r
658 at the beginning of the firmware volume. On exit, points the file handle of the next file\r
659 in the volume or NULL if there are no more files.\r
660\r
661 @retval EFI_NOT_FOUND The file was not found.\r
662 @retval EFI_NOT_FOUND The header checksum was not zero.\r
663 @retval EFI_SUCCESS The file was found.\r
b1f6a7c6 664\r
665**/\r
192f6d4c 666EFI_STATUS\r
667EFIAPI\r
668PeiFfsFindNextFile (\r
0c2b5da8 669 IN CONST EFI_PEI_SERVICES **PeiServices,\r
670 IN UINT8 SearchType,\r
3b428ade 671 IN EFI_PEI_FV_HANDLE FvHandle,\r
0c2b5da8 672 IN OUT EFI_PEI_FILE_HANDLE *FileHandle\r
192f6d4c 673 )\r
192f6d4c 674{\r
3b428ade 675 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
676 \r
677 CoreFvHandle = FvHandleToCoreHandle (FvHandle);\r
678 \r
2f016ba8 679 //\r
680 // To make backward compatiblity, if can not find corresponding the handle of FV\r
681 // then treat FV as build-in FFS2 format and memory mapped FV that FV handle is pointed\r
682 // to the address of first byte of FV.\r
683 //\r
684 if ((CoreFvHandle == NULL) && FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {\r
685 return FindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL);\r
686 } \r
687 \r
3b428ade 688 if ((CoreFvHandle == NULL) || CoreFvHandle->FvPpi == NULL) {\r
689 return EFI_NOT_FOUND;\r
690 }\r
691 \r
692 return CoreFvHandle->FvPpi->FindFileByType (CoreFvHandle->FvPpi, SearchType, FvHandle, FileHandle);\r
192f6d4c 693}\r
694\r
b0d803fe 695\r
b1f6a7c6 696/**\r
ed299e3c 697 Search the firmware volumes by index\r
b1f6a7c6 698\r
ed299e3c 699 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
3b428ade 700 @param Instance This instance of the firmware volume to find. The value 0 is the Boot Firmware\r
701 Volume (BFV).\r
702 @param VolumeHandle On exit, points to the next volume handle or NULL if it does not exist.\r
b1f6a7c6 703\r
3b428ade 704 @retval EFI_INVALID_PARAMETER VolumeHandle is NULL\r
705 @retval EFI_NOT_FOUND The volume was not found.\r
706 @retval EFI_SUCCESS The volume was found.\r
b1f6a7c6 707\r
708**/\r
192f6d4c 709EFI_STATUS \r
710EFIAPI\r
3b428ade 711PeiFfsFindNextVolume (\r
2a00326e 712 IN CONST EFI_PEI_SERVICES **PeiServices,\r
192f6d4c 713 IN UINTN Instance,\r
0c2b5da8 714 IN OUT EFI_PEI_FV_HANDLE *VolumeHandle\r
192f6d4c 715 )\r
192f6d4c 716{\r
3b428ade 717 PEI_CORE_INSTANCE *Private;\r
718 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
719 \r
3e4c5b49 720 if (VolumeHandle == NULL) {\r
721 return EFI_INVALID_PARAMETER;\r
722 }\r
723 \r
b0d803fe 724 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
2a00326e 725 \r
3b428ade 726 CoreFvHandle = FindNextCoreFvHandle (Private, Instance);\r
727 if (CoreFvHandle == NULL) {\r
728 *VolumeHandle = NULL;\r
729 return EFI_NOT_FOUND;\r
2a00326e 730 }\r
3b428ade 731 \r
732 *VolumeHandle = CoreFvHandle->FvHandle;\r
733 \r
b0d803fe 734 return EFI_SUCCESS;\r
735}\r
192f6d4c 736\r
192f6d4c 737\r
b1f6a7c6 738/**\r
ed299e3c 739 Find a file within a volume by its name.\r
b1f6a7c6 740\r
ed299e3c
LG
741 @param FileName A pointer to the name of the file to find within the firmware volume.\r
742 @param VolumeHandle The firmware volume to search\r
743 @param FileHandle Upon exit, points to the found file's handle \r
744 or NULL if it could not be found.\r
b1f6a7c6 745\r
ed299e3c
LG
746 @retval EFI_SUCCESS File was found.\r
747 @retval EFI_NOT_FOUND File was not found.\r
748 @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or FileName was NULL.\r
b1f6a7c6 749\r
b1f6a7c6 750**/\r
b0d803fe 751EFI_STATUS\r
752EFIAPI \r
753PeiFfsFindFileByName (\r
754 IN CONST EFI_GUID *FileName,\r
755 IN EFI_PEI_FV_HANDLE VolumeHandle,\r
756 OUT EFI_PEI_FILE_HANDLE *FileHandle\r
757 )\r
b0d803fe 758{\r
3b428ade 759 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
760 \r
b0d803fe 761 if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {\r
192f6d4c 762 return EFI_INVALID_PARAMETER;\r
763 }\r
3b428ade 764 \r
765 CoreFvHandle = FvHandleToCoreHandle (VolumeHandle);\r
766 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {\r
767 return EFI_NOT_FOUND;\r
b0d803fe 768 }\r
3b428ade 769 \r
770 return CoreFvHandle->FvPpi->FindFileByName (CoreFvHandle->FvPpi, FileName, &VolumeHandle, FileHandle);\r
b0d803fe 771}\r
772\r
b1f6a7c6 773/**\r
b1f6a7c6 774 Returns information about a specific file.\r
775\r
3b428ade 776 @param FileHandle Handle of the file.\r
777 @param FileInfo Upon exit, points to the file’s information.\r
b1f6a7c6 778\r
3b428ade 779 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.\r
780 @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file.\r
781 @retval EFI_SUCCESS File information returned.\r
b1f6a7c6 782\r
783**/\r
b0d803fe 784EFI_STATUS\r
785EFIAPI \r
786PeiFfsGetFileInfo (\r
787 IN EFI_PEI_FILE_HANDLE FileHandle,\r
788 OUT EFI_FV_FILE_INFO *FileInfo\r
789 )\r
b0d803fe 790{\r
3b428ade 791 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
792 \r
b0d803fe 793 if ((FileHandle == NULL) || (FileInfo == NULL)) {\r
794 return EFI_INVALID_PARAMETER;\r
795 }\r
796\r
797 //\r
798 // Retrieve the FirmwareVolume which the file resides in.\r
799 //\r
3b428ade 800 CoreFvHandle = FileHandleToVolume (FileHandle);\r
801 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {\r
b0d803fe 802 return EFI_INVALID_PARAMETER;\r
803 }\r
804\r
3b428ade 805 return CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, FileHandle, FileInfo);\r
b0d803fe 806}\r
807\r
808\r
b1f6a7c6 809/**\r
3b428ade 810 Returns information about the specified volume.\r
b1f6a7c6 811\r
5a9403b8 812 This function returns information about a specific firmware\r
813 volume, including its name, type, attributes, starting address\r
814 and size.\r
815\r
816 @param VolumeHandle Handle of the volume.\r
817 @param VolumeInfo Upon exit, points to the volume's information.\r
818\r
819 @retval EFI_SUCCESS Volume information returned.\r
820 @retval EFI_INVALID_PARAMETER If VolumeHandle does not represent a valid volume.\r
821 @retval EFI_INVALID_PARAMETER If VolumeHandle is NULL.\r
822 @retval EFI_SUCCESS Information successfully returned.\r
823 @retval EFI_INVALID_PARAMETER The volume designated by the VolumeHandle is not available.\r
b1f6a7c6 824\r
b1f6a7c6 825**/\r
b0d803fe 826EFI_STATUS\r
827EFIAPI \r
828PeiFfsGetVolumeInfo (\r
829 IN EFI_PEI_FV_HANDLE VolumeHandle,\r
830 OUT EFI_FV_INFO *VolumeInfo\r
831 )\r
b0d803fe 832{\r
3b428ade 833 PEI_CORE_FV_HANDLE *CoreHandle;\r
834 \r
b0d803fe 835 if (VolumeInfo == NULL) {\r
836 return EFI_INVALID_PARAMETER;\r
192f6d4c 837 }\r
288f9b38 838 \r
3b428ade 839 CoreHandle = FvHandleToCoreHandle (VolumeHandle);\r
840 \r
841 if ((CoreHandle == NULL) || (CoreHandle->FvPpi == NULL)) {\r
288f9b38
LG
842 return EFI_INVALID_PARAMETER;\r
843 }\r
3b428ade 844 \r
845 return CoreHandle->FvPpi->GetVolumeInfo (CoreHandle->FvPpi, VolumeHandle, VolumeInfo);\r
192f6d4c 846}\r
b0d803fe 847\r
4c6486b9 848/**\r
849 Get Fv image from the FV type file, then install FV INFO ppi, Build FV hob.\r
850\r
3b428ade 851 @param ParentFvCoreHandle Pointer of EFI_CORE_FV_HANDLE to parent Fv image that contain this Fv image.\r
97b2c9b5 852 @param ParentFvFileHandle File handle of a Fv type file that contain this Fv image.\r
4c6486b9 853\r
854 @retval EFI_NOT_FOUND FV image can't be found.\r
855 @retval EFI_SUCCESS Successfully to process it.\r
856 @retval EFI_OUT_OF_RESOURCES Can not allocate page when aligning FV image\r
857 @retval Others Can not find EFI_SECTION_FIRMWARE_VOLUME_IMAGE section\r
858 \r
859**/\r
860EFI_STATUS\r
861ProcessFvFile (\r
3b428ade 862 IN PEI_CORE_FV_HANDLE *ParentFvCoreHandle,\r
863 IN EFI_PEI_FILE_HANDLE ParentFvFileHandle\r
4c6486b9 864 )\r
865{\r
3b428ade 866 EFI_STATUS Status;\r
867 EFI_FV_INFO ParentFvImageInfo;\r
868 UINT32 FvAlignment;\r
869 VOID *NewFvBuffer;\r
870 EFI_PEI_HOB_POINTERS HobPtr;\r
871 EFI_PEI_FIRMWARE_VOLUME_PPI *ParentFvPpi;\r
872 EFI_PEI_FV_HANDLE ParentFvHandle;\r
873 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
874 EFI_FV_FILE_INFO FileInfo;\r
875 \r
4c6486b9 876 //\r
877 // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already\r
878 // been extracted.\r
879 //\r
880 HobPtr.Raw = GetHobList ();\r
881 while ((HobPtr.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobPtr.Raw)) != NULL) {\r
97b2c9b5 882 if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)ParentFvFileHandle)->Name), &HobPtr.FirmwareVolume2->FileName)) {\r
4c6486b9 883 //\r
884 // this FILE has been dispatched, it will not be dispatched again.\r
885 //\r
3b428ade 886 DEBUG ((EFI_D_INFO, "FV file %p has been dispatched!\r\n", ParentFvFileHandle));\r
4c6486b9 887 return EFI_SUCCESS;\r
888 }\r
889 HobPtr.Raw = GET_NEXT_HOB (HobPtr);\r
890 }\r
891\r
3b428ade 892 ParentFvHandle = ParentFvCoreHandle->FvHandle;\r
893 ParentFvPpi = ParentFvCoreHandle->FvPpi;\r
894 \r
4c6486b9 895 //\r
896 // Find FvImage in FvFile\r
897 //\r
3b428ade 898 Status = ParentFvPpi->FindSectionByType (\r
899 ParentFvPpi,\r
900 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
901 ParentFvFileHandle,\r
902 (VOID **)&FvHeader\r
903 );\r
904 \r
4c6486b9 905 if (EFI_ERROR (Status)) {\r
906 return Status;\r
907 }\r
97b2c9b5
LG
908\r
909 //\r
3b428ade 910 // FvAlignment must be more than 8 bytes required by FvHeader structure.\r
4c6486b9 911 //\r
3b428ade 912 FvAlignment = 1 << ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);\r
4c6486b9 913 if (FvAlignment < 8) {\r
914 FvAlignment = 8;\r
915 }\r
916 \r
917 //\r
918 // Check FvImage\r
919 //\r
3b428ade 920 if ((UINTN) FvHeader % FvAlignment != 0) {\r
921 NewFvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvHeader->FvLength), FvAlignment);\r
922 if (NewFvBuffer == NULL) {\r
4c6486b9 923 return EFI_OUT_OF_RESOURCES;\r
924 }\r
3b428ade 925 CopyMem (NewFvBuffer, FvHeader, (UINTN) FvHeader->FvLength);\r
926 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) NewFvBuffer;\r
4c6486b9 927 }\r
3b428ade 928 \r
929 Status = ParentFvPpi->GetVolumeInfo (ParentFvPpi, ParentFvHandle, &ParentFvImageInfo);\r
930 ASSERT_EFI_ERROR (Status);\r
931 \r
932 Status = ParentFvPpi->GetFileInfo (ParentFvPpi, ParentFvFileHandle, &FileInfo);\r
933 ASSERT_EFI_ERROR (Status);\r
934 \r
4c6486b9 935 //\r
936 // Install FvPpi and Build FvHob\r
937 //\r
187f1a5b 938 PeiServicesInstallFvInfoPpi (\r
3b428ade 939 &FvHeader->FileSystemGuid,\r
940 (VOID**) FvHeader,\r
941 (UINT32) FvHeader->FvLength,\r
97b2c9b5 942 &ParentFvImageInfo.FvName,\r
3b428ade 943 &FileInfo.FileName\r
4c6486b9 944 );\r
945\r
946 //\r
947 // Inform the extracted FvImage to Fv HOB consumer phase, i.e. DXE phase\r
4c6486b9 948 //\r
223c22d8 949 BuildFvHob (\r
3b428ade 950 (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,\r
951 FvHeader->FvLength\r
18fcd6a7 952 );\r
4c6486b9 953\r
954 //\r
955 // Makes the encapsulated volume show up in DXE phase to skip processing of\r
956 // encapsulated file again.\r
957 //\r
958 BuildFv2Hob (\r
3b428ade 959 (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,\r
960 FvHeader->FvLength,\r
97b2c9b5 961 &ParentFvImageInfo.FvName,\r
3b428ade 962 &FileInfo.FileName\r
4c6486b9 963 );\r
964\r
965 return EFI_SUCCESS;\r
966}\r
967\r
3b428ade 968/**\r
969 Process a firmware volume and create a volume handle.\r
970\r
971 Create a volume handle from the information in the buffer. For\r
972 memory-mapped firmware volumes, Buffer and BufferSize refer to\r
973 the start of the firmware volume and the firmware volume size.\r
974 For non memory-mapped firmware volumes, this points to a\r
975 buffer which contains the necessary information for creating\r
976 the firmware volume handle. Normally, these values are derived\r
977 from the EFI_FIRMWARE_VOLUME_INFO_PPI.\r
978 \r
979 \r
980 @param This Points to this instance of the\r
981 EFI_PEI_FIRMWARE_VOLUME_PPI.\r
982 @param Buffer Points to the start of the buffer.\r
983 @param BufferSize Size of the buffer.\r
984 @param FvHandle Points to the returned firmware volume\r
985 handle. The firmware volume handle must\r
986 be unique within the system. \r
987\r
988 @retval EFI_SUCCESS Firmware volume handle created.\r
989 @retval EFI_VOLUME_CORRUPTED Volume was corrupt.\r
990\r
991**/\r
992EFI_STATUS\r
993EFIAPI\r
994PeiFfs2FvPpiProcessVolume (\r
995 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,\r
996 IN VOID *Buffer,\r
997 IN UINTN BufferSize,\r
998 OUT EFI_PEI_FV_HANDLE *FvHandle\r
999 )\r
1000{\r
1001 EFI_STATUS Status;\r
3b428ade 1002 \r
dc6f9b35 1003 ASSERT (FvHandle != NULL);\r
1004 \r
1005 if (Buffer == NULL) {\r
1006 return EFI_VOLUME_CORRUPTED;\r
1007 }\r
3b428ade 1008 \r
1009 //\r
1010 // The build-in EFI_PEI_FIRMWARE_VOLUME_PPI for FFS2 support memory-mapped\r
1011 // FV image and the handle is pointed to Fv image's buffer.\r
1012 //\r
1013 *FvHandle = (EFI_PEI_FV_HANDLE) Buffer;\r
1014 \r
1015 //\r
1016 // Do verify for given FV buffer.\r
1017 //\r
1018 Status = VerifyFv ((EFI_FIRMWARE_VOLUME_HEADER*) Buffer);\r
1019 if (EFI_ERROR(Status)) {\r
1020 DEBUG ((EFI_D_ERROR, "Fail to verify FV which address is 0x%11p", Buffer));\r
1021 return EFI_VOLUME_CORRUPTED;\r
1022 }\r
1023\r
3b428ade 1024 return EFI_SUCCESS;\r
1025} \r
1026\r
1027/**\r
1028 Finds the next file of the specified type.\r
1029\r
1030 This service enables PEI modules to discover additional firmware files. \r
1031 The FileHandle must be unique within the system.\r
1032\r
1033 @param This Points to this instance of the\r
1034 EFI_PEI_FIRMWARE_VOLUME_PPI.\r
1035 @param SearchType A filter to find only files of this type. Type\r
1036 EFI_FV_FILETYPE_ALL causes no filtering to be\r
1037 done.\r
1038 @param FvHandle Handle of firmware volume in which to\r
1039 search.\r
1040 @param FileHandle Points to the current handle from which to\r
1041 begin searching or NULL to start at the\r
1042 beginning of the firmware volume. Updated\r
1043 upon return to reflect the file found.\r
1044\r
1045 @retval EFI_SUCCESS The file was found.\r
1046 @retval EFI_NOT_FOUND The file was not found. FileHandle contains NULL.\r
1047\r
1048**/\r
1049EFI_STATUS\r
1050EFIAPI\r
1051PeiFfs2FvPpiFindFileByType (\r
1052 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,\r
1053 IN EFI_FV_FILETYPE SearchType,\r
1054 IN EFI_PEI_FV_HANDLE FvHandle,\r
1055 IN OUT EFI_PEI_FILE_HANDLE *FileHandle\r
1056 )\r
1057{ \r
1058 return FindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL);\r
1059}\r
1060\r
1061/**\r
1062 Find a file within a volume by its name. \r
1063 \r
1064 This service searches for files with a specific name, within\r
1065 either the specified firmware volume or all firmware volumes.\r
1066\r
1067 @param This Points to this instance of the\r
1068 EFI_PEI_FIRMWARE_VOLUME_PPI.\r
1069 @param FileName A pointer to the name of the file to find\r
1070 within the firmware volume.\r
1071 @param FvHandle Upon entry, the pointer to the firmware\r
1072 volume to search or NULL if all firmware\r
1073 volumes should be searched. Upon exit, the\r
1074 actual firmware volume in which the file was\r
1075 found.\r
1076 @param FileHandle Upon exit, points to the found file's\r
1077 handle or NULL if it could not be found.\r
1078\r
1079 @retval EFI_SUCCESS File was found.\r
1080 @retval EFI_NOT_FOUND File was not found.\r
1081 @retval EFI_INVALID_PARAMETER FvHandle or FileHandle or\r
1082 FileName was NULL.\r
1083\r
1084\r
1085**/\r
1086EFI_STATUS\r
1087EFIAPI\r
1088PeiFfs2FvPpiFindFileByName (\r
1089 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,\r
1090 IN CONST EFI_GUID *FileName,\r
1091 IN EFI_PEI_FV_HANDLE *FvHandle,\r
1092 OUT EFI_PEI_FILE_HANDLE *FileHandle \r
1093 )\r
1094{\r
1095 EFI_STATUS Status;\r
1096 PEI_CORE_INSTANCE *PrivateData;\r
1097 UINTN Index;\r
1098 \r
1099 if ((FvHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {\r
1100 return EFI_INVALID_PARAMETER;\r
1101 }\r
1102 \r
1103 if (*FvHandle != NULL) {\r
1104 Status = FindFileEx (*FvHandle, FileName, 0, FileHandle, NULL);\r
1105 if (Status == EFI_NOT_FOUND) {\r
1106 *FileHandle = NULL;\r
1107 }\r
1108 } else { \r
1109 //\r
1110 // If *FvHandle = NULL, so search all FV for given filename\r
1111 //\r
1112 Status = EFI_NOT_FOUND;\r
1113 \r
1114 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer());\r
1115 for (Index = 0; Index < PrivateData->FvCount; Index ++) {\r
1116 //\r
1117 // Only search the FV which is associated with a EFI_PEI_FIRMWARE_VOLUME_PPI instance.\r
1118 //\r
1119 if (PrivateData->Fv[Index].FvPpi != NULL) {\r
1120 Status = FindFileEx (PrivateData->Fv[Index].FvHandle, FileName, 0, FileHandle, NULL);\r
1121 if (!EFI_ERROR (Status)) {\r
1122 *FvHandle = PrivateData->Fv[Index].FvHandle;\r
1123 }\r
1124 }\r
1125 }\r
1126 }\r
1127 \r
1128 return Status; \r
1129} \r
1130\r
1131/**\r
1132 Returns information about a specific file.\r
1133\r
1134 This function returns information about a specific\r
1135 file, including its file name, type, attributes, starting\r
1136 address and size. \r
1137 \r
1138 @param This Points to this instance of the\r
1139 EFI_PEI_FIRMWARE_VOLUME_PPI.\r
1140 @param FileHandle Handle of the file.\r
1141 @param FileInfo Upon exit, points to the file's\r
1142 information.\r
1143\r
1144 @retval EFI_SUCCESS File information returned.\r
1145 @retval EFI_INVALID_PARAMETER If FileHandle does not\r
1146 represent a valid file.\r
1147 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.\r
1148 \r
1149**/ \r
1150EFI_STATUS\r
1151EFIAPI\r
1152PeiFfs2FvPpiGetFileInfo (\r
1153 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, \r
1154 IN EFI_PEI_FILE_HANDLE FileHandle, \r
1155 OUT EFI_FV_FILE_INFO *FileInfo\r
1156 )\r
1157{\r
1158 UINT8 FileState;\r
1159 UINT8 ErasePolarity;\r
1160 EFI_FFS_FILE_HEADER *FileHeader;\r
1161 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
1162 \r
1163 if ((FileHandle == NULL) || (FileInfo == NULL)) {\r
1164 return EFI_INVALID_PARAMETER;\r
1165 }\r
1166\r
1167 //\r
1168 // Retrieve the FirmwareVolume which the file resides in.\r
1169 //\r
1170 CoreFvHandle = FileHandleToVolume (FileHandle);\r
1171 if (CoreFvHandle == NULL) {\r
1172 return EFI_INVALID_PARAMETER;\r
1173 }\r
1174\r
1175 if (CoreFvHandle->FvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
1176 ErasePolarity = 1;\r
1177 } else {\r
1178 ErasePolarity = 0;\r
1179 }\r
1180\r
1181 //\r
1182 // Get FileState which is the highest bit of the State \r
1183 //\r
1184 FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle);\r
1185\r
1186 switch (FileState) {\r
1187 case EFI_FILE_DATA_VALID:\r
1188 case EFI_FILE_MARKED_FOR_UPDATE:\r
1189 break; \r
1190 default:\r
1191 return EFI_INVALID_PARAMETER;\r
1192 }\r
1193\r
1194 FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;\r
1195 CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID));\r
1196 FileInfo->FileType = FileHeader->Type;\r
1197 FileInfo->FileAttributes = FileHeader->Attributes;\r
1198 FileInfo->BufferSize = ((*(UINT32 *)FileHeader->Size) & 0x00FFFFFF) - sizeof (EFI_FFS_FILE_HEADER);\r
1199 FileInfo->Buffer = (FileHeader + 1);\r
1200 return EFI_SUCCESS; \r
1201} \r
1202 \r
1203/**\r
1204 This function returns information about the firmware volume.\r
1205 \r
1206 @param This Points to this instance of the\r
1207 EFI_PEI_FIRMWARE_VOLUME_PPI.\r
1208 @param FvHandle Handle to the firmware handle.\r
1209 @param VolumeInfo Points to the returned firmware volume\r
1210 information.\r
1211\r
1212 @retval EFI_SUCCESS Information returned successfully.\r
1213 @retval EFI_INVALID_PARAMETER FvHandle does not indicate a valid\r
1214 firmware volume or VolumeInfo is NULL.\r
1215\r
1216**/ \r
1217EFI_STATUS\r
1218EFIAPI\r
1219PeiFfs2FvPpiGetVolumeInfo (\r
1220 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, \r
1221 IN EFI_PEI_FV_HANDLE FvHandle, \r
1222 OUT EFI_FV_INFO *VolumeInfo\r
1223 )\r
1224{\r
1225 EFI_FIRMWARE_VOLUME_HEADER FwVolHeader;\r
1226 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;\r
1227\r
1228 if (VolumeInfo == NULL) {\r
1229 return EFI_INVALID_PARAMETER;\r
1230 }\r
1231 \r
1232 //\r
1233 // VolumeHandle may not align at 8 byte, \r
1234 // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte. \r
1235 // So, Copy FvHeader into the local FvHeader structure.\r
1236 //\r
1237 CopyMem (&FwVolHeader, FvHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
1238\r
1239 //\r
1240 // Check Fv Image Signature\r
1241 //\r
1242 if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {\r
1243 return EFI_INVALID_PARAMETER;\r
1244 }\r
1245\r
1246 ZeroMem (VolumeInfo, sizeof (EFI_FV_INFO));\r
1247 VolumeInfo->FvAttributes = FwVolHeader.Attributes;\r
1248 VolumeInfo->FvStart = (VOID *) FvHandle;\r
1249 VolumeInfo->FvSize = FwVolHeader.FvLength;\r
1250 CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID));\r
1251\r
1252 if (FwVolHeader.ExtHeaderOffset != 0) {\r
1253 FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)FvHandle) + FwVolHeader.ExtHeaderOffset);\r
1254 CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID));\r
1255 }\r
1256 \r
1257 return EFI_SUCCESS; \r
1258} \r
1259\r
1260/**\r
1261 Find the next matching section in the firmware file.\r
1262 \r
1263 This service enables PEI modules to discover sections\r
1264 of a given type within a valid file.\r
1265 \r
1266 @param This Points to this instance of the\r
1267 EFI_PEI_FIRMWARE_VOLUME_PPI.\r
1268 @param SearchType A filter to find only sections of this\r
1269 type.\r
1270 @param FileHandle Handle of firmware file in which to\r
1271 search.\r
1272 @param SectionData Updated upon return to point to the\r
1273 section found.\r
1274 \r
1275 @retval EFI_SUCCESS Section was found.\r
1276 @retval EFI_NOT_FOUND Section of the specified type was not\r
1277 found. SectionData contains NULL.\r
1278**/\r
1279EFI_STATUS\r
1280EFIAPI\r
1281PeiFfs2FvPpiFindSectionByType (\r
1282 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,\r
1283 IN EFI_SECTION_TYPE SearchType,\r
1284 IN EFI_PEI_FILE_HANDLE FileHandle,\r
1285 OUT VOID **SectionData\r
1286 )\r
1287{\r
1288 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
1289 UINT32 FileSize;\r
1290 EFI_COMMON_SECTION_HEADER *Section;\r
1291 \r
1292 FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);\r
1293\r
1294 //\r
1295 // Size is 24 bits wide so mask upper 8 bits. \r
1296 // Does not include FfsFileHeader header size\r
1297 // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.\r
1298 //\r
1299 Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1);\r
1300 FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
1301 FileSize -= sizeof (EFI_FFS_FILE_HEADER);\r
1302\r
1303 return ProcessSection (\r
1304 GetPeiServicesTablePointer (),\r
1305 SearchType, \r
1306 Section, \r
1307 FileSize, \r
1308 SectionData\r
1309 ); \r
1310} \r
1311\r
1312/**\r
1313 Convert the handle of FV to pointer of corresponding PEI_CORE_FV_HANDLE.\r
1314 \r
1315 @param FvHandle The handle of a FV.\r
1316 \r
1317 @retval NULL if can not find.\r
1318 @return Pointer of corresponding PEI_CORE_FV_HANDLE. \r
1319**/\r
1320PEI_CORE_FV_HANDLE *\r
1321FvHandleToCoreHandle (\r
1322 IN EFI_PEI_FV_HANDLE FvHandle\r
1323 )\r
1324{\r
1325 UINTN Index;\r
1326 PEI_CORE_INSTANCE *PrivateData;\r
1327 \r
1328 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer()); \r
1329 for (Index = 0; Index < PrivateData->FvCount; Index ++) {\r
1330 if (FvHandle == PrivateData->Fv[Index].FvHandle) {\r
1331 return &PrivateData->Fv[Index];\r
1332 }\r
1333 }\r
1334 \r
1335 return NULL;\r
1336} \r
1337\r
1338/**\r
1339 Get instance of PEI_CORE_FV_HANDLE for next volume according to given index.\r
1340 \r
1341 This routine also will install FvInfo ppi for FV hob in PI ways.\r
1342 \r
1343 @param Private Pointer of PEI_CORE_INSTANCE\r
1344 @param Instance The index of FV want to be searched.\r
1345 \r
1346 @return Instance of PEI_CORE_FV_HANDLE.\r
1347**/\r
1348PEI_CORE_FV_HANDLE *\r
1349FindNextCoreFvHandle (\r
1350 IN PEI_CORE_INSTANCE *Private,\r
1351 IN UINTN Instance\r
1352 )\r
1353{\r
1354 UINTN Index;\r
1355 BOOLEAN Match;\r
1356 EFI_HOB_FIRMWARE_VOLUME *FvHob;\r
1357 \r
1358 //\r
1359 // Handle Framework FvHob and Install FvInfo Ppi for it.\r
1360 //\r
1361 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {\r
1362 //\r
1363 // Loop to search the wanted FirmwareVolume which supports FFS\r
1364 //\r
1365 FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetFirstHob (EFI_HOB_TYPE_FV);\r
1366 while (FvHob != NULL) {\r
1367 for (Index = 0, Match = FALSE; Index < Private->FvCount; Index++) {\r
1368 if ((EFI_PEI_FV_HANDLE)(UINTN)FvHob->BaseAddress == Private->Fv[Index].FvHeader) {\r
1369 Match = TRUE;\r
1370 break;\r
1371 }\r
1372 }\r
1373 //\r
1374 // If Not Found, Install FvInfo Ppi for it.\r
1375 //\r
1376 if (!Match) {\r
1377 PeiServicesInstallFvInfoPpi (\r
1378 &(((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvHob->BaseAddress)->FileSystemGuid),\r
1379 (VOID *)(UINTN)FvHob->BaseAddress,\r
1380 (UINT32)FvHob->Length,\r
1381 NULL,\r
1382 NULL\r
1383 );\r
1384 }\r
1385 FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetNextHob (EFI_HOB_TYPE_FV, (VOID *)((UINTN)FvHob + FvHob->Header.HobLength)); \r
1386 }\r
1387 }\r
1388\r
1389 if (Instance >= Private->FvCount) {\r
1390 return NULL;\r
1391 }\r
4c6486b9 1392\r
3b428ade 1393 return &Private->Fv[Instance];\r
1394} \r
8e0e40ed 1395\r
1396/**\r
1397 After PeiCore image is shadowed into permanent memory, all build-in FvPpi should\r
1398 be re-installed with the instance in permanent memory and all cached FvPpi pointers in \r
1399 PrivateData->Fv[] array should be fixed up to be pointed to the one in permenant\r
1400 memory.\r
1401 \r
1402 @param PrivateData Pointer to PEI_CORE_INSTANCE.\r
1403**/ \r
1404VOID\r
1405PeiReinitializeFv (\r
1406 IN PEI_CORE_INSTANCE *PrivateData\r
1407 )\r
1408{\r
7ec93917 1409 VOID *OldFfs2FvPpi;\r
1410 EFI_PEI_PPI_DESCRIPTOR *OldDescriptor;\r
1411 UINTN Index;\r
1412 EFI_STATUS Status;\r
1413\r
1414 //\r
1415 // Locate old build-in Ffs2 EFI_PEI_FIRMWARE_VOLUME_PPI which\r
1416 // in flash.\r
1417 //\r
1418 Status = PeiServicesLocatePpi (\r
1419 &gEfiFirmwareFileSystem2Guid,\r
1420 0,\r
1421 &OldDescriptor,\r
1422 &OldFfs2FvPpi\r
1423 );\r
1424 ASSERT_EFI_ERROR (Status);\r
1425\r
1426 //\r
1427 // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs2\r
1428 // which is shadowed from flash to permanent memory within PeiCore image.\r
1429 //\r
1430 Status = PeiServicesReInstallPpi (OldDescriptor, &mPeiFfs2FvPpiList);\r
1431 ASSERT_EFI_ERROR (Status);\r
1432 \r
1433 //\r
1434 // Fixup all FvPpi pointers for the implementation in flash to permanent memory.\r
1435 //\r
1436 for (Index = 0; Index < FixedPcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {\r
1437 if (PrivateData->Fv[Index].FvPpi == OldFfs2FvPpi) {\r
1438 PrivateData->Fv[Index].FvPpi = &mPeiFfs2FvPpi;\r
1439 }\r
1440 }\r
8e0e40ed 1441} \r
1442\r