SecurityPkg: Tpm2DeviceLib: Enable CapCRBIdleBypass support
authorZhang, Chao B <chao.b.zhang@intel.com>
Fri, 23 Mar 2018 06:04:01 +0000 (14:04 +0800)
committerZhang, Chao B <chao.b.zhang@intel.com>
Wed, 27 Jun 2018 01:31:01 +0000 (09:31 +0800)
Directly transition from CMD completion to CMD Ready state if device
supports IdleByPass

Cc: Long Qin <qin.long@intel.com>
Cc: Yao Jiewen <jiewen.yao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Chao Zhang <chao.b.zhang@intel.com>
Reviewed-by: Long Qin <qin.long@intel.com>
SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.c
SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.c
SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf
SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Ptp.c
SecurityPkg/SecurityPkg.dec
SecurityPkg/SecurityPkg.uni

index 3feb64d..e6fe563 100644 (file)
@@ -31,6 +31,18 @@ Tpm2GetPtpInterface (
   IN VOID *Register\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
 /**\r
   This service enables the sending of commands to the TPM2.\r
 \r
@@ -140,6 +152,7 @@ Tpm2DeviceLibConstructor (
   )\r
 {\r
   TPM2_PTP_INTERFACE_TYPE  PtpInterface;\r
+  UINT8                    IdleByPass;\r
 \r
   //\r
   // Cache current active TpmInterfaceType only when needed\r
@@ -148,5 +161,11 @@ Tpm2DeviceLibConstructor (
     PtpInterface = Tpm2GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
     PcdSet8S(PcdActiveTpmInterfaceType, PtpInterface);\r
   }\r
+\r
+  if (PcdGet8(PcdActiveTpmInterfaceType) == PtpInterfaceCrb && PcdGet8(PcdCRBIdleByPass) == 0xFF) {\r
+    IdleByPass = Tpm2GetIdleByPass((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
+    PcdSet8S(PcdCRBIdleByPass, IdleByPass);\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 }\r
index 634bbae..2e54a78 100644 (file)
@@ -55,3 +55,4 @@
 [Pcd]\r
   gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress            ## CONSUMES\r
   gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType    ## PRODUCES\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdCRBIdleByPass             ## PRODUCES
\ No newline at end of file
index 01f78bf..edcdb72 100644 (file)
@@ -34,6 +34,18 @@ Tpm2GetPtpInterface (
   IN VOID *Register\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
 /**\r
   Dump PTP register information.\r
 \r
@@ -97,6 +109,7 @@ Tpm2InstanceLibDTpmConstructor (
 {\r
   EFI_STATUS               Status;\r
   TPM2_PTP_INTERFACE_TYPE  PtpInterface;\r
+  UINT8                    IdleByPass;\r
 \r
   Status = Tpm2RegisterTpm2DeviceLib (&mDTpm2InternalTpm2Device);\r
   if ((Status == EFI_SUCCESS) || (Status == EFI_UNSUPPORTED)) {\r
@@ -111,6 +124,12 @@ Tpm2InstanceLibDTpmConstructor (
         PtpInterface = Tpm2GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
         PcdSet8S(PcdActiveTpmInterfaceType, PtpInterface);\r
       }\r
+\r
+      if (PcdGet8(PcdActiveTpmInterfaceType) == PtpInterfaceCrb && PcdGet8(PcdCRBIdleByPass) == 0xFF) {\r
+        IdleByPass = Tpm2GetIdleByPass((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
+        PcdSet8S(PcdCRBIdleByPass, IdleByPass);\r
+      }\r
+\r
       DumpPtpInfo ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
     }\r
     return EFI_SUCCESS;\r
index 876a5a6..24e4c35 100644 (file)
@@ -50,4 +50,5 @@
 \r
 [Pcd]\r
   gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress          ## CONSUMES\r
-  gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType  ## PRODUCES
\ No newline at end of file
+  gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType  ## PRODUCES\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdCRBIdleByPass             ## PRODUCES
\ No newline at end of file
index 1bc153a..ad2f188 100644 (file)
@@ -174,10 +174,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
@@ -191,7 +211,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
@@ -201,11 +221,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
@@ -221,7 +241,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
@@ -251,12 +271,12 @@ PtpCrbTpmCommand (
       // 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
@@ -283,14 +303,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
@@ -299,7 +322,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
@@ -308,11 +331,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
@@ -394,6 +446,28 @@ Tpm2GetPtpInterface (
   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
index 60f1c0a..e24b563 100644 (file)
   # @Prompt current active TPM interface type.\r
   gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType|0xFF|UINT8|0x0001001E\r
 \r
+  ## This PCD records IdleByass status supported by current active TPM interface.\r
+  #  Accodingt to TCG PTP spec 1.3, TPM with CRB interface can skip idle state and \r
+  #  diretcly move to CmdReady state. <BR>\r
+  #  0x00 - Do not support IdleByPass.<BR>\r
+  #  0x01 - Support IdleByPass.<BR>\r
+  #  0xFF - IdleByPass State is not synced with TPM hardware.<BR>\r
+  #\r
+  # @Prompt IdleByass status supported by current active TPM interface.\r
+  gEfiSecurityPkgTokenSpaceGuid.PcdCRBIdleByPass|0xFF|UINT8|0x0001001F\r
+\r
 [UserExtensions.TianoCore."ExtraFiles"]\r
   SecurityPkgExtra.uni\r
index c34250e..000bc83 100644 (file)
                                                                                           "0x00 - FIFO interface as defined in TIS 1.3 is active.<BR>\n"\r
                                                                                           "0x01 - FIFO interface as defined in PTP for TPM 2.0 is active.<BR>\n"\r
                                                                                           "0x02 - CRB interface is active.<BR>\n"\r
-                                                                                          "0xFF - Contains no current active TPM interface type<BR>"
\ No newline at end of file
+                                                                                          "0xFF - Contains no current active TPM interface type<BR>"\r
+\r
+#string STR_gEfiSecurityPkgTokenSpaceGuid_PcdCRBIdleByPass_PROMPT  #language en-US "IdleByass status supported by current active TPM interface."\r
+\r
+#string STR_gEfiSecurityPkgTokenSpaceGuid_PcdCRBIdleByPass_HELP  #language en-US "This PCD records IdleByass status supported by current active TPM interface.\n"\r
+                                                                                          "Accodingt to TCG PTP spec 1.3, TPM with CRB interface can skip idle state and diretcly move to CmdReady state. <BR>"\r
+                                                                                          "0x01 - Do not support IdleByPass.<BR>\n"\r
+                                                                                          "0x02 - Support IdleByPass.<BR>\n"\r
+                                                                                          "0xFF - IdleByPass State is not synced with TPM hardware.<BR>"
\ No newline at end of file