aboutsummaryrefslogtreecommitdiffstats
path: root/extras
diff options
context:
space:
mode:
authorDaniel De Graaf <dgdegra@tycho.nsa.gov>2013-04-11 12:20:25 -0400
committerIan Campbell <ian.campbell@citrix.com>2013-04-12 14:28:17 +0100
commitf494d9f3c37542435239236085be25c820912304 (patch)
tree571f23e359f4ba4c78c818ef288147dbd0f563ae /extras
parentc1f0b214536773630cd5f16bf3d275015373555b (diff)
downloadxen-f494d9f3c37542435239236085be25c820912304.tar.gz
xen-f494d9f3c37542435239236085be25c820912304.tar.bz2
xen-f494d9f3c37542435239236085be25c820912304.zip
mini-os/tpm{back, front}: Change shared page ABI
This changes the vTPM shared page ABI from a copy of the Xen network interface to a single-page interface that better reflects the expected behavior of a TPM: only a single request packet can be sent at any given time, and every packet sent generates a single response packet. This protocol change should also increase efficiency as it avoids mapping and unmapping grants when possible. The vtpm xenbus device now requires a feature-protocol-v2 node in xenstore to avoid conflicts with existing (xen-patched) kernels supporting the old interface. While the contents of the shared page have been defined to allow packets larger than a single page (actually 4088 bytes) by allowing the client to add extra grant references, the mapping of these extra references has not been implemented; a feature node in xenstore may be used in the future to indicate full support for the multi-page protocol. Most uses of the TPM should not require this feature. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> Cc: Jan Beulich <JBeulich@suse.com>
Diffstat (limited to 'extras')
-rw-r--r--extras/mini-os/include/tpmback.h1
-rw-r--r--extras/mini-os/include/tpmfront.h7
-rw-r--r--extras/mini-os/tpmback.c166
-rw-r--r--extras/mini-os/tpmfront.c144
4 files changed, 166 insertions, 152 deletions
diff --git a/extras/mini-os/include/tpmback.h b/extras/mini-os/include/tpmback.h
index ff8673285c..ec9eda4b57 100644
--- a/extras/mini-os/include/tpmback.h
+++ b/extras/mini-os/include/tpmback.h
@@ -43,6 +43,7 @@
struct tpmcmd {
domid_t domid; /* Domid of the frontend */
+ uint8_t locality; /* Locality requested by the frontend */
unsigned int handle; /* Handle of the frontend */
unsigned char uuid[16]; /* uuid of the tpm interface */
diff --git a/extras/mini-os/include/tpmfront.h b/extras/mini-os/include/tpmfront.h
index fd2cb17fc9..a0c7c4d8b5 100644
--- a/extras/mini-os/include/tpmfront.h
+++ b/extras/mini-os/include/tpmfront.h
@@ -37,9 +37,7 @@ struct tpmfront_dev {
grant_ref_t ring_ref;
evtchn_port_t evtchn;
- tpmif_tx_interface_t* tx;
-
- void** pages;
+ vtpm_shared_page_t *page;
domid_t bedomid;
char* nodename;
@@ -77,6 +75,9 @@ void shutdown_tpmfront(struct tpmfront_dev* dev);
* */
int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen);
+/* Set the locality used for communicating with a vTPM */
+int tpmfront_set_locality(struct tpmfront_dev* dev, int locality);
+
#ifdef HAVE_LIBC
#include <sys/stat.h>
/* POSIX IO functions:
diff --git a/extras/mini-os/tpmback.c b/extras/mini-os/tpmback.c
index 658fed1514..d68ad2b876 100644
--- a/extras/mini-os/tpmback.c
+++ b/extras/mini-os/tpmback.c
@@ -86,10 +86,7 @@ struct tpmif {
evtchn_port_t evtchn;
/* Shared page */
- tpmif_tx_interface_t* tx;
-
- /* pointer to TPMIF_RX_RING_SIZE pages */
- void** pages;
+ vtpm_shared_page_t *page;
enum xenbus_state state;
enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
@@ -266,6 +263,7 @@ int insert_tpmif(tpmif_t* tpmif)
unsigned int i, j;
tpmif_t* tmp;
char* err;
+ char path[512];
local_irq_save(flags);
@@ -303,6 +301,16 @@ int insert_tpmif(tpmif_t* tpmif)
local_irq_restore(flags);
+ snprintf(path, 512, "backend/vtpm/%u/%u/feature-protocol-v2", (unsigned int) tpmif->domid, tpmif->handle);
+ if ((err = xenbus_write(XBT_NIL, path, "1")))
+ {
+ /* if we got an error here we should carefully remove the interface and then return */
+ TPMBACK_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
+ free(err);
+ remove_tpmif(tpmif);
+ goto error_post_irq;
+ }
+
/*Listen for state changes on the new interface */
if((err = xenbus_watch_path_token(XBT_NIL, tpmif->fe_state_path, tpmif->fe_state_path, &gtpmdev.events)))
{
@@ -312,7 +320,6 @@ int insert_tpmif(tpmif_t* tpmif)
remove_tpmif(tpmif);
goto error_post_irq;
}
-
return 0;
error:
local_irq_restore(flags);
@@ -386,8 +393,7 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
tpmif->fe_state_path = NULL;
tpmif->state = XenbusStateInitialising;
tpmif->status = DISCONNECTED;
- tpmif->tx = NULL;
- tpmif->pages = NULL;
+ tpmif->page = NULL;
tpmif->flags = 0;
memset(tpmif->uuid, 0, sizeof(tpmif->uuid));
return tpmif;
@@ -395,9 +401,6 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int handle)
void __free_tpmif(tpmif_t* tpmif)
{
- if(tpmif->pages) {
- free(tpmif->pages);
- }
if(tpmif->fe_path) {
free(tpmif->fe_path);
}
@@ -430,12 +433,6 @@ tpmif_t* new_tpmif(domid_t domid, unsigned int handle)
goto error;
}
- /* allocate pages to be used for shared mapping */
- if((tpmif->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE)) == NULL) {
- goto error;
- }
- memset(tpmif->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
-
if(tpmif_change_state(tpmif, XenbusStateInitWait)) {
goto error;
}
@@ -486,7 +483,7 @@ void free_tpmif(tpmif_t* tpmif)
tpmif->status = DISCONNECTING;
mask_evtchn(tpmif->evtchn);
- if(gntmap_munmap(&gtpmdev.map, (unsigned long)tpmif->tx, 1)) {
+ if(gntmap_munmap(&gtpmdev.map, (unsigned long)tpmif->page, 1)) {
TPMBACK_ERR("%u/%u Error occured while trying to unmap shared page\n", (unsigned int) tpmif->domid, tpmif->handle);
}
@@ -529,15 +526,28 @@ void free_tpmif(tpmif_t* tpmif)
void tpmback_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
{
tpmif_t* tpmif = (tpmif_t*) data;
- tpmif_tx_request_t* tx = &tpmif->tx->ring[0].req;
- /* Throw away 0 size events, these can trigger from event channel unmasking */
- if(tx->size == 0)
- return;
-
- TPMBACK_DEBUG("EVENT CHANNEL FIRE %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
- tpmif_req_ready(tpmif);
- wake_up(&waitq);
+ vtpm_shared_page_t* pg = tpmif->page;
+ switch (pg->state)
+ {
+ case VTPM_STATE_SUBMIT:
+ TPMBACK_DEBUG("EVENT CHANNEL FIRE %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
+ tpmif_req_ready(tpmif);
+ wake_up(&waitq);
+ break;
+ case VTPM_STATE_CANCEL:
+ /* If we are busy with a request, do nothing */
+ if (tpmif->flags & TPMIF_REQ_READY)
+ return;
+ /* Acknowledge the cancellation if we are idle */
+ pg->state = VTPM_STATE_IDLE;
+ wmb();
+ notify_remote_via_evtchn(tpmif->evtchn);
+ return;
+ default:
+ /* Spurious wakeup; do nothing */
+ return;
+ }
}
/* Connect to frontend */
@@ -584,12 +594,25 @@ int connect_fe(tpmif_t* tpmif)
}
free(value);
+ /* Check that protocol v2 is being used */
+ snprintf(path, 512, "%s/feature-protocol-v2", tpmif->fe_path);
+ if((err = xenbus_read(XBT_NIL, path, &value))) {
+ TPMBACK_ERR("Unable to read %s during tpmback initialization! error = %s\n", path, err);
+ free(err);
+ return -1;
+ }
+ if(strcmp(value, "1")) {
+ TPMBACK_ERR("%s has an invalid value (%s)\n", path, value);
+ free(value);
+ return -1;
+ }
+ free(value);
+
domid = tpmif->domid;
- if((tpmif->tx = gntmap_map_grant_refs(&gtpmdev.map, 1, &domid, 0, &ringref, PROT_READ | PROT_WRITE)) == NULL) {
+ if((tpmif->page = gntmap_map_grant_refs(&gtpmdev.map, 1, &domid, 0, &ringref, PROT_READ | PROT_WRITE)) == NULL) {
TPMBACK_ERR("Failed to map grant reference %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
return -1;
}
- memset(tpmif->tx, 0, PAGE_SIZE);
/*Bind the event channel */
if((evtchn_bind_interdomain(tpmif->domid, evtchn, tpmback_handler, tpmif, &tpmif->evtchn)))
@@ -618,7 +641,7 @@ error_post_evtchn:
mask_evtchn(tpmif->evtchn);
unbind_evtchn(tpmif->evtchn);
error_post_map:
- gntmap_munmap(&gtpmdev.map, (unsigned long)tpmif->tx, 1);
+ gntmap_munmap(&gtpmdev.map, (unsigned long)tpmif->page, 1);
return -1;
}
@@ -633,9 +656,9 @@ static int frontend_changed(tpmif_t* tpmif)
switch (state) {
case XenbusStateInitialising:
- case XenbusStateInitialised:
break;
+ case XenbusStateInitialised:
case XenbusStateConnected:
if(connect_fe(tpmif)) {
TPMBACK_ERR("Failed to connect to front end %u/%u\n", (unsigned int) tpmif->domid, tpmif->handle);
@@ -874,6 +897,7 @@ void shutdown_tpmback(void)
inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, unsigned char uuid[16])
{
tpmcmd->domid = domid;
+ tpmcmd->locality = -1;
tpmcmd->handle = handle;
memcpy(tpmcmd->uuid, uuid, sizeof(tpmcmd->uuid));
tpmcmd->req = NULL;
@@ -884,12 +908,12 @@ inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int handle, un
tpmcmd_t* get_request(tpmif_t* tpmif) {
tpmcmd_t* cmd;
- tpmif_tx_request_t* tx;
- int offset;
- int tocopy;
- int i;
- uint32_t domid;
+ vtpm_shared_page_t* shr;
+ unsigned int offset;
int flags;
+#ifdef TPMBACK_PRINT_DEBUG
+ int i;
+#endif
local_irq_save(flags);
@@ -899,35 +923,22 @@ tpmcmd_t* get_request(tpmif_t* tpmif) {
}
init_tpmcmd(cmd, tpmif->domid, tpmif->handle, tpmif->uuid);
- tx = &tpmif->tx->ring[0].req;
- cmd->req_len = tx->size;
+ shr = tpmif->page;
+ cmd->req_len = shr->length;
+ cmd->locality = shr->locality;
+ offset = sizeof(*shr) + 4*shr->nr_extra_pages;
+ if (offset > PAGE_SIZE || offset + cmd->req_len > PAGE_SIZE) {
+ TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
+ goto error;
+ }
/* Allocate the buffer */
if(cmd->req_len) {
if((cmd->req = malloc(cmd->req_len)) == NULL) {
goto error;
}
}
- /* Copy the bits from the shared pages */
- offset = 0;
- for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->req_len; ++i) {
- tx = &tpmif->tx->ring[i].req;
-
- /* Map the page with the data */
- domid = (uint32_t)tpmif->domid;
- if((tpmif->pages[i] = gntmap_map_grant_refs(&gtpmdev.map, 1, &domid, 0, &tx->ref, PROT_READ)) == NULL) {
- TPMBACK_ERR("%u/%u Unable to map shared page during read!\n", (unsigned int) tpmif->domid, tpmif->handle);
- goto error;
- }
-
- /* do the copy now */
- tocopy = min(cmd->req_len - offset, PAGE_SIZE);
- memcpy(&cmd->req[offset], tpmif->pages[i], tocopy);
- offset += tocopy;
-
- /* release the page */
- gntmap_munmap(&gtpmdev.map, (unsigned long)tpmif->pages[i], 1);
-
- }
+ /* Copy the bits from the shared page(s) */
+ memcpy(cmd->req, offset + (uint8_t*)shr, cmd->req_len);
#ifdef TPMBACK_PRINT_DEBUG
TPMBACK_DEBUG("Received Tpm Command from %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->req_len);
@@ -958,38 +969,24 @@ error:
void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
{
- tpmif_tx_request_t* tx;
- int offset;
- int i;
- uint32_t domid;
- int tocopy;
+ vtpm_shared_page_t* shr;
+ unsigned int offset;
int flags;
+#ifdef TPMBACK_PRINT_DEBUG
+int i;
+#endif
local_irq_save(flags);
- tx = &tpmif->tx->ring[0].req;
- tx->size = cmd->resp_len;
-
- offset = 0;
- for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->resp_len; ++i) {
- tx = &tpmif->tx->ring[i].req;
-
- /* Map the page with the data */
- domid = (uint32_t)tpmif->domid;
- if((tpmif->pages[i] = gntmap_map_grant_refs(&gtpmdev.map, 1, &domid, 0, &tx->ref, PROT_WRITE)) == NULL) {
- TPMBACK_ERR("%u/%u Unable to map shared page during write!\n", (unsigned int) tpmif->domid, tpmif->handle);
- goto error;
- }
-
- /* do the copy now */
- tocopy = min(cmd->resp_len - offset, PAGE_SIZE);
- memcpy(tpmif->pages[i], &cmd->resp[offset], tocopy);
- offset += tocopy;
-
- /* release the page */
- gntmap_munmap(&gtpmdev.map, (unsigned long)tpmif->pages[i], 1);
+ shr = tpmif->page;
+ shr->length = cmd->resp_len;
+ offset = sizeof(*shr) + 4*shr->nr_extra_pages;
+ if (offset > PAGE_SIZE || offset + cmd->resp_len > PAGE_SIZE) {
+ TPMBACK_ERR("%u/%u Command size too long for shared page!\n", (unsigned int) tpmif->domid, tpmif->handle);
+ goto error;
}
+ memcpy(offset + (uint8_t*)shr, cmd->resp, cmd->resp_len);
#ifdef TPMBACK_PRINT_DEBUG
TPMBACK_DEBUG("Sent response to %u/%u of size %u", (unsigned int) tpmif->domid, tpmif->handle, cmd->resp_len);
@@ -1003,6 +1000,9 @@ void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
#endif
/* clear the ready flag and send the event channel notice to the frontend */
tpmif_req_finished(tpmif);
+ barrier();
+ shr->state = VTPM_STATE_FINISH;
+ wmb();
notify_remote_via_evtchn(tpmif->evtchn);
error:
local_irq_restore(flags);
diff --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
index 0218d7fb84..9f930b5c6f 100644
--- a/extras/mini-os/tpmfront.c
+++ b/extras/mini-os/tpmfront.c
@@ -47,11 +47,21 @@
void tpmfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data) {
struct tpmfront_dev* dev = (struct tpmfront_dev*) data;
+ vtpm_shared_page_t* shr = dev->page;
/*If we get a response when we didnt make a request, just ignore it */
if(!dev->waiting) {
return;
}
+ switch (shr->state) {
+ case VTPM_STATE_FINISH: /* request was completed */
+ case VTPM_STATE_IDLE: /* request was cancelled */
+ break;
+ default:
+ /* Spurious wakeup; do nothing, request is still pending */
+ return;
+ }
+
dev->waiting = 0;
#ifdef HAVE_LIBC
if(dev->fd >= 0) {
@@ -176,7 +186,7 @@ static int wait_for_backend_state_changed(struct tpmfront_dev* dev, XenbusState
ret = wait_for_backend_closed(&events, path);
break;
default:
- break;
+ TPMFRONT_ERR("Bad wait state %d, ignoring\n", state);
}
if((err = xenbus_unwatch_path_token(XBT_NIL, path, path))) {
@@ -190,13 +200,13 @@ static int tpmfront_connect(struct tpmfront_dev* dev)
{
char* err;
/* Create shared page */
- dev->tx = (tpmif_tx_interface_t*) alloc_page();
- if(dev->tx == NULL) {
+ dev->page = (vtpm_shared_page_t*) alloc_page();
+ if(dev->page == NULL) {
TPMFRONT_ERR("Unable to allocate page for shared memory\n");
goto error;
}
- memset(dev->tx, 0, PAGE_SIZE);
- dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->tx), 0);
+ memset(dev->page, 0, PAGE_SIZE);
+ dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->page), 0);
TPMFRONT_DEBUG("grant ref is %lu\n", (unsigned long) dev->ring_ref);
/*Create event channel */
@@ -228,7 +238,7 @@ error_postevtchn:
unbind_evtchn(dev->evtchn);
error_postmap:
gnttab_end_access(dev->ring_ref);
- free_page(dev->tx);
+ free_page(dev->page);
error:
return -1;
}
@@ -240,7 +250,6 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
char path[512];
char* value, *err;
unsigned long long ival;
- int i;
printk("============= Init TPM Front ================\n");
@@ -279,6 +288,15 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
goto error;
}
+ /* Publish protocol v2 feature */
+ snprintf(path, 512, "%s/feature-protocol-v2", dev->nodename);
+ if ((err = xenbus_write(XBT_NIL, path, "1")))
+ {
+ TPMFRONT_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
+ free(err);
+ goto error;
+ }
+
/* Create and publish grant reference and event channel */
if (tpmfront_connect(dev)) {
goto error;
@@ -289,18 +307,19 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
goto error;
}
- /* Allocate pages that will contain the messages */
- dev->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE);
- if(dev->pages == NULL) {
+ /* Ensure backend is also using protocol v2 */
+ snprintf(path, 512, "%s/feature-protocol-v2", dev->bepath);
+ if((err = xenbus_read(XBT_NIL, path, &value))) {
+ TPMFRONT_ERR("Unable to read %s during tpmfront initialization! error = %s\n", path, err);
+ free(err);
goto error;
}
- memset(dev->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
- for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
- dev->pages[i] = (void*)alloc_page();
- if(dev->pages[i] == NULL) {
- goto error;
- }
+ if(strcmp(value, "1")) {
+ TPMFRONT_ERR("%s has an invalid value (%s)\n", path, value);
+ free(value);
+ goto error;
}
+ free(value);
TPMFRONT_LOG("Initialization Completed successfully\n");
@@ -314,8 +333,6 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
{
char* err;
char path[512];
- int i;
- tpmif_tx_request_t* tx;
if(dev == NULL) {
return;
}
@@ -349,27 +366,12 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
/* Wait for the backend to close and unmap shared pages, ignore any errors */
wait_for_backend_state_changed(dev, XenbusStateClosed);
- /* Cleanup any shared pages */
- if(dev->pages) {
- for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
- if(dev->pages[i]) {
- tx = &dev->tx->ring[i].req;
- if(tx->ref != 0) {
- gnttab_end_access(tx->ref);
- }
- free_page(dev->pages[i]);
- }
- }
- free(dev->pages);
- }
-
/* Close event channel and unmap shared page */
mask_evtchn(dev->evtchn);
unbind_evtchn(dev->evtchn);
gnttab_end_access(dev->ring_ref);
- free_page(dev->tx);
-
+ free_page(dev->page);
}
/* Cleanup memory usage */
@@ -387,13 +389,17 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
{
+ unsigned int offset;
+ vtpm_shared_page_t* shr = NULL;
+#ifdef TPMFRONT_PRINT_DEBUG
int i;
- tpmif_tx_request_t* tx = NULL;
+#endif
/* Error Checking */
if(dev == NULL || dev->state != XenbusStateConnected) {
TPMFRONT_ERR("Tried to send message through disconnected frontend\n");
return -1;
}
+ shr = dev->page;
#ifdef TPMFRONT_PRINT_DEBUG
TPMFRONT_DEBUG("Sending Msg to backend size=%u", (unsigned int) length);
@@ -407,19 +413,16 @@ int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
#endif
/* Copy to shared pages now */
- for(i = 0; length > 0 && i < TPMIF_TX_RING_SIZE; ++i) {
- /* Share the page */
- tx = &dev->tx->ring[i].req;
- tx->unused = 0;
- tx->addr = virt_to_mach(dev->pages[i]);
- tx->ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->pages[i]), 0);
- /* Copy the bits to the page */
- tx->size = length > PAGE_SIZE ? PAGE_SIZE : length;
- memcpy(dev->pages[i], &msg[i * PAGE_SIZE], tx->size);
-
- /* Update counters */
- length -= tx->size;
+ offset = sizeof(*shr);
+ if (length + offset > PAGE_SIZE) {
+ TPMFRONT_ERR("Message too long for shared page\n");
+ return -1;
}
+ memcpy(offset + (uint8_t*)shr, msg, length);
+ shr->length = length;
+ barrier();
+ shr->state = VTPM_STATE_SUBMIT;
+
dev->waiting = 1;
dev->resplen = 0;
#ifdef HAVE_LIBC
@@ -429,49 +432,50 @@ int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t length)
files[dev->fd].tpmfront.offset = 0;
}
#endif
+ wmb();
notify_remote_via_evtchn(dev->evtchn);
return 0;
}
int tpmfront_recv(struct tpmfront_dev* dev, uint8_t** msg, size_t *length)
{
- tpmif_tx_request_t* tx;
- int i;
+ unsigned int offset;
+ vtpm_shared_page_t* shr = NULL;
+#ifdef TPMFRONT_PRINT_DEBUG
+int i;
+#endif
if(dev == NULL || dev->state != XenbusStateConnected) {
TPMFRONT_ERR("Tried to receive message from disconnected frontend\n");
return -1;
}
/*Wait for the response */
wait_event(dev->waitq, (!dev->waiting));
+ shr = dev->page;
/* Initialize */
*msg = NULL;
*length = 0;
+ offset = sizeof(*shr);
- /* special case, just quit */
- tx = &dev->tx->ring[0].req;
- if(tx->size == 0 ) {
- goto quit;
- }
- /* Get the total size */
- tx = &dev->tx->ring[0].req;
- for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
- tx = &dev->tx->ring[i].req;
- *length += tx->size;
+ if (shr->state != VTPM_STATE_FINISH)
+ goto quit;
+
+ *length = shr->length;
+
+ if (*length + offset > PAGE_SIZE) {
+ TPMFRONT_ERR("Reply too long for shared page\n");
+ return -1;
}
+
/* Alloc the buffer */
if(dev->respbuf) {
free(dev->respbuf);
}
*msg = dev->respbuf = malloc(*length);
dev->resplen = *length;
+
/* Copy the bits */
- tx = &dev->tx->ring[0].req;
- for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
- tx = &dev->tx->ring[i].req;
- memcpy(&(*msg)[i * PAGE_SIZE], dev->pages[i], tx->size);
- gnttab_end_access(tx->ref);
- tx->ref = 0;
- }
+ memcpy(*msg, offset + (uint8_t*)shr, *length);
+
#ifdef TPMFRONT_PRINT_DEBUG
TPMFRONT_DEBUG("Received response from backend size=%u", (unsigned int) *length);
for(i = 0; i < *length; ++i) {
@@ -504,6 +508,14 @@ int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, uint8_t*
return 0;
}
+int tpmfront_set_locality(struct tpmfront_dev* dev, int locality)
+{
+ if (!dev || !dev->page)
+ return -1;
+ dev->page->locality = locality;
+ return 0;
+}
+
#ifdef HAVE_LIBC
#include <errno.h>
int tpmfront_open(struct tpmfront_dev* dev)