2 TIS (TPM Interface Specification) functions used by TPM Dxe driver.
4 Copyright (c) 2005 - 2010, 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.
15 #include <IndustryStandard/Tpm12.h>
16 #include <Library/TimerLib.h>
17 #include <Library/TpmCommLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/IoLib.h>
20 #include <Library/BaseLib.h>
21 #include <Library/BaseMemoryLib.h>
23 STATIC UINT8 TpmCommandBuf
[TPMCMDBUFLENGTH
];
26 Send command to TPM for execution.
28 @param[in] TisReg TPM register space base address.
29 @param[in] TpmBuffer Buffer for TPM command data.
30 @param[in] DataLength TPM command data length.
32 @retval EFI_SUCCESS Operation completed successfully.
33 @retval EFI_TIMEOUT The register can't run into the expected status in time.
38 IN TIS_PC_REGISTERS_PTR TisReg
,
47 Status
= TisPcPrepareCommand (TisReg
);
48 if (EFI_ERROR (Status
)){
49 DEBUG ((DEBUG_ERROR
, "The Tpm not ready!\n"));
53 while (Index
< DataLength
) {
54 Status
= TisPcReadBurstCount (TisReg
, &BurstCount
);
55 if (EFI_ERROR (Status
)) {
58 for (; BurstCount
> 0 && Index
< DataLength
; BurstCount
--) {
59 MmioWrite8 ((UINTN
) &TisReg
->DataFifo
, *(TpmBuffer
+ Index
));
64 // Ensure the Tpm status STS_EXPECT change from 1 to 0
66 Status
= TisPcWaitRegisterBits (
76 Receive response data of last command from TPM.
78 @param[in] TisReg TPM register space base address.
79 @param[out] TpmBuffer Buffer for response data.
80 @param[out] RespSize Response data length.
82 @retval EFI_SUCCESS Operation completed successfully.
83 @retval EFI_TIMEOUT The register can't run into the expected status in time.
84 @retval EFI_DEVICE_ERROR Unexpected device status.
85 @retval EFI_BUFFER_TOO_SMALL Response data is too long.
90 IN TIS_PC_REGISTERS_PTR TisReg
,
102 // Wait for the command completion
104 Status
= TisPcWaitRegisterBits (
106 (UINT8
) (TIS_PC_VALID
| TIS_PC_STS_DATA
),
110 if (EFI_ERROR (Status
)) {
114 // Read the response data header and check it
118 while (Index
< sizeof (TPM_RSP_COMMAND_HDR
)) {
119 Status
= TisPcReadBurstCount (TisReg
, &BurstCount
);
120 if (EFI_ERROR (Status
)) {
123 for (; BurstCount
> 0 ; BurstCount
--) {
124 *(TpmBuffer
+ Index
) = MmioRead8 ((UINTN
) &TisReg
->DataFifo
);
126 if (Index
== sizeof (TPM_RSP_COMMAND_HDR
))
131 // Check the reponse data header (tag,parasize and returncode )
133 CopyMem (&Data32
, (TpmBuffer
+ 2), sizeof (UINT32
));
134 ResponseSize
= SwapBytes32 (Data32
);
135 *RespSize
= ResponseSize
;
136 if (ResponseSize
== sizeof (TPM_RSP_COMMAND_HDR
)) {
139 if (ResponseSize
< sizeof (TPM_RSP_COMMAND_HDR
)) {
140 return EFI_DEVICE_ERROR
;
142 if (ResponseSize
> TPMCMDBUFLENGTH
) {
143 return EFI_BUFFER_TOO_SMALL
;
146 // Continue reading the remaining data
148 while (Index
< ResponseSize
) {
149 for (; BurstCount
> 0 ; BurstCount
--) {
150 *(TpmBuffer
+ Index
) = MmioRead8 ((UINTN
) &TisReg
->DataFifo
);
152 if (Index
== ResponseSize
) {
156 Status
= TisPcReadBurstCount (TisReg
, &BurstCount
);
157 if (EFI_ERROR (Status
) && (Index
< ResponseSize
)) {
158 return EFI_DEVICE_ERROR
;
165 Format TPM command data according to the format control character.
167 @param[in] FmtChar Format control character.
168 @param[in, out] ap List of arguments.
169 @param[in] TpmBuffer Buffer for TPM command data.
170 @param[out] DataLength TPM command data length.
172 @retval EFI_SUCCESS Operation completed successfully.
173 @retval EFI_INVALID_PARAMETER Invalid format control character.
174 @retval EFI_BUFFER_TOO_SMALL Buffer too small for command data.
188 TPM_RQU_COMMAND_HDR TpmCmdHdr
;
189 TPM_RQU_COMMAND_HDR
*TpmCmdPtr
;
196 DataByte
= VA_ARG (*ap
, UINT8
);
198 Size
= sizeof (DataByte
);
202 DataWord
= VA_ARG (*ap
, UINT16
);
203 DataWord
= SwapBytes16 (DataWord
);
204 Raw
= (UINT8
*)&DataWord
;
205 Size
= sizeof (DataWord
);
209 DataDword
= VA_ARG (*ap
, UINT32
);
210 DataDword
= SwapBytes32 (DataDword
);
211 Raw
= (UINT8
*)&DataDword
;
212 Size
= sizeof (DataDword
);
216 TpmCmdPtr
= VA_ARG (*ap
, TPM_RQU_COMMAND_HDR
*);
217 TpmCmdHdr
.tag
= SwapBytes16 (TpmCmdPtr
->tag
);
218 TpmCmdHdr
.paramSize
= SwapBytes32 (TpmCmdPtr
->paramSize
);
219 TpmCmdHdr
.ordinal
= SwapBytes32 (TpmCmdPtr
->ordinal
);
220 Raw
= (UINT8
*) &TpmCmdHdr
;
221 Size
= sizeof (TpmCmdHdr
);
225 Raw
= VA_ARG (*ap
, UINT8
*);
226 Size
= VA_ARG (*ap
, UINTN
);
230 return EFI_INVALID_PARAMETER
;
233 return EFI_INVALID_PARAMETER
;
236 if(*DataLength
+ (UINT32
) Size
> TPMCMDBUFLENGTH
) {
237 return EFI_BUFFER_TOO_SMALL
;
239 CopyMem (TpmBuffer
+ *DataLength
, Raw
, Size
);
240 *DataLength
+= (UINT32
) Size
;
245 Format reponse data according to the format control character.
247 @param[in] FmtChar Format control character.
248 @param[in, out] ap List of arguments.
249 @param[out] TpmBuffer Buffer for reponse data.
250 @param[in, out] DataIndex Data offset in reponse data buffer.
251 @param[in] RespSize Response data length.
252 @param[out] DataFinished Reach the end of Response data.
254 @retval EFI_SUCCESS Operation completed successfully.
255 @retval EFI_INVALID_PARAMETER Invalid format control character.
256 @retval EFI_BUFFER_TOO_SMALL Buffer too small for command data.
263 OUT UINT8
*TpmBuffer
,
264 IN OUT UINT32
*DataIndex
,
266 OUT BOOLEAN
*DataFinished
270 TPM_RSP_COMMAND_HDR
*TpmRspPtr
;
273 Raw
= VA_ARG (*ap
, UINT8
*);
277 Size
= sizeof (UINT8
);
281 Size
= sizeof (UINT16
);
285 Size
= sizeof (UINT32
);
289 Size
= sizeof (*TpmRspPtr
);
293 Size
= VA_ARG (*ap
, UINTN
);
294 if(*DataIndex
+ (UINT32
) Size
<= RespSize
) {
297 *DataFinished
= TRUE
;
298 if (*DataIndex
>= RespSize
) {
301 CopyMem (Raw
, TpmBuffer
+ *DataIndex
, RespSize
- *DataIndex
);
302 *DataIndex
+= RespSize
- *DataIndex
;
306 return EFI_INVALID_PARAMETER
;
309 return EFI_WARN_UNKNOWN_GLYPH
;
312 if(*DataIndex
+ (UINT32
) Size
> RespSize
) {
313 *DataFinished
= TRUE
;
317 if( *DataIndex
+ (UINT32
) Size
> TPMCMDBUFLENGTH
)
318 return EFI_BUFFER_TOO_SMALL
;
320 CopyMem (Raw
, TpmBuffer
+ *DataIndex
, Size
);
321 *DataIndex
+= (UINT32
) Size
;
326 *(UINT16
*)Raw
= SwapBytes16 (*(UINT16
*) Raw
);
330 *(UINT32
*)Raw
= SwapBytes32 (*(UINT32
*) Raw
);
334 TpmRspPtr
= (TPM_RSP_COMMAND_HDR
*) Raw
;
335 TpmRspPtr
->tag
= SwapBytes16 (TpmRspPtr
->tag
);
336 TpmRspPtr
->paramSize
= SwapBytes32 (TpmRspPtr
->paramSize
);
337 TpmRspPtr
->returnCode
= SwapBytes32 (TpmRspPtr
->returnCode
);
344 Send formatted command to TPM for execution and return formatted data from response.
346 @param[in] TisReg TPM Handle.
347 @param[in] Fmt Format control string.
348 @param[in] ... The variable argument list.
350 @retval EFI_SUCCESS Operation completed successfully.
351 @retval EFI_TIMEOUT The register can't run into the expected status in time.
357 IN TIS_TPM_HANDLE TisReg
,
366 BOOLEAN DataFinished
;
371 // Put the formatted command to the TpmCommandBuf
374 while (*Fmt
!= '\0') {
375 if (*Fmt
== '%') Fmt
++;
376 if (*Fmt
== '/') break;
377 Status
= TisPcSendV (*Fmt
, &Ap
, TpmCommandBuf
, &BufSize
);
378 if (EFI_ERROR( Status
)) {
384 // Send the command to TPM
386 Status
= TisPcSend (TisReg
, TpmCommandBuf
, BufSize
);
387 if (EFI_ERROR (Status
)) {
389 // Ensure the TPM state change from "Reception" to "Idle/Ready"
391 MmioWrite8 ((UINTN
) &(((TIS_PC_REGISTERS_PTR
) TisReg
)->Status
), TIS_PC_STS_READY
);
395 MmioWrite8 ((UINTN
) &(((TIS_PC_REGISTERS_PTR
) TisReg
)->Status
), TIS_PC_STS_GO
);
398 // Receive the response data from TPM
400 ZeroMem (TpmCommandBuf
, TPMCMDBUFLENGTH
);
401 Status
= TisPcReceive (TisReg
, TpmCommandBuf
, &ResponseSize
);
403 // Ensure the TPM state change from "Execution" or "Completion" to "Idle/Ready"
405 MmioWrite8 ((UINTN
) &(((TIS_PC_REGISTERS_PTR
) TisReg
)->Status
), TIS_PC_STS_READY
);
406 if (EFI_ERROR (Status
)) {
411 // Get the formatted data from the TpmCommandBuf.
414 DataFinished
= FALSE
;
415 while (*Fmt
!= '\0') {
419 Status
= TisPcReceiveV (*Fmt
, &Ap
, TpmCommandBuf
, &BufSize
, ResponseSize
, &DataFinished
);
420 if (EFI_ERROR (Status
)) {