--- /dev/null
+/** @file\r
+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Guid/VariableFormat.h>\r
+#include <Guid/SystemNvDataGuid.h>\r
+#include "PeilessStartupInternal.h"\r
+\r
+/**\r
+ Check padding data all bit should be 1.\r
+\r
+ @param[in] Buffer - A pointer to buffer header\r
+ @param[in] BufferSize - Buffer size\r
+\r
+ @retval TRUE - The padding data is valid.\r
+ @retval TRUE - The padding data is invalid.\r
+\r
+**/\r
+BOOLEAN\r
+CheckPaddingData (\r
+ IN UINT8 *Buffer,\r
+ IN UINT32 BufferSize\r
+ )\r
+{\r
+ UINT32 index;\r
+\r
+ for (index = 0; index < BufferSize; index++) {\r
+ if (Buffer[index] != 0xFF) {\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Check the integrity of CFV data.\r
+\r
+ @param[in] TdxCfvBase - A pointer to CFV header\r
+ @param[in] TdxCfvSize - CFV data size\r
+\r
+ @retval TRUE - The CFV data is valid.\r
+ @retval FALSE - The CFV data is invalid.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+TdxValidateCfv (\r
+ IN UINT8 *TdxCfvBase,\r
+ IN UINT32 TdxCfvSize\r
+ )\r
+{\r
+ UINT16 Checksum;\r
+ UINTN VariableBase;\r
+ UINT32 VariableOffset;\r
+ UINT32 VariableOffsetBeforeAlign;\r
+ EFI_FIRMWARE_VOLUME_HEADER *CfvFvHeader;\r
+ VARIABLE_STORE_HEADER *CfvVariableStoreHeader;\r
+ AUTHENTICATED_VARIABLE_HEADER *VariableHeader;\r
+\r
+ static EFI_GUID FvHdrGUID = EFI_SYSTEM_NV_DATA_FV_GUID;\r
+ static EFI_GUID VarStoreHdrGUID = EFI_AUTHENTICATED_VARIABLE_GUID;\r
+\r
+ VariableOffset = 0;\r
+\r
+ if (TdxCfvBase == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "TDX CFV: CFV pointer is NULL\n"));\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Verify the header zerovetor, filesystemguid,\r
+ // revision, signature, attributes, fvlength, checksum\r
+ // HeaderLength cannot be an odd number\r
+ //\r
+ CfvFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)TdxCfvBase;\r
+\r
+ if ((!IsZeroBuffer (CfvFvHeader->ZeroVector, 16)) ||\r
+ (!CompareGuid (&FvHdrGUID, &CfvFvHeader->FileSystemGuid)) ||\r
+ (CfvFvHeader->Signature != EFI_FVH_SIGNATURE) ||\r
+ (CfvFvHeader->Attributes != 0x4feff) ||\r
+ (CfvFvHeader->Revision != EFI_FVH_REVISION) ||\r
+ (CfvFvHeader->FvLength != TdxCfvSize)\r
+ )\r
+ {\r
+ DEBUG ((DEBUG_ERROR, "TDX CFV: Basic FV headers were invalid\n"));\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Verify the header checksum\r
+ //\r
+ Checksum = CalculateSum16 ((VOID *)CfvFvHeader, CfvFvHeader->HeaderLength);\r
+\r
+ if (Checksum != 0) {\r
+ DEBUG ((DEBUG_ERROR, "TDX CFV: FV checksum was invalid\n"));\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Verify the header signature, size, format, state\r
+ //\r
+ CfvVariableStoreHeader = (VARIABLE_STORE_HEADER *)(TdxCfvBase + CfvFvHeader->HeaderLength);\r
+ if ((!CompareGuid (&VarStoreHdrGUID, &CfvVariableStoreHeader->Signature)) ||\r
+ (CfvVariableStoreHeader->Format != VARIABLE_STORE_FORMATTED) ||\r
+ (CfvVariableStoreHeader->State != VARIABLE_STORE_HEALTHY) ||\r
+ (CfvVariableStoreHeader->Size > (CfvFvHeader->FvLength - CfvFvHeader->HeaderLength)) ||\r
+ (CfvVariableStoreHeader->Size < sizeof (VARIABLE_STORE_HEADER))\r
+ )\r
+ {\r
+ DEBUG ((DEBUG_ERROR, "TDX CFV: Variable Store header was invalid\n"));\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Verify the header startId, state\r
+ // Verify data to the end\r
+ //\r
+ VariableBase = (UINTN)TdxCfvBase + CfvFvHeader->HeaderLength + sizeof (VARIABLE_STORE_HEADER);\r
+ while (VariableOffset < (CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER))) {\r
+ VariableHeader = (AUTHENTICATED_VARIABLE_HEADER *)(VariableBase + VariableOffset);\r
+ if (VariableHeader->StartId != VARIABLE_DATA) {\r
+ if (!CheckPaddingData ((UINT8 *)VariableHeader, CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - VariableOffset)) {\r
+ DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n"));\r
+ return FALSE;\r
+ }\r
+\r
+ VariableOffset = CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);\r
+ } else {\r
+ if (!((VariableHeader->State == VAR_IN_DELETED_TRANSITION) ||\r
+ (VariableHeader->State == VAR_DELETED) ||\r
+ (VariableHeader->State == VAR_HEADER_VALID_ONLY) ||\r
+ (VariableHeader->State == VAR_ADDED)))\r
+ {\r
+ DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n"));\r
+ return FALSE;\r
+ }\r
+\r
+ VariableOffset += sizeof (AUTHENTICATED_VARIABLE_HEADER) + VariableHeader->NameSize + VariableHeader->DataSize;\r
+ // Verify VariableOffset should be less than or equal CfvVariableStoreHeader->Size - sizeof(VARIABLE_STORE_HEADER)\r
+ if (VariableOffset > (CfvVariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER))) {\r
+ DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n"));\r
+ return FALSE;\r
+ }\r
+\r
+ VariableOffsetBeforeAlign = VariableOffset;\r
+ // 4 byte align\r
+ VariableOffset = (VariableOffset + 3) & (UINTN)(~3);\r
+\r
+ if (!CheckPaddingData ((UINT8 *)(VariableBase + VariableOffsetBeforeAlign), VariableOffset - VariableOffsetBeforeAlign)) {\r
+ DEBUG ((DEBUG_ERROR, "TDX CFV: Variable header was invalid\n"));\r
+ return FALSE;\r
+ }\r
+ }\r
+ }\r
+\r
+ return TRUE;\r
+}\r