}\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
// Still in Command Execution state. Try to goIdle, the behavior is agnostic.\r
//\r
Status = EFI_DEVICE_ERROR;\r
- goto Exit;\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
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
Dump PTP register information.\r
\r