]> Git Repo - qemu.git/blob - hw/tpm/tpm_tis.c
tpm: print buffers received from TPM when debugging
[qemu.git] / hw / tpm / tpm_tis.c
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 <[email protected]>
8  *  David Safford <[email protected]>
9  *
10  * Xen 4 support: Andrease Niederl <[email protected]>
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     tpm_tis_show_buffer(&s->loc[locty].r_buffer, "tpm_tis: From TPM");
426
427     if (TPM_TIS_IS_VALID_LOCTY(s->next_locty)) {
428         tpm_tis_abort(s, locty);
429     }
430
431     tpm_tis_raise_irq(s, locty,
432                       TPM_TIS_INT_DATA_AVAILABLE | TPM_TIS_INT_STS_VALID);
433 }
434
435 static void tpm_tis_request_completed(TPMIf *ti)
436 {
437     TPMState *s = TPM(ti);
438
439     bool is_selftest_done = s->cmd.selftest_done;
440     uint8_t locty = s->cmd.locty;
441     uint8_t l;
442
443     if (is_selftest_done) {
444         for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
445             s->loc[locty].sts |= TPM_TIS_STS_SELFTEST_DONE;
446         }
447     }
448
449     qemu_bh_schedule(s->bh);
450 }
451
452 /*
453  * Read a byte of response data
454  */
455 static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty)
456 {
457     uint32_t ret = TPM_TIS_NO_DATA_BYTE;
458     uint16_t len;
459
460     if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
461         len = tpm_tis_get_size_from_buffer(&s->loc[locty].r_buffer);
462
463         ret = s->loc[locty].r_buffer.buffer[s->loc[locty].r_offset++];
464         if (s->loc[locty].r_offset >= len) {
465             /* got last byte */
466             tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID);
467             tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID);
468         }
469         DPRINTF("tpm_tis: tpm_tis_data_read byte 0x%02x   [%d]\n",
470                 ret, s->loc[locty].r_offset - 1);
471     }
472
473     return ret;
474 }
475
476 #ifdef DEBUG_TIS
477 static void tpm_tis_dump_state(void *opaque, hwaddr addr)
478 {
479     static const unsigned regs[] = {
480         TPM_TIS_REG_ACCESS,
481         TPM_TIS_REG_INT_ENABLE,
482         TPM_TIS_REG_INT_VECTOR,
483         TPM_TIS_REG_INT_STATUS,
484         TPM_TIS_REG_INTF_CAPABILITY,
485         TPM_TIS_REG_STS,
486         TPM_TIS_REG_DID_VID,
487         TPM_TIS_REG_RID,
488         0xfff};
489     int idx;
490     uint8_t locty = tpm_tis_locality_from_addr(addr);
491     hwaddr base = addr & ~0xfff;
492     TPMState *s = opaque;
493
494     DPRINTF("tpm_tis: active locality      : %d\n"
495             "tpm_tis: state of locality %d : %d\n"
496             "tpm_tis: register dump:\n",
497             s->active_locty,
498             locty, s->loc[locty].state);
499
500     for (idx = 0; regs[idx] != 0xfff; idx++) {
501         DPRINTF("tpm_tis: 0x%04x : 0x%08x\n", regs[idx],
502                 (int)tpm_tis_mmio_read(opaque, base + regs[idx], 4));
503     }
504
505     DPRINTF("tpm_tis: read offset   : %d\n"
506             "tpm_tis: result buffer : ",
507             s->loc[locty].r_offset);
508     for (idx = 0;
509          idx < tpm_tis_get_size_from_buffer(&s->loc[locty].r_buffer);
510          idx++) {
511         DPRINTF("%c%02x%s",
512                 s->loc[locty].r_offset == idx ? '>' : ' ',
513                 s->loc[locty].r_buffer.buffer[idx],
514                 ((idx & 0xf) == 0xf) ? "\ntpm_tis:                 " : "");
515     }
516     DPRINTF("\n"
517             "tpm_tis: write offset  : %d\n"
518             "tpm_tis: request buffer: ",
519             s->loc[locty].w_offset);
520     for (idx = 0;
521          idx < tpm_tis_get_size_from_buffer(&s->loc[locty].w_buffer);
522          idx++) {
523         DPRINTF("%c%02x%s",
524                 s->loc[locty].w_offset == idx ? '>' : ' ',
525                 s->loc[locty].w_buffer.buffer[idx],
526                 ((idx & 0xf) == 0xf) ? "\ntpm_tis:                 " : "");
527     }
528     DPRINTF("\n");
529 }
530 #endif
531
532 /*
533  * Read a register of the TIS interface
534  * See specs pages 33-63 for description of the registers
535  */
536 static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
537                                   unsigned size)
538 {
539     TPMState *s = opaque;
540     uint16_t offset = addr & 0xffc;
541     uint8_t shift = (addr & 0x3) * 8;
542     uint32_t val = 0xffffffff;
543     uint8_t locty = tpm_tis_locality_from_addr(addr);
544     uint32_t avail;
545     uint8_t v;
546
547     if (tpm_backend_had_startup_error(s->be_driver)) {
548         return val;
549     }
550
551     switch (offset) {
552     case TPM_TIS_REG_ACCESS:
553         /* never show the SEIZE flag even though we use it internally */
554         val = s->loc[locty].access & ~TPM_TIS_ACCESS_SEIZE;
555         /* the pending flag is always calculated */
556         if (tpm_tis_check_request_use_except(s, locty)) {
557             val |= TPM_TIS_ACCESS_PENDING_REQUEST;
558         }
559         val |= !tpm_backend_get_tpm_established_flag(s->be_driver);
560         break;
561     case TPM_TIS_REG_INT_ENABLE:
562         val = s->loc[locty].inte;
563         break;
564     case TPM_TIS_REG_INT_VECTOR:
565         val = s->irq_num;
566         break;
567     case TPM_TIS_REG_INT_STATUS:
568         val = s->loc[locty].ints;
569         break;
570     case TPM_TIS_REG_INTF_CAPABILITY:
571         switch (s->be_tpm_version) {
572         case TPM_VERSION_UNSPEC:
573             val = 0;
574             break;
575         case TPM_VERSION_1_2:
576             val = TPM_TIS_CAPABILITIES_SUPPORTED1_3;
577             break;
578         case TPM_VERSION_2_0:
579             val = TPM_TIS_CAPABILITIES_SUPPORTED2_0;
580             break;
581         }
582         break;
583     case TPM_TIS_REG_STS:
584         if (s->active_locty == locty) {
585             if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
586                 val = TPM_TIS_BURST_COUNT(
587                        tpm_tis_get_size_from_buffer(&s->loc[locty].r_buffer)
588                        - s->loc[locty].r_offset) | s->loc[locty].sts;
589             } else {
590                 avail = s->loc[locty].w_buffer.size
591                         - s->loc[locty].w_offset;
592                 /*
593                  * byte-sized reads should not return 0x00 for 0x100
594                  * available bytes.
595                  */
596                 if (size == 1 && avail > 0xff) {
597                     avail = 0xff;
598                 }
599                 val = TPM_TIS_BURST_COUNT(avail) | s->loc[locty].sts;
600             }
601         }
602         break;
603     case TPM_TIS_REG_DATA_FIFO:
604     case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END:
605         if (s->active_locty == locty) {
606             if (size > 4 - (addr & 0x3)) {
607                 /* prevent access beyond FIFO */
608                 size = 4 - (addr & 0x3);
609             }
610             val = 0;
611             shift = 0;
612             while (size > 0) {
613                 switch (s->loc[locty].state) {
614                 case TPM_TIS_STATE_COMPLETION:
615                     v = tpm_tis_data_read(s, locty);
616                     break;
617                 default:
618                     v = TPM_TIS_NO_DATA_BYTE;
619                     break;
620                 }
621                 val |= (v << shift);
622                 shift += 8;
623                 size--;
624             }
625             shift = 0; /* no more adjustments */
626         }
627         break;
628     case TPM_TIS_REG_INTERFACE_ID:
629         val = s->loc[locty].iface_id;
630         break;
631     case TPM_TIS_REG_DID_VID:
632         val = (TPM_TIS_TPM_DID << 16) | TPM_TIS_TPM_VID;
633         break;
634     case TPM_TIS_REG_RID:
635         val = TPM_TIS_TPM_RID;
636         break;
637 #ifdef DEBUG_TIS
638     case TPM_TIS_REG_DEBUG:
639         tpm_tis_dump_state(opaque, addr);
640         break;
641 #endif
642     }
643
644     if (shift) {
645         val >>= shift;
646     }
647
648     DPRINTF("tpm_tis:  read.%u(%08x) = %08x\n", size, (int)addr, (int)val);
649
650     return val;
651 }
652
653 /*
654  * Write a value to a register of the TIS interface
655  * See specs pages 33-63 for description of the registers
656  */
657 static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
658                                uint64_t val, unsigned size)
659 {
660     TPMState *s = opaque;
661     uint16_t off = addr & 0xffc;
662     uint8_t shift = (addr & 0x3) * 8;
663     uint8_t locty = tpm_tis_locality_from_addr(addr);
664     uint8_t active_locty, l;
665     int c, set_new_locty = 1;
666     uint16_t len;
667     uint32_t mask = (size == 1) ? 0xff : ((size == 2) ? 0xffff : ~0);
668
669     DPRINTF("tpm_tis: write.%u(%08x) = %08x\n", size, (int)addr, (int)val);
670
671     if (locty == 4) {
672         DPRINTF("tpm_tis: Access to locality 4 only allowed from hardware\n");
673         return;
674     }
675
676     if (tpm_backend_had_startup_error(s->be_driver)) {
677         return;
678     }
679
680     val &= mask;
681
682     if (shift) {
683         val <<= shift;
684         mask <<= shift;
685     }
686
687     mask ^= 0xffffffff;
688
689     switch (off) {
690     case TPM_TIS_REG_ACCESS:
691
692         if ((val & TPM_TIS_ACCESS_SEIZE)) {
693             val &= ~(TPM_TIS_ACCESS_REQUEST_USE |
694                      TPM_TIS_ACCESS_ACTIVE_LOCALITY);
695         }
696
697         active_locty = s->active_locty;
698
699         if ((val & TPM_TIS_ACCESS_ACTIVE_LOCALITY)) {
700             /* give up locality if currently owned */
701             if (s->active_locty == locty) {
702                 DPRINTF("tpm_tis: Releasing locality %d\n", locty);
703
704                 uint8_t newlocty = TPM_TIS_NO_LOCALITY;
705                 /* anybody wants the locality ? */
706                 for (c = TPM_TIS_NUM_LOCALITIES - 1; c >= 0; c--) {
707                     if ((s->loc[c].access & TPM_TIS_ACCESS_REQUEST_USE)) {
708                         DPRINTF("tpm_tis: Locality %d requests use.\n", c);
709                         newlocty = c;
710                         break;
711                     }
712                 }
713                 DPRINTF("tpm_tis: TPM_TIS_ACCESS_ACTIVE_LOCALITY: "
714                         "Next active locality: %d\n",
715                         newlocty);
716
717                 if (TPM_TIS_IS_VALID_LOCTY(newlocty)) {
718                     set_new_locty = 0;
719                     tpm_tis_prep_abort(s, locty, newlocty);
720                 } else {
721                     active_locty = TPM_TIS_NO_LOCALITY;
722                 }
723             } else {
724                 /* not currently the owner; clear a pending request */
725                 s->loc[locty].access &= ~TPM_TIS_ACCESS_REQUEST_USE;
726             }
727         }
728
729         if ((val & TPM_TIS_ACCESS_BEEN_SEIZED)) {
730             s->loc[locty].access &= ~TPM_TIS_ACCESS_BEEN_SEIZED;
731         }
732
733         if ((val & TPM_TIS_ACCESS_SEIZE)) {
734             /*
735              * allow seize if a locality is active and the requesting
736              * locality is higher than the one that's active
737              * OR
738              * allow seize for requesting locality if no locality is
739              * active
740              */
741             while ((TPM_TIS_IS_VALID_LOCTY(s->active_locty) &&
742                     locty > s->active_locty) ||
743                     !TPM_TIS_IS_VALID_LOCTY(s->active_locty)) {
744                 bool higher_seize = FALSE;
745
746                 /* already a pending SEIZE ? */
747                 if ((s->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) {
748                     break;
749                 }
750
751                 /* check for ongoing seize by a higher locality */
752                 for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) {
753                     if ((s->loc[l].access & TPM_TIS_ACCESS_SEIZE)) {
754                         higher_seize = TRUE;
755                         break;
756                     }
757                 }
758
759                 if (higher_seize) {
760                     break;
761                 }
762
763                 /* cancel any seize by a lower locality */
764                 for (l = 0; l < locty - 1; l++) {
765                     s->loc[l].access &= ~TPM_TIS_ACCESS_SEIZE;
766                 }
767
768                 s->loc[locty].access |= TPM_TIS_ACCESS_SEIZE;
769                 DPRINTF("tpm_tis: TPM_TIS_ACCESS_SEIZE: "
770                         "Locality %d seized from locality %d\n",
771                         locty, s->active_locty);
772                 DPRINTF("tpm_tis: TPM_TIS_ACCESS_SEIZE: Initiating abort.\n");
773                 set_new_locty = 0;
774                 tpm_tis_prep_abort(s, s->active_locty, locty);
775                 break;
776             }
777         }
778
779         if ((val & TPM_TIS_ACCESS_REQUEST_USE)) {
780             if (s->active_locty != locty) {
781                 if (TPM_TIS_IS_VALID_LOCTY(s->active_locty)) {
782                     s->loc[locty].access |= TPM_TIS_ACCESS_REQUEST_USE;
783                 } else {
784                     /* no locality active -> make this one active now */
785                     active_locty = locty;
786                 }
787             }
788         }
789
790         if (set_new_locty) {
791             tpm_tis_new_active_locality(s, active_locty);
792         }
793
794         break;
795     case TPM_TIS_REG_INT_ENABLE:
796         if (s->active_locty != locty) {
797             break;
798         }
799
800         s->loc[locty].inte &= mask;
801         s->loc[locty].inte |= (val & (TPM_TIS_INT_ENABLED |
802                                         TPM_TIS_INT_POLARITY_MASK |
803                                         TPM_TIS_INTERRUPTS_SUPPORTED));
804         break;
805     case TPM_TIS_REG_INT_VECTOR:
806         /* hard wired -- ignore */
807         break;
808     case TPM_TIS_REG_INT_STATUS:
809         if (s->active_locty != locty) {
810             break;
811         }
812
813         /* clearing of interrupt flags */
814         if (((val & TPM_TIS_INTERRUPTS_SUPPORTED)) &&
815             (s->loc[locty].ints & TPM_TIS_INTERRUPTS_SUPPORTED)) {
816             s->loc[locty].ints &= ~val;
817             if (s->loc[locty].ints == 0) {
818                 qemu_irq_lower(s->irq);
819                 DPRINTF("tpm_tis: Lowering IRQ\n");
820             }
821         }
822         s->loc[locty].ints &= ~(val & TPM_TIS_INTERRUPTS_SUPPORTED);
823         break;
824     case TPM_TIS_REG_STS:
825         if (s->active_locty != locty) {
826             break;
827         }
828
829         if (s->be_tpm_version == TPM_VERSION_2_0) {
830             /* some flags that are only supported for TPM 2 */
831             if (val & TPM_TIS_STS_COMMAND_CANCEL) {
832                 if (s->loc[locty].state == TPM_TIS_STATE_EXECUTION) {
833                     /*
834                      * request the backend to cancel. Some backends may not
835                      * support it
836                      */
837                     tpm_backend_cancel_cmd(s->be_driver);
838                 }
839             }
840
841             if (val & TPM_TIS_STS_RESET_ESTABLISHMENT_BIT) {
842                 if (locty == 3 || locty == 4) {
843                     tpm_backend_reset_tpm_established_flag(s->be_driver, locty);
844                 }
845             }
846         }
847
848         val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO |
849                 TPM_TIS_STS_RESPONSE_RETRY);
850
851         if (val == TPM_TIS_STS_COMMAND_READY) {
852             switch (s->loc[locty].state) {
853
854             case TPM_TIS_STATE_READY:
855                 s->loc[locty].w_offset = 0;
856                 s->loc[locty].r_offset = 0;
857             break;
858
859             case TPM_TIS_STATE_IDLE:
860                 tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_COMMAND_READY);
861                 s->loc[locty].state = TPM_TIS_STATE_READY;
862                 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY);
863             break;
864
865             case TPM_TIS_STATE_EXECUTION:
866             case TPM_TIS_STATE_RECEPTION:
867                 /* abort currently running command */
868                 DPRINTF("tpm_tis: %s: Initiating abort.\n",
869                         __func__);
870                 tpm_tis_prep_abort(s, locty, locty);
871             break;
872
873             case TPM_TIS_STATE_COMPLETION:
874                 s->loc[locty].w_offset = 0;
875                 s->loc[locty].r_offset = 0;
876                 /* shortcut to ready state with C/R set */
877                 s->loc[locty].state = TPM_TIS_STATE_READY;
878                 if (!(s->loc[locty].sts & TPM_TIS_STS_COMMAND_READY)) {
879                     tpm_tis_sts_set(&s->loc[locty],
880                                     TPM_TIS_STS_COMMAND_READY);
881                     tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY);
882                 }
883                 s->loc[locty].sts &= ~(TPM_TIS_STS_DATA_AVAILABLE);
884             break;
885
886             }
887         } else if (val == TPM_TIS_STS_TPM_GO) {
888             switch (s->loc[locty].state) {
889             case TPM_TIS_STATE_RECEPTION:
890                 if ((s->loc[locty].sts & TPM_TIS_STS_EXPECT) == 0) {
891                     tpm_tis_tpm_send(s, locty);
892                 }
893                 break;
894             default:
895                 /* ignore */
896                 break;
897             }
898         } else if (val == TPM_TIS_STS_RESPONSE_RETRY) {
899             switch (s->loc[locty].state) {
900             case TPM_TIS_STATE_COMPLETION:
901                 s->loc[locty].r_offset = 0;
902                 tpm_tis_sts_set(&s->loc[locty],
903                                 TPM_TIS_STS_VALID|
904                                 TPM_TIS_STS_DATA_AVAILABLE);
905                 break;
906             default:
907                 /* ignore */
908                 break;
909             }
910         }
911         break;
912     case TPM_TIS_REG_DATA_FIFO:
913     case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END:
914         /* data fifo */
915         if (s->active_locty != locty) {
916             break;
917         }
918
919         if (s->loc[locty].state == TPM_TIS_STATE_IDLE ||
920             s->loc[locty].state == TPM_TIS_STATE_EXECUTION ||
921             s->loc[locty].state == TPM_TIS_STATE_COMPLETION) {
922             /* drop the byte */
923         } else {
924             DPRINTF("tpm_tis: Data to send to TPM: %08x (size=%d)\n",
925                     (int)val, size);
926             if (s->loc[locty].state == TPM_TIS_STATE_READY) {
927                 s->loc[locty].state = TPM_TIS_STATE_RECEPTION;
928                 tpm_tis_sts_set(&s->loc[locty],
929                                 TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);
930             }
931
932             val >>= shift;
933             if (size > 4 - (addr & 0x3)) {
934                 /* prevent access beyond FIFO */
935                 size = 4 - (addr & 0x3);
936             }
937
938             while ((s->loc[locty].sts & TPM_TIS_STS_EXPECT) && size > 0) {
939                 if (s->loc[locty].w_offset < s->loc[locty].w_buffer.size) {
940                     s->loc[locty].w_buffer.
941                         buffer[s->loc[locty].w_offset++] = (uint8_t)val;
942                     val >>= 8;
943                     size--;
944                 } else {
945                     tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID);
946                 }
947             }
948
949             /* check for complete packet */
950             if (s->loc[locty].w_offset > 5 &&
951                 (s->loc[locty].sts & TPM_TIS_STS_EXPECT)) {
952                 /* we have a packet length - see if we have all of it */
953                 bool need_irq = !(s->loc[locty].sts & TPM_TIS_STS_VALID);
954
955                 len = tpm_tis_get_size_from_buffer(&s->loc[locty].w_buffer);
956                 if (len > s->loc[locty].w_offset) {
957                     tpm_tis_sts_set(&s->loc[locty],
958                                     TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);
959                 } else {
960                     /* packet complete */
961                     tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID);
962                 }
963                 if (need_irq) {
964                     tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID);
965                 }
966             }
967         }
968         break;
969     case TPM_TIS_REG_INTERFACE_ID:
970         if (val & TPM_TIS_IFACE_ID_INT_SEL_LOCK) {
971             for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
972                 s->loc[l].iface_id |= TPM_TIS_IFACE_ID_INT_SEL_LOCK;
973             }
974         }
975         break;
976     }
977 }
978
979 static const MemoryRegionOps tpm_tis_memory_ops = {
980     .read = tpm_tis_mmio_read,
981     .write = tpm_tis_mmio_write,
982     .endianness = DEVICE_LITTLE_ENDIAN,
983     .valid = {
984         .min_access_size = 1,
985         .max_access_size = 4,
986     },
987 };
988
989 static int tpm_tis_do_startup_tpm(TPMState *s)
990 {
991     return tpm_backend_startup_tpm(s->be_driver);
992 }
993
994 static void tpm_tis_realloc_buffer(TPMSizedBuffer *sb)
995 {
996     size_t wanted_size = 4096; /* Linux tpm.c buffer size */
997
998     if (sb->size != wanted_size) {
999         sb->buffer = g_realloc(sb->buffer, wanted_size);
1000         sb->size = wanted_size;
1001     }
1002 }
1003
1004 /*
1005  * Get the TPMVersion of the backend device being used
1006  */
1007 TPMVersion tpm_tis_get_tpm_version(Object *obj)
1008 {
1009     TPMState *s = TPM(obj);
1010
1011     return tpm_backend_get_tpm_version(s->be_driver);
1012 }
1013
1014 /*
1015  * This function is called when the machine starts, resets or due to
1016  * S3 resume.
1017  */
1018 static void tpm_tis_reset(DeviceState *dev)
1019 {
1020     TPMState *s = TPM(dev);
1021     int c;
1022
1023     s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);
1024
1025     tpm_backend_reset(s->be_driver);
1026
1027     s->active_locty = TPM_TIS_NO_LOCALITY;
1028     s->next_locty = TPM_TIS_NO_LOCALITY;
1029     s->aborting_locty = TPM_TIS_NO_LOCALITY;
1030
1031     for (c = 0; c < TPM_TIS_NUM_LOCALITIES; c++) {
1032         s->loc[c].access = TPM_TIS_ACCESS_TPM_REG_VALID_STS;
1033         switch (s->be_tpm_version) {
1034         case TPM_VERSION_UNSPEC:
1035             break;
1036         case TPM_VERSION_1_2:
1037             s->loc[c].sts = TPM_TIS_STS_TPM_FAMILY1_2;
1038             s->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3;
1039             break;
1040         case TPM_VERSION_2_0:
1041             s->loc[c].sts = TPM_TIS_STS_TPM_FAMILY2_0;
1042             s->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0;
1043             break;
1044         }
1045         s->loc[c].inte = TPM_TIS_INT_POLARITY_LOW_LEVEL;
1046         s->loc[c].ints = 0;
1047         s->loc[c].state = TPM_TIS_STATE_IDLE;
1048
1049         s->loc[c].w_offset = 0;
1050         tpm_tis_realloc_buffer(&s->loc[c].w_buffer);
1051         s->loc[c].r_offset = 0;
1052         tpm_tis_realloc_buffer(&s->loc[c].r_buffer);
1053     }
1054
1055     tpm_tis_do_startup_tpm(s);
1056 }
1057
1058 static const VMStateDescription vmstate_tpm_tis = {
1059     .name = "tpm",
1060     .unmigratable = 1,
1061 };
1062
1063 static Property tpm_tis_properties[] = {
1064     DEFINE_PROP_UINT32("irq", TPMState, irq_num, TPM_TIS_IRQ),
1065     DEFINE_PROP_STRING("tpmdev", TPMState, backend),
1066     DEFINE_PROP_END_OF_LIST(),
1067 };
1068
1069 static void tpm_tis_realizefn(DeviceState *dev, Error **errp)
1070 {
1071     TPMState *s = TPM(dev);
1072
1073     s->be_driver = qemu_find_tpm(s->backend);
1074     if (!s->be_driver) {
1075         error_setg(errp, "tpm_tis: backend driver with id %s could not be "
1076                    "found", s->backend);
1077         return;
1078     }
1079
1080     s->be_driver->fe_model = TPM_MODEL_TPM_TIS;
1081
1082     if (tpm_backend_init(s->be_driver, s)) {
1083         error_setg(errp, "tpm_tis: backend driver with id %s could not be "
1084                    "initialized", s->backend);
1085         return;
1086     }
1087
1088     if (s->irq_num > 15) {
1089         error_setg(errp, "tpm_tis: IRQ %d for TPM TIS is outside valid range "
1090                    "of 0 to 15", s->irq_num);
1091         return;
1092     }
1093
1094     s->bh = qemu_bh_new(tpm_tis_receive_bh, s);
1095
1096     isa_init_irq(&s->busdev, &s->irq, s->irq_num);
1097
1098     memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
1099                                 TPM_TIS_ADDR_BASE, &s->mmio);
1100 }
1101
1102 static void tpm_tis_initfn(Object *obj)
1103 {
1104     TPMState *s = TPM(obj);
1105
1106     memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops,
1107                           s, "tpm-tis-mmio",
1108                           TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT);
1109 }
1110
1111 static void tpm_tis_class_init(ObjectClass *klass, void *data)
1112 {
1113     DeviceClass *dc = DEVICE_CLASS(klass);
1114     TPMIfClass *tc = TPM_IF_CLASS(klass);
1115
1116     dc->realize = tpm_tis_realizefn;
1117     dc->props = tpm_tis_properties;
1118     dc->reset = tpm_tis_reset;
1119     dc->vmsd  = &vmstate_tpm_tis;
1120     tc->request_completed = tpm_tis_request_completed;
1121 }
1122
1123 static const TypeInfo tpm_tis_info = {
1124     .name = TYPE_TPM_TIS,
1125     .parent = TYPE_ISA_DEVICE,
1126     .instance_size = sizeof(TPMState),
1127     .instance_init = tpm_tis_initfn,
1128     .class_init  = tpm_tis_class_init,
1129     .interfaces = (InterfaceInfo[]) {
1130         { TYPE_TPM_IF },
1131         { }
1132     }
1133 };
1134
1135 static void tpm_tis_register(void)
1136 {
1137     type_register_static(&tpm_tis_info);
1138     tpm_register_model(TPM_MODEL_TPM_TIS);
1139 }
1140
1141 type_init(tpm_tis_register)
This page took 0.091798 seconds and 4 git commands to generate.