2 * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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
20 FILE_LICENCE ( GPL2_OR_LATER );
29 #include <ipxe/malloc.h>
31 #include <ipxe/xenevent.h>
32 #include <ipxe/xenstore.h>
35 * xs_wire.h attempts to define a static error table xsd_errors, which
36 * interacts badly with the dynamically generated error numbers used
37 * by iPXE. Prevent this table from being constructed by including
38 * errno.h only after including xs_wire.h.
41 #include <xen/io/xs_wire.h>
50 /** Request identifier */
51 static uint32_t xenstore_req_id;
54 * Send XenStore request raw data
56 * @v xen Xen hypervisor
58 * @v len Length of data
60 static void xenstore_send ( struct xen_hypervisor *xen, const void *data,
62 struct xenstore_domain_interface *intf = xen->store.intf;
63 XENSTORE_RING_IDX prod = readl ( &intf->req_prod );
64 XENSTORE_RING_IDX cons;
65 XENSTORE_RING_IDX idx;
66 const char *bytes = data;
70 DBGCP ( intf, "XENSTORE raw request:\n" );
71 DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( prod ), data, len );
73 /* Write one byte at a time */
74 while ( offset < len ) {
76 /* Wait for space to become available */
78 cons = readl ( &intf->req_cons );
79 fill = ( prod - cons );
80 if ( fill < XENSTORE_RING_SIZE )
88 idx = MASK_XENSTORE_IDX ( prod++ );
89 writeb ( bytes[offset++], &intf->req[idx] );
92 /* Update producer counter */
94 writel ( prod, &intf->req_prod );
99 * Send XenStore request string (excluding terminating NUL)
101 * @v xen Xen hypervisor
104 static void xenstore_send_string ( struct xen_hypervisor *xen,
105 const char *string ) {
107 xenstore_send ( xen, string, strlen ( string ) );
111 * Receive XenStore response raw data
113 * @v xen Xen hypervisor
114 * @v data Data buffer, or NULL to discard data
115 * @v len Length of data
117 static void xenstore_recv ( struct xen_hypervisor *xen, void *data,
119 struct xenstore_domain_interface *intf = xen->store.intf;
120 XENSTORE_RING_IDX cons = readl ( &intf->rsp_cons );
121 XENSTORE_RING_IDX prod;
122 XENSTORE_RING_IDX idx;
127 DBGCP ( intf, "XENSTORE raw response:\n" );
129 /* Read one byte at a time */
130 while ( offset < len ) {
132 /* Wait for data to be ready */
134 prod = readl ( &intf->rsp_prod );
135 fill = ( prod - cons );
144 idx = MASK_XENSTORE_IDX ( cons++ );
146 bytes[offset++] = readb ( &intf->rsp[idx] );
149 DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( cons - len ), data, len );
151 /* Update consumer counter */
152 writel ( cons, &intf->rsp_cons );
157 * Send XenStore request
159 * @v xen Xen hypervisor
160 * @v type Message type
161 * @v req_id Request ID
162 * @v value Value, or NULL to omit
163 * @v key Key path components
164 * @ret rc Return status code
166 static int xenstore_request ( struct xen_hypervisor *xen,
167 enum xsd_sockmsg_type type, uint32_t req_id,
168 const char *value, va_list key ) {
169 struct xsd_sockmsg msg;
170 struct evtchn_send event;
176 /* Construct message header */
181 DBGC2 ( xen, "XENSTORE request ID %d type %d ", req_id, type );
183 /* Calculate total length */
184 va_copy ( tmp, key );
185 while ( ( string = va_arg ( tmp, const char * ) ) != NULL ) {
186 DBGC2 ( xen, "%s%s", ( msg.len ? "/" : "" ), string );
187 msg.len += ( strlen ( string ) + 1 /* '/' or NUL */ );
191 DBGC2 ( xen, " = \"%s\"", value );
192 msg.len += strlen ( value );
197 xenstore_send ( xen, &msg, sizeof ( msg ) );
198 string = va_arg ( key, const char * );
199 assert ( string != NULL );
200 xenstore_send_string ( xen, string );
201 while ( ( string = va_arg ( key, const char * ) ) != NULL ) {
202 xenstore_send_string ( xen, "/" );
203 xenstore_send_string ( xen, string );
205 xenstore_send ( xen, "", 1 ); /* Separating NUL */
207 xenstore_send_string ( xen, value );
209 /* Notify the back end */
210 event.port = xen->store.port;
211 if ( ( xenrc = xenevent_send ( xen, &event ) ) != 0 ) {
212 rc = -EXEN ( xenrc );
213 DBGC ( xen, "XENSTORE could not notify back end: %s\n",
222 * Receive XenStore response
224 * @v xen Xen hypervisor
225 * @v req_id Request ID
226 * @v value Value to fill in
227 * @v len Length to fill in
228 * @ret rc Return status code
230 * The caller is responsible for eventually calling free() on the
231 * returned value. Note that the value may comprise multiple
232 * NUL-terminated strings concatenated together. A terminating NUL
233 * will always be appended to the returned value.
235 static int xenstore_response ( struct xen_hypervisor *xen, uint32_t req_id,
236 char **value, size_t *len ) {
237 struct xsd_sockmsg msg;
241 /* Receive message header */
242 xenstore_recv ( xen, &msg, sizeof ( msg ) );
245 /* Allocate space for response */
246 *value = zalloc ( msg.len + 1 /* terminating NUL */ );
248 /* Receive data. Do this even if allocation failed, or if the
249 * request ID was incorrect, to avoid leaving data in the
252 xenstore_recv ( xen, *value, msg.len );
254 /* Validate request ID */
255 if ( msg.req_id != req_id ) {
256 DBGC ( xen, "XENSTORE response ID mismatch (got %d, expected "
257 "%d)\n", msg.req_id, req_id );
262 /* Check for allocation failure */
264 DBGC ( xen, "XENSTORE could not allocate %d bytes for "
265 "response\n", msg.len );
270 /* Check for explicit errors */
271 if ( msg.type == XS_ERROR ) {
272 DBGC ( xen, "XENSTORE response error \"%s\"\n", *value );
277 DBGC2 ( xen, "XENSTORE response ID %d\n", req_id );
279 for ( string = *value ; string < ( *value + msg.len ) ;
280 string += ( strlen ( string ) + 1 /* NUL */ ) ) {
281 DBGC2 ( xen, " - \"%s\"\n", string );
295 * Issue a XenStore message
297 * @v xen Xen hypervisor
298 * @v type Message type
299 * @v response Response value to fill in, or NULL to discard
300 * @v len Response length to fill in, or NULL to ignore
301 * @v request Request value, or NULL to omit
302 * @v key Key path components
303 * @ret rc Return status code
305 static int xenstore_message ( struct xen_hypervisor *xen,
306 enum xsd_sockmsg_type type, char **response,
307 size_t *len, const char *request, va_list key ) {
308 char *response_value;
313 if ( ( rc = xenstore_request ( xen, type, ++xenstore_req_id,
314 request, key ) ) != 0 )
317 /* Receive response */
318 if ( ( rc = xenstore_response ( xen, xenstore_req_id, &response_value,
319 &response_len ) ) != 0 )
322 /* Return response, if applicable */
324 *response = response_value;
326 free ( response_value );
335 * Read XenStore value
337 * @v xen Xen hypervisor
338 * @v value Value to fill in
339 * @v key Key path components
340 * @ret rc Return status code
342 * On a successful return, the caller is responsible for calling
343 * free() on the returned value.
345 static int xenstore_vread ( struct xen_hypervisor *xen, char **value,
348 return xenstore_message ( xen, XS_READ, value, NULL, NULL, key );
352 * Read XenStore value
354 * @v xen Xen hypervisor
355 * @v value Value to fill in
356 * @v ... Key path components
357 * @ret rc Return status code
359 * On a successful return, the caller is responsible for calling
360 * free() on the returned value.
362 __attribute__ (( sentinel )) int
363 xenstore_read ( struct xen_hypervisor *xen, char **value, ... ) {
367 va_start ( key, value );
368 rc = xenstore_vread ( xen, value, key );
374 * Read XenStore numeric value
376 * @v xen Xen hypervisor
377 * @v num Numeric value to fill in
378 * @v ... Key path components
379 * @ret rc Return status code
381 __attribute__ (( sentinel )) int
382 xenstore_read_num ( struct xen_hypervisor *xen, unsigned long *num, ... ) {
388 /* Try to read text value */
389 va_start ( key, num );
390 rc = xenstore_vread ( xen, &value, key );
395 /* Try to parse as numeric value */
396 *num = strtoul ( value, &endp, 10 );
397 if ( ( *value == '\0' ) || ( *endp != '\0' ) ) {
398 DBGC ( xen, "XENSTORE found invalid numeric value \"%s\"\n",
411 * Write XenStore value
413 * @v xen Xen hypervisor
415 * @v key Key path components
416 * @ret rc Return status code
418 static int xenstore_vwrite ( struct xen_hypervisor *xen, const char *value,
421 return xenstore_message ( xen, XS_WRITE, NULL, NULL, value, key );
425 * Write XenStore value
427 * @v xen Xen hypervisor
429 * @v ... Key path components
430 * @ret rc Return status code
432 __attribute__ (( sentinel )) int
433 xenstore_write ( struct xen_hypervisor *xen, const char *value, ... ) {
437 va_start ( key, value );
438 rc = xenstore_vwrite ( xen, value, key );
444 * Write XenStore numeric value
446 * @v xen Xen hypervisor
447 * @v num Numeric value
448 * @v ... Key path components
449 * @ret rc Return status code
451 __attribute__ (( sentinel )) int
452 xenstore_write_num ( struct xen_hypervisor *xen, unsigned long num, ... ) {
453 char value[ 21 /* "18446744073709551615" + NUL */ ];
457 /* Construct value */
458 snprintf ( value, sizeof ( value ), "%ld", num );
461 va_start ( key, num );
462 rc = xenstore_vwrite ( xen, value, key );
468 * Delete XenStore value
470 * @v xen Xen hypervisor
471 * @v ... Key path components
472 * @ret rc Return status code
474 __attribute__ (( sentinel )) int
475 xenstore_rm ( struct xen_hypervisor *xen, ... ) {
479 va_start ( key, xen );
480 rc = xenstore_message ( xen, XS_RM, NULL, NULL, NULL, key );
486 * Read XenStore directory
488 * @v xen Xen hypervisor
489 * @v children Child key names to fill in
490 * @v len Length of child key names to fill in
491 * @v ... Key path components
492 * @ret rc Return status code
494 __attribute__ (( sentinel )) int
495 xenstore_directory ( struct xen_hypervisor *xen, char **children, size_t *len,
500 va_start ( key, len );
501 rc = xenstore_message ( xen, XS_DIRECTORY, children, len, NULL, key );
507 * Dump XenStore directory contents (for debugging)
509 * @v xen Xen hypervisor
512 void xenstore_dump ( struct xen_hypervisor *xen, const char *key ) {
520 /* Try to dump current key as a value */
521 if ( ( rc = xenstore_read ( xen, &value, key, NULL ) ) == 0 ) {
522 DBGC ( xen, "%s = \"%s\"\n", key, value );
526 /* Try to recurse into each child in turn */
527 if ( ( rc = xenstore_directory ( xen, &children, &len, key,
529 for ( child = children ; child < ( children + len ) ;
530 child += ( strlen ( child ) + 1 /* NUL */ ) ) {
532 /* Construct child key */
533 asprintf ( &child_key, "%s/%s", key, child );
535 DBGC ( xen, "XENSTORE could not allocate child "
536 "key \"%s/%s\"\n", key, child );
541 /* Recurse into child key, continuing on error */
542 xenstore_dump ( xen, child_key );