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