1 /* 2 * tpm_tis.c - QEMU's TPM TIS interface emulator 3 * 4 * Copyright (C) 2006,2010-2013 IBM Corporation 5 * 6 * Authors: 7 * Stefan Berger <stefanb@us.ibm.com> 8 * David Safford <safford@us.ibm.com> 9 * 10 * Xen 4 support: Andrease Niederl <andreas.niederl@iaik.tugraz.at> 11 * 12 * This work is licensed under the terms of the GNU GPL, version 2 or later. 13 * See the COPYING file in the top-level directory. 14 * 15 * Implementation of the TIS interface according to specs found at 16 * http://www.trustedcomputinggroup.org. This implementation currently 17 * supports version 1.3, 21 March 2013 18 * In the developers menu choose the PC Client section then find the TIS 19 * specification. 20 * 21 * TPM TIS for TPM 2 implementation following TCG PC Client Platform 22 * TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43 23 */ 24 25 #include "qemu/osdep.h" 26 #include "hw/irq.h" 27 #include "hw/isa/isa.h" 28 #include "qapi/error.h" 29 #include "qemu/module.h" 30 31 #include "hw/acpi/tpm.h" 32 #include "hw/pci/pci_ids.h" 33 #include "sysemu/tpm_backend.h" 34 #include "tpm_int.h" 35 #include "tpm_util.h" 36 #include "tpm_ppi.h" 37 #include "trace.h" 38 39 #define TPM_TIS_NUM_LOCALITIES 5 /* per spec */ 40 #define TPM_TIS_LOCALITY_SHIFT 12 41 #define TPM_TIS_NO_LOCALITY 0xff 42 43 #define TPM_TIS_IS_VALID_LOCTY(x) ((x) < TPM_TIS_NUM_LOCALITIES) 44 45 #define TPM_TIS_BUFFER_MAX 4096 46 47 typedef enum { 48 TPM_TIS_STATE_IDLE = 0, 49 TPM_TIS_STATE_READY, 50 TPM_TIS_STATE_COMPLETION, 51 TPM_TIS_STATE_EXECUTION, 52 TPM_TIS_STATE_RECEPTION, 53 } TPMTISState; 54 55 /* locality data -- all fields are persisted */ 56 typedef struct TPMLocality { 57 TPMTISState state; 58 uint8_t access; 59 uint32_t sts; 60 uint32_t iface_id; 61 uint32_t inte; 62 uint32_t ints; 63 } TPMLocality; 64 65 typedef struct TPMState { 66 ISADevice busdev; 67 MemoryRegion mmio; 68 69 unsigned char buffer[TPM_TIS_BUFFER_MAX]; 70 uint16_t rw_offset; 71 72 uint8_t active_locty; 73 uint8_t aborting_locty; 74 uint8_t next_locty; 75 76 TPMLocality loc[TPM_TIS_NUM_LOCALITIES]; 77 78 qemu_irq irq; 79 uint32_t irq_num; 80 81 TPMBackendCmd cmd; 82 83 TPMBackend *be_driver; 84 TPMVersion be_tpm_version; 85 86 size_t be_buffer_size; 87 88 bool ppi_enabled; 89 TPMPPI ppi; 90 } TPMState; 91 92 #define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS) 93 94 #define DEBUG_TIS 0 95 96 /* local prototypes */ 97 98 static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, 99 unsigned size); 100 101 /* utility functions */ 102 103 static uint8_t tpm_tis_locality_from_addr(hwaddr addr) 104 { 105 return (uint8_t)((addr >> TPM_TIS_LOCALITY_SHIFT) & 0x7); 106 } 107 108 static void tpm_tis_show_buffer(const unsigned char *buffer, 109 size_t buffer_size, const char *string) 110 { 111 size_t len, i; 112 char *line_buffer, *p; 113 114 len = MIN(tpm_cmd_get_size(buffer), buffer_size); 115 116 /* 117 * allocate enough room for 3 chars per buffer entry plus a 118 * newline after every 16 chars and a final null terminator. 119 */ 120 line_buffer = g_malloc(len * 3 + (len / 16) + 1); 121 122 for (i = 0, p = line_buffer; i < len; i++) { 123 if (i && !(i % 16)) { 124 p += sprintf(p, "\n"); 125 } 126 p += sprintf(p, "%.2X ", buffer[i]); 127 } 128 trace_tpm_tis_show_buffer(string, len, line_buffer); 129 130 g_free(line_buffer); 131 } 132 133 /* 134 * Set the given flags in the STS register by clearing the register but 135 * preserving the SELFTEST_DONE and TPM_FAMILY_MASK flags and then setting 136 * the new flags. 137 * 138 * The SELFTEST_DONE flag is acquired from the backend that determines it by 139 * peeking into TPM commands. 140 * 141 * A VM suspend/resume will preserve the flag by storing it into the VM 142 * device state, but the backend will not remember it when QEMU is started 143 * again. Therefore, we cache the flag here. Once set, it will not be unset 144 * except by a reset. 145 */ 146 static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags) 147 { 148 l->sts &= TPM_TIS_STS_SELFTEST_DONE | TPM_TIS_STS_TPM_FAMILY_MASK; 149 l->sts |= flags; 150 } 151 152 /* 153 * Send a request to the TPM. 154 */ 155 static void tpm_tis_tpm_send(TPMState *s, uint8_t locty) 156 { 157 if (trace_event_get_state_backends(TRACE_TPM_TIS_SHOW_BUFFER)) { 158 tpm_tis_show_buffer(s->buffer, s->be_buffer_size, "To TPM"); 159 } 160 161 /* 162 * rw_offset serves as length indicator for length of data; 163 * it's reset when the response comes back 164 */ 165 s->loc[locty].state = TPM_TIS_STATE_EXECUTION; 166 167 s->cmd = (TPMBackendCmd) { 168 .locty = locty, 169 .in = s->buffer, 170 .in_len = s->rw_offset, 171 .out = s->buffer, 172 .out_len = s->be_buffer_size, 173 }; 174 175 tpm_backend_deliver_request(s->be_driver, &s->cmd); 176 } 177 178 /* raise an interrupt if allowed */ 179 static void tpm_tis_raise_irq(TPMState *s, uint8_t locty, uint32_t irqmask) 180 { 181 if (!TPM_TIS_IS_VALID_LOCTY(locty)) { 182 return; 183 } 184 185 if ((s->loc[locty].inte & TPM_TIS_INT_ENABLED) && 186 (s->loc[locty].inte & irqmask)) { 187 trace_tpm_tis_raise_irq(irqmask); 188 qemu_irq_raise(s->irq); 189 s->loc[locty].ints |= irqmask; 190 } 191 } 192 193 static uint32_t tpm_tis_check_request_use_except(TPMState *s, uint8_t locty) 194 { 195 uint8_t l; 196 197 for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { 198 if (l == locty) { 199 continue; 200 } 201 if ((s->loc[l].access & TPM_TIS_ACCESS_REQUEST_USE)) { 202 return 1; 203 } 204 } 205 206 return 0; 207 } 208 209 static void tpm_tis_new_active_locality(TPMState *s, uint8_t new_active_locty) 210 { 211 bool change = (s->active_locty != new_active_locty); 212 bool is_seize; 213 uint8_t mask; 214 215 if (change && TPM_TIS_IS_VALID_LOCTY(s->active_locty)) { 216 is_seize = TPM_TIS_IS_VALID_LOCTY(new_active_locty) && 217 s->loc[new_active_locty].access & TPM_TIS_ACCESS_SEIZE; 218 219 if (is_seize) { 220 mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY); 221 } else { 222 mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY| 223 TPM_TIS_ACCESS_REQUEST_USE); 224 } 225 /* reset flags on the old active locality */ 226 s->loc[s->active_locty].access &= mask; 227 228 if (is_seize) { 229 s->loc[s->active_locty].access |= TPM_TIS_ACCESS_BEEN_SEIZED; 230 } 231 } 232 233 s->active_locty = new_active_locty; 234 235 trace_tpm_tis_new_active_locality(s->active_locty); 236 237 if (TPM_TIS_IS_VALID_LOCTY(new_active_locty)) { 238 /* set flags on the new active locality */ 239 s->loc[new_active_locty].access |= TPM_TIS_ACCESS_ACTIVE_LOCALITY; 240 s->loc[new_active_locty].access &= ~(TPM_TIS_ACCESS_REQUEST_USE | 241 TPM_TIS_ACCESS_SEIZE); 242 } 243 244 if (change) { 245 tpm_tis_raise_irq(s, s->active_locty, TPM_TIS_INT_LOCALITY_CHANGED); 246 } 247 } 248 249 /* abort -- this function switches the locality */ 250 static void tpm_tis_abort(TPMState *s) 251 { 252 s->rw_offset = 0; 253 254 trace_tpm_tis_abort(s->next_locty); 255 256 /* 257 * Need to react differently depending on who's aborting now and 258 * which locality will become active afterwards. 259 */ 260 if (s->aborting_locty == s->next_locty) { 261 s->loc[s->aborting_locty].state = TPM_TIS_STATE_READY; 262 tpm_tis_sts_set(&s->loc[s->aborting_locty], 263 TPM_TIS_STS_COMMAND_READY); 264 tpm_tis_raise_irq(s, s->aborting_locty, TPM_TIS_INT_COMMAND_READY); 265 } 266 267 /* locality after abort is another one than the current one */ 268 tpm_tis_new_active_locality(s, s->next_locty); 269 270 s->next_locty = TPM_TIS_NO_LOCALITY; 271 /* nobody's aborting a command anymore */ 272 s->aborting_locty = TPM_TIS_NO_LOCALITY; 273 } 274 275 /* prepare aborting current command */ 276 static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty) 277 { 278 uint8_t busy_locty; 279 280 assert(TPM_TIS_IS_VALID_LOCTY(newlocty)); 281 282 s->aborting_locty = locty; /* may also be TPM_TIS_NO_LOCALITY */ 283 s->next_locty = newlocty; /* locality after successful abort */ 284 285 /* 286 * only abort a command using an interrupt if currently executing 287 * a command AND if there's a valid connection to the vTPM. 288 */ 289 for (busy_locty = 0; busy_locty < TPM_TIS_NUM_LOCALITIES; busy_locty++) { 290 if (s->loc[busy_locty].state == TPM_TIS_STATE_EXECUTION) { 291 /* 292 * request the backend to cancel. Some backends may not 293 * support it 294 */ 295 tpm_backend_cancel_cmd(s->be_driver); 296 return; 297 } 298 } 299 300 tpm_tis_abort(s); 301 } 302 303 /* 304 * Callback from the TPM to indicate that the response was received. 305 */ 306 static void tpm_tis_request_completed(TPMIf *ti, int ret) 307 { 308 TPMState *s = TPM(ti); 309 uint8_t locty = s->cmd.locty; 310 uint8_t l; 311 312 assert(TPM_TIS_IS_VALID_LOCTY(locty)); 313 314 if (s->cmd.selftest_done) { 315 for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { 316 s->loc[l].sts |= TPM_TIS_STS_SELFTEST_DONE; 317 } 318 } 319 320 /* FIXME: report error if ret != 0 */ 321 tpm_tis_sts_set(&s->loc[locty], 322 TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); 323 s->loc[locty].state = TPM_TIS_STATE_COMPLETION; 324 s->rw_offset = 0; 325 326 if (trace_event_get_state_backends(TRACE_TPM_TIS_SHOW_BUFFER)) { 327 tpm_tis_show_buffer(s->buffer, s->be_buffer_size, "From TPM"); 328 } 329 330 if (TPM_TIS_IS_VALID_LOCTY(s->next_locty)) { 331 tpm_tis_abort(s); 332 } 333 334 tpm_tis_raise_irq(s, locty, 335 TPM_TIS_INT_DATA_AVAILABLE | TPM_TIS_INT_STS_VALID); 336 } 337 338 /* 339 * Read a byte of response data 340 */ 341 static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty) 342 { 343 uint32_t ret = TPM_TIS_NO_DATA_BYTE; 344 uint16_t len; 345 346 if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) { 347 len = MIN(tpm_cmd_get_size(&s->buffer), 348 s->be_buffer_size); 349 350 ret = s->buffer[s->rw_offset++]; 351 if (s->rw_offset >= len) { 352 /* got last byte */ 353 tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID); 354 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID); 355 } 356 trace_tpm_tis_data_read(ret, s->rw_offset - 1); 357 } 358 359 return ret; 360 } 361 362 #ifdef DEBUG_TIS 363 static void tpm_tis_dump_state(void *opaque, hwaddr addr) 364 { 365 static const unsigned regs[] = { 366 TPM_TIS_REG_ACCESS, 367 TPM_TIS_REG_INT_ENABLE, 368 TPM_TIS_REG_INT_VECTOR, 369 TPM_TIS_REG_INT_STATUS, 370 TPM_TIS_REG_INTF_CAPABILITY, 371 TPM_TIS_REG_STS, 372 TPM_TIS_REG_DID_VID, 373 TPM_TIS_REG_RID, 374 0xfff}; 375 int idx; 376 uint8_t locty = tpm_tis_locality_from_addr(addr); 377 hwaddr base = addr & ~0xfff; 378 TPMState *s = opaque; 379 380 printf("tpm_tis: active locality : %d\n" 381 "tpm_tis: state of locality %d : %d\n" 382 "tpm_tis: register dump:\n", 383 s->active_locty, 384 locty, s->loc[locty].state); 385 386 for (idx = 0; regs[idx] != 0xfff; idx++) { 387 printf("tpm_tis: 0x%04x : 0x%08x\n", regs[idx], 388 (int)tpm_tis_mmio_read(opaque, base + regs[idx], 4)); 389 } 390 391 printf("tpm_tis: r/w offset : %d\n" 392 "tpm_tis: result buffer : ", 393 s->rw_offset); 394 for (idx = 0; 395 idx < MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size); 396 idx++) { 397 printf("%c%02x%s", 398 s->rw_offset == idx ? '>' : ' ', 399 s->buffer[idx], 400 ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); 401 } 402 printf("\n"); 403 } 404 #endif 405 406 /* 407 * Read a register of the TIS interface 408 * See specs pages 33-63 for description of the registers 409 */ 410 static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, 411 unsigned size) 412 { 413 TPMState *s = opaque; 414 uint16_t offset = addr & 0xffc; 415 uint8_t shift = (addr & 0x3) * 8; 416 uint32_t val = 0xffffffff; 417 uint8_t locty = tpm_tis_locality_from_addr(addr); 418 uint32_t avail; 419 uint8_t v; 420 421 if (tpm_backend_had_startup_error(s->be_driver)) { 422 return 0; 423 } 424 425 switch (offset) { 426 case TPM_TIS_REG_ACCESS: 427 /* never show the SEIZE flag even though we use it internally */ 428 val = s->loc[locty].access & ~TPM_TIS_ACCESS_SEIZE; 429 /* the pending flag is always calculated */ 430 if (tpm_tis_check_request_use_except(s, locty)) { 431 val |= TPM_TIS_ACCESS_PENDING_REQUEST; 432 } 433 val |= !tpm_backend_get_tpm_established_flag(s->be_driver); 434 break; 435 case TPM_TIS_REG_INT_ENABLE: 436 val = s->loc[locty].inte; 437 break; 438 case TPM_TIS_REG_INT_VECTOR: 439 val = s->irq_num; 440 break; 441 case TPM_TIS_REG_INT_STATUS: 442 val = s->loc[locty].ints; 443 break; 444 case TPM_TIS_REG_INTF_CAPABILITY: 445 switch (s->be_tpm_version) { 446 case TPM_VERSION_UNSPEC: 447 val = 0; 448 break; 449 case TPM_VERSION_1_2: 450 val = TPM_TIS_CAPABILITIES_SUPPORTED1_3; 451 break; 452 case TPM_VERSION_2_0: 453 val = TPM_TIS_CAPABILITIES_SUPPORTED2_0; 454 break; 455 } 456 break; 457 case TPM_TIS_REG_STS: 458 if (s->active_locty == locty) { 459 if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) { 460 val = TPM_TIS_BURST_COUNT( 461 MIN(tpm_cmd_get_size(&s->buffer), 462 s->be_buffer_size) 463 - s->rw_offset) | s->loc[locty].sts; 464 } else { 465 avail = s->be_buffer_size - s->rw_offset; 466 /* 467 * byte-sized reads should not return 0x00 for 0x100 468 * available bytes. 469 */ 470 if (size == 1 && avail > 0xff) { 471 avail = 0xff; 472 } 473 val = TPM_TIS_BURST_COUNT(avail) | s->loc[locty].sts; 474 } 475 } 476 break; 477 case TPM_TIS_REG_DATA_FIFO: 478 case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END: 479 if (s->active_locty == locty) { 480 if (size > 4 - (addr & 0x3)) { 481 /* prevent access beyond FIFO */ 482 size = 4 - (addr & 0x3); 483 } 484 val = 0; 485 shift = 0; 486 while (size > 0) { 487 switch (s->loc[locty].state) { 488 case TPM_TIS_STATE_COMPLETION: 489 v = tpm_tis_data_read(s, locty); 490 break; 491 default: 492 v = TPM_TIS_NO_DATA_BYTE; 493 break; 494 } 495 val |= (v << shift); 496 shift += 8; 497 size--; 498 } 499 shift = 0; /* no more adjustments */ 500 } 501 break; 502 case TPM_TIS_REG_INTERFACE_ID: 503 val = s->loc[locty].iface_id; 504 break; 505 case TPM_TIS_REG_DID_VID: 506 val = (TPM_TIS_TPM_DID << 16) | TPM_TIS_TPM_VID; 507 break; 508 case TPM_TIS_REG_RID: 509 val = TPM_TIS_TPM_RID; 510 break; 511 #ifdef DEBUG_TIS 512 case TPM_TIS_REG_DEBUG: 513 tpm_tis_dump_state(opaque, addr); 514 break; 515 #endif 516 } 517 518 if (shift) { 519 val >>= shift; 520 } 521 522 trace_tpm_tis_mmio_read(size, addr, val); 523 524 return val; 525 } 526 527 /* 528 * Write a value to a register of the TIS interface 529 * See specs pages 33-63 for description of the registers 530 */ 531 static void tpm_tis_mmio_write(void *opaque, hwaddr addr, 532 uint64_t val, unsigned size) 533 { 534 TPMState *s = opaque; 535 uint16_t off = addr & 0xffc; 536 uint8_t shift = (addr & 0x3) * 8; 537 uint8_t locty = tpm_tis_locality_from_addr(addr); 538 uint8_t active_locty, l; 539 int c, set_new_locty = 1; 540 uint16_t len; 541 uint32_t mask = (size == 1) ? 0xff : ((size == 2) ? 0xffff : ~0); 542 543 trace_tpm_tis_mmio_write(size, addr, val); 544 545 if (locty == 4) { 546 trace_tpm_tis_mmio_write_locty4(); 547 return; 548 } 549 550 if (tpm_backend_had_startup_error(s->be_driver)) { 551 return; 552 } 553 554 val &= mask; 555 556 if (shift) { 557 val <<= shift; 558 mask <<= shift; 559 } 560 561 mask ^= 0xffffffff; 562 563 switch (off) { 564 case TPM_TIS_REG_ACCESS: 565 566 if ((val & TPM_TIS_ACCESS_SEIZE)) { 567 val &= ~(TPM_TIS_ACCESS_REQUEST_USE | 568 TPM_TIS_ACCESS_ACTIVE_LOCALITY); 569 } 570 571 active_locty = s->active_locty; 572 573 if ((val & TPM_TIS_ACCESS_ACTIVE_LOCALITY)) { 574 /* give up locality if currently owned */ 575 if (s->active_locty == locty) { 576 trace_tpm_tis_mmio_write_release_locty(locty); 577 578 uint8_t newlocty = TPM_TIS_NO_LOCALITY; 579 /* anybody wants the locality ? */ 580 for (c = TPM_TIS_NUM_LOCALITIES - 1; c >= 0; c--) { 581 if ((s->loc[c].access & TPM_TIS_ACCESS_REQUEST_USE)) { 582 trace_tpm_tis_mmio_write_locty_req_use(c); 583 newlocty = c; 584 break; 585 } 586 } 587 trace_tpm_tis_mmio_write_next_locty(newlocty); 588 589 if (TPM_TIS_IS_VALID_LOCTY(newlocty)) { 590 set_new_locty = 0; 591 tpm_tis_prep_abort(s, locty, newlocty); 592 } else { 593 active_locty = TPM_TIS_NO_LOCALITY; 594 } 595 } else { 596 /* not currently the owner; clear a pending request */ 597 s->loc[locty].access &= ~TPM_TIS_ACCESS_REQUEST_USE; 598 } 599 } 600 601 if ((val & TPM_TIS_ACCESS_BEEN_SEIZED)) { 602 s->loc[locty].access &= ~TPM_TIS_ACCESS_BEEN_SEIZED; 603 } 604 605 if ((val & TPM_TIS_ACCESS_SEIZE)) { 606 /* 607 * allow seize if a locality is active and the requesting 608 * locality is higher than the one that's active 609 * OR 610 * allow seize for requesting locality if no locality is 611 * active 612 */ 613 while ((TPM_TIS_IS_VALID_LOCTY(s->active_locty) && 614 locty > s->active_locty) || 615 !TPM_TIS_IS_VALID_LOCTY(s->active_locty)) { 616 bool higher_seize = FALSE; 617 618 /* already a pending SEIZE ? */ 619 if ((s->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) { 620 break; 621 } 622 623 /* check for ongoing seize by a higher locality */ 624 for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) { 625 if ((s->loc[l].access & TPM_TIS_ACCESS_SEIZE)) { 626 higher_seize = TRUE; 627 break; 628 } 629 } 630 631 if (higher_seize) { 632 break; 633 } 634 635 /* cancel any seize by a lower locality */ 636 for (l = 0; l < locty; l++) { 637 s->loc[l].access &= ~TPM_TIS_ACCESS_SEIZE; 638 } 639 640 s->loc[locty].access |= TPM_TIS_ACCESS_SEIZE; 641 642 trace_tpm_tis_mmio_write_locty_seized(locty, s->active_locty); 643 trace_tpm_tis_mmio_write_init_abort(); 644 645 set_new_locty = 0; 646 tpm_tis_prep_abort(s, s->active_locty, locty); 647 break; 648 } 649 } 650 651 if ((val & TPM_TIS_ACCESS_REQUEST_USE)) { 652 if (s->active_locty != locty) { 653 if (TPM_TIS_IS_VALID_LOCTY(s->active_locty)) { 654 s->loc[locty].access |= TPM_TIS_ACCESS_REQUEST_USE; 655 } else { 656 /* no locality active -> make this one active now */ 657 active_locty = locty; 658 } 659 } 660 } 661 662 if (set_new_locty) { 663 tpm_tis_new_active_locality(s, active_locty); 664 } 665 666 break; 667 case TPM_TIS_REG_INT_ENABLE: 668 if (s->active_locty != locty) { 669 break; 670 } 671 672 s->loc[locty].inte &= mask; 673 s->loc[locty].inte |= (val & (TPM_TIS_INT_ENABLED | 674 TPM_TIS_INT_POLARITY_MASK | 675 TPM_TIS_INTERRUPTS_SUPPORTED)); 676 break; 677 case TPM_TIS_REG_INT_VECTOR: 678 /* hard wired -- ignore */ 679 break; 680 case TPM_TIS_REG_INT_STATUS: 681 if (s->active_locty != locty) { 682 break; 683 } 684 685 /* clearing of interrupt flags */ 686 if (((val & TPM_TIS_INTERRUPTS_SUPPORTED)) && 687 (s->loc[locty].ints & TPM_TIS_INTERRUPTS_SUPPORTED)) { 688 s->loc[locty].ints &= ~val; 689 if (s->loc[locty].ints == 0) { 690 qemu_irq_lower(s->irq); 691 trace_tpm_tis_mmio_write_lowering_irq(); 692 } 693 } 694 s->loc[locty].ints &= ~(val & TPM_TIS_INTERRUPTS_SUPPORTED); 695 break; 696 case TPM_TIS_REG_STS: 697 if (s->active_locty != locty) { 698 break; 699 } 700 701 if (s->be_tpm_version == TPM_VERSION_2_0) { 702 /* some flags that are only supported for TPM 2 */ 703 if (val & TPM_TIS_STS_COMMAND_CANCEL) { 704 if (s->loc[locty].state == TPM_TIS_STATE_EXECUTION) { 705 /* 706 * request the backend to cancel. Some backends may not 707 * support it 708 */ 709 tpm_backend_cancel_cmd(s->be_driver); 710 } 711 } 712 713 if (val & TPM_TIS_STS_RESET_ESTABLISHMENT_BIT) { 714 if (locty == 3 || locty == 4) { 715 tpm_backend_reset_tpm_established_flag(s->be_driver, locty); 716 } 717 } 718 } 719 720 val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO | 721 TPM_TIS_STS_RESPONSE_RETRY); 722 723 if (val == TPM_TIS_STS_COMMAND_READY) { 724 switch (s->loc[locty].state) { 725 726 case TPM_TIS_STATE_READY: 727 s->rw_offset = 0; 728 break; 729 730 case TPM_TIS_STATE_IDLE: 731 tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_COMMAND_READY); 732 s->loc[locty].state = TPM_TIS_STATE_READY; 733 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY); 734 break; 735 736 case TPM_TIS_STATE_EXECUTION: 737 case TPM_TIS_STATE_RECEPTION: 738 /* abort currently running command */ 739 trace_tpm_tis_mmio_write_init_abort(); 740 tpm_tis_prep_abort(s, locty, locty); 741 break; 742 743 case TPM_TIS_STATE_COMPLETION: 744 s->rw_offset = 0; 745 /* shortcut to ready state with C/R set */ 746 s->loc[locty].state = TPM_TIS_STATE_READY; 747 if (!(s->loc[locty].sts & TPM_TIS_STS_COMMAND_READY)) { 748 tpm_tis_sts_set(&s->loc[locty], 749 TPM_TIS_STS_COMMAND_READY); 750 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY); 751 } 752 s->loc[locty].sts &= ~(TPM_TIS_STS_DATA_AVAILABLE); 753 break; 754 755 } 756 } else if (val == TPM_TIS_STS_TPM_GO) { 757 switch (s->loc[locty].state) { 758 case TPM_TIS_STATE_RECEPTION: 759 if ((s->loc[locty].sts & TPM_TIS_STS_EXPECT) == 0) { 760 tpm_tis_tpm_send(s, locty); 761 } 762 break; 763 default: 764 /* ignore */ 765 break; 766 } 767 } else if (val == TPM_TIS_STS_RESPONSE_RETRY) { 768 switch (s->loc[locty].state) { 769 case TPM_TIS_STATE_COMPLETION: 770 s->rw_offset = 0; 771 tpm_tis_sts_set(&s->loc[locty], 772 TPM_TIS_STS_VALID| 773 TPM_TIS_STS_DATA_AVAILABLE); 774 break; 775 default: 776 /* ignore */ 777 break; 778 } 779 } 780 break; 781 case TPM_TIS_REG_DATA_FIFO: 782 case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END: 783 /* data fifo */ 784 if (s->active_locty != locty) { 785 break; 786 } 787 788 if (s->loc[locty].state == TPM_TIS_STATE_IDLE || 789 s->loc[locty].state == TPM_TIS_STATE_EXECUTION || 790 s->loc[locty].state == TPM_TIS_STATE_COMPLETION) { 791 /* drop the byte */ 792 } else { 793 trace_tpm_tis_mmio_write_data2send(val, size); 794 if (s->loc[locty].state == TPM_TIS_STATE_READY) { 795 s->loc[locty].state = TPM_TIS_STATE_RECEPTION; 796 tpm_tis_sts_set(&s->loc[locty], 797 TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); 798 } 799 800 val >>= shift; 801 if (size > 4 - (addr & 0x3)) { 802 /* prevent access beyond FIFO */ 803 size = 4 - (addr & 0x3); 804 } 805 806 while ((s->loc[locty].sts & TPM_TIS_STS_EXPECT) && size > 0) { 807 if (s->rw_offset < s->be_buffer_size) { 808 s->buffer[s->rw_offset++] = 809 (uint8_t)val; 810 val >>= 8; 811 size--; 812 } else { 813 tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID); 814 } 815 } 816 817 /* check for complete packet */ 818 if (s->rw_offset > 5 && 819 (s->loc[locty].sts & TPM_TIS_STS_EXPECT)) { 820 /* we have a packet length - see if we have all of it */ 821 bool need_irq = !(s->loc[locty].sts & TPM_TIS_STS_VALID); 822 823 len = tpm_cmd_get_size(&s->buffer); 824 if (len > s->rw_offset) { 825 tpm_tis_sts_set(&s->loc[locty], 826 TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); 827 } else { 828 /* packet complete */ 829 tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID); 830 } 831 if (need_irq) { 832 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID); 833 } 834 } 835 } 836 break; 837 case TPM_TIS_REG_INTERFACE_ID: 838 if (val & TPM_TIS_IFACE_ID_INT_SEL_LOCK) { 839 for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { 840 s->loc[l].iface_id |= TPM_TIS_IFACE_ID_INT_SEL_LOCK; 841 } 842 } 843 break; 844 } 845 } 846 847 static const MemoryRegionOps tpm_tis_memory_ops = { 848 .read = tpm_tis_mmio_read, 849 .write = tpm_tis_mmio_write, 850 .endianness = DEVICE_LITTLE_ENDIAN, 851 .valid = { 852 .min_access_size = 1, 853 .max_access_size = 4, 854 }, 855 }; 856 857 /* 858 * Get the TPMVersion of the backend device being used 859 */ 860 static enum TPMVersion tpm_tis_get_tpm_version(TPMIf *ti) 861 { 862 TPMState *s = TPM(ti); 863 864 if (tpm_backend_had_startup_error(s->be_driver)) { 865 return TPM_VERSION_UNSPEC; 866 } 867 868 return tpm_backend_get_tpm_version(s->be_driver); 869 } 870 871 /* 872 * This function is called when the machine starts, resets or due to 873 * S3 resume. 874 */ 875 static void tpm_tis_reset(DeviceState *dev) 876 { 877 TPMState *s = TPM(dev); 878 int c; 879 880 s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver); 881 s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->be_driver), 882 TPM_TIS_BUFFER_MAX); 883 884 if (s->ppi_enabled) { 885 tpm_ppi_reset(&s->ppi); 886 } 887 tpm_backend_reset(s->be_driver); 888 889 s->active_locty = TPM_TIS_NO_LOCALITY; 890 s->next_locty = TPM_TIS_NO_LOCALITY; 891 s->aborting_locty = TPM_TIS_NO_LOCALITY; 892 893 for (c = 0; c < TPM_TIS_NUM_LOCALITIES; c++) { 894 s->loc[c].access = TPM_TIS_ACCESS_TPM_REG_VALID_STS; 895 switch (s->be_tpm_version) { 896 case TPM_VERSION_UNSPEC: 897 break; 898 case TPM_VERSION_1_2: 899 s->loc[c].sts = TPM_TIS_STS_TPM_FAMILY1_2; 900 s->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3; 901 break; 902 case TPM_VERSION_2_0: 903 s->loc[c].sts = TPM_TIS_STS_TPM_FAMILY2_0; 904 s->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0; 905 break; 906 } 907 s->loc[c].inte = TPM_TIS_INT_POLARITY_LOW_LEVEL; 908 s->loc[c].ints = 0; 909 s->loc[c].state = TPM_TIS_STATE_IDLE; 910 911 s->rw_offset = 0; 912 } 913 914 if (tpm_backend_startup_tpm(s->be_driver, s->be_buffer_size) < 0) { 915 exit(1); 916 } 917 } 918 919 /* persistent state handling */ 920 921 static int tpm_tis_pre_save(void *opaque) 922 { 923 TPMState *s = opaque; 924 uint8_t locty = s->active_locty; 925 926 trace_tpm_tis_pre_save(locty, s->rw_offset); 927 928 if (DEBUG_TIS) { 929 tpm_tis_dump_state(opaque, 0); 930 } 931 932 /* 933 * Synchronize with backend completion. 934 */ 935 tpm_backend_finish_sync(s->be_driver); 936 937 return 0; 938 } 939 940 static const VMStateDescription vmstate_locty = { 941 .name = "tpm-tis/locty", 942 .version_id = 0, 943 .fields = (VMStateField[]) { 944 VMSTATE_UINT32(state, TPMLocality), 945 VMSTATE_UINT32(inte, TPMLocality), 946 VMSTATE_UINT32(ints, TPMLocality), 947 VMSTATE_UINT8(access, TPMLocality), 948 VMSTATE_UINT32(sts, TPMLocality), 949 VMSTATE_UINT32(iface_id, TPMLocality), 950 VMSTATE_END_OF_LIST(), 951 } 952 }; 953 954 static const VMStateDescription vmstate_tpm_tis = { 955 .name = "tpm-tis", 956 .version_id = 0, 957 .pre_save = tpm_tis_pre_save, 958 .fields = (VMStateField[]) { 959 VMSTATE_BUFFER(buffer, TPMState), 960 VMSTATE_UINT16(rw_offset, TPMState), 961 VMSTATE_UINT8(active_locty, TPMState), 962 VMSTATE_UINT8(aborting_locty, TPMState), 963 VMSTATE_UINT8(next_locty, TPMState), 964 965 VMSTATE_STRUCT_ARRAY(loc, TPMState, TPM_TIS_NUM_LOCALITIES, 0, 966 vmstate_locty, TPMLocality), 967 968 VMSTATE_END_OF_LIST() 969 } 970 }; 971 972 static Property tpm_tis_properties[] = { 973 DEFINE_PROP_UINT32("irq", TPMState, irq_num, TPM_TIS_IRQ), 974 DEFINE_PROP_TPMBE("tpmdev", TPMState, be_driver), 975 DEFINE_PROP_BOOL("ppi", TPMState, ppi_enabled, true), 976 DEFINE_PROP_END_OF_LIST(), 977 }; 978 979 static void tpm_tis_realizefn(DeviceState *dev, Error **errp) 980 { 981 TPMState *s = TPM(dev); 982 983 if (!tpm_find()) { 984 error_setg(errp, "at most one TPM device is permitted"); 985 return; 986 } 987 988 if (!s->be_driver) { 989 error_setg(errp, "'tpmdev' property is required"); 990 return; 991 } 992 if (s->irq_num > 15) { 993 error_setg(errp, "IRQ %d is outside valid range of 0 to 15", 994 s->irq_num); 995 return; 996 } 997 998 isa_init_irq(&s->busdev, &s->irq, s->irq_num); 999 1000 memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)), 1001 TPM_TIS_ADDR_BASE, &s->mmio); 1002 1003 if (s->ppi_enabled) { 1004 tpm_ppi_init(&s->ppi, isa_address_space(ISA_DEVICE(dev)), 1005 TPM_PPI_ADDR_BASE, OBJECT(s)); 1006 } 1007 } 1008 1009 static void tpm_tis_initfn(Object *obj) 1010 { 1011 TPMState *s = TPM(obj); 1012 1013 memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops, 1014 s, "tpm-tis-mmio", 1015 TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT); 1016 } 1017 1018 static void tpm_tis_class_init(ObjectClass *klass, void *data) 1019 { 1020 DeviceClass *dc = DEVICE_CLASS(klass); 1021 TPMIfClass *tc = TPM_IF_CLASS(klass); 1022 1023 dc->realize = tpm_tis_realizefn; 1024 dc->props = tpm_tis_properties; 1025 dc->reset = tpm_tis_reset; 1026 dc->vmsd = &vmstate_tpm_tis; 1027 tc->model = TPM_MODEL_TPM_TIS; 1028 tc->get_version = tpm_tis_get_tpm_version; 1029 tc->request_completed = tpm_tis_request_completed; 1030 } 1031 1032 static const TypeInfo tpm_tis_info = { 1033 .name = TYPE_TPM_TIS, 1034 .parent = TYPE_ISA_DEVICE, 1035 .instance_size = sizeof(TPMState), 1036 .instance_init = tpm_tis_initfn, 1037 .class_init = tpm_tis_class_init, 1038 .interfaces = (InterfaceInfo[]) { 1039 { TYPE_TPM_IF }, 1040 { } 1041 } 1042 }; 1043 1044 static void tpm_tis_register(void) 1045 { 1046 type_register_static(&tpm_tis_info); 1047 } 1048 1049 type_init(tpm_tis_register) 1050