/** @file\r
TIS (TPM Interface Specification) functions used by TPM1.2.\r
- \r
-Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>\r
-(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
-This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php\r
\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include <Library/Tpm12CommandLib.h>\r
#include <Library/PcdLib.h>\r
\r
-//\r
-// Set structure alignment to 1-byte\r
-//\r
-#pragma pack (1)\r
-\r
-//\r
-// Register set map as specified in TIS specification Chapter 10\r
-//\r
-typedef struct {\r
- ///\r
- /// Used to gain ownership for this particular port.\r
- ///\r
- UINT8 Access; // 0\r
- UINT8 Reserved1[7]; // 1\r
- ///\r
- /// Controls interrupts.\r
- ///\r
- UINT32 IntEnable; // 8\r
- ///\r
- /// SIRQ vector to be used by the TPM.\r
- ///\r
- UINT8 IntVector; // 0ch\r
- UINT8 Reserved2[3]; // 0dh\r
- ///\r
- /// What caused interrupt.\r
- ///\r
- UINT32 IntSts; // 10h\r
- ///\r
- /// Shows which interrupts are supported by that particular TPM.\r
- ///\r
- UINT32 IntfCapability; // 14h\r
- ///\r
- /// Status Register. Provides status of the TPM.\r
- ///\r
- UINT8 Status; // 18h\r
- ///\r
- /// Number of consecutive writes that can be done to the TPM.\r
- ///\r
- UINT16 BurstCount; // 19h\r
- UINT8 Reserved3[9];\r
- ///\r
- /// Read or write FIFO, depending on transaction.\r
- ///\r
- UINT32 DataFifo; // 24h\r
- UINT8 Reserved4[0xed8]; // 28h\r
- ///\r
- /// Vendor ID\r
- ///\r
- UINT16 Vid; // 0f00h\r
- ///\r
- /// Device ID\r
- ///\r
- UINT16 Did; // 0f02h\r
- ///\r
- /// Revision ID\r
- ///\r
- UINT8 Rid; // 0f04h\r
- ///\r
- /// TCG defined configuration registers.\r
- ///\r
- UINT8 TcgDefined[0x7b]; // 0f05h\r
- ///\r
- /// Alias to I/O legacy space.\r
- ///\r
- UINT32 LegacyAddress1; // 0f80h\r
- ///\r
- /// Additional 8 bits for I/O legacy space extension.\r
- ///\r
- UINT32 LegacyAddress1Ex; // 0f84h\r
- ///\r
- /// Alias to second I/O legacy space.\r
- ///\r
- UINT32 LegacyAddress2; // 0f88h\r
- ///\r
- /// Additional 8 bits for second I/O legacy space extension.\r
- ///\r
- UINT32 LegacyAddress2Ex; // 0f8ch\r
- ///\r
- /// Vendor-defined configuration registers.\r
- ///\r
- UINT8 VendorDefined[0x70];// 0f90h\r
-} TIS_PC_REGISTERS;\r
-\r
-//\r
-// Restore original structure alignment\r
-//\r
-#pragma pack ()\r
-\r
-//\r
-// Define pointer types used to access TIS registers on PC\r
-//\r
-typedef TIS_PC_REGISTERS *TIS_PC_REGISTERS_PTR;\r
-\r
-//\r
-// Define bits of ACCESS and STATUS registers\r
-//\r
-\r
-///\r
-/// This bit is a 1 to indicate that the other bits in this register are valid.\r
-///\r
-#define TIS_PC_VALID BIT7\r
-///\r
-/// Indicate that this locality is active.\r
-///\r
-#define TIS_PC_ACC_ACTIVE BIT5\r
-///\r
-/// Set to 1 to indicate that this locality had the TPM taken away while\r
-/// this locality had the TIS_PC_ACC_ACTIVE bit set.\r
-///\r
-#define TIS_PC_ACC_SEIZED BIT4\r
-///\r
-/// Set to 1 to indicate that TPM MUST reset the\r
-/// TIS_PC_ACC_ACTIVE bit and remove ownership for localities less than the\r
-/// locality that is writing this bit.\r
-///\r
-#define TIS_PC_ACC_SEIZE BIT3\r
-///\r
-/// When this bit is 1, another locality is requesting usage of the TPM.\r
-///\r
-#define TIS_PC_ACC_PENDIND BIT2\r
-///\r
-/// Set to 1 to indicate that this locality is requesting to use TPM.\r
-///\r
-#define TIS_PC_ACC_RQUUSE BIT1\r
-///\r
-/// A value of 1 indicates that a T/OS has not been established on the platform\r
-///\r
-#define TIS_PC_ACC_ESTABLISH BIT0\r
-\r
-///\r
-/// When this bit is 1, TPM is in the Ready state, \r
-/// indicating it is ready to receive a new command.\r
-///\r
-#define TIS_PC_STS_READY BIT6\r
-///\r
-/// Write a 1 to this bit to cause the TPM to execute that command.\r
-///\r
-#define TIS_PC_STS_GO BIT5\r
-///\r
-/// This bit indicates that the TPM has data available as a response.\r
-///\r
-#define TIS_PC_STS_DATA BIT4\r
-///\r
-/// The TPM sets this bit to a value of 1 when it expects another byte of data for a command.\r
-///\r
-#define TIS_PC_STS_EXPECT BIT3\r
-///\r
-/// Writes a 1 to this bit to force the TPM to re-send the response.\r
-///\r
-#define TIS_PC_STS_RETRY BIT1\r
+#include <IndustryStandard/TpmPtp.h>\r
+#include <IndustryStandard/TpmTis.h>\r
\r
-//\r
-// Default TimeOut value\r
-//\r
-#define TIS_TIMEOUT_A (750 * 1000) // 750ms\r
-#define TIS_TIMEOUT_B (2000 * 1000) // 2s\r
-#define TIS_TIMEOUT_C (750 * 1000) // 750ms\r
-#define TIS_TIMEOUT_D (750 * 1000) // 750ms\r
+typedef enum {\r
+ PtpInterfaceTis,\r
+ PtpInterfaceFifo,\r
+ PtpInterfaceCrb,\r
+ PtpInterfaceMax,\r
+} PTP_INTERFACE_TYPE;\r
\r
//\r
// Max TPM command/reponse length\r
)\r
{\r
UINT8 RegRead;\r
- \r
+\r
RegRead = MmioRead8 ((UINTN)&TisReg->Access);\r
return (BOOLEAN)(RegRead != (UINT8)-1);\r
}\r
\r
+/**\r
+ Return PTP interface type.\r
+\r
+ @param[in] Register Pointer to PTP register.\r
+\r
+ @return PTP interface type.\r
+**/\r
+PTP_INTERFACE_TYPE\r
+Tpm12GetPtpInterface (\r
+ IN VOID *Register\r
+ )\r
+{\r
+ PTP_CRB_INTERFACE_IDENTIFIER InterfaceId;\r
+ PTP_FIFO_INTERFACE_CAPABILITY InterfaceCapability;\r
+\r
+ if (!Tpm12TisPcPresenceCheck (Register)) {\r
+ return PtpInterfaceMax;\r
+ }\r
+ //\r
+ // Check interface id\r
+ //\r
+ InterfaceId.Uint32 = MmioRead32 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->InterfaceId);\r
+ InterfaceCapability.Uint32 = MmioRead32 ((UINTN)&((PTP_FIFO_REGISTERS *)Register)->InterfaceCapability);\r
+\r
+ if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_CRB) &&\r
+ (InterfaceId.Bits.InterfaceVersion == PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_CRB) &&\r
+ (InterfaceId.Bits.CapCRB != 0)) {\r
+ return PtpInterfaceCrb;\r
+ }\r
+ if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_FIFO) &&\r
+ (InterfaceId.Bits.InterfaceVersion == PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_FIFO) &&\r
+ (InterfaceId.Bits.CapFIFO != 0) &&\r
+ (InterfaceCapability.Bits.InterfaceVersion == INTERFACE_CAPABILITY_INTERFACE_VERSION_PTP)) {\r
+ return PtpInterfaceFifo;\r
+ }\r
+ return PtpInterfaceTis;\r
+}\r
+\r
/**\r
Check whether the value of a TPM chip register satisfies the input BIT setting.\r
\r
}\r
\r
/**\r
- Get BurstCount by reading the burstCount field of a TIS regiger \r
+ Get BurstCount by reading the burstCount field of a TIS regiger\r
in the time of default TIS_TIMEOUT_D.\r
\r
@param[in] TisReg Pointer to TIS register.\r
}\r
\r
/**\r
- Set TPM chip to ready state by sending ready command TIS_PC_STS_READY \r
+ Set TPM chip to ready state by sending ready command TIS_PC_STS_READY\r
to Status Register in time.\r
\r
@param[in] TisReg Pointer to TIS register.\r
}\r
\r
/**\r
- Get the control of TPM chip by sending requestUse command TIS_PC_ACC_RQUUSE \r
+ Get the control of TPM chip by sending requestUse command TIS_PC_ACC_RQUUSE\r
to ACCESS Register in the time of default TIS_TIMEOUT_A.\r
\r
@param[in] TisReg Pointer to TIS register.\r
)\r
{\r
EFI_STATUS Status;\r
- \r
+\r
if (TisReg == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
if (!Tpm12TisPcPresenceCheck (TisReg)) {\r
return EFI_NOT_FOUND;\r
}\r
/**\r
Send a command to TPM for execution and return response data.\r
\r
- @param[in] TisReg TPM register space base address. \r
- @param[in] BufferIn Buffer for command data. \r
- @param[in] SizeIn Size of command data. \r
- @param[in, out] BufferOut Buffer for response data. \r
- @param[in, out] SizeOut Size of response data. \r
- \r
+ @param[in] TisReg TPM register space base address.\r
+ @param[in] BufferIn Buffer for command data.\r
+ @param[in] SizeIn Size of command data.\r
+ @param[in, out] BufferOut Buffer for response data.\r
+ @param[in, out] SizeOut Size of response data.\r
+\r
@retval EFI_SUCCESS Operation completed successfully.\r
@retval EFI_BUFFER_TOO_SMALL Response data buffer is too small.\r
@retval EFI_DEVICE_ERROR Unexpected device behavior.\r
UINT32 TpmOutSize;\r
UINT16 Data16;\r
UINT32 Data32;\r
+ UINT16 RspTag;\r
\r
DEBUG_CODE (\r
UINTN DebugSize;\r
DEBUG ((EFI_D_VERBOSE, "\n"));\r
);\r
//\r
- // Check the reponse data header (tag,parasize and returncode )\r
+ // Check the response data header (tag, parasize and returncode)\r
//\r
CopyMem (&Data16, BufferOut, sizeof (UINT16));\r
- if (SwapBytes16 (Data16) != TPM_TAG_RSP_COMMAND) {\r
- DEBUG ((EFI_D_ERROR, "TPM12: TPM_ST_RSP error - %x\n", TPM_TAG_RSP_COMMAND));\r
+ RspTag = SwapBytes16 (Data16);\r
+ if (RspTag != TPM_TAG_RSP_COMMAND && RspTag != TPM_TAG_RSP_AUTH1_COMMAND && RspTag != TPM_TAG_RSP_AUTH2_COMMAND) {\r
+ DEBUG ((EFI_D_ERROR, "TPM12: Response tag error - current tag value is %x\n", RspTag));\r
Status = EFI_UNSUPPORTED;\r
goto Exit;\r
}\r
\r
@retval EFI_SUCCESS The command byte stream was successfully sent to the device and a response was successfully received.\r
@retval EFI_DEVICE_ERROR The command was not successfully sent to the device or a response was not successfully received from the device.\r
- @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small. \r
+ @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small.\r
**/\r
EFI_STATUS\r
EFIAPI\r
IN UINT8 *OutputParameterBlock\r
)\r
{\r
- return Tpm12TisTpmCommand (\r
- (TIS_PC_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress),\r
- InputParameterBlock,\r
- InputParameterBlockSize,\r
- OutputParameterBlock,\r
- OutputParameterBlockSize\r
- );\r
+ PTP_INTERFACE_TYPE PtpInterface;\r
+\r
+ //\r
+ // Special handle for TPM1.2 to check PTP too, because PTP/TIS share same register address.\r
+ //\r
+ PtpInterface = Tpm12GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
+ switch (PtpInterface) {\r
+ case PtpInterfaceFifo:\r
+ case PtpInterfaceTis:\r
+ return Tpm12TisTpmCommand (\r
+ (TIS_PC_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress),\r
+ InputParameterBlock,\r
+ InputParameterBlockSize,\r
+ OutputParameterBlock,\r
+ OutputParameterBlockSize\r
+ );\r
+ case PtpInterfaceCrb:\r
+ //\r
+ // No need to support CRB because it is only accept TPM2 command.\r
+ //\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Check whether the value of a TPM chip register satisfies the input BIT setting.\r
+\r
+ @param[in] Register Address port of register to be checked.\r
+ @param[in] BitSet Check these data bits are set.\r
+ @param[in] BitClear Check these data bits are clear.\r
+ @param[in] TimeOut The max wait time (unit MicroSecond) when checking register.\r
+\r
+ @retval EFI_SUCCESS The register satisfies the check bit.\r
+ @retval EFI_TIMEOUT The register can't run into the expected status in time.\r
+**/\r
+EFI_STATUS\r
+Tpm12PtpCrbWaitRegisterBits (\r
+ IN UINT32 *Register,\r
+ IN UINT32 BitSet,\r
+ IN UINT32 BitClear,\r
+ IN UINT32 TimeOut\r
+ )\r
+{\r
+ UINT32 RegRead;\r
+ UINT32 WaitTime;\r
+\r
+ for (WaitTime = 0; WaitTime < TimeOut; WaitTime += 30){\r
+ RegRead = MmioRead32 ((UINTN)Register);\r
+ if ((RegRead & BitSet) == BitSet && (RegRead & BitClear) == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ MicroSecondDelay (30);\r
+ }\r
+ return EFI_TIMEOUT;\r
+}\r
+\r
+/**\r
+ Get the control of TPM chip.\r
+\r
+ @param[in] CrbReg Pointer to CRB register.\r
+\r
+ @retval EFI_SUCCESS Get the control of TPM chip.\r
+ @retval EFI_INVALID_PARAMETER CrbReg is NULL.\r
+ @retval EFI_NOT_FOUND TPM chip doesn't exit.\r
+ @retval EFI_TIMEOUT Can't get the TPM control in time.\r
+**/\r
+EFI_STATUS\r
+Tpm12PtpCrbRequestUseTpm (\r
+ IN PTP_CRB_REGISTERS_PTR CrbReg\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ MmioWrite32((UINTN)&CrbReg->LocalityControl, PTP_CRB_LOCALITY_CONTROL_REQUEST_ACCESS);\r
+ Status = Tpm12PtpCrbWaitRegisterBits (\r
+ &CrbReg->LocalityStatus,\r
+ PTP_CRB_LOCALITY_STATUS_GRANTED,\r
+ 0,\r
+ PTP_TIMEOUT_A\r
+ );\r
+ return Status;\r
}\r
\r
/**\r
VOID\r
)\r
{\r
- return Tpm12TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
+ PTP_INTERFACE_TYPE PtpInterface;\r
+\r
+ //\r
+ // Special handle for TPM1.2 to check PTP too, because PTP/TIS share same register address.\r
+ // Some other program might leverage this function to check the existence of TPM chip.\r
+ //\r
+ PtpInterface = Tpm12GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
+ switch (PtpInterface) {\r
+ case PtpInterfaceCrb:\r
+ return Tpm12PtpCrbRequestUseTpm ((PTP_CRB_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
+ case PtpInterfaceFifo:\r
+ case PtpInterfaceTis:\r
+ return Tpm12TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
+ default:\r
+ return EFI_NOT_FOUND;\r
+ }\r
}\r