3 Copyright (c) 2004 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 These functions assist in parsing and manipulating a Firmware Volume.
26 #include "CommonLib.h"
27 #include "EfiUtilityMsgs.h"
30 // Module global variables
32 EFI_FIRMWARE_VOLUME_HEADER
*mFvHeader
= NULL
;
36 // External function implementations
47 This initializes the FV lib with a pointer to the FV and length. It does not
48 verify the FV in any way.
52 Fv Buffer containing the FV.
53 FvLength Length of the FV
57 EFI_SUCCESS Function Completed successfully.
58 EFI_INVALID_PARAMETER A required parameter was NULL.
63 // Verify input arguments
66 return EFI_INVALID_PARAMETER
;
69 mFvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) Fv
;
77 OUT EFI_FIRMWARE_VOLUME_HEADER
**FvHeader
,
84 This function returns a pointer to the current FV and the size.
88 FvHeader Pointer to the FV buffer.
89 FvLength Length of the FV
93 EFI_SUCCESS Function Completed successfully.
94 EFI_INVALID_PARAMETER A required parameter was NULL.
95 EFI_ABORTED The library needs to be initialized.
100 // Verify library has been initialized.
102 if (mFvHeader
== NULL
|| mFvLength
== 0) {
106 // Verify input arguments
108 if (FvHeader
== NULL
) {
109 return EFI_INVALID_PARAMETER
;
112 *FvHeader
= mFvHeader
;
118 IN EFI_FFS_FILE_HEADER
*CurrentFile
,
119 OUT EFI_FFS_FILE_HEADER
**NextFile
125 This function returns the next file. If the current file is NULL, it returns
126 the first file in the FV. If the function returns EFI_SUCCESS and the file
127 pointer is NULL, then there are no more files in the FV.
131 CurrentFile Pointer to the current file, must be within the current FV.
132 NextFile Pointer to the next file in the FV.
136 EFI_SUCCESS Function completed successfully.
137 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
138 EFI_ABORTED The library needs to be initialized.
145 // Verify library has been initialized.
147 if (mFvHeader
== NULL
|| mFvLength
== 0) {
151 // Verify input arguments
153 if (NextFile
== NULL
) {
154 return EFI_INVALID_PARAMETER
;
159 Status
= VerifyFv (mFvHeader
);
160 if (EFI_ERROR (Status
)) {
166 if (CurrentFile
== NULL
) {
167 CurrentFile
= (EFI_FFS_FILE_HEADER
*) ((UINTN
) mFvHeader
+ mFvHeader
->HeaderLength
);
170 // Verify file is valid
172 Status
= VerifyFfsFile (CurrentFile
);
173 if (EFI_ERROR (Status
)) {
175 // no files in this FV
181 // Verify file is in this FV.
183 if ((UINTN
) CurrentFile
+ GetLength (CurrentFile
->Size
) > (UINTN
) mFvHeader
+ mFvLength
) {
188 *NextFile
= CurrentFile
;
193 // Verify current file is in range
195 if (((UINTN
) CurrentFile
< (UINTN
) mFvHeader
+ mFvHeader
->HeaderLength
) ||
196 ((UINTN
) CurrentFile
+ GetLength (CurrentFile
->Size
) > (UINTN
) mFvHeader
+ mFvLength
)
198 return EFI_INVALID_PARAMETER
;
201 // Get next file, compensate for 8 byte alignment if necessary.
203 *NextFile
= (EFI_FFS_FILE_HEADER
*) (((UINTN
) CurrentFile
+ GetLength (CurrentFile
->Size
) + 0x07) & (-1 << 3));
206 // Verify file is in this FV.
208 if (((UINTN
) *NextFile
+ sizeof (EFI_FFS_FILE_HEADER
) >= (UINTN
) mFvHeader
+ mFvLength
) ||
209 ((UINTN
) *NextFile
+ GetLength ((*NextFile
)->Size
) > (UINTN
) mFvHeader
+ mFvLength
)
215 // Verify file is valid
217 Status
= VerifyFfsFile (*NextFile
);
218 if (EFI_ERROR (Status
)) {
220 // no more files in this FV
231 IN EFI_GUID
*FileName
,
232 OUT EFI_FFS_FILE_HEADER
**File
238 Find a file by name. The function will return NULL if the file is not found.
242 FileName The GUID file name of the file to search for.
243 File Return pointer. In the case of an error, contents are undefined.
247 EFI_SUCCESS The function completed successfully.
248 EFI_ABORTED An error was encountered.
249 EFI_INVALID_PARAMETER One of the parameters was NULL.
253 EFI_FFS_FILE_HEADER
*CurrentFile
;
255 CHAR8 FileGuidString
[80];
258 // Verify library has been initialized.
260 if (mFvHeader
== NULL
|| mFvLength
== 0) {
264 // Verify input parameters
266 if (FileName
== NULL
|| File
== NULL
) {
267 return EFI_INVALID_PARAMETER
;
270 // File Guid String Name
272 PrintGuidToBuffer (FileName
, (UINT8
*)FileGuidString
, sizeof (FileGuidString
), TRUE
);
276 Status
= VerifyFv (mFvHeader
);
277 if (EFI_ERROR (Status
)) {
281 // Get the first file
283 Status
= GetNextFile (NULL
, &CurrentFile
);
284 if (EFI_ERROR (Status
)) {
285 Error (NULL
, 0, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString
);
289 // Loop as long as we have a valid file
291 while (CurrentFile
) {
292 if (!CompareGuid (&CurrentFile
->Name
, FileName
)) {
297 Status
= GetNextFile (CurrentFile
, &CurrentFile
);
298 if (EFI_ERROR (Status
)) {
299 Error (NULL
, 0, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString
);
304 // File not found in this FV.
312 IN EFI_FV_FILETYPE FileType
,
314 OUT EFI_FFS_FILE_HEADER
**File
320 Find a file by type and instance. An instance of 1 is the first instance.
321 The function will return NULL if a matching file cannot be found.
322 File type EFI_FV_FILETYPE_ALL means any file type is valid.
326 FileType Type of file to search for.
327 Instance Instace of the file type to return.
328 File Return pointer. In the case of an error, contents are undefined.
332 EFI_SUCCESS The function completed successfully.
333 EFI_ABORTED An error was encountered.
334 EFI_INVALID_PARAMETER One of the parameters was NULL.
338 EFI_FFS_FILE_HEADER
*CurrentFile
;
343 // Verify library has been initialized.
345 if (mFvHeader
== NULL
|| mFvLength
== 0) {
349 // Verify input parameters
352 return EFI_INVALID_PARAMETER
;
357 Status
= VerifyFv (mFvHeader
);
358 if (EFI_ERROR (Status
)) {
362 // Initialize the number of matching files found.
367 // Get the first file
369 Status
= GetNextFile (NULL
, &CurrentFile
);
370 if (EFI_ERROR (Status
)) {
371 Error (NULL
, 0, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType
);
375 // Loop as long as we have a valid file
377 while (CurrentFile
) {
378 if (FileType
== EFI_FV_FILETYPE_ALL
|| CurrentFile
->Type
== FileType
) {
382 if (FileCount
== Instance
) {
387 Status
= GetNextFile (CurrentFile
, &CurrentFile
);
388 if (EFI_ERROR (Status
)) {
389 Error (NULL
, 0, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType
);
399 SearchSectionByType (
400 IN EFI_FILE_SECTION_POINTER FirstSection
,
402 IN EFI_SECTION_TYPE SectionType
,
403 IN OUT UINTN
*StartIndex
,
405 OUT EFI_FILE_SECTION_POINTER
*Section
411 Helper function to search a sequence of sections from the section pointed
412 by FirstSection to SearchEnd for the Instance-th section of type SectionType.
413 The current counter is saved in StartIndex and when the section is found, it's
414 saved in Section. GUID-defined sections, if special processing is not required,
415 are searched recursively in a depth-first manner.
419 FirstSection The first section to start searching from.
420 SearchEnd The end address to stop search.
421 SectionType The type of section to search.
422 StartIndex The current counter is saved.
423 Instance The requested n-th section number.
424 Section The found section returned.
428 EFI_SUCCESS The function completed successfully.
429 EFI_NOT_FOUND The section is not found.
432 EFI_FILE_SECTION_POINTER CurrentSection
;
433 EFI_FILE_SECTION_POINTER InnerSection
;
437 CurrentSection
= FirstSection
;
439 while ((UINTN
) CurrentSection
.CommonHeader
< (UINTN
) SearchEnd
) {
440 if (CurrentSection
.CommonHeader
->Type
== SectionType
) {
444 if (*StartIndex
== Instance
) {
445 *Section
= CurrentSection
;
449 // If the requesting section is not GUID-defined and
450 // we find a GUID-defined section that doesn't need
451 // special processing, go ahead to search the requesting
452 // section inside the GUID-defined section.
454 if (SectionType
!= EFI_SECTION_GUID_DEFINED
&&
455 CurrentSection
.CommonHeader
->Type
== EFI_SECTION_GUID_DEFINED
&&
456 !(CurrentSection
.GuidDefinedSection
->Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
)) {
457 InnerSection
.CommonHeader
= (EFI_COMMON_SECTION_HEADER
*)
458 ((UINTN
) CurrentSection
.CommonHeader
+ CurrentSection
.GuidDefinedSection
->DataOffset
);
459 SectionSize
= CurrentSection
.CommonHeader
->Size
[0] +
460 (CurrentSection
.CommonHeader
->Size
[1] << 8) +
461 (CurrentSection
.CommonHeader
->Size
[2] << 16);
462 Status
= SearchSectionByType (
464 (UINT8
*) ((UINTN
) CurrentSection
.CommonHeader
+ SectionSize
),
470 if (!EFI_ERROR (Status
)) {
475 // Find next section (including compensating for alignment issues.
477 CurrentSection
.CommonHeader
= (EFI_COMMON_SECTION_HEADER
*) ((((UINTN
) CurrentSection
.CommonHeader
) + GetLength (CurrentSection
.CommonHeader
->Size
) + 0x03) & (-1 << 2));
480 return EFI_NOT_FOUND
;
485 IN EFI_FFS_FILE_HEADER
*File
,
486 IN EFI_SECTION_TYPE SectionType
,
488 OUT EFI_FILE_SECTION_POINTER
*Section
494 Find a section in a file by type and instance. An instance of 1 is the first
495 instance. The function will return NULL if a matching section cannot be found.
496 GUID-defined sections, if special processing is not needed, are handled in a
501 File The file to search.
502 SectionType Type of file to search for.
503 Instance Instace of the section to return.
504 Section Return pointer. In the case of an error, contents are undefined.
508 EFI_SUCCESS The function completed successfully.
509 EFI_ABORTED An error was encountered.
510 EFI_INVALID_PARAMETER One of the parameters was NULL.
511 EFI_NOT_FOUND No found.
514 EFI_FILE_SECTION_POINTER CurrentSection
;
519 // Verify input parameters
521 if (File
== NULL
|| Instance
== 0) {
522 return EFI_INVALID_PARAMETER
;
527 Status
= VerifyFfsFile (File
);
528 if (EFI_ERROR (Status
)) {
529 Error (NULL
, 0, 0006, "invalid FFS file", NULL
);
533 // Initialize the number of matching sections found.
538 // Get the first section
540 CurrentSection
.CommonHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINTN
) File
+ sizeof (EFI_FFS_FILE_HEADER
));
543 // Depth-first manner to find section file.
545 Status
= SearchSectionByType (
547 (UINT8
*) ((UINTN
) File
+ GetLength (File
->Size
)),
554 if (!EFI_ERROR (Status
)) {
560 (*Section
).Code16Section
= NULL
;
561 return EFI_NOT_FOUND
;
565 // will not parse compressed sections
569 IN EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
575 Verify the current pointer points to a valid FV header.
579 FvHeader Pointer to an alleged FV file.
583 EFI_SUCCESS The FV header is valid.
584 EFI_VOLUME_CORRUPTED The FV header is not valid.
585 EFI_INVALID_PARAMETER A required parameter was NULL.
586 EFI_ABORTED Operation aborted.
593 // Verify input parameters
595 if (FvHeader
== NULL
) {
596 return EFI_INVALID_PARAMETER
;
599 if (FvHeader
->Signature
!= EFI_FVH_SIGNATURE
) {
600 Error (NULL
, 0, 0006, "invalid FV header signature", NULL
);
601 return EFI_VOLUME_CORRUPTED
;
604 // Verify header checksum
606 Checksum
= CalculateSum16 ((UINT16
*) FvHeader
, FvHeader
->HeaderLength
/ sizeof (UINT16
));
609 Error (NULL
, 0, 0006, "invalid FV header checksum", NULL
);
618 IN EFI_FFS_FILE_HEADER
*FfsHeader
624 Verify the current pointer points to a FFS file header.
628 FfsHeader Pointer to an alleged FFS file.
632 EFI_SUCCESS The Ffs header is valid.
633 EFI_NOT_FOUND This "file" is the beginning of free space.
634 EFI_VOLUME_CORRUPTED The Ffs header is not valid.
635 EFI_ABORTED The erase polarity is not known.
639 BOOLEAN ErasePolarity
;
641 EFI_FFS_FILE_HEADER BlankHeader
;
646 UINT8 FileGuidString
[80];
648 // Verify library has been initialized.
650 if (mFvHeader
== NULL
|| mFvLength
== 0) {
656 Status
= VerifyFv (mFvHeader
);
657 if (EFI_ERROR (Status
)) {
661 // Get the erase polarity.
663 Status
= GetErasePolarity (&ErasePolarity
);
664 if (EFI_ERROR (Status
)) {
668 // Check if we have free space
671 memset (&BlankHeader
, -1, sizeof (EFI_FFS_FILE_HEADER
));
673 memset (&BlankHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
676 if (memcmp (&BlankHeader
, FfsHeader
, sizeof (EFI_FFS_FILE_HEADER
)) == 0) {
677 return EFI_NOT_FOUND
;
680 // Convert the GUID to a string so we can at least report which file
681 // if we find an error.
683 PrintGuidToBuffer (&FfsHeader
->Name
, FileGuidString
, sizeof (FileGuidString
), TRUE
);
685 // Verify file header checksum
687 SavedState
= FfsHeader
->State
;
688 FfsHeader
->State
= 0;
689 SavedChecksum
= FfsHeader
->IntegrityCheck
.Checksum
.File
;
690 FfsHeader
->IntegrityCheck
.Checksum
.File
= 0;
691 Checksum
= CalculateSum8 ((UINT8
*) FfsHeader
, sizeof (EFI_FFS_FILE_HEADER
));
692 FfsHeader
->State
= SavedState
;
693 FfsHeader
->IntegrityCheck
.Checksum
.File
= SavedChecksum
;
695 Error (NULL
, 0, 0006, "invalid FFS file header checksum", "Ffs file with Guid %s", FileGuidString
);
699 // Verify file checksum
701 if (FfsHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
703 // Verify file data checksum
705 FileLength
= GetLength (FfsHeader
->Size
);
706 Checksum
= CalculateSum8 ((UINT8
*) FfsHeader
, FileLength
);
707 Checksum
= (UINT8
) (Checksum
- FfsHeader
->State
);
709 Error (NULL
, 0, 0006, "invalid FFS file checksum", "Ffs file with Guid %s", FileGuidString
);
714 // File does not have a checksum
715 // Verify contents are 0x5A as spec'd
717 if (FfsHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
718 Error (NULL
, 0, 0006, "invalid fixed FFS file header checksum", "Ffs file with Guid %s", FileGuidString
);
728 UINT8
*ThreeByteLength
734 Converts a three byte length value into a UINT32.
738 ThreeByteLength Pointer to the first of the 3 byte length.
742 UINT32 Size of the section
748 if (ThreeByteLength
== NULL
) {
752 Length
= *((UINT32
*) ThreeByteLength
);
753 Length
= Length
& 0x00FFFFFF;
760 OUT BOOLEAN
*ErasePolarity
766 This function returns with the FV erase polarity. If the erase polarity
767 for a bit is 1, the function return TRUE.
771 ErasePolarity A pointer to the erase polarity.
775 EFI_SUCCESS The function completed successfully.
776 EFI_INVALID_PARAMETER One of the input parameters was invalid.
777 EFI_ABORTED Operation aborted.
784 // Verify library has been initialized.
786 if (mFvHeader
== NULL
|| mFvLength
== 0) {
792 Status
= VerifyFv (mFvHeader
);
793 if (EFI_ERROR (Status
)) {
797 // Verify input parameters.
799 if (ErasePolarity
== NULL
) {
800 return EFI_INVALID_PARAMETER
;
803 if (mFvHeader
->Attributes
& EFI_FVB2_ERASE_POLARITY
) {
804 *ErasePolarity
= TRUE
;
806 *ErasePolarity
= FALSE
;
814 IN BOOLEAN ErasePolarity
,
815 IN EFI_FFS_FILE_HEADER
*FfsHeader
821 This function returns a the highest state bit in the FFS that is set.
822 It in no way validate the FFS file.
826 ErasePolarity The erase polarity for the file state bits.
827 FfsHeader Pointer to a FFS file.
831 UINT8 The hightest set state of the file.
838 FileState
= FfsHeader
->State
;
841 FileState
= (UINT8
)~FileState
;
845 while (HighestBit
!= 0 && (HighestBit
& FileState
) == 0) {