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