2 TIS (TPM Interface Specification) functions used by TPM1.2.
4 Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <IndustryStandard/Tpm12.h>
12 #include <Library/BaseLib.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/IoLib.h>
15 #include <Library/TimerLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/Tpm12CommandLib.h>
18 #include <Library/PcdLib.h>
20 #include <IndustryStandard/TpmPtp.h>
21 #include <IndustryStandard/TpmTis.h>
31 // Max TPM command/response length
33 #define TPMCMDBUFLENGTH 1024
36 Check whether TPM chip exist.
38 @param[in] TisReg Pointer to TIS register.
40 @retval TRUE TPM chip exists.
41 @retval FALSE TPM chip is not found.
44 Tpm12TisPcPresenceCheck (
45 IN TIS_PC_REGISTERS_PTR TisReg
50 RegRead
= MmioRead8 ((UINTN
)&TisReg
->Access
);
51 return (BOOLEAN
)(RegRead
!= (UINT8
)-1);
55 Return PTP interface type.
57 @param[in] Register Pointer to PTP register.
59 @return PTP interface type.
62 Tpm12GetPtpInterface (
66 PTP_CRB_INTERFACE_IDENTIFIER InterfaceId
;
67 PTP_FIFO_INTERFACE_CAPABILITY InterfaceCapability
;
69 if (!Tpm12TisPcPresenceCheck (Register
)) {
70 return PtpInterfaceMax
;
75 InterfaceId
.Uint32
= MmioRead32 ((UINTN
)&((PTP_CRB_REGISTERS
*)Register
)->InterfaceId
);
76 InterfaceCapability
.Uint32
= MmioRead32 ((UINTN
)&((PTP_FIFO_REGISTERS
*)Register
)->InterfaceCapability
);
78 if ((InterfaceId
.Bits
.InterfaceType
== PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_CRB
) &&
79 (InterfaceId
.Bits
.InterfaceVersion
== PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_CRB
) &&
80 (InterfaceId
.Bits
.CapCRB
!= 0)) {
81 return PtpInterfaceCrb
;
83 if ((InterfaceId
.Bits
.InterfaceType
== PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_FIFO
) &&
84 (InterfaceId
.Bits
.InterfaceVersion
== PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_FIFO
) &&
85 (InterfaceId
.Bits
.CapFIFO
!= 0) &&
86 (InterfaceCapability
.Bits
.InterfaceVersion
== INTERFACE_CAPABILITY_INTERFACE_VERSION_PTP
)) {
87 return PtpInterfaceFifo
;
89 return PtpInterfaceTis
;
93 Check whether the value of a TPM chip register satisfies the input BIT setting.
95 @param[in] Register Address port of register to be checked.
96 @param[in] BitSet Check these data bits are set.
97 @param[in] BitClear Check these data bits are clear.
98 @param[in] TimeOut The max wait time (unit MicroSecond) when checking register.
100 @retval EFI_SUCCESS The register satisfies the check bit.
101 @retval EFI_TIMEOUT The register can't run into the expected status in time.
104 Tpm12TisPcWaitRegisterBits (
114 for (WaitTime
= 0; WaitTime
< TimeOut
; WaitTime
+= 30){
115 RegRead
= MmioRead8 ((UINTN
)Register
);
116 if ((RegRead
& BitSet
) == BitSet
&& (RegRead
& BitClear
) == 0)
118 MicroSecondDelay (30);
124 Get BurstCount by reading the burstCount field of a TIS register
125 in the time of default TIS_TIMEOUT_D.
127 @param[in] TisReg Pointer to TIS register.
128 @param[out] BurstCount Pointer to a buffer to store the got BurstCount.
130 @retval EFI_SUCCESS Get BurstCount.
131 @retval EFI_INVALID_PARAMETER TisReg is NULL or BurstCount is NULL.
132 @retval EFI_TIMEOUT BurstCount can't be got in time.
135 Tpm12TisPcReadBurstCount (
136 IN TIS_PC_REGISTERS_PTR TisReg
,
137 OUT UINT16
*BurstCount
144 if (BurstCount
== NULL
|| TisReg
== NULL
) {
145 return EFI_INVALID_PARAMETER
;
151 // TIS_PC_REGISTERS_PTR->burstCount is UINT16, but it is not 2bytes aligned,
152 // so it needs to use MmioRead8 to read two times
154 DataByte0
= MmioRead8 ((UINTN
)&TisReg
->BurstCount
);
155 DataByte1
= MmioRead8 ((UINTN
)&TisReg
->BurstCount
+ 1);
156 *BurstCount
= (UINT16
)((DataByte1
<< 8) + DataByte0
);
157 if (*BurstCount
!= 0) {
160 MicroSecondDelay (30);
162 } while (WaitTime
< TIS_TIMEOUT_D
);
168 Set TPM chip to ready state by sending ready command TIS_PC_STS_READY
169 to Status Register in time.
171 @param[in] TisReg Pointer to TIS register.
173 @retval EFI_SUCCESS TPM chip enters into ready state.
174 @retval EFI_INVALID_PARAMETER TisReg is NULL.
175 @retval EFI_TIMEOUT TPM chip can't be set to ready state in time.
178 Tpm12TisPcPrepareCommand (
179 IN TIS_PC_REGISTERS_PTR TisReg
184 if (TisReg
== NULL
) {
185 return EFI_INVALID_PARAMETER
;
188 MmioWrite8((UINTN
)&TisReg
->Status
, TIS_PC_STS_READY
);
189 Status
= Tpm12TisPcWaitRegisterBits (
199 Get the control of TPM chip by sending requestUse command TIS_PC_ACC_RQUUSE
200 to ACCESS Register in the time of default TIS_TIMEOUT_A.
202 @param[in] TisReg Pointer to TIS register.
204 @retval EFI_SUCCESS Get the control of TPM chip.
205 @retval EFI_INVALID_PARAMETER TisReg is NULL.
206 @retval EFI_NOT_FOUND TPM chip doesn't exit.
207 @retval EFI_TIMEOUT Can't get the TPM control in time.
210 Tpm12TisPcRequestUseTpm (
211 IN TIS_PC_REGISTERS_PTR TisReg
216 if (TisReg
== NULL
) {
217 return EFI_INVALID_PARAMETER
;
220 if (!Tpm12TisPcPresenceCheck (TisReg
)) {
221 return EFI_NOT_FOUND
;
224 MmioWrite8((UINTN
)&TisReg
->Access
, TIS_PC_ACC_RQUUSE
);
225 Status
= Tpm12TisPcWaitRegisterBits (
227 (UINT8
)(TIS_PC_ACC_ACTIVE
|TIS_PC_VALID
),
235 Send a command to TPM for execution and return response data.
237 @param[in] TisReg TPM register space base address.
238 @param[in] BufferIn Buffer for command data.
239 @param[in] SizeIn Size of command data.
240 @param[in, out] BufferOut Buffer for response data.
241 @param[in, out] SizeOut Size of response data.
243 @retval EFI_SUCCESS Operation completed successfully.
244 @retval EFI_BUFFER_TOO_SMALL Response data buffer is too small.
245 @retval EFI_DEVICE_ERROR Unexpected device behavior.
246 @retval EFI_UNSUPPORTED Unsupported TPM version
251 IN TIS_PC_REGISTERS_PTR TisReg
,
254 IN OUT UINT8
*BufferOut
,
255 IN OUT UINT32
*SizeOut
269 DEBUG ((EFI_D_VERBOSE
, "Tpm12TisTpmCommand Send - "));
270 if (SizeIn
> 0x100) {
275 for (Index
= 0; Index
< DebugSize
; Index
++) {
276 DEBUG ((EFI_D_VERBOSE
, "%02x ", BufferIn
[Index
]));
278 if (DebugSize
!= SizeIn
) {
279 DEBUG ((EFI_D_VERBOSE
, "...... "));
280 for (Index
= SizeIn
- 0x20; Index
< SizeIn
; Index
++) {
281 DEBUG ((EFI_D_VERBOSE
, "%02x ", BufferIn
[Index
]));
284 DEBUG ((EFI_D_VERBOSE
, "\n"));
288 Status
= Tpm12TisPcPrepareCommand (TisReg
);
289 if (EFI_ERROR (Status
)){
290 DEBUG ((DEBUG_ERROR
, "Tpm12 is not ready for command!\n"));
291 return EFI_DEVICE_ERROR
;
294 // Send the command data to Tpm
297 while (Index
< SizeIn
) {
298 Status
= Tpm12TisPcReadBurstCount (TisReg
, &BurstCount
);
299 if (EFI_ERROR (Status
)) {
300 Status
= EFI_DEVICE_ERROR
;
303 for (; BurstCount
> 0 && Index
< SizeIn
; BurstCount
--) {
304 MmioWrite8((UINTN
)&TisReg
->DataFifo
, *(BufferIn
+ Index
));
309 // Check the Tpm status STS_EXPECT change from 1 to 0
311 Status
= Tpm12TisPcWaitRegisterBits (
313 (UINT8
) TIS_PC_VALID
,
317 if (EFI_ERROR (Status
)) {
318 DEBUG ((DEBUG_ERROR
, "Tpm12 The send buffer too small!\n"));
319 Status
= EFI_BUFFER_TOO_SMALL
;
323 // Executed the TPM command and waiting for the response data ready
325 MmioWrite8((UINTN
)&TisReg
->Status
, TIS_PC_STS_GO
);
326 Status
= Tpm12TisPcWaitRegisterBits (
328 (UINT8
) (TIS_PC_VALID
| TIS_PC_STS_DATA
),
332 if (EFI_ERROR (Status
)) {
333 DEBUG ((DEBUG_ERROR
, "Wait for Tpm12 response data time out!!\n"));
334 Status
= EFI_DEVICE_ERROR
;
338 // Get response data header
342 while (Index
< sizeof (TPM_RSP_COMMAND_HDR
)) {
343 Status
= Tpm12TisPcReadBurstCount (TisReg
, &BurstCount
);
344 if (EFI_ERROR (Status
)) {
345 Status
= EFI_DEVICE_ERROR
;
348 for (; BurstCount
> 0; BurstCount
--) {
349 *(BufferOut
+ Index
) = MmioRead8 ((UINTN
)&TisReg
->DataFifo
);
351 if (Index
== sizeof (TPM_RSP_COMMAND_HDR
)) break;
355 DEBUG ((EFI_D_VERBOSE
, "Tpm12TisTpmCommand ReceiveHeader - "));
356 for (Index
= 0; Index
< sizeof (TPM_RSP_COMMAND_HDR
); Index
++) {
357 DEBUG ((EFI_D_VERBOSE
, "%02x ", BufferOut
[Index
]));
359 DEBUG ((EFI_D_VERBOSE
, "\n"));
362 // Check the response data header (tag, parasize and returncode)
364 CopyMem (&Data16
, BufferOut
, sizeof (UINT16
));
365 RspTag
= SwapBytes16 (Data16
);
366 if (RspTag
!= TPM_TAG_RSP_COMMAND
&& RspTag
!= TPM_TAG_RSP_AUTH1_COMMAND
&& RspTag
!= TPM_TAG_RSP_AUTH2_COMMAND
) {
367 DEBUG ((EFI_D_ERROR
, "TPM12: Response tag error - current tag value is %x\n", RspTag
));
368 Status
= EFI_UNSUPPORTED
;
372 CopyMem (&Data32
, (BufferOut
+ 2), sizeof (UINT32
));
373 TpmOutSize
= SwapBytes32 (Data32
);
374 if (*SizeOut
< TpmOutSize
) {
375 Status
= EFI_BUFFER_TOO_SMALL
;
378 *SizeOut
= TpmOutSize
;
380 // Continue reading the remaining data
382 while ( Index
< TpmOutSize
) {
383 for (; BurstCount
> 0; BurstCount
--) {
384 *(BufferOut
+ Index
) = MmioRead8 ((UINTN
)&TisReg
->DataFifo
);
386 if (Index
== TpmOutSize
) {
387 Status
= EFI_SUCCESS
;
391 Status
= Tpm12TisPcReadBurstCount (TisReg
, &BurstCount
);
392 if (EFI_ERROR (Status
)) {
393 Status
= EFI_DEVICE_ERROR
;
399 DEBUG ((EFI_D_VERBOSE
, "Tpm12TisTpmCommand Receive - "));
400 for (Index
= 0; Index
< TpmOutSize
; Index
++) {
401 DEBUG ((EFI_D_VERBOSE
, "%02x ", BufferOut
[Index
]));
403 DEBUG ((EFI_D_VERBOSE
, "\n"));
405 MmioWrite8((UINTN
)&TisReg
->Status
, TIS_PC_STS_READY
);
410 This service enables the sending of commands to the TPM12.
412 @param[in] InputParameterBlockSize Size of the TPM12 input parameter block.
413 @param[in] InputParameterBlock Pointer to the TPM12 input parameter block.
414 @param[in,out] OutputParameterBlockSize Size of the TPM12 output parameter block.
415 @param[in] OutputParameterBlock Pointer to the TPM12 output parameter block.
417 @retval EFI_SUCCESS The command byte stream was successfully sent to the device and a response was successfully received.
418 @retval EFI_DEVICE_ERROR The command was not successfully sent to the device or a response was not successfully received from the device.
419 @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small.
424 IN UINT32 InputParameterBlockSize
,
425 IN UINT8
*InputParameterBlock
,
426 IN OUT UINT32
*OutputParameterBlockSize
,
427 IN UINT8
*OutputParameterBlock
430 PTP_INTERFACE_TYPE PtpInterface
;
433 // Special handle for TPM1.2 to check PTP too, because PTP/TIS share same register address.
435 PtpInterface
= Tpm12GetPtpInterface ((VOID
*) (UINTN
) PcdGet64 (PcdTpmBaseAddress
));
436 switch (PtpInterface
) {
437 case PtpInterfaceFifo
:
438 case PtpInterfaceTis
:
439 return Tpm12TisTpmCommand (
440 (TIS_PC_REGISTERS_PTR
) (UINTN
) PcdGet64 (PcdTpmBaseAddress
),
442 InputParameterBlockSize
,
443 OutputParameterBlock
,
444 OutputParameterBlockSize
446 case PtpInterfaceCrb
:
448 // No need to support CRB because it is only accept TPM2 command.
451 return EFI_DEVICE_ERROR
;
457 Check whether the value of a TPM chip register satisfies the input BIT setting.
459 @param[in] Register Address port of register to be checked.
460 @param[in] BitSet Check these data bits are set.
461 @param[in] BitClear Check these data bits are clear.
462 @param[in] TimeOut The max wait time (unit MicroSecond) when checking register.
464 @retval EFI_SUCCESS The register satisfies the check bit.
465 @retval EFI_TIMEOUT The register can't run into the expected status in time.
468 Tpm12PtpCrbWaitRegisterBits (
478 for (WaitTime
= 0; WaitTime
< TimeOut
; WaitTime
+= 30){
479 RegRead
= MmioRead32 ((UINTN
)Register
);
480 if ((RegRead
& BitSet
) == BitSet
&& (RegRead
& BitClear
) == 0) {
483 MicroSecondDelay (30);
489 Get the control of TPM chip.
491 @param[in] CrbReg Pointer to CRB register.
493 @retval EFI_SUCCESS Get the control of TPM chip.
494 @retval EFI_INVALID_PARAMETER CrbReg is NULL.
495 @retval EFI_NOT_FOUND TPM chip doesn't exit.
496 @retval EFI_TIMEOUT Can't get the TPM control in time.
499 Tpm12PtpCrbRequestUseTpm (
500 IN PTP_CRB_REGISTERS_PTR CrbReg
505 MmioWrite32((UINTN
)&CrbReg
->LocalityControl
, PTP_CRB_LOCALITY_CONTROL_REQUEST_ACCESS
);
506 Status
= Tpm12PtpCrbWaitRegisterBits (
507 &CrbReg
->LocalityStatus
,
508 PTP_CRB_LOCALITY_STATUS_GRANTED
,
516 This service requests use TPM12.
518 @retval EFI_SUCCESS Get the control of TPM12 chip.
519 @retval EFI_NOT_FOUND TPM12 not found.
520 @retval EFI_DEVICE_ERROR Unexpected device behavior.
528 PTP_INTERFACE_TYPE PtpInterface
;
531 // Special handle for TPM1.2 to check PTP too, because PTP/TIS share same register address.
532 // Some other program might leverage this function to check the existence of TPM chip.
534 PtpInterface
= Tpm12GetPtpInterface ((VOID
*) (UINTN
) PcdGet64 (PcdTpmBaseAddress
));
535 switch (PtpInterface
) {
536 case PtpInterfaceCrb
:
537 return Tpm12PtpCrbRequestUseTpm ((PTP_CRB_REGISTERS_PTR
) (UINTN
) PcdGet64 (PcdTpmBaseAddress
));
538 case PtpInterfaceFifo
:
539 case PtpInterfaceTis
:
540 return Tpm12TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR
) (UINTN
) PcdGet64 (PcdTpmBaseAddress
));
542 return EFI_NOT_FOUND
;