3 Copyright (c) 2004, 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"
28 #include "MultiPhase.h"
30 #include <CommonBuild.h>
34 #include EFI_GUID_DEFINITION (FirmwareFileSystem)
38 // Module global variables
40 EFI_FIRMWARE_VOLUME_HEADER
*mFvHeader
= NULL
;
44 // External function implementations
55 This initializes the FV lib with a pointer to the FV and length. It does not
56 verify the FV in any way.
60 Fv Buffer containing the FV.
61 FvLength Length of the FV
65 EFI_SUCCESS Function Completed successfully.
66 EFI_INVALID_PARAMETER A required parameter was NULL.
71 // Verify input arguments
74 return EFI_INVALID_PARAMETER
;
77 mFvHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) Fv
;
85 OUT EFI_FIRMWARE_VOLUME_HEADER
**FvHeader
,
92 This function returns a pointer to the current FV and the size.
96 FvHeader Pointer to the FV buffer.
97 FvLength Length of the FV
101 EFI_SUCCESS Function Completed successfully.
102 EFI_INVALID_PARAMETER A required parameter was NULL.
103 EFI_ABORTED The library needs to be initialized.
108 // Verify library has been initialized.
110 if (mFvHeader
== NULL
|| mFvLength
== 0) {
114 // Verify input arguments
116 if (FvHeader
== NULL
) {
117 return EFI_INVALID_PARAMETER
;
120 *FvHeader
= mFvHeader
;
126 IN EFI_FFS_FILE_HEADER
*CurrentFile
,
127 OUT EFI_FFS_FILE_HEADER
**NextFile
133 This function returns the next file. If the current file is NULL, it returns
134 the first file in the FV. If the function returns EFI_SUCCESS and the file
135 pointer is NULL, then there are no more files in the FV.
139 CurrentFile Pointer to the current file, must be within the current FV.
140 NextFile Pointer to the next file in the FV.
144 EFI_SUCCESS Function completed successfully.
145 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
146 EFI_ABORTED The library needs to be initialized.
153 // Verify library has been initialized.
155 if (mFvHeader
== NULL
|| mFvLength
== 0) {
159 // Verify input arguments
161 if (NextFile
== NULL
) {
162 return EFI_INVALID_PARAMETER
;
167 Status
= VerifyFv (mFvHeader
);
168 if (EFI_ERROR (Status
)) {
174 if (CurrentFile
== NULL
) {
175 CurrentFile
= (EFI_FFS_FILE_HEADER
*) ((UINTN
) mFvHeader
+ mFvHeader
->HeaderLength
);
178 // Verify file is valid
180 Status
= VerifyFfsFile (CurrentFile
);
181 if (EFI_ERROR (Status
)) {
183 // no files in this FV
189 // Verify file is in this FV.
191 if ((UINTN
) CurrentFile
>= (UINTN
) mFvHeader
+ mFvLength
- sizeof (EFI_FFS_FILE_HEADER
)) {
196 *NextFile
= CurrentFile
;
201 // Verify current file is in range
203 if (((UINTN
) CurrentFile
< (UINTN
) mFvHeader
+ sizeof (EFI_FIRMWARE_VOLUME_HEADER
)) ||
204 ((UINTN
) CurrentFile
>= (UINTN
) mFvHeader
+ mFvLength
- sizeof (EFI_FIRMWARE_VOLUME_HEADER
))
206 return EFI_INVALID_PARAMETER
;
209 // Get next file, compensate for 8 byte alignment if necessary.
211 *NextFile
= (EFI_FFS_FILE_HEADER
*) (((UINTN
) CurrentFile
+ GetLength (CurrentFile
->Size
) + 0x07) & (-1 << 3));
214 // Verify file is in this FV.
216 if ((UINTN
) *NextFile
>= (UINTN
) mFvHeader
+ mFvLength
- sizeof (EFI_FFS_FILE_HEADER
)) {
221 // Verify file is valid
223 Status
= VerifyFfsFile (*NextFile
);
224 if (EFI_ERROR (Status
)) {
226 // no more files in this FV
237 IN EFI_GUID
*FileName
,
238 OUT EFI_FFS_FILE_HEADER
**File
244 Find a file by name. The function will return NULL if the file is not found.
248 FileName The GUID file name of the file to search for.
249 File Return pointer. In the case of an error, contents are undefined.
253 EFI_SUCCESS The function completed successfully.
254 EFI_ABORTED An error was encountered.
255 EFI_INVALID_PARAMETER One of the parameters was NULL.
259 EFI_FFS_FILE_HEADER
*CurrentFile
;
263 // Verify library has been initialized.
265 if (mFvHeader
== NULL
|| mFvLength
== 0) {
269 // Verify input parameters
271 if (FileName
== NULL
|| File
== NULL
) {
272 return EFI_INVALID_PARAMETER
;
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, 0, "error parsing the FV", NULL
);
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, 0, "error parsing the FV", NULL
);
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, 0, "error parsing FV", NULL
);
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, 0, "error parsing the FV", NULL
);
401 IN EFI_FFS_FILE_HEADER
*File
,
402 IN EFI_SECTION_TYPE SectionType
,
404 OUT EFI_FILE_SECTION_POINTER
*Section
410 Find a section in a file by type and instance. An instance of 1 is the first
411 instance. The function will return NULL if a matching section cannot be found.
412 The function will not handle encapsulating sections.
416 File The file to search.
417 SectionType Type of file to search for.
418 Instance Instace of the section to return.
419 Section Return pointer. In the case of an error, contents are undefined.
423 EFI_SUCCESS The function completed successfully.
424 EFI_ABORTED An error was encountered.
425 EFI_INVALID_PARAMETER One of the parameters was NULL.
426 EFI_NOT_FOUND No found.
429 EFI_FILE_SECTION_POINTER CurrentSection
;
434 // Verify input parameters
436 if (File
== NULL
|| Instance
== 0) {
437 return EFI_INVALID_PARAMETER
;
442 Status
= VerifyFfsFile (File
);
443 if (EFI_ERROR (Status
)) {
444 Error (NULL
, 0, 0, "invalid FFS file", NULL
);
448 // Initialize the number of matching sections found.
453 // Get the first section
455 CurrentSection
.CommonHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINTN
) File
+ sizeof (EFI_FFS_FILE_HEADER
));
458 // Loop as long as we have a valid file
460 while ((UINTN
) CurrentSection
.CommonHeader
< (UINTN
) File
+ GetLength (File
->Size
)) {
461 if (CurrentSection
.CommonHeader
->Type
== SectionType
) {
465 if (SectionCount
== Instance
) {
466 *Section
= CurrentSection
;
470 // Find next section (including compensating for alignment issues.
472 CurrentSection
.CommonHeader
= (EFI_COMMON_SECTION_HEADER
*) ((((UINTN
) CurrentSection
.CommonHeader
) + GetLength (CurrentSection
.CommonHeader
->Size
) + 0x03) & (-1 << 2));
477 (*Section
).Code16Section
= NULL
;
478 return EFI_NOT_FOUND
;
481 // will not parse compressed sections
485 IN EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
491 Verify the current pointer points to a valid FV header.
495 FvHeader Pointer to an alleged FV file.
499 EFI_SUCCESS The FV header is valid.
500 EFI_VOLUME_CORRUPTED The FV header is not valid.
501 EFI_INVALID_PARAMETER A required parameter was NULL.
502 EFI_ABORTED Operation aborted.
509 // Verify input parameters
511 if (FvHeader
== NULL
) {
512 return EFI_INVALID_PARAMETER
;
515 if (FvHeader
->Signature
!= EFI_FVH_SIGNATURE
) {
516 Error (NULL
, 0, 0, "invalid FV header signature", NULL
);
517 return EFI_VOLUME_CORRUPTED
;
520 // Verify header checksum
522 Checksum
= CalculateSum16 ((UINT16
*) FvHeader
, FvHeader
->HeaderLength
/ sizeof (UINT16
));
525 Error (NULL
, 0, 0, "invalid FV header checksum", NULL
);
534 IN EFI_FFS_FILE_HEADER
*FfsHeader
540 Verify the current pointer points to a FFS file header.
544 FfsHeader Pointer to an alleged FFS file.
548 EFI_SUCCESS The Ffs header is valid.
549 EFI_NOT_FOUND This "file" is the beginning of free space.
550 EFI_VOLUME_CORRUPTED The Ffs header is not valid.
551 EFI_ABORTED The erase polarity is not known.
555 BOOLEAN ErasePolarity
;
557 EFI_FFS_FILE_HEADER BlankHeader
;
560 UINT32 OccupiedFileLength
;
561 EFI_FFS_FILE_TAIL
*Tail
;
564 UINT8 FileGuidString
[80];
567 // Verify library has been initialized.
569 if (mFvHeader
== NULL
|| mFvLength
== 0) {
575 Status
= VerifyFv (mFvHeader
);
576 if (EFI_ERROR (Status
)) {
580 // Get the erase polarity.
582 Status
= GetErasePolarity (&ErasePolarity
);
583 if (EFI_ERROR (Status
)) {
587 // Check if we have free space
590 memset (&BlankHeader
, -1, sizeof (EFI_FFS_FILE_HEADER
));
592 memset (&BlankHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
595 if (memcmp (&BlankHeader
, FfsHeader
, sizeof (EFI_FFS_FILE_HEADER
)) == 0) {
596 return EFI_NOT_FOUND
;
599 // Convert the GUID to a string so we can at least report which file
600 // if we find an error.
602 PrintGuidToBuffer (&FfsHeader
->Name
, FileGuidString
, sizeof (FileGuidString
), TRUE
);
603 if (FfsHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
604 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
609 // Verify file header checksum
611 SavedState
= FfsHeader
->State
;
612 FfsHeader
->State
= 0;
613 SavedChecksum
= FfsHeader
->IntegrityCheck
.Checksum
.File
;
614 FfsHeader
->IntegrityCheck
.Checksum
.File
= 0;
615 Checksum
= CalculateSum8 ((UINT8
*) FfsHeader
, sizeof (EFI_FFS_FILE_HEADER
));
616 FfsHeader
->State
= SavedState
;
617 FfsHeader
->IntegrityCheck
.Checksum
.File
= SavedChecksum
;
619 Error (NULL
, 0, 0, FileGuidString
, "invalid FFS file header checksum");
623 // Verify file checksum
625 if (FfsHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
627 // Verify file data checksum
629 FileLength
= GetLength (FfsHeader
->Size
);
630 OccupiedFileLength
= (FileLength
+ 0x07) & (-1 << 3);
631 Checksum
= CalculateSum8 ((UINT8
*) FfsHeader
, FileLength
- TailSize
);
632 Checksum
= (UINT8
) (Checksum
- FfsHeader
->State
);
634 Error (NULL
, 0, 0, FileGuidString
, "invalid FFS file checksum");
639 // File does not have a checksum
640 // Verify contents are 0x5A as spec'd
642 if (FfsHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
643 Error (NULL
, 0, 0, FileGuidString
, "invalid fixed FFS file header checksum");
648 // Check if the tail is present and verify it if it is.
650 if (FfsHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
652 // Verify tail is complement of integrity check field in the header.
654 Tail
= (EFI_FFS_FILE_TAIL
*) ((UINTN
) FfsHeader
+ GetLength (FfsHeader
->Size
) - sizeof (EFI_FFS_FILE_TAIL
));
655 if (FfsHeader
->IntegrityCheck
.TailReference
!= (EFI_FFS_FILE_TAIL
)~(*Tail
)) {
656 Error (NULL
, 0, 0, FileGuidString
, "invalid FFS file tail");
666 UINT8
*ThreeByteLength
672 Converts a three byte length value into a UINT32.
676 ThreeByteLength Pointer to the first of the 3 byte length.
680 UINT32 Size of the section
686 if (ThreeByteLength
== NULL
) {
690 Length
= *((UINT32
*) ThreeByteLength
);
691 Length
= Length
& 0x00FFFFFF;
698 OUT BOOLEAN
*ErasePolarity
704 This function returns with the FV erase polarity. If the erase polarity
705 for a bit is 1, the function return TRUE.
709 ErasePolarity A pointer to the erase polarity.
713 EFI_SUCCESS The function completed successfully.
714 EFI_INVALID_PARAMETER One of the input parameters was invalid.
715 EFI_ABORTED Operation aborted.
722 // Verify library has been initialized.
724 if (mFvHeader
== NULL
|| mFvLength
== 0) {
730 Status
= VerifyFv (mFvHeader
);
731 if (EFI_ERROR (Status
)) {
735 // Verify input parameters.
737 if (ErasePolarity
== NULL
) {
738 return EFI_INVALID_PARAMETER
;
741 if (mFvHeader
->Attributes
& EFI_FVB_ERASE_POLARITY
) {
742 *ErasePolarity
= TRUE
;
744 *ErasePolarity
= FALSE
;
752 IN BOOLEAN ErasePolarity
,
753 IN EFI_FFS_FILE_HEADER
*FfsHeader
759 This function returns a the highest state bit in the FFS that is set.
760 It in no way validate the FFS file.
764 ErasePolarity The erase polarity for the file state bits.
765 FfsHeader Pointer to a FFS file.
769 UINT8 The hightest set state of the file.
776 FileState
= FfsHeader
->State
;
779 FileState
= (UINT8
)~FileState
;
783 while (HighestBit
!= 0 && (HighestBit
& FileState
) == 0) {