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