/** @file | |
FFS file access utilities. | |
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "DxeMain.h" | |
#include "FwVolDriver.h" | |
/** | |
Get the FFS file state by checking the highest bit set in the header's state field. | |
@param ErasePolarity Erase polarity attribute of the firmware volume | |
@param FfsHeader Points to the FFS file header | |
@return FFS File state | |
**/ | |
EFI_FFS_FILE_STATE | |
GetFileState ( | |
IN UINT8 ErasePolarity, | |
IN EFI_FFS_FILE_HEADER *FfsHeader | |
) | |
{ | |
EFI_FFS_FILE_STATE FileState; | |
UINT8 HighestBit; | |
FileState = FfsHeader->State; | |
if (ErasePolarity != 0) { | |
FileState = (EFI_FFS_FILE_STATE) ~FileState; | |
} | |
HighestBit = 0x80; | |
while (HighestBit != 0 && ((HighestBit & FileState) == 0)) { | |
HighestBit >>= 1; | |
} | |
return (EFI_FFS_FILE_STATE)HighestBit; | |
} | |
/** | |
Check if a block of buffer is erased. | |
@param ErasePolarity Erase polarity attribute of the firmware volume | |
@param InBuffer The buffer to be checked | |
@param BufferSize Size of the buffer in bytes | |
@retval TRUE The block of buffer is erased | |
@retval FALSE The block of buffer is not erased | |
**/ | |
BOOLEAN | |
IsBufferErased ( | |
IN UINT8 ErasePolarity, | |
IN VOID *InBuffer, | |
IN UINTN BufferSize | |
) | |
{ | |
UINTN Count; | |
UINT8 EraseByte; | |
UINT8 *Buffer; | |
if (ErasePolarity == 1) { | |
EraseByte = 0xFF; | |
} else { | |
EraseByte = 0; | |
} | |
Buffer = InBuffer; | |
for (Count = 0; Count < BufferSize; Count++) { | |
if (Buffer[Count] != EraseByte) { | |
return FALSE; | |
} | |
} | |
return TRUE; | |
} | |
/** | |
Verify checksum of the firmware volume header. | |
@param FvHeader Points to the firmware volume header to be checked | |
@retval TRUE Checksum verification passed | |
@retval FALSE Checksum verification failed | |
**/ | |
BOOLEAN | |
VerifyFvHeaderChecksum ( | |
IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader | |
) | |
{ | |
UINT16 Checksum; | |
Checksum = CalculateSum16 ((UINT16 *)FvHeader, FvHeader->HeaderLength); | |
if (Checksum == 0) { | |
return TRUE; | |
} else { | |
return FALSE; | |
} | |
} | |
/** | |
Verify checksum of the FFS file header. | |
@param FfsHeader Points to the FFS file header to be checked | |
@retval TRUE Checksum verification passed | |
@retval FALSE Checksum verification failed | |
**/ | |
BOOLEAN | |
VerifyHeaderChecksum ( | |
IN EFI_FFS_FILE_HEADER *FfsHeader | |
) | |
{ | |
UINT8 HeaderChecksum; | |
if (IS_FFS_FILE2 (FfsHeader)) { | |
HeaderChecksum = CalculateSum8 ((UINT8 *)FfsHeader, sizeof (EFI_FFS_FILE_HEADER2)); | |
} else { | |
HeaderChecksum = CalculateSum8 ((UINT8 *)FfsHeader, sizeof (EFI_FFS_FILE_HEADER)); | |
} | |
HeaderChecksum = (UINT8)(HeaderChecksum - FfsHeader->State - FfsHeader->IntegrityCheck.Checksum.File); | |
if (HeaderChecksum == 0) { | |
return TRUE; | |
} else { | |
return FALSE; | |
} | |
} | |
/** | |
Check if it's a valid FFS file header. | |
@param ErasePolarity Erase polarity attribute of the firmware volume | |
@param FfsHeader Points to the FFS file header to be checked | |
@param FileState FFS file state to be returned | |
@retval TRUE Valid FFS file header | |
@retval FALSE Invalid FFS file header | |
**/ | |
BOOLEAN | |
IsValidFfsHeader ( | |
IN UINT8 ErasePolarity, | |
IN EFI_FFS_FILE_HEADER *FfsHeader, | |
OUT EFI_FFS_FILE_STATE *FileState | |
) | |
{ | |
*FileState = GetFileState (ErasePolarity, FfsHeader); | |
switch (*FileState) { | |
case EFI_FILE_HEADER_VALID: | |
case EFI_FILE_DATA_VALID: | |
case EFI_FILE_MARKED_FOR_UPDATE: | |
case EFI_FILE_DELETED: | |
// | |
// Here we need to verify header checksum | |
// | |
return VerifyHeaderChecksum (FfsHeader); | |
case EFI_FILE_HEADER_CONSTRUCTION: | |
case EFI_FILE_HEADER_INVALID: | |
default: | |
return FALSE; | |
} | |
} | |
/** | |
Check if it's a valid FFS file. | |
Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first. | |
@param ErasePolarity Erase polarity attribute of the firmware volume | |
@param FfsHeader Points to the FFS file to be checked | |
@retval TRUE Valid FFS file | |
@retval FALSE Invalid FFS file | |
**/ | |
BOOLEAN | |
IsValidFfsFile ( | |
IN UINT8 ErasePolarity, | |
IN EFI_FFS_FILE_HEADER *FfsHeader | |
) | |
{ | |
EFI_FFS_FILE_STATE FileState; | |
UINT8 DataCheckSum; | |
FileState = GetFileState (ErasePolarity, FfsHeader); | |
switch (FileState) { | |
case EFI_FILE_DELETED: | |
case EFI_FILE_DATA_VALID: | |
case EFI_FILE_MARKED_FOR_UPDATE: | |
DataCheckSum = FFS_FIXED_CHECKSUM; | |
if ((FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) == FFS_ATTRIB_CHECKSUM) { | |
if (IS_FFS_FILE2 (FfsHeader)) { | |
DataCheckSum = CalculateCheckSum8 ((CONST UINT8 *)FfsHeader + sizeof (EFI_FFS_FILE_HEADER2), FFS_FILE2_SIZE (FfsHeader) - sizeof (EFI_FFS_FILE_HEADER2)); | |
} else { | |
DataCheckSum = CalculateCheckSum8 ((CONST UINT8 *)FfsHeader + sizeof (EFI_FFS_FILE_HEADER), FFS_FILE_SIZE (FfsHeader) - sizeof (EFI_FFS_FILE_HEADER)); | |
} | |
} | |
if (FfsHeader->IntegrityCheck.Checksum.File == DataCheckSum) { | |
return TRUE; | |
} | |
default: | |
return FALSE; | |
} | |
} |