]> git.proxmox.com Git - mirror_edk2.git/commitdiff
QuarkPlatformPkg: Add Tpm12DeviceLib instance for Atmel I2C TPM
authorMichael Kinney <michael.d.kinney@intel.com>
Thu, 21 Jan 2016 19:30:29 +0000 (19:30 +0000)
committermdkinney <mdkinney@Edk2>
Thu, 21 Jan 2016 19:30:29 +0000 (19:30 +0000)
Add new Tpm12DeviceLib instance for an Atmel I2C TPM

Cc: Kelly Steele <kelly.steele@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Michael Kinney <michael.d.kinney@intel.com>
Reviewed-by: Kelly Steele <kelly.steele@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19730 6f19259b-4bc3-4df7-8a09-765794883524

QuarkPlatformPkg/Library/Tpm12DeviceLibAtmelI2c/TisPc.c [new file with mode: 0644]
QuarkPlatformPkg/Library/Tpm12DeviceLibAtmelI2c/Tpm12DeviceLibAtmelI2c.inf [new file with mode: 0644]
QuarkPlatformPkg/Library/Tpm12DeviceLibAtmelI2c/Tpm12DeviceLibAtmelI2c.uni [new file with mode: 0644]

diff --git a/QuarkPlatformPkg/Library/Tpm12DeviceLibAtmelI2c/TisPc.c b/QuarkPlatformPkg/Library/Tpm12DeviceLibAtmelI2c/TisPc.c
new file mode 100644 (file)
index 0000000..4e5aa41
--- /dev/null
@@ -0,0 +1,419 @@
+/** @file\r
+  Basic TIS (TPM Interface Specification) functions for Atmel I2C TPM.\r
+\r
+  Copyright (c) 2016, 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
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/Tpm12DeviceLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/I2cLib.h>\r
+#include <Library/Tpm12CommandLib.h>\r
+\r
+//\r
+// Atmel I2C TPM slave address\r
+//\r
+#define ATMEL_I2C_TPM_SLAVE_ADDRESS      0x29\r
+\r
+//\r
+// Maximum I2C transfer size for Atmel I2C TPM\r
+//\r
+#define ATMEL_I2C_TPM_MAX_TRANSFER_SIZE  0x10\r
+\r
+//\r
+// Default TimeOut values in microseconds\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
+\r
+/**\r
+  Send command to Atmel I2c TPM breaking request up into multiple I2C transfers\r
+  if required.\r
+\r
+  @param[in] Buffer  Pointer to TPM command data.\r
+  @param[in] Length  Number of bytes of TPM command data.\r
+\r
+  @retval EFI_SUCCESS    TPM command sent.\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
+WriteTpmBufferMultiple (\r
+  IN UINT8  *Buffer,\r
+  IN UINTN  Length\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_I2C_DEVICE_ADDRESS  I2CDeviceAddr;\r
+  UINTN                   Index;\r
+  UINTN                   PartialLength;\r
+\r
+  I2CDeviceAddr.I2CDeviceAddress = ATMEL_I2C_TPM_SLAVE_ADDRESS;\r
+\r
+  DEBUG ((EFI_D_VERBOSE, "WriteTpmBufferMultiple: Addr=%02x  Length=%02x\n", I2CDeviceAddr.I2CDeviceAddress, Length));\r
+\r
+  for (PartialLength = 0; Length > 0; Length -= PartialLength, Buffer += PartialLength) {\r
+    //\r
+    // Write data to TPM.\r
+    //\r
+    PartialLength = MIN (Length, ATMEL_I2C_TPM_MAX_TRANSFER_SIZE);\r
+    Status = I2cWriteMultipleByte (\r
+      I2CDeviceAddr,\r
+      EfiI2CSevenBitAddrMode,\r
+      &PartialLength,\r
+      Buffer\r
+      );\r
+    DEBUG ((EFI_D_VERBOSE, "  "));\r
+    for (Index = 0; Index < PartialLength; Index++) {\r
+      DEBUG ((EFI_D_VERBOSE, "%02x ", Buffer[Index]));\r
+    }\r
+    DEBUG ((EFI_D_VERBOSE, "\n"));\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_VERBOSE, "  Status = %r\n", Status));\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  DEBUG ((EFI_D_VERBOSE, "  Status = %r\n", Status));\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Receive a response to a command from Atmel I2c TPM breaking response into\r
+  multiple I2C transfers if required.\r
+\r
+  @param[out] Buffer  Pointer to TPM response data.\r
+  @param[in]  Length  Maximum number of bytes to receive.\r
+\r
+  @retval EFI_SUCCESS    TPM response received.\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
+ReadTpmBufferMultiple (\r
+  OUT UINT8  *Buffer,\r
+  IN  UINTN  Length\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_I2C_DEVICE_ADDRESS  I2CDeviceAddr;\r
+  UINTN                   WriteLength;\r
+  UINTN                   Index;\r
+  UINTN                   PartialLength;\r
+\r
+  I2CDeviceAddr.I2CDeviceAddress = ATMEL_I2C_TPM_SLAVE_ADDRESS;\r
+  WriteLength = 0;\r
+\r
+  DEBUG ((EFI_D_VERBOSE, "ReadTpmBufferMultiple: Addr=%02x  Length=%02x\n", I2CDeviceAddr.I2CDeviceAddress, Length));\r
+\r
+  for (PartialLength = 0; Length > 0; Length -= PartialLength, Buffer += PartialLength) {\r
+    //\r
+    // Read data from TPM.\r
+    //\r
+    PartialLength = MIN (Length, ATMEL_I2C_TPM_MAX_TRANSFER_SIZE);\r
+    Status = I2cReadMultipleByte (\r
+      I2CDeviceAddr,\r
+      EfiI2CSevenBitAddrMode,\r
+      &WriteLength,\r
+      &PartialLength,\r
+      Buffer\r
+      );\r
+    if (!EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_VERBOSE, "  "));\r
+      for (Index = 0; Index < PartialLength; Index++) {\r
+        DEBUG ((EFI_D_VERBOSE, "%02x ", Buffer[Index]));\r
+      }\r
+      DEBUG ((EFI_D_VERBOSE, "\n"));\r
+    }\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_VERBOSE, "  Status = %r\n", Status));\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  DEBUG ((EFI_D_VERBOSE, "  Status = %r\n", Status));\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This service requests use TPM12.\r
+\r
+  @retval EFI_SUCCESS       Get the control of TPM12 chip.\r
+  @retval EFI_NOT_FOUND     TPM12 not found.\r
+  @retval EFI_DEVICE_ERROR  Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12RequestUseTpm (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  UINT8                      Data;\r
+  UINT64                     Current;\r
+  UINT64                     Previous;\r
+  UINT64                     Total;\r
+  UINT64                     Start;\r
+  UINT64                     End;\r
+  UINT64                     Timeout;\r
+  INT64                      Cycle;\r
+  INT64                      Delta;\r
+\r
+  //\r
+  // Get the current timer value\r
+  //\r
+  Current = GetPerformanceCounter();\r
+\r
+  //\r
+  // Initialize local variables\r
+  //\r
+  Start = 0;\r
+  End   = 0;\r
+  Total = 0;\r
+\r
+  //\r
+  // Retrieve the performance counter properties and compute the number of\r
+  // performance counter ticks required to reach the maximum TIS timeout of\r
+  // TIS_TIMEOUT_A.  TIS_TIMEOUT_A is in microseconds.\r
+  //\r
+  Timeout = DivU64x32 (\r
+              MultU64x32 (\r
+                GetPerformanceCounterProperties (&Start, &End),\r
+                TIS_TIMEOUT_A\r
+                ),\r
+              1000000\r
+              );\r
+  Cycle = End - Start;\r
+  if (Cycle < 0) {\r
+    Cycle = -Cycle;\r
+  }\r
+  Cycle++;\r
+\r
+  //\r
+  // Attempt to read a byte from the Atmel I2C TPM\r
+  //\r
+  do {\r
+    Status = ReadTpmBufferMultiple (&Data, sizeof(Data));\r
+\r
+    Previous = Current;\r
+    Current  = GetPerformanceCounter();\r
+    Delta = (INT64) (Current - Previous);\r
+    if (Start > End) {\r
+      Delta = -Delta;\r
+    }\r
+    if (Delta < 0) {\r
+      Delta += Cycle;\r
+    }\r
+    Total += Delta;\r
+    if (Total >= Timeout) {\r
+      Status = EFI_TIMEOUT;\r
+      DEBUG ((EFI_D_ERROR, "Atmel I2C TPM failed to read: %r\n", Status));\r
+      return Status;\r
+    }\r
+  } while (EFI_ERROR (Status));\r
+\r
+  //\r
+  // Send Physical Presence Command to Atmel I2C TPM\r
+  //\r
+  Status = Tpm12PhysicalPresence (TPM_PHYSICAL_PRESENCE_PRESENT);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Atmel I2C TPM failed to submit physical presence command: %r\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This service enables the sending of commands to the TPM12.\r
+\r
+  @param[in]     InputParameterBlockSize   Size of the TPM12 input parameter block.\r
+  @param[in]     InputParameterBlock       Pointer to the TPM12 input parameter block.\r
+  @param[in,out] OutputParameterBlockSize  Size of the TPM12 output parameter block.\r
+  @param[in]     OutputParameterBlock      Pointer to the TPM12 output parameter block.\r
+\r
+  @retval EFI_SUCCESS           The command byte stream was successfully sent to\r
+                                the device and a response was successfully received.\r
+  @retval EFI_DEVICE_ERROR      The command was not successfully sent to the\r
+                                device or a response was not successfully received\r
+                                from the device.\r
+  @retval EFI_BUFFER_TOO_SMALL  The output parameter block is too small.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm12SubmitCommand (\r
+  IN UINT32      InputParameterBlockSize,\r
+  IN UINT8       *InputParameterBlock,\r
+  IN OUT UINT32  *OutputParameterBlockSize,\r
+  IN UINT8       *OutputParameterBlock\r
+  )\r
+{\r
+  EFI_STATUS           Status;\r
+  UINT32               TpmOutSize;\r
+  TPM_RSP_COMMAND_HDR  *ResponseHeader;\r
+  UINT64               Current;\r
+  UINT64               Previous;\r
+  UINT64               Total;\r
+  UINT64               Start;\r
+  UINT64               End;\r
+  UINT64               Timeout;\r
+  INT64                Cycle;\r
+  INT64                Delta;\r
+\r
+  //\r
+  // Make sure response buffer is big enough to hold a response header\r
+  //\r
+  if (*OutputParameterBlockSize < sizeof (TPM_RSP_COMMAND_HDR)) {\r
+    Status = EFI_BUFFER_TOO_SMALL;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Get the current timer value\r
+  //\r
+  Current = GetPerformanceCounter();\r
+\r
+  //\r
+  // Initialize local variables\r
+  //\r
+  Start = 0;\r
+  End   = 0;\r
+  Total = 0;\r
+\r
+  //\r
+  // Retrieve the performance counter properties and compute the number of\r
+  // performance counter ticks required to reach the maximum TIS timeout of\r
+  // TIS_TIMEOUT_A.  TIS_TIMEOUT_A is in microseconds.\r
+  //\r
+  Timeout = DivU64x32 (\r
+              MultU64x32 (\r
+                GetPerformanceCounterProperties (&Start, &End),\r
+                TIS_TIMEOUT_A\r
+                ),\r
+              1000000\r
+              );\r
+  Cycle = End - Start;\r
+  if (Cycle < 0) {\r
+    Cycle = -Cycle;\r
+  }\r
+  Cycle++;\r
+\r
+  //\r
+  // Send command\r
+  //\r
+  do {\r
+    Status = WriteTpmBufferMultiple (InputParameterBlock, InputParameterBlockSize);\r
+\r
+    Previous = Current;\r
+    Current  = GetPerformanceCounter();\r
+    Delta = (INT64) (Current - Previous);\r
+    if (Start > End) {\r
+      Delta = -Delta;\r
+    }\r
+    if (Delta < 0) {\r
+      Delta += Cycle;\r
+    }\r
+    Total += Delta;\r
+    if (Total >= Timeout) {\r
+      Status = EFI_TIMEOUT;\r
+      goto Done;\r
+    }\r
+  } while (EFI_ERROR (Status));\r
+\r
+  //\r
+  // Receive response header\r
+  //\r
+  do {\r
+    Status = ReadTpmBufferMultiple (OutputParameterBlock, sizeof (TPM_RSP_COMMAND_HDR));\r
+\r
+    Previous = Current;\r
+    Current  = GetPerformanceCounter();\r
+    Delta = (INT64) (Current - Previous);\r
+    if (Start > End) {\r
+      Delta = -Delta;\r
+    }\r
+    if (Delta < 0) {\r
+      Delta += Cycle;\r
+    }\r
+    Total += Delta;\r
+    if (Total >= Timeout) {\r
+      Status = EFI_TIMEOUT;\r
+      goto Done;\r
+    }\r
+  } while (EFI_ERROR (Status));\r
+\r
+  //\r
+  // Check the response data header (tag, parasize and returncode)\r
+  //\r
+  ResponseHeader = (TPM_RSP_COMMAND_HDR *)OutputParameterBlock;\r
+  if (SwapBytes16 (ReadUnaligned16 (&ResponseHeader->tag)) != TPM_TAG_RSP_COMMAND) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto Done;\r
+  }\r
+\r
+  TpmOutSize = SwapBytes32 (ReadUnaligned32 (&ResponseHeader->paramSize));\r
+  if (TpmOutSize == sizeof (TPM_RSP_COMMAND_HDR)) {\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
+  if (TpmOutSize < sizeof (TPM_RSP_COMMAND_HDR)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto Done;\r
+  }\r
+  if (*OutputParameterBlockSize < TpmOutSize) {\r
+    Status = EFI_BUFFER_TOO_SMALL;\r
+    goto Done;\r
+  }\r
+  *OutputParameterBlockSize = TpmOutSize;\r
+\r
+  //\r
+  // Receive the remaining data in the response header\r
+  //\r
+  do {\r
+    Status = ReadTpmBufferMultiple (\r
+               OutputParameterBlock + sizeof (TPM_RSP_COMMAND_HDR),\r
+               TpmOutSize - sizeof (TPM_RSP_COMMAND_HDR)\r
+               );\r
+\r
+    Previous = Current;\r
+    Current  = GetPerformanceCounter();\r
+    Delta = (INT64) (Current - Previous);\r
+    if (Start > End) {\r
+      Delta = -Delta;\r
+    }\r
+    if (Delta < 0) {\r
+      Delta += Cycle;\r
+    }\r
+    Total += Delta;\r
+    if (Total >= Timeout) {\r
+      Status = EFI_TIMEOUT;\r
+      goto Done;\r
+    }\r
+  } while (EFI_ERROR (Status));\r
+\r
+Done:\r
+  DEBUG ((\r
+    EFI_D_VERBOSE,\r
+    "Tpm12SubmitCommand() Status = %r  Time = %ld ms\n",\r
+    Status,\r
+    DivU64x64Remainder (\r
+      MultU64x32 (Total, 1000),\r
+      GetPerformanceCounterProperties (NULL, NULL),\r
+      NULL\r
+      )\r
+    ));\r
+\r
+  return Status;\r
+}\r
diff --git a/QuarkPlatformPkg/Library/Tpm12DeviceLibAtmelI2c/Tpm12DeviceLibAtmelI2c.inf b/QuarkPlatformPkg/Library/Tpm12DeviceLibAtmelI2c/Tpm12DeviceLibAtmelI2c.inf
new file mode 100644 (file)
index 0000000..5a8734f
--- /dev/null
@@ -0,0 +1,45 @@
+## @file\r
+#  Provides some common functions for the TCG feature for Atmel I2C TPM.\r
+#\r
+#  This instance provides basic TPM Interface Specification (TIS) functions\r
+#  or Atmel I2C TPM.\r
+#\r
+# Copyright (c) 2016, 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
+# 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
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = Tpm12DeviceLibAtmelI2c\r
+  MODULE_UNI_FILE                = Tpm12DeviceLibAtmelI2c.uni\r
+  FILE_GUID                      = A0C0B7EF-99FF-417F-8B9F-5AD4701D90D6\r
+  MODULE_TYPE                    = PEIM\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = Tpm12DeviceLib|PEIM DXE_DRIVER DXE_SMM_DRIVER UEFI_DRIVER\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  TisPc.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  SecurityPkg/SecurityPkg.dec\r
+  QuarkSocPkg/QuarkSocPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  TimerLib\r
+  DebugLib\r
+  I2cLib\r
+  Tpm12CommandLib\r
diff --git a/QuarkPlatformPkg/Library/Tpm12DeviceLibAtmelI2c/Tpm12DeviceLibAtmelI2c.uni b/QuarkPlatformPkg/Library/Tpm12DeviceLibAtmelI2c/Tpm12DeviceLibAtmelI2c.uni
new file mode 100644 (file)
index 0000000..aaee1e2
--- /dev/null
@@ -0,0 +1,21 @@
+// /** @file\r
+// Provides some common functions for the TCG feature for Atmel I2C TPM.\r
+//\r
+// This instance provides basic TPM Interface Specification (TIS) functions\r
+// for Atmel I2C TPM.\r
+//\r
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+//\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
+// 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
+//\r
+// **/\r
+\r
+#string STR_MODULE_ABSTRACT             #language en-US "Provides some common functions for the TCG feature for Atmel I2C TPM."\r
+\r
+#string STR_MODULE_DESCRIPTION          #language en-US "This instance provides basic TPM Interface Specification (TIS) functions for Atmel I2C TPM."\r
+\r