iPXE
xenstore.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 #include <stdint.h>
00027 #include <stdarg.h>
00028 #include <stdlib.h>
00029 #include <stdio.h>
00030 #include <string.h>
00031 #include <ipxe/io.h>
00032 #include <ipxe/nap.h>
00033 #include <ipxe/malloc.h>
00034 #include <ipxe/xen.h>
00035 #include <ipxe/xenevent.h>
00036 #include <ipxe/xenstore.h>
00037 
00038 /*
00039  * xs_wire.h attempts to define a static error table xsd_errors, which
00040  * interacts badly with the dynamically generated error numbers used
00041  * by iPXE.  Prevent this table from being constructed by including
00042  * errno.h only after including xs_wire.h.
00043  *
00044  */
00045 #include <xen/io/xs_wire.h>
00046 #include <errno.h>
00047 
00048 /** @file
00049  *
00050  * XenStore interface
00051  *
00052  */
00053 
00054 /** Request identifier */
00055 static uint32_t xenstore_req_id;
00056 
00057 /**
00058  * Send XenStore request raw data
00059  *
00060  * @v xen               Xen hypervisor
00061  * @v data              Data buffer
00062  * @v len               Length of data
00063  */
00064 static void xenstore_send ( struct xen_hypervisor *xen, const void *data,
00065                             size_t len ) {
00066         struct xenstore_domain_interface *intf = xen->store.intf;
00067         XENSTORE_RING_IDX prod = readl ( &intf->req_prod );
00068         XENSTORE_RING_IDX cons;
00069         XENSTORE_RING_IDX idx;
00070         const char *bytes = data;
00071         size_t offset = 0;
00072         size_t fill;
00073 
00074         DBGCP ( intf, "XENSTORE raw request:\n" );
00075         DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( prod ), data, len );
00076 
00077         /* Write one byte at a time */
00078         while ( offset < len ) {
00079 
00080                 /* Wait for space to become available */
00081                 while ( 1 ) {
00082                         cons = readl ( &intf->req_cons );
00083                         fill = ( prod - cons );
00084                         if ( fill < XENSTORE_RING_SIZE )
00085                                 break;
00086                         DBGC2 ( xen, "." );
00087                         cpu_nap();
00088                         rmb();
00089                 }
00090 
00091                 /* Write byte */
00092                 idx = MASK_XENSTORE_IDX ( prod++ );
00093                 writeb ( bytes[offset++], &intf->req[idx] );
00094         }
00095 
00096         /* Update producer counter */
00097         wmb();
00098         writel ( prod, &intf->req_prod );
00099         wmb();
00100 }
00101 
00102 /**
00103  * Send XenStore request string (excluding terminating NUL)
00104  *
00105  * @v xen               Xen hypervisor
00106  * @v string            String
00107  */
00108 static void xenstore_send_string ( struct xen_hypervisor *xen,
00109                                    const char *string ) {
00110 
00111         xenstore_send ( xen, string, strlen ( string ) );
00112 }
00113 
00114 /**
00115  * Receive XenStore response raw data
00116  *
00117  * @v xen               Xen hypervisor
00118  * @v data              Data buffer, or NULL to discard data
00119  * @v len               Length of data
00120  */
00121 static void xenstore_recv ( struct xen_hypervisor *xen, void *data,
00122                             size_t len ) {
00123         struct xenstore_domain_interface *intf = xen->store.intf;
00124         XENSTORE_RING_IDX cons = readl ( &intf->rsp_cons );
00125         XENSTORE_RING_IDX prod;
00126         XENSTORE_RING_IDX idx;
00127         char *bytes = data;
00128         size_t offset = 0;
00129         size_t fill;
00130 
00131         DBGCP ( intf, "XENSTORE raw response:\n" );
00132 
00133         /* Read one byte at a time */
00134         while ( offset < len ) {
00135 
00136                 /* Wait for data to be ready */
00137                 while ( 1 ) {
00138                         prod = readl ( &intf->rsp_prod );
00139                         fill = ( prod - cons );
00140                         if ( fill > 0 )
00141                                 break;
00142                         DBGC2 ( xen, "." );
00143                         cpu_nap();
00144                         rmb();
00145                 }
00146 
00147                 /* Read byte */
00148                 idx = MASK_XENSTORE_IDX ( cons++ );
00149                 if ( data )
00150                         bytes[offset++] = readb ( &intf->rsp[idx] );
00151         }
00152         if ( data )
00153                 DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( cons - len ), data, len );
00154 
00155         /* Update consumer counter */
00156         writel ( cons, &intf->rsp_cons );
00157         wmb();
00158 }
00159 
00160 /**
00161  * Send XenStore request
00162  *
00163  * @v xen               Xen hypervisor
00164  * @v type              Message type
00165  * @v req_id            Request ID
00166  * @v value             Value, or NULL to omit
00167  * @v key               Key path components
00168  * @ret rc              Return status code
00169  */
00170 static int xenstore_request ( struct xen_hypervisor *xen,
00171                               enum xsd_sockmsg_type type, uint32_t req_id,
00172                               const char *value, va_list key ) {
00173         struct xsd_sockmsg msg;
00174         struct evtchn_send event;
00175         const char *string;
00176         va_list tmp;
00177         int xenrc;
00178         int rc;
00179 
00180         /* Construct message header */
00181         msg.type = type;
00182         msg.req_id = req_id;
00183         msg.tx_id = 0;
00184         msg.len = 0;
00185         DBGC2 ( xen, "XENSTORE request ID %d type %d ", req_id, type );
00186 
00187         /* Calculate total length */
00188         va_copy ( tmp, key );
00189         while ( ( string = va_arg ( tmp, const char * ) ) != NULL ) {
00190                 DBGC2 ( xen, "%s%s", ( msg.len ? "/" : "" ), string );
00191                 msg.len += ( strlen ( string ) + 1 /* '/' or NUL */ );
00192         }
00193         va_end ( tmp );
00194         if ( value ) {
00195                 DBGC2 ( xen, " = \"%s\"", value );
00196                 msg.len += strlen ( value );
00197         }
00198         DBGC2 ( xen, "\n" );
00199 
00200         /* Send message */
00201         xenstore_send ( xen, &msg, sizeof ( msg ) );
00202         string = va_arg ( key, const char * );
00203         assert ( string != NULL );
00204         xenstore_send_string ( xen, string );
00205         while ( ( string = va_arg ( key, const char * ) ) != NULL ) {
00206                 xenstore_send_string ( xen, "/" );
00207                 xenstore_send_string ( xen, string );
00208         }
00209         xenstore_send ( xen, "", 1 ); /* Separating NUL */
00210         if ( value )
00211                 xenstore_send_string ( xen, value );
00212 
00213         /* Notify the back end */
00214         event.port = xen->store.port;
00215         if ( ( xenrc = xenevent_send ( xen, &event ) ) != 0 ) {
00216                 rc = -EXEN ( xenrc );
00217                 DBGC ( xen, "XENSTORE could not notify back end: %s\n",
00218                        strerror ( rc ) );
00219                 return rc;
00220         }
00221 
00222         return 0;
00223 }
00224 
00225 /**
00226  * Receive XenStore response
00227  *
00228  * @v xen               Xen hypervisor
00229  * @v req_id            Request ID
00230  * @v value             Value to fill in
00231  * @v len               Length to fill in
00232  * @ret rc              Return status code
00233  *
00234  * The caller is responsible for eventually calling free() on the
00235  * returned value.  Note that the value may comprise multiple
00236  * NUL-terminated strings concatenated together.  A terminating NUL
00237  * will always be appended to the returned value.
00238  */
00239 static int xenstore_response ( struct xen_hypervisor *xen, uint32_t req_id,
00240                                char **value, size_t *len ) {
00241         struct xsd_sockmsg msg;
00242         char *string;
00243         int rc;
00244 
00245         /* Wait for response to become available */
00246         while ( ! xenevent_pending ( xen, xen->store.port ) )
00247                 cpu_nap();
00248 
00249         /* Receive message header */
00250         xenstore_recv ( xen, &msg, sizeof ( msg ) );
00251         *len = msg.len;
00252 
00253         /* Allocate space for response */
00254         *value = zalloc ( msg.len + 1 /* terminating NUL */ );
00255 
00256         /* Receive data.  Do this even if allocation failed, or if the
00257          * request ID was incorrect, to avoid leaving data in the
00258          * ring.
00259          */
00260         xenstore_recv ( xen, *value, msg.len );
00261 
00262         /* Validate request ID */
00263         if ( msg.req_id != req_id ) {
00264                 DBGC ( xen, "XENSTORE response ID mismatch (got %d, expected "
00265                        "%d)\n", msg.req_id, req_id );
00266                 rc = -EPROTO;
00267                 goto err_req_id;
00268         }
00269 
00270         /* Check for allocation failure */
00271         if ( ! *value ) {
00272                 DBGC ( xen, "XENSTORE could not allocate %d bytes for "
00273                        "response\n", msg.len );
00274                 rc = -ENOMEM;
00275                 goto err_alloc;
00276         }
00277 
00278         /* Check for explicit errors */
00279         if ( msg.type == XS_ERROR ) {
00280                 DBGC ( xen, "XENSTORE response error \"%s\"\n", *value );
00281                 rc = -EIO;
00282                 goto err_explicit;
00283         }
00284 
00285         DBGC2 ( xen, "XENSTORE response ID %d\n", req_id );
00286         if ( DBG_EXTRA ) {
00287                 for ( string = *value ; string < ( *value + msg.len ) ;
00288                       string += ( strlen ( string ) + 1 /* NUL */ ) ) {
00289                         DBGC2 ( xen, " - \"%s\"\n", string );
00290                 }
00291         }
00292         return 0;
00293 
00294  err_explicit:
00295  err_alloc:
00296  err_req_id:
00297         free ( *value );
00298         *value = NULL;
00299         return rc;
00300 }
00301 
00302 /**
00303  * Issue a XenStore message
00304  *
00305  * @v xen               Xen hypervisor
00306  * @v type              Message type
00307  * @v response          Response value to fill in, or NULL to discard
00308  * @v len               Response length to fill in, or NULL to ignore
00309  * @v request           Request value, or NULL to omit
00310  * @v key               Key path components
00311  * @ret rc              Return status code
00312  */
00313 static int xenstore_message ( struct xen_hypervisor *xen,
00314                               enum xsd_sockmsg_type type, char **response,
00315                               size_t *len, const char *request, va_list key ) {
00316         char *response_value;
00317         size_t response_len;
00318         int rc;
00319 
00320         /* Send request */
00321         if ( ( rc = xenstore_request ( xen, type, ++xenstore_req_id,
00322                                        request, key ) ) != 0 )
00323                 return rc;
00324 
00325         /* Receive response */
00326         if ( ( rc = xenstore_response ( xen, xenstore_req_id, &response_value,
00327                                         &response_len ) ) != 0 )
00328                 return rc;
00329 
00330         /* Return response, if applicable */
00331         if ( response ) {
00332                 *response = response_value;
00333         } else {
00334                 free ( response_value );
00335         }
00336         if ( len )
00337                 *len = response_len;
00338 
00339         return 0;
00340 }
00341 
00342 /**
00343  * Read XenStore value
00344  *
00345  * @v xen               Xen hypervisor
00346  * @v value             Value to fill in
00347  * @v key               Key path components
00348  * @ret rc              Return status code
00349  *
00350  * On a successful return, the caller is responsible for calling
00351  * free() on the returned value.
00352  */
00353 static int xenstore_vread ( struct xen_hypervisor *xen, char **value,
00354                             va_list key ) {
00355 
00356         return xenstore_message ( xen, XS_READ, value, NULL, NULL, key );
00357 }
00358 
00359 /**
00360  * Read XenStore value
00361  *
00362  * @v xen               Xen hypervisor
00363  * @v value             Value to fill in
00364  * @v ...               Key path components
00365  * @ret rc              Return status code
00366  *
00367  * On a successful return, the caller is responsible for calling
00368  * free() on the returned value.
00369  */
00370 __attribute__ (( sentinel )) int
00371 xenstore_read ( struct xen_hypervisor *xen, char **value, ... ) {
00372         va_list key;
00373         int rc;
00374 
00375         va_start ( key, value );
00376         rc = xenstore_vread ( xen, value, key );
00377         va_end ( key );
00378         return rc;
00379 }
00380 
00381 /**
00382  * Read XenStore numeric value
00383  *
00384  * @v xen               Xen hypervisor
00385  * @v num               Numeric value to fill in
00386  * @v ...               Key path components
00387  * @ret rc              Return status code
00388  */
00389 __attribute__ (( sentinel )) int
00390 xenstore_read_num ( struct xen_hypervisor *xen, unsigned long *num, ... ) {
00391         va_list key;
00392         char *value;
00393         char *endp;
00394         int rc;
00395 
00396         /* Try to read text value */
00397         va_start ( key, num );
00398         rc = xenstore_vread ( xen, &value, key );
00399         va_end ( key );
00400         if ( rc != 0 )
00401                 goto err_read;
00402 
00403         /* Try to parse as numeric value */
00404         *num = strtoul ( value, &endp, 10 );
00405         if ( ( *value == '\0' ) || ( *endp != '\0' ) ) {
00406                 DBGC ( xen, "XENSTORE found invalid numeric value \"%s\"\n",
00407                        value );
00408                 rc = -EINVAL;
00409                 goto err_strtoul;
00410         }
00411 
00412  err_strtoul:
00413         free ( value );
00414  err_read:
00415         return rc;
00416 }
00417 
00418 /**
00419  * Write XenStore value
00420  *
00421  * @v xen               Xen hypervisor
00422  * @v value             Value
00423  * @v key               Key path components
00424  * @ret rc              Return status code
00425  */
00426 static int xenstore_vwrite ( struct xen_hypervisor *xen, const char *value,
00427                              va_list key ) {
00428 
00429         return xenstore_message ( xen, XS_WRITE, NULL, NULL, value, key );
00430 }
00431 
00432 /**
00433  * Write XenStore value
00434  *
00435  * @v xen               Xen hypervisor
00436  * @v value             Value
00437  * @v ...               Key path components
00438  * @ret rc              Return status code
00439  */
00440 __attribute__ (( sentinel )) int
00441 xenstore_write ( struct xen_hypervisor *xen, const char *value, ... ) {
00442         va_list key;
00443         int rc;
00444 
00445         va_start ( key, value );
00446         rc = xenstore_vwrite ( xen, value, key );
00447         va_end ( key );
00448         return rc;
00449 }
00450 
00451 /**
00452  * Write XenStore numeric value
00453  *
00454  * @v xen               Xen hypervisor
00455  * @v num               Numeric value
00456  * @v ...               Key path components
00457  * @ret rc              Return status code
00458  */
00459 __attribute__ (( sentinel )) int
00460 xenstore_write_num ( struct xen_hypervisor *xen, unsigned long num, ... ) {
00461         char value[ 21 /* "18446744073709551615" + NUL */ ];
00462         va_list key;
00463         int rc;
00464 
00465         /* Construct value */
00466         snprintf ( value, sizeof ( value ), "%ld", num );
00467 
00468         /* Write value */
00469         va_start ( key, num );
00470         rc = xenstore_vwrite ( xen, value, key );
00471         va_end ( key );
00472         return rc;
00473 }
00474 
00475 /**
00476  * Delete XenStore value
00477  *
00478  * @v xen               Xen hypervisor
00479  * @v ...               Key path components
00480  * @ret rc              Return status code
00481  */
00482 __attribute__ (( sentinel )) int
00483 xenstore_rm ( struct xen_hypervisor *xen, ... ) {
00484         va_list key;
00485         int rc;
00486 
00487         va_start ( key, xen );
00488         rc = xenstore_message ( xen, XS_RM, NULL, NULL, NULL, key );
00489         va_end ( key );
00490         return rc;
00491 }
00492 
00493 /**
00494  * Read XenStore directory
00495  *
00496  * @v xen               Xen hypervisor
00497  * @v children          Child key names to fill in
00498  * @v len               Length of child key names to fill in
00499  * @v ...               Key path components
00500  * @ret rc              Return status code
00501  */
00502 __attribute__ (( sentinel )) int
00503 xenstore_directory ( struct xen_hypervisor *xen, char **children, size_t *len,
00504                      ... ) {
00505         va_list key;
00506         int rc;
00507 
00508         va_start ( key, len );
00509         rc = xenstore_message ( xen, XS_DIRECTORY, children, len, NULL, key );
00510         va_end ( key );
00511         return rc;
00512 }
00513 
00514 /**
00515  * Dump XenStore directory contents (for debugging)
00516  *
00517  * @v xen               Xen hypervisor
00518  * @v key               Key
00519  */
00520 void xenstore_dump ( struct xen_hypervisor *xen, const char *key ) {
00521         char *value;
00522         char *children;
00523         char *child;
00524         char *child_key;
00525         size_t len;
00526         int rc;
00527 
00528         /* Try to dump current key as a value */
00529         if ( ( rc = xenstore_read ( xen, &value, key, NULL ) ) == 0 ) {
00530                 DBGC ( xen, "%s = \"%s\"\n", key, value );
00531                 free ( value );
00532         }
00533 
00534         /* Try to recurse into each child in turn */
00535         if ( ( rc = xenstore_directory ( xen, &children, &len, key,
00536                                          NULL ) ) == 0 ) {
00537                 for ( child = children ; child < ( children + len ) ;
00538                       child += ( strlen ( child ) + 1 /* NUL */ ) ) {
00539 
00540                         /* Construct child key */
00541                         if ( asprintf ( &child_key, "%s/%s", key, child ) < 0 ){
00542                                 DBGC ( xen, "XENSTORE could not allocate child "
00543                                        "key \"%s/%s\"\n", key, child );
00544                                 rc = -ENOMEM;
00545                                 break;
00546                         }
00547 
00548                         /* Recurse into child key, continuing on error */
00549                         xenstore_dump ( xen, child_key );
00550                         free ( child_key );
00551                 }
00552                 free ( children );
00553         }
00554 }