--- /dev/null
+/** @file\r
+ TPM NVS MM guid, used for exchanging information, including SWI value and NVS region\r
+ information, for patching TPM ACPI table.\r
+\r
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) Microsoft Corporation.\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef TCG2_NVS_MM_H_\r
+#define TCG2_NVS_MM_H_\r
+\r
+#define MM_TPM_NVS_HOB_GUID \\r
+ { 0xc96c76eb, 0xbc78, 0x429c, { 0x9f, 0x4b, 0xda, 0x51, 0x78, 0xc2, 0x84, 0x57 }}\r
+\r
+extern EFI_GUID gTpmNvsMmGuid;\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+ UINT8 SoftwareSmi;\r
+ UINT32 Parameter;\r
+ UINT32 Response;\r
+ UINT32 Request;\r
+ UINT32 RequestParameter;\r
+ UINT32 LastRequest;\r
+ UINT32 ReturnCode;\r
+} PHYSICAL_PRESENCE_NVS;\r
+\r
+typedef struct {\r
+ UINT8 SoftwareSmi;\r
+ UINT32 Parameter;\r
+ UINT32 Request;\r
+ UINT32 ReturnCode;\r
+} MEMORY_CLEAR_NVS;\r
+\r
+typedef struct {\r
+ PHYSICAL_PRESENCE_NVS PhysicalPresence;\r
+ MEMORY_CLEAR_NVS MemoryClear;\r
+ UINT32 PPRequestUserConfirm;\r
+ UINT32 TpmIrqNum;\r
+ BOOLEAN IsShortFormPkgLength;\r
+} TCG_NVS;\r
+\r
+typedef struct {\r
+ UINT8 OpRegionOp;\r
+ UINT32 NameString;\r
+ UINT8 RegionSpace;\r
+ UINT8 DWordPrefix;\r
+ UINT32 RegionOffset;\r
+ UINT8 BytePrefix;\r
+ UINT8 RegionLen;\r
+} AML_OP_REGION_32_8;\r
+\r
+typedef struct {\r
+ UINT64 Function;\r
+ UINT64 ReturnStatus;\r
+ EFI_PHYSICAL_ADDRESS TargetAddress;\r
+ UINT64 RegisteredPpSwiValue;\r
+ UINT64 RegisteredMcSwiValue;\r
+} TPM_NVS_MM_COMM_BUFFER;\r
+#pragma pack()\r
+\r
+typedef enum {\r
+ TpmNvsMmExchangeInfo,\r
+} TPM_NVS_MM_FUNCTION;\r
+\r
+#endif // TCG2_NVS_MM_H_\r
## Include/OpalPasswordExtraInfoVariable.h\r
gOpalExtraInfoVariableGuid = {0x44a2ad5d, 0x612c, 0x47b3, {0xb0, 0x6e, 0xc8, 0xf5, 0x0b, 0xfb, 0xf0, 0x7d}}\r
\r
+ ## GUID used to exchange registered SWI value and NVS region between Tcg2Acpi and Tcg2Smm.\r
+ ## Include/Guid/TpmNvsMm.h\r
+ gTpmNvsMmGuid = { 0xc96c76eb, 0xbc78, 0x429c, { 0x9f, 0x4b, 0xda, 0x51, 0x78, 0xc2, 0x84, 0x57 }}\r
+\r
+ ## GUID used to enforce loading order between Tcg2Acpi and Tcg2Smm\r
+ gTcg2MmSwSmiRegisteredGuid = { 0x9d4548b9, 0xa48d, 0x4db4, { 0x9a, 0x68, 0x32, 0xc5, 0x13, 0x9e, 0x20, 0x18 } }\r
+\r
\r
[Ppis]\r
## The PPI GUID for that TPM physical presence should be locked.\r
SecurityPkg/Tcg/MemoryOverwriteRequestControlLock/TcgMorLockSmm.inf\r
SecurityPkg/Tcg/TcgSmm/TcgSmm.inf\r
SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf\r
+ SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.inf\r
SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf\r
SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalPresenceLib.inf\r
\r
--- /dev/null
+/** @file\r
+ This driver implements TPM 2.0 definition block in ACPI table and\r
+ populates registered SMI callback functions for Tcg2 physical presence\r
+ and MemoryClear to handle the requests for ACPI method. It needs to be\r
+ used together with Tcg2 MM drivers to exchange information on registered\r
+ SwSmiValue and allocated NVS region address.\r
+\r
+ Caution: This module requires additional review when modified.\r
+ This driver will have external input - variable and ACPINvs data in SMM mode.\r
+ This external input must be validated carefully to avoid security issue.\r
+\r
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) Microsoft Corporation.\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <IndustryStandard/Tpm2Acpi.h>\r
+\r
+#include <Guid/TpmInstance.h>\r
+#include <Guid/TpmNvsMm.h>\r
+#include <Guid/PiSmmCommunicationRegionTable.h>\r
+\r
+#include <Protocol/AcpiTable.h>\r
+#include <Protocol/Tcg2Protocol.h>\r
+#include <Protocol/MmCommunication.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DxeServicesLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/TpmMeasurementLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+//\r
+// Physical Presence Interface Version supported by Platform\r
+//\r
+#define PHYSICAL_PRESENCE_VERSION_TAG "$PV"\r
+#define PHYSICAL_PRESENCE_VERSION_SIZE 4\r
+\r
+//\r
+// PNP _HID for TPM2 device\r
+//\r
+#define TPM_HID_TAG "NNNN0000"\r
+#define TPM_HID_PNP_SIZE 8\r
+#define TPM_HID_ACPI_SIZE 9\r
+\r
+#define TPM_PRS_RESL "RESL"\r
+#define TPM_PRS_RESS "RESS"\r
+#define TPM_PRS_RES_NAME_SIZE 4\r
+//\r
+// Minimum PRS resource template size\r
+// 1 byte for BufferOp\r
+// 1 byte for PkgLength\r
+// 2 bytes for BufferSize\r
+// 12 bytes for Memory32Fixed descriptor\r
+// 5 bytes for Interrupt descriptor\r
+// 2 bytes for END Tag\r
+//\r
+#define TPM_POS_RES_TEMPLATE_MIN_SIZE (1 + 1 + 2 + 12 + 5 + 2)\r
+\r
+//\r
+// Max Interrupt buffer size for PRS interrupt resource\r
+// Now support 15 interrupts in maxmum\r
+//\r
+#define MAX_PRS_INT_BUF_SIZE (15*4)\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+ EFI_ACPI_DESCRIPTION_HEADER Header;\r
+ // Flags field is replaced in version 4 and above\r
+ // BIT0~15: PlatformClass This field is only valid for version 4 and above\r
+ // BIT16~31: Reserved\r
+ UINT32 Flags;\r
+ UINT64 AddressOfControlArea;\r
+ UINT32 StartMethod;\r
+ UINT8 PlatformSpecificParameters[12]; // size up to 12\r
+ UINT32 Laml; // Optional\r
+ UINT64 Lasa; // Optional\r
+} EFI_TPM2_ACPI_TABLE_V4;\r
+\r
+#pragma pack()\r
+\r
+EFI_TPM2_ACPI_TABLE_V4 mTpm2AcpiTemplate = {\r
+ {\r
+ EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,\r
+ sizeof (mTpm2AcpiTemplate),\r
+ EFI_TPM2_ACPI_TABLE_REVISION,\r
+ //\r
+ // Compiler initializes the remaining bytes to 0\r
+ // These fields should be filled in in production\r
+ //\r
+ },\r
+ 0, // BIT0~15: PlatformClass\r
+ // BIT16~31: Reserved\r
+ 0, // Control Area\r
+ EFI_TPM2_ACPI_TABLE_START_METHOD_TIS, // StartMethod\r
+};\r
+\r
+TCG_NVS *mTcgNvs;\r
+\r
+/**\r
+ Find the operation region in TCG ACPI table by given Name and Size,\r
+ and initialize it if the region is found.\r
+\r
+ @param[in, out] Table The TPM item in ACPI table.\r
+ @param[in] Name The name string to find in TPM table.\r
+ @param[in] Size The size of the region to find.\r
+\r
+ @return The allocated address for the found region.\r
+\r
+**/\r
+VOID *\r
+AssignOpRegion (\r
+ EFI_ACPI_DESCRIPTION_HEADER *Table,\r
+ UINT32 Name,\r
+ UINT16 Size\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ AML_OP_REGION_32_8 *OpRegion;\r
+ EFI_PHYSICAL_ADDRESS MemoryAddress;\r
+\r
+ MemoryAddress = SIZE_4GB - 1;\r
+\r
+ //\r
+ // Patch some pointers for the ASL code before loading the SSDT.\r
+ //\r
+ for (OpRegion = (AML_OP_REGION_32_8 *) (Table + 1);\r
+ OpRegion <= (AML_OP_REGION_32_8 *) ((UINT8 *) Table + Table->Length);\r
+ OpRegion = (AML_OP_REGION_32_8 *) ((UINT8 *) OpRegion + 1)) {\r
+ if ((OpRegion->OpRegionOp == AML_EXT_REGION_OP) &&\r
+ (OpRegion->NameString == Name) &&\r
+ (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&\r
+ (OpRegion->BytePrefix == AML_BYTE_PREFIX)) {\r
+\r
+ Status = gBS->AllocatePages(AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (Size), &MemoryAddress);\r
+ ASSERT_EFI_ERROR (Status);\r
+ ZeroMem ((VOID *)(UINTN)MemoryAddress, Size);\r
+ OpRegion->RegionOffset = (UINT32) (UINTN) MemoryAddress;\r
+ OpRegion->RegionLen = (UINT8) Size;\r
+ break;\r
+ }\r
+ }\r
+\r
+ return (VOID *) (UINTN) MemoryAddress;\r
+}\r
+\r
+/**\r
+ Locate the MM communication buffer and protocol, then use it to exchange information with\r
+ Tcg2StandaloneMmm on NVS address and SMI value.\r
+\r
+ @param[in, out] TcgNvs The NVS subject to send to MM environment.\r
+\r
+ @return The status for locating MM common buffer, communicate to MM, etc.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ExchangeCommonBuffer (\r
+ IN OUT TCG_NVS *TcgNvs\r
+)\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_MM_COMMUNICATION_PROTOCOL *MmCommunication;\r
+ EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable;\r
+ EFI_MEMORY_DESCRIPTOR *MmCommMemRegion;\r
+ EFI_MM_COMMUNICATE_HEADER *CommHeader;\r
+ TPM_NVS_MM_COMM_BUFFER *CommBuffer;\r
+ UINTN CommBufferSize;\r
+ UINTN Index;\r
+\r
+ // Step 0: Sanity check for input argument\r
+ if (TcgNvs == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "%a - Input argument is NULL!\n", __FUNCTION__));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ // Step 1: Grab the common buffer header\r
+ Status = EfiGetSystemConfigurationTable (&gEdkiiPiSmmCommunicationRegionTableGuid, (VOID**) &PiSmmCommunicationRegionTable);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "%a - Failed to locate SMM communciation common buffer - %r!\n", __FUNCTION__, Status));\r
+ return Status;\r
+ }\r
+\r
+ // Step 2: Grab one that is large enough to hold TPM_NVS_MM_COMM_BUFFER, the IPL one should be sufficient\r
+ CommBufferSize = 0;\r
+ MmCommMemRegion = (EFI_MEMORY_DESCRIPTOR*) (PiSmmCommunicationRegionTable + 1);\r
+ for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {\r
+ if (MmCommMemRegion->Type == EfiConventionalMemory) {\r
+ CommBufferSize = EFI_PAGES_TO_SIZE ((UINTN)MmCommMemRegion->NumberOfPages);\r
+ if (CommBufferSize >= (sizeof (TPM_NVS_MM_COMM_BUFFER) + OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data))) {\r
+ break;\r
+ }\r
+ }\r
+ MmCommMemRegion = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)MmCommMemRegion + PiSmmCommunicationRegionTable->DescriptorSize);\r
+ }\r
+\r
+ if (Index >= PiSmmCommunicationRegionTable->NumberOfEntries) {\r
+ // Could not find one that meets our goal...\r
+ DEBUG ((DEBUG_ERROR, "%a - Could not find a common buffer that is big enough for NVS!\n", __FUNCTION__));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ // Step 3: Start to populate contents\r
+ // Step 3.1: MM Communication common header\r
+ CommHeader = (EFI_MM_COMMUNICATE_HEADER *) (UINTN) MmCommMemRegion->PhysicalStart;\r
+ CommBufferSize = sizeof (TPM_NVS_MM_COMM_BUFFER) + OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data);\r
+ ZeroMem (CommHeader, CommBufferSize);\r
+ CopyGuid (&CommHeader->HeaderGuid, &gTpmNvsMmGuid);\r
+ CommHeader->MessageLength = sizeof (TPM_NVS_MM_COMM_BUFFER);\r
+\r
+ // Step 3.2: TPM_NVS_MM_COMM_BUFFER content per our needs\r
+ CommBuffer = (TPM_NVS_MM_COMM_BUFFER *) (CommHeader->Data);\r
+ CommBuffer->Function = TpmNvsMmExchangeInfo;\r
+ CommBuffer->TargetAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) TcgNvs;\r
+\r
+ // Step 4: Locate the protocol and signal Mmi.\r
+ Status = gBS->LocateProtocol (&gEfiMmCommunicationProtocolGuid, NULL, (VOID**) &MmCommunication);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = MmCommunication->Communicate (MmCommunication, CommHeader, &CommBufferSize);\r
+ DEBUG ((DEBUG_INFO, "%a - Communicate() = %r\n", __FUNCTION__, Status));\r
+ }\r
+ else {\r
+ DEBUG ((DEBUG_ERROR, "%a - Failed to locate MmCommunication protocol - %r\n", __FUNCTION__, Status));\r
+ return Status;\r
+ }\r
+\r
+ // Step 5: If everything goes well, populate the channel number\r
+ if (!EFI_ERROR (CommBuffer->ReturnStatus)) {\r
+ // Need to demote to UINT8 according to SMI value definition\r
+ TcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) CommBuffer->RegisteredPpSwiValue;\r
+ TcgNvs->MemoryClear.SoftwareSmi = (UINT8) CommBuffer->RegisteredMcSwiValue;\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "%a Communication returned software SMI value. PP: 0x%x; MC: 0x%x.\n",\r
+ __FUNCTION__,\r
+ TcgNvs->PhysicalPresence.SoftwareSmi,\r
+ TcgNvs->MemoryClear.SoftwareSmi\r
+ ));\r
+ }\r
+\r
+ return (EFI_STATUS) CommBuffer->ReturnStatus;\r
+}\r
+\r
+/**\r
+ Patch version string of Physical Presence interface supported by platform. The initial string tag in TPM\r
+ACPI table is "$PV".\r
+\r
+ @param[in, out] Table The TPM item in ACPI table.\r
+ @param[in] PPVer Version string of Physical Presence interface supported by platform.\r
+\r
+ @return The allocated address for the found region.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdatePPVersion (\r
+ EFI_ACPI_DESCRIPTION_HEADER *Table,\r
+ CHAR8 *PPVer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 *DataPtr;\r
+\r
+ //\r
+ // Patch some pointers for the ASL code before loading the SSDT.\r
+ //\r
+ for (DataPtr = (UINT8 *)(Table + 1);\r
+ DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - PHYSICAL_PRESENCE_VERSION_SIZE);\r
+ DataPtr += 1) {\r
+ if (AsciiStrCmp((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_TAG) == 0) {\r
+ Status = AsciiStrCpyS((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_SIZE, PPVer);\r
+ DEBUG((DEBUG_INFO, "TPM2 Physical Presence Interface Version update status 0x%x\n", Status));\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Patch interrupt resources returned by TPM _PRS. ResourceTemplate to patch is determined by input\r
+ interrupt buffer size. BufferSize, PkgLength and interrupt descriptor in ByteList need to be patched\r
+\r
+ @param[in, out] Table The TPM item in ACPI table.\r
+ @param[in] IrqBuffer Input new IRQ buffer.\r
+ @param[in] IrqBuffserSize Input new IRQ buffer size.\r
+ @param[out] IsShortFormPkgLength If _PRS returns Short length Package(ACPI spec 20.2.4).\r
+\r
+ @return patch status.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdatePossibleResource (\r
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *Table,\r
+ IN UINT32 *IrqBuffer,\r
+ IN UINT32 IrqBuffserSize,\r
+ OUT BOOLEAN *IsShortFormPkgLength\r
+ )\r
+{\r
+ UINT8 *DataPtr;\r
+ UINT8 *DataEndPtr;\r
+ UINT32 NewPkgLength;\r
+ UINT32 OrignalPkgLength;\r
+\r
+ NewPkgLength = 0;\r
+ OrignalPkgLength = 0;\r
+ DataEndPtr = NULL;\r
+\r
+ //\r
+ // Follow ACPI spec\r
+ // 6.4.3 Extend Interrupt Descriptor.\r
+ // 19.3.3 ASL Resource Template\r
+ // 20 AML specification\r
+ // to patch TPM ACPI object _PRS returned ResourceTemplate() containing 2 resource descriptors and an auto appended End Tag\r
+ //\r
+ // AML data is organized by following rule.\r
+ // Code need to patch BufferSize and PkgLength and interrupt descriptor in ByteList\r
+ //\r
+ // ============= Buffer ====================\r
+ // DefBuffer := BufferOp PkgLength BufferSize ByteList\r
+ // BufferOp := 0x11\r
+ //\r
+ // ==============PkgLength==================\r
+ // PkgLength := PkgLeadByte |\r
+ // <PkgLeadByte ByteData> |\r
+ // <PkgLeadByte ByteData ByteData> |\r
+ // <PkgLeadByte ByteData ByteData ByteData>\r
+ //\r
+ // PkgLeadByte := <bit 7-6: ByteData count that follows (0-3)>\r
+ // <bit 5-4: Only used if PkgLength <= 63 >\r
+ // <bit 3-0: Least significant package length nybble>\r
+ //\r
+ //==============BufferSize==================\r
+ // BufferSize := Integer\r
+ // Integer := ByteConst|WordConst|DwordConst....\r
+ //\r
+ // ByteConst := BytePrefix ByteData\r
+ //\r
+ //==============ByteList===================\r
+ // ByteList := ByteData ByteList\r
+ //\r
+ //=========================================\r
+\r
+ //\r
+ // 1. Check TPM_PRS_RESS with PkgLength <=63 can hold the input interrupt number buffer for patching\r
+ //\r
+ for (DataPtr = (UINT8 *)(Table + 1);\r
+ DataPtr < (UINT8 *) ((UINT8 *) Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));\r
+ DataPtr += 1) {\r
+ if (CompareMem(DataPtr, TPM_PRS_RESS, TPM_PRS_RES_NAME_SIZE) == 0) {\r
+ //\r
+ // Jump over object name & BufferOp\r
+ //\r
+ DataPtr += TPM_PRS_RES_NAME_SIZE + 1;\r
+\r
+ if ((*DataPtr & (BIT7|BIT6)) == 0) {\r
+ OrignalPkgLength = (UINT32)*DataPtr;\r
+ DataEndPtr = DataPtr + OrignalPkgLength;\r
+\r
+ //\r
+ // Jump over PkgLength = PkgLeadByte only\r
+ //\r
+ NewPkgLength++;\r
+\r
+ //\r
+ // Jump over BufferSize\r
+ //\r
+ if (*(DataPtr + 1) == AML_BYTE_PREFIX) {\r
+ NewPkgLength += 2;\r
+ } else if (*(DataPtr + 1) == AML_WORD_PREFIX) {\r
+ NewPkgLength += 3;\r
+ } else if (*(DataPtr + 1) == AML_DWORD_PREFIX) {\r
+ NewPkgLength += 5;\r
+ } else {\r
+ ASSERT(FALSE);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ } else {\r
+ ASSERT(FALSE);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Include Memory32Fixed Descriptor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)\r
+ //\r
+ NewPkgLength += 19 + IrqBuffserSize;\r
+ if (NewPkgLength > 63) {\r
+ break;\r
+ }\r
+\r
+ if (NewPkgLength > OrignalPkgLength) {\r
+ ASSERT(FALSE);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // 1.1 Patch PkgLength\r
+ //\r
+ *DataPtr = (UINT8)NewPkgLength;\r
+\r
+ //\r
+ // 1.2 Patch BufferSize = sizeof(Memory32Fixed Descriptor + Interrupt Descriptor + End Tag).\r
+ // It is Little endian. So only patch lowest byte of BufferSize due to current interrupt number limit.\r
+ //\r
+ *(DataPtr + 2) = (UINT8)(IrqBuffserSize + 19);\r
+\r
+ //\r
+ // Notify _PRS to report short formed ResourceTemplate\r
+ //\r
+ *IsShortFormPkgLength = TRUE;\r
+\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // 2. Use TPM_PRS_RESL with PkgLength > 63 to hold longer input interrupt number buffer for patching\r
+ //\r
+ if (NewPkgLength > 63) {\r
+ NewPkgLength = 0;\r
+ OrignalPkgLength = 0;\r
+ for (DataPtr = (UINT8 *)(Table + 1);\r
+ DataPtr < (UINT8 *) ((UINT8 *) Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));\r
+ DataPtr += 1) {\r
+ if (CompareMem(DataPtr, TPM_PRS_RESL, TPM_PRS_RES_NAME_SIZE) == 0) {\r
+ //\r
+ // Jump over object name & BufferOp\r
+ //\r
+ DataPtr += TPM_PRS_RES_NAME_SIZE + 1;\r
+\r
+ if ((*DataPtr & (BIT7|BIT6)) != 0) {\r
+ OrignalPkgLength = (UINT32)(*(DataPtr + 1) << 4) + (*DataPtr & 0x0F);\r
+ DataEndPtr = DataPtr + OrignalPkgLength;\r
+ //\r
+ // Jump over PkgLength = PkgLeadByte + ByteData length\r
+ //\r
+ NewPkgLength += 1 + ((*DataPtr & (BIT7|BIT6)) >> 6);\r
+\r
+ //\r
+ // Jump over BufferSize\r
+ //\r
+ if (*(DataPtr + NewPkgLength) == AML_BYTE_PREFIX) {\r
+ NewPkgLength += 2;\r
+ } else if (*(DataPtr + NewPkgLength) == AML_WORD_PREFIX) {\r
+ NewPkgLength += 3;\r
+ } else if (*(DataPtr + NewPkgLength) == AML_DWORD_PREFIX) {\r
+ NewPkgLength += 5;\r
+ } else {\r
+ ASSERT(FALSE);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ } else {\r
+ ASSERT(FALSE);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Include Memory32Fixed Descriptor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)\r
+ //\r
+ NewPkgLength += 19 + IrqBuffserSize;\r
+\r
+ if (NewPkgLength > OrignalPkgLength) {\r
+ ASSERT(FALSE);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // 2.1 Patch PkgLength. Only patch PkgLeadByte and first ByteData\r
+ //\r
+ *DataPtr = (UINT8)((*DataPtr) & 0xF0) | (NewPkgLength & 0x0F);\r
+ *(DataPtr + 1) = (UINT8)((NewPkgLength & 0xFF0) >> 4);\r
+\r
+ //\r
+ // 2.2 Patch BufferSize = sizeof(Memory32Fixed Descriptor + Interrupt Descriptor + End Tag).\r
+ // It is Little endian. Only patch lowest byte of BufferSize due to current interrupt number limit.\r
+ //\r
+ *(DataPtr + 2 + ((*DataPtr & (BIT7|BIT6)) >> 6)) = (UINT8)(IrqBuffserSize + 19);\r
+\r
+ //\r
+ // Notify _PRS to report long formed ResourceTemplate\r
+ //\r
+ *IsShortFormPkgLength = FALSE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (DataPtr >= (UINT8 *) ((UINT8 *) Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE))) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // 3. Move DataPtr to Interrupt descriptor header and patch interrupt descriptor.\r
+ // 5 bytes for interrupt descriptor header, 2 bytes for End Tag\r
+ //\r
+ DataPtr += NewPkgLength - (5 + IrqBuffserSize + 2);\r
+ //\r
+ // 3.1 Patch Length bit[7:0] of Interrupt descriptor patch interrupt descriptor\r
+ //\r
+ *(DataPtr + 1) = (UINT8)(2 + IrqBuffserSize);\r
+ //\r
+ // 3.2 Patch Interrupt Table Length\r
+ //\r
+ *(DataPtr + 4) = (UINT8)(IrqBuffserSize / sizeof(UINT32));\r
+ //\r
+ // 3.3 Copy patched InterruptNumBuffer\r
+ //\r
+ CopyMem(DataPtr + 5, IrqBuffer, IrqBuffserSize);\r
+\r
+ //\r
+ // 4. Jump over Interrupt descriptor and Patch END Tag, set Checksum field to 0\r
+ //\r
+ DataPtr += 5 + IrqBuffserSize;\r
+ *DataPtr = ACPI_END_TAG_DESCRIPTOR;\r
+ *(DataPtr + 1) = 0;\r
+\r
+ //\r
+ // 5. Jump over new ResourceTemplate. Stuff rest bytes to NOOP\r
+ //\r
+ DataPtr += 2;\r
+ if (DataPtr < DataEndPtr) {\r
+ SetMem(DataPtr, (UINTN)DataEndPtr - (UINTN)DataPtr, AML_NOOP_OP);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Patch TPM2 device HID string. The initial string tag in TPM2 ACPI table is "NNN0000".\r
+\r
+ @param[in, out] Table The TPM2 SSDT ACPI table.\r
+\r
+ @return HID Update status.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdateHID (\r
+ EFI_ACPI_DESCRIPTION_HEADER *Table\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 *DataPtr;\r
+ CHAR8 Hid[TPM_HID_ACPI_SIZE];\r
+ UINT32 ManufacturerID;\r
+ UINT32 FirmwareVersion1;\r
+ UINT32 FirmwareVersion2;\r
+ BOOLEAN PnpHID;\r
+\r
+ PnpHID = TRUE;\r
+\r
+ //\r
+ // Initialize HID with Default PNP string\r
+ //\r
+ ZeroMem(Hid, TPM_HID_ACPI_SIZE);\r
+\r
+ //\r
+ // Get Manufacturer ID\r
+ //\r
+ Status = Tpm2GetCapabilityManufactureID(&ManufacturerID);\r
+ if (!EFI_ERROR(Status)) {\r
+ DEBUG((DEBUG_INFO, "TPM_PT_MANUFACTURER 0x%08x\n", ManufacturerID));\r
+ //\r
+ // ManufacturerID defined in TCG Vendor ID Registry\r
+ // may tailed with 0x00 or 0x20\r
+ //\r
+ if ((ManufacturerID >> 24) == 0x00 || ((ManufacturerID >> 24) == 0x20)) {\r
+ //\r
+ // HID containing PNP ID "NNN####"\r
+ // NNN is uppercase letter for Vendor ID specified by manufacturer\r
+ //\r
+ CopyMem(Hid, &ManufacturerID, 3);\r
+ } else {\r
+ //\r
+ // HID containing ACP ID "NNNN####"\r
+ // NNNN is uppercase letter for Vendor ID specified by manufacturer\r
+ //\r
+ CopyMem(Hid, &ManufacturerID, 4);\r
+ PnpHID = FALSE;\r
+ }\r
+ } else {\r
+ DEBUG ((DEBUG_ERROR, "Get TPM_PT_MANUFACTURER failed %x!\n", Status));\r
+ ASSERT(FALSE);\r
+ return Status;\r
+ }\r
+\r
+ Status = Tpm2GetCapabilityFirmwareVersion(&FirmwareVersion1, &FirmwareVersion2);\r
+ if (!EFI_ERROR(Status)) {\r
+ DEBUG((DEBUG_INFO, "TPM_PT_FIRMWARE_VERSION_1 0x%x\n", FirmwareVersion1));\r
+ DEBUG((DEBUG_INFO, "TPM_PT_FIRMWARE_VERSION_2 0x%x\n", FirmwareVersion2));\r
+ //\r
+ // #### is Firmware Version 1\r
+ //\r
+ if (PnpHID) {\r
+ AsciiSPrint(Hid + 3, TPM_HID_PNP_SIZE - 3, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 & 0x0000FFFF));\r
+ } else {\r
+ AsciiSPrint(Hid + 4, TPM_HID_ACPI_SIZE - 4, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 & 0x0000FFFF));\r
+ }\r
+\r
+ } else {\r
+ DEBUG ((DEBUG_ERROR, "Get TPM_PT_FIRMWARE_VERSION_X failed %x!\n", Status));\r
+ ASSERT(FALSE);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Patch HID in ASL code before loading the SSDT.\r
+ //\r
+ for (DataPtr = (UINT8 *)(Table + 1);\r
+ DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - TPM_HID_PNP_SIZE);\r
+ DataPtr += 1) {\r
+ if (AsciiStrCmp((CHAR8 *)DataPtr, TPM_HID_TAG) == 0) {\r
+ if (PnpHID) {\r
+ CopyMem(DataPtr, Hid, TPM_HID_PNP_SIZE);\r
+ //\r
+ // if HID is PNP ID, patch the last byte in HID TAG to Noop\r
+ //\r
+ *(DataPtr + TPM_HID_PNP_SIZE) = AML_NOOP_OP;\r
+ } else {\r
+\r
+ CopyMem(DataPtr, Hid, TPM_HID_ACPI_SIZE);\r
+ }\r
+ DEBUG((DEBUG_INFO, "TPM2 ACPI _HID is patched to %a\n", DataPtr));\r
+\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ DEBUG((DEBUG_ERROR, "TPM2 ACPI HID TAG for patch not found!\n"));\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Initialize and publish TPM items in ACPI table.\r
+\r
+ @retval EFI_SUCCESS The TCG ACPI table is published successfully.\r
+ @retval Others The TCG ACPI table is not published.\r
+\r
+**/\r
+EFI_STATUS\r
+PublishAcpiTable (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
+ UINTN TableKey;\r
+ EFI_ACPI_DESCRIPTION_HEADER *Table;\r
+ UINTN TableSize;\r
+ UINT32 *PossibleIrqNumBuf;\r
+ UINT32 PossibleIrqNumBufSize;\r
+ BOOLEAN IsShortFormPkgLength;\r
+\r
+ IsShortFormPkgLength = FALSE;\r
+\r
+ Status = GetSectionFromFv (\r
+ &gEfiCallerIdGuid,\r
+ EFI_SECTION_RAW,\r
+ 0,\r
+ (VOID **) &Table,\r
+ &TableSize\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Measure to PCR[0] with event EV_POST_CODE ACPI DATA.\r
+ // The measurement has to be done before any update.\r
+ // Otherwise, the PCR record would be different after TPM FW update\r
+ // or the PCD configuration change.\r
+ //\r
+ TpmMeasureAndLogData(\r
+ 0,\r
+ EV_POST_CODE,\r
+ EV_POSTCODE_INFO_ACPI_DATA,\r
+ ACPI_DATA_LEN,\r
+ Table,\r
+ TableSize\r
+ );\r
+\r
+ //\r
+ // Update Table version before measuring it to PCR\r
+ //\r
+ Status = UpdatePPVersion(Table, (CHAR8 *)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer));\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "Current physical presence interface version - %a\n",\r
+ (CHAR8 *) PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer)\r
+ ));\r
+\r
+ //\r
+ // Update TPM2 HID after measuring it to PCR\r
+ //\r
+ Status = UpdateHID(Table);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (PcdGet32(PcdTpm2CurrentIrqNum) != 0) {\r
+ //\r
+ // Patch _PRS interrupt resource only when TPM interrupt is supported\r
+ //\r
+ PossibleIrqNumBuf = (UINT32 *)PcdGetPtr(PcdTpm2PossibleIrqNumBuf);\r
+ PossibleIrqNumBufSize = (UINT32)PcdGetSize(PcdTpm2PossibleIrqNumBuf);\r
+\r
+ if (PossibleIrqNumBufSize <= MAX_PRS_INT_BUF_SIZE && (PossibleIrqNumBufSize % sizeof(UINT32)) == 0) {\r
+ Status = UpdatePossibleResource(Table, PossibleIrqNumBuf, PossibleIrqNumBufSize, &IsShortFormPkgLength);\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "UpdatePossibleResource status - %x. TPM2 service may not ready in OS.\n",\r
+ Status\r
+ ));\r
+ } else {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "PcdTpm2PossibleIrqNumBuf size %x is not correct. TPM2 service may not ready in OS.\n",\r
+ PossibleIrqNumBufSize\r
+ ));\r
+ }\r
+ }\r
+\r
+ ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));\r
+ CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId) );\r
+ mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));\r
+ ASSERT (mTcgNvs != NULL);\r
+ mTcgNvs->TpmIrqNum = PcdGet32(PcdTpm2CurrentIrqNum);\r
+ mTcgNvs->IsShortFormPkgLength = IsShortFormPkgLength;\r
+\r
+ Status = ExchangeCommonBuffer (mTcgNvs);\r
+\r
+ //\r
+ // Publish the TPM ACPI table. Table is re-checksummed.\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ TableKey = 0;\r
+ Status = AcpiTable->InstallAcpiTable (\r
+ AcpiTable,\r
+ Table,\r
+ TableSize,\r
+ &TableKey\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Publish TPM2 ACPI table\r
+\r
+ @retval EFI_SUCCESS The TPM2 ACPI table is published successfully.\r
+ @retval Others The TPM2 ACPI table is not published.\r
+\r
+**/\r
+EFI_STATUS\r
+PublishTpm2 (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
+ UINTN TableKey;\r
+ UINT64 OemTableId;\r
+ EFI_TPM2_ACPI_CONTROL_AREA *ControlArea;\r
+ TPM2_PTP_INTERFACE_TYPE InterfaceType;\r
+\r
+ //\r
+ // Measure to PCR[0] with event EV_POST_CODE ACPI DATA.\r
+ // The measurement has to be done before any update.\r
+ // Otherwise, the PCR record would be different after event log update\r
+ // or the PCD configuration change.\r
+ //\r
+ TpmMeasureAndLogData(\r
+ 0,\r
+ EV_POST_CODE,\r
+ EV_POSTCODE_INFO_ACPI_DATA,\r
+ ACPI_DATA_LEN,\r
+ &mTpm2AcpiTemplate,\r
+ mTpm2AcpiTemplate.Header.Length\r
+ );\r
+\r
+ mTpm2AcpiTemplate.Header.Revision = PcdGet8(PcdTpm2AcpiTableRev);\r
+ DEBUG((DEBUG_INFO, "Tpm2 ACPI table revision is %d\n", mTpm2AcpiTemplate.Header.Revision));\r
+\r
+ //\r
+ // PlatformClass is only valid for version 4 and above\r
+ // BIT0~15: PlatformClass\r
+ // BIT16~31: Reserved\r
+ //\r
+ if (mTpm2AcpiTemplate.Header.Revision >= EFI_TPM2_ACPI_TABLE_REVISION_4) {\r
+ mTpm2AcpiTemplate.Flags = (mTpm2AcpiTemplate.Flags & 0xFFFF0000) | PcdGet8(PcdTpmPlatformClass);\r
+ DEBUG((DEBUG_INFO, "Tpm2 ACPI table PlatformClass is %d\n", (mTpm2AcpiTemplate.Flags & 0x0000FFFF)));\r
+ }\r
+\r
+ mTpm2AcpiTemplate.Laml = PcdGet32(PcdTpm2AcpiTableLaml);\r
+ mTpm2AcpiTemplate.Lasa = PcdGet64(PcdTpm2AcpiTableLasa);\r
+ if ((mTpm2AcpiTemplate.Header.Revision < EFI_TPM2_ACPI_TABLE_REVISION_4) ||\r
+ (mTpm2AcpiTemplate.Laml == 0) || (mTpm2AcpiTemplate.Lasa == 0)) {\r
+ //\r
+ // If version is smaller than 4 or Laml/Lasa is not valid, rollback to original Length.\r
+ //\r
+ mTpm2AcpiTemplate.Header.Length = sizeof(EFI_TPM2_ACPI_TABLE);\r
+ }\r
+\r
+ InterfaceType = PcdGet8(PcdActiveTpmInterfaceType);\r
+ switch (InterfaceType) {\r
+ case Tpm2PtpInterfaceCrb:\r
+ mTpm2AcpiTemplate.StartMethod = EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE;\r
+ mTpm2AcpiTemplate.AddressOfControlArea = PcdGet64 (PcdTpmBaseAddress) + 0x40;\r
+ ControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *)(UINTN)mTpm2AcpiTemplate.AddressOfControlArea;\r
+ ControlArea->CommandSize = 0xF80;\r
+ ControlArea->ResponseSize = 0xF80;\r
+ ControlArea->Command = PcdGet64 (PcdTpmBaseAddress) + 0x80;\r
+ ControlArea->Response = PcdGet64 (PcdTpmBaseAddress) + 0x80;\r
+ break;\r
+ case Tpm2PtpInterfaceFifo:\r
+ case Tpm2PtpInterfaceTis:\r
+ break;\r
+ default:\r
+ DEBUG((DEBUG_ERROR, "TPM2 InterfaceType get error! %d\n", InterfaceType));\r
+ break;\r
+ }\r
+\r
+ CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));\r
+ OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
+ CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
+ mTpm2AcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
+ mTpm2AcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
+ mTpm2AcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
+\r
+ //\r
+ // Construct ACPI table\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = AcpiTable->InstallAcpiTable (\r
+ AcpiTable,\r
+ &mTpm2AcpiTemplate,\r
+ mTpm2AcpiTemplate.Header.Length,\r
+ &TableKey\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ The driver's entry point.\r
+\r
+ It patches and installs ACPI tables used for handling TPM physical presence\r
+ and Memory Clear requests through ACPI method.\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval Others Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeTcgAcpi (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)){\r
+ DEBUG ((DEBUG_ERROR, "No TPM2 DTPM instance required!\n"));\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = PublishAcpiTable ();\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Set TPM2 ACPI table\r
+ //\r
+ Status = PublishTpm2 ();\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
--- /dev/null
+## @file\r
+# Provides ACPI methods for TPM 2.0 support\r
+#\r
+# Spec Compliance Info:\r
+# "TCG ACPI Specification Version 1.2 Revision 8"\r
+# "Physical Presence Interface Specification Version 1.30 Revision 00.52"\r
+# along with\r
+# "Errata Version 0.4 for TCG PC Client Platform Physical Presence Interface Specification"\r
+# "Platform Reset Attack Mitigation Specification Version 1.00"\r
+# TPM2.0 ACPI device object\r
+# "TCG PC Client Platform Firmware Profile Specification for TPM Family 2.0 Level 00 Revision 1.03 v51"\r
+# along with\r
+# "Errata for PC Client Specific Platform Firmware Profile Specification Version 1.0 Revision 1.03"\r
+#\r
+# This driver implements TPM 2.0 definition block in ACPI table and\r
+# populates registered SMI callback functions for Tcg2 physical presence\r
+# and MemoryClear to handle the requests for ACPI method. It needs to be\r
+# used together with Tcg2 MM drivers to exchange information on registered\r
+# SwSmiValue and allocated NVS region address.\r
+#\r
+# Caution: This module requires additional review when modified.\r
+# This driver will have external input - variable and ACPINvs data in SMM mode.\r
+# This external input must be validated carefully to avoid security issue.\r
+#\r
+# Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) Microsoft Corporation.<BR>\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = Tcg2Acpi\r
+ FILE_GUID = 0D4BBF18-C2CC-4C23-BD63-BFDAD4C710D0\r
+ MODULE_TYPE = DXE_DRIVER\r
+ PI_SPECIFICATION_VERSION = 0x0001000A\r
+ VERSION_STRING = 1.0\r
+ ENTRY_POINT = InitializeTcgAcpi\r
+\r
+[Sources]\r
+ Tcg2Acpi.c\r
+ Tpm.asl\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ SecurityPkg/SecurityPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ BaseMemoryLib\r
+ UefiDriverEntryPoint\r
+ UefiBootServicesTableLib\r
+ DebugLib\r
+ DxeServicesLib\r
+ TpmMeasurementLib\r
+ Tpm2CommandLib\r
+ Tcg2PhysicalPresenceLib\r
+ PcdLib\r
+\r
+[Guids]\r
+ gEfiTpmDeviceInstanceTpm20DtpmGuid ## PRODUCES ## GUID # TPM device identifier\r
+ gTpmNvsMmGuid ## CONSUMES\r
+ gEdkiiPiSmmCommunicationRegionTableGuid ## CONSUMES\r
+\r
+[Protocols]\r
+ gEfiAcpiTableProtocolGuid ## CONSUMES\r
+ gEfiMmCommunicationProtocolGuid ## CONSUMES\r
+\r
+[FixedPcd]\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdSmiCommandIoPort ## CONSUMES\r
+\r
+[Pcd]\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid ## CONSUMES\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## SOMETIMES_CONSUMES\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## SOMETIMES_CONSUMES\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## SOMETIMES_CONSUMES\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## SOMETIMES_CONSUMES\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## SOMETIMES_CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer ## CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev ## CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass ## SOMETIMES_CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpm2CurrentIrqNum ## CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpm2PossibleIrqNumBuf ## CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType ## CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLaml ## CONSUMES\r
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLasa ## CONSUMES\r
+\r
+[Depex]\r
+ gEfiAcpiTableProtocolGuid AND\r
+ gTcg2MmSwSmiRegisteredGuid AND\r
+ gEfiTcg2ProtocolGuid\r
--- /dev/null
+/** @file\r
+ The TPM2 definition block in ACPI table for TCG2 physical presence\r
+ and MemoryClear.\r
+\r
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(c)Copyright 2016 HP Development Company, L.P.<BR>\r
+Copyright (c) Microsoft Corporation.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+DefinitionBlock (\r
+ "Tpm.aml",\r
+ "SSDT",\r
+ 2,\r
+ "INTEL ",\r
+ "Tpm2Tabl",\r
+ 0x1000\r
+ )\r
+{\r
+ Scope (\_SB)\r
+ {\r
+ Device (TPM)\r
+ {\r
+ //\r
+ // TCG2\r
+ //\r
+\r
+ //\r
+ // TAG for patching TPM2.0 _HID\r
+ //\r
+ Name (_HID, "NNNN0000")\r
+\r
+ Name (_CID, "MSFT0101")\r
+\r
+ //\r
+ // Readable name of this device, don't know if this way is correct yet\r
+ //\r
+ Name (_STR, Unicode ("TPM 2.0 Device"))\r
+\r
+ //\r
+ // Operational region for Smi port access\r
+ //\r
+ OperationRegion (SMIP, SystemIO, FixedPcdGet16 (PcdSmiCommandIoPort), 1)\r
+ Field (SMIP, ByteAcc, NoLock, Preserve)\r
+ {\r
+ IOPN, 8\r
+ }\r
+\r
+ //\r
+ // Operational region for TPM access\r
+ //\r
+ OperationRegion (TPMR, SystemMemory, 0xfed40000, 0x5000)\r
+ Field (TPMR, AnyAcc, NoLock, Preserve)\r
+ {\r
+ ACC0, 8, // TPM_ACCESS_0\r
+ Offset(0x8),\r
+ INTE, 32, // TPM_INT_ENABLE_0\r
+ INTV, 8, // TPM_INT_VECTOR_0\r
+ Offset(0x10),\r
+ INTS, 32, // TPM_INT_STATUS_0\r
+ INTF, 32, // TPM_INTF_CAPABILITY_0\r
+ STS0, 32, // TPM_STS_0\r
+ Offset(0x24),\r
+ FIFO, 32, // TPM_DATA_FIFO_0\r
+ Offset(0x30),\r
+ TID0, 32, // TPM_INTERFACE_ID_0\r
+ // ignore the rest\r
+ }\r
+\r
+ //\r
+ // Operational region for TPM support, TPM Physical Presence and TPM Memory Clear\r
+ // Region Offset 0xFFFF0000 and Length 0xF0 will be fixed in C code.\r
+ //\r
+ OperationRegion (TNVS, SystemMemory, 0xFFFF0000, 0xF0)\r
+ Field (TNVS, AnyAcc, NoLock, Preserve)\r
+ {\r
+ PPIN, 8, // Software SMI for Physical Presence Interface\r
+ PPIP, 32, // Used for save physical presence parameter\r
+ PPRP, 32, // Physical Presence request operation response\r
+ PPRQ, 32, // Physical Presence request operation\r
+ PPRM, 32, // Physical Presence request operation parameter\r
+ LPPR, 32, // Last Physical Presence request operation\r
+ FRET, 32, // Physical Presence function return code\r
+ MCIN, 8, // Software SMI for Memory Clear Interface\r
+ MCIP, 32, // Used for save the Mor parameter\r
+ MORD, 32, // Memory Overwrite Request Data\r
+ MRET, 32, // Memory Overwrite function return code\r
+ UCRQ, 32, // Physical Presence request operation to Get User Confirmation Status\r
+ IRQN, 32, // IRQ Number for _CRS\r
+ SFRB, 8 // Is shortformed Pkglength for resource buffer\r
+ }\r
+\r
+ //\r
+ // Possible resource settings returned by _PRS method\r
+ // RESS : ResourceTemplate with PkgLength <=63\r
+ // RESL : ResourceTemplate with PkgLength > 63\r
+ //\r
+ // The format of the data has to follow the same format as\r
+ // _CRS (according to ACPI spec).\r
+ //\r
+ Name (RESS, ResourceTemplate() {\r
+ Memory32Fixed (ReadWrite, 0xfed40000, 0x5000)\r
+ Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , ) {1,2,3,4,5,6,7,8,9,10}\r
+ })\r
+\r
+ Name (RESL, ResourceTemplate() {\r
+ Memory32Fixed (ReadWrite, 0xfed40000, 0x5000)\r
+ Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , ) {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}\r
+ })\r
+\r
+ //\r
+ // Current resource settings for _CRS method\r
+ //\r
+ Name(RES0, ResourceTemplate () {\r
+ Memory32Fixed (ReadWrite, 0xfed40000, 0x5000, REG0)\r
+ Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , INTR) {12}\r
+ })\r
+\r
+ Name(RES1, ResourceTemplate () {\r
+ Memory32Fixed (ReadWrite, 0xfed40000, 0x5000, REG1)\r
+ })\r
+\r
+\r
+ //\r
+ // Return the resource consumed by TPM device.\r
+ //\r
+ Method(_CRS,0,Serialized)\r
+ {\r
+ //\r
+ // IRQNum = 0 means disable IRQ support\r
+ //\r
+ If (LEqual(IRQN, 0)) {\r
+ Return (RES1)\r
+ }\r
+ Else\r
+ {\r
+ CreateDWordField(RES0, ^INTR._INT, LIRQ)\r
+ Store(IRQN, LIRQ)\r
+ Return (RES0)\r
+ }\r
+ }\r
+\r
+ //\r
+ // Set resources consumed by the TPM device. This is used to\r
+ // assign an interrupt number to the device. The input byte stream\r
+ // has to be the same as returned by _CRS (according to ACPI spec).\r
+ //\r
+ // Platform may choose to override this function with specific interrupt\r
+ // programing logic to replace FIFO/TIS SIRQ registers programing\r
+ //\r
+ Method(_SRS,1,Serialized)\r
+ {\r
+ //\r
+ // Do not configure Interrupt if IRQ Num is configured 0 by default\r
+ //\r
+ If (LNotEqual(IRQN, 0)) {\r
+ //\r
+ // Update resource descriptor\r
+ // Use the field name to identify the offsets in the argument\r
+ // buffer and RES0 buffer.\r
+ //\r
+ CreateDWordField(Arg0, ^INTR._INT, IRQ0)\r
+ CreateDWordField(RES0, ^INTR._INT, LIRQ)\r
+ Store(IRQ0, LIRQ)\r
+ Store(IRQ0, IRQN)\r
+\r
+ CreateBitField(Arg0, ^INTR._HE, ITRG)\r
+ CreateBitField(RES0, ^INTR._HE, LTRG)\r
+ Store(ITRG, LTRG)\r
+\r
+ CreateBitField(Arg0, ^INTR._LL, ILVL)\r
+ CreateBitField(RES0, ^INTR._LL, LLVL)\r
+ Store(ILVL, LLVL)\r
+\r
+ //\r
+ // Update TPM FIFO PTP/TIS interface only, identified by TPM_INTERFACE_ID_x lowest\r
+ // nibble.\r
+ // 0000 - FIFO interface as defined in PTP for TPM 2.0 is active\r
+ // 1111 - FIFO interface as defined in TIS1.3 is active\r
+ //\r
+ If (LOr(LEqual (And (TID0, 0x0F), 0x00), LEqual (And (TID0, 0x0F), 0x0F))) {\r
+ //\r
+ // If FIFO interface, interrupt vector register is\r
+ // available. TCG PTP specification allows only\r
+ // values 1..15 in this field. For other interrupts\r
+ // the field should stay 0.\r
+ //\r
+ If (LLess (IRQ0, 16)) {\r
+ Store (And(IRQ0, 0xF), INTV)\r
+ }\r
+ //\r
+ // Interrupt enable register (TPM_INT_ENABLE_x) bits 3:4\r
+ // contains settings for interrupt polarity.\r
+ // The other bits of the byte enable individual interrupts.\r
+ // They should be all be zero, but to avoid changing the\r
+ // configuration, the other bits are be preserved.\r
+ // 00 - high level\r
+ // 01 - low level\r
+ // 10 - rising edge\r
+ // 11 - falling edge\r
+ //\r
+ // ACPI spec definitions:\r
+ // _HE: '1' is Edge, '0' is Level\r
+ // _LL: '1' is ActiveHigh, '0' is ActiveLow (inverted from TCG spec)\r
+ //\r
+ If (LEqual (ITRG, 1)) {\r
+ Or(INTE, 0x00000010, INTE)\r
+ } Else {\r
+ And(INTE, 0xFFFFFFEF, INTE)\r
+ }\r
+ if (LEqual (ILVL, 0)) {\r
+ Or(INTE, 0x00000008, INTE)\r
+ } Else {\r
+ And(INTE, 0xFFFFFFF7, INTE)\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ Method(_PRS,0,Serialized)\r
+ {\r
+ //\r
+ // IRQNum = 0 means disable IRQ support\r
+ //\r
+ If (LEqual(IRQN, 0)) {\r
+ Return (RES1)\r
+ } ElseIf(LEqual(SFRB, 0)) {\r
+ //\r
+ // Long format. Possible resources PkgLength > 63\r
+ //\r
+ Return (RESL)\r
+ } Else {\r
+ //\r
+ // Short format. Possible resources PkgLength <=63\r
+ //\r
+ Return (RESS)\r
+ }\r
+ }\r
+\r
+ Method (PTS, 1, Serialized)\r
+ {\r
+ //\r
+ // Detect Sx state for MOR, only S4, S5 need to handle\r
+ //\r
+ If (LAnd (LLess (Arg0, 6), LGreater (Arg0, 3)))\r
+ {\r
+ //\r
+ // Bit4 -- DisableAutoDetect. 0 -- Firmware MAY autodetect.\r
+ //\r
+ If (LNot (And (MORD, 0x10)))\r
+ {\r
+ //\r
+ // Trigger the SMI through ACPI _PTS method.\r
+ //\r
+ Store (0x02, MCIP)\r
+\r
+ //\r
+ // Trigger the SMI interrupt\r
+ //\r
+ Store (MCIN, IOPN)\r
+ }\r
+ }\r
+ Return (0)\r
+ }\r
+\r
+ Method (_STA, 0)\r
+ {\r
+ if (LEqual (ACC0, 0xff))\r
+ {\r
+ Return (0)\r
+ }\r
+ Return (0x0f)\r
+ }\r
+\r
+ //\r
+ // TCG Hardware Information\r
+ //\r
+ Method (HINF, 1, Serialized, 0, {BuffObj, PkgObj}, {UnknownObj}) // IntObj\r
+ {\r
+ //\r
+ // Switch by function index\r
+ //\r
+ Switch (ToInteger(Arg0))\r
+ {\r
+ Case (0)\r
+ {\r
+ //\r
+ // Standard query\r
+ //\r
+ Return (Buffer () {0x03})\r
+ }\r
+ Case (1)\r
+ {\r
+ //\r
+ // Return failure if no TPM present\r
+ //\r
+ Name(TPMV, Package () {0x01, Package () {0x2, 0x0}})\r
+ if (LEqual (_STA (), 0x00))\r
+ {\r
+ Return (Package () {0x00})\r
+ }\r
+\r
+ //\r
+ // Return TPM version\r
+ //\r
+ Return (TPMV)\r
+ }\r
+ Default {BreakPoint}\r
+ }\r
+ Return (Buffer () {0})\r
+ }\r
+\r
+ Name(TPM2, Package (0x02){\r
+ Zero,\r
+ Zero\r
+ })\r
+\r
+ Name(TPM3, Package (0x03){\r
+ Zero,\r
+ Zero,\r
+ Zero\r
+ })\r
+\r
+ //\r
+ // TCG Physical Presence Interface\r
+ //\r
+ Method (TPPI, 2, Serialized, 0, {BuffObj, PkgObj, IntObj, StrObj}, {UnknownObj, UnknownObj}) // IntObj, PkgObj\r
+ {\r
+ //\r
+ // Switch by function index\r
+ //\r
+ Switch (ToInteger(Arg0))\r
+ {\r
+ Case (0)\r
+ {\r
+ //\r
+ // Standard query, supports function 1-8\r
+ //\r
+ Return (Buffer () {0xFF, 0x01})\r
+ }\r
+ Case (1)\r
+ {\r
+ //\r
+ // a) Get Physical Presence Interface Version\r
+ //\r
+ Return ("$PV")\r
+ }\r
+ Case (2)\r
+ {\r
+ //\r
+ // b) Submit TPM Operation Request to Pre-OS Environment\r
+ //\r
+\r
+ Store (DerefOf (Index (Arg1, 0x00)), PPRQ)\r
+ Store (0, PPRM)\r
+ Store (0x02, PPIP)\r
+\r
+ //\r
+ // Trigger the SMI interrupt\r
+ //\r
+ Store (PPIN, IOPN)\r
+ Return (FRET)\r
+\r
+\r
+ }\r
+ Case (3)\r
+ {\r
+ //\r
+ // c) Get Pending TPM Operation Requested By the OS\r
+ //\r
+\r
+ Store (PPRQ, Index (TPM2, 0x01))\r
+ Return (TPM2)\r
+ }\r
+ Case (4)\r
+ {\r
+ //\r
+ // d) Get Platform-Specific Action to Transition to Pre-OS Environment\r
+ //\r
+ Return (2)\r
+ }\r
+ Case (5)\r
+ {\r
+ //\r
+ // e) Return TPM Operation Response to OS Environment\r
+ //\r
+ Store (0x05, PPIP)\r
+\r
+ //\r
+ // Trigger the SMI interrupt\r
+ //\r
+ Store (PPIN, IOPN)\r
+\r
+ Store (LPPR, Index (TPM3, 0x01))\r
+ Store (PPRP, Index (TPM3, 0x02))\r
+\r
+ Return (TPM3)\r
+ }\r
+ Case (6)\r
+ {\r
+\r
+ //\r
+ // f) Submit preferred user language (Not implemented)\r
+ //\r
+\r
+ Return (3)\r
+\r
+ }\r
+ Case (7)\r
+ {\r
+ //\r
+ // g) Submit TPM Operation Request to Pre-OS Environment 2\r
+ //\r
+ Store (7, PPIP)\r
+ Store (DerefOf (Index (Arg1, 0x00)), PPRQ)\r
+ Store (0, PPRM)\r
+ If (LEqual (PPRQ, 23)) {\r
+ Store (DerefOf (Index (Arg1, 0x01)), PPRM)\r
+ }\r
+\r
+ //\r
+ // Trigger the SMI interrupt\r
+ //\r
+ Store (PPIN, IOPN)\r
+ Return (FRET)\r
+ }\r
+ Case (8)\r
+ {\r
+ //\r
+ // e) Get User Confirmation Status for Operation\r
+ //\r
+ Store (8, PPIP)\r
+ Store (DerefOf (Index (Arg1, 0x00)), UCRQ)\r
+\r
+ //\r
+ // Trigger the SMI interrupt\r
+ //\r
+ Store (PPIN, IOPN)\r
+\r
+ Return (FRET)\r
+ }\r
+\r
+ Default {BreakPoint}\r
+ }\r
+ Return (1)\r
+ }\r
+\r
+ Method (TMCI, 2, Serialized, 0, IntObj, {UnknownObj, UnknownObj}) // IntObj, PkgObj\r
+ {\r
+ //\r
+ // Switch by function index\r
+ //\r
+ Switch (ToInteger (Arg0))\r
+ {\r
+ Case (0)\r
+ {\r
+ //\r
+ // Standard query, supports function 1-1\r
+ //\r
+ Return (Buffer () {0x03})\r
+ }\r
+ Case (1)\r
+ {\r
+ //\r
+ // Save the Operation Value of the Request to MORD (reserved memory)\r
+ //\r
+ Store (DerefOf (Index (Arg1, 0x00)), MORD)\r
+\r
+ //\r
+ // Trigger the SMI through ACPI _DSM method.\r
+ //\r
+ Store (0x01, MCIP)\r
+\r
+ //\r
+ // Trigger the SMI interrupt\r
+ //\r
+ Store (MCIN, IOPN)\r
+ Return (MRET)\r
+ }\r
+ Default {BreakPoint}\r
+ }\r
+ Return (1)\r
+ }\r
+\r
+ Method (_DSM, 4, Serialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj})\r
+ {\r
+\r
+ //\r
+ // TCG Hardware Information\r
+ //\r
+ If(LEqual(Arg0, ToUUID ("cf8e16a5-c1e8-4e25-b712-4f54a96702c8")))\r
+ {\r
+ Return (HINF (Arg2))\r
+ }\r
+\r
+ //\r
+ // TCG Physical Presence Interface\r
+ //\r
+ If(LEqual(Arg0, ToUUID ("3dddfaa6-361b-4eb4-a424-8d10089d1653")))\r
+ {\r
+ Return (TPPI (Arg2, Arg3))\r
+ }\r
+\r
+ //\r
+ // TCG Memory Clear Interface\r
+ //\r
+ If(LEqual(Arg0, ToUUID ("376054ed-cc13-4675-901c-4756d7f2d45d")))\r
+ {\r
+ Return (TMCI (Arg2, Arg3))\r
+ }\r
+\r
+ Return (Buffer () {0})\r
+ }\r
+ }\r
+ }\r
+}\r
PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.\r
\r
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) Microsoft Corporation.\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "Tcg2Smm.h"\r
\r
-#pragma pack(1)\r
-\r
-typedef struct {\r
- EFI_ACPI_DESCRIPTION_HEADER Header;\r
- // Flags field is replaced in version 4 and above\r
- // BIT0~15: PlatformClass This field is only valid for version 4 and above\r
- // BIT16~31: Reserved\r
- UINT32 Flags;\r
- UINT64 AddressOfControlArea;\r
- UINT32 StartMethod;\r
- UINT8 PlatformSpecificParameters[12]; // size up to 12\r
- UINT32 Laml; // Optional\r
- UINT64 Lasa; // Optional\r
-} EFI_TPM2_ACPI_TABLE_V4;\r
-\r
-#pragma pack()\r
-\r
-EFI_TPM2_ACPI_TABLE_V4 mTpm2AcpiTemplate = {\r
- {\r
- EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,\r
- sizeof (mTpm2AcpiTemplate),\r
- EFI_TPM2_ACPI_TABLE_REVISION,\r
- //\r
- // Compiler initializes the remaining bytes to 0\r
- // These fields should be filled in in production\r
- //\r
- },\r
- 0, // BIT0~15: PlatformClass\r
- // BIT16~31: Reserved\r
- 0, // Control Area\r
- EFI_TPM2_ACPI_TABLE_START_METHOD_TIS, // StartMethod\r
-};\r
-\r
-EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable;\r
-TCG_NVS *mTcgNvs;\r
+EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable = NULL;\r
+TCG_NVS *mTcgNvs = NULL;\r
+UINTN mPpSoftwareSmi;\r
+UINTN mMcSoftwareSmi;\r
+EFI_HANDLE mReadyToLockHandle;\r
+\r
+/**\r
+ Communication service SMI Handler entry.\r
+\r
+ This handler takes requests to exchange Mmi channel and Nvs address between MM and DXE.\r
+\r
+ Caution: This function may receive untrusted input.\r
+ Communicate buffer and buffer size are external input, so this function will do basic validation.\r
+\r
+ @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
+ @param[in] RegisterContext Points to an optional handler context which was specified when the\r
+ handler was registered.\r
+ @param[in, out] CommBuffer A pointer to a collection of data in memory that will\r
+ be conveyed from a non-SMM environment into an SMM environment.\r
+ @param[in, out] CommBufferSize The size of the CommBuffer.\r
+\r
+ @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers\r
+ should still be called.\r
+ @retval EFI_UNSUPPORTED An unknown test function was requested.\r
+ @retval EFI_ACCESS_DENIED Part of the communication buffer lies in an invalid region.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TpmNvsCommunciate (\r
+ IN EFI_HANDLE DispatchHandle,\r
+ IN CONST VOID *RegisterContext,\r
+ IN OUT VOID *CommBuffer,\r
+ IN OUT UINTN *CommBufferSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN TempCommBufferSize;\r
+ TPM_NVS_MM_COMM_BUFFER *CommParams;\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "%a()\n", __FUNCTION__));\r
+\r
+ //\r
+ // If input is invalid, stop processing this SMI\r
+ //\r
+ if (CommBuffer == NULL || CommBufferSize == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ TempCommBufferSize = *CommBufferSize;\r
+\r
+ if(TempCommBufferSize != sizeof (TPM_NVS_MM_COMM_BUFFER)) {\r
+ DEBUG ((DEBUG_ERROR, "[%a] MM Communication buffer size is invalid for this handler!\n", __FUNCTION__));\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+ if (!IsBufferOutsideMmValid ((UINTN) CommBuffer, TempCommBufferSize)) {\r
+ DEBUG ((DEBUG_ERROR, "[%a] - MM Communication buffer in invalid location!\n", __FUNCTION__));\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ //\r
+ // Farm out the job to individual functions based on what was requested.\r
+ //\r
+ CommParams = (TPM_NVS_MM_COMM_BUFFER*) CommBuffer;\r
+ Status = EFI_SUCCESS;\r
+ switch (CommParams->Function) {\r
+ case TpmNvsMmExchangeInfo:\r
+ DEBUG ((DEBUG_VERBOSE, "[%a] - Function requested: MM_EXCHANGE_NVS_INFO\n", __FUNCTION__));\r
+ CommParams->RegisteredPpSwiValue = mPpSoftwareSmi;\r
+ CommParams->RegisteredMcSwiValue = mMcSoftwareSmi;\r
+ mTcgNvs = (TCG_NVS*) (UINTN) CommParams->TargetAddress;\r
+ break;\r
+\r
+ default:\r
+ DEBUG ((DEBUG_INFO, "[%a] - Unknown function %d!\n", __FUNCTION__, CommParams->Function));\r
+ Status = EFI_UNSUPPORTED;\r
+ break;\r
+ }\r
+\r
+ CommParams->ReturnStatus = (UINT64) Status;\r
+ return EFI_SUCCESS;\r
+}\r
\r
/**\r
Software SMI callback for TPM physical presence which is called from ACPI method.\r
}\r
\r
/**\r
- Find the operation region in TCG ACPI table by given Name and Size,\r
- and initialize it if the region is found.\r
-\r
- @param[in, out] Table The TPM item in ACPI table.\r
- @param[in] Name The name string to find in TPM table.\r
- @param[in] Size The size of the region to find.\r
-\r
- @return The allocated address for the found region.\r
-\r
-**/\r
-VOID *\r
-AssignOpRegion (\r
- EFI_ACPI_DESCRIPTION_HEADER *Table,\r
- UINT32 Name,\r
- UINT16 Size\r
- )\r
-{\r
- EFI_STATUS Status;\r
- AML_OP_REGION_32_8 *OpRegion;\r
- EFI_PHYSICAL_ADDRESS MemoryAddress;\r
-\r
- MemoryAddress = SIZE_4GB - 1;\r
-\r
- //\r
- // Patch some pointers for the ASL code before loading the SSDT.\r
- //\r
- for (OpRegion = (AML_OP_REGION_32_8 *) (Table + 1);\r
- OpRegion <= (AML_OP_REGION_32_8 *) ((UINT8 *) Table + Table->Length);\r
- OpRegion = (AML_OP_REGION_32_8 *) ((UINT8 *) OpRegion + 1)) {\r
- if ((OpRegion->OpRegionOp == AML_EXT_REGION_OP) &&\r
- (OpRegion->NameString == Name) &&\r
- (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&\r
- (OpRegion->BytePrefix == AML_BYTE_PREFIX)) {\r
-\r
- Status = gBS->AllocatePages(AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (Size), &MemoryAddress);\r
- ASSERT_EFI_ERROR (Status);\r
- ZeroMem ((VOID *)(UINTN)MemoryAddress, Size);\r
- OpRegion->RegionOffset = (UINT32) (UINTN) MemoryAddress;\r
- OpRegion->RegionLen = (UINT8) Size;\r
- break;\r
- }\r
- }\r
-\r
- return (VOID *) (UINTN) MemoryAddress;\r
-}\r
-\r
-/**\r
- Patch version string of Physical Presence interface supported by platform. The initial string tag in TPM\r
-ACPI table is "$PV".\r
-\r
- @param[in, out] Table The TPM item in ACPI table.\r
- @param[in] PPVer Version string of Physical Presence interface supported by platform.\r
-\r
- @return The allocated address for the found region.\r
-\r
-**/\r
-EFI_STATUS\r
-UpdatePPVersion (\r
- EFI_ACPI_DESCRIPTION_HEADER *Table,\r
- CHAR8 *PPVer\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT8 *DataPtr;\r
-\r
- //\r
- // Patch some pointers for the ASL code before loading the SSDT.\r
- //\r
- for (DataPtr = (UINT8 *)(Table + 1);\r
- DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - PHYSICAL_PRESENCE_VERSION_SIZE);\r
- DataPtr += 1) {\r
- if (AsciiStrCmp((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_TAG) == 0) {\r
- Status = AsciiStrCpyS((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_SIZE, PPVer);\r
- DEBUG((EFI_D_INFO, "TPM2 Physical Presence Interface Version update status 0x%x\n", Status));\r
- return Status;\r
- }\r
- }\r
-\r
- return EFI_NOT_FOUND;\r
-}\r
-\r
-/**\r
- Patch interrupt resources returned by TPM _PRS. ResourceTemplate to patch is determined by input\r
- interrupt buffer size. BufferSize, PkgLength and interrupt descriptor in ByteList need to be patched\r
+ Notification for SMM ReadyToLock protocol.\r
\r
- @param[in, out] Table The TPM item in ACPI table.\r
- @param[in] IrqBuffer Input new IRQ buffer.\r
- @param[in] IrqBuffserSize Input new IRQ buffer size.\r
- @param[out] IsShortFormPkgLength If _PRS returns Short length Package(ACPI spec 20.2.4).\r
+ @param[in] Protocol Points to the protocol's unique identifier.\r
+ @param[in] Interface Points to the interface instance.\r
+ @param[in] Handle The handle on which the interface was installed.\r
\r
- @return patch status.\r
+ @retval EFI_SUCCESS Notification runs successfully.\r
\r
**/\r
EFI_STATUS\r
-UpdatePossibleResource (\r
- IN OUT EFI_ACPI_DESCRIPTION_HEADER *Table,\r
- IN UINT32 *IrqBuffer,\r
- IN UINT32 IrqBuffserSize,\r
- OUT BOOLEAN *IsShortFormPkgLength\r
- )\r
-{\r
- UINT8 *DataPtr;\r
- UINT8 *DataEndPtr;\r
- UINT32 NewPkgLength;\r
- UINT32 OrignalPkgLength;\r
-\r
- NewPkgLength = 0;\r
- OrignalPkgLength = 0;\r
- DataEndPtr = NULL;\r
-\r
- //\r
- // Follow ACPI spec\r
- // 6.4.3 Extend Interrupt Descriptor.\r
- // 19.3.3 ASL Resource Template\r
- // 20 AML specification\r
- // to patch TPM ACPI object _PRS returned ResourceTemplate() containing 2 resource descriptors and an auto appended End Tag\r
- //\r
- // AML data is organized by following rule.\r
- // Code need to patch BufferSize and PkgLength and interrupt descriptor in ByteList\r
- //\r
- // ============= Buffer ====================\r
- // DefBuffer := BufferOp PkgLength BufferSize ByteList\r
- // BufferOp := 0x11\r
- //\r
- // ==============PkgLength==================\r
- // PkgLength := PkgLeadByte |\r
- // <PkgLeadByte ByteData> |\r
- // <PkgLeadByte ByteData ByteData> |\r
- // <PkgLeadByte ByteData ByteData ByteData>\r
- //\r
- // PkgLeadByte := <bit 7-6: ByteData count that follows (0-3)>\r
- // <bit 5-4: Only used if PkgLength <= 63 >\r
- // <bit 3-0: Least significant package length nybble>\r
- //\r
- //==============BufferSize==================\r
- // BufferSize := Integer\r
- // Integer := ByteConst|WordConst|DwordConst....\r
- //\r
- // ByteConst := BytePrefix ByteData\r
- //\r
- //==============ByteList===================\r
- // ByteList := ByteData ByteList\r
- //\r
- //=========================================\r
-\r
- //\r
- // 1. Check TPM_PRS_RESS with PkgLength <=63 can hold the input interrupt number buffer for patching\r
- //\r
- for (DataPtr = (UINT8 *)(Table + 1);\r
- DataPtr < (UINT8 *) ((UINT8 *) Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));\r
- DataPtr += 1) {\r
- if (CompareMem(DataPtr, TPM_PRS_RESS, TPM_PRS_RES_NAME_SIZE) == 0) {\r
- //\r
- // Jump over object name & BufferOp\r
- //\r
- DataPtr += TPM_PRS_RES_NAME_SIZE + 1;\r
-\r
- if ((*DataPtr & (BIT7|BIT6)) == 0) {\r
- OrignalPkgLength = (UINT32)*DataPtr;\r
- DataEndPtr = DataPtr + OrignalPkgLength;\r
-\r
- //\r
- // Jump over PkgLength = PkgLeadByte only\r
- //\r
- NewPkgLength++;\r
-\r
- //\r
- // Jump over BufferSize\r
- //\r
- if (*(DataPtr + 1) == AML_BYTE_PREFIX) {\r
- NewPkgLength += 2;\r
- } else if (*(DataPtr + 1) == AML_WORD_PREFIX) {\r
- NewPkgLength += 3;\r
- } else if (*(DataPtr + 1) == AML_DWORD_PREFIX) {\r
- NewPkgLength += 5;\r
- } else {\r
- ASSERT(FALSE);\r
- return EFI_UNSUPPORTED;\r
- }\r
- } else {\r
- ASSERT(FALSE);\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // Include Memory32Fixed Descriptor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)\r
- //\r
- NewPkgLength += 19 + IrqBuffserSize;\r
- if (NewPkgLength > 63) {\r
- break;\r
- }\r
-\r
- if (NewPkgLength > OrignalPkgLength) {\r
- ASSERT(FALSE);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // 1.1 Patch PkgLength\r
- //\r
- *DataPtr = (UINT8)NewPkgLength;\r
-\r
- //\r
- // 1.2 Patch BufferSize = sizeof(Memory32Fixed Descriptor + Interrupt Descriptor + End Tag).\r
- // It is Little endian. So only patch lowest byte of BufferSize due to current interrupt number limit.\r
- //\r
- *(DataPtr + 2) = (UINT8)(IrqBuffserSize + 19);\r
-\r
- //\r
- // Notify _PRS to report short formed ResourceTemplate\r
- //\r
- *IsShortFormPkgLength = TRUE;\r
-\r
- break;\r
- }\r
- }\r
-\r
- //\r
- // 2. Use TPM_PRS_RESL with PkgLength > 63 to hold longer input interrupt number buffer for patching\r
- //\r
- if (NewPkgLength > 63) {\r
- NewPkgLength = 0;\r
- OrignalPkgLength = 0;\r
- for (DataPtr = (UINT8 *)(Table + 1);\r
- DataPtr < (UINT8 *) ((UINT8 *) Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));\r
- DataPtr += 1) {\r
- if (CompareMem(DataPtr, TPM_PRS_RESL, TPM_PRS_RES_NAME_SIZE) == 0) {\r
- //\r
- // Jump over object name & BufferOp\r
- //\r
- DataPtr += TPM_PRS_RES_NAME_SIZE + 1;\r
-\r
- if ((*DataPtr & (BIT7|BIT6)) != 0) {\r
- OrignalPkgLength = (UINT32)(*(DataPtr + 1) << 4) + (*DataPtr & 0x0F);\r
- DataEndPtr = DataPtr + OrignalPkgLength;\r
- //\r
- // Jump over PkgLength = PkgLeadByte + ByteData length\r
- //\r
- NewPkgLength += 1 + ((*DataPtr & (BIT7|BIT6)) >> 6);\r
-\r
- //\r
- // Jump over BufferSize\r
- //\r
- if (*(DataPtr + NewPkgLength) == AML_BYTE_PREFIX) {\r
- NewPkgLength += 2;\r
- } else if (*(DataPtr + NewPkgLength) == AML_WORD_PREFIX) {\r
- NewPkgLength += 3;\r
- } else if (*(DataPtr + NewPkgLength) == AML_DWORD_PREFIX) {\r
- NewPkgLength += 5;\r
- } else {\r
- ASSERT(FALSE);\r
- return EFI_UNSUPPORTED;\r
- }\r
- } else {\r
- ASSERT(FALSE);\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // Include Memory32Fixed Descriptor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)\r
- //\r
- NewPkgLength += 19 + IrqBuffserSize;\r
-\r
- if (NewPkgLength > OrignalPkgLength) {\r
- ASSERT(FALSE);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // 2.1 Patch PkgLength. Only patch PkgLeadByte and first ByteData\r
- //\r
- *DataPtr = (UINT8)((*DataPtr) & 0xF0) | (NewPkgLength & 0x0F);\r
- *(DataPtr + 1) = (UINT8)((NewPkgLength & 0xFF0) >> 4);\r
-\r
- //\r
- // 2.2 Patch BufferSize = sizeof(Memory32Fixed Descriptor + Interrupt Descriptor + End Tag).\r
- // It is Little endian. Only patch lowest byte of BufferSize due to current interrupt number limit.\r
- //\r
- *(DataPtr + 2 + ((*DataPtr & (BIT7|BIT6)) >> 6)) = (UINT8)(IrqBuffserSize + 19);\r
-\r
- //\r
- // Notify _PRS to report long formed ResourceTemplate\r
- //\r
- *IsShortFormPkgLength = FALSE;\r
- break;\r
- }\r
- }\r
- }\r
-\r
- if (DataPtr >= (UINT8 *) ((UINT8 *) Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE))) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // 3. Move DataPtr to Interrupt descriptor header and patch interrupt descriptor.\r
- // 5 bytes for interrupt descriptor header, 2 bytes for End Tag\r
- //\r
- DataPtr += NewPkgLength - (5 + IrqBuffserSize + 2);\r
- //\r
- // 3.1 Patch Length bit[7:0] of Interrupt descriptor patch interrupt descriptor\r
- //\r
- *(DataPtr + 1) = (UINT8)(2 + IrqBuffserSize);\r
- //\r
- // 3.2 Patch Interrupt Table Length\r
- //\r
- *(DataPtr + 4) = (UINT8)(IrqBuffserSize / sizeof(UINT32));\r
- //\r
- // 3.3 Copy patched InterruptNumBuffer\r
- //\r
- CopyMem(DataPtr + 5, IrqBuffer, IrqBuffserSize);\r
-\r
- //\r
- // 4. Jump over Interrupt descriptor and Patch END Tag, set Checksum field to 0\r
- //\r
- DataPtr += 5 + IrqBuffserSize;\r
- *DataPtr = ACPI_END_TAG_DESCRIPTOR;\r
- *(DataPtr + 1) = 0;\r
-\r
- //\r
- // 5. Jump over new ResourceTemplate. Stuff rest bytes to NOOP\r
- //\r
- DataPtr += 2;\r
- if (DataPtr < DataEndPtr) {\r
- SetMem(DataPtr, (UINTN)DataEndPtr - (UINTN)DataPtr, AML_NOOP_OP);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Patch TPM2 device HID string. The initial string tag in TPM2 ACPI table is "NNN0000".\r
-\r
- @param[in, out] Table The TPM2 SSDT ACPI table.\r
-\r
- @return HID Update status.\r
-\r
-**/\r
-EFI_STATUS\r
-UpdateHID (\r
- EFI_ACPI_DESCRIPTION_HEADER *Table\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT8 *DataPtr;\r
- CHAR8 Hid[TPM_HID_ACPI_SIZE];\r
- UINT32 ManufacturerID;\r
- UINT32 FirmwareVersion1;\r
- UINT32 FirmwareVersion2;\r
- BOOLEAN PnpHID;\r
-\r
- PnpHID = TRUE;\r
-\r
- //\r
- // Initialize HID with Default PNP string\r
- //\r
- ZeroMem(Hid, TPM_HID_ACPI_SIZE);\r
-\r
- //\r
- // Get Manufacturer ID\r
- //\r
- Status = Tpm2GetCapabilityManufactureID(&ManufacturerID);\r
- if (!EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_INFO, "TPM_PT_MANUFACTURER 0x%08x\n", ManufacturerID));\r
- //\r
- // ManufacturerID defined in TCG Vendor ID Registry\r
- // may tailed with 0x00 or 0x20\r
- //\r
- if ((ManufacturerID >> 24) == 0x00 || ((ManufacturerID >> 24) == 0x20)) {\r
- //\r
- // HID containing PNP ID "NNN####"\r
- // NNN is uppercase letter for Vendor ID specified by manufacturer\r
- //\r
- CopyMem(Hid, &ManufacturerID, 3);\r
- } else {\r
- //\r
- // HID containing ACP ID "NNNN####"\r
- // NNNN is uppercase letter for Vendor ID specified by manufacturer\r
- //\r
- CopyMem(Hid, &ManufacturerID, 4);\r
- PnpHID = FALSE;\r
- }\r
- } else {\r
- DEBUG ((EFI_D_ERROR, "Get TPM_PT_MANUFACTURER failed %x!\n", Status));\r
- ASSERT(FALSE);\r
- return Status;\r
- }\r
-\r
- Status = Tpm2GetCapabilityFirmwareVersion(&FirmwareVersion1, &FirmwareVersion2);\r
- if (!EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_1 0x%x\n", FirmwareVersion1));\r
- DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_2 0x%x\n", FirmwareVersion2));\r
- //\r
- // #### is Firmware Version 1\r
- //\r
- if (PnpHID) {\r
- AsciiSPrint(Hid + 3, TPM_HID_PNP_SIZE - 3, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 & 0x0000FFFF));\r
- } else {\r
- AsciiSPrint(Hid + 4, TPM_HID_ACPI_SIZE - 4, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 & 0x0000FFFF));\r
- }\r
-\r
- } else {\r
- DEBUG ((EFI_D_ERROR, "Get TPM_PT_FIRMWARE_VERSION_X failed %x!\n", Status));\r
- ASSERT(FALSE);\r
- return Status;\r
- }\r
-\r
- //\r
- // Patch HID in ASL code before loading the SSDT.\r
- //\r
- for (DataPtr = (UINT8 *)(Table + 1);\r
- DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - TPM_HID_PNP_SIZE);\r
- DataPtr += 1) {\r
- if (AsciiStrCmp((CHAR8 *)DataPtr, TPM_HID_TAG) == 0) {\r
- if (PnpHID) {\r
- CopyMem(DataPtr, Hid, TPM_HID_PNP_SIZE);\r
- //\r
- // if HID is PNP ID, patch the last byte in HID TAG to Noop\r
- //\r
- *(DataPtr + TPM_HID_PNP_SIZE) = AML_NOOP_OP;\r
- } else {\r
-\r
- CopyMem(DataPtr, Hid, TPM_HID_ACPI_SIZE);\r
- }\r
- DEBUG((DEBUG_INFO, "TPM2 ACPI _HID is patched to %a\n", DataPtr));\r
-\r
- return Status;\r
- }\r
- }\r
-\r
- DEBUG((EFI_D_ERROR, "TPM2 ACPI HID TAG for patch not found!\n"));\r
- return EFI_NOT_FOUND;\r
-}\r
-\r
-/**\r
- Initialize and publish TPM items in ACPI table.\r
-\r
- @retval EFI_SUCCESS The TCG ACPI table is published successfully.\r
- @retval Others The TCG ACPI table is not published.\r
-\r
-**/\r
-EFI_STATUS\r
-PublishAcpiTable (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
- UINTN TableKey;\r
- EFI_ACPI_DESCRIPTION_HEADER *Table;\r
- UINTN TableSize;\r
- UINT32 *PossibleIrqNumBuf;\r
- UINT32 PossibleIrqNumBufSize;\r
- BOOLEAN IsShortFormPkgLength;\r
-\r
- IsShortFormPkgLength = FALSE;\r
-\r
- Status = GetSectionFromFv (\r
- &gEfiCallerIdGuid,\r
- EFI_SECTION_RAW,\r
- 0,\r
- (VOID **) &Table,\r
- &TableSize\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Measure to PCR[0] with event EV_POST_CODE ACPI DATA.\r
- // The measurement has to be done before any update.\r
- // Otherwise, the PCR record would be different after TPM FW update\r
- // or the PCD configuration change.\r
- //\r
- TpmMeasureAndLogData(\r
- 0,\r
- EV_POST_CODE,\r
- EV_POSTCODE_INFO_ACPI_DATA,\r
- ACPI_DATA_LEN,\r
- Table,\r
- TableSize\r
- );\r
-\r
- //\r
- // Update Table version before measuring it to PCR\r
- //\r
- Status = UpdatePPVersion(Table, (CHAR8 *)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer));\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- DEBUG ((\r
- DEBUG_INFO,\r
- "Current physical presence interface version - %a\n",\r
- (CHAR8 *) PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer)\r
- ));\r
-\r
- //\r
- // Update TPM2 HID after measuring it to PCR\r
- //\r
- Status = UpdateHID(Table);\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
-\r
- if (PcdGet32(PcdTpm2CurrentIrqNum) != 0) {\r
- //\r
- // Patch _PRS interrupt resource only when TPM interrupt is supported\r
- //\r
- PossibleIrqNumBuf = (UINT32 *)PcdGetPtr(PcdTpm2PossibleIrqNumBuf);\r
- PossibleIrqNumBufSize = (UINT32)PcdGetSize(PcdTpm2PossibleIrqNumBuf);\r
-\r
- if (PossibleIrqNumBufSize <= MAX_PRS_INT_BUF_SIZE && (PossibleIrqNumBufSize % sizeof(UINT32)) == 0) {\r
- Status = UpdatePossibleResource(Table, PossibleIrqNumBuf, PossibleIrqNumBufSize, &IsShortFormPkgLength);\r
- DEBUG ((\r
- DEBUG_INFO,\r
- "UpdatePossibleResource status - %x. TPM2 service may not ready in OS.\n",\r
- Status\r
- ));\r
- } else {\r
- DEBUG ((\r
- DEBUG_INFO,\r
- "PcdTpm2PossibleIrqNumBuf size %x is not correct. TPM2 service may not ready in OS.\n",\r
- PossibleIrqNumBufSize\r
- ));\r
- }\r
- }\r
-\r
- ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));\r
- CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId) );\r
- mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));\r
- ASSERT (mTcgNvs != NULL);\r
- mTcgNvs->TpmIrqNum = PcdGet32(PcdTpm2CurrentIrqNum);\r
- mTcgNvs->IsShortFormPkgLength = IsShortFormPkgLength;\r
-\r
- //\r
- // Publish the TPM ACPI table. Table is re-checksummed.\r
- //\r
- Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- TableKey = 0;\r
- Status = AcpiTable->InstallAcpiTable (\r
- AcpiTable,\r
- Table,\r
- TableSize,\r
- &TableKey\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Publish TPM2 ACPI table\r
-\r
- @retval EFI_SUCCESS The TPM2 ACPI table is published successfully.\r
- @retval Others The TPM2 ACPI table is not published.\r
-\r
-**/\r
-EFI_STATUS\r
-PublishTpm2 (\r
- VOID\r
- )\r
+EFIAPI\r
+TcgMmReadyToLock (\r
+ IN CONST EFI_GUID *Protocol,\r
+ IN VOID *Interface,\r
+ IN EFI_HANDLE Handle\r
+)\r
{\r
- EFI_STATUS Status;\r
- EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
- UINTN TableKey;\r
- UINT64 OemTableId;\r
- EFI_TPM2_ACPI_CONTROL_AREA *ControlArea;\r
- TPM2_PTP_INTERFACE_TYPE InterfaceType;\r
-\r
- //\r
- // Measure to PCR[0] with event EV_POST_CODE ACPI DATA.\r
- // The measurement has to be done before any update.\r
- // Otherwise, the PCR record would be different after event log update\r
- // or the PCD configuration change.\r
- //\r
- TpmMeasureAndLogData(\r
- 0,\r
- EV_POST_CODE,\r
- EV_POSTCODE_INFO_ACPI_DATA,\r
- ACPI_DATA_LEN,\r
- &mTpm2AcpiTemplate,\r
- mTpm2AcpiTemplate.Header.Length\r
- );\r
-\r
- mTpm2AcpiTemplate.Header.Revision = PcdGet8(PcdTpm2AcpiTableRev);\r
- DEBUG((DEBUG_INFO, "Tpm2 ACPI table revision is %d\n", mTpm2AcpiTemplate.Header.Revision));\r
-\r
- //\r
- // PlatformClass is only valid for version 4 and above\r
- // BIT0~15: PlatformClass\r
- // BIT16~31: Reserved\r
- //\r
- if (mTpm2AcpiTemplate.Header.Revision >= EFI_TPM2_ACPI_TABLE_REVISION_4) {\r
- mTpm2AcpiTemplate.Flags = (mTpm2AcpiTemplate.Flags & 0xFFFF0000) | PcdGet8(PcdTpmPlatformClass);\r
- DEBUG((DEBUG_INFO, "Tpm2 ACPI table PlatformClass is %d\n", (mTpm2AcpiTemplate.Flags & 0x0000FFFF)));\r
- }\r
-\r
- mTpm2AcpiTemplate.Laml = PcdGet32(PcdTpm2AcpiTableLaml);\r
- mTpm2AcpiTemplate.Lasa = PcdGet64(PcdTpm2AcpiTableLasa);\r
- if ((mTpm2AcpiTemplate.Header.Revision < EFI_TPM2_ACPI_TABLE_REVISION_4) ||\r
- (mTpm2AcpiTemplate.Laml == 0) || (mTpm2AcpiTemplate.Lasa == 0)) {\r
- //\r
- // If version is smaller than 4 or Laml/Lasa is not valid, rollback to original Length.\r
- //\r
- mTpm2AcpiTemplate.Header.Length = sizeof(EFI_TPM2_ACPI_TABLE);\r
- }\r
+ EFI_STATUS Status;\r
\r
- InterfaceType = PcdGet8(PcdActiveTpmInterfaceType);\r
- switch (InterfaceType) {\r
- case Tpm2PtpInterfaceCrb:\r
- mTpm2AcpiTemplate.StartMethod = EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE;\r
- mTpm2AcpiTemplate.AddressOfControlArea = PcdGet64 (PcdTpmBaseAddress) + 0x40;\r
- ControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *)(UINTN)mTpm2AcpiTemplate.AddressOfControlArea;\r
- ControlArea->CommandSize = 0xF80;\r
- ControlArea->ResponseSize = 0xF80;\r
- ControlArea->Command = PcdGet64 (PcdTpmBaseAddress) + 0x80;\r
- ControlArea->Response = PcdGet64 (PcdTpmBaseAddress) + 0x80;\r
- break;\r
- case Tpm2PtpInterfaceFifo:\r
- case Tpm2PtpInterfaceTis:\r
- break;\r
- default:\r
- DEBUG((EFI_D_ERROR, "TPM2 InterfaceType get error! %d\n", InterfaceType));\r
- break;\r
+ if (mReadyToLockHandle != NULL) {\r
+ Status = gMmst->MmiHandlerUnRegister (mReadyToLockHandle);\r
+ mReadyToLockHandle = NULL;\r
}\r
-\r
- CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));\r
- OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
- CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
- mTpm2AcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
- mTpm2AcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
- mTpm2AcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
-\r
- //\r
- // Construct ACPI table\r
- //\r
- Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- Status = AcpiTable->InstallAcpiTable (\r
- AcpiTable,\r
- &mTpm2AcpiTemplate,\r
- mTpm2AcpiTemplate.Header.Length,\r
- &TableKey\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
return Status;\r
}\r
\r
/**\r
- The driver's entry point.\r
+ The driver's common initialization routine.\r
\r
It install callbacks for TPM physical presence and MemoryClear, and locate\r
SMM variable to be used in the callback function.\r
\r
- @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
- @param[in] SystemTable A pointer to the EFI System Table.\r
-\r
@retval EFI_SUCCESS The entry point is executed successfully.\r
@retval Others Some error occurs when executing this entry point.\r
\r
**/\r
EFI_STATUS\r
-EFIAPI\r
-InitializeTcgSmm (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
+InitializeTcgCommon (\r
+ VOID\r
)\r
{\r
EFI_STATUS Status;\r
EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;\r
EFI_SMM_SW_REGISTER_CONTEXT SwContext;\r
- EFI_HANDLE SwHandle;\r
+ EFI_HANDLE PpSwHandle;\r
+ EFI_HANDLE McSwHandle;\r
+ EFI_HANDLE NotifyHandle;\r
\r
if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)){\r
DEBUG ((EFI_D_ERROR, "No TPM2 DTPM instance required!\n"));\r
return EFI_UNSUPPORTED;\r
}\r
\r
- Status = PublishAcpiTable ();\r
+ // Initialize variables first\r
+ mReadyToLockHandle = NULL;\r
+ SwDispatch = NULL;\r
+ PpSwHandle = NULL;\r
+ McSwHandle = NULL;\r
+ NotifyHandle = NULL;\r
+\r
+ // Register a root handler to communicate the NVS region and SMI channel between MM and DXE\r
+ Status = gMmst->MmiHandlerRegister (TpmNvsCommunciate, &gTpmNvsMmGuid, &mReadyToLockHandle);\r
ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to register NVS communicate as root MM handler - %r!\n", __FUNCTION__, Status));\r
+ goto Cleanup;\r
+ }\r
\r
//\r
// Get the Sw dispatch protocol and register SMI callback functions.\r
//\r
Status = gMmst->MmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID**)&SwDispatch);\r
ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to locate Sw dispatch protocol - %r!\n", __FUNCTION__, Status));\r
+ goto Cleanup;\r
+ }\r
+\r
SwContext.SwSmiInputValue = (UINTN) -1;\r
- Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &SwHandle);\r
+ Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &PpSwHandle);\r
ASSERT_EFI_ERROR (Status);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to register PP callback as SW MM handler - %r!\n", __FUNCTION__, Status));\r
+ goto Cleanup;\r
}\r
- mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;\r
+ mPpSoftwareSmi = SwContext.SwSmiInputValue;\r
\r
SwContext.SwSmiInputValue = (UINTN) -1;\r
- Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle);\r
+ Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &McSwHandle);\r
ASSERT_EFI_ERROR (Status);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to register MC callback as SW MM handler - %r!\n", __FUNCTION__, Status));\r
+ goto Cleanup;\r
}\r
- mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;\r
+ mMcSoftwareSmi = SwContext.SwSmiInputValue;\r
\r
//\r
// Locate SmmVariableProtocol.\r
//\r
Status = gMmst->MmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable);\r
ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ // Should not happen\r
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to locate SMM variable protocol - %r!\n", __FUNCTION__, Status));\r
+ goto Cleanup;\r
+ }\r
\r
- //\r
- // Set TPM2 ACPI table\r
- //\r
- Status = PublishTpm2 ();\r
+ // Turn off the light before leaving the room... at least, take a remote...\r
+ Status = gMmst->MmRegisterProtocolNotify (&gEfiMmReadyToLockProtocolGuid, TcgMmReadyToLock, &NotifyHandle);\r
ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to register ready to lock notification - %r!\n", __FUNCTION__, Status));\r
+ goto Cleanup;\r
+ }\r
\r
+ Tcg2NotifyMmReady ();\r
\r
- return EFI_SUCCESS;\r
+Cleanup:\r
+ if (EFI_ERROR (Status)) {\r
+ // Something is whacked, clean up the mess...\r
+ if (NotifyHandle != NULL) {\r
+ gMmst->MmRegisterProtocolNotify (&gEfiMmReadyToLockProtocolGuid, NULL, &NotifyHandle);\r
+ }\r
+ if (McSwHandle != NULL && SwDispatch != NULL) {\r
+ SwDispatch->UnRegister (SwDispatch, McSwHandle);\r
+ }\r
+ if (PpSwHandle != NULL && SwDispatch != NULL) {\r
+ SwDispatch->UnRegister (SwDispatch, PpSwHandle);\r
+ }\r
+ if (mReadyToLockHandle != NULL) {\r
+ gMmst->MmiHandlerUnRegister (mReadyToLockHandle);\r
+ }\r
+ }\r
+\r
+ return Status;\r
}\r
\r
The header file for Tcg2 SMM driver.\r
\r
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) Microsoft Corporation.\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
#ifndef __TCG2_SMM_H__\r
#define __TCG2_SMM_H__\r
\r
-#include <PiDxe.h>\r
-#include <IndustryStandard/Acpi.h>\r
-#include <IndustryStandard/Tpm2Acpi.h>\r
+#include <PiMm.h>\r
\r
#include <Guid/MemoryOverwriteControl.h>\r
#include <Guid/TpmInstance.h>\r
+#include <Guid/TpmNvsMm.h>\r
\r
+#include <Protocol/MmReadyToLock.h>\r
#include <Protocol/SmmSwDispatch2.h>\r
#include <Protocol/AcpiTable.h>\r
#include <Protocol/SmmVariable.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
#include <Library/MmServicesTableLib.h>\r
-#include <Library/UefiDriverEntryPoint.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/DxeServicesLib.h>\r
-#include <Library/TpmMeasurementLib.h>\r
#include <Library/Tpm2CommandLib.h>\r
#include <Library/Tcg2PhysicalPresenceLib.h>\r
#include <Library/IoLib.h>\r
-#include <Library/PrintLib.h>\r
#include <Library/PcdLib.h>\r
#include <Library/Tpm2DeviceLib.h>\r
\r
#include <IndustryStandard/TpmPtp.h>\r
\r
-#pragma pack(1)\r
-typedef struct {\r
- UINT8 SoftwareSmi;\r
- UINT32 Parameter;\r
- UINT32 Response;\r
- UINT32 Request;\r
- UINT32 RequestParameter;\r
- UINT32 LastRequest;\r
- UINT32 ReturnCode;\r
-} PHYSICAL_PRESENCE_NVS;\r
-\r
-typedef struct {\r
- UINT8 SoftwareSmi;\r
- UINT32 Parameter;\r
- UINT32 Request;\r
- UINT32 ReturnCode;\r
-} MEMORY_CLEAR_NVS;\r
-\r
-typedef struct {\r
- PHYSICAL_PRESENCE_NVS PhysicalPresence;\r
- MEMORY_CLEAR_NVS MemoryClear;\r
- UINT32 PPRequestUserConfirm;\r
- UINT32 TpmIrqNum;\r
- BOOLEAN IsShortFormPkgLength;\r
-} TCG_NVS;\r
-\r
-typedef struct {\r
- UINT8 OpRegionOp;\r
- UINT32 NameString;\r
- UINT8 RegionSpace;\r
- UINT8 DWordPrefix;\r
- UINT32 RegionOffset;\r
- UINT8 BytePrefix;\r
- UINT8 RegionLen;\r
-} AML_OP_REGION_32_8;\r
-#pragma pack()\r
-\r
//\r
// The definition for TCG MOR\r
//\r
#define MOR_REQUEST_SUCCESS 0\r
#define MOR_REQUEST_GENERAL_FAILURE 1\r
\r
-//\r
-// Physical Presence Interface Version supported by Platform\r
-//\r
-#define PHYSICAL_PRESENCE_VERSION_TAG "$PV"\r
-#define PHYSICAL_PRESENCE_VERSION_SIZE 4\r
+/**\r
+ Notify the system that the SMM variable driver is ready.\r
+**/\r
+VOID\r
+Tcg2NotifyMmReady (\r
+ VOID\r
+ );\r
\r
-//\r
-// PNP _HID for TPM2 device\r
-//\r
-#define TPM_HID_TAG "NNNN0000"\r
-#define TPM_HID_PNP_SIZE 8\r
-#define TPM_HID_ACPI_SIZE 9\r
+/**\r
+ This function is an abstraction layer for implementation specific Mm buffer validation routine.\r
\r
-#define TPM_PRS_RESL "RESL"\r
-#define TPM_PRS_RESS "RESS"\r
-#define TPM_PRS_RES_NAME_SIZE 4\r
-//\r
-// Minimum PRS resource template size\r
-// 1 byte for BufferOp\r
-// 1 byte for PkgLength\r
-// 2 bytes for BufferSize\r
-// 12 bytes for Memory32Fixed descriptor\r
-// 5 bytes for Interrupt descriptor\r
-// 2 bytes for END Tag\r
-//\r
-#define TPM_POS_RES_TEMPLATE_MIN_SIZE (1 + 1 + 2 + 12 + 5 + 2)\r
+ @param Buffer The buffer start address to be checked.\r
+ @param Length The buffer length to be checked.\r
+\r
+ @retval TRUE This buffer is valid per processor architecture and not overlap with SMRAM.\r
+ @retval FALSE This buffer is not valid per processor architecture or overlap with SMRAM.\r
+**/\r
+BOOLEAN\r
+IsBufferOutsideMmValid (\r
+ IN EFI_PHYSICAL_ADDRESS Buffer,\r
+ IN UINT64 Length\r
+ );\r
+\r
+/**\r
+ The driver's common initialization routine.\r
+\r
+ It install callbacks for TPM physical presence and MemoryClear, and locate\r
+ SMM variable to be used in the callback function.\r
+\r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval Others Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeTcgCommon (\r
+ VOID\r
+ );\r
\r
-//\r
-// Max Interrupt buffer size for PRS interrupt resource\r
-// Now support 15 interrupts in maxmum\r
-//\r
-#define MAX_PRS_INT_BUF_SIZE (15*4)\r
#endif // __TCG_SMM_H__\r
[Sources]\r
Tcg2Smm.h\r
Tcg2Smm.c\r
- Tpm.asl\r
+ Tcg2TraditionalMm.c\r
\r
[Packages]\r
MdePkg/MdePkg.dec\r
Tpm2CommandLib\r
Tcg2PhysicalPresenceLib\r
PcdLib\r
+ SmmMemLib\r
\r
[Guids]\r
## SOMETIMES_PRODUCES ## Variable:L"MemoryOverwriteRequestControl"\r
gEfiMemoryOverwriteControlDataGuid\r
\r
gEfiTpmDeviceInstanceTpm20DtpmGuid ## PRODUCES ## GUID # TPM device identifier\r
+ gTcg2MmSwSmiRegisteredGuid ## PRODUCES\r
+ gTpmNvsMmGuid ## CONSUMES\r
\r
[Protocols]\r
gEfiSmmSwDispatch2ProtocolGuid ## CONSUMES\r
gEfiSmmVariableProtocolGuid ## CONSUMES\r
- gEfiAcpiTableProtocolGuid ## CONSUMES\r
-\r
-[FixedPcd]\r
- gEfiSecurityPkgTokenSpaceGuid.PcdSmiCommandIoPort ## CONSUMES\r
+ gEfiMmReadyToLockProtocolGuid ## CONSUMES\r
\r
[Pcd]\r
gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid ## CONSUMES\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## SOMETIMES_CONSUMES\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## SOMETIMES_CONSUMES\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## SOMETIMES_CONSUMES\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## SOMETIMES_CONSUMES\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## SOMETIMES_CONSUMES\r
- gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES\r
- gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer ## CONSUMES\r
- gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev ## CONSUMES\r
- gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass ## SOMETIMES_CONSUMES\r
- gEfiSecurityPkgTokenSpaceGuid.PcdTpm2CurrentIrqNum ## CONSUMES\r
- gEfiSecurityPkgTokenSpaceGuid.PcdTpm2PossibleIrqNumBuf ## CONSUMES\r
- gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType ## CONSUMES\r
- gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLaml ## CONSUMES\r
- gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLasa ## CONSUMES\r
\r
[Depex]\r
- gEfiAcpiTableProtocolGuid AND\r
gEfiSmmSwDispatch2ProtocolGuid AND\r
gEfiSmmVariableProtocolGuid AND\r
gEfiTcg2ProtocolGuid\r
--- /dev/null
+/** @file\r
+ TCG2 SMM driver that updates TPM2 items in ACPI table and registers\r
+ SMI2 callback functions for Tcg2 physical presence, ClearMemory, and\r
+ sample for dTPM StartMethod.\r
+\r
+ Caution: This module requires additional review when modified.\r
+ This driver will have external input - variable and ACPINvs data in SMM mode.\r
+ This external input must be validated carefully to avoid security issue.\r
+\r
+ PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.\r
+\r
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) Microsoft Corporation.\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "Tcg2Smm.h"\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/SmmMemLib.h>\r
+\r
+/**\r
+ Notify the system that the SMM variable driver is ready.\r
+**/\r
+VOID\r
+Tcg2NotifyMmReady (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+\r
+ Handle = NULL;\r
+ Status = gBS->InstallProtocolInterface (\r
+ &Handle,\r
+ &gTcg2MmSwSmiRegisteredGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+ This function is an abstraction layer for implementation specific Mm buffer validation routine.\r
+\r
+ @param Buffer The buffer start address to be checked.\r
+ @param Length The buffer length to be checked.\r
+\r
+ @retval TRUE This buffer is valid per processor architecture and not overlap with SMRAM.\r
+ @retval FALSE This buffer is not valid per processor architecture or overlap with SMRAM.\r
+**/\r
+BOOLEAN\r
+IsBufferOutsideMmValid (\r
+ IN EFI_PHYSICAL_ADDRESS Buffer,\r
+ IN UINT64 Length\r
+ )\r
+{\r
+ return SmmIsBufferOutsideSmmValid (Buffer, Length);\r
+}\r
+\r
+/**\r
+ The driver's entry point.\r
+\r
+ It install callbacks for TPM physical presence and MemoryClear, and locate\r
+ SMM variable to be used in the callback function.\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval Others Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeTcgSmm (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ return InitializeTcgCommon ();\r
+}\r
+++ /dev/null
-/** @file\r
- The TPM2 definition block in ACPI table for TCG2 physical presence\r
- and MemoryClear.\r
-\r
-Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
-(c)Copyright 2016 HP Development Company, L.P.<BR>\r
-Copyright (c) Microsoft Corporation.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-DefinitionBlock (\r
- "Tpm.aml",\r
- "SSDT",\r
- 2,\r
- "INTEL ",\r
- "Tpm2Tabl",\r
- 0x1000\r
- )\r
-{\r
- Scope (\_SB)\r
- {\r
- Device (TPM)\r
- {\r
- //\r
- // TCG2\r
- //\r
-\r
- //\r
- // TAG for patching TPM2.0 _HID\r
- //\r
- Name (_HID, "NNNN0000")\r
-\r
- Name (_CID, "MSFT0101")\r
-\r
- //\r
- // Readable name of this device, don't know if this way is correct yet\r
- //\r
- Name (_STR, Unicode ("TPM 2.0 Device"))\r
-\r
- //\r
- // Operational region for Smi port access\r
- //\r
- OperationRegion (SMIP, SystemIO, FixedPcdGet16 (PcdSmiCommandIoPort), 1)\r
- Field (SMIP, ByteAcc, NoLock, Preserve)\r
- {\r
- IOPN, 8\r
- }\r
-\r
- //\r
- // Operational region for TPM access\r
- //\r
- OperationRegion (TPMR, SystemMemory, 0xfed40000, 0x5000)\r
- Field (TPMR, AnyAcc, NoLock, Preserve)\r
- {\r
- ACC0, 8, // TPM_ACCESS_0\r
- Offset(0x8),\r
- INTE, 32, // TPM_INT_ENABLE_0\r
- INTV, 8, // TPM_INT_VECTOR_0\r
- Offset(0x10),\r
- INTS, 32, // TPM_INT_STATUS_0\r
- INTF, 32, // TPM_INTF_CAPABILITY_0\r
- STS0, 32, // TPM_STS_0\r
- Offset(0x24),\r
- FIFO, 32, // TPM_DATA_FIFO_0\r
- Offset(0x30),\r
- TID0, 32, // TPM_INTERFACE_ID_0\r
- // ignore the rest\r
- }\r
-\r
- //\r
- // Operational region for TPM support, TPM Physical Presence and TPM Memory Clear\r
- // Region Offset 0xFFFF0000 and Length 0xF0 will be fixed in C code.\r
- //\r
- OperationRegion (TNVS, SystemMemory, 0xFFFF0000, 0xF0)\r
- Field (TNVS, AnyAcc, NoLock, Preserve)\r
- {\r
- PPIN, 8, // Software SMI for Physical Presence Interface\r
- PPIP, 32, // Used for save physical presence parameter\r
- PPRP, 32, // Physical Presence request operation response\r
- PPRQ, 32, // Physical Presence request operation\r
- PPRM, 32, // Physical Presence request operation parameter\r
- LPPR, 32, // Last Physical Presence request operation\r
- FRET, 32, // Physical Presence function return code\r
- MCIN, 8, // Software SMI for Memory Clear Interface\r
- MCIP, 32, // Used for save the Mor parameter\r
- MORD, 32, // Memory Overwrite Request Data\r
- MRET, 32, // Memory Overwrite function return code\r
- UCRQ, 32, // Physical Presence request operation to Get User Confirmation Status\r
- IRQN, 32, // IRQ Number for _CRS\r
- SFRB, 8 // Is shortformed Pkglength for resource buffer\r
- }\r
-\r
- //\r
- // Possible resource settings returned by _PRS method\r
- // RESS : ResourceTemplate with PkgLength <=63\r
- // RESL : ResourceTemplate with PkgLength > 63\r
- //\r
- // The format of the data has to follow the same format as\r
- // _CRS (according to ACPI spec).\r
- //\r
- Name (RESS, ResourceTemplate() {\r
- Memory32Fixed (ReadWrite, 0xfed40000, 0x5000)\r
- Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , ) {1,2,3,4,5,6,7,8,9,10}\r
- })\r
-\r
- Name (RESL, ResourceTemplate() {\r
- Memory32Fixed (ReadWrite, 0xfed40000, 0x5000)\r
- Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , ) {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}\r
- })\r
-\r
- //\r
- // Current resource settings for _CRS method\r
- //\r
- Name(RES0, ResourceTemplate () {\r
- Memory32Fixed (ReadWrite, 0xfed40000, 0x5000, REG0)\r
- Interrupt(ResourceConsumer, Level, ActiveLow, Shared, , , INTR) {12}\r
- })\r
-\r
- Name(RES1, ResourceTemplate () {\r
- Memory32Fixed (ReadWrite, 0xfed40000, 0x5000, REG1)\r
- })\r
-\r
-\r
- //\r
- // Return the resource consumed by TPM device.\r
- //\r
- Method(_CRS,0,Serialized)\r
- {\r
- //\r
- // IRQNum = 0 means disable IRQ support\r
- //\r
- If (LEqual(IRQN, 0)) {\r
- Return (RES1)\r
- }\r
- Else\r
- {\r
- CreateDWordField(RES0, ^INTR._INT, LIRQ)\r
- Store(IRQN, LIRQ)\r
- Return (RES0)\r
- }\r
- }\r
-\r
- //\r
- // Set resources consumed by the TPM device. This is used to\r
- // assign an interrupt number to the device. The input byte stream\r
- // has to be the same as returned by _CRS (according to ACPI spec).\r
- //\r
- // Platform may choose to override this function with specific interrupt\r
- // programing logic to replace FIFO/TIS SIRQ registers programing\r
- //\r
- Method(_SRS,1,Serialized)\r
- {\r
- //\r
- // Do not configure Interrupt if IRQ Num is configured 0 by default\r
- //\r
- If (LNotEqual(IRQN, 0)) {\r
- //\r
- // Update resource descriptor\r
- // Use the field name to identify the offsets in the argument\r
- // buffer and RES0 buffer.\r
- //\r
- CreateDWordField(Arg0, ^INTR._INT, IRQ0)\r
- CreateDWordField(RES0, ^INTR._INT, LIRQ)\r
- Store(IRQ0, LIRQ)\r
- Store(IRQ0, IRQN)\r
-\r
- CreateBitField(Arg0, ^INTR._HE, ITRG)\r
- CreateBitField(RES0, ^INTR._HE, LTRG)\r
- Store(ITRG, LTRG)\r
-\r
- CreateBitField(Arg0, ^INTR._LL, ILVL)\r
- CreateBitField(RES0, ^INTR._LL, LLVL)\r
- Store(ILVL, LLVL)\r
-\r
- //\r
- // Update TPM FIFO PTP/TIS interface only, identified by TPM_INTERFACE_ID_x lowest\r
- // nibble.\r
- // 0000 - FIFO interface as defined in PTP for TPM 2.0 is active\r
- // 1111 - FIFO interface as defined in TIS1.3 is active\r
- //\r
- If (LOr(LEqual (And (TID0, 0x0F), 0x00), LEqual (And (TID0, 0x0F), 0x0F))) {\r
- //\r
- // If FIFO interface, interrupt vector register is\r
- // available. TCG PTP specification allows only\r
- // values 1..15 in this field. For other interrupts\r
- // the field should stay 0.\r
- //\r
- If (LLess (IRQ0, 16)) {\r
- Store (And(IRQ0, 0xF), INTV)\r
- }\r
- //\r
- // Interrupt enable register (TPM_INT_ENABLE_x) bits 3:4\r
- // contains settings for interrupt polarity.\r
- // The other bits of the byte enable individual interrupts.\r
- // They should be all be zero, but to avoid changing the\r
- // configuration, the other bits are be preserved.\r
- // 00 - high level\r
- // 01 - low level\r
- // 10 - rising edge\r
- // 11 - falling edge\r
- //\r
- // ACPI spec definitions:\r
- // _HE: '1' is Edge, '0' is Level\r
- // _LL: '1' is ActiveHigh, '0' is ActiveLow (inverted from TCG spec)\r
- //\r
- If (LEqual (ITRG, 1)) {\r
- Or(INTE, 0x00000010, INTE)\r
- } Else {\r
- And(INTE, 0xFFFFFFEF, INTE)\r
- }\r
- if (LEqual (ILVL, 0)) {\r
- Or(INTE, 0x00000008, INTE)\r
- } Else {\r
- And(INTE, 0xFFFFFFF7, INTE)\r
- }\r
- }\r
- }\r
- }\r
-\r
- Method(_PRS,0,Serialized)\r
- {\r
- //\r
- // IRQNum = 0 means disable IRQ support\r
- //\r
- If (LEqual(IRQN, 0)) {\r
- Return (RES1)\r
- } ElseIf(LEqual(SFRB, 0)) {\r
- //\r
- // Long format. Possible resources PkgLength > 63\r
- //\r
- Return (RESL)\r
- } Else {\r
- //\r
- // Short format. Possible resources PkgLength <=63\r
- //\r
- Return (RESS)\r
- }\r
- }\r
-\r
- Method (PTS, 1, Serialized)\r
- {\r
- //\r
- // Detect Sx state for MOR, only S4, S5 need to handle\r
- //\r
- If (LAnd (LLess (Arg0, 6), LGreater (Arg0, 3)))\r
- {\r
- //\r
- // Bit4 -- DisableAutoDetect. 0 -- Firmware MAY autodetect.\r
- //\r
- If (LNot (And (MORD, 0x10)))\r
- {\r
- //\r
- // Trigger the SMI through ACPI _PTS method.\r
- //\r
- Store (0x02, MCIP)\r
-\r
- //\r
- // Trigger the SMI interrupt\r
- //\r
- Store (MCIN, IOPN)\r
- }\r
- }\r
- Return (0)\r
- }\r
-\r
- Method (_STA, 0)\r
- {\r
- if (LEqual (ACC0, 0xff))\r
- {\r
- Return (0)\r
- }\r
- Return (0x0f)\r
- }\r
-\r
- //\r
- // TCG Hardware Information\r
- //\r
- Method (HINF, 1, Serialized, 0, {BuffObj, PkgObj}, {UnknownObj}) // IntObj\r
- {\r
- //\r
- // Switch by function index\r
- //\r
- Switch (ToInteger(Arg0))\r
- {\r
- Case (0)\r
- {\r
- //\r
- // Standard query\r
- //\r
- Return (Buffer () {0x03})\r
- }\r
- Case (1)\r
- {\r
- //\r
- // Return failure if no TPM present\r
- //\r
- Name(TPMV, Package () {0x01, Package () {0x2, 0x0}})\r
- if (LEqual (_STA (), 0x00))\r
- {\r
- Return (Package () {0x00})\r
- }\r
-\r
- //\r
- // Return TPM version\r
- //\r
- Return (TPMV)\r
- }\r
- Default {BreakPoint}\r
- }\r
- Return (Buffer () {0})\r
- }\r
-\r
- Name(TPM2, Package (0x02){\r
- Zero,\r
- Zero\r
- })\r
-\r
- Name(TPM3, Package (0x03){\r
- Zero,\r
- Zero,\r
- Zero\r
- })\r
-\r
- //\r
- // TCG Physical Presence Interface\r
- //\r
- Method (TPPI, 2, Serialized, 0, {BuffObj, PkgObj, IntObj, StrObj}, {UnknownObj, UnknownObj}) // IntObj, PkgObj\r
- {\r
- //\r
- // Switch by function index\r
- //\r
- Switch (ToInteger(Arg0))\r
- {\r
- Case (0)\r
- {\r
- //\r
- // Standard query, supports function 1-8\r
- //\r
- Return (Buffer () {0xFF, 0x01})\r
- }\r
- Case (1)\r
- {\r
- //\r
- // a) Get Physical Presence Interface Version\r
- //\r
- Return ("$PV")\r
- }\r
- Case (2)\r
- {\r
- //\r
- // b) Submit TPM Operation Request to Pre-OS Environment\r
- //\r
-\r
- Store (DerefOf (Index (Arg1, 0x00)), PPRQ)\r
- Store (0, PPRM)\r
- Store (0x02, PPIP)\r
-\r
- //\r
- // Trigger the SMI interrupt\r
- //\r
- Store (PPIN, IOPN)\r
- Return (FRET)\r
-\r
-\r
- }\r
- Case (3)\r
- {\r
- //\r
- // c) Get Pending TPM Operation Requested By the OS\r
- //\r
-\r
- Store (PPRQ, Index (TPM2, 0x01))\r
- Return (TPM2)\r
- }\r
- Case (4)\r
- {\r
- //\r
- // d) Get Platform-Specific Action to Transition to Pre-OS Environment\r
- //\r
- Return (2)\r
- }\r
- Case (5)\r
- {\r
- //\r
- // e) Return TPM Operation Response to OS Environment\r
- //\r
- Store (0x05, PPIP)\r
-\r
- //\r
- // Trigger the SMI interrupt\r
- //\r
- Store (PPIN, IOPN)\r
-\r
- Store (LPPR, Index (TPM3, 0x01))\r
- Store (PPRP, Index (TPM3, 0x02))\r
-\r
- Return (TPM3)\r
- }\r
- Case (6)\r
- {\r
-\r
- //\r
- // f) Submit preferred user language (Not implemented)\r
- //\r
-\r
- Return (3)\r
-\r
- }\r
- Case (7)\r
- {\r
- //\r
- // g) Submit TPM Operation Request to Pre-OS Environment 2\r
- //\r
- Store (7, PPIP)\r
- Store (DerefOf (Index (Arg1, 0x00)), PPRQ)\r
- Store (0, PPRM)\r
- If (LEqual (PPRQ, 23)) {\r
- Store (DerefOf (Index (Arg1, 0x01)), PPRM)\r
- }\r
-\r
- //\r
- // Trigger the SMI interrupt\r
- //\r
- Store (PPIN, IOPN)\r
- Return (FRET)\r
- }\r
- Case (8)\r
- {\r
- //\r
- // e) Get User Confirmation Status for Operation\r
- //\r
- Store (8, PPIP)\r
- Store (DerefOf (Index (Arg1, 0x00)), UCRQ)\r
-\r
- //\r
- // Trigger the SMI interrupt\r
- //\r
- Store (PPIN, IOPN)\r
-\r
- Return (FRET)\r
- }\r
-\r
- Default {BreakPoint}\r
- }\r
- Return (1)\r
- }\r
-\r
- Method (TMCI, 2, Serialized, 0, IntObj, {UnknownObj, UnknownObj}) // IntObj, PkgObj\r
- {\r
- //\r
- // Switch by function index\r
- //\r
- Switch (ToInteger (Arg0))\r
- {\r
- Case (0)\r
- {\r
- //\r
- // Standard query, supports function 1-1\r
- //\r
- Return (Buffer () {0x03})\r
- }\r
- Case (1)\r
- {\r
- //\r
- // Save the Operation Value of the Request to MORD (reserved memory)\r
- //\r
- Store (DerefOf (Index (Arg1, 0x00)), MORD)\r
-\r
- //\r
- // Trigger the SMI through ACPI _DSM method.\r
- //\r
- Store (0x01, MCIP)\r
-\r
- //\r
- // Trigger the SMI interrupt\r
- //\r
- Store (MCIN, IOPN)\r
- Return (MRET)\r
- }\r
- Default {BreakPoint}\r
- }\r
- Return (1)\r
- }\r
-\r
- Method (_DSM, 4, Serialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj})\r
- {\r
-\r
- //\r
- // TCG Hardware Information\r
- //\r
- If(LEqual(Arg0, ToUUID ("cf8e16a5-c1e8-4e25-b712-4f54a96702c8")))\r
- {\r
- Return (HINF (Arg2))\r
- }\r
-\r
- //\r
- // TCG Physical Presence Interface\r
- //\r
- If(LEqual(Arg0, ToUUID ("3dddfaa6-361b-4eb4-a424-8d10089d1653")))\r
- {\r
- Return (TPPI (Arg2, Arg3))\r
- }\r
-\r
- //\r
- // TCG Memory Clear Interface\r
- //\r
- If(LEqual(Arg0, ToUUID ("376054ed-cc13-4675-901c-4756d7f2d45d")))\r
- {\r
- Return (TMCI (Arg2, Arg3))\r
- }\r
-\r
- Return (Buffer () {0})\r
- }\r
- }\r
- }\r
-}\r