iPXE
|
XenStore interface. More...
#include <stdint.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ipxe/io.h>
#include <ipxe/nap.h>
#include <ipxe/malloc.h>
#include <ipxe/xen.h>
#include <ipxe/xenevent.h>
#include <ipxe/xenstore.h>
#include <xen/io/xs_wire.h>
#include <errno.h>
Go to the source code of this file.
Functions | |
FILE_LICENCE (GPL2_OR_LATER_OR_UBDL) | |
static void | xenstore_send (struct xen_hypervisor *xen, const void *data, size_t len) |
Send XenStore request raw data. | |
static void | xenstore_send_string (struct xen_hypervisor *xen, const char *string) |
Send XenStore request string (excluding terminating NUL) | |
static void | xenstore_recv (struct xen_hypervisor *xen, void *data, size_t len) |
Receive XenStore response raw data. | |
static int | xenstore_request (struct xen_hypervisor *xen, enum xsd_sockmsg_type type, uint32_t req_id, const char *value, va_list key) |
Send XenStore request. | |
static int | xenstore_response (struct xen_hypervisor *xen, uint32_t req_id, char **value, size_t *len) |
Receive XenStore response. | |
static int | xenstore_message (struct xen_hypervisor *xen, enum xsd_sockmsg_type type, char **response, size_t *len, const char *request, va_list key) |
Issue a XenStore message. | |
static int | xenstore_vread (struct xen_hypervisor *xen, char **value, va_list key) |
Read XenStore value. | |
int | xenstore_read (struct xen_hypervisor *xen, char **value,...) |
Read XenStore value. | |
int | xenstore_read_num (struct xen_hypervisor *xen, unsigned long *num,...) |
Read XenStore numeric value. | |
static int | xenstore_vwrite (struct xen_hypervisor *xen, const char *value, va_list key) |
Write XenStore value. | |
int | xenstore_write (struct xen_hypervisor *xen, const char *value,...) |
Write XenStore value. | |
int | xenstore_write_num (struct xen_hypervisor *xen, unsigned long num,...) |
Write XenStore numeric value. | |
int | xenstore_rm (struct xen_hypervisor *xen,...) |
Delete XenStore value. | |
int | xenstore_directory (struct xen_hypervisor *xen, char **children, size_t *len,...) |
Read XenStore directory. | |
void | xenstore_dump (struct xen_hypervisor *xen, const char *key) |
Dump XenStore directory contents (for debugging) | |
Variables | |
static uint32_t | xenstore_req_id |
Request identifier. |
XenStore interface.
Definition in file xenstore.c.
FILE_LICENCE | ( | GPL2_OR_LATER_OR_UBDL | ) |
static void xenstore_send | ( | struct xen_hypervisor * | xen, |
const void * | data, | ||
size_t | len | ||
) | [static] |
Send XenStore request raw data.
xen | Xen hypervisor |
data | Data buffer |
len | Length of data |
Definition at line 64 of file xenstore.c.
References bytes, cons, cpu_nap(), data, DBGC2, DBGCP, DBGCP_HDA, fill, xen_store::intf, MASK_XENSTORE_IDX, offset, readl(), xenstore_domain_interface::req, xenstore_domain_interface::req_cons, xenstore_domain_interface::req_prod, rmb, xen_hypervisor::store, wmb, writeb(), writel(), and XENSTORE_RING_SIZE.
Referenced by xenstore_request(), and xenstore_send_string().
{ struct xenstore_domain_interface *intf = xen->store.intf; XENSTORE_RING_IDX prod = readl ( &intf->req_prod ); XENSTORE_RING_IDX cons; XENSTORE_RING_IDX idx; const char *bytes = data; size_t offset = 0; size_t fill; DBGCP ( intf, "XENSTORE raw request:\n" ); DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( prod ), data, len ); /* Write one byte at a time */ while ( offset < len ) { /* Wait for space to become available */ while ( 1 ) { cons = readl ( &intf->req_cons ); fill = ( prod - cons ); if ( fill < XENSTORE_RING_SIZE ) break; DBGC2 ( xen, "." ); cpu_nap(); rmb(); } /* Write byte */ idx = MASK_XENSTORE_IDX ( prod++ ); writeb ( bytes[offset++], &intf->req[idx] ); } /* Update producer counter */ wmb(); writel ( prod, &intf->req_prod ); wmb(); }
static void xenstore_send_string | ( | struct xen_hypervisor * | xen, |
const char * | string | ||
) | [static] |
Send XenStore request string (excluding terminating NUL)
xen | Xen hypervisor |
string | String |
Definition at line 108 of file xenstore.c.
References strlen(), and xenstore_send().
Referenced by xenstore_request().
{ xenstore_send ( xen, string, strlen ( string ) ); }
static void xenstore_recv | ( | struct xen_hypervisor * | xen, |
void * | data, | ||
size_t | len | ||
) | [static] |
Receive XenStore response raw data.
xen | Xen hypervisor |
data | Data buffer, or NULL to discard data |
len | Length of data |
Definition at line 121 of file xenstore.c.
References bytes, cons, cpu_nap(), data, DBGC2, DBGCP, DBGCP_HDA, fill, xen_store::intf, MASK_XENSTORE_IDX, offset, readb(), readl(), rmb, xenstore_domain_interface::rsp, xenstore_domain_interface::rsp_cons, xenstore_domain_interface::rsp_prod, xen_hypervisor::store, wmb, and writel().
Referenced by xenstore_response().
{ struct xenstore_domain_interface *intf = xen->store.intf; XENSTORE_RING_IDX cons = readl ( &intf->rsp_cons ); XENSTORE_RING_IDX prod; XENSTORE_RING_IDX idx; char *bytes = data; size_t offset = 0; size_t fill; DBGCP ( intf, "XENSTORE raw response:\n" ); /* Read one byte at a time */ while ( offset < len ) { /* Wait for data to be ready */ while ( 1 ) { prod = readl ( &intf->rsp_prod ); fill = ( prod - cons ); if ( fill > 0 ) break; DBGC2 ( xen, "." ); cpu_nap(); rmb(); } /* Read byte */ idx = MASK_XENSTORE_IDX ( cons++ ); if ( data ) bytes[offset++] = readb ( &intf->rsp[idx] ); } if ( data ) DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( cons - len ), data, len ); /* Update consumer counter */ writel ( cons, &intf->rsp_cons ); wmb(); }
static int xenstore_request | ( | struct xen_hypervisor * | xen, |
enum xsd_sockmsg_type | type, | ||
uint32_t | req_id, | ||
const char * | value, | ||
va_list | key | ||
) | [static] |
Send XenStore request.
xen | Xen hypervisor |
type | Message type |
req_id | Request ID |
value | Value, or NULL to omit |
key | Key path components |
rc | Return status code |
Definition at line 170 of file xenstore.c.
References assert, DBGC, DBGC2, EXEN, xsd_sockmsg::len, NULL, xen_store::port, rc, xsd_sockmsg::req_id, xen_hypervisor::store, strerror(), string, strlen(), xsd_sockmsg::tx_id, xsd_sockmsg::type, type, va_arg, va_copy, va_end, xenstore_send(), and xenstore_send_string().
Referenced by xenstore_message().
{ struct xsd_sockmsg msg; struct evtchn_send event; const char *string; va_list tmp; int xenrc; int rc; /* Construct message header */ msg.type = type; msg.req_id = req_id; msg.tx_id = 0; msg.len = 0; DBGC2 ( xen, "XENSTORE request ID %d type %d ", req_id, type ); /* Calculate total length */ va_copy ( tmp, key ); while ( ( string = va_arg ( tmp, const char * ) ) != NULL ) { DBGC2 ( xen, "%s%s", ( msg.len ? "/" : "" ), string ); msg.len += ( strlen ( string ) + 1 /* '/' or NUL */ ); } va_end ( tmp ); if ( value ) { DBGC2 ( xen, " = \"%s\"", value ); msg.len += strlen ( value ); } DBGC2 ( xen, "\n" ); /* Send message */ xenstore_send ( xen, &msg, sizeof ( msg ) ); string = va_arg ( key, const char * ); assert ( string != NULL ); xenstore_send_string ( xen, string ); while ( ( string = va_arg ( key, const char * ) ) != NULL ) { xenstore_send_string ( xen, "/" ); xenstore_send_string ( xen, string ); } xenstore_send ( xen, "", 1 ); /* Separating NUL */ if ( value ) xenstore_send_string ( xen, value ); /* Notify the back end */ event.port = xen->store.port; if ( ( xenrc = xenevent_send ( xen, &event ) ) != 0 ) { rc = -EXEN ( xenrc ); DBGC ( xen, "XENSTORE could not notify back end: %s\n", strerror ( rc ) ); return rc; } return 0; }
static int xenstore_response | ( | struct xen_hypervisor * | xen, |
uint32_t | req_id, | ||
char ** | value, | ||
size_t * | len | ||
) | [static] |
Receive XenStore response.
xen | Xen hypervisor |
req_id | Request ID |
value | Value to fill in |
len | Length to fill in |
rc | Return status code |
The caller is responsible for eventually calling free() on the returned value. Note that the value may comprise multiple NUL-terminated strings concatenated together. A terminating NUL will always be appended to the returned value.
Definition at line 239 of file xenstore.c.
References cpu_nap(), DBG_EXTRA, DBGC, DBGC2, EIO, ENOMEM, EPROTO, free, xsd_sockmsg::len, NULL, xen_store::port, rc, xsd_sockmsg::req_id, xen_hypervisor::store, string, strlen(), xsd_sockmsg::type, xenstore_recv(), XS_ERROR, and zalloc().
Referenced by xenstore_message().
{ struct xsd_sockmsg msg; char *string; int rc; /* Wait for response to become available */ while ( ! xenevent_pending ( xen, xen->store.port ) ) cpu_nap(); /* Receive message header */ xenstore_recv ( xen, &msg, sizeof ( msg ) ); *len = msg.len; /* Allocate space for response */ *value = zalloc ( msg.len + 1 /* terminating NUL */ ); /* Receive data. Do this even if allocation failed, or if the * request ID was incorrect, to avoid leaving data in the * ring. */ xenstore_recv ( xen, *value, msg.len ); /* Validate request ID */ if ( msg.req_id != req_id ) { DBGC ( xen, "XENSTORE response ID mismatch (got %d, expected " "%d)\n", msg.req_id, req_id ); rc = -EPROTO; goto err_req_id; } /* Check for allocation failure */ if ( ! *value ) { DBGC ( xen, "XENSTORE could not allocate %d bytes for " "response\n", msg.len ); rc = -ENOMEM; goto err_alloc; } /* Check for explicit errors */ if ( msg.type == XS_ERROR ) { DBGC ( xen, "XENSTORE response error \"%s\"\n", *value ); rc = -EIO; goto err_explicit; } DBGC2 ( xen, "XENSTORE response ID %d\n", req_id ); if ( DBG_EXTRA ) { for ( string = *value ; string < ( *value + msg.len ) ; string += ( strlen ( string ) + 1 /* NUL */ ) ) { DBGC2 ( xen, " - \"%s\"\n", string ); } } return 0; err_explicit: err_alloc: err_req_id: free ( *value ); *value = NULL; return rc; }
static int xenstore_message | ( | struct xen_hypervisor * | xen, |
enum xsd_sockmsg_type | type, | ||
char ** | response, | ||
size_t * | len, | ||
const char * | request, | ||
va_list | key | ||
) | [static] |
Issue a XenStore message.
xen | Xen hypervisor |
type | Message type |
response | Response value to fill in, or NULL to discard |
len | Response length to fill in, or NULL to ignore |
request | Request value, or NULL to omit |
key | Key path components |
rc | Return status code |
Definition at line 313 of file xenstore.c.
References free, rc, xenstore_req_id, xenstore_request(), and xenstore_response().
Referenced by xenstore_directory(), xenstore_rm(), xenstore_vread(), and xenstore_vwrite().
{ char *response_value; size_t response_len; int rc; /* Send request */ if ( ( rc = xenstore_request ( xen, type, ++xenstore_req_id, request, key ) ) != 0 ) return rc; /* Receive response */ if ( ( rc = xenstore_response ( xen, xenstore_req_id, &response_value, &response_len ) ) != 0 ) return rc; /* Return response, if applicable */ if ( response ) { *response = response_value; } else { free ( response_value ); } if ( len ) *len = response_len; return 0; }
static int xenstore_vread | ( | struct xen_hypervisor * | xen, |
char ** | value, | ||
va_list | key | ||
) | [static] |
Read XenStore value.
xen | Xen hypervisor |
value | Value to fill in |
key | Key path components |
rc | Return status code |
On a successful return, the caller is responsible for calling free() on the returned value.
Definition at line 353 of file xenstore.c.
References NULL, xenstore_message(), and XS_READ.
Referenced by xenstore_read(), and xenstore_read_num().
int xenstore_read | ( | struct xen_hypervisor * | xen, |
char ** | value, | ||
... | |||
) |
Read XenStore value.
xen | Xen hypervisor |
value | Value to fill in |
... | Key path components |
rc | Return status code |
On a successful return, the caller is responsible for calling free() on the returned value.
Definition at line 371 of file xenstore.c.
References key, rc, va_end, va_start, and xenstore_vread().
Referenced by hvm_map_xenstore(), netfront_read_mac(), xenbus_probe_device(), and xenstore_dump().
int xenstore_read_num | ( | struct xen_hypervisor * | xen, |
unsigned long * | num, | ||
... | |||
) |
Read XenStore numeric value.
xen | Xen hypervisor |
num | Numeric value to fill in |
... | Key path components |
rc | Return status code |
Definition at line 390 of file xenstore.c.
References DBGC, EINVAL, free, key, rc, strtoul(), va_end, va_start, value, and xenstore_vread().
Referenced by xenbus_backend_state(), and xenbus_probe_device().
{ va_list key; char *value; char *endp; int rc; /* Try to read text value */ va_start ( key, num ); rc = xenstore_vread ( xen, &value, key ); va_end ( key ); if ( rc != 0 ) goto err_read; /* Try to parse as numeric value */ *num = strtoul ( value, &endp, 10 ); if ( ( *value == '\0' ) || ( *endp != '\0' ) ) { DBGC ( xen, "XENSTORE found invalid numeric value \"%s\"\n", value ); rc = -EINVAL; goto err_strtoul; } err_strtoul: free ( value ); err_read: return rc; }
static int xenstore_vwrite | ( | struct xen_hypervisor * | xen, |
const char * | value, | ||
va_list | key | ||
) | [static] |
Write XenStore value.
xen | Xen hypervisor |
value | Value |
key | Key path components |
rc | Return status code |
Definition at line 426 of file xenstore.c.
References NULL, xenstore_message(), and XS_WRITE.
Referenced by xenstore_write(), and xenstore_write_num().
int xenstore_write | ( | struct xen_hypervisor * | xen, |
const char * | value, | ||
... | |||
) |
Write XenStore value.
xen | Xen hypervisor |
value | Value |
... | Key path components |
rc | Return status code |
Definition at line 441 of file xenstore.c.
References key, rc, va_end, va_start, and xenstore_vwrite().
int xenstore_write_num | ( | struct xen_hypervisor * | xen, |
unsigned long | num, | ||
... | |||
) |
Write XenStore numeric value.
xen | Xen hypervisor |
num | Numeric value |
... | Key path components |
rc | Return status code |
Definition at line 460 of file xenstore.c.
References key, rc, snprintf(), va_end, va_start, value, and xenstore_vwrite().
Referenced by netfront_write_num(), and xenbus_set_state().
int xenstore_rm | ( | struct xen_hypervisor * | xen, |
... | |||
) |
Delete XenStore value.
xen | Xen hypervisor |
... | Key path components |
rc | Return status code |
Definition at line 483 of file xenstore.c.
References key, NULL, rc, va_end, va_start, xenstore_message(), and XS_RM.
Referenced by netfront_rm().
int xenstore_directory | ( | struct xen_hypervisor * | xen, |
char ** | children, | ||
size_t * | len, | ||
... | |||
) |
Read XenStore directory.
xen | Xen hypervisor |
children | Child key names to fill in |
len | Length of child key names to fill in |
... | Key path components |
rc | Return status code |
Definition at line 503 of file xenstore.c.
References key, NULL, rc, va_end, va_start, xenstore_message(), and XS_DIRECTORY.
Referenced by xenbus_probe(), xenbus_probe_type(), and xenstore_dump().
void xenstore_dump | ( | struct xen_hypervisor * | xen, |
const char * | key | ||
) |
Dump XenStore directory contents (for debugging)
xen | Xen hypervisor |
key | Key |
Definition at line 520 of file xenstore.c.
References asprintf(), children, DBGC, ENOMEM, free, len, NULL, rc, strlen(), value, xenstore_directory(), xenstore_dump(), and xenstore_read().
Referenced by xenstore_dump().
{ char *value; char *children; char *child; char *child_key; size_t len; int rc; /* Try to dump current key as a value */ if ( ( rc = xenstore_read ( xen, &value, key, NULL ) ) == 0 ) { DBGC ( xen, "%s = \"%s\"\n", key, value ); free ( value ); } /* Try to recurse into each child in turn */ if ( ( rc = xenstore_directory ( xen, &children, &len, key, NULL ) ) == 0 ) { for ( child = children ; child < ( children + len ) ; child += ( strlen ( child ) + 1 /* NUL */ ) ) { /* Construct child key */ if ( asprintf ( &child_key, "%s/%s", key, child ) < 0 ){ DBGC ( xen, "XENSTORE could not allocate child " "key \"%s/%s\"\n", key, child ); rc = -ENOMEM; break; } /* Recurse into child key, continuing on error */ xenstore_dump ( xen, child_key ); free ( child_key ); } free ( children ); } }
uint32_t xenstore_req_id [static] |