[efi] Do not raise TPL within EFI_DRIVER_BINDING_PROTOCOL.Supported()
[ipxe.git] / src / interface / xen / xenstore.c
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 */
55 static uint32_t xenstore_req_id;
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 );
68 XENSTORE_RING_IDX cons;
69 XENSTORE_RING_IDX idx;
70 const char *bytes = data;
71 size_t offset = 0;
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 while ( offset < len ) {
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 = 0;
129 size_t fill;
130
131 DBGCP ( intf, "XENSTORE raw response:\n" );
132
133 /* Read one byte at a time */
134 while ( offset < len ) {
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 );
509 rc = xenstore_message ( xen, XS_DIRECTORY, children, len, NULL, key );
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 }