/** @file\r
TIS (TPM Interface Specification) functions used by dTPM2.0 library.\r
- \r
-Copyright (c) 2013 - 2016, 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
\r
#include <IndustryStandard/TpmTis.h>\r
\r
-#define TIS_TIMEOUT_MAX (90000 * 1000) // 90s\r
+#define TIS_TIMEOUT_MAX (90000 * 1000) // 90s\r
\r
//\r
-// Max TPM command/reponse length\r
+// Max TPM command/response length\r
//\r
-#define TPMCMDBUFLENGTH 0x500\r
+#define TPMCMDBUFLENGTH 0x500\r
\r
/**\r
Check whether TPM chip exist.\r
**/\r
BOOLEAN\r
TisPcPresenceCheck (\r
- IN TIS_PC_REGISTERS_PTR TisReg\r
+ IN TIS_PC_REGISTERS_PTR TisReg\r
)\r
{\r
- UINT8 RegRead;\r
- \r
+ UINT8 RegRead;\r
+\r
RegRead = MmioRead8 ((UINTN)&TisReg->Access);\r
return (BOOLEAN)(RegRead != (UINT8)-1);\r
}\r
**/\r
EFI_STATUS\r
TisPcWaitRegisterBits (\r
- IN UINT8 *Register,\r
- IN UINT8 BitSet,\r
- IN UINT8 BitClear,\r
- IN UINT32 TimeOut\r
+ IN UINT8 *Register,\r
+ IN UINT8 BitSet,\r
+ IN UINT8 BitClear,\r
+ IN UINT32 TimeOut\r
)\r
{\r
- UINT8 RegRead;\r
- UINT32 WaitTime;\r
+ UINT8 RegRead;\r
+ UINT32 WaitTime;\r
\r
- for (WaitTime = 0; WaitTime < TimeOut; WaitTime += 30){\r
+ for (WaitTime = 0; WaitTime < TimeOut; WaitTime += 30) {\r
RegRead = MmioRead8 ((UINTN)Register);\r
- if ((RegRead & BitSet) == BitSet && (RegRead & BitClear) == 0)\r
+ if (((RegRead & BitSet) == BitSet) && ((RegRead & BitClear) == 0)) {\r
return EFI_SUCCESS;\r
+ }\r
+\r
MicroSecondDelay (30);\r
}\r
+\r
return EFI_TIMEOUT;\r
}\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 register\r
in the time of default TIS_TIMEOUT_D.\r
\r
@param[in] TisReg Pointer to TIS register.\r
- @param[out] BurstCount Pointer to a buffer to store the got BurstConut.\r
+ @param[out] BurstCount Pointer to a buffer to store the got BurstCount.\r
\r
@retval EFI_SUCCESS Get BurstCount.\r
@retval EFI_INVALID_PARAMETER TisReg is NULL or BurstCount is NULL.\r
**/\r
EFI_STATUS\r
TisPcReadBurstCount (\r
- IN TIS_PC_REGISTERS_PTR TisReg,\r
- OUT UINT16 *BurstCount\r
+ IN TIS_PC_REGISTERS_PTR TisReg,\r
+ OUT UINT16 *BurstCount\r
)\r
{\r
- UINT32 WaitTime;\r
- UINT8 DataByte0;\r
- UINT8 DataByte1;\r
+ UINT32 WaitTime;\r
+ UINT8 DataByte0;\r
+ UINT8 DataByte1;\r
\r
- if (BurstCount == NULL || TisReg == NULL) {\r
+ if ((BurstCount == NULL) || (TisReg == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
if (*BurstCount != 0) {\r
return EFI_SUCCESS;\r
}\r
+\r
MicroSecondDelay (30);\r
WaitTime += 30;\r
} while (WaitTime < TIS_TIMEOUT_D);\r
}\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
**/\r
EFI_STATUS\r
TisPcPrepareCommand (\r
- IN TIS_PC_REGISTERS_PTR TisReg\r
+ IN TIS_PC_REGISTERS_PTR TisReg\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
\r
if (TisReg == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_READY);\r
+ MmioWrite8 ((UINTN)&TisReg->Status, TIS_PC_STS_READY);\r
Status = TisPcWaitRegisterBits (\r
&TisReg->Status,\r
TIS_PC_STS_READY,\r
}\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
**/\r
EFI_STATUS\r
TisPcRequestUseTpm (\r
- IN TIS_PC_REGISTERS_PTR TisReg\r
+ IN TIS_PC_REGISTERS_PTR TisReg\r
)\r
{\r
- EFI_STATUS Status;\r
- \r
+ EFI_STATUS Status;\r
+\r
if (TisReg == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
if (!TisPcPresenceCheck (TisReg)) {\r
return EFI_NOT_FOUND;\r
}\r
\r
- MmioWrite8((UINTN)&TisReg->Access, TIS_PC_ACC_RQUUSE);\r
+ MmioWrite8 ((UINTN)&TisReg->Access, TIS_PC_ACC_RQUUSE);\r
Status = TisPcWaitRegisterBits (\r
&TisReg->Access,\r
(UINT8)(TIS_PC_ACC_ACTIVE |TIS_PC_VALID),\r
/**\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
**/\r
EFI_STATUS\r
Tpm2TisTpmCommand (\r
- IN TIS_PC_REGISTERS_PTR TisReg,\r
- IN UINT8 *BufferIn,\r
- IN UINT32 SizeIn,\r
- IN OUT UINT8 *BufferOut,\r
- IN OUT UINT32 *SizeOut\r
+ IN TIS_PC_REGISTERS_PTR TisReg,\r
+ IN UINT8 *BufferIn,\r
+ IN UINT32 SizeIn,\r
+ IN OUT UINT8 *BufferOut,\r
+ IN OUT UINT32 *SizeOut\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT16 BurstCount;\r
- UINT32 Index;\r
- UINT32 TpmOutSize;\r
- UINT16 Data16;\r
- UINT32 Data32;\r
-\r
- DEBUG_CODE (\r
- UINTN DebugSize;\r
-\r
- DEBUG ((EFI_D_VERBOSE, "Tpm2TisTpmCommand Send - "));\r
- if (SizeIn > 0x100) {\r
- DebugSize = 0x40;\r
- } else {\r
- DebugSize = SizeIn;\r
- }\r
- for (Index = 0; Index < DebugSize; Index++) {\r
- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferIn[Index]));\r
- }\r
- if (DebugSize != SizeIn) {\r
- DEBUG ((EFI_D_VERBOSE, "...... "));\r
- for (Index = SizeIn - 0x20; Index < SizeIn; Index++) {\r
- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferIn[Index]));\r
- }\r
+ EFI_STATUS Status;\r
+ UINT16 BurstCount;\r
+ UINT32 Index;\r
+ UINT32 TpmOutSize;\r
+ UINT16 Data16;\r
+ UINT32 Data32;\r
+\r
+ DEBUG_CODE_BEGIN ();\r
+ UINTN DebugSize;\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "Tpm2TisTpmCommand Send - "));\r
+ if (SizeIn > 0x100) {\r
+ DebugSize = 0x40;\r
+ } else {\r
+ DebugSize = SizeIn;\r
+ }\r
+\r
+ for (Index = 0; Index < DebugSize; Index++) {\r
+ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferIn[Index]));\r
+ }\r
+\r
+ if (DebugSize != SizeIn) {\r
+ DEBUG ((DEBUG_VERBOSE, "...... "));\r
+ for (Index = SizeIn - 0x20; Index < SizeIn; Index++) {\r
+ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferIn[Index]));\r
}\r
- DEBUG ((EFI_D_VERBOSE, "\n"));\r
- );\r
+ }\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "\n"));\r
+ DEBUG_CODE_END ();\r
TpmOutSize = 0;\r
\r
Status = TisPcPrepareCommand (TisReg);\r
- if (EFI_ERROR (Status)){\r
+ if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "Tpm2 is not ready for command!\n"));\r
return EFI_DEVICE_ERROR;\r
}\r
+\r
//\r
// Send the command data to Tpm\r
//\r
Status = EFI_DEVICE_ERROR;\r
goto Exit;\r
}\r
- for (; BurstCount > 0 && Index < SizeIn; BurstCount--) {\r
- MmioWrite8((UINTN)&TisReg->DataFifo, *(BufferIn + Index));\r
+\r
+ for ( ; BurstCount > 0 && Index < SizeIn; BurstCount--) {\r
+ MmioWrite8 ((UINTN)&TisReg->DataFifo, *(BufferIn + Index));\r
Index++;\r
}\r
}\r
+\r
//\r
// Check the Tpm status STS_EXPECT change from 1 to 0\r
//\r
Status = TisPcWaitRegisterBits (\r
&TisReg->Status,\r
- (UINT8) TIS_PC_VALID,\r
+ (UINT8)TIS_PC_VALID,\r
TIS_PC_STS_EXPECT,\r
TIS_TIMEOUT_C\r
);\r
Status = EFI_BUFFER_TOO_SMALL;\r
goto Exit;\r
}\r
+\r
//\r
// Executed the TPM command and waiting for the response data ready\r
//\r
- MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_GO);\r
+ MmioWrite8 ((UINTN)&TisReg->Status, TIS_PC_STS_GO);\r
\r
//\r
// NOTE: That may take many seconds to minutes for certain commands, such as key generation.\r
//\r
Status = TisPcWaitRegisterBits (\r
&TisReg->Status,\r
- (UINT8) (TIS_PC_VALID | TIS_PC_STS_DATA),\r
+ (UINT8)(TIS_PC_VALID | TIS_PC_STS_DATA),\r
0,\r
TIS_TIMEOUT_MAX\r
);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "Wait for Tpm2 response data time out!!\n"));\r
- Status = EFI_DEVICE_ERROR;\r
- goto Exit;\r
+ //\r
+ // dataAvail check timeout. Cancel the currently executing command by writing commandCancel,\r
+ // Expect TPM_RC_CANCELLED or successfully completed response.\r
+ //\r
+ DEBUG ((DEBUG_ERROR, "Wait for Tpm2 response data time out. Trying to cancel the command!!\n"));\r
+\r
+ MmioWrite32 ((UINTN)&TisReg->Status, TIS_PC_STS_CANCEL);\r
+ Status = TisPcWaitRegisterBits (\r
+ &TisReg->Status,\r
+ (UINT8)(TIS_PC_VALID | TIS_PC_STS_DATA),\r
+ 0,\r
+ TIS_TIMEOUT_B\r
+ );\r
+ //\r
+ // Do not clear CANCEL bit here because Writes of 0 to this bit are ignored\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Cancel executing command fail to get any response\r
+ // Try to abort the command with write of a 1 to commandReady in Command Execution state\r
+ //\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
}\r
+\r
//\r
// Get response data header\r
//\r
- Index = 0;\r
+ Index = 0;\r
BurstCount = 0;\r
while (Index < sizeof (TPM2_RESPONSE_HEADER)) {\r
Status = TisPcReadBurstCount (TisReg, &BurstCount);\r
Status = EFI_DEVICE_ERROR;\r
goto Exit;\r
}\r
- for (; BurstCount > 0; BurstCount--) {\r
+\r
+ for ( ; BurstCount > 0; BurstCount--) {\r
*(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);\r
Index++;\r
- if (Index == sizeof (TPM2_RESPONSE_HEADER)) break;\r
+ if (Index == sizeof (TPM2_RESPONSE_HEADER)) {\r
+ break;\r
+ }\r
}\r
}\r
- DEBUG_CODE (\r
- DEBUG ((EFI_D_VERBOSE, "Tpm2TisTpmCommand ReceiveHeader - "));\r
- for (Index = 0; Index < sizeof (TPM2_RESPONSE_HEADER); Index++) {\r
- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferOut[Index]));\r
- }\r
- DEBUG ((EFI_D_VERBOSE, "\n"));\r
- );\r
+\r
+ DEBUG_CODE_BEGIN ();\r
+ DEBUG ((DEBUG_VERBOSE, "Tpm2TisTpmCommand ReceiveHeader - "));\r
+ for (Index = 0; Index < sizeof (TPM2_RESPONSE_HEADER); Index++) {\r
+ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferOut[Index]));\r
+ }\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "\n"));\r
+ DEBUG_CODE_END ();\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
// TPM2 should not use this RSP_COMMAND\r
if (SwapBytes16 (Data16) == TPM_ST_RSP_COMMAND) {\r
- DEBUG ((EFI_D_ERROR, "TPM2: TPM_ST_RSP error - %x\n", TPM_ST_RSP_COMMAND));\r
+ DEBUG ((DEBUG_ERROR, "TPM2: TPM_ST_RSP error - %x\n", TPM_ST_RSP_COMMAND));\r
Status = EFI_UNSUPPORTED;\r
goto Exit;\r
}\r
\r
CopyMem (&Data32, (BufferOut + 2), sizeof (UINT32));\r
- TpmOutSize = SwapBytes32 (Data32);\r
+ TpmOutSize = SwapBytes32 (Data32);\r
if (*SizeOut < TpmOutSize) {\r
Status = EFI_BUFFER_TOO_SMALL;\r
goto Exit;\r
}\r
+\r
*SizeOut = TpmOutSize;\r
//\r
// Continue reading the remaining data\r
//\r
while ( Index < TpmOutSize ) {\r
- for (; BurstCount > 0; BurstCount--) {\r
+ for ( ; BurstCount > 0; BurstCount--) {\r
*(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);\r
Index++;\r
if (Index == TpmOutSize) {\r
goto Exit;\r
}\r
}\r
+\r
Status = TisPcReadBurstCount (TisReg, &BurstCount);\r
if (EFI_ERROR (Status)) {\r
Status = EFI_DEVICE_ERROR;\r
goto Exit;\r
}\r
}\r
+\r
Exit:\r
- DEBUG_CODE (\r
- DEBUG ((EFI_D_VERBOSE, "Tpm2TisTpmCommand Receive - "));\r
- for (Index = 0; Index < TpmOutSize; Index++) {\r
- DEBUG ((EFI_D_VERBOSE, "%02x ", BufferOut[Index]));\r
- }\r
- DEBUG ((EFI_D_VERBOSE, "\n"));\r
- );\r
- MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_READY);\r
+ DEBUG_CODE_BEGIN ();\r
+ DEBUG ((DEBUG_VERBOSE, "Tpm2TisTpmCommand Receive - "));\r
+ for (Index = 0; Index < TpmOutSize; Index++) {\r
+ DEBUG ((DEBUG_VERBOSE, "%02x ", BufferOut[Index]));\r
+ }\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "\n"));\r
+ DEBUG_CODE_END ();\r
+ MmioWrite8 ((UINTN)&TisReg->Status, TIS_PC_STS_READY);\r
return Status;\r
}\r
\r
\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
DTpm2TisSubmitCommand (\r
- IN UINT32 InputParameterBlockSize,\r
- IN UINT8 *InputParameterBlock,\r
- IN OUT UINT32 *OutputParameterBlockSize,\r
- IN UINT8 *OutputParameterBlock\r
+ IN UINT32 InputParameterBlockSize,\r
+ IN UINT8 *InputParameterBlock,\r
+ IN OUT UINT32 *OutputParameterBlockSize,\r
+ IN UINT8 *OutputParameterBlock\r
)\r
{\r
return Tpm2TisTpmCommand (\r
- (TIS_PC_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress),\r
+ (TIS_PC_REGISTERS_PTR)(UINTN)PcdGet64 (PcdTpmBaseAddress),\r
InputParameterBlock,\r
InputParameterBlockSize,\r
OutputParameterBlock,\r
VOID\r
)\r
{\r
- return TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
+ return TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR)(UINTN)PcdGet64 (PcdTpmBaseAddress));\r
}\r