+++ /dev/null
-/** @file\r
- Basic TIS (TPM Interface Specification) functions for Atmel I2C TPM.\r
-\r
- Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\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
-\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
- Status = EFI_SUCCESS;\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
- Status = EFI_SUCCESS;\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
- 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
- // Initialize local variables\r
- //\r
- Start = 0;\r
- End = 0;\r
- Total = 0;\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
- // 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
- *OutputParameterBlockSize = TpmOutSize;\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