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 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 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 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 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 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 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 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 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 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 * 319 tpm_interface_getops(struct tpm_chip_data *chip_data, uint8_t locality) 320 { 321 return &fifo_ops; 322 } 323