+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+\r
+ Ffs.c\r
+\r
+Abstract:\r
+\r
+ FFS file access utilities.\r
+\r
+--*/\r
+\r
+\r
+#include <DxeMain.h>\r
+\r
+#define PHYSICAL_ADDRESS_TO_POINTER(Address) ((VOID *)((UINTN)(Address)))\r
+\r
+\r
+EFI_FFS_FILE_STATE\r
+GetFileState (\r
+ IN UINT8 ErasePolarity,\r
+ IN EFI_FFS_FILE_HEADER *FfsHeader\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Get the FFS file state by checking the highest bit set in the header's state field\r
+\r
+Arguments:\r
+ ErasePolarity - Erase polarity attribute of the firmware volume\r
+ FfsHeader - Points to the FFS file header\r
+ \r
+Returns:\r
+ FFS File state \r
+ \r
+--*/\r
+{\r
+ EFI_FFS_FILE_STATE FileState;\r
+ UINT8 HighestBit;\r
+\r
+ FileState = FfsHeader->State;\r
+\r
+ if (ErasePolarity != 0) {\r
+ FileState = (EFI_FFS_FILE_STATE)~FileState;\r
+ }\r
+\r
+ HighestBit = 0x80;\r
+ while (HighestBit != 0 && ((HighestBit & FileState) == 0)) {\r
+ HighestBit >>= 1;\r
+ }\r
+\r
+ return (EFI_FFS_FILE_STATE)HighestBit;\r
+}\r
+\r
+\r
+BOOLEAN\r
+IsBufferErased (\r
+ IN UINT8 ErasePolarity,\r
+ IN VOID *InBuffer,\r
+ IN UINTN BufferSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Check if a block of buffer is erased\r
+\r
+Arguments:\r
+ ErasePolarity - Erase polarity attribute of the firmware volume\r
+ InBuffer - The buffer to be checked\r
+ BufferSize - Size of the buffer in bytes\r
+ \r
+Returns:\r
+ TRUE - The block of buffer is erased\r
+ FALSE - The block of buffer is not erased\r
+ \r
+--*/\r
+{\r
+ UINTN Count;\r
+ UINT8 EraseByte;\r
+ UINT8 *Buffer;\r
+\r
+ if(ErasePolarity == 1) {\r
+ EraseByte = 0xFF;\r
+ } else {\r
+ EraseByte = 0;\r
+ }\r
+\r
+ Buffer = InBuffer;\r
+ for (Count = 0; Count < BufferSize; Count++) {\r
+ if (Buffer[Count] != EraseByte) {\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+\r
+BOOLEAN\r
+VerifyFvHeaderChecksum (\r
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Verify checksum of the firmware volume header \r
+\r
+Arguments:\r
+ FvHeader - Points to the firmware volume header to be checked\r
+ \r
+Returns:\r
+ TRUE - Checksum verification passed\r
+ FALSE - Checksum verification failed\r
+ \r
+--*/\r
+{\r
+ UINT32 Index;\r
+ UINT32 HeaderLength;\r
+ UINT16 Checksum;\r
+ UINT16 *ptr;\r
+\r
+ HeaderLength = FvHeader->HeaderLength;\r
+ ptr = (UINT16 *)FvHeader;\r
+ Checksum = 0;\r
+\r
+ for (Index = 0; Index < HeaderLength / sizeof (UINT16); Index++) {\r
+ Checksum = (UINT16)(Checksum + ptr[Index]);\r
+ }\r
+\r
+ if (Checksum == 0) {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+STATIC\r
+BOOLEAN\r
+VerifyHeaderChecksum (\r
+ IN EFI_FFS_FILE_HEADER *FfsHeader\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Verify checksum of the FFS file header \r
+\r
+Arguments:\r
+ FfsHeader - Points to the FFS file header to be checked\r
+ \r
+Returns:\r
+ TRUE - Checksum verification passed\r
+ FALSE - Checksum verification failed\r
+ \r
+--*/\r
+{\r
+ UINT32 Index;\r
+ UINT8 *ptr;\r
+ UINT8 HeaderChecksum;\r
+\r
+ ptr = (UINT8 *)FfsHeader;\r
+ HeaderChecksum = 0;\r
+ for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) {\r
+ HeaderChecksum = (UINT8)(HeaderChecksum + ptr[Index]);\r
+ }\r
+\r
+ HeaderChecksum = (UINT8) (HeaderChecksum - FfsHeader->State - FfsHeader->IntegrityCheck.Checksum.File);\r
+\r
+ if (HeaderChecksum == 0) {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+\r
+BOOLEAN\r
+IsValidFfsHeader (\r
+ IN UINT8 ErasePolarity,\r
+ IN EFI_FFS_FILE_HEADER *FfsHeader,\r
+ OUT EFI_FFS_FILE_STATE *FileState\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Check if it's a valid FFS file header\r
+\r
+Arguments:\r
+ ErasePolarity - Erase polarity attribute of the firmware volume\r
+ FfsHeader - Points to the FFS file header to be checked\r
+ FileState - FFS file state to be returned\r
+ \r
+Returns:\r
+ TRUE - Valid FFS file header\r
+ FALSE - Invalid FFS file header\r
+ \r
+--*/\r
+{\r
+ *FileState = GetFileState (ErasePolarity, FfsHeader);\r
+\r
+ switch (*FileState) {\r
+ case EFI_FILE_HEADER_VALID:\r
+ case EFI_FILE_DATA_VALID:\r
+ case EFI_FILE_MARKED_FOR_UPDATE:\r
+ case EFI_FILE_DELETED:\r
+ //\r
+ // Here we need to verify header checksum\r
+ //\r
+ return VerifyHeaderChecksum (FfsHeader);\r
+ \r
+ case EFI_FILE_HEADER_CONSTRUCTION:\r
+ case EFI_FILE_HEADER_INVALID:\r
+ default:\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+\r
+BOOLEAN\r
+IsValidFfsFile (\r
+ IN UINT8 ErasePolarity,\r
+ IN EFI_FFS_FILE_HEADER *FfsHeader\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Check if it's a valid FFS file. \r
+ Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first.\r
+\r
+Arguments:\r
+ ErasePolarity - Erase polarity attribute of the firmware volume\r
+ FfsHeader - Points to the FFS file to be checked\r
+ \r
+Returns:\r
+ TRUE - Valid FFS file\r
+ FALSE - Invalid FFS file\r
+ \r
+--*/\r
+{\r
+ EFI_FFS_FILE_STATE FileState;\r
+\r
+ FileState = GetFileState (ErasePolarity, FfsHeader);\r
+ switch (FileState) {\r
+\r
+ case EFI_FILE_DELETED:\r
+ case EFI_FILE_DATA_VALID:\r
+ case EFI_FILE_MARKED_FOR_UPDATE:\r
+ //\r
+ // Some other vliadation like file content checksum might be done here.\r
+ // For performance issue, Tiano only do FileState check.\r
+ //\r
+ return TRUE;\r
+\r
+ default:\r
+ return FALSE;\r
+ }\r
+}\r
+\r