iPXE
xenstore.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <stdint.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <ipxe/io.h>
32 #include <ipxe/nap.h>
33 #include <ipxe/malloc.h>
34 #include <ipxe/xen.h>
35 #include <ipxe/xenevent.h>
36 #include <ipxe/xenstore.h>
37 
38 /*
39  * xs_wire.h attempts to define a static error table xsd_errors, which
40  * interacts badly with the dynamically generated error numbers used
41  * by iPXE. Prevent this table from being constructed by including
42  * errno.h only after including xs_wire.h.
43  *
44  */
45 #include <xen/io/xs_wire.h>
46 #include <errno.h>
47 
48 /** @file
49  *
50  * XenStore interface
51  *
52  */
53 
54 /** Request identifier */
56 
57 /**
58  * Send XenStore request raw data
59  *
60  * @v xen Xen hypervisor
61  * @v data Data buffer
62  * @v len Length of data
63  */
64 static void xenstore_send ( struct xen_hypervisor *xen, const void *data,
65  size_t len ) {
66  struct xenstore_domain_interface *intf = xen->store.intf;
67  XENSTORE_RING_IDX prod = readl ( &intf->req_prod );
70  const char *bytes = data;
71  size_t offset;
72  size_t fill;
73 
74  DBGCP ( intf, "XENSTORE raw request:\n" );
75  DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( prod ), data, len );
76 
77  /* Write one byte at a time */
78  for ( offset = 0 ; offset < len ; offset++ ) {
79 
80  /* Wait for space to become available */
81  while ( 1 ) {
82  cons = readl ( &intf->req_cons );
83  fill = ( prod - cons );
84  if ( fill < XENSTORE_RING_SIZE )
85  break;
86  DBGC2 ( xen, "." );
87  cpu_nap();
88  rmb();
89  }
90 
91  /* Write byte */
92  idx = MASK_XENSTORE_IDX ( prod++ );
93  writeb ( bytes[offset], &intf->req[idx] );
94  }
95 
96  /* Update producer counter */
97  wmb();
98  writel ( prod, &intf->req_prod );
99  wmb();
100 }
101 
102 /**
103  * Send XenStore request string (excluding terminating NUL)
104  *
105  * @v xen Xen hypervisor
106  * @v string String
107  */
108 static void xenstore_send_string ( struct xen_hypervisor *xen,
109  const char *string ) {
110 
111  xenstore_send ( xen, string, strlen ( string ) );
112 }
113 
114 /**
115  * Receive XenStore response raw data
116  *
117  * @v xen Xen hypervisor
118  * @v data Data buffer, or NULL to discard data
119  * @v len Length of data
120  */
121 static void xenstore_recv ( struct xen_hypervisor *xen, void *data,
122  size_t len ) {
123  struct xenstore_domain_interface *intf = xen->store.intf;
124  XENSTORE_RING_IDX cons = readl ( &intf->rsp_cons );
125  XENSTORE_RING_IDX prod;
126  XENSTORE_RING_IDX idx;
127  char *bytes = data;
128  size_t offset;
129  size_t fill;
130 
131  DBGCP ( intf, "XENSTORE raw response:\n" );
132 
133  /* Read one byte at a time */
134  for ( offset = 0 ; offset < len ; offset++ ) {
135 
136  /* Wait for data to be ready */
137  while ( 1 ) {
138  prod = readl ( &intf->rsp_prod );
139  fill = ( prod - cons );
140  if ( fill > 0 )
141  break;
142  DBGC2 ( xen, "." );
143  cpu_nap();
144  rmb();
145  }
146 
147  /* Read byte */
148  idx = MASK_XENSTORE_IDX ( cons++ );
149  if ( data )
150  bytes[offset] = readb ( &intf->rsp[idx] );
151  }
152  if ( data )
153  DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( cons - len ), data, len );
154 
155  /* Update consumer counter */
156  writel ( cons, &intf->rsp_cons );
157  wmb();
158 }
159 
160 /**
161  * Send XenStore request
162  *
163  * @v xen Xen hypervisor
164  * @v type Message type
165  * @v req_id Request ID
166  * @v value Value, or NULL to omit
167  * @v key Key path components
168  * @ret rc Return status code
169  */
170 static int xenstore_request ( struct xen_hypervisor *xen,
171  enum xsd_sockmsg_type type, uint32_t req_id,
172  const char *value, va_list key ) {
173  struct xsd_sockmsg msg;
174  struct evtchn_send event;
175  const char *string;
176  va_list tmp;
177  int xenrc;
178  int rc;
179 
180  /* Construct message header */
181  msg.type = type;
182  msg.req_id = req_id;
183  msg.tx_id = 0;
184  msg.len = 0;
185  DBGC2 ( xen, "XENSTORE request ID %d type %d ", req_id, type );
186 
187  /* Calculate total length */
188  va_copy ( tmp, key );
189  while ( ( string = va_arg ( tmp, const char * ) ) != NULL ) {
190  DBGC2 ( xen, "%s%s", ( msg.len ? "/" : "" ), string );
191  msg.len += ( strlen ( string ) + 1 /* '/' or NUL */ );
192  }
193  va_end ( tmp );
194  if ( value ) {
195  DBGC2 ( xen, " = \"%s\"", value );
196  msg.len += strlen ( value );
197  }
198  DBGC2 ( xen, "\n" );
199 
200  /* Send message */
201  xenstore_send ( xen, &msg, sizeof ( msg ) );
202  string = va_arg ( key, const char * );
203  assert ( string != NULL );
204  xenstore_send_string ( xen, string );
205  while ( ( string = va_arg ( key, const char * ) ) != NULL ) {
206  xenstore_send_string ( xen, "/" );
207  xenstore_send_string ( xen, string );
208  }
209  xenstore_send ( xen, "", 1 ); /* Separating NUL */
210  if ( value )
211  xenstore_send_string ( xen, value );
212 
213  /* Notify the back end */
214  event.port = xen->store.port;
215  if ( ( xenrc = xenevent_send ( xen, &event ) ) != 0 ) {
216  rc = -EXEN ( xenrc );
217  DBGC ( xen, "XENSTORE could not notify back end: %s\n",
218  strerror ( rc ) );
219  return rc;
220  }
221 
222  return 0;
223 }
224 
225 /**
226  * Receive XenStore response
227  *
228  * @v xen Xen hypervisor
229  * @v req_id Request ID
230  * @v value Value to fill in
231  * @v len Length to fill in
232  * @ret rc Return status code
233  *
234  * The caller is responsible for eventually calling free() on the
235  * returned value. Note that the value may comprise multiple
236  * NUL-terminated strings concatenated together. A terminating NUL
237  * will always be appended to the returned value.
238  */
239 static int xenstore_response ( struct xen_hypervisor *xen, uint32_t req_id,
240  char **value, size_t *len ) {
241  struct xsd_sockmsg msg;
242  char *string;
243  int rc;
244 
245  /* Wait for response to become available */
246  while ( ! xenevent_pending ( xen, xen->store.port ) )
247  cpu_nap();
248 
249  /* Receive message header */
250  xenstore_recv ( xen, &msg, sizeof ( msg ) );
251  *len = msg.len;
252 
253  /* Allocate space for response */
254  *value = zalloc ( msg.len + 1 /* terminating NUL */ );
255 
256  /* Receive data. Do this even if allocation failed, or if the
257  * request ID was incorrect, to avoid leaving data in the
258  * ring.
259  */
260  xenstore_recv ( xen, *value, msg.len );
261 
262  /* Validate request ID */
263  if ( msg.req_id != req_id ) {
264  DBGC ( xen, "XENSTORE response ID mismatch (got %d, expected "
265  "%d)\n", msg.req_id, req_id );
266  rc = -EPROTO;
267  goto err_req_id;
268  }
269 
270  /* Check for allocation failure */
271  if ( ! *value ) {
272  DBGC ( xen, "XENSTORE could not allocate %d bytes for "
273  "response\n", msg.len );
274  rc = -ENOMEM;
275  goto err_alloc;
276  }
277 
278  /* Check for explicit errors */
279  if ( msg.type == XS_ERROR ) {
280  DBGC ( xen, "XENSTORE response error \"%s\"\n", *value );
281  rc = -EIO;
282  goto err_explicit;
283  }
284 
285  DBGC2 ( xen, "XENSTORE response ID %d\n", req_id );
286  if ( DBG_EXTRA ) {
287  for ( string = *value ; string < ( *value + msg.len ) ;
288  string += ( strlen ( string ) + 1 /* NUL */ ) ) {
289  DBGC2 ( xen, " - \"%s\"\n", string );
290  }
291  }
292  return 0;
293 
294  err_explicit:
295  err_alloc:
296  err_req_id:
297  free ( *value );
298  *value = NULL;
299  return rc;
300 }
301 
302 /**
303  * Issue a XenStore message
304  *
305  * @v xen Xen hypervisor
306  * @v type Message type
307  * @v response Response value to fill in, or NULL to discard
308  * @v len Response length to fill in, or NULL to ignore
309  * @v request Request value, or NULL to omit
310  * @v key Key path components
311  * @ret rc Return status code
312  */
313 static int xenstore_message ( struct xen_hypervisor *xen,
314  enum xsd_sockmsg_type type, char **response,
315  size_t *len, const char *request, va_list key ) {
316  char *response_value;
317  size_t response_len;
318  int rc;
319 
320  /* Send request */
321  if ( ( rc = xenstore_request ( xen, type, ++xenstore_req_id,
322  request, key ) ) != 0 )
323  return rc;
324 
325  /* Receive response */
326  if ( ( rc = xenstore_response ( xen, xenstore_req_id, &response_value,
327  &response_len ) ) != 0 )
328  return rc;
329 
330  /* Return response, if applicable */
331  if ( response ) {
332  *response = response_value;
333  } else {
334  free ( response_value );
335  }
336  if ( len )
337  *len = response_len;
338 
339  return 0;
340 }
341 
342 /**
343  * Read XenStore value
344  *
345  * @v xen Xen hypervisor
346  * @v value Value to fill in
347  * @v key Key path components
348  * @ret rc Return status code
349  *
350  * On a successful return, the caller is responsible for calling
351  * free() on the returned value.
352  */
353 static int xenstore_vread ( struct xen_hypervisor *xen, char **value,
354  va_list key ) {
355 
356  return xenstore_message ( xen, XS_READ, value, NULL, NULL, key );
357 }
358 
359 /**
360  * Read XenStore value
361  *
362  * @v xen Xen hypervisor
363  * @v value Value to fill in
364  * @v ... Key path components
365  * @ret rc Return status code
366  *
367  * On a successful return, the caller is responsible for calling
368  * free() on the returned value.
369  */
370 __attribute__ (( sentinel )) int
371 xenstore_read ( struct xen_hypervisor *xen, char **value, ... ) {
372  va_list key;
373  int rc;
374 
375  va_start ( key, value );
376  rc = xenstore_vread ( xen, value, key );
377  va_end ( key );
378  return rc;
379 }
380 
381 /**
382  * Read XenStore numeric value
383  *
384  * @v xen Xen hypervisor
385  * @v num Numeric value to fill in
386  * @v ... Key path components
387  * @ret rc Return status code
388  */
389 __attribute__ (( sentinel )) int
390 xenstore_read_num ( struct xen_hypervisor *xen, unsigned long *num, ... ) {
391  va_list key;
392  char *value;
393  char *endp;
394  int rc;
395 
396  /* Try to read text value */
397  va_start ( key, num );
398  rc = xenstore_vread ( xen, &value, key );
399  va_end ( key );
400  if ( rc != 0 )
401  goto err_read;
402 
403  /* Try to parse as numeric value */
404  *num = strtoul ( value, &endp, 10 );
405  if ( ( *value == '\0' ) || ( *endp != '\0' ) ) {
406  DBGC ( xen, "XENSTORE found invalid numeric value \"%s\"\n",
407  value );
408  rc = -EINVAL;
409  goto err_strtoul;
410  }
411 
412  err_strtoul:
413  free ( value );
414  err_read:
415  return rc;
416 }
417 
418 /**
419  * Write XenStore value
420  *
421  * @v xen Xen hypervisor
422  * @v value Value
423  * @v key Key path components
424  * @ret rc Return status code
425  */
426 static int xenstore_vwrite ( struct xen_hypervisor *xen, const char *value,
427  va_list key ) {
428 
429  return xenstore_message ( xen, XS_WRITE, NULL, NULL, value, key );
430 }
431 
432 /**
433  * Write XenStore value
434  *
435  * @v xen Xen hypervisor
436  * @v value Value
437  * @v ... Key path components
438  * @ret rc Return status code
439  */
440 __attribute__ (( sentinel )) int
441 xenstore_write ( struct xen_hypervisor *xen, const char *value, ... ) {
442  va_list key;
443  int rc;
444 
445  va_start ( key, value );
446  rc = xenstore_vwrite ( xen, value, key );
447  va_end ( key );
448  return rc;
449 }
450 
451 /**
452  * Write XenStore numeric value
453  *
454  * @v xen Xen hypervisor
455  * @v num Numeric value
456  * @v ... Key path components
457  * @ret rc Return status code
458  */
459 __attribute__ (( sentinel )) int
460 xenstore_write_num ( struct xen_hypervisor *xen, unsigned long num, ... ) {
461  char value[ 21 /* "18446744073709551615" + NUL */ ];
462  va_list key;
463  int rc;
464 
465  /* Construct value */
466  snprintf ( value, sizeof ( value ), "%ld", num );
467 
468  /* Write value */
469  va_start ( key, num );
470  rc = xenstore_vwrite ( xen, value, key );
471  va_end ( key );
472  return rc;
473 }
474 
475 /**
476  * Delete XenStore value
477  *
478  * @v xen Xen hypervisor
479  * @v ... Key path components
480  * @ret rc Return status code
481  */
482 __attribute__ (( sentinel )) int
483 xenstore_rm ( struct xen_hypervisor *xen, ... ) {
484  va_list key;
485  int rc;
486 
487  va_start ( key, xen );
488  rc = xenstore_message ( xen, XS_RM, NULL, NULL, NULL, key );
489  va_end ( key );
490  return rc;
491 }
492 
493 /**
494  * Read XenStore directory
495  *
496  * @v xen Xen hypervisor
497  * @v children Child key names to fill in
498  * @v len Length of child key names to fill in
499  * @v ... Key path components
500  * @ret rc Return status code
501  */
502 __attribute__ (( sentinel )) int
503 xenstore_directory ( struct xen_hypervisor *xen, char **children, size_t *len,
504  ... ) {
505  va_list key;
506  int rc;
507 
508  va_start ( key, len );
510  va_end ( key );
511  return rc;
512 }
513 
514 /**
515  * Dump XenStore directory contents (for debugging)
516  *
517  * @v xen Xen hypervisor
518  * @v key Key
519  */
520 void xenstore_dump ( struct xen_hypervisor *xen, const char *key ) {
521  char *value;
522  char *children;
523  char *child;
524  char *child_key;
525  size_t len;
526  int rc;
527 
528  /* Try to dump current key as a value */
529  if ( ( rc = xenstore_read ( xen, &value, key, NULL ) ) == 0 ) {
530  DBGC ( xen, "%s = \"%s\"\n", key, value );
531  free ( value );
532  }
533 
534  /* Try to recurse into each child in turn */
535  if ( ( rc = xenstore_directory ( xen, &children, &len, key,
536  NULL ) ) == 0 ) {
537  for ( child = children ; child < ( children + len ) ;
538  child += ( strlen ( child ) + 1 /* NUL */ ) ) {
539 
540  /* Construct child key */
541  if ( asprintf ( &child_key, "%s/%s", key, child ) < 0 ){
542  DBGC ( xen, "XENSTORE could not allocate child "
543  "key \"%s/%s\"\n", key, child );
544  rc = -ENOMEM;
545  break;
546  }
547 
548  /* Recurse into child key, continuing on error */
549  xenstore_dump ( xen, child_key );
550  free ( child_key );
551  }
552  free ( children );
553  }
554 }
CPU sleeping.
#define __attribute__(x)
Definition: compiler.h:10
#define EINVAL
Invalid argument.
Definition: errno.h:428
iPXE I/O API
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
Xen events.
wmb()
uint8_t readb(volatile uint8_t *io_addr)
Read byte from memory-mapped device.
#define va_end(ap)
Definition: stdarg.h:9
Definition: xs_wire.h:30
uint32_t XENSTORE_RING_IDX
Definition: xs_wire.h:105
unsigned long strtoul(const char *string, char **endp, int base)
Convert string to numeric value.
Definition: string.c:471
static int xenstore_response(struct xen_hypervisor *xen, uint32_t req_id, char **value, size_t *len)
Receive XenStore response.
Definition: xenstore.c:239
static void xenstore_recv(struct xen_hypervisor *xen, void *data, size_t len)
Receive XenStore response raw data.
Definition: xenstore.c:121
char req[XENSTORE_RING_SIZE]
Definition: xs_wire.h:108
Error codes.
uint32_t readl(volatile uint32_t *io_addr)
Read 32-bit dword from memory-mapped device.
#define DBGC(...)
Definition: compiler.h:505
XENSTORE_RING_IDX rsp_cons
Definition: xs_wire.h:111
static void xenstore_send(struct xen_hypervisor *xen, const void *data, size_t len)
Send XenStore request raw data.
Definition: xenstore.c:64
static int xenstore_vread(struct xen_hypervisor *xen, char **value, va_list key)
Read XenStore value.
Definition: xenstore.c:353
uint32_t string
Definition: multiboot.h:14
uint32_t req_id
Definition: xs_wire.h:87
#define va_copy(dest, src)
Definition: stdarg.h:10
int xenstore_read(struct xen_hypervisor *xen, char **value,...)
Read XenStore value.
Definition: xenstore.c:371
int xenstore_write_num(struct xen_hypervisor *xen, unsigned long num,...)
Write XenStore numeric value.
Definition: xenstore.c:460
int xenstore_write(struct xen_hypervisor *xen, const char *value,...)
Write XenStore value.
Definition: xenstore.c:441
void writeb(uint8_t data, volatile uint8_t *io_addr)
Write byte to memory-mapped device.
#define EXEN(xenrc)
Convert a Xen status code to an iPXE status code.
Definition: xen.h:87
Dynamic memory allocation.
A Xen hypervisor.
Definition: xen.h:51
Xen interface.
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.
Definition: xenstore.c:170
unsigned long tmp
Definition: linux_pci.h:53
#define DBGCP_HDA(...)
Definition: compiler.h:540
#define rmb()
Definition: io.h:484
#define ENOMEM
Not enough space.
Definition: errno.h:534
char unsigned long const char unsigned long char ** children
Definition: xenstore.h:25
#define va_arg(ap, type)
Definition: stdarg.h:8
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
void writel(uint32_t data, volatile uint32_t *io_addr)
Write 32-bit dword to memory-mapped device.
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
#define EPROTO
Protocol error.
Definition: errno.h:624
char unsigned long * num
Definition: xenstore.h:17
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
uint16_t cons
Consumer index.
Definition: ena.h:22
int xenstore_directory(struct xen_hypervisor *xen, char **children, size_t *len,...)
Read XenStore directory.
Definition: xenstore.c:503
int asprintf(char **strp, const char *fmt,...)
Write a formatted string to newly allocated memory.
Definition: asprintf.c:41
int xenstore_read_num(struct xen_hypervisor *xen, unsigned long *num,...)
Read XenStore numeric value.
Definition: xenstore.c:390
evtchn_port_t port
Event channel.
Definition: xen.h:47
size_t strlen(const char *src)
Get length of string.
Definition: string.c:243
XENSTORE_RING_IDX rsp_prod
Definition: xs_wire.h:111
void xenstore_dump(struct xen_hypervisor *xen, const char *key)
Dump XenStore directory contents (for debugging)
Definition: xenstore.c:520
unsigned int uint32_t
Definition: stdint.h:12
XENSTORE_RING_IDX req_prod
Definition: xs_wire.h:110
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.
Definition: xenstore.c:313
struct xenstore_domain_interface * intf
XenStore domain interface.
Definition: xen.h:45
uint32_t len
Length.
Definition: ena.h:14
uint32_t type
Operating system type.
Definition: ena.h:12
#define DBGC2(...)
Definition: compiler.h:522
static int xenstore_vwrite(struct xen_hypervisor *xen, const char *value, va_list key)
Write XenStore value.
Definition: xenstore.c:426
void cpu_nap(void)
Sleep until next CPU interrupt.
__builtin_va_list va_list
Definition: stdarg.h:6
#define EIO
Input/output error.
Definition: errno.h:433
XENSTORE_RING_IDX req_cons
Definition: xs_wire.h:110
u8 request[0]
List of IEs requested.
Definition: ieee80211.h:16
uint8_t fill
Length pair.
Definition: deflate.h:12
uint8_t data[48]
Additional event data.
Definition: ena.h:22
struct xen_store store
XenStore.
Definition: xen.h:59
xsd_sockmsg_type
Definition: xs_wire.h:14
static void xenstore_send_string(struct xen_hypervisor *xen, const char *string)
Send XenStore request string (excluding terminating NUL)
Definition: xenstore.c:108
#define DBGCP(...)
Definition: compiler.h:539
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:382
char rsp[XENSTORE_RING_SIZE]
Definition: xs_wire.h:109
#define DBG_EXTRA
Definition: compiler.h:319
#define va_start(ap, last)
Definition: stdarg.h:7
#define MASK_XENSTORE_IDX(idx)
Definition: xs_wire.h:106
uint8_t bytes[64]
Definition: ib_mad.h:16
#define XENSTORE_RING_SIZE
Definition: xs_wire.h:104
XenStore interface.
int xenstore_rm(struct xen_hypervisor *xen,...)
Delete XenStore value.
Definition: xenstore.c:483
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
String functions.
union @382 key
Sense key.
Definition: crypto.h:284
static uint32_t xenstore_req_id
Request identifier.
Definition: xenstore.c:55
static void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
Definition: settings_ui.c:285