ia64/xen-unstable

view tools/ioemu/hw/tpm_tis.c @ 16648:6730dfe7ec69

hvm: Fix TPMD and QEMU connection

In HVM domain, MA_Transmit function in tcgbios sometimes become an
error (TCG_NO_RESPONSE). The cause of the error is not to make
connection of QEMU and TPMD instance within a timeout of MA_Transmit
function.

Before the MA_Transmit function was called, the attached patch
corrected so that connection of QEMU and TPMD might be completed.

Signed-off-by: Kouichi YASAKI <yasaki.kouichi@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Dec 20 10:43:06 2007 +0000 (2007-12-20)
parents 8e9ec8711efa
children c433ebd2a9bb
line source
1 /*
2 * tpm_tis.c - QEMU emulator for a 1.2 TPM with TIS interface
3 *
4 * Copyright (C) 2006 IBM Corporation
5 *
6 * Author: Stefan Berger <stefanb@us.ibm.com>
7 * David Safford <safford@us.ibm.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 *
14 *
15 * Implementation of the TIS interface according to specs at
16 * https://www.trustedcomputinggroup.org/groups/pc_client/TCG_PCClientTPMSpecification_1-20_1-00_FINAL.pdf
17 *
18 */
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/socket.h>
23 #include <sys/un.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include "vl.h"
28 //#define DEBUG_TPM
30 #define TPM_MAX_PKT 4096
32 #define VTPM_BAD_INSTANCE (uint32_t)0xffffffff
34 #define TIS_ADDR_BASE 0xFED40000
36 /* tis registers */
37 #define TPM_REG_ACCESS 0x00
38 #define TPM_REG_INT_ENABLE 0x08
39 #define TPM_REG_INT_VECTOR 0x0c
40 #define TPM_REG_INT_STATUS 0x10
41 #define TPM_REG_INTF_CAPABILITY 0x14
42 #define TPM_REG_STS 0x18
43 #define TPM_REG_DATA_FIFO 0x24
44 #define TPM_REG_DID_VID 0xf00
45 #define TPM_REG_RID 0xf04
47 #define STS_VALID (1 << 7)
48 #define STS_COMMAND_READY (1 << 6)
49 #define STS_TPM_GO (1 << 5)
50 #define STS_DATA_AVAILABLE (1 << 4)
51 #define STS_EXPECT (1 << 3)
52 #define STS_RESPONSE_RETRY (1 << 1)
54 #define ACCESS_TPM_REG_VALID_STS (1 << 7)
55 #define ACCESS_ACTIVE_LOCALITY (1 << 5)
56 #define ACCESS_BEEN_SEIZED (1 << 4)
57 #define ACCESS_SEIZE (1 << 3)
58 #define ACCESS_PENDING_REQUEST (1 << 2)
59 #define ACCESS_REQUEST_USE (1 << 1)
60 #define ACCESS_TPM_ESTABLISHMENT (1 << 0)
62 #define INT_ENABLED (1 << 31)
63 #define INT_DATA_AVAILABLE (1 << 0)
64 #define INT_LOCALITY_CHANGED (1 << 2)
65 #define INT_COMMAND_READY (1 << 7)
67 #define INTERRUPTS_SUPPORTED (INT_LOCALITY_CHANGED | \
68 INT_DATA_AVAILABLE | \
69 INT_COMMAND_READY)
70 #define CAPABILITIES_SUPPORTED ((1 << 4) | \
71 INTERRUPTS_SUPPORTED)
73 enum {
74 STATE_IDLE = 0,
75 STATE_READY,
76 STATE_COMPLETION,
77 STATE_EXECUTION,
78 STATE_RECEPTION
79 };
81 #define NUM_LOCALITIES 5
82 #define NO_LOCALITY 0xff
84 #define IS_VALID_LOC(x) ((x) < NUM_LOCALITIES)
86 #define TPM_DID 0x0001
87 #define TPM_VID 0x0001
88 #define TPM_RID 0x0001
90 /* if the connection to the vTPM should be closed after a successfully
91 received response; set to '0' to allow keeping the connection */
92 #define FORCE_CLOSE 0
94 /* local data structures */
96 typedef struct TPMTx {
97 int fd[2];
98 } tpmTx;
100 typedef struct TPMBuffer {
101 uint8_t instance[4]; /* instance number in network byte order */
102 uint8_t buf[TPM_MAX_PKT];
103 } __attribute__((packed)) tpmBuffer;
105 /* locality data */
106 typedef struct TPMLocal {
107 uint32_t state;
108 uint8_t access;
109 uint8_t sts;
110 uint32_t inte;
111 uint32_t ints;
112 } tpmLoc;
114 /* overall state of the TPM interface; 's' marks as save upon suspension */
115 typedef struct TPMState {
116 uint32_t offset; /* s */
117 tpmBuffer buffer; /* s */
118 uint8_t active_loc; /* s */
119 uint8_t aborting_locty;
120 uint8_t next_locty;
121 uint8_t irq_pending; /* s */
122 tpmLoc loc[NUM_LOCALITIES]; /* s */
123 QEMUTimer *poll_timer;
124 SetIRQFunc *set_irq;
125 void *irq_opaque;
126 int irq;
127 int poll_attempts;
128 uint32_t vtpm_instance; /* vtpm inst. number; determined from xenstore*/
129 int Transmitlayer;
130 tpmTx tpmTx;
131 } tpmState;
134 /* local prototypes */
135 static int TPM_Send(tpmState *s, tpmBuffer *buffer, uint8_t locty, char *msg);
136 static int TPM_Receive(tpmState *s, tpmBuffer *buffer);
137 static uint32_t vtpm_instance_from_xenstore(void);
138 static void tis_poll_timer(void *opaque);
139 static void tis_prep_next_interrupt(tpmState *s);
140 static void tis_raise_irq(tpmState *s, uint8_t locty, uint32_t irqmask);
141 static void close_vtpm_channel(tpmState *s, int force);
142 static void open_vtpm_channel(tpmState *s);
143 static void tis_attempt_receive(tpmState *s, uint8_t locty);
145 /* transport layer functions: local sockets */
146 static int create_local_socket(tpmState *s, uint32_t vtpm_instance);
147 static int write_local_socket(tpmState *s, const tpmBuffer *);
148 static int read_local_socket(tpmState *s, tpmBuffer *);
149 static int close_local_socket(tpmState *s, int force);
150 static int has_channel_local_socket(tpmState *s);
151 #define LOCAL_SOCKET_PATH "/var/vtpm/socks/%d.socket"
154 #define NUM_TRANSPORTS 1
156 struct vTPM_transmit {
157 int (*open_fn) (tpmState *s, uint32_t vtpm_instance);
158 int (*write_fn) (tpmState *s, const tpmBuffer *);
159 int (*read_fn) (tpmState *s, tpmBuffer *);
160 int (*close_fn) (tpmState *s, int);
161 int (*has_channel) (tpmState *s);
162 } vTPMTransmit[NUM_TRANSPORTS] = {
163 { .open_fn = create_local_socket,
164 .write_fn = write_local_socket,
165 .read_fn = read_local_socket,
166 .close_fn = close_local_socket,
167 .has_channel = has_channel_local_socket,
168 }
169 };
172 #define IS_COMM_WITH_VTPM(s) \
173 ((s)->Transmitlayer >= 0 && \
174 vTPMTransmit[(s)->Transmitlayer].has_channel(s))
177 /**********************************************************************
178 helper functions
179 *********************************************************************/
181 static inline uint32_t tpm_get_size_from_buffer(const uint8_t *buffer)
182 {
183 uint32_t len = (buffer[4] << 8) + buffer[5];
184 return len;
185 }
187 static inline void tpm_initialize_instance(tpmState *s, uint32_t instance)
188 {
189 s->buffer.instance[0] = (instance >> 24) & 0xff;
190 s->buffer.instance[1] = (instance >> 16) & 0xff;
191 s->buffer.instance[2] = (instance >> 8) & 0xff;
192 s->buffer.instance[3] = (instance >> 0) & 0xff;
193 }
195 /*
196 * open communication channel with a vTPM
197 */
198 static void open_vtpm_channel(tpmState *s)
199 {
200 int idx;
201 /* search a usable transmit layer */
202 for (idx = 0; idx < NUM_TRANSPORTS; idx++) {
203 if (1 == vTPMTransmit[idx].open_fn(s, s->vtpm_instance)) {
204 /* found one */
205 s->Transmitlayer = idx;
206 break;
207 }
208 }
209 }
211 /*
212 * close the communication channel with the vTPM
213 */
214 static inline void close_vtpm_channel(tpmState *s, int force)
215 {
216 if (1 == vTPMTransmit[s->Transmitlayer].close_fn(s, force)) {
217 s->Transmitlayer = -1;
218 }
219 }
221 static inline uint8_t locality_from_addr(target_phys_addr_t addr)
222 {
223 return (uint8_t)((addr >> 12) & 0x7);
224 }
227 /**********************************************************************
228 low-level transmission layer methods
229 *********************************************************************/
231 /*
232 * the 'open' method that creates the filedescriptor for communicating
233 * only one is needed for reading and writing
234 */
235 static int create_local_socket(tpmState *s, uint32_t vtpm_instance)
236 {
237 int success = 1;
238 if (s->tpmTx.fd[0] < 0) {
239 s->tpmTx.fd[0] = socket(PF_LOCAL, SOCK_STREAM, 0);
241 #ifdef DEBUG_TPM
242 fprintf(logfile," SOCKET FD %d errno %d \n", s->tpmTx.fd[0], errno );
243 #endif
244 if (has_channel_local_socket(s)) {
245 int ret;
246 struct sockaddr_un addr;
247 memset(&addr, 0x0, sizeof(addr));
248 addr.sun_family = AF_LOCAL;
249 snprintf(addr.sun_path, sizeof(addr.sun_path)-1,
250 LOCAL_SOCKET_PATH, (uint32_t) vtpm_instance);
251 #ifdef DEBUG_TPM
252 fprintf(logfile," SOCKET NAME %s \n", addr.sun_path );
253 #endif
255 if ((ret = connect(s->tpmTx.fd[0], (struct sockaddr *)&addr,
256 sizeof(addr))) != 0) {
257 close_local_socket(s, 1);
258 #ifdef DEBUG_TPM
259 fprintf(logfile," RET %d errno %d\n", ret, errno );
260 #endif
261 success = 0;
262 } else {
263 /* put filedescriptor in non-blocking mode for polling */
264 #ifdef DEBUG_TPM
265 fprintf(logfile," put filedescriptor in non-blocking mode "
266 "for polling \n");
267 #endif
268 int flags = fcntl(s->tpmTx.fd[0], F_GETFL);
269 fcntl(s->tpmTx.fd[0], F_SETFL, flags | O_NONBLOCK);
270 }
271 #ifdef DEBUG_TPM
272 if (success)
273 fprintf(logfile,"Successfully connected using local socket "
274 LOCAL_SOCKET_PATH ".\n");
275 else
276 fprintf(logfile,"Could not connect to local socket "
277 LOCAL_SOCKET_PATH ".\n");
278 #endif
279 } else {
280 success = 0;
281 }
282 }
283 return success;
284 }
286 /*
287 * the 'write' method for sending requests to the vTPM
288 * four bytes with the vTPM instance number are prepended to each request
289 * the locality in which the command was sent is transmitted in the
290 * highest 3 bits
291 */
292 static int write_local_socket(tpmState *s, const tpmBuffer *buffer)
293 {
294 uint32_t size = tpm_get_size_from_buffer(buffer->buf);
295 int len;
297 len = write(s->tpmTx.fd[0],
298 buffer->instance,
299 sizeof(buffer->instance) + size);
300 if (len == sizeof(buffer->instance) + size) {
301 return len;
302 } else {
303 return -1;
304 }
305 }
307 /*
308 * the 'read' method for receiving of responses from the TPM
309 * this function expects that four bytes with the instance number
310 * are received from the vTPM
311 */
312 static int read_local_socket(tpmState *s, tpmBuffer *buffer)
313 {
314 int off;
315 #ifdef DEBUG_TPM
316 fprintf(logfile, "Reading from fd %d\n", s->tpmTx.fd[0]);
317 #endif
318 off = read(s->tpmTx.fd[0],
319 buffer->instance,
320 sizeof(buffer->instance)+TPM_MAX_PKT);
321 #ifdef DEBUG_TPM
322 fprintf(logfile, "Read %d bytes\n", off);
323 #endif
324 return off;
325 }
327 /*
328 * the 'close' method
329 * shut down communication with the vTPM
330 * 'force' = 1 indicates that the socket *must* be closed
331 * 'force' = 0 indicates that a connection may be maintained
332 */
333 static int close_local_socket(tpmState *s, int force)
334 {
335 if (force) {
336 close(s->tpmTx.fd[0]);
337 #ifdef DEBUG_TPM
338 fprintf(logfile,"Closed connection with fd %d\n",s->tpmTx.fd[0]);
339 #endif
340 s->tpmTx.fd[0] = -1;
341 return 1; /* socket was closed */
342 }
343 #ifdef DEBUG_TPM
344 fprintf(logfile,"Keeping connection with fd %d\n",s->tpmTx.fd[0]);
345 #endif
346 return 0;
347 }
349 /*
350 * the 'has_channel' method that checks whether there's a communication
351 * channel with the vTPM
352 */
353 static int has_channel_local_socket(tpmState *s)
354 {
355 return (s->tpmTx.fd[0] > 0);
356 }
358 /**********************************************************************/
360 /*
361 * read a byte of response data
362 */
363 static uint32_t tpm_data_read(tpmState *s, uint8_t locty)
364 {
365 uint32_t ret, len;
367 /* try to receive data, if none are there it is ok */
368 tis_attempt_receive(s, locty);
370 if (s->loc[locty].state != STATE_COMPLETION) {
371 return 0xff;
372 }
374 len = tpm_get_size_from_buffer(s->buffer.buf);
375 ret = s->buffer.buf[s->offset++];
376 if (s->offset >= len) {
377 s->loc[locty].sts = STS_VALID ;
378 s->offset = 0;
379 }
380 #ifdef DEBUG_TPM
381 fprintf(logfile,"tpm_data_read byte x%02x [%d]\n",ret,s->offset-1);
382 #endif
383 return ret;
384 }
388 /* raise an interrupt if allowed */
389 static void tis_raise_irq(tpmState *s, uint8_t locty, uint32_t irqmask)
390 {
391 if (!s->irq_pending &&
392 (s->loc[locty].inte & INT_ENABLED) &&
393 (s->loc[locty].inte & irqmask)) {
394 if ((irqmask & s->loc[locty].ints) == 0) {
395 #ifdef DEBUG_TPM
396 fprintf(logfile,"Raising IRQ for flag %08x\n",irqmask);
397 #endif
398 s->set_irq(s->irq_opaque, s->irq, 1);
399 s->irq_pending = 1;
400 s->loc[locty].ints |= irqmask;
401 }
402 }
403 }
405 /* abort execution of command */
406 static void tis_abort(tpmState *s)
407 {
408 s->offset = 0;
409 s->active_loc = s->next_locty;
411 /*
412 * Need to react differently depending on who's aborting now and
413 * which locality will become active afterwards.
414 */
415 if (s->aborting_locty == s->next_locty) {
416 s->loc[s->aborting_locty].state = STATE_READY;
417 s->loc[s->aborting_locty].sts = STS_COMMAND_READY;
418 tis_raise_irq(s, s->aborting_locty, INT_COMMAND_READY);
419 }
421 /* locality after abort is another one than the current one */
422 if (s->aborting_locty != s->next_locty && s->next_locty != NO_LOCALITY) {
423 s->loc[s->aborting_locty].access &= ~ACCESS_ACTIVE_LOCALITY;
424 s->loc[s->next_locty].access |= ACCESS_ACTIVE_LOCALITY;
425 tis_raise_irq(s, s->next_locty, INT_LOCALITY_CHANGED);
426 }
428 s->aborting_locty = NO_LOCALITY; /* nobody's aborting a command anymore */
430 qemu_del_timer(s->poll_timer);
431 }
433 /* abort current command */
434 static void tis_prep_abort(tpmState *s, uint8_t locty, uint8_t newlocty)
435 {
436 s->aborting_locty = locty; /* current locality */
437 s->next_locty = newlocty; /* locality after successful abort */
439 /*
440 * only abort a command using an interrupt if currently executing
441 * a command AND if there's a valid connection to the vTPM.
442 */
443 if (s->loc[locty].state == STATE_EXECUTION &&
444 IS_COMM_WITH_VTPM(s)) {
445 /* start timer and inside the timer wait for the result */
446 s->poll_attempts = 0;
447 tis_prep_next_interrupt(s);
448 } else {
449 tis_abort(s);
450 }
451 }
454 /*
455 * Try to receive a response from the vTPM
456 */
457 static void tis_attempt_receive(tpmState *s, uint8_t locty)
458 {
459 /*
460 * Attempt to read from the vTPM here if
461 * - not aborting a command
462 * - command has been sent and state is 'EXECUTION' now
463 * - no data are already available (data have already been read)
464 * - there's a communication path to the vTPM established
465 */
466 if (!IS_VALID_LOC(s->aborting_locty)) {
467 if (s->loc[locty].state == STATE_EXECUTION) {
468 if (0 == (s->loc[locty].sts & STS_DATA_AVAILABLE)){
469 if (IS_COMM_WITH_VTPM(s)) {
470 int n = TPM_Receive(s, &s->buffer);
471 if (n > 0) {
472 s->loc[locty].sts = STS_VALID | STS_DATA_AVAILABLE;
473 s->loc[locty].state = STATE_COMPLETION;
474 close_vtpm_channel(s, FORCE_CLOSE);
475 tis_raise_irq(s, locty, INT_DATA_AVAILABLE);
476 }
477 }
478 }
479 }
480 }
481 }
483 /*
484 * Read a register of the TIS interface
485 * See specs pages 33-63 for description of the registers
486 */
487 static uint32_t tis_mem_readl(void *opaque, target_phys_addr_t addr)
488 {
489 tpmState *s = (tpmState *)opaque;
490 uint16_t offset = addr & 0xffc;
491 uint8_t shift = (addr & 0x3) * 8;
492 uint32_t val = 0;
493 uint8_t locty = locality_from_addr(addr);
495 if (offset == TPM_REG_ACCESS) {
496 if (s->active_loc == locty) {
497 s->loc[locty].access |= (1 << 5);
498 } else {
499 s->loc[locty].access &= ~(1 << 5);
500 }
501 val = s->loc[locty].access;
502 } else
503 if (offset == TPM_REG_INT_ENABLE) {
504 val = s->loc[locty].inte;
505 } else
506 if (offset == TPM_REG_INT_VECTOR) {
507 val = s->irq;
508 } else
509 if (offset == TPM_REG_INT_STATUS) {
510 tis_attempt_receive(s, locty);
511 val = s->loc[locty].ints;
512 } else
513 if (offset == TPM_REG_INTF_CAPABILITY) {
514 val = CAPABILITIES_SUPPORTED;
515 } else
516 if (offset == TPM_REG_STS) { /* status register */
517 tis_attempt_receive(s, locty);
518 val = (sizeof(s->buffer.buf) - s->offset) << 8 | s->loc[locty].sts;
519 } else
520 if (offset == TPM_REG_DATA_FIFO) {
521 val = tpm_data_read(s, locty);
522 } else
523 if (offset == TPM_REG_DID_VID) {
524 val = (TPM_DID << 16) | TPM_VID;
525 } else
526 if (offset == TPM_REG_RID) {
527 val = TPM_RID;
528 }
530 if (shift)
531 val >>= shift;
533 #ifdef DEBUG_TPM
534 fprintf(logfile," read(%08x) = %08x\n",
535 (int)addr,
536 val);
537 #endif
539 return val;
540 }
542 /*
543 * Write a value to a register of the TIS interface
544 * See specs pages 33-63 for description of the registers
545 */
546 static void tis_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
547 {
548 tpmState* s=(tpmState*)opaque;
549 uint16_t off = addr & 0xfff;
550 uint8_t locty = locality_from_addr(addr);
551 int n, c;
552 uint32_t len;
554 #ifdef DEBUG_TPM
555 fprintf(logfile,"write(%08x) = %08x\n",
556 (int)addr,
557 val);
558 #endif
560 if (off == TPM_REG_ACCESS) {
561 if (val & ACCESS_ACTIVE_LOCALITY) {
562 /* give up locality if currently owned */
563 if (s->active_loc == locty) {
564 uint8_t newlocty = NO_LOCALITY;
565 s->loc[locty].access &= ~(ACCESS_PENDING_REQUEST);
566 /* anybody wants the locality ? */
567 for (c = NUM_LOCALITIES - 1; c >= 0; c--) {
568 if (s->loc[c].access & ACCESS_REQUEST_USE) {
569 s->loc[c].access |= ACCESS_TPM_REG_VALID_STS;
570 s->loc[c].access &= ~ACCESS_REQUEST_USE;
571 newlocty = c;
572 break;
573 }
574 }
575 tis_prep_abort(s, locty, newlocty);
576 }
577 }
578 if (val & ACCESS_BEEN_SEIZED) {
579 /* clear the flag */
580 s->loc[locty].access &= ~ACCESS_BEEN_SEIZED;
581 }
582 if (val & ACCESS_SEIZE) {
583 if (locty > s->active_loc && IS_VALID_LOC(s->active_loc)) {
584 s->loc[s->active_loc].access |= ACCESS_BEEN_SEIZED;
585 s->loc[locty].access = ACCESS_TPM_REG_VALID_STS;
586 tis_prep_abort(s, s->active_loc, locty);
587 }
588 }
589 if (val & ACCESS_REQUEST_USE) {
590 if (IS_VALID_LOC(s->active_loc)) {
591 /* locality election */
592 s->loc[s->active_loc].access |= ACCESS_PENDING_REQUEST;
593 } else {
594 /* no locality active -> make this one active now */
595 s->loc[locty].access |= ACCESS_ACTIVE_LOCALITY;
596 s->active_loc = locty;
597 tis_raise_irq(s, locty, INT_LOCALITY_CHANGED);
598 }
599 }
600 } else
601 if (off == TPM_REG_INT_ENABLE) {
602 s->loc[locty].inte = (val & (INT_ENABLED | (0x3 << 3) |
603 INTERRUPTS_SUPPORTED));
604 } else
605 if (off == TPM_REG_INT_STATUS) {
606 /* clearing of interrupt flags */
607 if ((val & INTERRUPTS_SUPPORTED) &&
608 (s->loc[locty].ints & INTERRUPTS_SUPPORTED)) {
609 s->set_irq(s->irq_opaque, s->irq, 0);
610 s->irq_pending = 0;
611 }
612 s->loc[locty].ints &= ~(val & INTERRUPTS_SUPPORTED);
613 } else
614 if (off == TPM_REG_STS) {
615 if (val & STS_COMMAND_READY) {
616 if (s->loc[locty].state == STATE_IDLE) {
617 s->loc[locty].sts = STS_COMMAND_READY;
618 s->loc[locty].state = STATE_READY;
619 tis_raise_irq(s, locty, INT_COMMAND_READY);
620 } else if (s->loc[locty].state == STATE_COMPLETION ||
621 s->loc[locty].state == STATE_EXECUTION ||
622 s->loc[locty].state == STATE_RECEPTION) {
623 /* abort currently running command */
624 tis_prep_abort(s, locty, locty);
625 }
626 }
627 if (val & STS_TPM_GO) {
628 n = TPM_Send(s, &s->buffer, locty, "tpm_data_write");
629 if (n > 0) {
630 /* sending of data was successful */
631 s->offset = 0;
632 s->loc[locty].state = STATE_EXECUTION;
633 if (s->loc[locty].inte & (INT_ENABLED | INT_DATA_AVAILABLE)) {
634 s->poll_attempts = 0;
635 tis_prep_next_interrupt(s);
636 }
637 }
638 }
639 if (val & STS_RESPONSE_RETRY) {
640 s->offset = 0;
641 }
642 } else if (off == TPM_REG_DATA_FIFO) {
643 /* data fifo */
644 if (s->loc[locty].state == STATE_IDLE ||
645 s->loc[locty].state == STATE_EXECUTION ||
646 s->loc[locty].state == STATE_COMPLETION) {
647 /* drop the byte */
648 } else {
649 #ifdef TPM_DEBUG
650 fprintf(logfile,"Byte to send to TPM: %02x\n", val);
651 #endif
652 s->loc[locty].state = STATE_RECEPTION;
654 if (s->offset < sizeof(s->buffer.buf))
655 s->buffer.buf[s->offset++] = (uint8_t)val;
657 if (s->offset > 5) {
658 /* we have a packet length - see if we have all of it */
659 len = tpm_get_size_from_buffer(s->buffer.buf);
660 if (len > s->offset) {
661 s->loc[locty].sts = STS_EXPECT | STS_VALID;
662 } else {
663 s->loc[locty].sts = STS_VALID;
664 }
665 }
666 }
667 }
668 }
670 /*
671 * Prepare the next interrupt for example after a command has
672 * been sent out for the purpose of receiving the response.
673 * Depending on how many interrupts (used for polling on the fd) have
674 * already been schedule, this function determines the delta in time
675 * to the next interrupt. This accomodates for commands that finish
676 * quickly.
677 */
678 static void tis_prep_next_interrupt(tpmState *s)
679 {
680 int64_t expiration;
681 int rate = 5; /* 5 times per second */
683 /*
684 poll often at the beginning for quickly finished commands,
685 then back off
686 */
687 if (s->poll_attempts < 5) {
688 rate = 20;
689 } else if (s->poll_attempts < 10) {
690 rate = 10;
691 }
693 expiration = qemu_get_clock(vm_clock) + (ticks_per_sec / rate);
694 qemu_mod_timer(s->poll_timer, expiration);
695 s->poll_attempts++;
696 }
699 /*
700 * The polling routine called when the 'timer interrupt' fires.
701 * Tries to receive a command from the vTPM.
702 */
703 static void tis_poll_timer(void *opaque)
704 {
705 tpmState* s=(tpmState*)opaque;
706 uint8_t locty = s->active_loc;
708 if (!IS_VALID_LOC(locty) ||
709 (!(s->loc[locty].inte & INT_ENABLED) &&
710 (s->aborting_locty != NO_LOCALITY)) ||
711 !IS_COMM_WITH_VTPM(s)) {
712 /* no more interrupts requested, so no more polling needed */
713 qemu_del_timer(s->poll_timer);
714 }
716 if (!IS_COMM_WITH_VTPM(s)) {
717 if (s->aborting_locty != NO_LOCALITY) {
718 tis_abort(s);
719 }
720 return;
721 }
723 if (s->aborting_locty != NO_LOCALITY) {
724 int n = TPM_Receive(s, &s->buffer);
725 #ifdef DEBUG_TPM
726 fprintf(logfile,"Receiving for abort.\n");
727 #endif
728 if (n > 0) {
729 close_vtpm_channel(s, FORCE_CLOSE);
730 tis_abort(s);
731 #ifdef DEBUG_TPM
732 fprintf(logfile,"Abort is complete.\n");
733 #endif
734 } else {
735 tis_prep_next_interrupt(s);
736 }
737 } else if (IS_VALID_LOC(locty)) {
738 if (s->loc[locty].state == STATE_EXECUTION) {
739 /* poll for result */
740 int n = TPM_Receive(s, &s->buffer);
741 if (n > 0) {
742 s->loc[locty].sts = STS_VALID | STS_DATA_AVAILABLE;
743 s->loc[locty].state = STATE_COMPLETION;
744 close_vtpm_channel(s, FORCE_CLOSE);
745 tis_raise_irq(s, locty, INT_DATA_AVAILABLE);
746 } else {
747 /* nothing received */
748 tis_prep_next_interrupt(s);
749 }
750 }
751 }
752 }
755 static CPUReadMemoryFunc *tis_readfn[3]={
756 tis_mem_readl,
757 tis_mem_readl,
758 tis_mem_readl
759 };
761 static CPUWriteMemoryFunc *tis_writefn[3]={
762 tis_mem_writel,
763 tis_mem_writel,
764 tis_mem_writel
765 };
767 /*
768 * Save the internal state of this interface for later resumption.
769 * Need to get any outstanding responses from the vTPM back, so
770 * this might delay the suspend for a while.
771 */
772 static void tpm_save(QEMUFile* f,void* opaque)
773 {
774 tpmState* s=(tpmState*)opaque;
775 uint8_t locty = s->active_loc;
776 int c;
778 /* need to wait for outstanding requests to complete */
779 if (s->loc[locty].state == STATE_EXECUTION) {
780 int repeats = 30; /* 30 seconds; really should be infty */
781 while (repeats > 0 &&
782 !(s->loc[s->active_loc].sts & STS_DATA_AVAILABLE)) {
783 int n = TPM_Receive(s, &s->buffer);
784 if (n > 0) {
785 if (IS_VALID_LOC(s->active_loc)) {
786 s->loc[s->active_loc].sts = STS_VALID | STS_DATA_AVAILABLE;
787 s->loc[s->active_loc].state = STATE_COMPLETION;
788 tis_raise_irq(s, s->active_loc, INT_DATA_AVAILABLE);
789 }
790 /* close the connection with the vTPM for good */
791 close_vtpm_channel(s, 1);
792 break;
793 }
794 sleep(1);
795 }
796 }
798 if (IS_COMM_WITH_VTPM(s)) {
799 close_vtpm_channel(s, 1);
800 }
802 qemu_put_be32s(f,&s->offset);
803 qemu_put_buffer(f, s->buffer.buf, TPM_MAX_PKT);
804 qemu_put_8s(f, &s->active_loc);
805 qemu_put_8s(f, &s->irq_pending);
806 for (c = 0; c < NUM_LOCALITIES; c++) {
807 qemu_put_be32s(f, &s->loc[c].state);
808 qemu_put_8s(f, &s->loc[c].access);
809 qemu_put_8s(f, &s->loc[c].sts);
810 qemu_put_be32s(f, &s->loc[c].inte);
811 qemu_put_be32s(f, &s->loc[c].ints);
812 }
813 }
815 /*
816 * load TIS interface state
817 */
818 static int tpm_load(QEMUFile* f,void* opaque,int version_id)
819 {
820 tpmState* s=(tpmState*)opaque;
821 int c;
823 if (version_id != 1)
824 return -EINVAL;
826 qemu_get_be32s(f,&s->offset);
827 qemu_get_buffer(f, s->buffer.buf, TPM_MAX_PKT);
828 qemu_get_8s(f, &s->active_loc);
829 qemu_get_8s(f, &s->irq_pending);
830 for (c = 0; c < NUM_LOCALITIES; c++) {
831 qemu_get_be32s(f, &s->loc[c].state);
832 qemu_get_8s(f, &s->loc[c].access);
833 qemu_get_8s(f, &s->loc[c].sts);
834 qemu_get_be32s(f, &s->loc[c].inte);
835 qemu_get_be32s(f, &s->loc[c].ints);
836 }
838 /* need to be able to get the instance number from the xenstore */
839 s->vtpm_instance = vtpm_instance_from_xenstore();
840 if (s->vtpm_instance == VTPM_BAD_INSTANCE)
841 return -EINVAL;
842 tpm_initialize_instance(s, s->vtpm_instance);
844 return 0;
845 }
848 typedef struct LPCtpmState {
849 tpmState tpm;
850 int mem;
851 } LPCtpmState;
854 /*
855 * initialize TIS interface
856 */
857 void tpm_tis_init(SetIRQFunc *set_irq, void *opaque, int irq)
858 {
859 LPCtpmState *d;
860 tpmState *s;
861 int c = 0;
862 uint32_t vtpm_in;
864 vtpm_in = vtpm_instance_from_xenstore();
865 /* no valid vtpm instance -> no device */
866 if (vtpm_in == VTPM_BAD_INSTANCE)
867 return;
869 d = qemu_mallocz(sizeof(LPCtpmState));
870 d->mem = cpu_register_io_memory(0, tis_readfn, tis_writefn, d);
872 if (d->mem == -1) {
873 return;
874 }
876 cpu_register_physical_memory(TIS_ADDR_BASE,
877 0x1000 * NUM_LOCALITIES, d->mem);
879 /* initialize tpmState */
880 s = &d->tpm;
882 s->offset = 0;
883 s->active_loc = NO_LOCALITY;
885 while (c < NUM_LOCALITIES) {
886 s->loc[c].access = (1 << 7);
887 s->loc[c].sts = 0;
888 s->loc[c].inte = (1 << 3);
889 s->loc[c].ints = 0;
890 s->loc[c].state = STATE_IDLE;
891 c++;
892 }
893 s->poll_timer = qemu_new_timer(vm_clock, tis_poll_timer, s);
894 s->set_irq = set_irq;
895 s->irq_opaque = opaque;
896 s->irq = irq;
897 s->vtpm_instance = vtpm_in;
898 s->Transmitlayer = -1;
899 s->tpmTx.fd[0] = -1;
900 s->tpmTx.fd[1] = -1;
901 s->aborting_locty = NO_LOCALITY;
903 tpm_initialize_instance(s, s->vtpm_instance);
904 memset(s->buffer.buf,0,sizeof(s->buffer.buf));
906 register_savevm("tpm-tis", 0, 1, tpm_save, tpm_load, s);
908 for (c = 0; !IS_COMM_WITH_VTPM(s) && (c < 5); c++) {
909 open_vtpm_channel(s);
910 sleep(1);
911 }
912 }
914 /****************************************************************************/
915 /* optional verbose logging of data to/from vtpm */
916 /****************************************************************************/
917 #ifdef DEBUG_TPM
918 static void showBuff(unsigned char *buff, char *string)
919 {
920 uint32_t i, len;
922 len = tpm_get_size_from_buffer(buff);
923 fprintf(logfile,"%s length = %d\n", string, len);
924 for (i = 0; i < len; i++) {
925 if (i && !(i % 16)) {
926 fprintf(logfile,"\n");
927 }
928 fprintf(logfile,"%.2X ", buff[i]);
929 }
930 fprintf(logfile,"\n");
931 }
932 #endif
934 /****************************************************************************/
935 /* Transmit request to TPM and read Response */
936 /****************************************************************************/
938 const static unsigned char tpm_failure[] = {
939 0x00, 0x00,
940 0x00, 0x00, 0x00, 0x0a,
941 0x00, 0x00, 0x00, 0x09
942 };
945 /*
946 * Send a TPM request.
947 */
948 static int TPM_Send(tpmState *s, tpmBuffer *buffer, uint8_t locty, char *msg)
949 {
950 int len;
951 uint32_t size = tpm_get_size_from_buffer(buffer->buf);
953 /* try to establish a connection to the vTPM */
954 if ( !IS_COMM_WITH_VTPM(s)) {
955 open_vtpm_channel(s);
956 }
958 if ( !IS_COMM_WITH_VTPM(s)) {
959 unsigned char tag = buffer->buf[1];
961 /* there's a failure response from the TPM */
962 memcpy(buffer->buf, tpm_failure, sizeof(tpm_failure));
963 buffer->buf[1] = tag + 3;
964 if (IS_VALID_LOC(s->active_loc)) {
965 s->loc[s->active_loc].sts = STS_DATA_AVAILABLE | STS_VALID;
966 }
967 #ifdef DEBUG_TPM
968 fprintf(logfile,"No TPM running!\n");
969 #endif
970 /* the request went out ok. */
971 return sizeof(buffer->instance) + size;
972 }
974 #ifdef DEBUG_TPM
975 showBuff(buffer->buf, "To TPM");
976 #endif
978 /* transmit the locality in the highest 3 bits */
979 buffer->instance[0] &= 0x1f;
980 buffer->instance[0] |= (locty << 5);
982 len = vTPMTransmit[s->Transmitlayer].write_fn(s, buffer);
983 if (len < 0) {
984 s->Transmitlayer = -1;
985 }
986 return len;
987 }
989 /*
990 * Try to receive data from the file descriptor. Since it is in
991 * non-blocking mode it is possible that no data are actually received -
992 * whatever calls this function needs to try again later.
993 */
994 static int TPM_Receive(tpmState *s, tpmBuffer *buffer)
995 {
996 int off;
998 off = vTPMTransmit[s->Transmitlayer].read_fn(s, buffer);
1000 if (off < 0) {
1001 /* EAGAIN is set in errno due to non-blocking mode */
1002 return -1;
1005 if (off == 0) {
1006 #ifdef DEBUG_TPM
1007 fprintf(logfile,"TPM GONE? errno=%d\n",errno);
1008 #endif
1009 close_vtpm_channel(s, 1);
1010 /* pretend that data are available */
1011 if (IS_VALID_LOC(s->active_loc)) {
1012 s->loc[s->active_loc].sts = STS_VALID | STS_DATA_AVAILABLE;
1013 s->loc[s->active_loc].state = STATE_COMPLETION;
1014 tis_raise_irq(s, s->active_loc, INT_DATA_AVAILABLE);
1016 return -1;
1019 #ifdef DEBUG_TPM
1020 if (off > sizeof(buffer->instance ) + 6) {
1021 uint32_t size = tpm_get_size_from_buffer(buffer->buf);
1022 if (size + sizeof(buffer->instance) != off) {
1023 fprintf(logfile,"TPM: Packet size is bad! %d != %d\n",
1024 (int)(size + sizeof(buffer->instance)),
1025 off);
1026 } else {
1027 uint32_t ret;
1028 showBuff(buffer->buf, "From TPM");
1029 ret = (buffer->buf[8])*256 + buffer->buf[9];
1030 if (ret)
1031 fprintf(logfile,"Receive failed with error %d\n", ret);
1032 else
1033 fprintf(logfile,"Receive succeeded. Got response of length %d (=%d)\n",
1034 size, off);
1037 #endif
1039 /* assuming reading in one chunk for now */
1040 return off;
1044 /****************************************************************************
1045 Helper functions for reading data from the xenstore such as
1046 reading virtual TPM instance information
1047 ****************************************************************************/
1048 int has_tpm_device(void)
1050 int ret = 0;
1051 struct xs_handle *handle = xs_daemon_open();
1052 if (handle) {
1053 ret = xenstore_domain_has_devtype(handle, "vtpm");
1054 xs_daemon_close(handle);
1056 return ret;
1060 /*
1061 * Wait until hotplug scripts have finished then read the vTPM instance
1062 * number from the xenstore.
1063 */
1064 static uint32_t vtpm_instance_from_xenstore(void)
1066 unsigned int num;
1067 uint32_t number = VTPM_BAD_INSTANCE;
1068 int end = 0;
1069 char *token = "tok";
1070 int subscribed = 0;
1071 int ctr = 0;
1072 fd_set readfds;
1074 struct xs_handle *handle = xs_daemon_open();
1076 FD_ZERO(&readfds);
1078 if (handle) {
1079 char **e = xenstore_domain_get_devices(handle, "vtpm", &num);
1080 int fd = xs_fileno(handle);
1081 FD_SET(fd, &readfds);
1082 if (e) {
1083 do {
1084 struct timeval tv = {
1085 .tv_sec = 30,
1086 .tv_usec = 0,
1087 };
1088 /* need to make sure that the hotplug scripts have finished */
1089 char *status = xenstore_read_hotplug_status(handle,
1090 "vtpm",
1091 e[0]);
1092 if (status) {
1093 if (!strcmp(status, "connected")) {
1094 char *inst = xenstore_backend_read_variable(handle,
1095 "vtpm",
1096 e[0],
1097 "instance");
1098 if (1 != (sscanf(inst,"%d",&number)))
1099 number = VTPM_BAD_INSTANCE;
1100 free(inst);
1101 } else {
1102 fprintf(logfile,
1103 "bad status '%s' from vtpm hotplug\n",
1104 status);
1106 free(status);
1107 end = 1;
1108 } else {
1109 /* no status, yet */
1110 int rc;
1111 unsigned int nr;
1112 char **f;
1114 if (!subscribed) {
1115 rc = xenstore_subscribe_to_hotplug_status(handle,
1116 "vtpm",
1117 e[0],
1118 token);
1119 if (rc != 0)
1120 break;
1121 subscribed = 1;
1123 rc = select(fd+1, &readfds, NULL, NULL, &tv);
1124 /* get what's available -- drain the fd */
1125 f = xs_read_watch(handle, &nr);
1126 ctr++;
1127 free(f);
1128 if (ctr > 2)
1129 end = 1;
1131 } while (end == 0);
1132 free(e);
1134 if (subscribed) {
1135 /* clean up */
1136 xenstore_unsubscribe_from_hotplug_status(handle,
1137 "vtpm",
1138 e[0],
1139 token);
1141 xs_daemon_close(handle);
1143 if (number == VTPM_BAD_INSTANCE)
1144 fprintf(logfile, "no valid vtpm instance");
1145 else
1146 fprintf(logfile,"vtpm instance:%d\n",number);
1147 return number;