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