~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/ipxe/src/interface/xen/xenstore.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
                        asprintf ( &child_key, "%s/%s", key, child );
 
542
                        if ( ! child_key ) {
 
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
}