⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tpm_tis.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 3 页
字号:
 * 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);    open_vtpm_channel(s);    for (c = 0; !IS_COMM_WITH_VTPM(s) && (c < 5); c++) {       sleep(1);       open_vtpm_channel(s);    }}/****************************************************************************//*  optional verbose logging of data to/from vtpm                           *//****************************************************************************/#ifdef DEBUG_TPMstatic 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_fn(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_fn(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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -