]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Library/PrePiLib/FwVol.c
EmbeddedPkg: Fix various typos
[mirror_edk2.git] / EmbeddedPkg / Library / PrePiLib / FwVol.c
CommitLineData
1e57a462 1/** @file\r
2 Implementation of the 6 PEI Ffs (FV) APIs in library form.\r
3402aac7 3\r
1e57a462 4 This code only knows about a FV if it has a EFI_HOB_TYPE_FV entry in the HOB list\r
5\r
6 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
3402aac7 7\r
878b807a 8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
1e57a462 9\r
10**/\r
11\r
12#include <PrePi.h>\r
13#include <Library/ExtractGuidedSectionLib.h>\r
14\r
15\r
16#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \\r
17 (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))\r
18\r
19\r
20/**\r
21 Returns the highest bit set of the State field\r
3402aac7 22\r
1e57a462 23 @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY\r
24 in the Attributes field.\r
25 @param FfsHeader Pointer to FFS File Header\r
3402aac7 26\r
1e57a462 27\r
28 @retval the highest bit in the State field\r
29\r
30**/\r
31STATIC\r
32EFI_FFS_FILE_STATE\r
33GetFileState(\r
34 IN UINT8 ErasePolarity,\r
35 IN EFI_FFS_FILE_HEADER *FfsHeader\r
36 )\r
37{\r
38 EFI_FFS_FILE_STATE FileState;\r
39 EFI_FFS_FILE_STATE HighestBit;\r
40\r
41 FileState = FfsHeader->State;\r
42\r
43 if (ErasePolarity != 0) {\r
44 FileState = (EFI_FFS_FILE_STATE)~FileState;\r
45 }\r
46\r
47 HighestBit = 0x80;\r
48 while (HighestBit != 0 && (HighestBit & FileState) == 0) {\r
49 HighestBit >>= 1;\r
50 }\r
51\r
52 return HighestBit;\r
3402aac7 53}\r
1e57a462 54\r
55\r
56/**\r
57 Calculates the checksum of the header of a file.\r
58 The header is a zero byte checksum, so zero means header is good\r
3402aac7 59\r
1e57a462 60 @param FfsHeader Pointer to FFS File Header\r
3402aac7 61\r
1e57a462 62 @retval Checksum of the header\r
63\r
64**/\r
65STATIC\r
66UINT8\r
67CalculateHeaderChecksum (\r
68 IN EFI_FFS_FILE_HEADER *FileHeader\r
69 )\r
70{\r
71 UINT8 *Ptr;\r
72 UINTN Index;\r
73 UINT8 Sum;\r
3402aac7 74\r
1e57a462 75 Sum = 0;\r
76 Ptr = (UINT8 *)FileHeader;\r
77\r
78 for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER) - 3; Index += 4) {\r
79 Sum = (UINT8)(Sum + Ptr[Index]);\r
80 Sum = (UINT8)(Sum + Ptr[Index+1]);\r
81 Sum = (UINT8)(Sum + Ptr[Index+2]);\r
82 Sum = (UINT8)(Sum + Ptr[Index+3]);\r
83 }\r
84\r
85 for (; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) {\r
86 Sum = (UINT8)(Sum + Ptr[Index]);\r
87 }\r
3402aac7 88\r
1e57a462 89 //\r
3402aac7 90 // State field (since this indicates the different state of file).\r
1e57a462 91 //\r
92 Sum = (UINT8)(Sum - FileHeader->State);\r
93 //\r
94 // Checksum field of the file is not part of the header checksum.\r
95 //\r
96 Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File);\r
97\r
98 return Sum;\r
99}\r
100\r
101\r
102/**\r
103 Given a FileHandle return the VolumeHandle\r
3402aac7 104\r
1e57a462 105 @param FileHandle File handle to look up\r
106 @param VolumeHandle Match for FileHandle\r
3402aac7 107\r
1e57a462 108 @retval TRUE VolumeHandle is valid\r
109\r
110**/\r
111STATIC\r
112BOOLEAN\r
113EFIAPI\r
114FileHandleToVolume (\r
115 IN EFI_PEI_FILE_HANDLE FileHandle,\r
116 OUT EFI_PEI_FV_HANDLE *VolumeHandle\r
117 )\r
118{\r
119 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
120 EFI_PEI_HOB_POINTERS Hob;\r
121\r
122 Hob.Raw = GetHobList ();\r
123 if (Hob.Raw == NULL) {\r
124 return FALSE;\r
125 }\r
3402aac7 126\r
1e57a462 127 do {\r
128 Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw);\r
129 if (Hob.Raw != NULL) {\r
130 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(Hob.FirmwareVolume->BaseAddress);\r
131 if (((UINT64) (UINTN) FileHandle > (UINT64) (UINTN) FwVolHeader ) && \\r
132 ((UINT64) (UINTN) FileHandle <= ((UINT64) (UINTN) FwVolHeader + FwVolHeader->FvLength - 1))) {\r
133 *VolumeHandle = (EFI_PEI_FV_HANDLE)FwVolHeader;\r
134 return TRUE;\r
135 }\r
136\r
137 Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, GET_NEXT_HOB (Hob));\r
138 }\r
139 } while (Hob.Raw != NULL);\r
3402aac7 140\r
1e57a462 141 return FALSE;\r
142}\r
143\r
144\r
145\r
146/**\r
147 Given the input file pointer, search for the next matching file in the\r
148 FFS volume as defined by SearchType. The search starts from FileHeader inside\r
149 the Firmware Volume defined by FwVolHeader.\r
3402aac7 150\r
1e57a462 151 @param FileHandle File handle to look up\r
152 @param VolumeHandle Match for FileHandle\r
3402aac7 153\r
1e57a462 154\r
155**/\r
156EFI_STATUS\r
157FindFileEx (\r
158 IN CONST EFI_PEI_FV_HANDLE FvHandle,\r
159 IN CONST EFI_GUID *FileName, OPTIONAL\r
160 IN EFI_FV_FILETYPE SearchType,\r
161 IN OUT EFI_PEI_FILE_HANDLE *FileHandle\r
162 )\r
163{\r
164 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
165 EFI_FFS_FILE_HEADER **FileHeader;\r
166 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
167 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;\r
168 UINT32 FileLength;\r
169 UINT32 FileOccupiedSize;\r
170 UINT32 FileOffset;\r
171 UINT64 FvLength;\r
172 UINT8 ErasePolarity;\r
173 UINT8 FileState;\r
174\r
175 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvHandle;\r
176 FileHeader = (EFI_FFS_FILE_HEADER **)FileHandle;\r
177\r
178 FvLength = FwVolHeader->FvLength;\r
179 if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
180 ErasePolarity = 1;\r
181 } else {\r
182 ErasePolarity = 0;\r
183 }\r
184\r
185 //\r
186 // If FileHeader is not specified (NULL) or FileName is not NULL,\r
187 // start with the first file in the firmware volume. Otherwise,\r
188 // start from the FileHeader.\r
189 //\r
190 if ((*FileHeader == NULL) || (FileName != NULL)) {\r
191 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);\r
192 if (FwVolHeader->ExtHeaderOffset != 0) {\r
193 FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(((UINT8 *)FwVolHeader) + FwVolHeader->ExtHeaderOffset);\r
194 FfsFileHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FwVolExHeaderInfo) + FwVolExHeaderInfo->ExtHeaderSize);\r
195 }\r
196 } else {\r
197 //\r
198 // Length is 24 bits wide so mask upper 8 bits\r
199 // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.\r
200 //\r
201 FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF;\r
202 FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);\r
203 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize);\r
204 }\r
3402aac7 205\r
5a44a766
OM
206 // FFS files begin with a header that is aligned on an 8-byte boundary\r
207 FfsFileHeader = ALIGN_POINTER (FfsFileHeader, 8);\r
208\r
1e57a462 209 FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader);\r
210 ASSERT (FileOffset <= 0xFFFFFFFF);\r
211\r
212 while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {\r
213 //\r
3402aac7 214 // Get FileState which is the highest bit of the State\r
1e57a462 215 //\r
216 FileState = GetFileState (ErasePolarity, FfsFileHeader);\r
217\r
218 switch (FileState) {\r
219\r
220 case EFI_FILE_HEADER_INVALID:\r
221 FileOffset += sizeof(EFI_FFS_FILE_HEADER);\r
222 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER));\r
223 break;\r
3402aac7 224\r
1e57a462 225 case EFI_FILE_DATA_VALID:\r
226 case EFI_FILE_MARKED_FOR_UPDATE:\r
227 if (CalculateHeaderChecksum (FfsFileHeader) != 0) {\r
228 ASSERT (FALSE);\r
229 *FileHeader = NULL;\r
230 return EFI_NOT_FOUND;\r
231 }\r
232\r
233 FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
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
3402aac7
RC
241 } else if (((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) &&\r
242 (FfsFileHeader->Type != EFI_FV_FILETYPE_FFS_PAD)) {\r
1e57a462 243 *FileHeader = FfsFileHeader;\r
244 return EFI_SUCCESS;\r
245 }\r
246\r
3402aac7 247 FileOffset += FileOccupiedSize;\r
1e57a462 248 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);\r
249 break;\r
3402aac7 250\r
1e57a462 251 case EFI_FILE_DELETED:\r
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
256 break;\r
257\r
258 default:\r
259 *FileHeader = NULL;\r
260 return EFI_NOT_FOUND;\r
3402aac7 261 }\r
1e57a462 262 }\r
263\r
3402aac7 264\r
1e57a462 265 *FileHeader = NULL;\r
3402aac7 266 return EFI_NOT_FOUND;\r
1e57a462 267}\r
268\r
269\r
270/**\r
271 Go through the file to search SectionType section,\r
3402aac7
RC
272 when meeting an encapsuled section.\r
273\r
1e57a462 274 @param SectionType - Filter to find only section of this type.\r
275 @param Section - From where to search.\r
276 @param SectionSize - The file size to search.\r
277 @param OutputBuffer - Pointer to the section to search.\r
3402aac7 278\r
1e57a462 279 @retval EFI_SUCCESS\r
280**/\r
281EFI_STATUS\r
282FfsProcessSection (\r
283 IN EFI_SECTION_TYPE SectionType,\r
284 IN EFI_COMMON_SECTION_HEADER *Section,\r
285 IN UINTN SectionSize,\r
286 OUT VOID **OutputBuffer\r
287 )\r
288{\r
289 EFI_STATUS Status;\r
290 UINT32 SectionLength;\r
291 UINT32 ParsedLength;\r
292 EFI_COMPRESSION_SECTION *CompressionSection;\r
4efc8a40 293 EFI_COMPRESSION_SECTION2 *CompressionSection2;\r
c1cdcab9 294 UINT32 DstBufferSize;\r
1e57a462 295 VOID *ScratchBuffer;\r
296 UINT32 ScratchBufferSize;\r
297 VOID *DstBuffer;\r
298 UINT16 SectionAttribute;\r
299 UINT32 AuthenticationStatus;\r
4efc8a40
MZ
300 CHAR8 *CompressedData;\r
301 UINTN CompressedDataLength;\r
1e57a462 302\r
303\r
304 *OutputBuffer = NULL;\r
305 ParsedLength = 0;\r
306 Status = EFI_NOT_FOUND;\r
307 while (ParsedLength < SectionSize) {\r
4efc8a40
MZ
308 if (IS_SECTION2 (Section)) {\r
309 ASSERT (SECTION2_SIZE (Section) > 0x00FFFFFF);\r
310 }\r
311\r
1e57a462 312 if (Section->Type == SectionType) {\r
4efc8a40
MZ
313 if (IS_SECTION2 (Section)) {\r
314 *OutputBuffer = (VOID *)((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2));\r
315 } else {\r
316 *OutputBuffer = (VOID *)((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER));\r
317 }\r
1e57a462 318\r
319 return EFI_SUCCESS;\r
320 } else if ((Section->Type == EFI_SECTION_COMPRESSION) || (Section->Type == EFI_SECTION_GUID_DEFINED)) {\r
3402aac7 321\r
1e57a462 322 if (Section->Type == EFI_SECTION_COMPRESSION) {\r
4efc8a40
MZ
323 if (IS_SECTION2 (Section)) {\r
324 CompressionSection2 = (EFI_COMPRESSION_SECTION2 *) Section;\r
325 SectionLength = SECTION2_SIZE (Section);\r
326\r
327 if (CompressionSection2->CompressionType != EFI_STANDARD_COMPRESSION) {\r
328 return EFI_UNSUPPORTED;\r
329 }\r
330\r
331 CompressedData = (CHAR8 *) ((EFI_COMPRESSION_SECTION2 *) Section + 1);\r
332 CompressedDataLength = (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION2);\r
333 } else {\r
334 CompressionSection = (EFI_COMPRESSION_SECTION *) Section;\r
335 SectionLength = SECTION_SIZE (Section);\r
336\r
337 if (CompressionSection->CompressionType != EFI_STANDARD_COMPRESSION) {\r
338 return EFI_UNSUPPORTED;\r
339 }\r
340\r
341 CompressedData = (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1);\r
342 CompressedDataLength = (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION);\r
1e57a462 343 }\r
344\r
345 Status = UefiDecompressGetInfo (\r
4efc8a40
MZ
346 CompressedData,\r
347 CompressedDataLength,\r
c1cdcab9 348 &DstBufferSize,\r
1e57a462 349 &ScratchBufferSize\r
350 );\r
351 } else if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
352 Status = ExtractGuidedSectionGetInfo (\r
353 Section,\r
c1cdcab9 354 &DstBufferSize,\r
1e57a462 355 &ScratchBufferSize,\r
356 &SectionAttribute\r
357 );\r
358 }\r
3402aac7 359\r
1e57a462 360 if (EFI_ERROR (Status)) {\r
361 //\r
362 // GetInfo failed\r
363 //\r
364 DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
365 return EFI_NOT_FOUND;\r
366 }\r
367 //\r
368 // Allocate scratch buffer\r
369 //\r
370 ScratchBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
371 if (ScratchBuffer == NULL) {\r
372 return EFI_OUT_OF_RESOURCES;\r
373 }\r
374 //\r
3402aac7 375 // Allocate destination buffer, extra one page for adjustment\r
1e57a462 376 //\r
377 DstBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
378 if (DstBuffer == NULL) {\r
379 return EFI_OUT_OF_RESOURCES;\r
380 }\r
381 //\r
382 // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header\r
383 // to make section data at page alignment.\r
384 //\r
4efc8a40
MZ
385 if (IS_SECTION2 (Section))\r
386 DstBuffer = (UINT8 *)DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER2);\r
387 else\r
388 DstBuffer = (UINT8 *)DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
1e57a462 389 //\r
390 // Call decompress function\r
391 //\r
392 if (Section->Type == EFI_SECTION_COMPRESSION) {\r
4efc8a40
MZ
393 if (IS_SECTION2 (Section)) {\r
394 CompressedData = (CHAR8 *) ((EFI_COMPRESSION_SECTION2 *) Section + 1);\r
395 }\r
396 else {\r
397 CompressedData = (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1);\r
398 }\r
399\r
1e57a462 400 Status = UefiDecompress (\r
4efc8a40 401 CompressedData,\r
1e57a462 402 DstBuffer,\r
403 ScratchBuffer\r
404 );\r
405 } else if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
406 Status = ExtractGuidedSectionDecode (\r
407 Section,\r
408 &DstBuffer,\r
409 ScratchBuffer,\r
410 &AuthenticationStatus\r
411 );\r
412 }\r
3402aac7 413\r
1e57a462 414 if (EFI_ERROR (Status)) {\r
415 //\r
416 // Decompress failed\r
417 //\r
418 DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status));\r
419 return EFI_NOT_FOUND;\r
420 } else {\r
421 return FfsProcessSection (\r
3402aac7
RC
422 SectionType,\r
423 DstBuffer,\r
424 DstBufferSize,\r
425 OutputBuffer\r
1e57a462 426 );\r
3402aac7 427 }\r
1e57a462 428 }\r
429\r
4efc8a40
MZ
430 if (IS_SECTION2 (Section)) {\r
431 SectionLength = SECTION2_SIZE (Section);\r
432 } else {\r
433 SectionLength = SECTION_SIZE (Section);\r
434 }\r
1e57a462 435 //\r
1e57a462 436 // SectionLength is adjusted it is 4 byte aligned.\r
437 // Go to the next section\r
438 //\r
1e57a462 439 SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
440 ASSERT (SectionLength != 0);\r
441 ParsedLength += SectionLength;\r
442 Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);\r
443 }\r
3402aac7 444\r
1e57a462 445 return EFI_NOT_FOUND;\r
446}\r
447\r
448\r
449\r
450/**\r
451 This service enables discovery sections of a given type within a valid FFS file.\r
452\r
453 @param SearchType The value of the section type to find.\r
454 @param FfsFileHeader A pointer to the file header that contains the set of sections to\r
455 be searched.\r
456 @param SectionData A pointer to the discovered section, if successful.\r
457\r
458 @retval EFI_SUCCESS The section was found.\r
459 @retval EFI_NOT_FOUND The section was not found.\r
460\r
461**/\r
462EFI_STATUS\r
463EFIAPI\r
464FfsFindSectionData (\r
465 IN EFI_SECTION_TYPE SectionType,\r
466 IN EFI_PEI_FILE_HANDLE FileHandle,\r
467 OUT VOID **SectionData\r
468 )\r
469{\r
470 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
471 UINT32 FileSize;\r
472 EFI_COMMON_SECTION_HEADER *Section;\r
473\r
474 FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);\r
475\r
476 //\r
3402aac7 477 // Size is 24 bits wide so mask upper 8 bits.\r
1e57a462 478 // Does not include FfsFileHeader header size\r
479 // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.\r
480 //\r
481 Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1);\r
482 FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
483 FileSize -= sizeof (EFI_FFS_FILE_HEADER);\r
484\r
485 return FfsProcessSection (\r
3402aac7
RC
486 SectionType,\r
487 Section,\r
488 FileSize,\r
1e57a462 489 SectionData\r
490 );\r
491}\r
492\r
493\r
494\r
495\r
496\r
497\r
498/**\r
499 This service enables discovery of additional firmware files.\r
500\r
501 @param SearchType A filter to find files only of this type.\r
502 @param FwVolHeader Pointer to the firmware volume header of the volume to search.\r
503 This parameter must point to a valid FFS volume.\r
504 @param FileHeader Pointer to the current file from which to begin searching.\r
505\r
506 @retval EFI_SUCCESS The file was found.\r
507 @retval EFI_NOT_FOUND The file was not found.\r
508 @retval EFI_NOT_FOUND The header checksum was not zero.\r
509\r
510**/\r
511EFI_STATUS\r
512EFIAPI\r
513FfsFindNextFile (\r
514 IN UINT8 SearchType,\r
515 IN EFI_PEI_FV_HANDLE VolumeHandle,\r
516 IN OUT EFI_PEI_FILE_HANDLE *FileHandle\r
517 )\r
518{\r
519 return FindFileEx (VolumeHandle, NULL, SearchType, FileHandle);\r
520}\r
521\r
522\r
523/**\r
524 This service enables discovery of additional firmware volumes.\r
525\r
526 @param Instance This instance of the firmware volume to find. The value 0 is the\r
527 Boot Firmware Volume (BFV).\r
528 @param FwVolHeader Pointer to the firmware volume header of the volume to return.\r
529\r
530 @retval EFI_SUCCESS The volume was found.\r
531 @retval EFI_NOT_FOUND The volume was not found.\r
532\r
533**/\r
534EFI_STATUS\r
535EFIAPI\r
536FfsFindNextVolume (\r
537 IN UINTN Instance,\r
538 IN OUT EFI_PEI_FV_HANDLE *VolumeHandle\r
539 )\r
540{\r
541 EFI_PEI_HOB_POINTERS Hob;\r
3402aac7 542\r
1e57a462 543\r
544 Hob.Raw = GetHobList ();\r
545 if (Hob.Raw == NULL) {\r
546 return EFI_NOT_FOUND;\r
547 }\r
3402aac7 548\r
1e57a462 549 do {\r
550 Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw);\r
551 if (Hob.Raw != NULL) {\r
552 if (Instance-- == 0) {\r
553 *VolumeHandle = (EFI_PEI_FV_HANDLE)(UINTN)(Hob.FirmwareVolume->BaseAddress);\r
554 return EFI_SUCCESS;\r
555 }\r
556\r
557 Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, GET_NEXT_HOB (Hob));\r
558 }\r
559 } while (Hob.Raw != NULL);\r
3402aac7 560\r
1e57a462 561 return EFI_NOT_FOUND;\r
562\r
563}\r
564\r
565\r
566/**\r
567 Find a file in the volume by name\r
3402aac7 568\r
1e57a462 569 @param FileName A pointer to the name of the file to\r
570 find within the firmware volume.\r
571\r
572 @param VolumeHandle The firmware volume to search FileHandle\r
573 Upon exit, points to the found file's\r
574 handle or NULL if it could not be found.\r
575\r
576 @retval EFI_SUCCESS File was found.\r
577\r
578 @retval EFI_NOT_FOUND File was not found.\r
579\r
580 @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or\r
581 FileName was NULL.\r
582\r
583**/\r
584EFI_STATUS\r
3402aac7 585EFIAPI\r
1e57a462 586FfsFindFileByName (\r
587 IN CONST EFI_GUID *FileName,\r
588 IN EFI_PEI_FV_HANDLE VolumeHandle,\r
589 OUT EFI_PEI_FILE_HANDLE *FileHandle\r
590 )\r
591{\r
592 EFI_STATUS Status;\r
593 if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {\r
594 return EFI_INVALID_PARAMETER;\r
595 }\r
596 Status = FindFileEx (VolumeHandle, FileName, 0, FileHandle);\r
597 if (Status == EFI_NOT_FOUND) {\r
598 *FileHandle = NULL;\r
599 }\r
600 return Status;\r
601}\r
602\r
603\r
604\r
605\r
606/**\r
607 Get information about the file by name.\r
608\r
609 @param FileHandle Handle of the file.\r
610\r
611 @param FileInfo Upon exit, points to the file's\r
612 information.\r
613\r
614 @retval EFI_SUCCESS File information returned.\r
3402aac7 615\r
1e57a462 616 @retval EFI_INVALID_PARAMETER If FileHandle does not\r
617 represent a valid file.\r
3402aac7 618\r
1e57a462 619 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.\r
3402aac7 620\r
1e57a462 621**/\r
622EFI_STATUS\r
3402aac7 623EFIAPI\r
1e57a462 624FfsGetFileInfo (\r
625 IN EFI_PEI_FILE_HANDLE FileHandle,\r
626 OUT EFI_FV_FILE_INFO *FileInfo\r
627 )\r
628{\r
629 UINT8 FileState;\r
630 UINT8 ErasePolarity;\r
631 EFI_FFS_FILE_HEADER *FileHeader;\r
632 EFI_PEI_FV_HANDLE VolumeHandle;\r
633\r
634 if ((FileHandle == NULL) || (FileInfo == NULL)) {\r
635 return EFI_INVALID_PARAMETER;\r
636 }\r
637\r
638 VolumeHandle = 0;\r
639 //\r
640 // Retrieve the FirmwareVolume which the file resides in.\r
641 //\r
642 if (!FileHandleToVolume(FileHandle, &VolumeHandle)) {\r
643 return EFI_INVALID_PARAMETER;\r
644 }\r
645\r
646 if (((EFI_FIRMWARE_VOLUME_HEADER*)VolumeHandle)->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
647 ErasePolarity = 1;\r
648 } else {\r
649 ErasePolarity = 0;\r
650 }\r
651\r
652 //\r
3402aac7 653 // Get FileState which is the highest bit of the State\r
1e57a462 654 //\r
655 FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle);\r
656\r
657 switch (FileState) {\r
658 case EFI_FILE_DATA_VALID:\r
659 case EFI_FILE_MARKED_FOR_UPDATE:\r
3402aac7 660 break;\r
1e57a462 661 default:\r
662 return EFI_INVALID_PARAMETER;\r
663 }\r
664\r
665 FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;\r
666 CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID));\r
667 FileInfo->FileType = FileHeader->Type;\r
668 FileInfo->FileAttributes = FileHeader->Attributes;\r
669 FileInfo->BufferSize = ((*(UINT32 *)FileHeader->Size) & 0x00FFFFFF) - sizeof (EFI_FFS_FILE_HEADER);\r
670 FileInfo->Buffer = (FileHeader + 1);\r
671 return EFI_SUCCESS;\r
672}\r
673\r
674\r
675/**\r
676 Get Information about the volume by name\r
677\r
678 @param VolumeHandle Handle of the volume.\r
679\r
680 @param VolumeInfo Upon exit, points to the volume's\r
681 information.\r
682\r
683 @retval EFI_SUCCESS File information returned.\r
3402aac7 684\r
1e57a462 685 @retval EFI_INVALID_PARAMETER If FileHandle does not\r
686 represent a valid file.\r
3402aac7 687\r
1e57a462 688 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.\r
689\r
690**/\r
691EFI_STATUS\r
3402aac7 692EFIAPI\r
1e57a462 693FfsGetVolumeInfo (\r
694 IN EFI_PEI_FV_HANDLE VolumeHandle,\r
695 OUT EFI_FV_INFO *VolumeInfo\r
696 )\r
697{\r
698 EFI_FIRMWARE_VOLUME_HEADER FwVolHeader;\r
699 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;\r
700\r
701 if (VolumeInfo == NULL) {\r
702 return EFI_INVALID_PARAMETER;\r
703 }\r
3402aac7 704\r
1e57a462 705 //\r
3402aac7
RC
706 // VolumeHandle may not align at 8 byte,\r
707 // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte.\r
1e57a462 708 // So, Copy FvHeader into the local FvHeader structure.\r
709 //\r
710 CopyMem (&FwVolHeader, VolumeHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
711 //\r
712 // Check Fv Image Signature\r
713 //\r
714 if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {\r
715 return EFI_INVALID_PARAMETER;\r
716 }\r
717 VolumeInfo->FvAttributes = FwVolHeader.Attributes;\r
718 VolumeInfo->FvStart = (VOID *) VolumeHandle;\r
719 VolumeInfo->FvSize = FwVolHeader.FvLength;\r
720 CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID));\r
721\r
722 if (FwVolHeader.ExtHeaderOffset != 0) {\r
723 FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)VolumeHandle) + FwVolHeader.ExtHeaderOffset);\r
724 CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID));\r
725 }\r
726 return EFI_SUCCESS;\r
727}\r
728\r
729\r
730\r
731/**\r
732 Search through every FV until you find a file of type FileType\r
733\r
91c38d4e 734 @param FileType File handle of a Fv type file.\r
c6a72cd7 735 @param Volumehandle On success Volume Handle of the match\r
91c38d4e 736 @param FileHandle On success File Handle of the match\r
3402aac7 737\r
91c38d4e
RC
738 @retval EFI_NOT_FOUND FV image can't be found.\r
739 @retval EFI_SUCCESS Successfully found FileType\r
1e57a462 740\r
741**/\r
742EFI_STATUS\r
743EFIAPI\r
744FfsAnyFvFindFirstFile (\r
745 IN EFI_FV_FILETYPE FileType,\r
746 OUT EFI_PEI_FV_HANDLE *VolumeHandle,\r
747 OUT EFI_PEI_FILE_HANDLE *FileHandle\r
748 )\r
749{\r
750 EFI_STATUS Status;\r
751 UINTN Instance;\r
752\r
753 //\r
754 // Search every FV for the DXE Core\r
755 //\r
756 Instance = 0;\r
757 *FileHandle = NULL;\r
758\r
759 while (1)\r
760 {\r
761 Status = FfsFindNextVolume (Instance++, VolumeHandle);\r
762 if (EFI_ERROR (Status))\r
763 {\r
764 break;\r
765 }\r
766\r
767 Status = FfsFindNextFile (FileType, *VolumeHandle, FileHandle);\r
768 if (!EFI_ERROR (Status))\r
769 {\r
770 break;\r
771 }\r
772 }\r
3402aac7 773\r
1e57a462 774 return Status;\r
775}\r
776\r
777\r
778\r
779/**\r
780 Get Fv image from the FV type file, then add FV & FV2 Hob.\r
781\r
91c38d4e 782 @param FileHandle File handle of a Fv type file.\r
1e57a462 783\r
784\r
91c38d4e
RC
785 @retval EFI_NOT_FOUND FV image can't be found.\r
786 @retval EFI_SUCCESS Successfully to process it.\r
1e57a462 787\r
788**/\r
789EFI_STATUS\r
790EFIAPI\r
791FfsProcessFvFile (\r
792 IN EFI_PEI_FILE_HANDLE FvFileHandle\r
793 )\r
794{\r
795 EFI_STATUS Status;\r
796 EFI_PEI_FV_HANDLE FvImageHandle;\r
797 EFI_FV_INFO FvImageInfo;\r
798 UINT32 FvAlignment;\r
799 VOID *FvBuffer;\r
800 EFI_PEI_HOB_POINTERS HobFv2;\r
801\r
802 FvBuffer = NULL;\r
803\r
804\r
805 //\r
806 // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already\r
807 // been extracted.\r
808 //\r
809 HobFv2.Raw = GetHobList ();\r
810 while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) {\r
811 if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name), &HobFv2.FirmwareVolume2->FileName)) {\r
812 //\r
813 // this FILE has been dispatched, it will not be dispatched again.\r
814 //\r
815 return EFI_SUCCESS;\r
816 }\r
817 HobFv2.Raw = GET_NEXT_HOB (HobFv2);\r
818 }\r
819\r
820 //\r
821 // Find FvImage in FvFile\r
822 //\r
823 Status = FfsFindSectionData (EFI_SECTION_FIRMWARE_VOLUME_IMAGE, FvFileHandle, (VOID **)&FvImageHandle);\r
824 if (EFI_ERROR (Status)) {\r
825 return Status;\r
826 }\r
3402aac7 827\r
1e57a462 828 //\r
829 // Collect FvImage Info.\r
830 //\r
831 ZeroMem (&FvImageInfo, sizeof (FvImageInfo));\r
832 Status = FfsGetVolumeInfo (FvImageHandle, &FvImageInfo);\r
833 ASSERT_EFI_ERROR (Status);\r
3402aac7 834\r
1e57a462 835 //\r
836 // FvAlignment must be more than 8 bytes required by FvHeader structure.\r
837 //\r
838 FvAlignment = 1 << ((FvImageInfo.FvAttributes & EFI_FVB2_ALIGNMENT) >> 16);\r
839 if (FvAlignment < 8) {\r
840 FvAlignment = 8;\r
841 }\r
3402aac7 842\r
1e57a462 843 //\r
844 // Check FvImage\r
845 //\r
846 if ((UINTN) FvImageInfo.FvStart % FvAlignment != 0) {\r
847 FvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvImageInfo.FvSize), FvAlignment);\r
848 if (FvBuffer == NULL) {\r
849 return EFI_OUT_OF_RESOURCES;\r
850 }\r
851 CopyMem (FvBuffer, FvImageInfo.FvStart, (UINTN) FvImageInfo.FvSize);\r
852 //\r
853 // Update FvImageInfo after reload FvImage to new aligned memory\r
854 //\r
855 FfsGetVolumeInfo ((EFI_PEI_FV_HANDLE) FvBuffer, &FvImageInfo);\r
856 }\r
857\r
858\r
859 //\r
c6a72cd7 860 // Inform HOB consumer phase, i.e. DXE core, the existence of this FV\r
1e57a462 861 //\r
862 BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart, FvImageInfo.FvSize);\r
3402aac7 863\r
1e57a462 864 //\r
865 // Makes the encapsulated volume show up in DXE phase to skip processing of\r
866 // encapsulated file again.\r
867 //\r
868 BuildFv2Hob (\r
869 (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart,\r
870 FvImageInfo.FvSize,\r
871 &FvImageInfo.FvName,\r
872 &(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name)\r
873 );\r
874\r
875 return EFI_SUCCESS;\r
876}\r
877\r
878\r