]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12Tis.c
SecurityPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / SecurityPkg / Library / Tpm12DeviceLibDTpm / Tpm12Tis.c
index b8d13aa30b792536eea9b91d61a4ff320c556f01..9c5b3d5740bafe8d6e53cbe998c30ee749759d5e 100644 (file)
@@ -1,15 +1,9 @@
 /** @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
@@ -23,164 +17,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #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
@@ -201,11 +46,49 @@ Tpm12TisPcPresenceCheck (
   )\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
@@ -238,7 +121,7 @@ Tpm12TisPcWaitRegisterBits (
 }\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
@@ -282,7 +165,7 @@ Tpm12TisPcReadBurstCount (
 }\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
@@ -313,7 +196,7 @@ Tpm12TisPcPrepareCommand (
 }\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
@@ -329,11 +212,11 @@ Tpm12TisPcRequestUseTpm (
   )\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
@@ -351,12 +234,12 @@ Tpm12TisPcRequestUseTpm (
 /**\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
@@ -378,6 +261,7 @@ Tpm12TisTpmCommand (
   UINT32                            TpmOutSize;\r
   UINT16                            Data16;\r
   UINT32                            Data32;\r
+  UINT16                            RspTag;\r
 \r
   DEBUG_CODE (\r
     UINTN  DebugSize;\r
@@ -475,11 +359,12 @@ Tpm12TisTpmCommand (
     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
@@ -531,7 +416,7 @@ Exit:
 \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
@@ -542,13 +427,89 @@ Tpm12SubmitCommand (
   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
@@ -564,5 +525,20 @@ Tpm12RequestUseTpm (
   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