?? tpm-tis-device
字號:
+static CPUWriteMemoryFunc *tis_writefn[3]={+ tis_mem_writel,+ tis_mem_writel,+ tis_mem_writel+};++/*+ * Save the internal state of this interface for later resumption.+ * Need to get any outstanding responses from the vTPM back, so+ * this might delay the suspend for a while.+ */+static void tpm_save(QEMUFile* f,void* opaque)+{+ tpmState* s=(tpmState*)opaque;+ uint8_t locty = s->active_loc;+ int c;++ /* need to wait for outstanding requests to complete */+ if (s->loc[locty].state == STATE_EXECUTION) {+ int repeats = 30; /* 30 seconds; really should be infty */+ while (repeats > 0 &&+ !(s->loc[s->active_loc].sts & STS_DATA_AVAILABLE)) {+ int n = TPM_Receive(s, &s->buffer);+ if (n > 0) {+ if (IS_VALID_LOC(s->active_loc)) {+ s->loc[s->active_loc].sts = STS_VALID | STS_DATA_AVAILABLE;+ s->loc[s->active_loc].state = STATE_COMPLETION;+ tis_raise_irq(s, s->active_loc, INT_DATA_AVAILABLE);+ }+ /* close the connection with the vTPM for good */+ close_vtpm_channel(s, 1);+ break;+ }+ sleep(1);+ }+ }++ if (IS_COMM_WITH_VTPM(s)) {+ close_vtpm_channel(s, 1);+ }++ qemu_put_be32s(f,&s->offset);+ qemu_put_buffer(f, s->buffer.buf, TPM_MAX_PKT);+ qemu_put_8s(f, &s->active_loc);+ qemu_put_8s(f, &s->irq_pending);+ for (c = 0; c < NUM_LOCALITIES; c++) {+ qemu_put_be32s(f, &s->loc[c].state);+ qemu_put_8s(f, &s->loc[c].access);+ qemu_put_8s(f, &s->loc[c].sts);+ qemu_put_be32s(f, &s->loc[c].inte);+ qemu_put_be32s(f, &s->loc[c].ints);+ }+}++/*+ * load TIS interface state+ */+static int tpm_load(QEMUFile* f,void* opaque,int version_id)+{+ tpmState* s=(tpmState*)opaque;+ int c;++ if (version_id != 1)+ return -EINVAL;++ qemu_get_be32s(f,&s->offset);+ qemu_get_buffer(f, s->buffer.buf, TPM_MAX_PKT);+ qemu_get_8s(f, &s->active_loc);+ qemu_get_8s(f, &s->irq_pending);+ for (c = 0; c < NUM_LOCALITIES; c++) {+ qemu_get_be32s(f, &s->loc[c].state);+ qemu_get_8s(f, &s->loc[c].access);+ qemu_get_8s(f, &s->loc[c].sts);+ qemu_get_be32s(f, &s->loc[c].inte);+ qemu_get_be32s(f, &s->loc[c].ints);+ }++ /* need to be able to get the instance number from the xenstore */+ s->vtpm_instance = vtpm_instance_from_xenstore();+ if (s->vtpm_instance == VTPM_BAD_INSTANCE)+ return -EINVAL;+ tpm_initialize_instance(s, s->vtpm_instance);++ return 0;+}+++typedef struct LPCtpmState {+ tpmState tpm;+ int mem;+} LPCtpmState;+++/*+ * initialize TIS interface+ */+void tpm_tis_init(SetIRQFunc *set_irq, void *opaque, int irq)+{+ LPCtpmState *d;+ tpmState *s;+ int c = 0;+ uint32_t vtpm_in;++ vtpm_in = vtpm_instance_from_xenstore();+ /* no valid vtpm instance -> no device */+ if (vtpm_in == VTPM_BAD_INSTANCE)+ return;++ d = qemu_mallocz(sizeof(LPCtpmState));+ d->mem = cpu_register_io_memory(0, tis_readfn, tis_writefn, d);++ if (d->mem == -1) {+ return;+ }++ cpu_register_physical_memory(TIS_ADDR_BASE,+ 0x1000 * NUM_LOCALITIES, d->mem);++ /* initialize tpmState */+ s = &d->tpm;++ s->offset = 0;+ s->active_loc = NO_LOCALITY;++ while (c < NUM_LOCALITIES) {+ s->loc[c].access = (1 << 7);+ s->loc[c].sts = 0;+ s->loc[c].inte = (1 << 3);+ s->loc[c].ints = 0;+ s->loc[c].state = STATE_IDLE;+ c++;+ }+ s->poll_timer = qemu_new_timer(vm_clock, tis_poll_timer, s);+ s->set_irq = set_irq;+ s->irq_opaque = opaque;+ s->irq = irq;+ s->vtpm_instance = vtpm_in;+ s->Transmitlayer = -1;+ s->tpmTx.fd[0] = -1;+ s->tpmTx.fd[1] = -1;+ s->aborting_locty = NO_LOCALITY;++ tpm_initialize_instance(s, s->vtpm_instance);+ memset(s->buffer.buf,0,sizeof(s->buffer.buf));++ register_savevm("tpm-tis", 0, 1, tpm_save, tpm_load, s);+}++/****************************************************************************/+/* optional verbose logging of data to/from vtpm */+/****************************************************************************/+#ifdef DEBUG_TPM+static void showBuff(unsigned char *buff, char *string)+{+ uint32_t i, len;++ len = tpm_get_size_from_buffer(buff);+ fprintf(logfile,"%s length = %d\n", string, len);+ for (i = 0; i < len; i++) {+ if (i && !(i % 16)) {+ fprintf(logfile,"\n");+ }+ fprintf(logfile,"%.2X ", buff[i]);+ }+ fprintf(logfile,"\n");+}+#endif++/****************************************************************************/+/* Transmit request to TPM and read Response */+/****************************************************************************/++const static unsigned char tpm_failure[] = {+ 0x00, 0x00,+ 0x00, 0x00, 0x00, 0x0a,+ 0x00, 0x00, 0x00, 0x09+};+++/*+ * Send a TPM request.+ */+static int TPM_Send(tpmState *s, tpmBuffer *buffer, uint8_t locty, char *msg)+{+ int len;+ uint32_t size = tpm_get_size_from_buffer(buffer->buf);++ /* try to establish a connection to the vTPM */+ if ( !IS_COMM_WITH_VTPM(s)) {+ open_vtpm_channel(s);+ }++ if ( !IS_COMM_WITH_VTPM(s)) {+ unsigned char tag = buffer->buf[1];++ /* there's a failure response from the TPM */+ memcpy(buffer->buf, tpm_failure, sizeof(tpm_failure));+ buffer->buf[1] = tag + 3;+ if (IS_VALID_LOC(s->active_loc)) {+ s->loc[s->active_loc].sts = STS_DATA_AVAILABLE | STS_VALID;+ }+#ifdef DEBUG_TPM+ fprintf(logfile,"No TPM running!\n");+#endif+ /* the request went out ok. */+ return sizeof(buffer->instance) + size;+ }++#ifdef DEBUG_TPM+ showBuff(buffer->buf, "To TPM");+#endif++ /* transmit the locality in the highest 3 bits */+ buffer->instance[0] &= 0x1f;+ buffer->instance[0] |= (locty << 5);++ len = vTPMTransmit[s->Transmitlayer].write(s, buffer);+ if (len < 0) {+ s->Transmitlayer = -1;+ }+ return len;+}++/*+ * Try to receive data from the file descriptor. Since it is in+ * non-blocking mode it is possible that no data are actually received -+ * whatever calls this function needs to try again later.+ */+static int TPM_Receive(tpmState *s, tpmBuffer *buffer)+{+ int off;++ off = vTPMTransmit[s->Transmitlayer].read(s, buffer);++ if (off < 0) {+ /* EAGAIN is set in errno due to non-blocking mode */+ return -1;+ }++ if (off == 0) {+#ifdef DEBUG_TPM+ fprintf(logfile,"TPM GONE? errno=%d\n",errno);+#endif+ close_vtpm_channel(s, 1);+ /* pretend that data are available */+ if (IS_VALID_LOC(s->active_loc)) {+ s->loc[s->active_loc].sts = STS_VALID | STS_DATA_AVAILABLE;+ s->loc[s->active_loc].state = STATE_COMPLETION;+ tis_raise_irq(s, s->active_loc, INT_DATA_AVAILABLE);+ }+ return -1;+ }++#ifdef DEBUG_TPM+ if (off > sizeof(buffer->instance ) + 6) {+ uint32_t size = tpm_get_size_from_buffer(buffer->buf);+ if (size + sizeof(buffer->instance) != off) {+ fprintf(logfile,"TPM: Packet size is bad! %d != %d\n",+ (int)(size + sizeof(buffer->instance)),+ off);+ } else {+ uint32_t ret;+ showBuff(buffer->buf, "From TPM");+ ret = (buffer->buf[8])*256 + buffer->buf[9];+ if (ret)+ fprintf(logfile,"Receive failed with error %d\n", ret);+ else+ fprintf(logfile,"Receive succeeded. Got response of length %d (=%d)\n",+ size, off);+ }+ }+#endif++ /* assuming reading in one chunk for now */+ return off;+}+++/****************************************************************************+ Helper functions for reading data from the xenstore such as+ reading virtual TPM instance information+ ****************************************************************************/+int has_tpm_device(void)+{+ int ret = 0;+ struct xs_handle *handle = xs_daemon_open();+ if (handle) {+ ret = xenstore_domain_has_devtype(handle, "vtpm");+ xs_daemon_close(handle);+ }+ return ret;+}+++/*+ * Wait until hotplug scripts have finished then read the vTPM instance+ * number from the xenstore.+ */+static uint32_t vtpm_instance_from_xenstore(void)+{+ unsigned int num;+ uint32_t number = VTPM_BAD_INSTANCE;+ int end = 0;+ char *token = "tok";+ int subscribed = 0;+ int ctr = 0;+ fd_set readfds;++ struct xs_handle *handle = xs_daemon_open();++ FD_ZERO(&readfds);++ if (handle) {+ char **e = xenstore_domain_get_devices(handle, "vtpm", &num);+ int fd = xs_fileno(handle);+ FD_SET(fd, &readfds);+ if (e) {+ do {+ struct timeval tv = {+ .tv_sec = 30,+ .tv_usec = 0,+ };+ /* need to make sure that the hotplug scripts have finished */+ char *status = xenstore_read_hotplug_status(handle,+ "vtpm",+ e[0]);+ if (status) {+ if (!strcmp(status, "connected")) {+ char *inst = xenstore_backend_read_variable(handle,+ "vtpm",+ e[0],+ "instance");+ if (1 != (sscanf(inst,"%d",&number)))+ number = VTPM_BAD_INSTANCE;+ free(inst);+ } else {+ fprintf(logfile,+ "bad status '%s' from vtpm hotplug\n",+ status);+ }+ free(status);+ end = 1;+ } else {+ /* no status, yet */+ int rc;+ unsigned int nr;+ char **f;++ if (!subscribed) {+ rc = xenstore_subscribe_to_hotplug_status(handle,+ "vtpm",+ e[0],+ token);+ if (rc != 0)+ break;+ subscribed = 1;+ }+ rc = select(fd+1, &readfds, NULL, NULL, &tv);+ /* get what's available -- drain the fd */+ f = xs_read_watch(handle, &nr);+ ctr++;+ free(f);+ if (ctr > 2)+ end = 1;+ }+ } while (end == 0);+ free(e);+ }+ if (subscribed) {+ /* clean up */+ xenstore_unsubscribe_from_hotplug_status(handle,+ "vtpm",+ e[0],+ token);+ }+ xs_daemon_close(handle);+ }+ if (number == VTPM_BAD_INSTANCE)+ fprintf(logfile, "no valid vtpm instance");+ else+ fprintf(logfile,"vtpm instance:%d\n",number);+ return number;+}Index: ioemu/vl.h===================================================================--- ioemu.orig/vl.h 2007-05-10 15:19:29.000000000 +0100+++ ioemu/vl.h 2007-05-10 15:19:29.000000000 +0100@@ -1086,6 +1086,10 @@ /* smbus_eeprom.c */ SMBusDevice *smbus_eeprom_device_init(uint8_t addr, uint8_t *buf); +/* tpm_tis.c */+int has_tpm_device(void);+void tpm_tis_init(SetIRQFunc *set_irq, void *irq_opaque, int irq);+ /* piix4acpi.c */ extern void pci_piix4_acpi_init(PCIBus *bus, int devfn);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -