--- /dev/null
+/** @file\r
+ TdxLib definitions\r
+\r
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef TDX_LIB_H_\r
+#define TDX_LIB_H_\r
+\r
+/**\r
+ This function accepts a pending private page, and initialize the page to\r
+ all-0 using the TD ephemeral private key.\r
+\r
+ @param[in] StartAddress Guest physical address of the private page\r
+ to accept. [63:52] and [11:0] must be 0.\r
+ @param[in] NumberOfPages Number of the pages to be accepted.\r
+ @param[in] PageSize GPA page size. Accept 2M/4K page size.\r
+\r
+ @return EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TdAcceptPages (\r
+ IN UINT64 StartAddress,\r
+ IN UINT64 NumberOfPages,\r
+ IN UINT32 PageSize\r
+ );\r
+\r
+/**\r
+ This function extends one of the RTMR measurement register\r
+ in TDCS with the provided extension data in memory.\r
+ RTMR extending supports SHA384 which length is 48 bytes.\r
+\r
+ @param[in] Data Point to the data to be extended\r
+ @param[in] DataLen Length of the data. Must be 48\r
+ @param[in] Index RTMR index\r
+\r
+ @return EFI_SUCCESS\r
+ @return EFI_INVALID_PARAMETER\r
+ @return EFI_DEVICE_ERROR\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TdExtendRtmr (\r
+ IN UINT32 *Data,\r
+ IN UINT32 DataLen,\r
+ IN UINT8 Index\r
+ );\r
+\r
+/**\r
+ This function gets the Td guest shared page mask.\r
+\r
+ The guest indicates if a page is shared using the Guest Physical Address\r
+ (GPA) Shared (S) bit. If the GPA Width(GPAW) is 48, the S-bit is bit-47.\r
+ If the GPAW is 52, the S-bit is bit-51.\r
+\r
+ @return Shared page bit mask\r
+**/\r
+UINT64\r
+EFIAPI\r
+TdSharedPageMask (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ This function gets the maximum number of Virtual CPUs that are usable for\r
+ Td Guest.\r
+\r
+ @return maximum Virtual CPUs number\r
+**/\r
+UINT32\r
+EFIAPI\r
+TdMaxVCpuNum (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ This function gets the number of Virtual CPUs that are usable for Td\r
+ Guest.\r
+\r
+ @return Virtual CPUs number\r
+**/\r
+UINT32\r
+EFIAPI\r
+TdVCpuNum (\r
+ VOID\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+\r
+ Unaccepted memory is a special type of private memory. In Td guest\r
+ TDCALL [TDG.MEM.PAGE.ACCEPT] is invoked to accept the unaccepted\r
+ memory before use it.\r
+\r
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <IndustryStandard/Tdx.h>\r
+#include <Uefi/UefiBaseType.h>\r
+#include <Library/TdxLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+UINT64 mNumberOfDuplicatedAcceptedPages;\r
+\r
+#define TDX_ACCEPTPAGE_MAX_RETRIED 3\r
+\r
+// PageSize is mapped to PageLevel like below:\r
+// 4KB - 0, 2MB - 1\r
+UINT32 mTdxAcceptPageLevelMap[2] = {\r
+ SIZE_4KB,\r
+ SIZE_2MB\r
+};\r
+\r
+#define INVALID_ACCEPT_PAGELEVEL ARRAY_SIZE(mTdxAcceptPageLevelMap)\r
+\r
+/**\r
+ This function gets the PageLevel according to the input page size.\r
+\r
+ @param[in] PageSize Page size\r
+\r
+ @return UINT32 The mapped page level\r
+**/\r
+UINT32\r
+GetGpaPageLevel (\r
+ UINT32 PageSize\r
+ )\r
+{\r
+ UINT32 Index;\r
+\r
+ for (Index = 0; Index < ARRAY_SIZE (mTdxAcceptPageLevelMap); Index++) {\r
+ if (mTdxAcceptPageLevelMap[Index] == PageSize) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ return Index;\r
+}\r
+\r
+/**\r
+ This function accept a pending private page, and initialize the page to\r
+ all-0 using the TD ephemeral private key.\r
+\r
+ Sometimes TDCALL [TDG.MEM.PAGE.ACCEPT] may return\r
+ TDX_EXIT_REASON_PAGE_SIZE_MISMATCH. It indicates the input PageLevel is\r
+ not workable. In this case we need to try to fallback to a smaller\r
+ PageLevel if possible.\r
+\r
+ @param[in] StartAddress Guest physical address of the private\r
+ page to accept. [63:52] and [11:0] must be 0.\r
+ @param[in] NumberOfPages Number of the pages to be accepted.\r
+ @param[in] PageSize GPA page size. Only accept 2M/4K size.\r
+\r
+ @return EFI_SUCCESS Accept successfully\r
+ @return others Indicate other errors\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TdAcceptPages (\r
+ IN UINT64 StartAddress,\r
+ IN UINT64 NumberOfPages,\r
+ IN UINT32 PageSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 Address;\r
+ UINT64 TdxStatus;\r
+ UINT64 Index;\r
+ UINT32 GpaPageLevel;\r
+ UINT32 PageSize2;\r
+ UINTN Retried;\r
+\r
+ Retried = 0;\r
+\r
+ if ((StartAddress & ~0xFFFFFFFFFF000ULL) != 0) {\r
+ ASSERT (FALSE);\r
+ DEBUG ((DEBUG_ERROR, "Accept page address(0x%llx) is not valid. [63:52] and [11:0] must be 0\n", StartAddress));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Address = StartAddress;\r
+\r
+ GpaPageLevel = GetGpaPageLevel (PageSize);\r
+ if (GpaPageLevel == INVALID_ACCEPT_PAGELEVEL) {\r
+ ASSERT (FALSE);\r
+ DEBUG ((DEBUG_ERROR, "Accept page size must be 4K/2M. Invalid page size - 0x%llx\n", PageSize));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ for (Index = 0; Index < NumberOfPages; Index++) {\r
+ Retried = 0;\r
+\r
+DoAcceptPage:\r
+ TdxStatus = TdCall (TDCALL_TDACCEPTPAGE, Address | GpaPageLevel, 0, 0, 0);\r
+ if (TdxStatus != TDX_EXIT_REASON_SUCCESS) {\r
+ if ((TdxStatus & ~0xFFFFULL) == TDX_EXIT_REASON_PAGE_ALREADY_ACCEPTED) {\r
+ //\r
+ // Already accepted\r
+ //\r
+ mNumberOfDuplicatedAcceptedPages++;\r
+ DEBUG ((DEBUG_WARN, "Page at Address (0x%llx) has already been accepted. - %d\n", Address, mNumberOfDuplicatedAcceptedPages));\r
+ } else if ((TdxStatus & ~0xFFFFULL) == TDX_EXIT_REASON_PAGE_SIZE_MISMATCH) {\r
+ //\r
+ // GpaPageLevel is mismatch, fall back to a smaller GpaPageLevel if possible\r
+ //\r
+ DEBUG ((DEBUG_VERBOSE, "Address %llx cannot be accepted in PageLevel of %d\n", Address, GpaPageLevel));\r
+\r
+ if (GpaPageLevel == 0) {\r
+ //\r
+ // Cannot fall back to smaller page level\r
+ //\r
+ DEBUG ((DEBUG_ERROR, "AcceptPage cannot fallback from PageLevel %d\n", GpaPageLevel));\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ } else {\r
+ //\r
+ // Fall back to a smaller page size\r
+ //\r
+ PageSize2 = mTdxAcceptPageLevelMap[GpaPageLevel - 1];\r
+ Status = TdAcceptPages (Address, 512, PageSize2);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+ } else if ((TdxStatus & ~0xFFFFULL) == TDX_EXIT_REASON_OPERAND_BUSY) {\r
+ //\r
+ // Concurrent TDG.MEM.PAGE.ACCEPT is using the same Secure EPT entry\r
+ // So try it again. There is a max retried count. If Retried exceeds the max count,\r
+ // report the error and quit.\r
+ //\r
+ Retried += 1;\r
+ if (Retried > TDX_ACCEPTPAGE_MAX_RETRIED) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "Address %llx (%d) failed to be accepted because of OPERAND_BUSY. Retried %d time.\n",\r
+ Address,\r
+ Index,\r
+ Retried\r
+ ));\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ } else {\r
+ goto DoAcceptPage;\r
+ }\r
+ } else {\r
+ //\r
+ // Other errors\r
+ //\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "Address %llx (%d) failed to be accepted. Error = 0x%llx\n",\r
+ Address,\r
+ Index,\r
+ TdxStatus\r
+ ));\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ }\r
+ }\r
+\r
+ Address += PageSize;\r
+ }\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+\r
+ Extends one of the RTMR measurement registers in TDCS with the provided\r
+ extension data in memory.\r
+\r
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Uefi/UefiBaseType.h>\r
+#include <Library/TdxLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <IndustryStandard/Tpm20.h>\r
+#include <IndustryStandard/Tdx.h>\r
+\r
+#define RTMR_COUNT 4\r
+#define TD_EXTEND_BUFFER_LEN (64 + 48)\r
+\r
+UINT8 mExtendBuffer[TD_EXTEND_BUFFER_LEN];\r
+\r
+/**\r
+ This function extends one of the RTMR measurement register\r
+ in TDCS with the provided extension data in memory.\r
+ RTMR extending supports SHA384 which length is 48 bytes.\r
+\r
+ @param[in] Data Point to the data to be extended\r
+ @param[in] DataLen Length of the data. Must be 48\r
+ @param[in] Index RTMR index\r
+\r
+ @return EFI_SUCCESS\r
+ @return EFI_INVALID_PARAMETER\r
+ @return EFI_DEVICE_ERROR\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TdExtendRtmr (\r
+ IN UINT32 *Data,\r
+ IN UINT32 DataLen,\r
+ IN UINT8 Index\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 TdCallStatus;\r
+ UINT8 *ExtendBuffer;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ ASSERT (Data != NULL);\r
+ ASSERT (DataLen == SHA384_DIGEST_SIZE);\r
+ ASSERT (Index >= 0 && Index < RTMR_COUNT);\r
+\r
+ if ((Data == NULL) || (DataLen != SHA384_DIGEST_SIZE) || (Index >= RTMR_COUNT)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ // TD.RTMR.EXTEND requires 64B-aligned guest physical address of\r
+ // 48B-extension data. We use ALIGN_POINTER(Pointer, 64) to get\r
+ // the 64B-aligned guest physical address.\r
+ ExtendBuffer = ALIGN_POINTER (mExtendBuffer, 64);\r
+ ASSERT (((UINTN)ExtendBuffer & 0x3f) == 0);\r
+\r
+ ZeroMem (ExtendBuffer, SHA384_DIGEST_SIZE);\r
+ CopyMem (ExtendBuffer, Data, SHA384_DIGEST_SIZE);\r
+\r
+ TdCallStatus = TdCall (TDCALL_TDEXTENDRTMR, (UINT64)(UINTN)ExtendBuffer, Index, 0, 0);\r
+\r
+ if (TdCallStatus == TDX_EXIT_REASON_SUCCESS) {\r
+ Status = EFI_SUCCESS;\r
+ } else if (TdCallStatus == TDX_EXIT_REASON_OPERAND_INVALID) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ } else {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ if (Status != EFI_SUCCESS) {\r
+ DEBUG ((DEBUG_ERROR, "Error returned from TdExtendRtmr call - 0x%lx\n", TdCallStatus));\r
+ }\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+\r
+ Fetch the Tdx info.\r
+\r
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <IndustryStandard/Tdx.h>\r
+#include <Uefi/UefiBaseType.h>\r
+#include <Library/TdxLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+UINT64 mTdSharedPageMask = 0;\r
+UINT32 mTdMaxVCpuNum = 0;\r
+UINT32 mTdVCpuNum = 0;\r
+BOOLEAN mTdDataReturned = FALSE;\r
+\r
+/**\r
+ This function call TDCALL_TDINFO to get the TD_RETURN_DATA.\r
+ If the TDCALL is successful, populate below variables:\r
+ - mTdSharedPageMask\r
+ - mTdMaxVCpunum\r
+ - mTdVCpuNum\r
+ - mTdDataReturned\r
+\r
+ @return TRUE The TDCALL is successful and above variables are populated.\r
+ @return FALSE The TDCALL is failed. Above variables are not set.\r
+**/\r
+BOOLEAN\r
+GetTdInfo (\r
+ VOID\r
+ )\r
+{\r
+ UINT64 Status;\r
+ TD_RETURN_DATA TdReturnData;\r
+ UINT8 Gpaw;\r
+\r
+ Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);\r
+ if (Status == TDX_EXIT_REASON_SUCCESS) {\r
+ Gpaw = (UINT8)(TdReturnData.TdInfo.Gpaw & 0x3f);\r
+ mTdSharedPageMask = 1ULL << (Gpaw - 1);\r
+ mTdMaxVCpuNum = TdReturnData.TdInfo.MaxVcpus;\r
+ mTdVCpuNum = TdReturnData.TdInfo.NumVcpus;\r
+ mTdDataReturned = TRUE;\r
+ } else {\r
+ DEBUG ((DEBUG_ERROR, "Failed call TDCALL_TDINFO. %llx\n", Status));\r
+ mTdDataReturned = FALSE;\r
+ }\r
+\r
+ return mTdDataReturned;\r
+}\r
+\r
+/**\r
+ This function gets the Td guest shared page mask.\r
+\r
+ The guest indicates if a page is shared using the Guest Physical Address\r
+ (GPA) Shared (S) bit. If the GPA Width(GPAW) is 48, the S-bit is bit-47.\r
+ If the GPAW is 52, the S-bit is bit-51.\r
+\r
+ @return Shared page bit mask\r
+**/\r
+UINT64\r
+EFIAPI\r
+TdSharedPageMask (\r
+ VOID\r
+ )\r
+{\r
+ if (mTdDataReturned) {\r
+ return mTdSharedPageMask;\r
+ }\r
+\r
+ return GetTdInfo () ? mTdSharedPageMask : 0;\r
+}\r
+\r
+/**\r
+ This function gets the maximum number of Virtual CPUs that are usable for\r
+ Td Guest.\r
+\r
+ @return maximum Virtual CPUs number\r
+**/\r
+UINT32\r
+EFIAPI\r
+TdMaxVCpuNum (\r
+ VOID\r
+ )\r
+{\r
+ if (mTdDataReturned) {\r
+ return mTdMaxVCpuNum;\r
+ }\r
+\r
+ return GetTdInfo () ? mTdMaxVCpuNum : 0;\r
+}\r
+\r
+/**\r
+ This function gets the number of Virtual CPUs that are usable for Td\r
+ Guest.\r
+\r
+ @return Virtual CPUs number\r
+**/\r
+UINT32\r
+EFIAPI\r
+TdVCpuNum (\r
+ VOID\r
+ )\r
+{\r
+ if (mTdDataReturned) {\r
+ return mTdVCpuNum;\r
+ }\r
+\r
+ return GetTdInfo () ? mTdVCpuNum : 0;\r
+}\r
--- /dev/null
+## @file\r
+# Tdx library\r
+#\r
+# Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = TdxLib\r
+ FILE_GUID = 032A8E0D-0C27-40C0-9CAA-23B731C1B223\r
+ MODULE_TYPE = BASE\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = TdxLib\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64\r
+#\r
+\r
+[Sources.IA32]\r
+ TdxLibNull.c\r
+\r
+[Sources.X64]\r
+ AcceptPages.c\r
+ Rtmr.c\r
+ TdInfo.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ BaseMemoryLib\r
+ DebugLib\r
--- /dev/null
+/** @file\r
+\r
+ Null stub of TdxLib\r
+\r
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Uefi/UefiBaseType.h>\r
+#include <Library/TdxLib.h>\r
+\r
+/**\r
+ This function accepts a pending private page, and initialize the page to\r
+ all-0 using the TD ephemeral private key.\r
+\r
+ @param[in] StartAddress Guest physical address of the private page\r
+ to accept.\r
+ @param[in] NumberOfPages Number of the pages to be accepted.\r
+ @param[in] PageSize GPA page size. Accept 1G/2M/4K page size.\r
+\r
+ @return EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TdAcceptPages (\r
+ IN UINT64 StartAddress,\r
+ IN UINT64 NumberOfPages,\r
+ IN UINT32 PageSize\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ This function extends one of the RTMR measurement register\r
+ in TDCS with the provided extension data in memory.\r
+ RTMR extending supports SHA384 which length is 48 bytes.\r
+\r
+ @param[in] Data Point to the data to be extended\r
+ @param[in] DataLen Length of the data. Must be 48\r
+ @param[in] Index RTMR index\r
+\r
+ @return EFI_SUCCESS\r
+ @return EFI_INVALID_PARAMETER\r
+ @return EFI_DEVICE_ERROR\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TdExtendRtmr (\r
+ IN UINT32 *Data,\r
+ IN UINT32 DataLen,\r
+ IN UINT8 Index\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ This function gets the Td guest shared page mask.\r
+\r
+ The guest indicates if a page is shared using the Guest Physical Address\r
+ (GPA) Shared (S) bit. If the GPA Width(GPAW) is 48, the S-bit is bit-47.\r
+ If the GPAW is 52, the S-bit is bit-51.\r
+\r
+ @return Shared page bit mask\r
+**/\r
+UINT64\r
+EFIAPI\r
+TdSharedPageMask (\r
+ VOID\r
+ )\r
+{\r
+ return 0;\r
+}\r
+\r
+/**\r
+ This function gets the maximum number of Virtual CPUs that are usable for\r
+ Td Guest.\r
+\r
+ @return maximum Virtual CPUs number\r
+**/\r
+UINT32\r
+EFIAPI\r
+TdMaxVCpuNum (\r
+ VOID\r
+ )\r
+{\r
+ return 0;\r
+}\r
+\r
+/**\r
+ This function gets the number of Virtual CPUs that are usable for Td\r
+ Guest.\r
+\r
+ @return Virtual CPUs number\r
+**/\r
+UINT32\r
+EFIAPI\r
+TdVCpuNum (\r
+ VOID\r
+ )\r
+{\r
+ return 0;\r
+}\r
## @libraryclass Provides services to log the SMI handler registration.\r
SmiHandlerProfileLib|Include/Library/SmiHandlerProfileLib.h\r
\r
+ ## @libraryclass Provides function to support TDX processing.\r
+ TdxLib|Include/Library/TdxLib.h\r
+\r
[Guids]\r
#\r
# GUID defined in UEFI2.1/UEFI2.0/EFI1.1\r
MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf\r
MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf\r
MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf\r
+ MdePkg/Library/TdxLib/TdxLib.inf\r
\r
[Components.EBC]\r
MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf\r