]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/FwVol/FwVol.c
correct comments
[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
b0d803fe 4Copyright (c) 2006 - 2007, 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
192f6d4c 25 (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))\r
26\r
b1f6a7c6 27/**\r
192f6d4c 28 Returns the highest bit set of the State field\r
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
b1f6a7c6 34 @return Returns the highest bit in the State field\r
192f6d4c 35\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
51\r
52 HighestBit = 0x80;\r
53 while (HighestBit != 0 && (HighestBit & FileState) == 0) {\r
54 HighestBit >>= 1;\r
55 }\r
56\r
57 return HighestBit;\r
58} \r
59\r
b1f6a7c6 60/**\r
61 Calculates the checksum of the header of a file.\r
62\r
63 @param FileHeader Pointer to FFS File Header.\r
64\r
65 @return Checksum of the header.\r
66 The header is zero byte checksum.\r
67 Zero means the header is good.\r
68 Non-zero means the header is bad.\r
69**/\r
192f6d4c 70UINT8\r
71CalculateHeaderChecksum (\r
72 IN EFI_FFS_FILE_HEADER *FileHeader\r
73 )\r
192f6d4c 74{\r
b1f6a7c6 75 UINT8 *Ptr;\r
192f6d4c 76 UINTN Index;\r
77 UINT8 Sum;\r
78 \r
79 Sum = 0;\r
b1f6a7c6 80 Ptr = (UINT8 *)FileHeader;\r
192f6d4c 81\r
82 for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER) - 3; Index += 4) {\r
b1f6a7c6 83 Sum = (UINT8)(Sum + Ptr[Index]);\r
84 Sum = (UINT8)(Sum + Ptr[Index+1]);\r
85 Sum = (UINT8)(Sum + Ptr[Index+2]);\r
86 Sum = (UINT8)(Sum + Ptr[Index+3]);\r
192f6d4c 87 }\r
88\r
89 for (; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) {\r
b1f6a7c6 90 Sum = (UINT8)(Sum + Ptr[Index]);\r
192f6d4c 91 }\r
92 \r
93 //\r
94 // State field (since this indicates the different state of file). \r
95 //\r
96 Sum = (UINT8)(Sum - FileHeader->State);\r
97 //\r
98 // Checksum field of the file is not part of the header checksum.\r
99 //\r
100 Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File);\r
101\r
102 return Sum;\r
103}\r
104\r
b1f6a7c6 105/**\r
106 Find FV handler according some FileHandle in that FV.\r
107\r
108 @param FileHandle Handle of file image\r
109 @param VolumeHandle Handle of FV\r
110\r
111 @return EDES_TODO: Add description for return value\r
112\r
113**/\r
b0d803fe 114BOOLEAN\r
115EFIAPI\r
116PeiFileHandleToVolume (\r
117 IN EFI_PEI_FILE_HANDLE FileHandle,\r
118 OUT EFI_PEI_FV_HANDLE *VolumeHandle\r
119 )\r
120{\r
121 UINTN Index;\r
122 PEI_CORE_INSTANCE *PrivateData;\r
123 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
124\r
125 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());\r
126 for (Index = 0; Index < PrivateData->FvCount; Index++) {\r
127 FwVolHeader = PrivateData->Fv[Index].FvHeader;\r
67a58d0f 128 if (((UINT64) (UINTN) FileHandle > (UINT64) (UINTN) FwVolHeader ) && \\r
129 ((UINT64) (UINTN) FileHandle <= ((UINT64) (UINTN) FwVolHeader + FwVolHeader->FvLength - 1))) {\r
b0d803fe 130 *VolumeHandle = (EFI_PEI_FV_HANDLE)FwVolHeader;\r
131 return TRUE;\r
132 }\r
133 }\r
134 return FALSE;\r
135}\r
136\r
b1f6a7c6 137/**\r
138 Given the input file pointer, search for the next matching file in the\r
139 FFS volume as defined by SearchType. The search starts from FileHeader inside\r
140 the Firmware Volume defined by FwVolHeader.\r
141\r
142\r
143 @param FvHandle Pointer to the FV header of the volume to search\r
144 @param FileName File name\r
145 @param SearchType Filter to find only files of this type.\r
146 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.\r
147 @param FileHandle This parameter must point to a valid FFS volume.\r
148 @param AprioriFile Pointer to AprioriFile image in this FV if has\r
b0d803fe 149\r
b1f6a7c6 150 @return EFI_NOT_FOUND No files matching the search criteria were found\r
151 @retval EFI_SUCCESS Success to search given file\r
152\r
153**/\r
192f6d4c 154EFI_STATUS\r
b0d803fe 155PeiFindFileEx (\r
156 IN CONST EFI_PEI_FV_HANDLE FvHandle,\r
157 IN CONST EFI_GUID *FileName, OPTIONAL\r
158 IN EFI_FV_FILETYPE SearchType,\r
159 IN OUT EFI_PEI_FILE_HANDLE *FileHandle,\r
160 IN OUT EFI_PEI_FV_HANDLE *AprioriFile OPTIONAL\r
192f6d4c 161 )\r
192f6d4c 162{\r
b0d803fe 163 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
164 EFI_FFS_FILE_HEADER **FileHeader;\r
165 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
166 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;\r
167 UINT32 FileLength;\r
168 UINT32 FileOccupiedSize;\r
169 UINT32 FileOffset;\r
170 UINT64 FvLength;\r
171 UINT8 ErasePolarity;\r
172 UINT8 FileState;\r
173\r
174 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvHandle;\r
175 FileHeader = (EFI_FFS_FILE_HEADER **)FileHandle;\r
192f6d4c 176\r
177 FvLength = FwVolHeader->FvLength;\r
797a9d67 178 if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
192f6d4c 179 ErasePolarity = 1;\r
180 } else {\r
181 ErasePolarity = 0;\r
182 }\r
183 \r
184 //\r
b0d803fe 185 // If FileHeader is not specified (NULL) or FileName is not NULL,\r
186 // start with the first file in the firmware volume. Otherwise,\r
187 // start from the FileHeader.\r
192f6d4c 188 //\r
b0d803fe 189 if ((*FileHeader == NULL) || (FileName != NULL)) {\r
192f6d4c 190 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);\r
b0d803fe 191 if (FwVolHeader->ExtHeaderOffset != 0) {\r
192 FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(((UINT8 *)FwVolHeader) + FwVolHeader->ExtHeaderOffset);\r
193 FfsFileHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FwVolExHeaderInfo) + FwVolExHeaderInfo->ExtHeaderSize);\r
194 }\r
192f6d4c 195 } else {\r
196 //\r
197 // Length is 24 bits wide so mask upper 8 bits\r
198 // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.\r
199 //\r
200 FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF;\r
b0d803fe 201 FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);\r
192f6d4c 202 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize);\r
203 }\r
e98cd821 204 \r
192f6d4c 205 FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader);\r
206 ASSERT (FileOffset <= 0xFFFFFFFF);\r
e98cd821 207\r
b0d803fe 208 while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {\r
192f6d4c 209 //\r
210 // Get FileState which is the highest bit of the State \r
211 //\r
212 FileState = GetFileState (ErasePolarity, FfsFileHeader);\r
192f6d4c 213 switch (FileState) {\r
214\r
215 case EFI_FILE_HEADER_INVALID:\r
40f26b8f 216 FileOffset += sizeof(EFI_FFS_FILE_HEADER);\r
217 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER));\r
192f6d4c 218 break;\r
219 \r
220 case EFI_FILE_DATA_VALID:\r
221 case EFI_FILE_MARKED_FOR_UPDATE:\r
b0d803fe 222 if (CalculateHeaderChecksum (FfsFileHeader) != 0) {\r
192f6d4c 223 ASSERT (FALSE);\r
e98cd821 224 *FileHeader = NULL;\r
192f6d4c 225 return EFI_NOT_FOUND;\r
226 }\r
b0d803fe 227\r
40f26b8f 228 FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
b0d803fe 229 FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);\r
230\r
231 if (FileName != NULL) {\r
232 if (CompareGuid (&FfsFileHeader->Name, (EFI_GUID*)FileName)) {\r
233 *FileHeader = FfsFileHeader;\r
234 return EFI_SUCCESS;\r
235 }\r
236 } else if (SearchType == PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE) {\r
237 if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) || \r
288f9b38
LG
238 (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER) ||\r
239 (FfsFileHeader->Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE)) { \r
b0d803fe 240 \r
241 *FileHeader = FfsFileHeader;\r
242 return EFI_SUCCESS;\r
243 } else if (AprioriFile != NULL) {\r
244 if (FfsFileHeader->Type == EFI_FV_FILETYPE_FREEFORM) {\r
245 if (CompareGuid (&FfsFileHeader->Name, &gPeiAprioriFileNameGuid)) {\r
246 *AprioriFile = FfsFileHeader;\r
247 } \r
248 } \r
249 }\r
7e181f2f 250 } else if (((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) && \r
251 (FfsFileHeader->Type != EFI_FV_FILETYPE_FFS_PAD)) { \r
b0d803fe 252 *FileHeader = FfsFileHeader;\r
253 return EFI_SUCCESS;\r
254 }\r
255\r
40f26b8f 256 FileOffset += FileOccupiedSize; \r
257 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);\r
192f6d4c 258 break;\r
259 \r
260 case EFI_FILE_DELETED:\r
40f26b8f 261 FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
262 FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);\r
263 FileOffset += FileOccupiedSize;\r
264 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);\r
192f6d4c 265 break;\r
266\r
267 default:\r
e98cd821 268 *FileHeader = NULL;\r
192f6d4c 269 return EFI_NOT_FOUND;\r
192f6d4c 270 } \r
271 }\r
e98cd821
LG
272 \r
273 *FileHeader = NULL;\r
192f6d4c 274 return EFI_NOT_FOUND; \r
275}\r
276\r
b1f6a7c6 277/**\r
b1f6a7c6 278 Initialize PeiCore Fv List.\r
279\r
b1f6a7c6 280 @param PrivateData - Pointer to PEI_CORE_INSTANCE.\r
281 @param SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF.\r
b1f6a7c6 282**/\r
b0d803fe 283VOID \r
284PeiInitializeFv (\r
285 IN PEI_CORE_INSTANCE *PrivateData,\r
286 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData\r
287 )\r
b0d803fe 288{\r
289 EFI_STATUS Status;\r
290 //\r
291 // The BFV must be the first entry. The Core FV support is stateless \r
292 // The AllFV list has a single entry per FV in PEI. \r
293 // The Fv list only includes FV that PEIMs will be dispatched from and\r
294 // its File System Format is PI 1.0 definition.\r
295 //\r
296 PrivateData->FvCount = 1;\r
297 PrivateData->Fv[0].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;\r
298\r
299 PrivateData->AllFvCount = 1;\r
300 PrivateData->AllFv[0] = (EFI_PEI_FV_HANDLE)PrivateData->Fv[0].FvHeader;\r
301\r
302\r
303 //\r
304 // Post a call-back for the FvInfoPPI services to expose\r
305 // additional Fvs to PeiCore.\r
306 //\r
307 Status = PeiServicesNotifyPpi (&mNotifyOnFvInfoList);\r
308 ASSERT_EFI_ERROR (Status);\r
309\r
310}\r
311\r
b1f6a7c6 312/**\r
313 Process Firmware Volum Information once FvInfoPPI install.\r
314\r
315\r
316 @param PeiServices - General purpose services available to every PEIM.\r
317 @param NotifyDescriptor EDES_TODO: Add parameter description\r
318 @param Ppi EDES_TODO: Add parameter description\r
319\r
320 @retval EFI_SUCCESS if the interface could be successfully installed\r
321\r
322**/\r
b0d803fe 323EFI_STATUS\r
324EFIAPI\r
325FirmwareVolmeInfoPpiNotifyCallback (\r
326 IN EFI_PEI_SERVICES **PeiServices,\r
327 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
328 IN VOID *Ppi\r
329 )\r
b0d803fe 330{\r
331 UINT8 FvCount;\r
332 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv;\r
333 PEI_CORE_INSTANCE *PrivateData;\r
288f9b38
LG
334 EFI_PEI_FILE_HANDLE FileHandle;\r
335 VOID *DepexData;\r
336 UINT32 AuthenticationStatus;\r
337 EFI_STATUS Status;\r
b0d803fe 338 \r
288f9b38
LG
339 FileHandle = NULL;\r
340 DepexData = NULL;\r
341 Status = EFI_SUCCESS;\r
342 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
b0d803fe 343\r
177aabe6 344 if (PrivateData->FvCount >= FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {\r
b0d803fe 345 ASSERT (FALSE);\r
346 }\r
347\r
348 Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *)Ppi;\r
349\r
288f9b38
LG
350 if (CompareGuid (&Fv->FvFormat, &gEfiFirmwareFileSystem2Guid)) {\r
351 for (FvCount = 0; FvCount < PrivateData->FvCount; FvCount ++) {\r
352 if ((UINTN)PrivateData->Fv[FvCount].FvHeader == (UINTN)Fv->FvInfo) {\r
353 return EFI_SUCCESS;\r
354 }\r
355 }\r
b0d803fe 356 PrivateData->Fv[PrivateData->FvCount++].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Fv->FvInfo;\r
b0d803fe 357\r
288f9b38
LG
358 //\r
359 // Only add FileSystem2 Fv to the All list\r
360 //\r
361 PrivateData->AllFv[PrivateData->AllFvCount++] = (EFI_PEI_FV_HANDLE)Fv->FvInfo;\r
362 \r
91136124 363 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
364 //\r
365 // Preprocess all FV type files in this new FileSystem2 Fv image\r
366 //\r
367 do {\r
368 Status = PeiFindFileEx (\r
369 (EFI_PEI_FV_HANDLE)Fv->FvInfo, \r
370 NULL, \r
371 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, \r
372 &FileHandle, \r
373 NULL\r
374 );\r
375 if (!EFI_ERROR (Status)) {\r
376 Status = PeiFfsFindSectionData (\r
377 (CONST EFI_PEI_SERVICES **) PeiServices,\r
378 EFI_SECTION_PEI_DEPEX,\r
379 FileHandle, \r
380 (VOID **)&DepexData\r
381 );\r
382 if (!EFI_ERROR (Status)) {\r
383 if (!PeimDispatchReadiness (PeiServices, DepexData)) {\r
384 //\r
385 // Dependency is not satisfied.\r
386 //\r
387 continue;\r
388 }\r
389 }\r
390 //\r
391 // Process FvFile to install FvInfo ppi and build FvHob\r
392 // \r
393 ProcessFvFile (PeiServices, FileHandle, &AuthenticationStatus);\r
394 }\r
395 } while (FileHandle != NULL);\r
396 }\r
b0d803fe 397\r
398 return EFI_SUCCESS;\r
399}\r
400\r
b1f6a7c6 401/**\r
402\r
403 Go through the file to search SectionType section,\r
404 when meeting an encapsuled section.\r
405\r
406\r
407 @param PeiServices - General purpose services available to every PEIM.\r
408 SearchType - Filter to find only section of this type.\r
409 @param SectionType EDES_TODO: Add parameter description\r
410 @param Section - From where to search.\r
411 @param SectionSize - The file size to search.\r
412 @param OutputBuffer - Pointer to the section to search.\r
413\r
414 @return EFI_STATUS\r
415\r
416**/\r
b0d803fe 417EFI_STATUS\r
418PeiFfsProcessSection (\r
419 IN CONST EFI_PEI_SERVICES **PeiServices,\r
420 IN EFI_SECTION_TYPE SectionType,\r
421 IN EFI_COMMON_SECTION_HEADER *Section,\r
422 IN UINTN SectionSize,\r
288f9b38 423 OUT VOID **OutputBuffer\r
b0d803fe 424 )\r
b0d803fe 425{\r
426 EFI_STATUS Status;\r
427 UINT32 SectionLength;\r
428 UINT32 ParsedLength;\r
b0d803fe 429 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *GuidSectionPpi;\r
b0d803fe 430 EFI_PEI_DECOMPRESS_PPI *DecompressPpi;\r
431 VOID *PpiOutput;\r
432 UINTN PpiOutputSize;\r
288f9b38
LG
433 UINTN Index;\r
434 UINT32 Authentication;\r
435 PEI_CORE_INSTANCE *PrivateData;\r
b0d803fe 436\r
288f9b38 437 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
b0d803fe 438 *OutputBuffer = NULL;\r
288f9b38
LG
439 ParsedLength = 0;\r
440 Index = 0;\r
441 Status = EFI_NOT_FOUND;\r
442 PpiOutput = NULL;\r
443 PpiOutputSize = 0;\r
b0d803fe 444 while (ParsedLength < SectionSize) {\r
445 if (Section->Type == SectionType) {\r
446 *OutputBuffer = (VOID *)(Section + 1);\r
447 return EFI_SUCCESS;\r
288f9b38
LG
448 } else if ((Section->Type == EFI_SECTION_GUID_DEFINED) || (Section->Type == EFI_SECTION_COMPRESSION)) {\r
449 //\r
450 // Check the encapsulated section is extracted into the cache data.\r
451 //\r
452 for (Index = 0; Index < PrivateData->CacheSection.AllSectionCount; Index ++) {\r
453 if (Section == PrivateData->CacheSection.Section[Index]) {\r
454 PpiOutput = PrivateData->CacheSection.SectionData[Index];\r
455 PpiOutputSize = PrivateData->CacheSection.SectionSize[Index];\r
456 //\r
457 // Search section directly from the cache data.\r
458 //\r
b0d803fe 459 return PeiFfsProcessSection (\r
460 PeiServices,\r
461 SectionType, \r
462 PpiOutput, \r
463 PpiOutputSize, \r
288f9b38 464 OutputBuffer \r
b0d803fe 465 );\r
466 }\r
467 }\r
288f9b38
LG
468 \r
469 Status = EFI_NOT_FOUND;\r
470 if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
471 Status = PeiServicesLocatePpi (\r
472 &((EFI_GUID_DEFINED_SECTION *)Section)->SectionDefinitionGuid, \r
473 0, \r
474 NULL, \r
475 (VOID **) &GuidSectionPpi\r
476 );\r
b0d803fe 477 if (!EFI_ERROR (Status)) {\r
288f9b38
LG
478 Status = GuidSectionPpi->ExtractSection (\r
479 GuidSectionPpi,\r
480 Section,\r
481 &PpiOutput,\r
482 &PpiOutputSize,\r
483 &Authentication\r
484 );\r
485 }\r
486 } else if (Section->Type == EFI_SECTION_COMPRESSION) {\r
487 Status = PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid, 0, NULL, (VOID **) &DecompressPpi);\r
488 if (!EFI_ERROR (Status)) {\r
489 Status = DecompressPpi->Decompress (\r
490 DecompressPpi,\r
491 (CONST EFI_COMPRESSION_SECTION*) Section,\r
492 &PpiOutput,\r
493 &PpiOutputSize\r
494 );\r
b0d803fe 495 }\r
496 }\r
288f9b38
LG
497 \r
498 if (!EFI_ERROR (Status)) {\r
499 //\r
500 // Update cache section data.\r
501 //\r
502 if (PrivateData->CacheSection.AllSectionCount < CACHE_SETION_MAX_NUMBER) {\r
503 PrivateData->CacheSection.AllSectionCount ++;\r
504 }\r
505 PrivateData->CacheSection.Section [PrivateData->CacheSection.SectionIndex] = Section;\r
506 PrivateData->CacheSection.SectionData [PrivateData->CacheSection.SectionIndex] = PpiOutput;\r
507 PrivateData->CacheSection.SectionSize [PrivateData->CacheSection.SectionIndex] = PpiOutputSize;\r
508 PrivateData->CacheSection.SectionIndex = (PrivateData->CacheSection.SectionIndex + 1)%CACHE_SETION_MAX_NUMBER;\r
509 \r
510 return PeiFfsProcessSection (\r
511 PeiServices,\r
512 SectionType, \r
513 PpiOutput, \r
514 PpiOutputSize, \r
515 OutputBuffer \r
516 );\r
517 }\r
b0d803fe 518 }\r
519\r
520 //\r
521 // Size is 24 bits wide so mask upper 8 bits. \r
522 // SectionLength is adjusted it is 4 byte aligned.\r
523 // Go to the next section\r
524 //\r
525 SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;\r
526 SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
527 ASSERT (SectionLength != 0);\r
528 ParsedLength += SectionLength;\r
529 Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);\r
530 }\r
531 \r
532 return EFI_NOT_FOUND;\r
533}\r
534\r
192f6d4c 535\r
b1f6a7c6 536/**\r
537 Given the input file pointer, search for the next matching section in the\r
538 FFS volume.\r
539\r
540\r
541 @param PeiServices Pointer to the PEI Core Services Table.\r
542 @param SectionType Filter to find only sections of this type.\r
543 @param FileHandle Pointer to the current file to search.\r
544 @param SectionData Pointer to the Section matching SectionType in FfsFileHeader.\r
545 NULL if section not found\r
546\r
547 @retval EFI_NOT_FOUND No files matching the search criteria were found\r
548 @retval EFI_SUCCESS Success to find section data in given file\r
549\r
550**/\r
192f6d4c 551EFI_STATUS\r
552EFIAPI\r
553PeiFfsFindSectionData (\r
0c2b5da8 554 IN CONST EFI_PEI_SERVICES **PeiServices,\r
192f6d4c 555 IN EFI_SECTION_TYPE SectionType,\r
0c2b5da8 556 IN EFI_PEI_FILE_HANDLE FileHandle,\r
192f6d4c 557 IN OUT VOID **SectionData\r
558 )\r
192f6d4c 559{\r
b0d803fe 560 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
561 UINT32 FileSize;\r
562 EFI_COMMON_SECTION_HEADER *Section;\r
b0d803fe 563\r
564 FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);\r
192f6d4c 565\r
566 //\r
567 // Size is 24 bits wide so mask upper 8 bits. \r
b0d803fe 568 // Does not include FfsFileHeader header size\r
192f6d4c 569 // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.\r
570 //\r
571 Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1);\r
572 FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
b0d803fe 573 FileSize -= sizeof (EFI_FFS_FILE_HEADER);\r
574\r
575 return PeiFfsProcessSection (\r
288f9b38 576 PeiServices,\r
b0d803fe 577 SectionType, \r
578 Section, \r
579 FileSize, \r
288f9b38 580 SectionData\r
b0d803fe 581 );\r
192f6d4c 582}\r
583\r
b1f6a7c6 584/**\r
585 Given the input file pointer, search for the next matching file in the\r
586 FFS volume as defined by SearchType. The search starts from FileHeader inside\r
587 the Firmware Volume defined by FwVolHeader.\r
192f6d4c 588\r
b1f6a7c6 589\r
590 @param PeiServices Pointer to the PEI Core Services Table.\r
591 @param SearchType Filter to find only files of this type.\r
592 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.\r
593 @param VolumeHandle Pointer to the FV header of the volume to search.\r
594 @param FileHandle Pointer to the current file from which to begin searching.\r
595 This pointer will be updated upon return to reflect the file found.\r
596 @retval EFI_NOT_FOUND No files matching the search criteria were found\r
597 @retval EFI_SUCCESS Success to find next file in given volume\r
598\r
599**/\r
192f6d4c 600EFI_STATUS\r
601EFIAPI\r
602PeiFfsFindNextFile (\r
0c2b5da8 603 IN CONST EFI_PEI_SERVICES **PeiServices,\r
604 IN UINT8 SearchType,\r
605 IN EFI_PEI_FV_HANDLE VolumeHandle,\r
606 IN OUT EFI_PEI_FILE_HANDLE *FileHandle\r
192f6d4c 607 )\r
192f6d4c 608{\r
b0d803fe 609 return PeiFindFileEx (VolumeHandle, NULL, SearchType, FileHandle, NULL);\r
192f6d4c 610}\r
611\r
b0d803fe 612\r
b1f6a7c6 613/**\r
614 search the firmware volumes by index\r
615\r
616 @param PeiServices The PEI core services table.\r
617 @param Instance Instance of FV to find\r
618 @param VolumeHandle Pointer to found Volume.\r
619\r
620 @retval EFI_INVALID_PARAMETER FwVolHeader is NULL\r
621 @retval EFI_SUCCESS Firmware volume instance successfully found.\r
622\r
623**/\r
192f6d4c 624EFI_STATUS \r
625EFIAPI\r
626PeiFvFindNextVolume (\r
0c2b5da8 627 IN CONST EFI_PEI_SERVICES **PeiServices,\r
192f6d4c 628 IN UINTN Instance,\r
0c2b5da8 629 IN OUT EFI_PEI_FV_HANDLE *VolumeHandle\r
192f6d4c 630 )\r
192f6d4c 631{\r
b0d803fe 632 PEI_CORE_INSTANCE *Private;\r
192f6d4c 633\r
b0d803fe 634 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
635 if (VolumeHandle == NULL) {\r
636 return EFI_INVALID_PARAMETER;\r
637 } \r
192f6d4c 638\r
b0d803fe 639 if (Instance >= Private->AllFvCount) {\r
640 VolumeHandle = NULL;\r
641 return EFI_NOT_FOUND;\r
642 }\r
192f6d4c 643\r
b0d803fe 644 *VolumeHandle = Private->AllFv[Instance];\r
645 return EFI_SUCCESS;\r
646}\r
192f6d4c 647\r
192f6d4c 648\r
b1f6a7c6 649/**\r
650\r
651 Given the input VolumeHandle, search for the next matching name file.\r
652\r
653\r
654 @param FileName - File name to search.\r
655 @param VolumeHandle - The current FV to search.\r
656 @param FileHandle - Pointer to the file matching name in VolumeHandle.\r
657 - NULL if file not found\r
658\r
659 @return EFI_STATUS\r
660\r
661**/\r
b0d803fe 662EFI_STATUS\r
663EFIAPI \r
664PeiFfsFindFileByName (\r
665 IN CONST EFI_GUID *FileName,\r
666 IN EFI_PEI_FV_HANDLE VolumeHandle,\r
667 OUT EFI_PEI_FILE_HANDLE *FileHandle\r
668 )\r
b0d803fe 669{\r
670 EFI_STATUS Status;\r
671 if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {\r
192f6d4c 672 return EFI_INVALID_PARAMETER;\r
673 }\r
b0d803fe 674 Status = PeiFindFileEx (VolumeHandle, FileName, 0, FileHandle, NULL);\r
675 if (Status == EFI_NOT_FOUND) {\r
676 *FileHandle = NULL;\r
677 }\r
678 return Status;\r
679}\r
680\r
b1f6a7c6 681/**\r
682\r
683 Returns information about a specific file.\r
684\r
685\r
686 @param FileHandle - The handle to file.\r
687 @param FileInfo - Pointer to the file information.\r
688\r
689 @retval EFI_INVALID_PARAMETER Invalid FileHandle or FileInfo.\r
690 @retval EFI_SUCCESS Success to collect file info.\r
691\r
692**/\r
b0d803fe 693EFI_STATUS\r
694EFIAPI \r
695PeiFfsGetFileInfo (\r
696 IN EFI_PEI_FILE_HANDLE FileHandle,\r
697 OUT EFI_FV_FILE_INFO *FileInfo\r
698 )\r
b0d803fe 699{\r
700 UINT8 FileState;\r
701 UINT8 ErasePolarity;\r
702 EFI_FFS_FILE_HEADER *FileHeader;\r
703 EFI_PEI_FV_HANDLE VolumeHandle;\r
704\r
705 if ((FileHandle == NULL) || (FileInfo == NULL)) {\r
706 return EFI_INVALID_PARAMETER;\r
707 }\r
708\r
173b35e4 709 VolumeHandle = 0;\r
b0d803fe 710 //\r
711 // Retrieve the FirmwareVolume which the file resides in.\r
712 //\r
713 if (!PeiFileHandleToVolume(FileHandle, &VolumeHandle)) {\r
714 return EFI_INVALID_PARAMETER;\r
715 }\r
716\r
797a9d67 717 if (((EFI_FIRMWARE_VOLUME_HEADER*)VolumeHandle)->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
b0d803fe 718 ErasePolarity = 1;\r
192f6d4c 719 } else {\r
b0d803fe 720 ErasePolarity = 0;\r
721 }\r
722\r
723 //\r
724 // Get FileState which is the highest bit of the State \r
725 //\r
726 FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle);\r
192f6d4c 727\r
b0d803fe 728 switch (FileState) {\r
729 case EFI_FILE_DATA_VALID:\r
730 case EFI_FILE_MARKED_FOR_UPDATE:\r
731 break; \r
732 default:\r
733 return EFI_INVALID_PARAMETER;\r
192f6d4c 734 }\r
b0d803fe 735\r
736 FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;\r
737 CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID));\r
738 FileInfo->FileType = FileHeader->Type;\r
739 FileInfo->FileAttributes = FileHeader->Attributes;\r
740 FileInfo->BufferSize = ((*(UINT32 *)FileHeader->Size) & 0x00FFFFFF) - sizeof (EFI_FFS_FILE_HEADER);\r
741 FileInfo->Buffer = (FileHeader + 1);\r
742 return EFI_SUCCESS;\r
743}\r
744\r
745\r
b1f6a7c6 746/**\r
747\r
748 Collect information of given Fv Volume.\r
749\r
750 @param VolumeHandle - The handle to Fv Volume.\r
751 @param VolumeInfo - The pointer to volume information.\r
752\r
753 @retval EFI_INVALID_PARAMETER VolumeInfo is NULL\r
754 @retval EFI_SUCCESS Success to collect fv info.\r
755**/\r
b0d803fe 756EFI_STATUS\r
757EFIAPI \r
758PeiFfsGetVolumeInfo (\r
759 IN EFI_PEI_FV_HANDLE VolumeHandle,\r
760 OUT EFI_FV_INFO *VolumeInfo\r
761 )\r
b0d803fe 762{\r
288f9b38 763 EFI_FIRMWARE_VOLUME_HEADER FwVolHeader;\r
b0d803fe 764 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;\r
765\r
766 if (VolumeInfo == NULL) {\r
767 return EFI_INVALID_PARAMETER;\r
192f6d4c 768 }\r
288f9b38
LG
769 \r
770 //\r
771 // VolumeHandle may not align at 8 byte, \r
772 // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte. \r
773 // So, Copy FvHeader into the local FvHeader structure.\r
774 //\r
775 CopyMem (&FwVolHeader, VolumeHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
776 //\r
777 // Check Fv Image Signature\r
778 //\r
779 if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {\r
780 return EFI_INVALID_PARAMETER;\r
781 }\r
782 VolumeInfo->FvAttributes = FwVolHeader.Attributes;\r
783 VolumeInfo->FvStart = (VOID *) VolumeHandle;\r
784 VolumeInfo->FvSize = FwVolHeader.FvLength;\r
785 CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID));\r
b0d803fe 786\r
288f9b38
LG
787 if (FwVolHeader.ExtHeaderOffset != 0) {\r
788 FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)VolumeHandle) + FwVolHeader.ExtHeaderOffset);\r
b0d803fe 789 CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID));\r
790 }\r
791 return EFI_SUCCESS;\r
192f6d4c 792}\r
b0d803fe 793\r