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
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_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 */
65static 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 );
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 */
109static 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 */
122static void xenstore_recv ( struct xen_hypervisor *xen, void *data,
123 size_t len ) {
124 struct xenstore_domain_interface *intf = xen->store.intf;
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 */
171static 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 )
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 */
240static 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 */
314static 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 */
354static 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
372xenstore_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
391xenstore_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 */
427static 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
442xenstore_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
461xenstore_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
484xenstore_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
504xenstore_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 */
521void 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}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
union @162305117151260234136356364136041353210355154177 key
Sense key.
Definition scsi.h:3
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
pseudo_bit_t value[0x00020]
Definition arbel.h:2
unsigned int uint32_t
Definition stdint.h:12
static int fill
Definition string.h:209
int asprintf(char **strp, const char *fmt,...)
Write a formatted string to newly allocated memory.
Definition asprintf.c:42
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
uint16_t offset
Offset to command line.
Definition bzimage.h:3
ring len
Length.
Definition dwmac.h:226
uint16_t cons
Consumer index.
Definition ena.h:11
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t data[48]
Additional event data.
Definition ena.h:11
Error codes.
#define DBGCP_HDA(...)
Definition compiler.h:540
#define DBGC2(...)
Definition compiler.h:522
#define DBG_EXTRA
Definition compiler.h:319
#define DBGCP(...)
Definition compiler.h:539
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define EINVAL
Invalid argument.
Definition errno.h:429
#define EPROTO
Protocol error.
Definition errno.h:625
#define ENOMEM
Not enough space.
Definition errno.h:535
#define EIO
Input/output error.
Definition errno.h:434
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
uint8_t bytes[64]
Definition ib_mad.h:5
u8 request[0]
List of IEs requested.
Definition ieee80211.h:2
#define __attribute__(x)
Definition compiler.h:10
iPXE I/O API
#define rmb()
Definition io.h:545
#define wmb()
Definition io.h:546
CPU sleeping.
void cpu_nap(void)
Sleep with interrupts enabled until next CPU interrupt.
Xen interface.
#define EXEN(xenrc)
Convert a Xen status code to an iPXE status code.
Definition xen.h:87
String functions.
unsigned long tmp
Definition linux_pci.h:65
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
Dynamic memory allocation.
void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
Definition message.c:62
uint32_t num
Definition multiboot.h:0
uint32_t string
Definition multiboot.h:2
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define va_copy(dest, src)
Definition stdarg.h:11
#define va_arg(ap, type)
Definition stdarg.h:9
#define va_end(ap)
Definition stdarg.h:10
#define va_start(ap, last)
Definition stdarg.h:8
__builtin_va_list va_list
Definition stdarg.h:7
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
unsigned long strtoul(const char *string, char **endp, int base)
Convert string to numeric value.
Definition string.c:485
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
A Xen hypervisor.
Definition xen.h:51
struct xen_store store
XenStore.
Definition xen.h:59
struct xenstore_domain_interface * intf
XenStore domain interface.
Definition xen.h:45
evtchn_port_t port
Event channel.
Definition xen.h:47
XENSTORE_RING_IDX req_prod
Definition xs_wire.h:111
char req[XENSTORE_RING_SIZE]
Definition xs_wire.h:109
XENSTORE_RING_IDX rsp_prod
Definition xs_wire.h:112
XENSTORE_RING_IDX rsp_cons
Definition xs_wire.h:112
XENSTORE_RING_IDX req_cons
Definition xs_wire.h:111
char rsp[XENSTORE_RING_SIZE]
Definition xs_wire.h:110
uint32_t req_id
Definition xs_wire.h:88
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383
#define readl
Definition w89c840.c:157
#define writel
Definition w89c840.c:160
#define readb
Definition w89c840.c:155
#define writeb
Definition w89c840.c:158
Xen events.
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 int xenstore_vread(struct xen_hypervisor *xen, char **value, va_list key)
Read XenStore value.
Definition xenstore.c:354
static void xenstore_send_string(struct xen_hypervisor *xen, const char *string)
Send XenStore request string (excluding terminating NUL)
Definition xenstore.c:109
static void xenstore_send(struct xen_hypervisor *xen, const void *data, size_t len)
Send XenStore request raw data.
Definition xenstore.c:65
void xenstore_dump(struct xen_hypervisor *xen, const char *key)
Dump XenStore directory contents (for debugging)
Definition xenstore.c:521
int xenstore_directory(struct xen_hypervisor *xen, char **children, size_t *len,...)
Read XenStore directory.
Definition xenstore.c:504
int xenstore_rm(struct xen_hypervisor *xen,...)
Delete XenStore value.
Definition xenstore.c:484
int xenstore_read(struct xen_hypervisor *xen, char **value,...)
Read XenStore value.
Definition xenstore.c:372
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
int xenstore_read_num(struct xen_hypervisor *xen, unsigned long *num,...)
Read XenStore numeric value.
Definition xenstore.c:391
static void xenstore_recv(struct xen_hypervisor *xen, void *data, size_t len)
Receive XenStore response raw data.
Definition xenstore.c:122
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
int xenstore_write(struct xen_hypervisor *xen, const char *value,...)
Write XenStore value.
Definition xenstore.c:442
static uint32_t xenstore_req_id
Request identifier.
Definition xenstore.c:56
int xenstore_write_num(struct xen_hypervisor *xen, unsigned long num,...)
Write XenStore numeric value.
Definition xenstore.c:461
static int xenstore_vwrite(struct xen_hypervisor *xen, const char *value, va_list key)
Write XenStore value.
Definition xenstore.c:427
XenStore interface.
char unsigned long const char unsigned long char ** children
Definition xenstore.h:26
#define XENSTORE_RING_SIZE
Definition xs_wire.h:105
xsd_sockmsg_type
Definition xs_wire.h:16
@ XS_WRITE
Definition xs_wire.h:29
@ XS_DIRECTORY
Definition xs_wire.h:19
@ XS_READ
Definition xs_wire.h:20
@ XS_ERROR
Definition xs_wire.h:34
@ XS_RM
Definition xs_wire.h:31
#define MASK_XENSTORE_IDX(idx)
Definition xs_wire.h:107
uint32_t XENSTORE_RING_IDX
Definition xs_wire.h:106