]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Ptp.c
SecurityPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / SecurityPkg / Library / Tpm2DeviceLibDTpm / Tpm2Ptp.c
index a627bbdedf7a220221b1512f379c87dc42c8339d..8596143b535cb529e9701b7097272e347d9071ba 100644 (file)
@@ -1,14 +1,8 @@
 /** @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
@@ -25,13 +19,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #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
@@ -52,7 +39,7 @@ typedef enum {
   @retval    FALSE   TPM PTP is not found.\r
 **/\r
 BOOLEAN\r
-IsPtpPresence (\r
+Tpm2IsPtpPresence (\r
   IN VOID *Reg\r
   )\r
 {\r
@@ -117,7 +104,7 @@ PtpCrbRequestUseTpm (
 {\r
   EFI_STATUS                        Status;\r
 \r
-  if (!IsPtpPresence (CrbReg)) {\r
+  if (!Tpm2IsPtpPresence (CrbReg)) {\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
@@ -181,10 +168,30 @@ PtpCrbTpmCommand (
     }\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
@@ -198,7 +205,7 @@ PtpCrbTpmCommand (
              );\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
@@ -208,11 +215,11 @@ PtpCrbTpmCommand (
              );\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
@@ -228,7 +235,7 @@ PtpCrbTpmCommand (
   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
@@ -240,12 +247,30 @@ PtpCrbTpmCommand (
              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
@@ -272,14 +297,17 @@ PtpCrbTpmCommand (
   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
@@ -288,7 +316,7 @@ PtpCrbTpmCommand (
   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
@@ -297,11 +325,40 @@ Exit:
     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
@@ -352,16 +409,16 @@ TisPcRequestUseTpm (
 \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
@@ -372,15 +429,37 @@ GetPtpInterface (
   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
@@ -399,9 +478,9 @@ DumpPtpInfo (
   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
@@ -440,16 +519,16 @@ DumpPtpInfo (
   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
@@ -483,11 +562,11 @@ DTpm2SubmitCommand (
   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
@@ -495,8 +574,8 @@ DTpm2SubmitCommand (
            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
@@ -522,14 +601,14 @@ DTpm2RequestUseTpm (
   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