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