/** @file\r
PTP (Platform TPM Profile) CRB (Command Response Buffer) interface used by dTPM2.0 library.\r
\r
-Copyright (c) 2015, Intel Corporation. All rights reserved.<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) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include <IndustryStandard/TpmPtp.h>\r
#include <IndustryStandard/TpmTis.h>\r
\r
-typedef enum {\r
- PtpInterfaceTis,\r
- PtpInterfaceFifo,\r
- PtpInterfaceCrb,\r
- PtpInterfaceMax,\r
-} PTP_INTERFACE_TYPE;\r
-\r
//\r
// Execution of the command may take from several seconds to minutes for certain\r
// commands, such as key generation.\r
@retval FALSE TPM PTP is not found.\r
**/\r
BOOLEAN\r
-IsPtpPresence (\r
+Tpm2IsPtpPresence (\r
IN VOID *Reg\r
)\r
{\r
{\r
EFI_STATUS Status;\r
\r
- if (!IsPtpPresence (CrbReg)) {\r
+ if (!Tpm2IsPtpPresence (CrbReg)) {\r
return EFI_NOT_FOUND;\r
}\r
\r
}\r
DEBUG ((EFI_D_VERBOSE, "\n"));\r
);\r
- TpmOutSize = 0;\r
+ TpmOutSize = 0;\r
\r
//\r
// STEP 0:\r
+ // if CapCRbIdelByPass == 0, enforce Idle state before sending command\r
+ //\r
+ if (PcdGet8(PcdCRBIdleByPass) == 0 && (MmioRead32((UINTN)&CrbReg->CrbControlStatus) & PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE) == 0){\r
+ Status = PtpCrbWaitRegisterBits (\r
+ &CrbReg->CrbControlStatus,\r
+ PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE,\r
+ 0,\r
+ PTP_TIMEOUT_C\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Try to goIdle to recover TPM\r
+ //\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto GoIdle_Exit;\r
+ }\r
+ }\r
+\r
+ //\r
+ // STEP 1:\r
// Ready is any time the TPM is ready to receive a command, following a write\r
// of 1 by software to Request.cmdReady, as indicated by the Status field\r
// being cleared to 0.\r
);\r
if (EFI_ERROR (Status)) {\r
Status = EFI_DEVICE_ERROR;\r
- goto Exit;\r
+ goto GoIdle_Exit;\r
}\r
Status = PtpCrbWaitRegisterBits (\r
&CrbReg->CrbControlStatus,\r
);\r
if (EFI_ERROR (Status)) {\r
Status = EFI_DEVICE_ERROR;\r
- goto Exit;\r
+ goto GoIdle_Exit;\r
}\r
\r
//\r
- // STEP 1:\r
+ // STEP 2:\r
// Command Reception occurs following a Ready state between the write of the\r
// first byte of a command to the Command Buffer and the receipt of a write\r
// of 1 to Start.\r
MmioWrite32 ((UINTN)&CrbReg->CrbControlResponseSize, sizeof(CrbReg->CrbDataBuffer));\r
\r
//\r
- // STEP 2:\r
+ // STEP 3:\r
// Command Execution occurs after receipt of a 1 to Start and the TPM\r
// clearing Start to 0.\r
//\r
PTP_TIMEOUT_MAX\r
);\r
if (EFI_ERROR (Status)) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Exit;\r
+ //\r
+ // Command Completion check timeout. Cancel the currently executing command by writing TPM_CRB_CTRL_CANCEL,\r
+ // Expect TPM_RC_CANCELLED or successfully completed response.\r
+ //\r
+ MmioWrite32((UINTN)&CrbReg->CrbControlCancel, PTP_CRB_CONTROL_CANCEL);\r
+ Status = PtpCrbWaitRegisterBits (\r
+ &CrbReg->CrbControlStart,\r
+ 0,\r
+ PTP_CRB_CONTROL_START,\r
+ PTP_TIMEOUT_B\r
+ );\r
+ MmioWrite32((UINTN)&CrbReg->CrbControlCancel, 0);\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ //\r
+ // Still in Command Execution state. Try to goIdle, the behavior is agnostic.\r
+ //\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto GoIdle_Exit;\r
+ }\r
}\r
\r
//\r
- // STEP 3:\r
+ // STEP 4:\r
// Command Completion occurs after completion of a command (indicated by the\r
// TPM clearing TPM_CRB_CTRL_Start_x to 0) and before a write of a 1 by the\r
// software to Request.goIdle.\r
if (SwapBytes16 (Data16) == TPM_ST_RSP_COMMAND) {\r
DEBUG ((EFI_D_ERROR, "TPM2: TPM_ST_RSP error - %x\n", TPM_ST_RSP_COMMAND));\r
Status = EFI_UNSUPPORTED;\r
- goto Exit;\r
+ goto GoIdle_Exit;\r
}\r
\r
CopyMem (&Data32, (BufferOut + 2), sizeof (UINT32));\r
TpmOutSize = SwapBytes32 (Data32);\r
if (*SizeOut < TpmOutSize) {\r
+ //\r
+ // Command completed, but buffer is not enough\r
+ //\r
Status = EFI_BUFFER_TOO_SMALL;\r
- goto Exit;\r
+ goto GoReady_Exit;\r
}\r
*SizeOut = TpmOutSize;\r
//\r
for (Index = sizeof (TPM2_RESPONSE_HEADER); Index < TpmOutSize; Index++) {\r
BufferOut[Index] = MmioRead8 ((UINTN)&CrbReg->CrbDataBuffer[Index]);\r
}\r
-Exit:\r
+\r
DEBUG_CODE (\r
DEBUG ((EFI_D_VERBOSE, "PtpCrbTpmCommand Receive - "));\r
for (Index = 0; Index < TpmOutSize; Index++) {\r
DEBUG ((EFI_D_VERBOSE, "\n"));\r
);\r
\r
+GoReady_Exit:\r
//\r
- // STEP 4:\r
- // Idle is any time TPM_CRB_CTRL_STS_x.Status.goIdle is 1.\r
+ // Goto Ready State if command is completed succesfully and TPM support IdleBypass\r
+ // If not supported. flow down to GoIdle\r
+ //\r
+ if (PcdGet8(PcdCRBIdleByPass) == 1) {\r
+ MmioWrite32((UINTN)&CrbReg->CrbControlRequest, PTP_CRB_CONTROL_AREA_REQUEST_COMMAND_READY);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Do not wait for state transition for TIMEOUT_C\r
+ // This function will try to wait 2 TIMEOUT_C at the beginning in next call.\r
+ //\r
+GoIdle_Exit:\r
+\r
+ //\r
+ // Return to Idle state by setting TPM_CRB_CTRL_STS_x.Status.goIdle to 1.\r
//\r
MmioWrite32((UINTN)&CrbReg->CrbControlRequest, PTP_CRB_CONTROL_AREA_REQUEST_GO_IDLE);\r
+\r
+ //\r
+ // Only enforce Idle state transition if execution fails when CRBIndleBypass==1\r
+ // Leave regular Idle delay at the beginning of next command execution\r
+ //\r
+ if (PcdGet8(PcdCRBIdleByPass) == 1){\r
+ Status = PtpCrbWaitRegisterBits (\r
+ &CrbReg->CrbControlStatus,\r
+ PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE,\r
+ 0,\r
+ PTP_TIMEOUT_C\r
+ );\r
+ }\r
+\r
return Status;\r
}\r
\r
\r
@return PTP interface type.\r
**/\r
-PTP_INTERFACE_TYPE\r
-GetPtpInterface (\r
+TPM2_PTP_INTERFACE_TYPE\r
+Tpm2GetPtpInterface (\r
IN VOID *Register\r
)\r
{\r
PTP_CRB_INTERFACE_IDENTIFIER InterfaceId;\r
PTP_FIFO_INTERFACE_CAPABILITY InterfaceCapability;\r
\r
- if (!IsPtpPresence (Register)) {\r
- return PtpInterfaceMax;\r
+ if (!Tpm2IsPtpPresence (Register)) {\r
+ return Tpm2PtpInterfaceMax;\r
}\r
//\r
// Check interface id\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
+ return Tpm2PtpInterfaceCrb;\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
+ return Tpm2PtpInterfaceFifo;\r
}\r
- return PtpInterfaceTis;\r
+ return Tpm2PtpInterfaceTis;\r
+}\r
+\r
+/**\r
+ Return PTP CRB interface IdleByPass state.\r
+\r
+ @param[in] Register Pointer to PTP register.\r
+\r
+ @return PTP CRB interface IdleByPass state.\r
+**/\r
+UINT8\r
+Tpm2GetIdleByPass (\r
+ IN VOID *Register\r
+ )\r
+{\r
+ PTP_CRB_INTERFACE_IDENTIFIER InterfaceId;\r
+\r
+ //\r
+ // Check interface id\r
+ //\r
+ InterfaceId.Uint32 = MmioRead32 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->InterfaceId);\r
+\r
+ return (UINT8)(InterfaceId.Bits.CapCRBIdleBypass);\r
}\r
\r
/**\r
UINT16 Vid;\r
UINT16 Did;\r
UINT8 Rid;\r
- PTP_INTERFACE_TYPE PtpInterface;\r
+ TPM2_PTP_INTERFACE_TYPE PtpInterface;\r
\r
- if (!IsPtpPresence (Register)) {\r
+ if (!Tpm2IsPtpPresence (Register)) {\r
return ;\r
}\r
\r
Vid = 0xFFFF;\r
Did = 0xFFFF;\r
Rid = 0xFF;\r
- PtpInterface = GetPtpInterface (Register);\r
+ PtpInterface = PcdGet8(PcdActiveTpmInterfaceType);\r
DEBUG ((EFI_D_INFO, "PtpInterface - %x\n", PtpInterface));\r
switch (PtpInterface) {\r
- case PtpInterfaceCrb:\r
+ case Tpm2PtpInterfaceCrb:\r
Vid = MmioRead16 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->Vid);\r
Did = MmioRead16 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->Did);\r
Rid = (UINT8)InterfaceId.Bits.Rid;\r
break;\r
- case PtpInterfaceFifo:\r
- case PtpInterfaceTis:\r
+ case Tpm2PtpInterfaceFifo:\r
+ case Tpm2PtpInterfaceTis:\r
Vid = MmioRead16 ((UINTN)&((PTP_FIFO_REGISTERS *)Register)->Vid);\r
Did = MmioRead16 ((UINTN)&((PTP_FIFO_REGISTERS *)Register)->Did);\r
Rid = MmioRead8 ((UINTN)&((PTP_FIFO_REGISTERS *)Register)->Rid);\r
IN UINT8 *OutputParameterBlock\r
)\r
{\r
- PTP_INTERFACE_TYPE PtpInterface;\r
+ TPM2_PTP_INTERFACE_TYPE PtpInterface;\r
\r
- PtpInterface = GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
+ PtpInterface = PcdGet8(PcdActiveTpmInterfaceType);\r
switch (PtpInterface) {\r
- case PtpInterfaceCrb:\r
+ case Tpm2PtpInterfaceCrb:\r
return PtpCrbTpmCommand (\r
(PTP_CRB_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress),\r
InputParameterBlock,\r
OutputParameterBlock,\r
OutputParameterBlockSize\r
);\r
- case PtpInterfaceFifo:\r
- case PtpInterfaceTis:\r
+ case Tpm2PtpInterfaceFifo:\r
+ case Tpm2PtpInterfaceTis:\r
return Tpm2TisTpmCommand (\r
(TIS_PC_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress),\r
InputParameterBlock,\r
VOID\r
)\r
{\r
- PTP_INTERFACE_TYPE PtpInterface;\r
+ TPM2_PTP_INTERFACE_TYPE PtpInterface;\r
\r
- PtpInterface = GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
+ PtpInterface = PcdGet8(PcdActiveTpmInterfaceType);\r
switch (PtpInterface) {\r
- case PtpInterfaceCrb:\r
+ case Tpm2PtpInterfaceCrb:\r
return PtpCrbRequestUseTpm ((PTP_CRB_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
- case PtpInterfaceFifo:\r
- case PtpInterfaceTis:\r
+ case Tpm2PtpInterfaceFifo:\r
+ case Tpm2PtpInterfaceTis:\r
return TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
default:\r
return EFI_NOT_FOUND;\r