xref: /rk3399_ARM-atf/drivers/tpm/tpm2_fifo.c (revision 07282860f491eaa95bf7d29790bfdd906c6018d0)
1 /*
2  * Copyright (c) 2025, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <lib/libc/endian.h>
7 
8 #include <drivers/delay_timer.h>
9 #include <drivers/tpm/tpm2.h>
10 #include <drivers/tpm/tpm2_chip.h>
11 #include <drivers/tpm/tpm2_interface.h>
12 
13 #define LOCALITY_START_ADDRESS(x, y) \
14 	((uint16_t)(x->address + (0x1000 * y)))
15 
tpm2_get_info(struct tpm_chip_data * chip_data,uint8_t locality)16 static int tpm2_get_info(struct tpm_chip_data *chip_data, uint8_t locality)
17 {
18 	uint16_t tpm_base_addr = LOCALITY_START_ADDRESS(chip_data, locality);
19 	uint32_t vid_did;
20 	uint8_t revision;
21 	int err;
22 
23 	err = tpm2_fifo_read_chunk(tpm_base_addr + TPM_FIFO_REG_VENDID, DWORD, &vid_did);
24 	if (err < 0) {
25 		return err;
26 	}
27 
28 	err = tpm2_fifo_read_byte(tpm_base_addr + TPM_FIFO_REG_REVID, &revision);
29 	if (err < 0) {
30 		return err;
31 	}
32 
33 	INFO("TPM Chip: vendor-id 0x%x, device-id 0x%x, revision-id: 0x%x\n",
34 		0xFFFF & vid_did, vid_did >> 16, revision);
35 
36 	return TPM_SUCCESS;
37 }
38 
tpm2_wait_reg_bits(uint16_t reg,uint8_t set,unsigned long timeout,uint8_t * status)39 static int tpm2_wait_reg_bits(uint16_t reg, uint8_t set, unsigned long timeout, uint8_t *status)
40 {
41 	int err;
42 	uint64_t timeout_delay = timeout_init_us(timeout * 1000);
43 
44 	do {
45 		err = tpm2_fifo_read_byte(reg, status);
46 		if (err < 0) {
47 			return err;
48 		}
49 		if ((*status & set) == set) {
50 			return TPM_SUCCESS;
51 		}
52 	} while (!timeout_elapsed(timeout_delay));
53 
54 	return TPM_ERR_TIMEOUT;
55 }
56 
tpm2_fifo_request_access(struct tpm_chip_data * chip_data,uint8_t locality)57 static int tpm2_fifo_request_access(struct tpm_chip_data *chip_data, uint8_t locality)
58 {
59 	uint16_t tpm_base_addr = LOCALITY_START_ADDRESS(chip_data, locality);
60 	uint8_t status;
61 	int err;
62 
63 	err = tpm2_fifo_write_byte(tpm_base_addr + TPM_FIFO_REG_ACCESS, TPM_ACCESS_REQUEST_USE);
64 	if (err < 0) {
65 		return err;
66 	}
67 
68 	err = tpm2_wait_reg_bits(tpm_base_addr + TPM_FIFO_REG_ACCESS,
69 				TPM_ACCESS_ACTIVE_LOCALITY,
70 				chip_data->timeout_msec_a, &status);
71 	if (err == 0) {
72 		chip_data->locality = locality;
73 		return TPM_SUCCESS;
74 	}
75 
76 	return err;
77 }
78 
tpm2_fifo_release_locality(struct tpm_chip_data * chip_data,uint8_t locality)79 static int tpm2_fifo_release_locality(struct tpm_chip_data *chip_data, uint8_t locality)
80 {
81 	uint16_t tpm_base_addr = LOCALITY_START_ADDRESS(chip_data, locality);
82 	uint8_t buf;
83 	int err;
84 
85 	err = tpm2_fifo_read_byte(tpm_base_addr + TPM_FIFO_REG_ACCESS, &buf);
86 	if (err < 0) {
87 		return err;
88 	}
89 
90 	if (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) {
91 		return tpm2_fifo_write_byte(tpm_base_addr + TPM_FIFO_REG_ACCESS,
92 				TPM_ACCESS_RELINQUISH_LOCALITY);
93 	}
94 
95 	ERROR("%s: Unable to release locality\n", __func__);
96 	return TPM_ERR_RESPONSE;
97 }
98 
tpm2_fifo_prepare(struct tpm_chip_data * chip_data)99 static int tpm2_fifo_prepare(struct tpm_chip_data *chip_data)
100 {
101 	uint16_t tpm_base_addr = LOCALITY_START_ADDRESS(chip_data, chip_data->locality);
102 	uint8_t status;
103 	int err;
104 
105 	err = tpm2_fifo_write_byte(tpm_base_addr + TPM_FIFO_REG_STATUS, TPM_STAT_COMMAND_READY);
106 	if (err < 0) {
107 		return err;
108 	}
109 
110 	err = tpm2_wait_reg_bits(tpm_base_addr + TPM_FIFO_REG_STATUS,
111 				TPM_STAT_COMMAND_READY,
112 				chip_data->timeout_msec_b, &status);
113 	if (err < 0) {
114 		ERROR("%s: TPM Status Busy\n", __func__);
115 		return err;
116 	}
117 
118 	return TPM_SUCCESS;
119 }
120 
tpm2_fifo_get_burstcount(struct tpm_chip_data * chip_data,uint16_t * burstcount)121 static int tpm2_fifo_get_burstcount(struct tpm_chip_data *chip_data, uint16_t *burstcount)
122 {
123 	uint16_t tpm_base_addr = LOCALITY_START_ADDRESS(chip_data, chip_data->locality);
124 	uint64_t timeout_delay = timeout_init_us(chip_data->timeout_msec_a * 1000);
125 	int err;
126 
127 	if (burstcount == NULL) {
128 		return TPM_INVALID_PARAM;
129 	}
130 
131 	do {
132 		uint8_t byte0, byte1;
133 
134 		err = tpm2_fifo_read_byte(tpm_base_addr + TPM_FIFO_REG_BURST_COUNT_LO, &byte0);
135 		if (err < 0) {
136 			return err;
137 		}
138 
139 		err = tpm2_fifo_read_byte(tpm_base_addr + TPM_FIFO_REG_BURST_COUNT_HI, &byte1);
140 		if (err < 0) {
141 			return err;
142 		}
143 
144 		*burstcount = (uint16_t)((byte1 << 8) + byte0);
145 		if (*burstcount != 0U) {
146 			return TPM_SUCCESS;
147 		}
148 	} while (!timeout_elapsed(timeout_delay));
149 
150 	return TPM_ERR_TIMEOUT;
151 }
152 
tpm2_fifo_send(struct tpm_chip_data * chip_data,const tpm_cmd * buf)153 static int tpm2_fifo_send(struct tpm_chip_data *chip_data, const tpm_cmd *buf)
154 {
155 	uint16_t tpm_base_addr = LOCALITY_START_ADDRESS(chip_data, chip_data->locality);
156 	uint8_t status;
157 	uint16_t burstcnt;
158 	int err;
159 	uint32_t len, index;
160 
161 	if (sizeof(buf->header) != TPM_HEADER_SIZE) {
162 		ERROR("%s: invalid command header size.\n", __func__);
163 		return TPM_INVALID_PARAM;
164 	}
165 
166 	err = tpm2_fifo_read_byte(tpm_base_addr + TPM_FIFO_REG_STATUS, &status);
167 	if (err < 0) {
168 		return err;
169 	}
170 
171 	if (!(status & TPM_STAT_COMMAND_READY)) {
172 		err = tpm2_fifo_prepare(chip_data);
173 		if (err < 0) {
174 			return err;
175 		}
176 	}
177 
178 	/* write the command header to the TPM first */
179 	const uint8_t *header_data = (const uint8_t *)&buf->header;
180 
181 	for (index = 0; index < TPM_HEADER_SIZE; index++) {
182 		err = tpm2_fifo_write_byte(tpm_base_addr + TPM_FIFO_REG_DATA_FIFO,
183 				header_data[index]);
184 		if (err < 0) {
185 			return err;
186 		}
187 	}
188 
189 	len =  be32toh(buf->header.cmd_size);
190 
191 	while (index < len) {
192 		err = tpm2_fifo_get_burstcount(chip_data, &burstcnt);
193 		if (err < 0) {
194 			return err;
195 		}
196 
197 		for (; burstcnt > 0U && index < len; burstcnt--) {
198 			err = tpm2_fifo_write_byte(tpm_base_addr + TPM_FIFO_REG_DATA_FIFO,
199 					buf->data[index - TPM_HEADER_SIZE]);
200 			if (err < 0) {
201 				return err;
202 			}
203 			index++;
204 		}
205 	}
206 
207 	err = tpm2_wait_reg_bits(tpm_base_addr + TPM_FIFO_REG_STATUS,
208 				TPM_STAT_VALID,
209 				chip_data->timeout_msec_c,
210 				&status);
211 	if (err < 0) {
212 		return err;
213 	}
214 
215 	if (status & TPM_STAT_EXPECT) {
216 		ERROR("%s: TPM is still expecting data after command buffer is sent\n", __func__);
217 		return TPM_ERR_TRANSFER;
218 	}
219 
220 	err = tpm2_fifo_write_byte(tpm_base_addr + TPM_FIFO_REG_STATUS, TPM_STAT_GO);
221 	if (err < 0) {
222 		return err;
223 	}
224 
225 	return TPM_SUCCESS;
226 }
227 
tpm2_fifo_read_data(struct tpm_chip_data * chip_data,tpm_cmd * buf,uint16_t tpm_base_addr,uint8_t * status,int * size,int bytes_expected)228 static int tpm2_fifo_read_data(struct tpm_chip_data *chip_data, tpm_cmd *buf,
229 			uint16_t tpm_base_addr, uint8_t *status, int *size, int bytes_expected)
230 {
231 	int err, read_size, loop_index;
232 	uint16_t burstcnt;
233 	uint8_t *read_data;
234 
235 	if (bytes_expected == TPM_READ_HEADER) {
236 		/* read the response header from the TPM first */
237 		read_data = (uint8_t *)&buf->header;
238 		read_size = TPM_HEADER_SIZE;
239 		loop_index = *size;
240 	} else {
241 		/* process the rest of the mssg with bytes_expected */
242 		read_data = buf->data;
243 		read_size = bytes_expected;
244 		loop_index = *size - TPM_HEADER_SIZE;
245 	}
246 
247 	err = tpm2_wait_reg_bits(tpm_base_addr + TPM_FIFO_REG_STATUS,
248 				TPM_STAT_AVAIL,
249 				chip_data->timeout_msec_a,
250 				status);
251 	if (err < 0) {
252 		return err;
253 	}
254 
255 	while (*size < read_size) {
256 		err = tpm2_fifo_get_burstcount(chip_data, &burstcnt);
257 		if (err < 0) {
258 			ERROR("%s: TPM burst count error\n", __func__);
259 			return err;
260 		}
261 
262 		for (; burstcnt > 0U && loop_index < read_size;
263 		    burstcnt--, loop_index++, (*size)++) {
264 			err = tpm2_fifo_read_byte(
265 				tpm_base_addr + TPM_FIFO_REG_DATA_FIFO,
266 				(void *)&read_data[loop_index]);
267 			if (err < 0) {
268 				return err;
269 			}
270 		}
271 	}
272 
273 	return TPM_SUCCESS;
274 }
275 
tpm2_fifo_receive(struct tpm_chip_data * chip_data,tpm_cmd * buf)276 static int tpm2_fifo_receive(struct tpm_chip_data *chip_data, tpm_cmd *buf)
277 {
278 	uint16_t tpm_base_addr = LOCALITY_START_ADDRESS(chip_data, chip_data->locality);
279 	int size = 0, bytes_expected, err;
280 	uint8_t status;
281 
282 	err = tpm2_fifo_read_data(chip_data, buf, tpm_base_addr, &status, &size, TPM_READ_HEADER);
283 	if (err < 0) {
284 		return err;
285 	}
286 
287 	bytes_expected = be32toh(buf->header.cmd_size);
288 	if (bytes_expected > sizeof(*buf)) {
289 		ERROR("%s: tpm response buffer cannot store expected response\n", __func__);
290 		return TPM_INVALID_PARAM;
291 	}
292 
293 	if (size == bytes_expected) {
294 		return size;
295 	}
296 
297 	err = tpm2_fifo_read_data(chip_data, buf, tpm_base_addr, &status, &size, bytes_expected);
298 	if (err < 0) {
299 		return err;
300 	}
301 
302 	if (size < bytes_expected) {
303 		ERROR("%s: response buffer size is less than expected\n", __func__);
304 		return TPM_ERR_RESPONSE;
305 	}
306 
307 	return TPM_SUCCESS;
308 }
309 
310 static interface_ops_t fifo_ops = {
311 	.get_info = tpm2_get_info,
312 	.send = tpm2_fifo_send,
313 	.receive = tpm2_fifo_receive,
314 	.request_access = tpm2_fifo_request_access,
315 	.release_locality = tpm2_fifo_release_locality,
316 };
317 
318 struct interface_ops *
tpm_interface_getops(struct tpm_chip_data * chip_data,uint8_t locality)319 tpm_interface_getops(struct tpm_chip_data *chip_data,  uint8_t locality)
320 {
321 	return &fifo_ops;
322 }
323