2 Basic TIS (TPM Interface Specification) functions for Infineon I2C TPM.
4 Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/Tpm12DeviceLib.h>
17 #include <Library/BaseLib.h>
18 #include <Library/TimerLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/I2cLib.h>
23 // Default TPM (Infineon SLB9645) I2C Slave Device Address on Crosshill board.
25 #define TPM_I2C_SLAVE_DEVICE_ADDRESS 0x20
28 // Default Infineon SLB9645 TPM I2C mapped registers (SLB9645 I2C Comm. Protocol Application Note).
30 #define INFINEON_TPM_ACCESS_0_ADDRESS_DEFAULT 0x0
31 #define INFINEON_TPM_STS_0_ADDRESS_DEFAULT 0x01
32 #define INFINEON_TPM_BURST0_COUNT_0_DEFAULT 0x02
33 #define INFINEON_TPM_BURST1_COUNT_0_DEFAULT 0x03
34 #define INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT 0x05
35 #define INFINEON_TPM_DID_VID_0_DEFAULT 0x09
38 // Max. retry count for read transfers (as recommended by Infineon).
43 // Guard time of 250us between I2C read and next I2C write transfer (as recommended by Infineon).
45 #define GUARD_TIME 250
48 // Define bits of ACCESS and STATUS registers
52 /// This bit is a 1 to indicate that the other bits in this register are valid.
54 #define TIS_PC_VALID BIT7
56 /// Indicate that this locality is active.
58 #define TIS_PC_ACC_ACTIVE BIT5
60 /// Set to 1 to indicate that this locality had the TPM taken away while
61 /// this locality had the TIS_PC_ACC_ACTIVE bit set.
63 #define TIS_PC_ACC_SEIZED BIT4
65 /// Set to 1 to indicate that TPM MUST reset the
66 /// TIS_PC_ACC_ACTIVE bit and remove ownership for localities less than the
67 /// locality that is writing this bit.
69 #define TIS_PC_ACC_SEIZE BIT3
71 /// When this bit is 1, another locality is requesting usage of the TPM.
73 #define TIS_PC_ACC_PENDIND BIT2
75 /// Set to 1 to indicate that this locality is requesting to use TPM.
77 #define TIS_PC_ACC_RQUUSE BIT1
79 /// A value of 1 indicates that a T/OS has not been established on the platform
81 #define TIS_PC_ACC_ESTABLISH BIT0
84 /// When this bit is 1, TPM is in the Ready state,
85 /// indicating it is ready to receive a new command.
87 #define TIS_PC_STS_READY BIT6
89 /// Write a 1 to this bit to cause the TPM to execute that command.
91 #define TIS_PC_STS_GO BIT5
93 /// This bit indicates that the TPM has data available as a response.
95 #define TIS_PC_STS_DATA BIT4
97 /// The TPM sets this bit to a value of 1 when it expects another byte of data for a command.
99 #define TIS_PC_STS_EXPECT BIT3
101 /// Writes a 1 to this bit to force the TPM to re-send the response.
103 #define TIS_PC_STS_RETRY BIT1
106 // Default TimeOut values in microseconds
108 #define TIS_TIMEOUT_A (750 * 1000) // 750ms
109 #define TIS_TIMEOUT_B (2000 * 1000) // 2s
110 #define TIS_TIMEOUT_C (750 * 1000) // 750ms
111 #define TIS_TIMEOUT_D (750 * 1000) // 750ms
114 // Global variable to indicate if TPM I2C Read Transfer has previously occurred.
115 // NOTE: Given the GUARD_TIME requirement (TpmAccess.h), if this library loaded
116 // by PEI Drivers this global variable required to be resident in R/W memory
118 BOOLEAN mI2CPrevReadTransfer
= FALSE
;
121 Writes single byte data to TPM specified by I2C register address.
123 @param[in] TpmAddress The register to write.
124 @param[in] Data The data to write to the register.
136 EFI_I2C_DEVICE_ADDRESS I2CDeviceAddr
;
139 // Setup I2C Slave device address and address mode (7-bit).
141 I2CDeviceAddr
.I2CDeviceAddress
= TPM_I2C_SLAVE_DEVICE_ADDRESS
;
144 // As recommended by Infineon (SLB9645 I2C Communication protocol application
145 // note revision 1.0) wait 250 microseconds between a read and a write transfer.
147 if (mI2CPrevReadTransfer
) {
148 MicroSecondDelay (GUARD_TIME
);
152 // Write to TPM register.
155 WriteData
[0] = (UINT8
)TpmAddress
;
158 Status
= I2cWriteMultipleByte (
160 EfiI2CSevenBitAddrMode
,
164 if (EFI_ERROR(Status
)) {
165 DEBUG ((EFI_D_ERROR
, "TpmWriteByte(): I2C Write to TPM address %0x failed (%r)\n", TpmAddress
, Status
));
166 ASSERT (FALSE
); // Writes to TPM should always succeed.
169 mI2CPrevReadTransfer
= FALSE
;
173 Reads single byte data from TPM specified by I2C register address.
175 Due to stability issues when using I2C combined write/read transfers (with
176 RESTART) to TPM (specifically read from status register), a single write is
177 performed followed by single read (with STOP condition in between).
179 @param[in] TpmAddress Address of register to read.
181 @return The value register read.
193 EFI_I2C_DEVICE_ADDRESS I2CDeviceAddr
;
194 EFI_I2C_ADDR_MODE I2CAddrMode
;
198 Status
= EFI_SUCCESS
;
203 // Locate I2C protocol for TPM I2C access.
205 I2CDeviceAddr
.I2CDeviceAddress
= TPM_I2C_SLAVE_DEVICE_ADDRESS
;
206 I2CAddrMode
= EfiI2CSevenBitAddrMode
;
209 // As recommended by Infineon (SLB9645 I2C Communication protocol application
210 // note revision 1.0) retry up to 3 times if TPM status, access or burst count
211 // registers return 0xFF.
213 while ((ReadData
== 0xFF) && (ReadCount
< READ_RETRY
)) {
215 // As recommended by Infineon (SLB9645 I2C Communication protocol application
216 // note revision 1.0) wait 250 microseconds between a read and a write transfer.
218 if (mI2CPrevReadTransfer
) {
219 MicroSecondDelay (GUARD_TIME
);
223 // Write address to TPM.
225 Data
[0] = (UINT8
)TpmAddress
;
226 Status
= I2cWriteByte (
232 if (EFI_ERROR(Status
)) {
233 DEBUG ((EFI_D_INFO
, "TpmReadByte(): write to TPM address %0x failed (%r)\n", TpmAddress
, Status
));
236 mI2CPrevReadTransfer
= FALSE
;
239 // Read data from TPM.
241 Data
[0] = (UINT8
)TpmAddress
;
242 Status
= I2cReadByte (
248 if (EFI_ERROR(Status
)) {
249 DEBUG ((EFI_D_INFO
, "TpmReadByte(): read from TPM address %0x failed (%r)\n", TpmAddress
, Status
));
256 // Only need to retry 3 times for TPM status, access, and burst count registers.
257 // If read transfer is to TPM Data FIFO, do not retry, exit loop.
259 if (TpmAddress
== INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT
) {
260 ReadCount
= READ_RETRY
;
265 mI2CPrevReadTransfer
= TRUE
;
268 if (EFI_ERROR(Status
)) {
270 // Only reads to access register allowed to fail.
272 if (TpmAddress
!= INFINEON_TPM_ACCESS_0_ADDRESS_DEFAULT
) {
273 DEBUG ((EFI_D_ERROR
, "TpmReadByte(): read from TPM address %0x failed\n", TpmAddress
));
274 ASSERT_EFI_ERROR (Status
);
281 Check whether the value of a TPM chip register satisfies the input BIT setting.
283 @param[in] Register TPM register to be checked.
284 @param[in] BitSet Check these data bits are set.
285 @param[in] BitClear Check these data bits are clear.
286 @param[in] TimeOut The max wait time (unit MicroSecond) when checking register.
288 @retval EFI_SUCCESS The register satisfies the check bit.
289 @retval EFI_TIMEOUT The register can't run into the expected status in time.
292 TisPcWaitRegisterBits (
302 for (WaitTime
= 0; WaitTime
< TimeOut
; WaitTime
+= 30){
303 RegRead
= TpmReadByte (Register
);
304 if ((RegRead
& BitSet
) == BitSet
&& (RegRead
& BitClear
) == 0)
306 MicroSecondDelay (30);
312 Get BurstCount by reading the burstCount field of a TIS register
313 in the time of default TIS_TIMEOUT_D.
315 @param[out] BurstCount Pointer to a buffer to store the got BurstConut.
317 @retval EFI_SUCCESS Get BurstCount.
318 @retval EFI_INVALID_PARAMETER BurstCount is NULL.
319 @retval EFI_TIMEOUT BurstCount can't be got in time.
322 TisPcReadBurstCount (
323 OUT UINT16
*BurstCount
330 if (BurstCount
== NULL
) {
331 return EFI_INVALID_PARAMETER
;
337 // BurstCount is UINT16, but it is not 2bytes aligned,
338 // so it needs to use TpmReadByte to read two times
340 DataByte0
= TpmReadByte (INFINEON_TPM_BURST0_COUNT_0_DEFAULT
);
341 DataByte1
= TpmReadByte (INFINEON_TPM_BURST1_COUNT_0_DEFAULT
);
342 *BurstCount
= (UINT16
)((DataByte1
<< 8) + DataByte0
);
343 if (*BurstCount
!= 0) {
346 MicroSecondDelay (30);
348 } while (WaitTime
< TIS_TIMEOUT_D
);
354 Set TPM chip to ready state by sending ready command TIS_PC_STS_READY
355 to Status Register in time.
357 @retval EFI_SUCCESS TPM chip enters into ready state.
358 @retval EFI_TIMEOUT TPM chip can't be set to ready state in time.
361 TisPcPrepareCommand (
367 TpmWriteByte (INFINEON_TPM_STS_0_ADDRESS_DEFAULT
, TIS_PC_STS_READY
);
368 Status
= TisPcWaitRegisterBits (
369 INFINEON_TPM_STS_0_ADDRESS_DEFAULT
,
378 This service requests use TPM12.
380 @retval EFI_SUCCESS Get the control of TPM12 chip.
381 @retval EFI_NOT_FOUND TPM12 not found.
382 @retval EFI_DEVICE_ERROR Unexpected device behavior.
393 // Check to see if TPM exists
395 if (TpmReadByte (INFINEON_TPM_ACCESS_0_ADDRESS_DEFAULT
) == 0xFF) {
396 return EFI_NOT_FOUND
;
399 TpmWriteByte (INFINEON_TPM_ACCESS_0_ADDRESS_DEFAULT
, TIS_PC_ACC_RQUUSE
);
402 // No locality set before, ACCESS_X.activeLocality MUST be valid within TIMEOUT_A
404 Status
= TisPcWaitRegisterBits (
405 INFINEON_TPM_ACCESS_0_ADDRESS_DEFAULT
,
406 (UINT8
)(TIS_PC_ACC_ACTIVE
|TIS_PC_VALID
),
414 Send command to TPM for execution.
416 @param[in] TpmBuffer Buffer for TPM command data.
417 @param[in] DataLength TPM command data length.
419 @retval EFI_SUCCESS Operation completed successfully.
420 @retval EFI_TIMEOUT The register can't run into the expected status in time.
433 Status
= TisPcPrepareCommand ();
434 if (EFI_ERROR (Status
)){
435 DEBUG ((DEBUG_ERROR
, "The TPM is not ready!\n"));
439 while (Index
< DataLength
) {
440 Status
= TisPcReadBurstCount (&BurstCount
);
441 if (EFI_ERROR (Status
)) {
442 Status
= EFI_TIMEOUT
;
445 for (; BurstCount
> 0 && Index
< DataLength
; BurstCount
--) {
446 TpmWriteByte (INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT
, *(TpmBuffer
+ Index
));
451 // Ensure the TPM status STS_EXPECT change from 1 to 0
453 Status
= TisPcWaitRegisterBits (
454 INFINEON_TPM_STS_0_ADDRESS_DEFAULT
,
455 (UINT8
) TIS_PC_VALID
,
459 if (EFI_ERROR (Status
)) {
466 TpmWriteByte (INFINEON_TPM_STS_0_ADDRESS_DEFAULT
, TIS_PC_STS_GO
);
469 if (EFI_ERROR (Status
)) {
471 // Ensure the TPM state change from "Reception" to "Idle/Ready"
473 TpmWriteByte (INFINEON_TPM_STS_0_ADDRESS_DEFAULT
, TIS_PC_STS_READY
);
480 Receive response data of last command from TPM.
482 @param[out] TpmBuffer Buffer for response data.
483 @param[out] RespSize Response data length.
485 @retval EFI_SUCCESS Operation completed successfully.
486 @retval EFI_TIMEOUT The register can't run into the expected status in time.
487 @retval EFI_DEVICE_ERROR Unexpected device status.
488 @retval EFI_BUFFER_TOO_SMALL Response data is too long.
493 OUT UINT8
*TpmBuffer
,
501 TPM_RSP_COMMAND_HDR
*ResponseHeader
;
504 // Wait for the command completion
506 Status
= TisPcWaitRegisterBits (
507 INFINEON_TPM_STS_0_ADDRESS_DEFAULT
,
508 (UINT8
) (TIS_PC_VALID
| TIS_PC_STS_DATA
),
512 if (EFI_ERROR (Status
)) {
513 Status
= EFI_TIMEOUT
;
517 // Read the response data header and check it
521 while (Index
< sizeof (TPM_RSP_COMMAND_HDR
)) {
522 Status
= TisPcReadBurstCount (&BurstCount
);
523 if (EFI_ERROR (Status
)) {
524 Status
= EFI_TIMEOUT
;
527 for (; BurstCount
> 0 ; BurstCount
--) {
528 *(TpmBuffer
+ Index
) = TpmReadByte (INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT
);
530 if (Index
== sizeof (TPM_RSP_COMMAND_HDR
))
536 // Check the response data header (tag, parasize and returncode)
538 ResponseHeader
= (TPM_RSP_COMMAND_HDR
*)TpmBuffer
;
539 if (SwapBytes16 (ReadUnaligned16 (&ResponseHeader
->tag
)) != TPM_TAG_RSP_COMMAND
) {
540 Status
= EFI_DEVICE_ERROR
;
544 ResponseSize
= SwapBytes32 (ReadUnaligned32 (&ResponseHeader
->paramSize
));
545 if (ResponseSize
== sizeof (TPM_RSP_COMMAND_HDR
)) {
546 Status
= EFI_SUCCESS
;
549 if (ResponseSize
< sizeof (TPM_RSP_COMMAND_HDR
)) {
550 Status
= EFI_DEVICE_ERROR
;
553 if (*RespSize
< ResponseSize
) {
554 Status
= EFI_BUFFER_TOO_SMALL
;
557 *RespSize
= ResponseSize
;
560 // Continue reading the remaining data
562 while (Index
< ResponseSize
) {
563 for (; BurstCount
> 0 ; BurstCount
--) {
564 *(TpmBuffer
+ Index
) = TpmReadByte (INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT
);
566 if (Index
== ResponseSize
) {
567 Status
= EFI_SUCCESS
;
571 Status
= TisPcReadBurstCount (&BurstCount
);
572 if (EFI_ERROR (Status
) && (Index
< ResponseSize
)) {
573 Status
= EFI_DEVICE_ERROR
;
580 // Ensure the TPM state change from "Execution" or "Completion" to "Idle/Ready"
582 TpmWriteByte (INFINEON_TPM_STS_0_ADDRESS_DEFAULT
, TIS_PC_STS_READY
);
588 This service enables the sending of commands to the TPM12.
590 @param[in] InputParameterBlockSize Size of the TPM12 input parameter block.
591 @param[in] InputParameterBlock Pointer to the TPM12 input parameter block.
592 @param[in,out] OutputParameterBlockSize Size of the TPM12 output parameter block.
593 @param[in] OutputParameterBlock Pointer to the TPM12 output parameter block.
595 @retval EFI_SUCCESS The command byte stream was successfully sent to
596 the device and a response was successfully received.
597 @retval EFI_DEVICE_ERROR The command was not successfully sent to the
598 device or a response was not successfully received
600 @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small.
605 IN UINT32 InputParameterBlockSize
,
606 IN UINT8
*InputParameterBlock
,
607 IN OUT UINT32
*OutputParameterBlockSize
,
608 IN UINT8
*OutputParameterBlock
613 Status
= TisPcSend (InputParameterBlock
, InputParameterBlockSize
);
614 if (!EFI_ERROR (Status
)) {
615 Status
= TisPcReceive (OutputParameterBlock
, OutputParameterBlockSize
);