From feccee87a78e68d575dbdf44b34ca0cb5a21ea8d Mon Sep 17 00:00:00 2001 From: lhauch Date: Thu, 5 Oct 2006 23:12:07 +0000 Subject: Restructuring for better separation of Tool packages. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1674 6f19259b-4bc3-4df7-8a09-765794883524 --- Tools/CodeTools/TianoTools/Common/FvLib.c | 780 ++++++++++++++++++++++++++++++ 1 file changed, 780 insertions(+) create mode 100644 Tools/CodeTools/TianoTools/Common/FvLib.c (limited to 'Tools/CodeTools/TianoTools/Common/FvLib.c') diff --git a/Tools/CodeTools/TianoTools/Common/FvLib.c b/Tools/CodeTools/TianoTools/Common/FvLib.c new file mode 100644 index 0000000000..e8d62791f3 --- /dev/null +++ b/Tools/CodeTools/TianoTools/Common/FvLib.c @@ -0,0 +1,780 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + FvLib.c + +Abstract: + + These functions assist in parsing and manipulating a Firmware Volume. + +--*/ + +// +// Include files +// +#include "FvLib.h" +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" + +// +// Module global variables +// +EFI_FIRMWARE_VOLUME_HEADER *mFvHeader = NULL; +UINT32 mFvLength = 0; + +// +// External function implementations +// +EFI_STATUS +InitializeFvLib ( + IN VOID *Fv, + IN UINT32 FvLength + ) +/*++ + +Routine Description: + + This initializes the FV lib with a pointer to the FV and length. It does not + verify the FV in any way. + +Arguments: + + Fv Buffer containing the FV. + FvLength Length of the FV + +Returns: + + EFI_SUCCESS Function Completed successfully. + EFI_INVALID_PARAMETER A required parameter was NULL. + +--*/ +{ + // + // Verify input arguments + // + if (Fv == NULL) { + return EFI_INVALID_PARAMETER; + } + + mFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Fv; + mFvLength = FvLength; + + return EFI_SUCCESS; +} + +EFI_STATUS +GetFvHeader ( + OUT EFI_FIRMWARE_VOLUME_HEADER **FvHeader, + OUT UINT32 *FvLength + ) +/*++ + +Routine Description: + + This function returns a pointer to the current FV and the size. + +Arguments: + + FvHeader Pointer to the FV buffer. + FvLength Length of the FV + +Returns: + + EFI_SUCCESS Function Completed successfully. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_ABORTED The library needs to be initialized. + +--*/ +{ + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify input arguments + // + if (FvHeader == NULL) { + return EFI_INVALID_PARAMETER; + } + + *FvHeader = mFvHeader; + return EFI_SUCCESS; +} + +EFI_STATUS +GetNextFile ( + IN EFI_FFS_FILE_HEADER *CurrentFile, + OUT EFI_FFS_FILE_HEADER **NextFile + ) +/*++ + +Routine Description: + + This function returns the next file. If the current file is NULL, it returns + the first file in the FV. If the function returns EFI_SUCCESS and the file + pointer is NULL, then there are no more files in the FV. + +Arguments: + + CurrentFile Pointer to the current file, must be within the current FV. + NextFile Pointer to the next file in the FV. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_INVALID_PARAMETER A required parameter was NULL or is out of range. + EFI_ABORTED The library needs to be initialized. + +--*/ +{ + EFI_STATUS Status; + + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify input arguments + // + if (NextFile == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Verify FV header + // + Status = VerifyFv (mFvHeader); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Get first file + // + if (CurrentFile == NULL) { + CurrentFile = (EFI_FFS_FILE_HEADER *) ((UINTN) mFvHeader + mFvHeader->HeaderLength); + + // + // Verify file is valid + // + Status = VerifyFfsFile (CurrentFile); + if (EFI_ERROR (Status)) { + // + // no files in this FV + // + *NextFile = NULL; + return EFI_SUCCESS; + } else { + // + // Verify file is in this FV. + // + if ((UINTN) CurrentFile >= (UINTN) mFvHeader + mFvLength - sizeof (EFI_FFS_FILE_HEADER)) { + *NextFile = NULL; + return EFI_SUCCESS; + } + + *NextFile = CurrentFile; + return EFI_SUCCESS; + } + } + // + // Verify current file is in range + // + if (((UINTN) CurrentFile < (UINTN) mFvHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER)) || + ((UINTN) CurrentFile >= (UINTN) mFvHeader + mFvLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) + ) { + return EFI_INVALID_PARAMETER; + } + // + // Get next file, compensate for 8 byte alignment if necessary. + // + *NextFile = (EFI_FFS_FILE_HEADER *) (((UINTN) CurrentFile + GetLength (CurrentFile->Size) + 0x07) & (-1 << 3)); + + // + // Verify file is in this FV. + // + if ((UINTN) *NextFile >= (UINTN) mFvHeader + mFvLength - sizeof (EFI_FFS_FILE_HEADER)) { + *NextFile = NULL; + return EFI_SUCCESS; + } + // + // Verify file is valid + // + Status = VerifyFfsFile (*NextFile); + if (EFI_ERROR (Status)) { + // + // no more files in this FV + // + *NextFile = NULL; + return EFI_SUCCESS; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetFileByName ( + IN EFI_GUID *FileName, + OUT EFI_FFS_FILE_HEADER **File + ) +/*++ + +Routine Description: + + Find a file by name. The function will return NULL if the file is not found. + +Arguments: + + FileName The GUID file name of the file to search for. + File Return pointer. In the case of an error, contents are undefined. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_ABORTED An error was encountered. + EFI_INVALID_PARAMETER One of the parameters was NULL. + +--*/ +{ + EFI_FFS_FILE_HEADER *CurrentFile; + EFI_STATUS Status; + + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify input parameters + // + if (FileName == NULL || File == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Verify FV header + // + Status = VerifyFv (mFvHeader); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Get the first file + // + Status = GetNextFile (NULL, &CurrentFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "error parsing the FV", NULL); + return EFI_ABORTED; + } + // + // Loop as long as we have a valid file + // + while (CurrentFile) { + if (!CompareGuid (&CurrentFile->Name, FileName)) { + *File = CurrentFile; + return EFI_SUCCESS; + } + + Status = GetNextFile (CurrentFile, &CurrentFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "error parsing the FV", NULL); + return EFI_ABORTED; + } + } + // + // File not found in this FV. + // + *File = NULL; + return EFI_SUCCESS; +} + +EFI_STATUS +GetFileByType ( + IN EFI_FV_FILETYPE FileType, + IN UINTN Instance, + OUT EFI_FFS_FILE_HEADER **File + ) +/*++ + +Routine Description: + + Find a file by type and instance. An instance of 1 is the first instance. + The function will return NULL if a matching file cannot be found. + File type EFI_FV_FILETYPE_ALL means any file type is valid. + +Arguments: + + FileType Type of file to search for. + Instance Instace of the file type to return. + File Return pointer. In the case of an error, contents are undefined. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_ABORTED An error was encountered. + EFI_INVALID_PARAMETER One of the parameters was NULL. + +--*/ +{ + EFI_FFS_FILE_HEADER *CurrentFile; + EFI_STATUS Status; + UINTN FileCount; + + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify input parameters + // + if (File == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Verify FV header + // + Status = VerifyFv (mFvHeader); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Initialize the number of matching files found. + // + FileCount = 0; + + // + // Get the first file + // + Status = GetNextFile (NULL, &CurrentFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "error parsing FV", NULL); + return EFI_ABORTED; + } + // + // Loop as long as we have a valid file + // + while (CurrentFile) { + if (FileType == EFI_FV_FILETYPE_ALL || CurrentFile->Type == FileType) { + FileCount++; + } + + if (FileCount == Instance) { + *File = CurrentFile; + return EFI_SUCCESS; + } + + Status = GetNextFile (CurrentFile, &CurrentFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "error parsing the FV", NULL); + return EFI_ABORTED; + } + } + + *File = NULL; + return EFI_SUCCESS; +} + +EFI_STATUS +GetSectionByType ( + IN EFI_FFS_FILE_HEADER *File, + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT EFI_FILE_SECTION_POINTER *Section + ) +/*++ + +Routine Description: + + Find a section in a file by type and instance. An instance of 1 is the first + instance. The function will return NULL if a matching section cannot be found. + The function will not handle encapsulating sections. + +Arguments: + + File The file to search. + SectionType Type of file to search for. + Instance Instace of the section to return. + Section Return pointer. In the case of an error, contents are undefined. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_ABORTED An error was encountered. + EFI_INVALID_PARAMETER One of the parameters was NULL. + EFI_NOT_FOUND No found. +--*/ +{ + EFI_FILE_SECTION_POINTER CurrentSection; + EFI_STATUS Status; + UINTN SectionCount; + + // + // Verify input parameters + // + if (File == NULL || Instance == 0) { + return EFI_INVALID_PARAMETER; + } + // + // Verify FFS header + // + Status = VerifyFfsFile (File); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "invalid FFS file", NULL); + return EFI_ABORTED; + } + // + // Initialize the number of matching sections found. + // + SectionCount = 0; + + // + // Get the first section + // + CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + sizeof (EFI_FFS_FILE_HEADER)); + + // + // Loop as long as we have a valid file + // + while ((UINTN) CurrentSection.CommonHeader < (UINTN) File + GetLength (File->Size)) { + if (CurrentSection.CommonHeader->Type == SectionType) { + SectionCount++; + } + + if (SectionCount == Instance) { + *Section = CurrentSection; + return EFI_SUCCESS; + } + // + // Find next section (including compensating for alignment issues. + // + CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetLength (CurrentSection.CommonHeader->Size) + 0x03) & (-1 << 2)); + } + // + // Section not found + // + (*Section).Code16Section = NULL; + return EFI_NOT_FOUND; +} +// +// will not parse compressed sections +// +EFI_STATUS +VerifyFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ) +/*++ + +Routine Description: + + Verify the current pointer points to a valid FV header. + +Arguments: + + FvHeader Pointer to an alleged FV file. + +Returns: + + EFI_SUCCESS The FV header is valid. + EFI_VOLUME_CORRUPTED The FV header is not valid. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_ABORTED Operation aborted. + +--*/ +{ + UINT16 Checksum; + + // + // Verify input parameters + // + if (FvHeader == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (FvHeader->Signature != EFI_FVH_SIGNATURE) { + Error (NULL, 0, 0, "invalid FV header signature", NULL); + return EFI_VOLUME_CORRUPTED; + } + // + // Verify header checksum + // + Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + + if (Checksum != 0) { + Error (NULL, 0, 0, "invalid FV header checksum", NULL); + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +VerifyFfsFile ( + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + + Verify the current pointer points to a FFS file header. + +Arguments: + + FfsHeader Pointer to an alleged FFS file. + +Returns: + + EFI_SUCCESS The Ffs header is valid. + EFI_NOT_FOUND This "file" is the beginning of free space. + EFI_VOLUME_CORRUPTED The Ffs header is not valid. + EFI_ABORTED The erase polarity is not known. + +--*/ +{ + BOOLEAN ErasePolarity; + EFI_STATUS Status; + EFI_FFS_FILE_HEADER BlankHeader; + UINT8 Checksum; + UINT32 FileLength; + UINT32 OccupiedFileLength; + EFI_FFS_FILE_TAIL *Tail; + UINT8 SavedChecksum; + UINT8 SavedState; + UINT8 FileGuidString[80]; + UINT32 TailSize; + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify FV header + // + Status = VerifyFv (mFvHeader); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Get the erase polarity. + // + Status = GetErasePolarity (&ErasePolarity); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Check if we have free space + // + if (ErasePolarity) { + memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER)); + } else { + memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER)); + } + + if (memcmp (&BlankHeader, FfsHeader, sizeof (EFI_FFS_FILE_HEADER)) == 0) { + return EFI_NOT_FOUND; + } + // + // Convert the GUID to a string so we can at least report which file + // if we find an error. + // + PrintGuidToBuffer (&FfsHeader->Name, FileGuidString, sizeof (FileGuidString), TRUE); + if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailSize = sizeof (EFI_FFS_FILE_TAIL); + } else { + TailSize = 0; + } + // + // Verify file header checksum + // + SavedState = FfsHeader->State; + FfsHeader->State = 0; + SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File; + FfsHeader->IntegrityCheck.Checksum.File = 0; + Checksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER)); + FfsHeader->State = SavedState; + FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum; + if (Checksum != 0) { + Error (NULL, 0, 0, FileGuidString, "invalid FFS file header checksum"); + return EFI_ABORTED; + } + // + // Verify file checksum + // + if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) { + // + // Verify file data checksum + // + FileLength = GetLength (FfsHeader->Size); + OccupiedFileLength = (FileLength + 0x07) & (-1 << 3); + Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FileLength - TailSize); + Checksum = (UINT8) (Checksum - FfsHeader->State); + if (Checksum != 0) { + Error (NULL, 0, 0, FileGuidString, "invalid FFS file checksum"); + return EFI_ABORTED; + } + } else { + // + // File does not have a checksum + // Verify contents are 0x5A as spec'd + // + if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) { + Error (NULL, 0, 0, FileGuidString, "invalid fixed FFS file header checksum"); + return EFI_ABORTED; + } + } + // + // Check if the tail is present and verify it if it is. + // + if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + // + // Verify tail is complement of integrity check field in the header. + // + Tail = (EFI_FFS_FILE_TAIL *) ((UINTN) FfsHeader + GetLength (FfsHeader->Size) - sizeof (EFI_FFS_FILE_TAIL)); + if (FfsHeader->IntegrityCheck.TailReference != (EFI_FFS_FILE_TAIL)~(*Tail)) { + Error (NULL, 0, 0, FileGuidString, "invalid FFS file tail"); + return EFI_ABORTED; + } + } + + return EFI_SUCCESS; +} + +UINT32 +GetLength ( + UINT8 *ThreeByteLength + ) +/*++ + +Routine Description: + + Converts a three byte length value into a UINT32. + +Arguments: + + ThreeByteLength Pointer to the first of the 3 byte length. + +Returns: + + UINT32 Size of the section + +--*/ +{ + UINT32 Length; + + if (ThreeByteLength == NULL) { + return 0; + } + + Length = *((UINT32 *) ThreeByteLength); + Length = Length & 0x00FFFFFF; + + return Length; +} + +EFI_STATUS +GetErasePolarity ( + OUT BOOLEAN *ErasePolarity + ) +/*++ + +Routine Description: + + This function returns with the FV erase polarity. If the erase polarity + for a bit is 1, the function return TRUE. + +Arguments: + + ErasePolarity A pointer to the erase polarity. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED Operation aborted. + +--*/ +{ + EFI_STATUS Status; + + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify FV header + // + Status = VerifyFv (mFvHeader); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Verify input parameters. + // + if (ErasePolarity == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (mFvHeader->Attributes & EFI_FVB_ERASE_POLARITY) { + *ErasePolarity = TRUE; + } else { + *ErasePolarity = FALSE; + } + + return EFI_SUCCESS; +} + +UINT8 +GetFileState ( + IN BOOLEAN ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + + This function returns a the highest state bit in the FFS that is set. + It in no way validate the FFS file. + +Arguments: + + ErasePolarity The erase polarity for the file state bits. + FfsHeader Pointer to a FFS file. + +Returns: + + UINT8 The hightest set state of the file. + +--*/ +{ + UINT8 FileState; + UINT8 HighestBit; + + FileState = FfsHeader->State; + + if (ErasePolarity) { + FileState = (UINT8)~FileState; + } + + HighestBit = 0x80; + while (HighestBit != 0 && (HighestBit & FileState) == 0) { + HighestBit >>= 1; + } + + return HighestBit; +} -- cgit v1.2.3