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
;
113 *FvLength
= mFvLength
;
119 IN EFI_FFS_FILE_HEADER
*CurrentFile
,
120 OUT EFI_FFS_FILE_HEADER
**NextFile
126 This function returns the next file. If the current file is NULL, it returns
127 the first file in the FV. If the function returns EFI_SUCCESS and the file
128 pointer is NULL, then there are no more files in the FV.
132 CurrentFile Pointer to the current file, must be within the current FV.
133 NextFile Pointer to the next file in the FV.
137 EFI_SUCCESS Function completed successfully.
138 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
139 EFI_ABORTED The library needs to be initialized.
146 // Verify library has been initialized.
148 if (mFvHeader
== NULL
|| mFvLength
== 0) {
152 // Verify input arguments
154 if (NextFile
== NULL
) {
155 return EFI_INVALID_PARAMETER
;
160 Status
= VerifyFv (mFvHeader
);
161 if (EFI_ERROR (Status
)) {
167 if (CurrentFile
== NULL
) {
168 CurrentFile
= (EFI_FFS_FILE_HEADER
*) ((UINTN
) mFvHeader
+ mFvHeader
->HeaderLength
);
171 // Verify file is valid
173 Status
= VerifyFfsFile (CurrentFile
);
174 if (EFI_ERROR (Status
)) {
176 // no files in this FV
182 // Verify file is in this FV.
184 if ((UINTN
) CurrentFile
+ GetLength (CurrentFile
->Size
) > (UINTN
) mFvHeader
+ mFvLength
) {
189 *NextFile
= CurrentFile
;
194 // Verify current file is in range
196 if (((UINTN
) CurrentFile
< (UINTN
) mFvHeader
+ mFvHeader
->HeaderLength
) ||
197 ((UINTN
) CurrentFile
+ GetLength (CurrentFile
->Size
) > (UINTN
) mFvHeader
+ mFvLength
)
199 return EFI_INVALID_PARAMETER
;
202 // Get next file, compensate for 8 byte alignment if necessary.
204 *NextFile
= (EFI_FFS_FILE_HEADER
*) ((((UINTN
) CurrentFile
- (UINTN
) mFvHeader
+ GetLength (CurrentFile
->Size
) + 0x07) & (-1 << 3)) + (UINT8
*) mFvHeader
);
207 // Verify file is in this FV.
209 if (((UINTN
) *NextFile
+ sizeof (EFI_FFS_FILE_HEADER
) >= (UINTN
) mFvHeader
+ mFvLength
) ||
210 ((UINTN
) *NextFile
+ GetLength ((*NextFile
)->Size
) > (UINTN
) mFvHeader
+ mFvLength
)
216 // Verify file is valid
218 Status
= VerifyFfsFile (*NextFile
);
219 if (EFI_ERROR (Status
)) {
221 // no more files in this FV
232 IN EFI_GUID
*FileName
,
233 OUT EFI_FFS_FILE_HEADER
**File
239 Find a file by name. The function will return NULL if the file is not found.
243 FileName The GUID file name of the file to search for.
244 File Return pointer. In the case of an error, contents are undefined.
248 EFI_SUCCESS The function completed successfully.
249 EFI_ABORTED An error was encountered.
250 EFI_INVALID_PARAMETER One of the parameters was NULL.
254 EFI_FFS_FILE_HEADER
*CurrentFile
;
256 CHAR8 FileGuidString
[80];
259 // Verify library has been initialized.
261 if (mFvHeader
== NULL
|| mFvLength
== 0) {
265 // Verify input parameters
267 if (FileName
== NULL
|| File
== NULL
) {
268 return EFI_INVALID_PARAMETER
;
271 // File Guid String Name
273 PrintGuidToBuffer (FileName
, (UINT8
*)FileGuidString
, sizeof (FileGuidString
), TRUE
);
277 Status
= VerifyFv (mFvHeader
);
278 if (EFI_ERROR (Status
)) {
282 // Get the first file
284 Status
= GetNextFile (NULL
, &CurrentFile
);
285 if (EFI_ERROR (Status
)) {
286 Error (NULL
, 0, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString
);
290 // Loop as long as we have a valid file
292 while (CurrentFile
) {
293 if (!CompareGuid (&CurrentFile
->Name
, FileName
)) {
298 Status
= GetNextFile (CurrentFile
, &CurrentFile
);
299 if (EFI_ERROR (Status
)) {
300 Error (NULL
, 0, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString
);
305 // File not found in this FV.
313 IN EFI_FV_FILETYPE FileType
,
315 OUT EFI_FFS_FILE_HEADER
**File
321 Find a file by type and instance. An instance of 1 is the first instance.
322 The function will return NULL if a matching file cannot be found.
323 File type EFI_FV_FILETYPE_ALL means any file type is valid.
327 FileType Type of file to search for.
328 Instance Instace of the file type to return.
329 File Return pointer. In the case of an error, contents are undefined.
333 EFI_SUCCESS The function completed successfully.
334 EFI_ABORTED An error was encountered.
335 EFI_INVALID_PARAMETER One of the parameters was NULL.
339 EFI_FFS_FILE_HEADER
*CurrentFile
;
344 // Verify library has been initialized.
346 if (mFvHeader
== NULL
|| mFvLength
== 0) {
350 // Verify input parameters
353 return EFI_INVALID_PARAMETER
;
358 Status
= VerifyFv (mFvHeader
);
359 if (EFI_ERROR (Status
)) {
363 // Initialize the number of matching files found.
368 // Get the first file
370 Status
= GetNextFile (NULL
, &CurrentFile
);
371 if (EFI_ERROR (Status
)) {
372 Error (NULL
, 0, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType
);
376 // Loop as long as we have a valid file
378 while (CurrentFile
) {
379 if (FileType
== EFI_FV_FILETYPE_ALL
|| CurrentFile
->Type
== FileType
) {
383 if (FileCount
== Instance
) {
388 Status
= GetNextFile (CurrentFile
, &CurrentFile
);
389 if (EFI_ERROR (Status
)) {
390 Error (NULL
, 0, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType
);
400 SearchSectionByType (
401 IN EFI_FILE_SECTION_POINTER FirstSection
,
403 IN EFI_SECTION_TYPE SectionType
,
404 IN OUT UINTN
*StartIndex
,
406 OUT EFI_FILE_SECTION_POINTER
*Section
412 Helper function to search a sequence of sections from the section pointed
413 by FirstSection to SearchEnd for the Instance-th section of type SectionType.
414 The current counter is saved in StartIndex and when the section is found, it's
415 saved in Section. GUID-defined sections, if special processing is not required,
416 are searched recursively in a depth-first manner.
420 FirstSection The first section to start searching from.
421 SearchEnd The end address to stop search.
422 SectionType The type of section to search.
423 StartIndex The current counter is saved.
424 Instance The requested n-th section number.
425 Section The found section returned.
429 EFI_SUCCESS The function completed successfully.
430 EFI_NOT_FOUND The section is not found.
433 EFI_FILE_SECTION_POINTER CurrentSection
;
434 EFI_FILE_SECTION_POINTER InnerSection
;
438 CurrentSection
= FirstSection
;
440 while ((UINTN
) CurrentSection
.CommonHeader
< (UINTN
) SearchEnd
) {
441 if (CurrentSection
.CommonHeader
->Type
== SectionType
) {
445 if (*StartIndex
== Instance
) {
446 *Section
= CurrentSection
;
450 // If the requesting section is not GUID-defined and
451 // we find a GUID-defined section that doesn't need
452 // special processing, go ahead to search the requesting
453 // section inside the GUID-defined section.
455 if (SectionType
!= EFI_SECTION_GUID_DEFINED
&&
456 CurrentSection
.CommonHeader
->Type
== EFI_SECTION_GUID_DEFINED
&&
457 !(CurrentSection
.GuidDefinedSection
->Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
)) {
458 InnerSection
.CommonHeader
= (EFI_COMMON_SECTION_HEADER
*)
459 ((UINTN
) CurrentSection
.CommonHeader
+ CurrentSection
.GuidDefinedSection
->DataOffset
);
460 SectionSize
= CurrentSection
.CommonHeader
->Size
[0] +
461 (CurrentSection
.CommonHeader
->Size
[1] << 8) +
462 (CurrentSection
.CommonHeader
->Size
[2] << 16);
463 Status
= SearchSectionByType (
465 (UINT8
*) ((UINTN
) CurrentSection
.CommonHeader
+ SectionSize
),
471 if (!EFI_ERROR (Status
)) {
476 // Find next section (including compensating for alignment issues.
478 CurrentSection
.CommonHeader
= (EFI_COMMON_SECTION_HEADER
*) ((((UINTN
) CurrentSection
.CommonHeader
) + GetLength (CurrentSection
.CommonHeader
->Size
) + 0x03) & (-1 << 2));
481 return EFI_NOT_FOUND
;
486 IN EFI_FFS_FILE_HEADER
*File
,
487 IN EFI_SECTION_TYPE SectionType
,
489 OUT EFI_FILE_SECTION_POINTER
*Section
495 Find a section in a file by type and instance. An instance of 1 is the first
496 instance. The function will return NULL if a matching section cannot be found.
497 GUID-defined sections, if special processing is not needed, are handled in a
502 File The file to search.
503 SectionType Type of file to search for.
504 Instance Instace of the section to return.
505 Section Return pointer. In the case of an error, contents are undefined.
509 EFI_SUCCESS The function completed successfully.
510 EFI_ABORTED An error was encountered.
511 EFI_INVALID_PARAMETER One of the parameters was NULL.
512 EFI_NOT_FOUND No found.
515 EFI_FILE_SECTION_POINTER CurrentSection
;
520 // Verify input parameters
522 if (File
== NULL
|| Instance
== 0) {
523 return EFI_INVALID_PARAMETER
;
528 Status
= VerifyFfsFile (File
);
529 if (EFI_ERROR (Status
)) {
530 Error (NULL
, 0, 0006, "invalid FFS file", NULL
);
534 // Initialize the number of matching sections found.
539 // Get the first section
541 CurrentSection
.CommonHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINTN
) File
+ sizeof (EFI_FFS_FILE_HEADER
));
544 // Depth-first manner to find section file.
546 Status
= SearchSectionByType (
548 (UINT8
*) ((UINTN
) File
+ GetLength (File
->Size
)),
555 if (!EFI_ERROR (Status
)) {
561 (*Section
).Code16Section
= NULL
;
562 return EFI_NOT_FOUND
;
566 // will not parse compressed sections
570 IN EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
576 Verify the current pointer points to a valid FV header.
580 FvHeader Pointer to an alleged FV file.
584 EFI_SUCCESS The FV header is valid.
585 EFI_VOLUME_CORRUPTED The FV header is not valid.
586 EFI_INVALID_PARAMETER A required parameter was NULL.
587 EFI_ABORTED Operation aborted.
594 // Verify input parameters
596 if (FvHeader
== NULL
) {
597 return EFI_INVALID_PARAMETER
;
600 if (FvHeader
->Signature
!= EFI_FVH_SIGNATURE
) {
601 Error (NULL
, 0, 0006, "invalid FV header signature", NULL
);
602 return EFI_VOLUME_CORRUPTED
;
605 // Verify header checksum
607 Checksum
= CalculateSum16 ((UINT16
*) FvHeader
, FvHeader
->HeaderLength
/ sizeof (UINT16
));
610 Error (NULL
, 0, 0006, "invalid FV header checksum", NULL
);
619 IN EFI_FFS_FILE_HEADER
*FfsHeader
625 Verify the current pointer points to a FFS file header.
629 FfsHeader Pointer to an alleged FFS file.
633 EFI_SUCCESS The Ffs header is valid.
634 EFI_NOT_FOUND This "file" is the beginning of free space.
635 EFI_VOLUME_CORRUPTED The Ffs header is not valid.
636 EFI_ABORTED The erase polarity is not known.
640 BOOLEAN ErasePolarity
;
642 EFI_FFS_FILE_HEADER BlankHeader
;
647 UINT8 FileGuidString
[80];
649 // Verify library has been initialized.
651 if (mFvHeader
== NULL
|| mFvLength
== 0) {
657 Status
= VerifyFv (mFvHeader
);
658 if (EFI_ERROR (Status
)) {
662 // Get the erase polarity.
664 Status
= GetErasePolarity (&ErasePolarity
);
665 if (EFI_ERROR (Status
)) {
669 // Check if we have free space
672 memset (&BlankHeader
, -1, sizeof (EFI_FFS_FILE_HEADER
));
674 memset (&BlankHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
677 if (memcmp (&BlankHeader
, FfsHeader
, sizeof (EFI_FFS_FILE_HEADER
)) == 0) {
678 return EFI_NOT_FOUND
;
681 // Convert the GUID to a string so we can at least report which file
682 // if we find an error.
684 PrintGuidToBuffer (&FfsHeader
->Name
, FileGuidString
, sizeof (FileGuidString
), TRUE
);
686 // Verify file header checksum
688 SavedState
= FfsHeader
->State
;
689 FfsHeader
->State
= 0;
690 SavedChecksum
= FfsHeader
->IntegrityCheck
.Checksum
.File
;
691 FfsHeader
->IntegrityCheck
.Checksum
.File
= 0;
692 Checksum
= CalculateSum8 ((UINT8
*) FfsHeader
, sizeof (EFI_FFS_FILE_HEADER
));
693 FfsHeader
->State
= SavedState
;
694 FfsHeader
->IntegrityCheck
.Checksum
.File
= SavedChecksum
;
696 Error (NULL
, 0, 0006, "invalid FFS file header checksum", "Ffs file with Guid %s", FileGuidString
);
700 // Verify file checksum
702 if (FfsHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
704 // Verify file data checksum
706 FileLength
= GetLength (FfsHeader
->Size
);
707 Checksum
= CalculateSum8 ((UINT8
*) (FfsHeader
+ 1), FileLength
- sizeof (EFI_FFS_FILE_HEADER
));
708 Checksum
= Checksum
+ FfsHeader
->IntegrityCheck
.Checksum
.File
;
710 Error (NULL
, 0, 0006, "invalid FFS file checksum", "Ffs file with Guid %s", FileGuidString
);
715 // File does not have a checksum
716 // Verify contents are 0xAA as spec'd
718 if (FfsHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
719 Error (NULL
, 0, 0006, "invalid fixed FFS file header checksum", "Ffs file with Guid %s", FileGuidString
);
729 UINT8
*ThreeByteLength
735 Converts a three byte length value into a UINT32.
739 ThreeByteLength Pointer to the first of the 3 byte length.
743 UINT32 Size of the section
749 if (ThreeByteLength
== NULL
) {
753 Length
= *((UINT32
*) ThreeByteLength
);
754 Length
= Length
& 0x00FFFFFF;
761 OUT BOOLEAN
*ErasePolarity
767 This function returns with the FV erase polarity. If the erase polarity
768 for a bit is 1, the function return TRUE.
772 ErasePolarity A pointer to the erase polarity.
776 EFI_SUCCESS The function completed successfully.
777 EFI_INVALID_PARAMETER One of the input parameters was invalid.
778 EFI_ABORTED Operation aborted.
785 // Verify library has been initialized.
787 if (mFvHeader
== NULL
|| mFvLength
== 0) {
793 Status
= VerifyFv (mFvHeader
);
794 if (EFI_ERROR (Status
)) {
798 // Verify input parameters.
800 if (ErasePolarity
== NULL
) {
801 return EFI_INVALID_PARAMETER
;
804 if (mFvHeader
->Attributes
& EFI_FVB2_ERASE_POLARITY
) {
805 *ErasePolarity
= TRUE
;
807 *ErasePolarity
= FALSE
;
815 IN BOOLEAN ErasePolarity
,
816 IN EFI_FFS_FILE_HEADER
*FfsHeader
822 This function returns a the highest state bit in the FFS that is set.
823 It in no way validate the FFS file.
827 ErasePolarity The erase polarity for the file state bits.
828 FfsHeader Pointer to a FFS file.
832 UINT8 The hightest set state of the file.
839 FileState
= FfsHeader
->State
;
842 FileState
= (UINT8
)~FileState
;
846 while (HighestBit
!= 0 && (HighestBit
& FileState
) == 0) {