blob: ea8cf3de70654123f337cc952571a1b73454a35f [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
22int tis_open(void)
23{
24 int rc;
25
Patrick Georgic9b13592019-11-29 11:47:47 +010026 if (chip.is_open) {
Elyes HAOUAS421285e2021-01-16 17:30:08 +010027 printk(BIOS_DEBUG, "%s() called twice.\n", __func__);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080028 return -1;
29 }
30
Patrick Georgic9b13592019-11-29 11:47:47 +010031 rc = tpm_vendor_init(&chip, CONFIG_DRIVER_TPM_I2C_BUS,
Duncan Laurie40ae1702016-08-31 13:51:14 -070032 CONFIG_DRIVER_TPM_I2C_ADDR);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080033 if (rc < 0)
Patrick Georgic9b13592019-11-29 11:47:47 +010034 chip.is_open = 0;
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080035
Lee Leahy52ab30b2017-03-15 09:22:11 -070036 if (rc)
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080037 return -1;
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080038
39 return 0;
40}
41
42int tis_close(void)
43{
Patrick Georgic9b13592019-11-29 11:47:47 +010044 if (chip.is_open) {
45 tpm_vendor_cleanup(&chip);
46 chip.is_open = 0;
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080047 }
48
49 return 0;
50}
51
52int tis_init(void)
53{
Duncan Laurie1ca19682016-09-07 10:52:12 -070054 return tpm_vendor_probe(CONFIG_DRIVER_TPM_I2C_BUS,
55 CONFIG_DRIVER_TPM_I2C_ADDR);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080056}
57
Aaron Durbin92190192017-03-27 16:20:17 -050058static ssize_t tpm_transmit(const uint8_t *sbuf, size_t sbufsiz, void *rbuf,
59 size_t rbufsiz)
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080060{
61 int rc;
Aaron Durbin9b878442017-03-27 16:40:03 -050062 uint32_t count;
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080063
Aaron Durbin92190192017-03-27 16:20:17 -050064 memcpy(&count, sbuf + TPM_CMD_COUNT_BYTE, sizeof(count));
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080065 count = be32_to_cpu(count);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080066
Patrick Georgic9b13592019-11-29 11:47:47 +010067 if (!chip.vendor.send || !chip.vendor.status || !chip.vendor.cancel)
Duncan Laurie112ab912016-09-02 14:45:53 -070068 return -1;
69
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080070 if (count == 0) {
Elyes HAOUAS421285e2021-01-16 17:30:08 +010071 printk(BIOS_DEBUG, "%s: no data\n", __func__);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080072 return -1;
73 }
Aaron Durbin92190192017-03-27 16:20:17 -050074 if (count > sbufsiz) {
Elyes HAOUAS421285e2021-01-16 17:30:08 +010075 printk(BIOS_DEBUG, "%s: invalid count value %x %zx\n", __func__,
Aaron Durbin92190192017-03-27 16:20:17 -050076 count, sbufsiz);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080077 return -1;
78 }
79
Patrick Georgic9b13592019-11-29 11:47:47 +010080 ASSERT(chip.vendor.send);
Elyes Haouas1ef547e2022-11-18 15:05:39 +010081 rc = chip.vendor.send(&chip, (uint8_t *)sbuf, count);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080082 if (rc < 0) {
Elyes HAOUAS421285e2021-01-16 17:30:08 +010083 printk(BIOS_DEBUG, "%s: tpm_send error\n", __func__);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080084 goto out;
85 }
86
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080087 int timeout = 2 * 60 * 1000; /* two minutes timeout */
88 while (timeout) {
Patrick Georgic9b13592019-11-29 11:47:47 +010089 ASSERT(chip.vendor.status);
90 uint8_t status = chip.vendor.status(&chip);
91 if ((status & chip.vendor.req_complete_mask) ==
92 chip.vendor.req_complete_val) {
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080093 goto out_recv;
94 }
95
Patrick Georgic9b13592019-11-29 11:47:47 +010096 if (status == chip.vendor.req_canceled) {
Lee Leahy52ab30b2017-03-15 09:22:11 -070097 printk(BIOS_DEBUG,
Elyes HAOUAS421285e2021-01-16 17:30:08 +010098 "%s: Operation Canceled\n", __func__);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080099 rc = -1;
100 goto out;
101 }
102 mdelay(TPM_TIMEOUT);
103 timeout--;
104 }
105
Patrick Georgic9b13592019-11-29 11:47:47 +0100106 ASSERT(chip.vendor.cancel);
107 chip.vendor.cancel(&chip);
Elyes HAOUAS421285e2021-01-16 17:30:08 +0100108 printk(BIOS_DEBUG, "%s: Operation Timed out\n", __func__);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800109 rc = -1; //ETIME;
110 goto out;
111
112out_recv:
113
Elyes Haouas1ef547e2022-11-18 15:05:39 +0100114 rc = chip.vendor.recv(&chip, (uint8_t *)rbuf, rbufsiz);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800115 if (rc < 0)
Elyes HAOUAS421285e2021-01-16 17:30:08 +0100116 printk(BIOS_DEBUG, "%s: tpm_recv: error %d\n", __func__, rc);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800117out:
118 return rc;
119}
120
121int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
122 uint8_t *recvbuf, size_t *rbuf_len)
123{
Lee Leahye0668e42017-01-08 11:38:14 -0800124 ASSERT(sbuf_size >= 10);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800125
Lee Leahye0668e42017-01-08 11:38:14 -0800126 /* Display the TPM command */
Julius Wernercd49cce2019-03-05 16:53:33 -0800127 if (CONFIG(DRIVER_TPM_DISPLAY_TIS_BYTES)) {
Lee Leahye0668e42017-01-08 11:38:14 -0800128 printk(BIOS_DEBUG, "TPM Command: 0x%08x\n",
129 read_at_be32(sendbuf, sizeof(uint16_t)
130 + sizeof(uint32_t)));
131 hexdump(sendbuf, sbuf_size);
132 }
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800133
Aaron Durbin92190192017-03-27 16:20:17 -0500134 int len = tpm_transmit(sendbuf, sbuf_size, recvbuf, *rbuf_len);
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800135
136 if (len < 10) {
137 *rbuf_len = 0;
138 return -1;
139 }
140
141 if (len > *rbuf_len) {
142 *rbuf_len = len;
143 return -1;
144 }
145
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800146 *rbuf_len = len;
147
Lee Leahye0668e42017-01-08 11:38:14 -0800148 /* Display the TPM response */
Julius Wernercd49cce2019-03-05 16:53:33 -0800149 if (CONFIG(DRIVER_TPM_DISPLAY_TIS_BYTES)) {
Lee Leahye0668e42017-01-08 11:38:14 -0800150 printk(BIOS_DEBUG, "TPM Response: 0x%08x\n",
151 read_at_be32(recvbuf, sizeof(uint16_t)
152 + sizeof(uint32_t)));
153 hexdump(recvbuf, *rbuf_len);
154 }
155
Stefan Reinauerd518c7a2013-11-04 17:38:32 -0800156 return 0;
157}