3 Copyright (c) 2004 - 2006, 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
;
257 // Verify library has been initialized.
259 if (mFvHeader
== NULL
|| mFvLength
== 0) {
263 // Verify input parameters
265 if (FileName
== NULL
|| File
== NULL
) {
266 return EFI_INVALID_PARAMETER
;
271 Status
= VerifyFv (mFvHeader
);
272 if (EFI_ERROR (Status
)) {
276 // Get the first file
278 Status
= GetNextFile (NULL
, &CurrentFile
);
279 if (EFI_ERROR (Status
)) {
280 Error (NULL
, 0, 0, "error parsing the FV", NULL
);
284 // Loop as long as we have a valid file
286 while (CurrentFile
) {
287 if (!CompareGuid (&CurrentFile
->Name
, FileName
)) {
292 Status
= GetNextFile (CurrentFile
, &CurrentFile
);
293 if (EFI_ERROR (Status
)) {
294 Error (NULL
, 0, 0, "error parsing the FV", NULL
);
299 // File not found in this FV.
307 IN EFI_FV_FILETYPE FileType
,
309 OUT EFI_FFS_FILE_HEADER
**File
315 Find a file by type and instance. An instance of 1 is the first instance.
316 The function will return NULL if a matching file cannot be found.
317 File type EFI_FV_FILETYPE_ALL means any file type is valid.
321 FileType Type of file to search for.
322 Instance Instace of the file type to return.
323 File Return pointer. In the case of an error, contents are undefined.
327 EFI_SUCCESS The function completed successfully.
328 EFI_ABORTED An error was encountered.
329 EFI_INVALID_PARAMETER One of the parameters was NULL.
333 EFI_FFS_FILE_HEADER
*CurrentFile
;
338 // Verify library has been initialized.
340 if (mFvHeader
== NULL
|| mFvLength
== 0) {
344 // Verify input parameters
347 return EFI_INVALID_PARAMETER
;
352 Status
= VerifyFv (mFvHeader
);
353 if (EFI_ERROR (Status
)) {
357 // Initialize the number of matching files found.
362 // Get the first file
364 Status
= GetNextFile (NULL
, &CurrentFile
);
365 if (EFI_ERROR (Status
)) {
366 Error (NULL
, 0, 0, "error parsing FV", NULL
);
370 // Loop as long as we have a valid file
372 while (CurrentFile
) {
373 if (FileType
== EFI_FV_FILETYPE_ALL
|| CurrentFile
->Type
== FileType
) {
377 if (FileCount
== Instance
) {
382 Status
= GetNextFile (CurrentFile
, &CurrentFile
);
383 if (EFI_ERROR (Status
)) {
384 Error (NULL
, 0, 0, "error parsing the FV", NULL
);
395 IN EFI_FFS_FILE_HEADER
*File
,
396 IN EFI_SECTION_TYPE SectionType
,
398 OUT EFI_FILE_SECTION_POINTER
*Section
404 Find a section in a file by type and instance. An instance of 1 is the first
405 instance. The function will return NULL if a matching section cannot be found.
406 The function will not handle encapsulating sections.
410 File The file to search.
411 SectionType Type of file to search for.
412 Instance Instace of the section to return.
413 Section Return pointer. In the case of an error, contents are undefined.
417 EFI_SUCCESS The function completed successfully.
418 EFI_ABORTED An error was encountered.
419 EFI_INVALID_PARAMETER One of the parameters was NULL.
420 EFI_NOT_FOUND No found.
423 EFI_FILE_SECTION_POINTER CurrentSection
;
428 // Verify input parameters
430 if (File
== NULL
|| Instance
== 0) {
431 return EFI_INVALID_PARAMETER
;
436 Status
= VerifyFfsFile (File
);
437 if (EFI_ERROR (Status
)) {
438 Error (NULL
, 0, 0, "invalid FFS file", NULL
);
442 // Initialize the number of matching sections found.
447 // Get the first section
449 CurrentSection
.CommonHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINTN
) File
+ sizeof (EFI_FFS_FILE_HEADER
));
452 // Loop as long as we have a valid file
454 while ((UINTN
) CurrentSection
.CommonHeader
< (UINTN
) File
+ GetLength (File
->Size
)) {
455 if (CurrentSection
.CommonHeader
->Type
== SectionType
) {
459 if (SectionCount
== Instance
) {
460 *Section
= CurrentSection
;
464 // Find next section (including compensating for alignment issues.
466 CurrentSection
.CommonHeader
= (EFI_COMMON_SECTION_HEADER
*) ((((UINTN
) CurrentSection
.CommonHeader
) + GetLength (CurrentSection
.CommonHeader
->Size
) + 0x03) & (-1 << 2));
471 (*Section
).Code16Section
= NULL
;
472 return EFI_NOT_FOUND
;
475 // will not parse compressed sections
479 IN EFI_FIRMWARE_VOLUME_HEADER
*FvHeader
485 Verify the current pointer points to a valid FV header.
489 FvHeader Pointer to an alleged FV file.
493 EFI_SUCCESS The FV header is valid.
494 EFI_VOLUME_CORRUPTED The FV header is not valid.
495 EFI_INVALID_PARAMETER A required parameter was NULL.
496 EFI_ABORTED Operation aborted.
503 // Verify input parameters
505 if (FvHeader
== NULL
) {
506 return EFI_INVALID_PARAMETER
;
509 if (FvHeader
->Signature
!= EFI_FVH_SIGNATURE
) {
510 Error (NULL
, 0, 0, "invalid FV header signature", NULL
);
511 return EFI_VOLUME_CORRUPTED
;
514 // Verify header checksum
516 Checksum
= CalculateSum16 ((UINT16
*) FvHeader
, FvHeader
->HeaderLength
/ sizeof (UINT16
));
519 Error (NULL
, 0, 0, "invalid FV header checksum", NULL
);
528 IN EFI_FFS_FILE_HEADER
*FfsHeader
534 Verify the current pointer points to a FFS file header.
538 FfsHeader Pointer to an alleged FFS file.
542 EFI_SUCCESS The Ffs header is valid.
543 EFI_NOT_FOUND This "file" is the beginning of free space.
544 EFI_VOLUME_CORRUPTED The Ffs header is not valid.
545 EFI_ABORTED The erase polarity is not known.
549 BOOLEAN ErasePolarity
;
551 EFI_FFS_FILE_HEADER BlankHeader
;
554 UINT32 OccupiedFileLength
;
555 EFI_FFS_FILE_TAIL
*Tail
;
558 UINT8 FileGuidString
[80];
561 // Verify library has been initialized.
563 if (mFvHeader
== NULL
|| mFvLength
== 0) {
569 Status
= VerifyFv (mFvHeader
);
570 if (EFI_ERROR (Status
)) {
574 // Get the erase polarity.
576 Status
= GetErasePolarity (&ErasePolarity
);
577 if (EFI_ERROR (Status
)) {
581 // Check if we have free space
584 memset (&BlankHeader
, -1, sizeof (EFI_FFS_FILE_HEADER
));
586 memset (&BlankHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
589 if (memcmp (&BlankHeader
, FfsHeader
, sizeof (EFI_FFS_FILE_HEADER
)) == 0) {
590 return EFI_NOT_FOUND
;
593 // Convert the GUID to a string so we can at least report which file
594 // if we find an error.
596 PrintGuidToBuffer (&FfsHeader
->Name
, FileGuidString
, sizeof (FileGuidString
), TRUE
);
597 if (FfsHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
598 TailSize
= sizeof (EFI_FFS_FILE_TAIL
);
603 // Verify file header checksum
605 SavedState
= FfsHeader
->State
;
606 FfsHeader
->State
= 0;
607 SavedChecksum
= FfsHeader
->IntegrityCheck
.Checksum
.File
;
608 FfsHeader
->IntegrityCheck
.Checksum
.File
= 0;
609 Checksum
= CalculateSum8 ((UINT8
*) FfsHeader
, sizeof (EFI_FFS_FILE_HEADER
));
610 FfsHeader
->State
= SavedState
;
611 FfsHeader
->IntegrityCheck
.Checksum
.File
= SavedChecksum
;
613 Error (NULL
, 0, 0, FileGuidString
, "invalid FFS file header checksum");
617 // Verify file checksum
619 if (FfsHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
621 // Verify file data checksum
623 FileLength
= GetLength (FfsHeader
->Size
);
624 OccupiedFileLength
= (FileLength
+ 0x07) & (-1 << 3);
625 Checksum
= CalculateSum8 ((UINT8
*) FfsHeader
, FileLength
- TailSize
);
626 Checksum
= (UINT8
) (Checksum
- FfsHeader
->State
);
628 Error (NULL
, 0, 0, FileGuidString
, "invalid FFS file checksum");
633 // File does not have a checksum
634 // Verify contents are 0x5A as spec'd
636 if (FfsHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
637 Error (NULL
, 0, 0, FileGuidString
, "invalid fixed FFS file header checksum");
642 // Check if the tail is present and verify it if it is.
644 if (FfsHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
646 // Verify tail is complement of integrity check field in the header.
648 Tail
= (EFI_FFS_FILE_TAIL
*) ((UINTN
) FfsHeader
+ GetLength (FfsHeader
->Size
) - sizeof (EFI_FFS_FILE_TAIL
));
649 if (FfsHeader
->IntegrityCheck
.TailReference
!= (EFI_FFS_FILE_TAIL
)~(*Tail
)) {
650 Error (NULL
, 0, 0, FileGuidString
, "invalid FFS file tail");
660 UINT8
*ThreeByteLength
666 Converts a three byte length value into a UINT32.
670 ThreeByteLength Pointer to the first of the 3 byte length.
674 UINT32 Size of the section
680 if (ThreeByteLength
== NULL
) {
684 Length
= *((UINT32
*) ThreeByteLength
);
685 Length
= Length
& 0x00FFFFFF;
692 OUT BOOLEAN
*ErasePolarity
698 This function returns with the FV erase polarity. If the erase polarity
699 for a bit is 1, the function return TRUE.
703 ErasePolarity A pointer to the erase polarity.
707 EFI_SUCCESS The function completed successfully.
708 EFI_INVALID_PARAMETER One of the input parameters was invalid.
709 EFI_ABORTED Operation aborted.
716 // Verify library has been initialized.
718 if (mFvHeader
== NULL
|| mFvLength
== 0) {
724 Status
= VerifyFv (mFvHeader
);
725 if (EFI_ERROR (Status
)) {
729 // Verify input parameters.
731 if (ErasePolarity
== NULL
) {
732 return EFI_INVALID_PARAMETER
;
735 if (mFvHeader
->Attributes
& EFI_FVB_ERASE_POLARITY
) {
736 *ErasePolarity
= TRUE
;
738 *ErasePolarity
= FALSE
;
746 IN BOOLEAN ErasePolarity
,
747 IN EFI_FFS_FILE_HEADER
*FfsHeader
753 This function returns a the highest state bit in the FFS that is set.
754 It in no way validate the FFS file.
758 ErasePolarity The erase polarity for the file state bits.
759 FfsHeader Pointer to a FFS file.
763 UINT8 The hightest set state of the file.
770 FileState
= FfsHeader
->State
;
773 FileState
= (UINT8
)~FileState
;
777 while (HighestBit
!= 0 && (HighestBit
& FileState
) == 0) {