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.21, revision 1.0. 18 * In the developers menu choose the PC Client section then find the TIS 19 * specification. 20 */ 21 22 #include "sysemu/tpm_backend.h" 23 #include "tpm_int.h" 24 #include "block/block.h" 25 #include "exec/address-spaces.h" 26 #include "hw/hw.h" 27 #include "hw/i386/pc.h" 28 #include "hw/pci/pci_ids.h" 29 #include "tpm_tis.h" 30 #include "qemu-common.h" 31 32 /*#define DEBUG_TIS */ 33 34 #ifdef DEBUG_TIS 35 #define DPRINTF(fmt, ...) \ 36 do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) 37 #else 38 #define DPRINTF(fmt, ...) \ 39 do { } while (0) 40 #endif 41 42 /* whether the STS interrupt is supported */ 43 #define RAISE_STS_IRQ 44 45 /* tis registers */ 46 #define TPM_TIS_REG_ACCESS 0x00 47 #define TPM_TIS_REG_INT_ENABLE 0x08 48 #define TPM_TIS_REG_INT_VECTOR 0x0c 49 #define TPM_TIS_REG_INT_STATUS 0x10 50 #define TPM_TIS_REG_INTF_CAPABILITY 0x14 51 #define TPM_TIS_REG_STS 0x18 52 #define TPM_TIS_REG_DATA_FIFO 0x24 53 #define TPM_TIS_REG_DID_VID 0xf00 54 #define TPM_TIS_REG_RID 0xf04 55 56 /* vendor-specific registers */ 57 #define TPM_TIS_REG_DEBUG 0xf90 58 59 #define TPM_TIS_STS_VALID (1 << 7) 60 #define TPM_TIS_STS_COMMAND_READY (1 << 6) 61 #define TPM_TIS_STS_TPM_GO (1 << 5) 62 #define TPM_TIS_STS_DATA_AVAILABLE (1 << 4) 63 #define TPM_TIS_STS_EXPECT (1 << 3) 64 #define TPM_TIS_STS_RESPONSE_RETRY (1 << 1) 65 66 #define TPM_TIS_BURST_COUNT_SHIFT 8 67 #define TPM_TIS_BURST_COUNT(X) \ 68 ((X) << TPM_TIS_BURST_COUNT_SHIFT) 69 70 #define TPM_TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) 71 #define TPM_TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) 72 #define TPM_TIS_ACCESS_BEEN_SEIZED (1 << 4) 73 #define TPM_TIS_ACCESS_SEIZE (1 << 3) 74 #define TPM_TIS_ACCESS_PENDING_REQUEST (1 << 2) 75 #define TPM_TIS_ACCESS_REQUEST_USE (1 << 1) 76 #define TPM_TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) 77 78 #define TPM_TIS_INT_ENABLED (1 << 31) 79 #define TPM_TIS_INT_DATA_AVAILABLE (1 << 0) 80 #define TPM_TIS_INT_STS_VALID (1 << 1) 81 #define TPM_TIS_INT_LOCALITY_CHANGED (1 << 2) 82 #define TPM_TIS_INT_COMMAND_READY (1 << 7) 83 84 #define TPM_TIS_INT_POLARITY_MASK (3 << 3) 85 #define TPM_TIS_INT_POLARITY_LOW_LEVEL (1 << 3) 86 87 #ifndef RAISE_STS_IRQ 88 89 #define TPM_TIS_INTERRUPTS_SUPPORTED (TPM_TIS_INT_LOCALITY_CHANGED | \ 90 TPM_TIS_INT_DATA_AVAILABLE | \ 91 TPM_TIS_INT_COMMAND_READY) 92 93 #else 94 95 #define TPM_TIS_INTERRUPTS_SUPPORTED (TPM_TIS_INT_LOCALITY_CHANGED | \ 96 TPM_TIS_INT_DATA_AVAILABLE | \ 97 TPM_TIS_INT_STS_VALID | \ 98 TPM_TIS_INT_COMMAND_READY) 99 100 #endif 101 102 #define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL (1 << 4) /* support is mandatory */ 103 #define TPM_TIS_CAPABILITIES_SUPPORTED (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \ 104 TPM_TIS_INTERRUPTS_SUPPORTED) 105 106 #define TPM_TIS_TPM_DID 0x0001 107 #define TPM_TIS_TPM_VID PCI_VENDOR_ID_IBM 108 #define TPM_TIS_TPM_RID 0x0001 109 110 #define TPM_TIS_NO_DATA_BYTE 0xff 111 112 /* local prototypes */ 113 114 static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, 115 unsigned size); 116 117 /* utility functions */ 118 119 static uint8_t tpm_tis_locality_from_addr(hwaddr addr) 120 { 121 return (uint8_t)((addr >> TPM_TIS_LOCALITY_SHIFT) & 0x7); 122 } 123 124 static uint32_t tpm_tis_get_size_from_buffer(const TPMSizedBuffer *sb) 125 { 126 return be32_to_cpu(*(uint32_t *)&sb->buffer[2]); 127 } 128 129 static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, const char *string) 130 { 131 #ifdef DEBUG_TIS 132 uint32_t len, i; 133 134 len = tpm_tis_get_size_from_buffer(sb); 135 DPRINTF("tpm_tis: %s length = %d\n", string, len); 136 for (i = 0; i < len; i++) { 137 if (i && !(i % 16)) { 138 DPRINTF("\n"); 139 } 140 DPRINTF("%.2X ", sb->buffer[i]); 141 } 142 DPRINTF("\n"); 143 #endif 144 } 145 146 /* 147 * Send a request to the TPM. 148 */ 149 static void tpm_tis_tpm_send(TPMState *s, uint8_t locty) 150 { 151 TPMTISEmuState *tis = &s->s.tis; 152 153 tpm_tis_show_buffer(&tis->loc[locty].w_buffer, "tpm_tis: To TPM"); 154 155 s->locty_number = locty; 156 s->locty_data = &tis->loc[locty]; 157 158 /* 159 * w_offset serves as length indicator for length of data; 160 * it's reset when the response comes back 161 */ 162 tis->loc[locty].state = TPM_TIS_STATE_EXECUTION; 163 164 tpm_backend_deliver_request(s->be_driver); 165 } 166 167 /* raise an interrupt if allowed */ 168 static void tpm_tis_raise_irq(TPMState *s, uint8_t locty, uint32_t irqmask) 169 { 170 TPMTISEmuState *tis = &s->s.tis; 171 172 if (!TPM_TIS_IS_VALID_LOCTY(locty)) { 173 return; 174 } 175 176 if ((tis->loc[locty].inte & TPM_TIS_INT_ENABLED) && 177 (tis->loc[locty].inte & irqmask)) { 178 DPRINTF("tpm_tis: Raising IRQ for flag %08x\n", irqmask); 179 qemu_irq_raise(s->s.tis.irq); 180 tis->loc[locty].ints |= irqmask; 181 } 182 } 183 184 static uint32_t tpm_tis_check_request_use_except(TPMState *s, uint8_t locty) 185 { 186 uint8_t l; 187 188 for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { 189 if (l == locty) { 190 continue; 191 } 192 if ((s->s.tis.loc[l].access & TPM_TIS_ACCESS_REQUEST_USE)) { 193 return 1; 194 } 195 } 196 197 return 0; 198 } 199 200 static void tpm_tis_new_active_locality(TPMState *s, uint8_t new_active_locty) 201 { 202 TPMTISEmuState *tis = &s->s.tis; 203 bool change = (s->s.tis.active_locty != new_active_locty); 204 bool is_seize; 205 uint8_t mask; 206 207 if (change && TPM_TIS_IS_VALID_LOCTY(s->s.tis.active_locty)) { 208 is_seize = TPM_TIS_IS_VALID_LOCTY(new_active_locty) && 209 tis->loc[new_active_locty].access & TPM_TIS_ACCESS_SEIZE; 210 211 if (is_seize) { 212 mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY); 213 } else { 214 mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY| 215 TPM_TIS_ACCESS_REQUEST_USE); 216 } 217 /* reset flags on the old active locality */ 218 tis->loc[s->s.tis.active_locty].access &= mask; 219 220 if (is_seize) { 221 tis->loc[tis->active_locty].access |= TPM_TIS_ACCESS_BEEN_SEIZED; 222 } 223 } 224 225 tis->active_locty = new_active_locty; 226 227 DPRINTF("tpm_tis: Active locality is now %d\n", s->s.tis.active_locty); 228 229 if (TPM_TIS_IS_VALID_LOCTY(new_active_locty)) { 230 /* set flags on the new active locality */ 231 tis->loc[new_active_locty].access |= TPM_TIS_ACCESS_ACTIVE_LOCALITY; 232 tis->loc[new_active_locty].access &= ~(TPM_TIS_ACCESS_REQUEST_USE | 233 TPM_TIS_ACCESS_SEIZE); 234 } 235 236 if (change) { 237 tpm_tis_raise_irq(s, tis->active_locty, TPM_TIS_INT_LOCALITY_CHANGED); 238 } 239 } 240 241 /* abort -- this function switches the locality */ 242 static void tpm_tis_abort(TPMState *s, uint8_t locty) 243 { 244 TPMTISEmuState *tis = &s->s.tis; 245 246 tis->loc[locty].r_offset = 0; 247 tis->loc[locty].w_offset = 0; 248 249 DPRINTF("tpm_tis: tis_abort: new active locality is %d\n", tis->next_locty); 250 251 /* 252 * Need to react differently depending on who's aborting now and 253 * which locality will become active afterwards. 254 */ 255 if (tis->aborting_locty == tis->next_locty) { 256 tis->loc[tis->aborting_locty].state = TPM_TIS_STATE_READY; 257 tis->loc[tis->aborting_locty].sts = TPM_TIS_STS_COMMAND_READY; 258 tpm_tis_raise_irq(s, tis->aborting_locty, TPM_TIS_INT_COMMAND_READY); 259 } 260 261 /* locality after abort is another one than the current one */ 262 tpm_tis_new_active_locality(s, tis->next_locty); 263 264 tis->next_locty = TPM_TIS_NO_LOCALITY; 265 /* nobody's aborting a command anymore */ 266 tis->aborting_locty = TPM_TIS_NO_LOCALITY; 267 } 268 269 /* prepare aborting current command */ 270 static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty) 271 { 272 TPMTISEmuState *tis = &s->s.tis; 273 uint8_t busy_locty; 274 275 tis->aborting_locty = locty; 276 tis->next_locty = newlocty; /* locality after successful abort */ 277 278 /* 279 * only abort a command using an interrupt if currently executing 280 * a command AND if there's a valid connection to the vTPM. 281 */ 282 for (busy_locty = 0; busy_locty < TPM_TIS_NUM_LOCALITIES; busy_locty++) { 283 if (tis->loc[busy_locty].state == TPM_TIS_STATE_EXECUTION) { 284 /* 285 * request the backend to cancel. Some backends may not 286 * support it 287 */ 288 tpm_backend_cancel_cmd(s->be_driver); 289 return; 290 } 291 } 292 293 tpm_tis_abort(s, locty); 294 } 295 296 static void tpm_tis_receive_bh(void *opaque) 297 { 298 TPMState *s = opaque; 299 TPMTISEmuState *tis = &s->s.tis; 300 uint8_t locty = s->locty_number; 301 302 tis->loc[locty].sts = TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE; 303 tis->loc[locty].state = TPM_TIS_STATE_COMPLETION; 304 tis->loc[locty].r_offset = 0; 305 tis->loc[locty].w_offset = 0; 306 307 if (TPM_TIS_IS_VALID_LOCTY(tis->next_locty)) { 308 tpm_tis_abort(s, locty); 309 } 310 311 #ifndef RAISE_STS_IRQ 312 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_DATA_AVAILABLE); 313 #else 314 tpm_tis_raise_irq(s, locty, 315 TPM_TIS_INT_DATA_AVAILABLE | TPM_TIS_INT_STS_VALID); 316 #endif 317 } 318 319 /* 320 * Callback from the TPM to indicate that the response was received. 321 */ 322 static void tpm_tis_receive_cb(TPMState *s, uint8_t locty) 323 { 324 TPMTISEmuState *tis = &s->s.tis; 325 326 assert(s->locty_number == locty); 327 328 qemu_bh_schedule(tis->bh); 329 } 330 331 /* 332 * Read a byte of response data 333 */ 334 static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty) 335 { 336 TPMTISEmuState *tis = &s->s.tis; 337 uint32_t ret = TPM_TIS_NO_DATA_BYTE; 338 uint16_t len; 339 340 if ((tis->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) { 341 len = tpm_tis_get_size_from_buffer(&tis->loc[locty].r_buffer); 342 343 ret = tis->loc[locty].r_buffer.buffer[tis->loc[locty].r_offset++]; 344 if (tis->loc[locty].r_offset >= len) { 345 /* got last byte */ 346 tis->loc[locty].sts = TPM_TIS_STS_VALID; 347 #ifdef RAISE_STS_IRQ 348 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID); 349 #endif 350 } 351 DPRINTF("tpm_tis: tpm_tis_data_read byte 0x%02x [%d]\n", 352 ret, tis->loc[locty].r_offset-1); 353 } 354 355 return ret; 356 } 357 358 #ifdef DEBUG_TIS 359 static void tpm_tis_dump_state(void *opaque, hwaddr addr) 360 { 361 static const unsigned regs[] = { 362 TPM_TIS_REG_ACCESS, 363 TPM_TIS_REG_INT_ENABLE, 364 TPM_TIS_REG_INT_VECTOR, 365 TPM_TIS_REG_INT_STATUS, 366 TPM_TIS_REG_INTF_CAPABILITY, 367 TPM_TIS_REG_STS, 368 TPM_TIS_REG_DID_VID, 369 TPM_TIS_REG_RID, 370 0xfff}; 371 int idx; 372 uint8_t locty = tpm_tis_locality_from_addr(addr); 373 hwaddr base = addr & ~0xfff; 374 TPMState *s = opaque; 375 TPMTISEmuState *tis = &s->s.tis; 376 377 DPRINTF("tpm_tis: active locality : %d\n" 378 "tpm_tis: state of locality %d : %d\n" 379 "tpm_tis: register dump:\n", 380 tis->active_locty, 381 locty, tis->loc[locty].state); 382 383 for (idx = 0; regs[idx] != 0xfff; idx++) { 384 DPRINTF("tpm_tis: 0x%04x : 0x%08x\n", regs[idx], 385 (uint32_t)tpm_tis_mmio_read(opaque, base + regs[idx], 4)); 386 } 387 388 DPRINTF("tpm_tis: read offset : %d\n" 389 "tpm_tis: result buffer : ", 390 tis->loc[locty].r_offset); 391 for (idx = 0; 392 idx < tpm_tis_get_size_from_buffer(&tis->loc[locty].r_buffer); 393 idx++) { 394 DPRINTF("%c%02x%s", 395 tis->loc[locty].r_offset == idx ? '>' : ' ', 396 tis->loc[locty].r_buffer.buffer[idx], 397 ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); 398 } 399 DPRINTF("\n" 400 "tpm_tis: write offset : %d\n" 401 "tpm_tis: request buffer: ", 402 tis->loc[locty].w_offset); 403 for (idx = 0; 404 idx < tpm_tis_get_size_from_buffer(&tis->loc[locty].w_buffer); 405 idx++) { 406 DPRINTF("%c%02x%s", 407 tis->loc[locty].w_offset == idx ? '>' : ' ', 408 tis->loc[locty].w_buffer.buffer[idx], 409 ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); 410 } 411 DPRINTF("\n"); 412 } 413 #endif 414 415 /* 416 * Read a register of the TIS interface 417 * See specs pages 33-63 for description of the registers 418 */ 419 static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, 420 unsigned size) 421 { 422 TPMState *s = opaque; 423 TPMTISEmuState *tis = &s->s.tis; 424 uint16_t offset = addr & 0xffc; 425 uint8_t shift = (addr & 0x3) * 8; 426 uint32_t val = 0xffffffff; 427 uint8_t locty = tpm_tis_locality_from_addr(addr); 428 uint32_t avail; 429 430 if (tpm_backend_had_startup_error(s->be_driver)) { 431 return val; 432 } 433 434 switch (offset) { 435 case TPM_TIS_REG_ACCESS: 436 /* never show the SEIZE flag even though we use it internally */ 437 val = tis->loc[locty].access & ~TPM_TIS_ACCESS_SEIZE; 438 /* the pending flag is always calculated */ 439 if (tpm_tis_check_request_use_except(s, locty)) { 440 val |= TPM_TIS_ACCESS_PENDING_REQUEST; 441 } 442 val |= !tpm_backend_get_tpm_established_flag(s->be_driver); 443 break; 444 case TPM_TIS_REG_INT_ENABLE: 445 val = tis->loc[locty].inte; 446 break; 447 case TPM_TIS_REG_INT_VECTOR: 448 val = tis->irq_num; 449 break; 450 case TPM_TIS_REG_INT_STATUS: 451 val = tis->loc[locty].ints; 452 break; 453 case TPM_TIS_REG_INTF_CAPABILITY: 454 val = TPM_TIS_CAPABILITIES_SUPPORTED; 455 break; 456 case TPM_TIS_REG_STS: 457 if (tis->active_locty == locty) { 458 if ((tis->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) { 459 val = TPM_TIS_BURST_COUNT( 460 tpm_tis_get_size_from_buffer(&tis->loc[locty].r_buffer) 461 - tis->loc[locty].r_offset) | tis->loc[locty].sts; 462 } else { 463 avail = tis->loc[locty].w_buffer.size 464 - tis->loc[locty].w_offset; 465 /* 466 * byte-sized reads should not return 0x00 for 0x100 467 * available bytes. 468 */ 469 if (size == 1 && avail > 0xff) { 470 avail = 0xff; 471 } 472 val = TPM_TIS_BURST_COUNT(avail) | tis->loc[locty].sts; 473 } 474 } 475 break; 476 case TPM_TIS_REG_DATA_FIFO: 477 if (tis->active_locty == locty) { 478 switch (tis->loc[locty].state) { 479 case TPM_TIS_STATE_COMPLETION: 480 val = tpm_tis_data_read(s, locty); 481 break; 482 default: 483 val = TPM_TIS_NO_DATA_BYTE; 484 break; 485 } 486 } 487 break; 488 case TPM_TIS_REG_DID_VID: 489 val = (TPM_TIS_TPM_DID << 16) | TPM_TIS_TPM_VID; 490 break; 491 case TPM_TIS_REG_RID: 492 val = TPM_TIS_TPM_RID; 493 break; 494 #ifdef DEBUG_TIS 495 case TPM_TIS_REG_DEBUG: 496 tpm_tis_dump_state(opaque, addr); 497 break; 498 #endif 499 } 500 501 if (shift) { 502 val >>= shift; 503 } 504 505 DPRINTF("tpm_tis: read.%u(%08x) = %08x\n", size, (int)addr, (uint32_t)val); 506 507 return val; 508 } 509 510 /* 511 * Write a value to a register of the TIS interface 512 * See specs pages 33-63 for description of the registers 513 */ 514 static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr, 515 uint64_t val, unsigned size, 516 bool hw_access) 517 { 518 TPMState *s = opaque; 519 TPMTISEmuState *tis = &s->s.tis; 520 uint16_t off = addr & 0xfff; 521 uint8_t locty = tpm_tis_locality_from_addr(addr); 522 uint8_t active_locty, l; 523 int c, set_new_locty = 1; 524 uint16_t len; 525 526 DPRINTF("tpm_tis: write.%u(%08x) = %08x\n", size, (int)addr, (uint32_t)val); 527 528 if (locty == 4 && !hw_access) { 529 DPRINTF("tpm_tis: Access to locality 4 only allowed from hardware\n"); 530 return; 531 } 532 533 if (tpm_backend_had_startup_error(s->be_driver)) { 534 return; 535 } 536 537 switch (off) { 538 case TPM_TIS_REG_ACCESS: 539 540 if ((val & TPM_TIS_ACCESS_SEIZE)) { 541 val &= ~(TPM_TIS_ACCESS_REQUEST_USE | 542 TPM_TIS_ACCESS_ACTIVE_LOCALITY); 543 } 544 545 active_locty = tis->active_locty; 546 547 if ((val & TPM_TIS_ACCESS_ACTIVE_LOCALITY)) { 548 /* give up locality if currently owned */ 549 if (tis->active_locty == locty) { 550 DPRINTF("tpm_tis: Releasing locality %d\n", locty); 551 552 uint8_t newlocty = TPM_TIS_NO_LOCALITY; 553 /* anybody wants the locality ? */ 554 for (c = TPM_TIS_NUM_LOCALITIES - 1; c >= 0; c--) { 555 if ((tis->loc[c].access & TPM_TIS_ACCESS_REQUEST_USE)) { 556 DPRINTF("tpm_tis: Locality %d requests use.\n", c); 557 newlocty = c; 558 break; 559 } 560 } 561 DPRINTF("tpm_tis: TPM_TIS_ACCESS_ACTIVE_LOCALITY: " 562 "Next active locality: %d\n", 563 newlocty); 564 565 if (TPM_TIS_IS_VALID_LOCTY(newlocty)) { 566 set_new_locty = 0; 567 tpm_tis_prep_abort(s, locty, newlocty); 568 } else { 569 active_locty = TPM_TIS_NO_LOCALITY; 570 } 571 } else { 572 /* not currently the owner; clear a pending request */ 573 tis->loc[locty].access &= ~TPM_TIS_ACCESS_REQUEST_USE; 574 } 575 } 576 577 if ((val & TPM_TIS_ACCESS_BEEN_SEIZED)) { 578 tis->loc[locty].access &= ~TPM_TIS_ACCESS_BEEN_SEIZED; 579 } 580 581 if ((val & TPM_TIS_ACCESS_SEIZE)) { 582 /* 583 * allow seize if a locality is active and the requesting 584 * locality is higher than the one that's active 585 * OR 586 * allow seize for requesting locality if no locality is 587 * active 588 */ 589 while ((TPM_TIS_IS_VALID_LOCTY(tis->active_locty) && 590 locty > tis->active_locty) || 591 !TPM_TIS_IS_VALID_LOCTY(tis->active_locty)) { 592 bool higher_seize = FALSE; 593 594 /* already a pending SEIZE ? */ 595 if ((tis->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) { 596 break; 597 } 598 599 /* check for ongoing seize by a higher locality */ 600 for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) { 601 if ((tis->loc[l].access & TPM_TIS_ACCESS_SEIZE)) { 602 higher_seize = TRUE; 603 break; 604 } 605 } 606 607 if (higher_seize) { 608 break; 609 } 610 611 /* cancel any seize by a lower locality */ 612 for (l = 0; l < locty - 1; l++) { 613 tis->loc[l].access &= ~TPM_TIS_ACCESS_SEIZE; 614 } 615 616 tis->loc[locty].access |= TPM_TIS_ACCESS_SEIZE; 617 DPRINTF("tpm_tis: TPM_TIS_ACCESS_SEIZE: " 618 "Locality %d seized from locality %d\n", 619 locty, tis->active_locty); 620 DPRINTF("tpm_tis: TPM_TIS_ACCESS_SEIZE: Initiating abort.\n"); 621 set_new_locty = 0; 622 tpm_tis_prep_abort(s, tis->active_locty, locty); 623 break; 624 } 625 } 626 627 if ((val & TPM_TIS_ACCESS_REQUEST_USE)) { 628 if (tis->active_locty != locty) { 629 if (TPM_TIS_IS_VALID_LOCTY(tis->active_locty)) { 630 tis->loc[locty].access |= TPM_TIS_ACCESS_REQUEST_USE; 631 } else { 632 /* no locality active -> make this one active now */ 633 active_locty = locty; 634 } 635 } 636 } 637 638 if (set_new_locty) { 639 tpm_tis_new_active_locality(s, active_locty); 640 } 641 642 break; 643 case TPM_TIS_REG_INT_ENABLE: 644 if (tis->active_locty != locty) { 645 break; 646 } 647 648 tis->loc[locty].inte = (val & (TPM_TIS_INT_ENABLED | 649 TPM_TIS_INT_POLARITY_MASK | 650 TPM_TIS_INTERRUPTS_SUPPORTED)); 651 break; 652 case TPM_TIS_REG_INT_VECTOR: 653 /* hard wired -- ignore */ 654 break; 655 case TPM_TIS_REG_INT_STATUS: 656 if (tis->active_locty != locty) { 657 break; 658 } 659 660 /* clearing of interrupt flags */ 661 if (((val & TPM_TIS_INTERRUPTS_SUPPORTED)) && 662 (tis->loc[locty].ints & TPM_TIS_INTERRUPTS_SUPPORTED)) { 663 tis->loc[locty].ints &= ~val; 664 if (tis->loc[locty].ints == 0) { 665 qemu_irq_lower(tis->irq); 666 DPRINTF("tpm_tis: Lowering IRQ\n"); 667 } 668 } 669 tis->loc[locty].ints &= ~(val & TPM_TIS_INTERRUPTS_SUPPORTED); 670 break; 671 case TPM_TIS_REG_STS: 672 if (tis->active_locty != locty) { 673 break; 674 } 675 676 val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO | 677 TPM_TIS_STS_RESPONSE_RETRY); 678 679 if (val == TPM_TIS_STS_COMMAND_READY) { 680 switch (tis->loc[locty].state) { 681 682 case TPM_TIS_STATE_READY: 683 tis->loc[locty].w_offset = 0; 684 tis->loc[locty].r_offset = 0; 685 break; 686 687 case TPM_TIS_STATE_IDLE: 688 tis->loc[locty].sts = TPM_TIS_STS_COMMAND_READY; 689 tis->loc[locty].state = TPM_TIS_STATE_READY; 690 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY); 691 break; 692 693 case TPM_TIS_STATE_EXECUTION: 694 case TPM_TIS_STATE_RECEPTION: 695 /* abort currently running command */ 696 DPRINTF("tpm_tis: %s: Initiating abort.\n", 697 __func__); 698 tpm_tis_prep_abort(s, locty, locty); 699 break; 700 701 case TPM_TIS_STATE_COMPLETION: 702 tis->loc[locty].w_offset = 0; 703 tis->loc[locty].r_offset = 0; 704 /* shortcut to ready state with C/R set */ 705 tis->loc[locty].state = TPM_TIS_STATE_READY; 706 if (!(tis->loc[locty].sts & TPM_TIS_STS_COMMAND_READY)) { 707 tis->loc[locty].sts = TPM_TIS_STS_COMMAND_READY; 708 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY); 709 } 710 tis->loc[locty].sts &= ~(TPM_TIS_STS_DATA_AVAILABLE); 711 break; 712 713 } 714 } else if (val == TPM_TIS_STS_TPM_GO) { 715 switch (tis->loc[locty].state) { 716 case TPM_TIS_STATE_RECEPTION: 717 if ((tis->loc[locty].sts & TPM_TIS_STS_EXPECT) == 0) { 718 tpm_tis_tpm_send(s, locty); 719 } 720 break; 721 default: 722 /* ignore */ 723 break; 724 } 725 } else if (val == TPM_TIS_STS_RESPONSE_RETRY) { 726 switch (tis->loc[locty].state) { 727 case TPM_TIS_STATE_COMPLETION: 728 tis->loc[locty].r_offset = 0; 729 tis->loc[locty].sts = TPM_TIS_STS_VALID | 730 TPM_TIS_STS_DATA_AVAILABLE; 731 break; 732 default: 733 /* ignore */ 734 break; 735 } 736 } 737 break; 738 case TPM_TIS_REG_DATA_FIFO: 739 /* data fifo */ 740 if (tis->active_locty != locty) { 741 break; 742 } 743 744 if (tis->loc[locty].state == TPM_TIS_STATE_IDLE || 745 tis->loc[locty].state == TPM_TIS_STATE_EXECUTION || 746 tis->loc[locty].state == TPM_TIS_STATE_COMPLETION) { 747 /* drop the byte */ 748 } else { 749 DPRINTF("tpm_tis: Byte to send to TPM: %02x\n", (uint8_t)val); 750 if (tis->loc[locty].state == TPM_TIS_STATE_READY) { 751 tis->loc[locty].state = TPM_TIS_STATE_RECEPTION; 752 tis->loc[locty].sts = TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID; 753 } 754 755 if ((tis->loc[locty].sts & TPM_TIS_STS_EXPECT)) { 756 if (tis->loc[locty].w_offset < tis->loc[locty].w_buffer.size) { 757 tis->loc[locty].w_buffer. 758 buffer[tis->loc[locty].w_offset++] = (uint8_t)val; 759 } else { 760 tis->loc[locty].sts = TPM_TIS_STS_VALID; 761 } 762 } 763 764 /* check for complete packet */ 765 if (tis->loc[locty].w_offset > 5 && 766 (tis->loc[locty].sts & TPM_TIS_STS_EXPECT)) { 767 /* we have a packet length - see if we have all of it */ 768 #ifdef RAISE_STS_IRQ 769 bool needIrq = !(tis->loc[locty].sts & TPM_TIS_STS_VALID); 770 #endif 771 len = tpm_tis_get_size_from_buffer(&tis->loc[locty].w_buffer); 772 if (len > tis->loc[locty].w_offset) { 773 tis->loc[locty].sts = TPM_TIS_STS_EXPECT | 774 TPM_TIS_STS_VALID; 775 } else { 776 /* packet complete */ 777 tis->loc[locty].sts = TPM_TIS_STS_VALID; 778 } 779 #ifdef RAISE_STS_IRQ 780 if (needIrq) { 781 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID); 782 } 783 #endif 784 } 785 } 786 break; 787 } 788 } 789 790 static void tpm_tis_mmio_write(void *opaque, hwaddr addr, 791 uint64_t val, unsigned size) 792 { 793 return tpm_tis_mmio_write_intern(opaque, addr, val, size, false); 794 } 795 796 static const MemoryRegionOps tpm_tis_memory_ops = { 797 .read = tpm_tis_mmio_read, 798 .write = tpm_tis_mmio_write, 799 .endianness = DEVICE_LITTLE_ENDIAN, 800 .valid = { 801 .min_access_size = 1, 802 .max_access_size = 4, 803 }, 804 }; 805 806 static int tpm_tis_do_startup_tpm(TPMState *s) 807 { 808 return tpm_backend_startup_tpm(s->be_driver); 809 } 810 811 /* 812 * This function is called when the machine starts, resets or due to 813 * S3 resume. 814 */ 815 static void tpm_tis_reset(DeviceState *dev) 816 { 817 TPMState *s = TPM(dev); 818 TPMTISEmuState *tis = &s->s.tis; 819 int c; 820 821 tpm_backend_reset(s->be_driver); 822 823 tis->active_locty = TPM_TIS_NO_LOCALITY; 824 tis->next_locty = TPM_TIS_NO_LOCALITY; 825 tis->aborting_locty = TPM_TIS_NO_LOCALITY; 826 827 for (c = 0; c < TPM_TIS_NUM_LOCALITIES; c++) { 828 tis->loc[c].access = TPM_TIS_ACCESS_TPM_REG_VALID_STS; 829 tis->loc[c].sts = 0; 830 tis->loc[c].inte = TPM_TIS_INT_POLARITY_LOW_LEVEL; 831 tis->loc[c].ints = 0; 832 tis->loc[c].state = TPM_TIS_STATE_IDLE; 833 834 tis->loc[c].w_offset = 0; 835 tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].w_buffer); 836 tis->loc[c].r_offset = 0; 837 tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].r_buffer); 838 } 839 840 tpm_tis_do_startup_tpm(s); 841 } 842 843 static const VMStateDescription vmstate_tpm_tis = { 844 .name = "tpm", 845 .unmigratable = 1, 846 }; 847 848 static Property tpm_tis_properties[] = { 849 DEFINE_PROP_UINT32("irq", TPMState, 850 s.tis.irq_num, TPM_TIS_IRQ), 851 DEFINE_PROP_STRING("tpmdev", TPMState, backend), 852 DEFINE_PROP_END_OF_LIST(), 853 }; 854 855 static void tpm_tis_realizefn(DeviceState *dev, Error **errp) 856 { 857 TPMState *s = TPM(dev); 858 TPMTISEmuState *tis = &s->s.tis; 859 860 s->be_driver = qemu_find_tpm(s->backend); 861 if (!s->be_driver) { 862 error_setg(errp, "tpm_tis: backend driver with id %s could not be " 863 "found", s->backend); 864 return; 865 } 866 867 s->be_driver->fe_model = TPM_MODEL_TPM_TIS; 868 869 if (tpm_backend_init(s->be_driver, s, tpm_tis_receive_cb)) { 870 error_setg(errp, "tpm_tis: backend driver with id %s could not be " 871 "initialized", s->backend); 872 return; 873 } 874 875 if (tis->irq_num > 15) { 876 error_setg(errp, "tpm_tis: IRQ %d for TPM TIS is outside valid range " 877 "of 0 to 15.\n", tis->irq_num); 878 return; 879 } 880 881 tis->bh = qemu_bh_new(tpm_tis_receive_bh, s); 882 883 isa_init_irq(&s->busdev, &tis->irq, tis->irq_num); 884 } 885 886 static void tpm_tis_initfn(Object *obj) 887 { 888 ISADevice *dev = ISA_DEVICE(obj); 889 TPMState *s = TPM(obj); 890 891 memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops, 892 s, "tpm-tis-mmio", 893 TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT); 894 memory_region_add_subregion(isa_address_space(dev), TPM_TIS_ADDR_BASE, 895 &s->mmio); 896 } 897 898 static void tpm_tis_uninitfn(Object *obj) 899 { 900 TPMState *s = TPM(obj); 901 902 memory_region_del_subregion(get_system_memory(), &s->mmio); 903 memory_region_destroy(&s->mmio); 904 } 905 906 static void tpm_tis_class_init(ObjectClass *klass, void *data) 907 { 908 DeviceClass *dc = DEVICE_CLASS(klass); 909 910 dc->realize = tpm_tis_realizefn; 911 dc->props = tpm_tis_properties; 912 dc->reset = tpm_tis_reset; 913 dc->vmsd = &vmstate_tpm_tis; 914 } 915 916 static const TypeInfo tpm_tis_info = { 917 .name = TYPE_TPM_TIS, 918 .parent = TYPE_ISA_DEVICE, 919 .instance_size = sizeof(TPMState), 920 .instance_init = tpm_tis_initfn, 921 .instance_finalize = tpm_tis_uninitfn, 922 .class_init = tpm_tis_class_init, 923 }; 924 925 static void tpm_tis_register(void) 926 { 927 type_register_static(&tpm_tis_info); 928 tpm_register_model(TPM_MODEL_TPM_TIS); 929 } 930 931 type_init(tpm_tis_register) 932