blob: 669ac68f6c8254233afd7a5cc0894e8f615a07e7 [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Lee Leahy1b39f172017-01-05 17:59:38 -08002
Lee Leahy1b39f172017-01-05 17:59:38 -08003#include <assert.h>
4#include <commonlib/endian.h>
Elyes HAOUAS361a9352019-12-18 21:26:33 +01005#include <commonlib/helpers.h>
Lee Leahy1b39f172017-01-05 17:59:38 -08006#include <console/console.h>
7#include <delay.h>
Nico Huber0f2dd1e2017-08-01 14:02:40 +02008#include <device/i2c_simple.h>
Lee Leahy1b39f172017-01-05 17:59:38 -08009#include <endian.h>
10#include <lib.h>
Philipp Deppenwiesed88fb362017-10-18 20:26:18 +020011#include <security/tpm/tis.h>
Lee Leahy1b39f172017-01-05 17:59:38 -080012#include <timer.h>
Elyes HAOUASede8dd02019-06-23 06:57:53 +020013#include <types.h>
Lee Leahy1b39f172017-01-05 17:59:38 -080014
15#define RECV_TIMEOUT (1 * 1000) /* 1 second */
16#define XMIT_TIMEOUT (1 * 1000) /* 1 second */
17#define SLEEP_DURATION 1000 /* microseconds */
18
19struct tpm_output_header {
20 uint16_t tag;
21 uint32_t length;
22 uint32_t return_code;
Stefan Reinauer6a001132017-07-13 02:20:27 +020023} __packed;
Lee Leahy1b39f172017-01-05 17:59:38 -080024
Sergii Dmytruk4ee03172022-12-22 19:35:25 +020025int tis_open(void)
26{
27 return 0;
28}
29
30int tis_init(void)
31{
32 return 0;
33}
34
35int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
36 uint8_t *recvbuf, size_t *rbuf_len)
Lee Leahy1b39f172017-01-05 17:59:38 -080037{
38 size_t hdr_bytes;
39 struct tpm_output_header *header;
40 size_t max_recv_bytes;
41 size_t recv_bytes;
42 int status;
43 struct stopwatch sw;
44
45 ASSERT(sbuf_size >= 10);
Julius Wernercd49cce2019-03-05 16:53:33 -080046 if (CONFIG(DRIVER_TPM_DISPLAY_TIS_BYTES)) {
Lee Leahy1b39f172017-01-05 17:59:38 -080047 /* Display the TPM command */
48 if (sbuf_size >= 10)
49 printk(BIOS_DEBUG, "TPM Command: 0x%08x\n",
50 read_at_be32(sendbuf, sizeof(uint16_t)
51 + sizeof(uint32_t)));
52 hexdump(sendbuf, sbuf_size);
53 }
54
55 /* Send the command to the TPM */
56 stopwatch_init_msecs_expire(&sw, XMIT_TIMEOUT);
57 while (1) {
58 status = i2c_write_raw(CONFIG_DRIVER_TPM_I2C_BUS,
59 CONFIG_DRIVER_TPM_I2C_ADDR, (uint8_t *)sendbuf,
60 sbuf_size);
61 if ((status < 0) && (!stopwatch_expired(&sw)))
62 continue;
63 if (status < 0)
64 return status;
65 break;
66 }
67
68 /* Read the TPM response header */
69 max_recv_bytes = *rbuf_len;
70 ASSERT(max_recv_bytes >= sizeof(*header));
71 hdr_bytes = sizeof(*header);
72 header = (struct tpm_output_header *)recvbuf;
73 stopwatch_init_msecs_expire(&sw, RECV_TIMEOUT);
74 do {
75 status = i2c_read_raw(CONFIG_DRIVER_TPM_I2C_BUS,
76 CONFIG_DRIVER_TPM_I2C_ADDR, recvbuf, hdr_bytes);
77 if (status > 0)
78 break;
79 udelay(SLEEP_DURATION);
80 } while (!stopwatch_expired(&sw));
81 if (status != sizeof(*header))
82 return -1;
83
84 /* Determine the number of bytes remaining */
Elyes HAOUAS361a9352019-12-18 21:26:33 +010085 recv_bytes = MIN(be32_to_cpu(*(uint32_t *)&header->length),
Lee Leahy1b39f172017-01-05 17:59:38 -080086 max_recv_bytes);
87
88 /* Determine if there is additional response data */
89 if (recv_bytes > hdr_bytes) {
90 /* Display the TPM response */
Julius Wernercd49cce2019-03-05 16:53:33 -080091 if (CONFIG(DRIVER_TPM_DISPLAY_TIS_BYTES))
Lee Leahy1b39f172017-01-05 17:59:38 -080092 hexdump(recvbuf, hdr_bytes);
93
94 /* Read the full TPM response */
95 status = i2c_read_raw(CONFIG_DRIVER_TPM_I2C_BUS,
96 CONFIG_DRIVER_TPM_I2C_ADDR, recvbuf, recv_bytes);
97 if (status < 0)
98 return status;
99 }
100
101 /* Return the number of bytes received */
102 *rbuf_len = status;
103
104 /* Display the TPM response */
Julius Wernercd49cce2019-03-05 16:53:33 -0800105 if (CONFIG(DRIVER_TPM_DISPLAY_TIS_BYTES)) {
Lee Leahy1b39f172017-01-05 17:59:38 -0800106 printk(BIOS_DEBUG, "TPM Response: 0x%08x\n",
107 read_at_be32(recvbuf, sizeof(uint16_t)
108 + sizeof(uint32_t)));
109 hexdump(recvbuf, *rbuf_len);
110 }
111
112 /* Successful transfer */
113 return 0;
114}