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