]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/FwVol/FwVol.c
1. Add three sample PCD in HelloWorld application for user reference of PCD usage.
[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
ed299e3c 4Copyright (c) 2006 - 2008, 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
192f6d4c 15#include <PeiMain.h>\r
16\r
b0d803fe 17STATIC EFI_PEI_NOTIFY_DESCRIPTOR mNotifyOnFvInfoList = {\r
18 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
19 &gEfiPeiFirmwareVolumeInfoPpiGuid,\r
20 FirmwareVolmeInfoPpiNotifyCallback \r
21};\r
22\r
23\r
24#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \\r
ed299e3c 25 ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))\r
192f6d4c 26\r
b1f6a7c6 27/**\r
ed299e3c 28 Returns the file state set by the highest zero bit in the State field\r
192f6d4c 29\r
b1f6a7c6 30 @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY\r
31 in the Attributes field.\r
32 @param FfsHeader Pointer to FFS File Header.\r
192f6d4c 33\r
ed299e3c
LG
34 @retval EFI_FFS_FILE_STATE File state is set by the highest none zero bit \r
35 in the header State field.\r
b1f6a7c6 36**/\r
37EFI_FFS_FILE_STATE\r
38GetFileState(\r
39 IN UINT8 ErasePolarity,\r
40 IN EFI_FFS_FILE_HEADER *FfsHeader\r
41 )\r
192f6d4c 42{\r
43 EFI_FFS_FILE_STATE FileState;\r
44 EFI_FFS_FILE_STATE HighestBit;\r
45\r
46 FileState = FfsHeader->State;\r
47\r
48 if (ErasePolarity != 0) {\r
49 FileState = (EFI_FFS_FILE_STATE)~FileState;\r
50 }\r
ed299e3c
LG
51 \r
52 //\r
53 // Get file state set by its highest none zero bit.\r
54 //\r
192f6d4c 55 HighestBit = 0x80;\r
56 while (HighestBit != 0 && (HighestBit & FileState) == 0) {\r
57 HighestBit >>= 1;\r
58 }\r
59\r
60 return HighestBit;\r
61} \r
62\r
b1f6a7c6 63/**\r
64 Calculates the checksum of the header of a file.\r
65\r
66 @param FileHeader Pointer to FFS File Header.\r
67\r
68 @return Checksum of the header.\r
b1f6a7c6 69 Zero means the header is good.\r
70 Non-zero means the header is bad.\r
71**/\r
192f6d4c 72UINT8\r
73CalculateHeaderChecksum (\r
74 IN EFI_FFS_FILE_HEADER *FileHeader\r
75 )\r
192f6d4c 76{\r
ed299e3c 77 EFI_FFS_FILE_HEADER TestFileHeader;\r
192f6d4c 78 \r
ed299e3c 79 CopyMem (&TestFileHeader, FileHeader, sizeof (EFI_FFS_FILE_HEADER));\r
192f6d4c 80 //\r
ed299e3c 81 // Ingore State and File field in FFS header.\r
192f6d4c 82 //\r
ed299e3c
LG
83 TestFileHeader.State = 0;\r
84 TestFileHeader.IntegrityCheck.Checksum.File = 0;\r
192f6d4c 85\r
ed299e3c 86 return CalculateSum8 ((CONST UINT8 *) &TestFileHeader, sizeof (EFI_FFS_FILE_HEADER));\r
192f6d4c 87}\r
88\r
b1f6a7c6 89/**\r
90 Find FV handler according some FileHandle in that FV.\r
91\r
92 @param FileHandle Handle of file image\r
ed299e3c 93 @param VolumeHandle Handle of the found FV, if not found, NULL will be set.\r
b1f6a7c6 94\r
ed299e3c
LG
95 @retval TRUE The corresponding FV handler is found.\r
96 @retval FALSE The corresponding FV handler is not found.\r
b1f6a7c6 97\r
98**/\r
b0d803fe 99BOOLEAN\r
100EFIAPI\r
101PeiFileHandleToVolume (\r
102 IN EFI_PEI_FILE_HANDLE FileHandle,\r
103 OUT EFI_PEI_FV_HANDLE *VolumeHandle\r
104 )\r
105{\r
106 UINTN Index;\r
107 PEI_CORE_INSTANCE *PrivateData;\r
108 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
109\r
110 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());\r
111 for (Index = 0; Index < PrivateData->FvCount; Index++) {\r
112 FwVolHeader = PrivateData->Fv[Index].FvHeader;\r
67a58d0f 113 if (((UINT64) (UINTN) FileHandle > (UINT64) (UINTN) FwVolHeader ) && \\r
114 ((UINT64) (UINTN) FileHandle <= ((UINT64) (UINTN) FwVolHeader + FwVolHeader->FvLength - 1))) {\r
b0d803fe 115 *VolumeHandle = (EFI_PEI_FV_HANDLE)FwVolHeader;\r
116 return TRUE;\r
117 }\r
118 }\r
ed299e3c 119 *VolumeHandle = NULL;\r
b0d803fe 120 return FALSE;\r
121}\r
122\r
b1f6a7c6 123/**\r
ed299e3c 124 Given the input file pointer, search for the first matching file in the\r
b1f6a7c6 125 FFS volume as defined by SearchType. The search starts from FileHeader inside\r
126 the Firmware Volume defined by FwVolHeader.\r
ed299e3c
LG
127 If SearchType is EFI_FV_FILETYPE_ALL, the first FFS file will return without check its file type.\r
128 If SearchType is PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, \r
129 the first PEIM, or COMBINED PEIM or FV file type FFS file will return. \r
b1f6a7c6 130\r
131 @param FvHandle Pointer to the FV header of the volume to search\r
132 @param FileName File name\r
133 @param SearchType Filter to find only files of this type.\r
134 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.\r
135 @param FileHandle This parameter must point to a valid FFS volume.\r
136 @param AprioriFile Pointer to AprioriFile image in this FV if has\r
b0d803fe 137\r
b1f6a7c6 138 @return EFI_NOT_FOUND No files matching the search criteria were found\r
139 @retval EFI_SUCCESS Success to search given file\r
140\r
141**/\r
192f6d4c 142EFI_STATUS\r
b0d803fe 143PeiFindFileEx (\r
144 IN CONST EFI_PEI_FV_HANDLE FvHandle,\r
145 IN CONST EFI_GUID *FileName, OPTIONAL\r
146 IN EFI_FV_FILETYPE SearchType,\r
147 IN OUT EFI_PEI_FILE_HANDLE *FileHandle,\r
148 IN OUT EFI_PEI_FV_HANDLE *AprioriFile OPTIONAL\r
192f6d4c 149 )\r
192f6d4c 150{\r
b0d803fe 151 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
152 EFI_FFS_FILE_HEADER **FileHeader;\r
153 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
154 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;\r
155 UINT32 FileLength;\r
156 UINT32 FileOccupiedSize;\r
157 UINT32 FileOffset;\r
158 UINT64 FvLength;\r
159 UINT8 ErasePolarity;\r
160 UINT8 FileState;\r
161\r
162 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvHandle;\r
163 FileHeader = (EFI_FFS_FILE_HEADER **)FileHandle;\r
192f6d4c 164\r
165 FvLength = FwVolHeader->FvLength;\r
797a9d67 166 if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
192f6d4c 167 ErasePolarity = 1;\r
168 } else {\r
169 ErasePolarity = 0;\r
170 }\r
171 \r
172 //\r
b0d803fe 173 // If FileHeader is not specified (NULL) or FileName is not NULL,\r
174 // start with the first file in the firmware volume. Otherwise,\r
175 // start from the FileHeader.\r
192f6d4c 176 //\r
b0d803fe 177 if ((*FileHeader == NULL) || (FileName != NULL)) {\r
192f6d4c 178 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);\r
b0d803fe 179 if (FwVolHeader->ExtHeaderOffset != 0) {\r
180 FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(((UINT8 *)FwVolHeader) + FwVolHeader->ExtHeaderOffset);\r
181 FfsFileHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FwVolExHeaderInfo) + FwVolExHeaderInfo->ExtHeaderSize);\r
182 }\r
192f6d4c 183 } else {\r
184 //\r
185 // Length is 24 bits wide so mask upper 8 bits\r
186 // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.\r
187 //\r
188 FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF;\r
b0d803fe 189 FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);\r
192f6d4c 190 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize);\r
191 }\r
e98cd821 192 \r
192f6d4c 193 FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader);\r
194 ASSERT (FileOffset <= 0xFFFFFFFF);\r
e98cd821 195\r
b0d803fe 196 while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {\r
192f6d4c 197 //\r
198 // Get FileState which is the highest bit of the State \r
199 //\r
200 FileState = GetFileState (ErasePolarity, FfsFileHeader);\r
192f6d4c 201 switch (FileState) {\r
202\r
203 case EFI_FILE_HEADER_INVALID:\r
40f26b8f 204 FileOffset += sizeof(EFI_FFS_FILE_HEADER);\r
205 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER));\r
192f6d4c 206 break;\r
207 \r
208 case EFI_FILE_DATA_VALID:\r
209 case EFI_FILE_MARKED_FOR_UPDATE:\r
b0d803fe 210 if (CalculateHeaderChecksum (FfsFileHeader) != 0) {\r
192f6d4c 211 ASSERT (FALSE);\r
e98cd821 212 *FileHeader = NULL;\r
192f6d4c 213 return EFI_NOT_FOUND;\r
214 }\r
b0d803fe 215\r
40f26b8f 216 FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
b0d803fe 217 FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);\r
218\r
219 if (FileName != NULL) {\r
220 if (CompareGuid (&FfsFileHeader->Name, (EFI_GUID*)FileName)) {\r
221 *FileHeader = FfsFileHeader;\r
222 return EFI_SUCCESS;\r
223 }\r
224 } else if (SearchType == PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE) {\r
225 if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) || \r
288f9b38
LG
226 (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER) ||\r
227 (FfsFileHeader->Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE)) { \r
b0d803fe 228 \r
229 *FileHeader = FfsFileHeader;\r
230 return EFI_SUCCESS;\r
231 } else if (AprioriFile != NULL) {\r
232 if (FfsFileHeader->Type == EFI_FV_FILETYPE_FREEFORM) {\r
233 if (CompareGuid (&FfsFileHeader->Name, &gPeiAprioriFileNameGuid)) {\r
234 *AprioriFile = FfsFileHeader;\r
235 } \r
236 } \r
237 }\r
7e181f2f 238 } else if (((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) && \r
239 (FfsFileHeader->Type != EFI_FV_FILETYPE_FFS_PAD)) { \r
b0d803fe 240 *FileHeader = FfsFileHeader;\r
241 return EFI_SUCCESS;\r
242 }\r
243\r
40f26b8f 244 FileOffset += FileOccupiedSize; \r
245 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);\r
192f6d4c 246 break;\r
247 \r
248 case EFI_FILE_DELETED:\r
40f26b8f 249 FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
250 FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);\r
251 FileOffset += FileOccupiedSize;\r
252 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);\r
192f6d4c 253 break;\r
254\r
255 default:\r
e98cd821 256 *FileHeader = NULL;\r
192f6d4c 257 return EFI_NOT_FOUND;\r
192f6d4c 258 } \r
259 }\r
e98cd821
LG
260 \r
261 *FileHeader = NULL;\r
192f6d4c 262 return EFI_NOT_FOUND; \r
263}\r
264\r
b1f6a7c6 265/**\r
b1f6a7c6 266 Initialize PeiCore Fv List.\r
267\r
b1f6a7c6 268 @param PrivateData - Pointer to PEI_CORE_INSTANCE.\r
269 @param SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF.\r
b1f6a7c6 270**/\r
b0d803fe 271VOID \r
272PeiInitializeFv (\r
273 IN PEI_CORE_INSTANCE *PrivateData,\r
274 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData\r
275 )\r
b0d803fe 276{\r
277 EFI_STATUS Status;\r
278 //\r
279 // The BFV must be the first entry. The Core FV support is stateless \r
280 // The AllFV list has a single entry per FV in PEI. \r
281 // The Fv list only includes FV that PEIMs will be dispatched from and\r
282 // its File System Format is PI 1.0 definition.\r
283 //\r
284 PrivateData->FvCount = 1;\r
285 PrivateData->Fv[0].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;\r
286\r
287 PrivateData->AllFvCount = 1;\r
288 PrivateData->AllFv[0] = (EFI_PEI_FV_HANDLE)PrivateData->Fv[0].FvHeader;\r
289\r
290\r
291 //\r
292 // Post a call-back for the FvInfoPPI services to expose\r
293 // additional Fvs to PeiCore.\r
294 //\r
295 Status = PeiServicesNotifyPpi (&mNotifyOnFvInfoList);\r
296 ASSERT_EFI_ERROR (Status);\r
297\r
298}\r
299\r
b1f6a7c6 300/**\r
301 Process Firmware Volum Information once FvInfoPPI install.\r
ed299e3c
LG
302 The FV Info will be registered into PeiCore private data structure.\r
303 And search the inside FV image, if found, the new FV INFO PPI will be installed.\r
b1f6a7c6 304\r
ed299e3c 305 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
731bd38e 306 @param NotifyDescriptor Address of the notification descriptor data structure.\r
307 @param Ppi Address of the PPI that was installed.\r
b1f6a7c6 308\r
ed299e3c 309 @retval EFI_SUCCESS The FV Info is registered into PeiCore private data structure.\r
6a1ae84a 310 @return if not EFI_SUCESS, fail to verify FV.\r
b1f6a7c6 311\r
312**/\r
b0d803fe 313EFI_STATUS\r
314EFIAPI\r
315FirmwareVolmeInfoPpiNotifyCallback (\r
316 IN EFI_PEI_SERVICES **PeiServices,\r
317 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
318 IN VOID *Ppi\r
319 )\r
b0d803fe 320{\r
321 UINT8 FvCount;\r
322 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv;\r
323 PEI_CORE_INSTANCE *PrivateData;\r
288f9b38
LG
324 EFI_PEI_FILE_HANDLE FileHandle;\r
325 VOID *DepexData;\r
326 UINT32 AuthenticationStatus;\r
327 EFI_STATUS Status;\r
b0d803fe 328 \r
288f9b38
LG
329 FileHandle = NULL;\r
330 DepexData = NULL;\r
331 Status = EFI_SUCCESS;\r
332 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
b0d803fe 333\r
177aabe6 334 if (PrivateData->FvCount >= FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {\r
b0d803fe 335 ASSERT (FALSE);\r
336 }\r
337\r
338 Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *)Ppi;\r
339\r
288f9b38
LG
340 if (CompareGuid (&Fv->FvFormat, &gEfiFirmwareFileSystem2Guid)) {\r
341 for (FvCount = 0; FvCount < PrivateData->FvCount; FvCount ++) {\r
342 if ((UINTN)PrivateData->Fv[FvCount].FvHeader == (UINTN)Fv->FvInfo) {\r
343 return EFI_SUCCESS;\r
344 }\r
345 }\r
6a1ae84a 346 \r
347 Status = VerifyFv ((EFI_FIRMWARE_VOLUME_HEADER*)Fv->FvInfo);\r
348 if (EFI_ERROR(Status)) {\r
349 DEBUG ((EFI_D_ERROR, "Fail to verify FV which address is 0x%11p", (VOID *) Fv->FvInfo));\r
350 return Status;\r
351 }\r
352 \r
b0d803fe 353 PrivateData->Fv[PrivateData->FvCount++].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Fv->FvInfo;\r
b0d803fe 354\r
288f9b38
LG
355 //\r
356 // Only add FileSystem2 Fv to the All list\r
357 //\r
358 PrivateData->AllFv[PrivateData->AllFvCount++] = (EFI_PEI_FV_HANDLE)Fv->FvInfo;\r
359 \r
91136124 360 DEBUG ((EFI_D_INFO, "The %dth FvImage start address is 0x%11p and size is 0x%08x\n", PrivateData->AllFvCount, (VOID *) Fv->FvInfo, Fv->FvInfoSize));\r
288f9b38
LG
361 //\r
362 // Preprocess all FV type files in this new FileSystem2 Fv image\r
363 //\r
364 do {\r
365 Status = PeiFindFileEx (\r
366 (EFI_PEI_FV_HANDLE)Fv->FvInfo, \r
367 NULL, \r
368 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, \r
369 &FileHandle, \r
370 NULL\r
371 );\r
372 if (!EFI_ERROR (Status)) {\r
373 Status = PeiFfsFindSectionData (\r
374 (CONST EFI_PEI_SERVICES **) PeiServices,\r
375 EFI_SECTION_PEI_DEPEX,\r
376 FileHandle, \r
377 (VOID **)&DepexData\r
378 );\r
379 if (!EFI_ERROR (Status)) {\r
380 if (!PeimDispatchReadiness (PeiServices, DepexData)) {\r
381 //\r
382 // Dependency is not satisfied.\r
383 //\r
384 continue;\r
385 }\r
386 }\r
387 //\r
388 // Process FvFile to install FvInfo ppi and build FvHob\r
389 // \r
390 ProcessFvFile (PeiServices, FileHandle, &AuthenticationStatus);\r
391 }\r
392 } while (FileHandle != NULL);\r
393 }\r
b0d803fe 394\r
395 return EFI_SUCCESS;\r
396}\r
397\r
b1f6a7c6 398/**\r
ed299e3c
LG
399 Go through the file to search SectionType section. \r
400 Search within encapsulation sections (compression and GUIDed) recursively, \r
401 until the match section is found.\r
402 \r
403 @param PeiServices - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
404 @param SectionType - Filter to find only section of this type.\r
405 @param Section - From where to search.\r
406 @param SectionSize - The file size to search.\r
407 @param OutputBuffer - A pointer to the discovered section, if successful.\r
408 NULL if section not found\r
b1f6a7c6 409\r
ed299e3c
LG
410 @return EFI_NOT_FOUND The match section is not found.\r
411 @return EFI_SUCCESS The match section is found.\r
b1f6a7c6 412\r
413**/\r
b0d803fe 414EFI_STATUS\r
415PeiFfsProcessSection (\r
416 IN CONST EFI_PEI_SERVICES **PeiServices,\r
417 IN EFI_SECTION_TYPE SectionType,\r
418 IN EFI_COMMON_SECTION_HEADER *Section,\r
419 IN UINTN SectionSize,\r
288f9b38 420 OUT VOID **OutputBuffer\r
b0d803fe 421 )\r
b0d803fe 422{\r
423 EFI_STATUS Status;\r
424 UINT32 SectionLength;\r
425 UINT32 ParsedLength;\r
b0d803fe 426 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *GuidSectionPpi;\r
b0d803fe 427 EFI_PEI_DECOMPRESS_PPI *DecompressPpi;\r
428 VOID *PpiOutput;\r
429 UINTN PpiOutputSize;\r
288f9b38
LG
430 UINTN Index;\r
431 UINT32 Authentication;\r
432 PEI_CORE_INSTANCE *PrivateData;\r
b0d803fe 433\r
288f9b38 434 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
b0d803fe 435 *OutputBuffer = NULL;\r
288f9b38
LG
436 ParsedLength = 0;\r
437 Index = 0;\r
438 Status = EFI_NOT_FOUND;\r
439 PpiOutput = NULL;\r
440 PpiOutputSize = 0;\r
b0d803fe 441 while (ParsedLength < SectionSize) {\r
442 if (Section->Type == SectionType) {\r
443 *OutputBuffer = (VOID *)(Section + 1);\r
444 return EFI_SUCCESS;\r
288f9b38
LG
445 } else if ((Section->Type == EFI_SECTION_GUID_DEFINED) || (Section->Type == EFI_SECTION_COMPRESSION)) {\r
446 //\r
447 // Check the encapsulated section is extracted into the cache data.\r
448 //\r
449 for (Index = 0; Index < PrivateData->CacheSection.AllSectionCount; Index ++) {\r
450 if (Section == PrivateData->CacheSection.Section[Index]) {\r
451 PpiOutput = PrivateData->CacheSection.SectionData[Index];\r
452 PpiOutputSize = PrivateData->CacheSection.SectionSize[Index];\r
453 //\r
454 // Search section directly from the cache data.\r
455 //\r
b0d803fe 456 return PeiFfsProcessSection (\r
457 PeiServices,\r
458 SectionType, \r
459 PpiOutput, \r
460 PpiOutputSize, \r
288f9b38 461 OutputBuffer \r
b0d803fe 462 );\r
463 }\r
464 }\r
288f9b38
LG
465 \r
466 Status = EFI_NOT_FOUND;\r
467 if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
468 Status = PeiServicesLocatePpi (\r
469 &((EFI_GUID_DEFINED_SECTION *)Section)->SectionDefinitionGuid, \r
470 0, \r
471 NULL, \r
472 (VOID **) &GuidSectionPpi\r
473 );\r
b0d803fe 474 if (!EFI_ERROR (Status)) {\r
288f9b38
LG
475 Status = GuidSectionPpi->ExtractSection (\r
476 GuidSectionPpi,\r
477 Section,\r
478 &PpiOutput,\r
479 &PpiOutputSize,\r
480 &Authentication\r
481 );\r
482 }\r
483 } else if (Section->Type == EFI_SECTION_COMPRESSION) {\r
484 Status = PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid, 0, NULL, (VOID **) &DecompressPpi);\r
485 if (!EFI_ERROR (Status)) {\r
486 Status = DecompressPpi->Decompress (\r
487 DecompressPpi,\r
488 (CONST EFI_COMPRESSION_SECTION*) Section,\r
489 &PpiOutput,\r
490 &PpiOutputSize\r
491 );\r
b0d803fe 492 }\r
493 }\r
288f9b38
LG
494 \r
495 if (!EFI_ERROR (Status)) {\r
496 //\r
497 // Update cache section data.\r
498 //\r
499 if (PrivateData->CacheSection.AllSectionCount < CACHE_SETION_MAX_NUMBER) {\r
500 PrivateData->CacheSection.AllSectionCount ++;\r
501 }\r
502 PrivateData->CacheSection.Section [PrivateData->CacheSection.SectionIndex] = Section;\r
503 PrivateData->CacheSection.SectionData [PrivateData->CacheSection.SectionIndex] = PpiOutput;\r
504 PrivateData->CacheSection.SectionSize [PrivateData->CacheSection.SectionIndex] = PpiOutputSize;\r
505 PrivateData->CacheSection.SectionIndex = (PrivateData->CacheSection.SectionIndex + 1)%CACHE_SETION_MAX_NUMBER;\r
506 \r
507 return PeiFfsProcessSection (\r
508 PeiServices,\r
509 SectionType, \r
510 PpiOutput, \r
511 PpiOutputSize, \r
512 OutputBuffer \r
513 );\r
514 }\r
b0d803fe 515 }\r
516\r
517 //\r
518 // Size is 24 bits wide so mask upper 8 bits. \r
519 // SectionLength is adjusted it is 4 byte aligned.\r
520 // Go to the next section\r
521 //\r
522 SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;\r
523 SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
524 ASSERT (SectionLength != 0);\r
525 ParsedLength += SectionLength;\r
526 Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);\r
527 }\r
528 \r
529 return EFI_NOT_FOUND;\r
530}\r
531\r
192f6d4c 532\r
b1f6a7c6 533/**\r
ed299e3c 534 Given the input file pointer, search for the first matching section in the\r
b1f6a7c6 535 FFS volume.\r
536\r
ed299e3c 537 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
b1f6a7c6 538 @param SectionType Filter to find only sections of this type.\r
539 @param FileHandle Pointer to the current file to search.\r
ed299e3c 540 @param SectionData A pointer to the discovered section, if successful.\r
b1f6a7c6 541 NULL if section not found\r
542\r
543 @retval EFI_NOT_FOUND No files matching the search criteria were found\r
544 @retval EFI_SUCCESS Success to find section data in given file\r
545\r
546**/\r
192f6d4c 547EFI_STATUS\r
548EFIAPI\r
549PeiFfsFindSectionData (\r
0c2b5da8 550 IN CONST EFI_PEI_SERVICES **PeiServices,\r
192f6d4c 551 IN EFI_SECTION_TYPE SectionType,\r
0c2b5da8 552 IN EFI_PEI_FILE_HANDLE FileHandle,\r
192f6d4c 553 IN OUT VOID **SectionData\r
554 )\r
192f6d4c 555{\r
b0d803fe 556 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
557 UINT32 FileSize;\r
558 EFI_COMMON_SECTION_HEADER *Section;\r
b0d803fe 559\r
560 FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);\r
192f6d4c 561\r
562 //\r
563 // Size is 24 bits wide so mask upper 8 bits. \r
b0d803fe 564 // Does not include FfsFileHeader header size\r
192f6d4c 565 // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.\r
566 //\r
567 Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1);\r
568 FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
b0d803fe 569 FileSize -= sizeof (EFI_FFS_FILE_HEADER);\r
570\r
571 return PeiFfsProcessSection (\r
288f9b38 572 PeiServices,\r
b0d803fe 573 SectionType, \r
574 Section, \r
575 FileSize, \r
288f9b38 576 SectionData\r
b0d803fe 577 );\r
192f6d4c 578}\r
579\r
b1f6a7c6 580/**\r
581 Given the input file pointer, search for the next matching file in the\r
582 FFS volume as defined by SearchType. The search starts from FileHeader inside\r
583 the Firmware Volume defined by FwVolHeader.\r
192f6d4c 584\r
b1f6a7c6 585\r
d73d93c3 586 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
b1f6a7c6 587 @param SearchType Filter to find only files of this type.\r
588 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.\r
589 @param VolumeHandle Pointer to the FV header of the volume to search.\r
590 @param FileHandle Pointer to the current file from which to begin searching.\r
591 This pointer will be updated upon return to reflect the file found.\r
592 @retval EFI_NOT_FOUND No files matching the search criteria were found\r
593 @retval EFI_SUCCESS Success to find next file in given volume\r
594\r
595**/\r
192f6d4c 596EFI_STATUS\r
597EFIAPI\r
598PeiFfsFindNextFile (\r
0c2b5da8 599 IN CONST EFI_PEI_SERVICES **PeiServices,\r
600 IN UINT8 SearchType,\r
601 IN EFI_PEI_FV_HANDLE VolumeHandle,\r
602 IN OUT EFI_PEI_FILE_HANDLE *FileHandle\r
192f6d4c 603 )\r
192f6d4c 604{\r
b0d803fe 605 return PeiFindFileEx (VolumeHandle, NULL, SearchType, FileHandle, NULL);\r
192f6d4c 606}\r
607\r
b0d803fe 608\r
b1f6a7c6 609/**\r
ed299e3c 610 Search the firmware volumes by index\r
b1f6a7c6 611\r
ed299e3c 612 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
b1f6a7c6 613 @param Instance Instance of FV to find\r
614 @param VolumeHandle Pointer to found Volume.\r
615\r
616 @retval EFI_INVALID_PARAMETER FwVolHeader is NULL\r
617 @retval EFI_SUCCESS Firmware volume instance successfully found.\r
618\r
619**/\r
192f6d4c 620EFI_STATUS \r
621EFIAPI\r
622PeiFvFindNextVolume (\r
2a00326e 623 IN CONST EFI_PEI_SERVICES **PeiServices,\r
192f6d4c 624 IN UINTN Instance,\r
0c2b5da8 625 IN OUT EFI_PEI_FV_HANDLE *VolumeHandle\r
192f6d4c 626 )\r
192f6d4c 627{\r
2a00326e
LG
628 PEI_CORE_INSTANCE *Private;\r
629 UINTN Index;\r
630 BOOLEAN Match;\r
631 EFI_HOB_FIRMWARE_VOLUME *FvHob;\r
192f6d4c 632\r
b0d803fe 633 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
634 if (VolumeHandle == NULL) {\r
635 return EFI_INVALID_PARAMETER;\r
2a00326e
LG
636 }\r
637 \r
638 //\r
639 // Handle Framework FvHob and Install FvInfo Ppi for it.\r
640 //\r
641 if (FeaturePcdGet (PcdFrameworkFvHobCompatibilitySupport)) {\r
642 //\r
643 // Loop to search the wanted FirmwareVolume which supports FFS\r
644 //\r
645 FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetFirstHob (EFI_HOB_TYPE_FV);\r
646 while (FvHob != NULL) {\r
647 for (Index = 0, Match = FALSE; Index < Private->AllFvCount; Index++) {\r
648 if ((EFI_PEI_FV_HANDLE)(UINTN)FvHob->BaseAddress == Private->AllFv[Index]) {\r
649 Match = TRUE;\r
650 break;\r
651 }\r
652 }\r
653 //\r
654 // If Not Found, Install FvInfo Ppi for it.\r
655 //\r
656 if (!Match) {\r
657 PiLibInstallFvInfoPpi (\r
658 NULL,\r
659 (VOID *)(UINTN)FvHob->BaseAddress,\r
660 (UINT32)FvHob->Length,\r
661 NULL,\r
662 NULL\r
663 );\r
664 }\r
665 FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetNextHob (EFI_HOB_TYPE_FV, (VOID *)((UINTN)FvHob + FvHob->Header.HobLength)); \r
666 }\r
667 }\r
192f6d4c 668\r
b0d803fe 669 if (Instance >= Private->AllFvCount) {\r
670 VolumeHandle = NULL;\r
671 return EFI_NOT_FOUND;\r
672 }\r
192f6d4c 673\r
b0d803fe 674 *VolumeHandle = Private->AllFv[Instance];\r
675 return EFI_SUCCESS;\r
676}\r
192f6d4c 677\r
192f6d4c 678\r
b1f6a7c6 679/**\r
ed299e3c 680 Find a file within a volume by its name.\r
b1f6a7c6 681\r
ed299e3c
LG
682 @param FileName A pointer to the name of the file to find within the firmware volume.\r
683 @param VolumeHandle The firmware volume to search\r
684 @param FileHandle Upon exit, points to the found file's handle \r
685 or NULL if it could not be found.\r
b1f6a7c6 686\r
ed299e3c
LG
687 @retval EFI_SUCCESS File was found.\r
688 @retval EFI_NOT_FOUND File was not found.\r
689 @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or FileName was NULL.\r
b1f6a7c6 690\r
b1f6a7c6 691**/\r
b0d803fe 692EFI_STATUS\r
693EFIAPI \r
694PeiFfsFindFileByName (\r
695 IN CONST EFI_GUID *FileName,\r
696 IN EFI_PEI_FV_HANDLE VolumeHandle,\r
697 OUT EFI_PEI_FILE_HANDLE *FileHandle\r
698 )\r
b0d803fe 699{\r
700 EFI_STATUS Status;\r
701 if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {\r
192f6d4c 702 return EFI_INVALID_PARAMETER;\r
703 }\r
b0d803fe 704 Status = PeiFindFileEx (VolumeHandle, FileName, 0, FileHandle, NULL);\r
705 if (Status == EFI_NOT_FOUND) {\r
706 *FileHandle = NULL;\r
707 }\r
708 return Status;\r
709}\r
710\r
b1f6a7c6 711/**\r
712\r
713 Returns information about a specific file.\r
714\r
715\r
716 @param FileHandle - The handle to file.\r
717 @param FileInfo - Pointer to the file information.\r
718\r
719 @retval EFI_INVALID_PARAMETER Invalid FileHandle or FileInfo.\r
720 @retval EFI_SUCCESS Success to collect file info.\r
721\r
722**/\r
b0d803fe 723EFI_STATUS\r
724EFIAPI \r
725PeiFfsGetFileInfo (\r
726 IN EFI_PEI_FILE_HANDLE FileHandle,\r
727 OUT EFI_FV_FILE_INFO *FileInfo\r
728 )\r
b0d803fe 729{\r
730 UINT8 FileState;\r
731 UINT8 ErasePolarity;\r
732 EFI_FFS_FILE_HEADER *FileHeader;\r
733 EFI_PEI_FV_HANDLE VolumeHandle;\r
734\r
735 if ((FileHandle == NULL) || (FileInfo == NULL)) {\r
736 return EFI_INVALID_PARAMETER;\r
737 }\r
738\r
173b35e4 739 VolumeHandle = 0;\r
b0d803fe 740 //\r
741 // Retrieve the FirmwareVolume which the file resides in.\r
742 //\r
743 if (!PeiFileHandleToVolume(FileHandle, &VolumeHandle)) {\r
744 return EFI_INVALID_PARAMETER;\r
745 }\r
746\r
797a9d67 747 if (((EFI_FIRMWARE_VOLUME_HEADER*)VolumeHandle)->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
b0d803fe 748 ErasePolarity = 1;\r
192f6d4c 749 } else {\r
b0d803fe 750 ErasePolarity = 0;\r
751 }\r
752\r
753 //\r
754 // Get FileState which is the highest bit of the State \r
755 //\r
756 FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle);\r
192f6d4c 757\r
b0d803fe 758 switch (FileState) {\r
759 case EFI_FILE_DATA_VALID:\r
760 case EFI_FILE_MARKED_FOR_UPDATE:\r
761 break; \r
762 default:\r
763 return EFI_INVALID_PARAMETER;\r
192f6d4c 764 }\r
b0d803fe 765\r
766 FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;\r
767 CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID));\r
768 FileInfo->FileType = FileHeader->Type;\r
769 FileInfo->FileAttributes = FileHeader->Attributes;\r
770 FileInfo->BufferSize = ((*(UINT32 *)FileHeader->Size) & 0x00FFFFFF) - sizeof (EFI_FFS_FILE_HEADER);\r
771 FileInfo->Buffer = (FileHeader + 1);\r
772 return EFI_SUCCESS;\r
773}\r
774\r
775\r
b1f6a7c6 776/**\r
777\r
778 Collect information of given Fv Volume.\r
779\r
780 @param VolumeHandle - The handle to Fv Volume.\r
781 @param VolumeInfo - The pointer to volume information.\r
782\r
783 @retval EFI_INVALID_PARAMETER VolumeInfo is NULL\r
784 @retval EFI_SUCCESS Success to collect fv info.\r
785**/\r
b0d803fe 786EFI_STATUS\r
787EFIAPI \r
788PeiFfsGetVolumeInfo (\r
789 IN EFI_PEI_FV_HANDLE VolumeHandle,\r
790 OUT EFI_FV_INFO *VolumeInfo\r
791 )\r
b0d803fe 792{\r
288f9b38 793 EFI_FIRMWARE_VOLUME_HEADER FwVolHeader;\r
b0d803fe 794 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;\r
795\r
796 if (VolumeInfo == NULL) {\r
797 return EFI_INVALID_PARAMETER;\r
192f6d4c 798 }\r
288f9b38
LG
799 \r
800 //\r
801 // VolumeHandle may not align at 8 byte, \r
802 // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte. \r
803 // So, Copy FvHeader into the local FvHeader structure.\r
804 //\r
805 CopyMem (&FwVolHeader, VolumeHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
806 //\r
807 // Check Fv Image Signature\r
808 //\r
809 if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {\r
810 return EFI_INVALID_PARAMETER;\r
811 }\r
812 VolumeInfo->FvAttributes = FwVolHeader.Attributes;\r
813 VolumeInfo->FvStart = (VOID *) VolumeHandle;\r
814 VolumeInfo->FvSize = FwVolHeader.FvLength;\r
815 CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID));\r
b0d803fe 816\r
288f9b38
LG
817 if (FwVolHeader.ExtHeaderOffset != 0) {\r
818 FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)VolumeHandle) + FwVolHeader.ExtHeaderOffset);\r
b0d803fe 819 CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID));\r
820 }\r
821 return EFI_SUCCESS;\r
192f6d4c 822}\r
b0d803fe 823\r
4c6486b9 824/**\r
825 Get Fv image from the FV type file, then install FV INFO ppi, Build FV hob.\r
826\r
827 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
828 @param FvFileHandle File handle of a Fv type file.\r
829 @param AuthenticationState Pointer to attestation authentication state of image.\r
830\r
831\r
832 @retval EFI_NOT_FOUND FV image can't be found.\r
833 @retval EFI_SUCCESS Successfully to process it.\r
834 @retval EFI_OUT_OF_RESOURCES Can not allocate page when aligning FV image\r
835 @retval Others Can not find EFI_SECTION_FIRMWARE_VOLUME_IMAGE section\r
836 \r
837**/\r
838EFI_STATUS\r
839ProcessFvFile (\r
840 IN EFI_PEI_SERVICES **PeiServices,\r
841 IN EFI_PEI_FILE_HANDLE FvFileHandle,\r
842 OUT UINT32 *AuthenticationState\r
843 )\r
844{\r
845 EFI_STATUS Status;\r
846 EFI_PEI_FV_HANDLE FvImageHandle;\r
847 EFI_FV_INFO FvImageInfo;\r
848 UINT32 FvAlignment;\r
849 VOID *FvBuffer;\r
850 EFI_PEI_HOB_POINTERS HobPtr;\r
851\r
852 FvBuffer = NULL;\r
853 *AuthenticationState = 0;\r
854\r
855 //\r
856 // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already\r
857 // been extracted.\r
858 //\r
859 HobPtr.Raw = GetHobList ();\r
860 while ((HobPtr.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobPtr.Raw)) != NULL) {\r
861 if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name), &HobPtr.FirmwareVolume2->FileName)) {\r
862 //\r
863 // this FILE has been dispatched, it will not be dispatched again.\r
864 //\r
865 return EFI_SUCCESS;\r
866 }\r
867 HobPtr.Raw = GET_NEXT_HOB (HobPtr);\r
868 }\r
869\r
870 //\r
871 // Find FvImage in FvFile\r
872 //\r
873 Status = PeiFfsFindSectionData (\r
874 (CONST EFI_PEI_SERVICES **) PeiServices,\r
875 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
876 FvFileHandle,\r
877 (VOID **)&FvImageHandle\r
878 );\r
879\r
880 if (EFI_ERROR (Status)) {\r
881 return Status;\r
882 }\r
883 \r
884 //\r
885 // Collect FvImage Info.\r
886 //\r
887 Status = PeiFfsGetVolumeInfo (FvImageHandle, &FvImageInfo);\r
888 ASSERT_EFI_ERROR (Status);\r
889 \r
890 //\r
891 // FvAlignment must be more than 8 bytes required by FvHeader structure.\r
892 //\r
893 FvAlignment = 1 << ((FvImageInfo.FvAttributes & EFI_FVB2_ALIGNMENT) >> 16);\r
894 if (FvAlignment < 8) {\r
895 FvAlignment = 8;\r
896 }\r
897 \r
898 //\r
899 // Check FvImage\r
900 //\r
901 if ((UINTN) FvImageInfo.FvStart % FvAlignment != 0) {\r
902 FvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvImageInfo.FvSize), FvAlignment);\r
903 if (FvBuffer == NULL) {\r
904 return EFI_OUT_OF_RESOURCES;\r
905 }\r
906 CopyMem (FvBuffer, FvImageInfo.FvStart, (UINTN) FvImageInfo.FvSize);\r
907 //\r
908 // Update FvImageInfo after reload FvImage to new aligned memory\r
909 //\r
910 PeiFfsGetVolumeInfo ((EFI_PEI_FV_HANDLE) FvBuffer, &FvImageInfo);\r
911 }\r
912\r
913 //\r
914 // Install FvPpi and Build FvHob\r
915 //\r
916 PiLibInstallFvInfoPpi (\r
917 NULL,\r
918 FvImageInfo.FvStart,\r
919 (UINT32) FvImageInfo.FvSize,\r
920 &(FvImageInfo.FvName),\r
921 &(((EFI_FFS_FILE_HEADER*)FvFileHandle)->Name)\r
922 );\r
923\r
924 //\r
925 // Inform the extracted FvImage to Fv HOB consumer phase, i.e. DXE phase\r
4c6486b9 926 //\r
223c22d8
LG
927 BuildFvHob (\r
928 (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart,\r
929 FvImageInfo.FvSize\r
930 );\r
4c6486b9 931\r
932 //\r
933 // Makes the encapsulated volume show up in DXE phase to skip processing of\r
934 // encapsulated file again.\r
935 //\r
936 BuildFv2Hob (\r
937 (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart,\r
938 FvImageInfo.FvSize,\r
939 &FvImageInfo.FvName,\r
940 &(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name)\r
941 );\r
942\r
943 return EFI_SUCCESS;\r
944}\r
945\r
946\r