iPXE
Functions | Variables
xenstore.c File Reference

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.

Detailed Description

XenStore interface.

Definition in file xenstore.c.


Function Documentation

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.

Parameters:
xenXen hypervisor
dataData buffer
lenLength 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)

Parameters:
xenXen hypervisor
stringString

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.

Parameters:
xenXen hypervisor
dataData buffer, or NULL to discard data
lenLength 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.

Parameters:
xenXen hypervisor
typeMessage type
req_idRequest ID
valueValue, or NULL to omit
keyKey path components
Return values:
rcReturn 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.

Parameters:
xenXen hypervisor
req_idRequest ID
valueValue to fill in
lenLength to fill in
Return values:
rcReturn 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.

Parameters:
xenXen hypervisor
typeMessage type
responseResponse value to fill in, or NULL to discard
lenResponse length to fill in, or NULL to ignore
requestRequest value, or NULL to omit
keyKey path components
Return values:
rcReturn 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.

Parameters:
xenXen hypervisor
valueValue to fill in
keyKey path components
Return values:
rcReturn 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().

                                          {

        return xenstore_message ( xen, XS_READ, value, NULL, NULL, key );
}
int xenstore_read ( struct xen_hypervisor xen,
char **  value,
  ... 
)

Read XenStore value.

Parameters:
xenXen hypervisor
valueValue to fill in
...Key path components
Return values:
rcReturn 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().

                                                                {
        va_list key;
        int rc;

        va_start ( key, value );
        rc = xenstore_vread ( xen, value, key );
        va_end ( key );
        return rc;
}
int xenstore_read_num ( struct xen_hypervisor xen,
unsigned long *  num,
  ... 
)

Read XenStore numeric value.

Parameters:
xenXen hypervisor
numNumeric value to fill in
...Key path components
Return values:
rcReturn 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.

Parameters:
xenXen hypervisor
valueValue
keyKey path components
Return values:
rcReturn 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().

                                           {

        return xenstore_message ( xen, XS_WRITE, NULL, NULL, value, key );
}
int xenstore_write ( struct xen_hypervisor xen,
const char *  value,
  ... 
)

Write XenStore value.

Parameters:
xenXen hypervisor
valueValue
...Key path components
Return values:
rcReturn status code

Definition at line 441 of file xenstore.c.

References key, rc, va_end, va_start, and xenstore_vwrite().

                                                                      {
        va_list key;
        int rc;

        va_start ( key, value );
        rc = xenstore_vwrite ( xen, value, key );
        va_end ( key );
        return rc;
}
int xenstore_write_num ( struct xen_hypervisor xen,
unsigned long  num,
  ... 
)

Write XenStore numeric value.

Parameters:
xenXen hypervisor
numNumeric value
...Key path components
Return values:
rcReturn 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().

                                                                          {
        char value[ 21 /* "18446744073709551615" + NUL */ ];
        va_list key;
        int rc;

        /* Construct value */
        snprintf ( value, sizeof ( value ), "%ld", num );

        /* Write value */
        va_start ( key, num );
        rc = xenstore_vwrite ( xen, value, key );
        va_end ( key );
        return rc;
}
int xenstore_rm ( struct xen_hypervisor xen,
  ... 
)

Delete XenStore value.

Parameters:
xenXen hypervisor
...Key path components
Return values:
rcReturn 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().

                                                {
        va_list key;
        int rc;

        va_start ( key, xen );
        rc = xenstore_message ( xen, XS_RM, NULL, NULL, NULL, key );
        va_end ( key );
        return rc;
}
int xenstore_directory ( struct xen_hypervisor xen,
char **  children,
size_t len,
  ... 
)

Read XenStore directory.

Parameters:
xenXen hypervisor
childrenChild key names to fill in
lenLength of child key names to fill in
...Key path components
Return values:
rcReturn 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().

                           {
        va_list key;
        int rc;

        va_start ( key, len );
        rc = xenstore_message ( xen, XS_DIRECTORY, children, len, NULL, key );
        va_end ( key );
        return rc;
}
void xenstore_dump ( struct xen_hypervisor xen,
const char *  key 
)

Dump XenStore directory contents (for debugging)

Parameters:
xenXen hypervisor
keyKey

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 );
        }
}

Variable Documentation

Request identifier.

Definition at line 55 of file xenstore.c.

Referenced by xenstore_message().