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_FVB2_ERASE_POLARITY) { *ErasePolarity = TRUE; } else { *ErasePolarity = FALSE; } 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_HEADER2 BlankHeader; UINT8 Checksum; UINT32 FileLength; UINT8 SavedChecksum; UINT8 SavedState; UINT8 FileGuidString[80]; UINT32 FfsHeaderSize; // // 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; } FfsHeaderSize = GetFfsHeaderLength(FfsHeader); // // Check if we have free space // if (ErasePolarity) { memset (&BlankHeader, -1, FfsHeaderSize); } else { memset (&BlankHeader, 0, FfsHeaderSize); } if (memcmp (&BlankHeader, FfsHeader, FfsHeaderSize) == 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); // // Verify file header checksum // SavedState = FfsHeader->State; FfsHeader->State = 0; SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File; FfsHeader->IntegrityCheck.Checksum.File = 0; Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FfsHeaderSize); FfsHeader->State = SavedState; FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum; if (Checksum != 0) { Error (NULL, 0, 0006, "invalid FFS file header checksum", "Ffs file with Guid %s", FileGuidString); return EFI_ABORTED; } // // Verify file checksum // if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) { // // Verify file data checksum // FileLength = GetFfsFileLength (FfsHeader); Checksum = CalculateSum8 ((UINT8 *) ((UINT8 *)FfsHeader + FfsHeaderSize), FileLength - FfsHeaderSize); Checksum = Checksum + FfsHeader->IntegrityCheck.Checksum.File; if (Checksum != 0) { Error (NULL, 0, 0006, "invalid FFS file checksum", "Ffs file with Guid %s", FileGuidString); return EFI_ABORTED; } } else { // // File does not have a checksum // Verify contents are 0xAA as spec'd // if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) { Error (NULL, 0, 0006, "invalid fixed FFS file header checksum", "Ffs file with Guid %s", FileGuidString); return EFI_ABORTED; } } 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, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType); 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, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType); return EFI_ABORTED; } } *File = NULL; 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; CHAR8 FileGuidString[80]; // // 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; } // // File Guid String Name // PrintGuidToBuffer (FileName, (UINT8 *)FileGuidString, sizeof (FileGuidString), TRUE); // // 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, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString); 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, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString); return EFI_ABORTED; } } // // File not found in this FV. // *File = NULL; 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 + GetFfsFileLength(CurrentFile) > (UINTN) mFvHeader + mFvLength) { *NextFile = NULL; return EFI_SUCCESS; } *NextFile = CurrentFile; return EFI_SUCCESS; } } // // Verify current file is in range // if (((UINTN) CurrentFile < (UINTN) mFvHeader + mFvHeader->HeaderLength) || ((UINTN) CurrentFile + GetFfsFileLength(CurrentFile) > (UINTN) mFvHeader + mFvLength) ) { return EFI_INVALID_PARAMETER; } // // Get next file, compensate for 8 byte alignment if necessary. // *NextFile = (EFI_FFS_FILE_HEADER *) ((((UINTN) CurrentFile - (UINTN) mFvHeader + GetFfsFileLength(CurrentFile) + 0x07) & (-1 << 3)) + (UINT8 *) mFvHeader); // // Verify file is in this FV. // if (((UINTN) *NextFile + GetFfsHeaderLength(*NextFile) >= (UINTN) mFvHeader + mFvLength) || ((UINTN) *NextFile + GetFfsFileLength (*NextFile) > (UINTN) mFvHeader + mFvLength) ) { *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 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; UINT8 SavedChecksum; UINT8 SavedState; UINT8 FileGuidString[80]; UINT32 TailSize; #if (PI_SPECIFICATION_VERSION < 0x00010000) EFI_FFS_FILE_TAIL *Tail; #endif // // 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); #if (PI_SPECIFICATION_VERSION < 0x00010000) Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FileLength - TailSize); Checksum = (UINT8) (Checksum - FfsHeader->State); #else Checksum = CalculateSum8 ((UINT8 *) ((UINTN)FfsHeader + sizeof (EFI_FFS_FILE_HEADER)), FileLength - TailSize - sizeof (EFI_FFS_FILE_HEADER)); Checksum = Checksum + (UINT8)FfsHeader->IntegrityCheck.Checksum.File; #endif 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(Framework) and 0xAA(PI 1.0) as spec'd // if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) { Error (NULL, 0, 0, FileGuidString, "invalid fixed file checksum"); return EFI_ABORTED; } } #if (PI_SPECIFICATION_VERSION < 0x00010000) // // 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; } } #endif return EFI_SUCCESS; }