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