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