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"
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
>= (UINTN
) mFvHeader
+ mFvLength
- sizeof (EFI_FFS_FILE_HEADER
)) {
188 *NextFile
= CurrentFile
;
193 // Verify current file is in range
195 if (((UINTN
) CurrentFile
< (UINTN
) mFvHeader
+ sizeof (EFI_FIRMWARE_VOLUME_HEADER
)) ||
196 ((UINTN
) CurrentFile
>= (UINTN
) mFvHeader
+ mFvLength
- sizeof (EFI_FIRMWARE_VOLUME_HEADER
))
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
>= (UINTN
) mFvHeader
+ mFvLength
- sizeof (EFI_FFS_FILE_HEADER
)) {
213 // Verify file is valid
215 Status
= VerifyFfsFile (*NextFile
);
216 if (EFI_ERROR (Status
)) {
218 // no more files in this FV
229 IN EFI_GUID
*FileName
,
230 OUT EFI_FFS_FILE_HEADER
**File
236 Find a file by name. The function will return NULL if the file is not found.
240 FileName The GUID file name of the file to search for.
241 File Return pointer. In the case of an error, contents are undefined.
245 EFI_SUCCESS The function completed successfully.
246 EFI_ABORTED An error was encountered.
247 EFI_INVALID_PARAMETER One of the parameters was NULL.
251 EFI_FFS_FILE_HEADER
*CurrentFile
;
255 // Verify library has been initialized.
257 if (mFvHeader
== NULL
|| mFvLength
== 0) {
261 // Verify input parameters
263 if (FileName
== NULL
|| File
== NULL
) {
264 return EFI_INVALID_PARAMETER
;
269 Status
= VerifyFv (mFvHeader
);
270 if (EFI_ERROR (Status
)) {
274 // Get the first file
276 Status
= GetNextFile (NULL
, &CurrentFile
);
277 if (EFI_ERROR (Status
)) {
278 Error (NULL
, 0, 0, "error parsing the FV", NULL
);
282 // Loop as long as we have a valid file
284 while (CurrentFile
) {
285 if (!CompareGuid (&CurrentFile
->Name
, FileName
)) {
290 Status
= GetNextFile (CurrentFile
, &CurrentFile
);
291 if (EFI_ERROR (Status
)) {
292 Error (NULL
, 0, 0, "error parsing the FV", NULL
);
297 // File not found in this FV.
305 IN EFI_FV_FILETYPE FileType
,
307 OUT EFI_FFS_FILE_HEADER
**File
313 Find a file by type and instance. An instance of 1 is the first instance.
314 The function will return NULL if a matching file cannot be found.
315 File type EFI_FV_FILETYPE_ALL means any file type is valid.
319 FileType Type of file to search for.
320 Instance Instace of the file type to return.
321 File Return pointer. In the case of an error, contents are undefined.
325 EFI_SUCCESS The function completed successfully.
326 EFI_ABORTED An error was encountered.
327 EFI_INVALID_PARAMETER One of the parameters was NULL.
331 EFI_FFS_FILE_HEADER
*CurrentFile
;
336 // Verify library has been initialized.
338 if (mFvHeader
== NULL
|| mFvLength
== 0) {
342 // Verify input parameters
345 return EFI_INVALID_PARAMETER
;
350 Status
= VerifyFv (mFvHeader
);
351 if (EFI_ERROR (Status
)) {
355 // Initialize the number of matching files found.
360 // Get the first file
362 Status
= GetNextFile (NULL
, &CurrentFile
);
363 if (EFI_ERROR (Status
)) {
364 Error (NULL
, 0, 0, "error parsing FV", NULL
);
368 // Loop as long as we have a valid file
370 while (CurrentFile
) {
371 if (FileType
== EFI_FV_FILETYPE_ALL
|| CurrentFile
->Type
== FileType
) {
375 if (FileCount
== Instance
) {
380 Status
= GetNextFile (CurrentFile
, &CurrentFile
);
381 if (EFI_ERROR (Status
)) {
382 Error (NULL
, 0, 0, "error parsing the FV", NULL
);
393 IN EFI_FFS_FILE_HEADER
*File
,
394 IN EFI_SECTION_TYPE SectionType
,
396 OUT EFI_FILE_SECTION_POINTER
*Section
402 Find a section in a file by type and instance. An instance of 1 is the first
403 instance. The function will return NULL if a matching section cannot be found.
404 The function will not handle encapsulating sections.
408 File The file to search.
409 SectionType Type of file to search for.
410 Instance Instace of the section to return.
411 Section Return pointer. In the case of an error, contents are undefined.
415 EFI_SUCCESS The function completed successfully.
416 EFI_ABORTED An error was encountered.
417 EFI_INVALID_PARAMETER One of the parameters was NULL.
418 EFI_NOT_FOUND No found.
421 EFI_FILE_SECTION_POINTER CurrentSection
;
426 // Verify input parameters
428 if (File
== NULL
|| Instance
== 0) {
429 return EFI_INVALID_PARAMETER
;
434 Status
= VerifyFfsFile (File
);
435 if (EFI_ERROR (Status
)) {
436 Error (NULL
, 0, 0, "invalid FFS file", NULL
);
440 // Initialize the number of matching sections found.
445 // Get the first section
447 CurrentSection
.CommonHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINTN
) File
+ sizeof (EFI_FFS_FILE_HEADER
));
450 // Loop as long as we have a valid file
452 while ((UINTN
) CurrentSection
.CommonHeader
< (UINTN
) File
+ GetLength (File
->Size
)) {
453 if (CurrentSection
.CommonHeader
->Type
== SectionType
) {
457 if (SectionCount
== Instance
) {
458 *Section
= CurrentSection
;
462 // Find next section (including compensating for alignment issues.
464 CurrentSection
.CommonHeader
= (EFI_COMMON_SECTION_HEADER
*) ((((UINTN
) CurrentSection
.CommonHeader
) + GetLength (CurrentSection
.CommonHeader
->Size
) + 0x03) & (-1 << 2));
469 (*Section
).Code16Section
= NULL
;
470 return EFI_NOT_FOUND
;
473 // will not parse compressed sections
477 IN EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
483 Verify the current pointer points to a valid FV header.
487 FvHeader Pointer to an alleged FV file.
491 EFI_SUCCESS The FV header is valid.
492 EFI_VOLUME_CORRUPTED The FV header is not valid.
493 EFI_INVALID_PARAMETER A required parameter was NULL.
494 EFI_ABORTED Operation aborted.
501 // Verify input parameters
503 if (FvHeader
== NULL
) {
504 return EFI_INVALID_PARAMETER
;
507 if (FvHeader
->Signature
!= EFI_FVH_SIGNATURE
) {
508 Error (NULL
, 0, 0, "invalid FV header signature", NULL
);
509 return EFI_VOLUME_CORRUPTED
;
512 // Verify header checksum
514 Checksum
= CalculateSum16 ((UINT16
*) FvHeader
, FvHeader
->HeaderLength
/ sizeof (UINT16
));
517 Error (NULL
, 0, 0, "invalid FV header checksum", NULL
);
526 IN EFI_FFS_FILE_HEADER
*FfsHeader
532 Verify the current pointer points to a FFS file header.
536 FfsHeader Pointer to an alleged FFS file.
540 EFI_SUCCESS The Ffs header is valid.
541 EFI_NOT_FOUND This "file" is the beginning of free space.
542 EFI_VOLUME_CORRUPTED The Ffs header is not valid.
543 EFI_ABORTED The erase polarity is not known.
547 BOOLEAN ErasePolarity
;
549 EFI_FFS_FILE_HEADER BlankHeader
;
552 UINT32 OccupiedFileLength
;
553 EFI_FFS_FILE_TAIL
*Tail
;
556 UINT8 FileGuidString
[80];
559 // Verify library has been initialized.
561 if (mFvHeader
== NULL
|| mFvLength
== 0) {
567 Status
= VerifyFv (mFvHeader
);
568 if (EFI_ERROR (Status
)) {
572 // Get the erase polarity.
574 Status
= GetErasePolarity (&ErasePolarity
);
575 if (EFI_ERROR (Status
)) {
579 // Check if we have free space
582 memset (&BlankHeader
, -1, sizeof (EFI_FFS_FILE_HEADER
));
584 memset (&BlankHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
587 if (memcmp (&BlankHeader
, FfsHeader
, sizeof (EFI_FFS_FILE_HEADER
)) == 0) {
588 return EFI_NOT_FOUND
;
591 // Convert the GUID to a string so we can at least report which file
592 // if we find an error.
594 PrintGuidToBuffer (&FfsHeader
->Name
, FileGuidString
, sizeof (FileGuidString
), TRUE
);
595 if (FfsHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
596 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
601 // Verify file header checksum
603 SavedState
= FfsHeader
->State
;
604 FfsHeader
->State
= 0;
605 SavedChecksum
= FfsHeader
->IntegrityCheck
.Checksum
.File
;
606 FfsHeader
->IntegrityCheck
.Checksum
.File
= 0;
607 Checksum
= CalculateSum8 ((UINT8
*) FfsHeader
, sizeof (EFI_FFS_FILE_HEADER
));
608 FfsHeader
->State
= SavedState
;
609 FfsHeader
->IntegrityCheck
.Checksum
.File
= SavedChecksum
;
611 Error (NULL
, 0, 0, FileGuidString
, "invalid FFS file header checksum");
615 // Verify file checksum
617 if (FfsHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
619 // Verify file data checksum
621 FileLength
= GetLength (FfsHeader
->Size
);
622 OccupiedFileLength
= (FileLength
+ 0x07) & (-1 << 3);
623 Checksum
= CalculateSum8 ((UINT8
*) FfsHeader
, FileLength
- TailSize
);
624 Checksum
= (UINT8
) (Checksum
- FfsHeader
->State
);
626 Error (NULL
, 0, 0, FileGuidString
, "invalid FFS file checksum");
631 // File does not have a checksum
632 // Verify contents are 0x5A as spec'd
634 if (FfsHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
635 Error (NULL
, 0, 0, FileGuidString
, "invalid fixed FFS file header checksum");
640 // Check if the tail is present and verify it if it is.
642 if (FfsHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
644 // Verify tail is complement of integrity check field in the header.
646 Tail
= (EFI_FFS_FILE_TAIL
*) ((UINTN
) FfsHeader
+ GetLength (FfsHeader
->Size
) - sizeof (EFI_FFS_FILE_TAIL
));
647 if (FfsHeader
->IntegrityCheck
.TailReference
!= (EFI_FFS_FILE_TAIL
)~(*Tail
)) {
648 Error (NULL
, 0, 0, FileGuidString
, "invalid FFS file tail");
658 UINT8
*ThreeByteLength
664 Converts a three byte length value into a UINT32.
668 ThreeByteLength Pointer to the first of the 3 byte length.
672 UINT32 Size of the section
678 if (ThreeByteLength
== NULL
) {
682 Length
= *((UINT32
*) ThreeByteLength
);
683 Length
= Length
& 0x00FFFFFF;
690 OUT BOOLEAN
*ErasePolarity
696 This function returns with the FV erase polarity. If the erase polarity
697 for a bit is 1, the function return TRUE.
701 ErasePolarity A pointer to the erase polarity.
705 EFI_SUCCESS The function completed successfully.
706 EFI_INVALID_PARAMETER One of the input parameters was invalid.
707 EFI_ABORTED Operation aborted.
714 // Verify library has been initialized.
716 if (mFvHeader
== NULL
|| mFvLength
== 0) {
722 Status
= VerifyFv (mFvHeader
);
723 if (EFI_ERROR (Status
)) {
727 // Verify input parameters.
729 if (ErasePolarity
== NULL
) {
730 return EFI_INVALID_PARAMETER
;
733 if (mFvHeader
->Attributes
& EFI_FVB_ERASE_POLARITY
) {
734 *ErasePolarity
= TRUE
;
736 *ErasePolarity
= FALSE
;
744 IN BOOLEAN ErasePolarity
,
745 IN EFI_FFS_FILE_HEADER
*FfsHeader
751 This function returns a the highest state bit in the FFS that is set.
752 It in no way validate the FFS file.
756 ErasePolarity The erase polarity for the file state bits.
757 FfsHeader Pointer to a FFS file.
761 UINT8 The hightest set state of the file.
768 FileState
= FfsHeader
->State
;
771 FileState
= (UINT8
)~FileState
;
775 while (HighestBit
!= 0 && (HighestBit
& FileState
) == 0) {