blob: e9bf2cf7062a3fc98286130e2ab6219f1edefb65 [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Stefan Reinauerd518c7a2013-11-04 17:38:32 -08002
3#include <stdint.h>
4#include <string.h>
5#include <assert.h>
Lee Leahye0668e42017-01-08 11:38:14 -08006#include <commonlib/endian.h>
Elyes HAOUASadd76f92019-03-21 09:55:49 +01007#include <console/console.h>
Stefan Reinauerd518c7a2013-11-04 17:38:32 -08008#include <delay.h>
Nico Huber0f2dd1e2017-08-01 14:02:40 +02009#include <device/i2c_simple.h>
Julius Werner9ff8f6f2015-02-23 14:31:09 -080010#include <endian.h>
Lee Leahye0668e42017-01-08 11:38:14 -080011#include <lib.h>
Philipp Deppenwiesed88fb362017-10-18 20:26:18 +020012#include <security/tpm/tis.h>
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080013
Elyes HAOUASadd76f92019-03-21 09:55:49 +010014#include "tpm.h"
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080015
16/* global structure for tpm chip data */
Patrick Georgic9b13592019-11-29 11:47:47 +010017static struct tpm_chip chip;
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080018
19#define TPM_CMD_COUNT_BYTE 2
20#define TPM_CMD_ORDINAL_BYTE 6
21
Sergii Dmytruk4ee03172022-12-22 19:35:25 +020022int tis_open(void)
23{
24 int rc;
25
26 if (chip.is_open) {
27 printk(BIOS_DEBUG, "%s() called twice.\n", __func__);
28 return -1;
29 }
30
31 rc = tpm_vendor_init(&chip, CONFIG_DRIVER_TPM_I2C_BUS,
32 CONFIG_DRIVER_TPM_I2C_ADDR);
33 if (rc < 0)
34 chip.is_open = 0;
35
36 if (rc)
37 return -1;
38
39 return 0;
40}
41
42int tis_init(void)
43{
44 return tpm_vendor_probe(CONFIG_DRIVER_TPM_I2C_BUS,
45 CONFIG_DRIVER_TPM_I2C_ADDR);
46}
47
Aaron Durbin92190192017-03-27 16:20:17 -050048static ssize_t tpm_transmit(const uint8_t *sbuf, size_t sbufsiz, void *rbuf,
49 size_t rbufsiz)
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080050{
51 int rc;
Aaron Durbin9b878442017-03-27 16:40:03 -050052 uint32_t count;
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080053
Aaron Durbin92190192017-03-27 16:20:17 -050054 memcpy(&count, sbuf + TPM_CMD_COUNT_BYTE, sizeof(count));
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080055 count = be32_to_cpu(count);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080056
Sergii Dmytruk86f845a2022-10-29 18:55:24 +030057 if (!chip.send || !chip.status || !chip.cancel)
Duncan Laurie112ab912016-09-02 14:45:53 -070058 return -1;
59
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080060 if (count == 0) {
Elyes HAOUAS421285e2021-01-16 17:30:08 +010061 printk(BIOS_DEBUG, "%s: no data\n", __func__);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080062 return -1;
63 }
Aaron Durbin92190192017-03-27 16:20:17 -050064 if (count > sbufsiz) {
Elyes HAOUAS421285e2021-01-16 17:30:08 +010065 printk(BIOS_DEBUG, "%s: invalid count value %x %zx\n", __func__,
Aaron Durbin92190192017-03-27 16:20:17 -050066 count, sbufsiz);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080067 return -1;
68 }
69
Sergii Dmytruk86f845a2022-10-29 18:55:24 +030070 ASSERT(chip.send);
71 rc = chip.send((uint8_t *)sbuf, count);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080072 if (rc < 0) {
Elyes HAOUAS421285e2021-01-16 17:30:08 +010073 printk(BIOS_DEBUG, "%s: tpm_send error\n", __func__);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080074 goto out;
75 }
76
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080077 int timeout = 2 * 60 * 1000; /* two minutes timeout */
78 while (timeout) {
Sergii Dmytruk86f845a2022-10-29 18:55:24 +030079 ASSERT(chip.status);
80 uint8_t status = chip.status();
81 if ((status & chip.req_complete_mask) == chip.req_complete_val) {
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080082 goto out_recv;
83 }
84
Sergii Dmytruk86f845a2022-10-29 18:55:24 +030085 if (status == chip.req_canceled) {
Lee Leahy52ab30b2017-03-15 09:22:11 -070086 printk(BIOS_DEBUG,
Elyes HAOUAS421285e2021-01-16 17:30:08 +010087 "%s: Operation Canceled\n", __func__);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080088 rc = -1;
89 goto out;
90 }
91 mdelay(TPM_TIMEOUT);
92 timeout--;
93 }
94
Sergii Dmytruk86f845a2022-10-29 18:55:24 +030095 ASSERT(chip.cancel);
96 chip.cancel();
Elyes HAOUAS421285e2021-01-16 17:30:08 +010097 printk(BIOS_DEBUG, "%s: Operation Timed out\n", __func__);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080098 rc = -1; //ETIME;
99 goto out;
100
101out_recv:
102
Sergii Dmytruk86f845a2022-10-29 18:55:24 +0300103 rc = chip.recv((uint8_t *)rbuf, rbufsiz);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800104 if (rc < 0)
Elyes HAOUAS421285e2021-01-16 17:30:08 +0100105 printk(BIOS_DEBUG, "%s: tpm_recv: error %d\n", __func__, rc);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800106out:
107 return rc;
108}
109
Sergii Dmytruk4ee03172022-12-22 19:35:25 +0200110int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
111 uint8_t *recvbuf, size_t *rbuf_len)
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800112{
Lee Leahye0668e42017-01-08 11:38:14 -0800113 ASSERT(sbuf_size >= 10);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800114
Lee Leahye0668e42017-01-08 11:38:14 -0800115 /* Display the TPM command */
Julius Wernercd49cce2019-03-05 16:53:33 -0800116 if (CONFIG(DRIVER_TPM_DISPLAY_TIS_BYTES)) {
Lee Leahye0668e42017-01-08 11:38:14 -0800117 printk(BIOS_DEBUG, "TPM Command: 0x%08x\n",
118 read_at_be32(sendbuf, sizeof(uint16_t)
119 + sizeof(uint32_t)));
120 hexdump(sendbuf, sbuf_size);
121 }
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800122
Aaron Durbin92190192017-03-27 16:20:17 -0500123 int len = tpm_transmit(sendbuf, sbuf_size, recvbuf, *rbuf_len);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800124
125 if (len < 10) {
126 *rbuf_len = 0;
127 return -1;
128 }
129
130 if (len > *rbuf_len) {
131 *rbuf_len = len;
132 return -1;
133 }
134
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800135 *rbuf_len = len;
136
Lee Leahye0668e42017-01-08 11:38:14 -0800137 /* Display the TPM response */
Julius Wernercd49cce2019-03-05 16:53:33 -0800138 if (CONFIG(DRIVER_TPM_DISPLAY_TIS_BYTES)) {
Lee Leahye0668e42017-01-08 11:38:14 -0800139 printk(BIOS_DEBUG, "TPM Response: 0x%08x\n",
140 read_at_be32(recvbuf, sizeof(uint16_t)
141 + sizeof(uint32_t)));
142 hexdump(recvbuf, *rbuf_len);
143 }
144
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800145 return 0;
146}