2 These functions assist in parsing and manipulating a Firmware Volume.
4 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #include "CommonLib.h"
20 #include "EfiUtilityMsgs.h"
23 // Module global variables
25 EFI_FIRMWARE_VOLUME_HEADER
*mFvHeader
= NULL
;
29 // External function implementations
40 This initializes the FV lib with a pointer to the FV and length. It does not
41 verify the FV in any way.
45 Fv Buffer containing the FV.
46 FvLength Length of the FV
50 EFI_SUCCESS Function Completed successfully.
51 EFI_INVALID_PARAMETER A required parameter was NULL.
56 // Verify input arguments
59 return EFI_INVALID_PARAMETER
;
62 mFvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) Fv
;
70 OUT EFI_FIRMWARE_VOLUME_HEADER
**FvHeader
,
77 This function returns a pointer to the current FV and the size.
81 FvHeader Pointer to the FV buffer.
82 FvLength Length of the FV
86 EFI_SUCCESS Function Completed successfully.
87 EFI_INVALID_PARAMETER A required parameter was NULL.
88 EFI_ABORTED The library needs to be initialized.
93 // Verify library has been initialized.
95 if (mFvHeader
== NULL
|| mFvLength
== 0) {
99 // Verify input arguments
101 if (FvHeader
== NULL
) {
102 return EFI_INVALID_PARAMETER
;
105 *FvHeader
= mFvHeader
;
106 *FvLength
= mFvLength
;
112 IN EFI_FFS_FILE_HEADER
*CurrentFile
,
113 OUT EFI_FFS_FILE_HEADER
**NextFile
119 This function returns the next file. If the current file is NULL, it returns
120 the first file in the FV. If the function returns EFI_SUCCESS and the file
121 pointer is NULL, then there are no more files in the FV.
125 CurrentFile Pointer to the current file, must be within the current FV.
126 NextFile Pointer to the next file in the FV.
130 EFI_SUCCESS Function completed successfully.
131 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
132 EFI_ABORTED The library needs to be initialized.
139 // Verify library has been initialized.
141 if (mFvHeader
== NULL
|| mFvLength
== 0) {
145 // Verify input arguments
147 if (NextFile
== NULL
) {
148 return EFI_INVALID_PARAMETER
;
153 Status
= VerifyFv (mFvHeader
);
154 if (EFI_ERROR (Status
)) {
160 if (CurrentFile
== NULL
) {
161 CurrentFile
= (EFI_FFS_FILE_HEADER
*) ((UINTN
) mFvHeader
+ mFvHeader
->HeaderLength
);
164 // Verify file is valid
166 Status
= VerifyFfsFile (CurrentFile
);
167 if (EFI_ERROR (Status
)) {
169 // no files in this FV
175 // Verify file is in this FV.
177 if ((UINTN
) CurrentFile
+ GetFfsFileLength(CurrentFile
) > (UINTN
) mFvHeader
+ mFvLength
) {
182 *NextFile
= CurrentFile
;
187 // Verify current file is in range
189 if (((UINTN
) CurrentFile
< (UINTN
) mFvHeader
+ mFvHeader
->HeaderLength
) ||
190 ((UINTN
) CurrentFile
+ GetFfsFileLength(CurrentFile
) > (UINTN
) mFvHeader
+ mFvLength
)
192 return EFI_INVALID_PARAMETER
;
195 // Get next file, compensate for 8 byte alignment if necessary.
197 *NextFile
= (EFI_FFS_FILE_HEADER
*) ((((UINTN
) CurrentFile
- (UINTN
) mFvHeader
+ GetFfsFileLength(CurrentFile
) + 0x07) & (-1 << 3)) + (UINT8
*) mFvHeader
);
200 // Verify file is in this FV.
202 if (((UINTN
) *NextFile
+ GetFfsHeaderLength(*NextFile
) >= (UINTN
) mFvHeader
+ mFvLength
) ||
203 ((UINTN
) *NextFile
+ GetFfsFileLength (*NextFile
) > (UINTN
) mFvHeader
+ mFvLength
)
209 // Verify file is valid
211 Status
= VerifyFfsFile (*NextFile
);
212 if (EFI_ERROR (Status
)) {
214 // no more files in this FV
225 IN EFI_GUID
*FileName
,
226 OUT EFI_FFS_FILE_HEADER
**File
232 Find a file by name. The function will return NULL if the file is not found.
236 FileName The GUID file name of the file to search for.
237 File Return pointer. In the case of an error, contents are undefined.
241 EFI_SUCCESS The function completed successfully.
242 EFI_ABORTED An error was encountered.
243 EFI_INVALID_PARAMETER One of the parameters was NULL.
247 EFI_FFS_FILE_HEADER
*CurrentFile
;
249 CHAR8 FileGuidString
[80];
252 // Verify library has been initialized.
254 if (mFvHeader
== NULL
|| mFvLength
== 0) {
258 // Verify input parameters
260 if (FileName
== NULL
|| File
== NULL
) {
261 return EFI_INVALID_PARAMETER
;
264 // File Guid String Name
266 PrintGuidToBuffer (FileName
, (UINT8
*)FileGuidString
, sizeof (FileGuidString
), TRUE
);
270 Status
= VerifyFv (mFvHeader
);
271 if (EFI_ERROR (Status
)) {
275 // Get the first file
277 Status
= GetNextFile (NULL
, &CurrentFile
);
278 if (EFI_ERROR (Status
)) {
279 Error (NULL
, 0, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString
);
283 // Loop as long as we have a valid file
285 while (CurrentFile
) {
286 if (!CompareGuid (&CurrentFile
->Name
, FileName
)) {
291 Status
= GetNextFile (CurrentFile
, &CurrentFile
);
292 if (EFI_ERROR (Status
)) {
293 Error (NULL
, 0, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString
);
298 // File not found in this FV.
306 IN EFI_FV_FILETYPE FileType
,
308 OUT EFI_FFS_FILE_HEADER
**File
314 Find a file by type and instance. An instance of 1 is the first instance.
315 The function will return NULL if a matching file cannot be found.
316 File type EFI_FV_FILETYPE_ALL means any file type is valid.
320 FileType Type of file to search for.
321 Instance Instace of the file type to return.
322 File Return pointer. In the case of an error, contents are undefined.
326 EFI_SUCCESS The function completed successfully.
327 EFI_ABORTED An error was encountered.
328 EFI_INVALID_PARAMETER One of the parameters was NULL.
332 EFI_FFS_FILE_HEADER
*CurrentFile
;
337 // Verify library has been initialized.
339 if (mFvHeader
== NULL
|| mFvLength
== 0) {
343 // Verify input parameters
346 return EFI_INVALID_PARAMETER
;
351 Status
= VerifyFv (mFvHeader
);
352 if (EFI_ERROR (Status
)) {
356 // Initialize the number of matching files found.
361 // Get the first file
363 Status
= GetNextFile (NULL
, &CurrentFile
);
364 if (EFI_ERROR (Status
)) {
365 Error (NULL
, 0, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType
);
369 // Loop as long as we have a valid file
371 while (CurrentFile
) {
372 if (FileType
== EFI_FV_FILETYPE_ALL
|| CurrentFile
->Type
== FileType
) {
376 if (FileCount
== Instance
) {
381 Status
= GetNextFile (CurrentFile
, &CurrentFile
);
382 if (EFI_ERROR (Status
)) {
383 Error (NULL
, 0, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType
);
393 SearchSectionByType (
394 IN EFI_FILE_SECTION_POINTER FirstSection
,
396 IN EFI_SECTION_TYPE SectionType
,
397 IN OUT UINTN
*StartIndex
,
399 OUT EFI_FILE_SECTION_POINTER
*Section
405 Helper function to search a sequence of sections from the section pointed
406 by FirstSection to SearchEnd for the Instance-th section of type SectionType.
407 The current counter is saved in StartIndex and when the section is found, it's
408 saved in Section. GUID-defined sections, if special processing is not required,
409 are searched recursively in a depth-first manner.
413 FirstSection The first section to start searching from.
414 SearchEnd The end address to stop search.
415 SectionType The type of section to search.
416 StartIndex The current counter is saved.
417 Instance The requested n-th section number.
418 Section The found section returned.
422 EFI_SUCCESS The function completed successfully.
423 EFI_NOT_FOUND The section is not found.
426 EFI_FILE_SECTION_POINTER CurrentSection
;
427 EFI_FILE_SECTION_POINTER InnerSection
;
431 UINT16 GuidDataOffset
;
435 CurrentSection
= FirstSection
;
437 while ((UINTN
) CurrentSection
.CommonHeader
< (UINTN
) SearchEnd
) {
438 if (CurrentSection
.CommonHeader
->Type
== SectionType
) {
442 if (*StartIndex
== Instance
) {
443 *Section
= CurrentSection
;
447 // If the requesting section is not GUID-defined and
448 // we find a GUID-defined section that doesn't need
449 // special processing, go ahead to search the requesting
450 // section inside the GUID-defined section.
452 if (CurrentSection
.CommonHeader
->Type
== EFI_SECTION_GUID_DEFINED
) {
453 if (GetLength(CurrentSection
.CommonHeader
->Size
) == 0xffffff) {
454 GuidSecAttr
= CurrentSection
.GuidDefinedSection2
->Attributes
;
455 GuidDataOffset
= CurrentSection
.GuidDefinedSection2
->DataOffset
;
457 GuidSecAttr
= CurrentSection
.GuidDefinedSection
->Attributes
;
458 GuidDataOffset
= CurrentSection
.GuidDefinedSection
->DataOffset
;
461 if (SectionType
!= EFI_SECTION_GUID_DEFINED
&&
462 CurrentSection
.CommonHeader
->Type
== EFI_SECTION_GUID_DEFINED
&&
463 !(GuidSecAttr
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
)) {
464 InnerSection
.CommonHeader
= (EFI_COMMON_SECTION_HEADER
*)
465 ((UINTN
) CurrentSection
.CommonHeader
+ GuidDataOffset
);
466 SectionSize
= GetSectionFileLength(CurrentSection
.CommonHeader
);
467 Status
= SearchSectionByType (
469 (UINT8
*) ((UINTN
) CurrentSection
.CommonHeader
+ SectionSize
),
475 if (!EFI_ERROR (Status
)) {
480 // Find next section (including compensating for alignment issues.
482 CurrentSection
.CommonHeader
= (EFI_COMMON_SECTION_HEADER
*) ((((UINTN
) CurrentSection
.CommonHeader
) + GetSectionFileLength(CurrentSection
.CommonHeader
) + 0x03) & (-1 << 2));
485 return EFI_NOT_FOUND
;
490 IN EFI_FFS_FILE_HEADER
*File
,
491 IN EFI_SECTION_TYPE SectionType
,
493 OUT EFI_FILE_SECTION_POINTER
*Section
499 Find a section in a file by type and instance. An instance of 1 is the first
500 instance. The function will return NULL if a matching section cannot be found.
501 GUID-defined sections, if special processing is not needed, are handled in a
506 File The file to search.
507 SectionType Type of file to search for.
508 Instance Instace of the section to return.
509 Section Return pointer. In the case of an error, contents are undefined.
513 EFI_SUCCESS The function completed successfully.
514 EFI_ABORTED An error was encountered.
515 EFI_INVALID_PARAMETER One of the parameters was NULL.
516 EFI_NOT_FOUND No found.
519 EFI_FILE_SECTION_POINTER CurrentSection
;
524 // Verify input parameters
526 if (File
== NULL
|| Instance
== 0) {
527 return EFI_INVALID_PARAMETER
;
532 Status
= VerifyFfsFile (File
);
533 if (EFI_ERROR (Status
)) {
534 Error (NULL
, 0, 0006, "invalid FFS file", NULL
);
538 // Initialize the number of matching sections found.
543 // Get the first section
545 CurrentSection
.CommonHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINTN
) File
+ GetFfsHeaderLength(File
));
548 // Depth-first manner to find section file.
550 Status
= SearchSectionByType (
552 (UINT8
*) ((UINTN
) File
+ GetFfsFileLength (File
)),
559 if (!EFI_ERROR (Status
)) {
565 (*Section
).Code16Section
= NULL
;
566 return EFI_NOT_FOUND
;
570 // will not parse compressed sections
574 IN EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
580 Verify the current pointer points to a valid FV header.
584 FvHeader Pointer to an alleged FV file.
588 EFI_SUCCESS The FV header is valid.
589 EFI_VOLUME_CORRUPTED The FV header is not valid.
590 EFI_INVALID_PARAMETER A required parameter was NULL.
591 EFI_ABORTED Operation aborted.
598 // Verify input parameters
600 if (FvHeader
== NULL
) {
601 return EFI_INVALID_PARAMETER
;
604 if (FvHeader
->Signature
!= EFI_FVH_SIGNATURE
) {
605 Error (NULL
, 0, 0006, "invalid FV header signature", NULL
);
606 return EFI_VOLUME_CORRUPTED
;
609 // Verify header checksum
611 Checksum
= CalculateSum16 ((UINT16
*) FvHeader
, FvHeader
->HeaderLength
/ sizeof (UINT16
));
614 Error (NULL
, 0, 0006, "invalid FV header checksum", NULL
);
623 IN EFI_FFS_FILE_HEADER
*FfsHeader
629 Verify the current pointer points to a FFS file header.
633 FfsHeader Pointer to an alleged FFS file.
637 EFI_SUCCESS The Ffs header is valid.
638 EFI_NOT_FOUND This "file" is the beginning of free space.
639 EFI_VOLUME_CORRUPTED The Ffs header is not valid.
640 EFI_ABORTED The erase polarity is not known.
644 BOOLEAN ErasePolarity
;
646 EFI_FFS_FILE_HEADER2 BlankHeader
;
651 UINT8 FileGuidString
[80];
652 UINT32 FfsHeaderSize
;
655 // Verify library has been initialized.
657 if (mFvHeader
== NULL
|| mFvLength
== 0) {
663 Status
= VerifyFv (mFvHeader
);
664 if (EFI_ERROR (Status
)) {
668 // Get the erase polarity.
670 Status
= GetErasePolarity (&ErasePolarity
);
671 if (EFI_ERROR (Status
)) {
675 FfsHeaderSize
= GetFfsHeaderLength(FfsHeader
);
677 // Check if we have free space
680 memset (&BlankHeader
, -1, FfsHeaderSize
);
682 memset (&BlankHeader
, 0, FfsHeaderSize
);
685 if (memcmp (&BlankHeader
, FfsHeader
, FfsHeaderSize
) == 0) {
686 return EFI_NOT_FOUND
;
689 // Convert the GUID to a string so we can at least report which file
690 // if we find an error.
692 PrintGuidToBuffer (&FfsHeader
->Name
, FileGuidString
, sizeof (FileGuidString
), TRUE
);
694 // Verify file header checksum
696 SavedState
= FfsHeader
->State
;
697 FfsHeader
->State
= 0;
698 SavedChecksum
= FfsHeader
->IntegrityCheck
.Checksum
.File
;
699 FfsHeader
->IntegrityCheck
.Checksum
.File
= 0;
700 Checksum
= CalculateSum8 ((UINT8
*) FfsHeader
, FfsHeaderSize
);
701 FfsHeader
->State
= SavedState
;
702 FfsHeader
->IntegrityCheck
.Checksum
.File
= SavedChecksum
;
704 Error (NULL
, 0, 0006, "invalid FFS file header checksum", "Ffs file with Guid %s", FileGuidString
);
708 // Verify file checksum
710 if (FfsHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
712 // Verify file data checksum
714 FileLength
= GetFfsFileLength (FfsHeader
);
715 Checksum
= CalculateSum8 ((UINT8
*) ((UINT8
*)FfsHeader
+ FfsHeaderSize
), FileLength
- FfsHeaderSize
);
716 Checksum
= Checksum
+ FfsHeader
->IntegrityCheck
.Checksum
.File
;
718 Error (NULL
, 0, 0006, "invalid FFS file checksum", "Ffs file with Guid %s", FileGuidString
);
723 // File does not have a checksum
724 // Verify contents are 0xAA as spec'd
726 if (FfsHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
727 Error (NULL
, 0, 0006, "invalid fixed FFS file header checksum", "Ffs file with Guid %s", FileGuidString
);
737 IN EFI_FFS_FILE_HEADER
*FfsHeader
740 if (FfsHeader
== NULL
) {
743 if (FfsHeader
->Attributes
& FFS_ATTRIB_LARGE_FILE
) {
744 return sizeof(EFI_FFS_FILE_HEADER2
);
746 return sizeof(EFI_FFS_FILE_HEADER
);
750 GetSectionHeaderLength(
751 IN EFI_COMMON_SECTION_HEADER
*SectionHeader
754 if (SectionHeader
== NULL
) {
757 if (GetLength(SectionHeader
->Size
) == 0xffffff) {
758 return sizeof(EFI_COMMON_SECTION_HEADER2
);
760 return sizeof(EFI_COMMON_SECTION_HEADER
);
765 EFI_FFS_FILE_HEADER
*FfsHeader
771 Get FFS file length including FFS header.
775 FfsHeader Pointer to EFI_FFS_FILE_HEADER.
779 UINT32 Length of FFS file header.
783 if (FfsHeader
== NULL
) {
786 if (FfsHeader
->Attributes
& FFS_ATTRIB_LARGE_FILE
) {
787 return ((EFI_FFS_FILE_HEADER2
*)FfsHeader
)->ExtendedSize
;
789 return GetLength(FfsHeader
->Size
);
794 GetSectionFileLength (
795 EFI_COMMON_SECTION_HEADER
*SectionHeader
799 if (SectionHeader
== NULL
) {
802 Length
= GetLength(SectionHeader
->Size
);
803 if (Length
== 0xffffff) {
804 Length
= ((EFI_COMMON_SECTION_HEADER2
*)SectionHeader
)->ExtendedSize
;
811 UINT8
*ThreeByteLength
817 Converts a three byte length value into a UINT32.
821 ThreeByteLength Pointer to the first of the 3 byte length.
825 UINT32 Size of the section
831 if (ThreeByteLength
== NULL
) {
835 Length
= *((UINT32
*) ThreeByteLength
);
836 Length
= Length
& 0x00FFFFFF;
843 OUT BOOLEAN
*ErasePolarity
849 This function returns with the FV erase polarity. If the erase polarity
850 for a bit is 1, the function return TRUE.
854 ErasePolarity A pointer to the erase polarity.
858 EFI_SUCCESS The function completed successfully.
859 EFI_INVALID_PARAMETER One of the input parameters was invalid.
860 EFI_ABORTED Operation aborted.
867 // Verify library has been initialized.
869 if (mFvHeader
== NULL
|| mFvLength
== 0) {
875 Status
= VerifyFv (mFvHeader
);
876 if (EFI_ERROR (Status
)) {
880 // Verify input parameters.
882 if (ErasePolarity
== NULL
) {
883 return EFI_INVALID_PARAMETER
;
886 if (mFvHeader
->Attributes
& EFI_FVB2_ERASE_POLARITY
) {
887 *ErasePolarity
= TRUE
;
889 *ErasePolarity
= FALSE
;
897 IN BOOLEAN ErasePolarity
,
898 IN EFI_FFS_FILE_HEADER
*FfsHeader
904 This function returns a the highest state bit in the FFS that is set.
905 It in no way validate the FFS file.
909 ErasePolarity The erase polarity for the file state bits.
910 FfsHeader Pointer to a FFS file.
914 UINT8 The hightest set state of the file.
921 FileState
= FfsHeader
->State
;
924 FileState
= (UINT8
)~FileState
;
928 while (HighestBit
!= 0 && (HighestBit
& FileState
) == 0) {