iPXE
xenbus.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 <stdio.h>
28#include <string.h>
29#include <errno.h>
30#include <ipxe/malloc.h>
31#include <ipxe/device.h>
32#include <ipxe/timer.h>
33#include <ipxe/nap.h>
34#include <ipxe/xen.h>
35#include <ipxe/xenstore.h>
36#include <ipxe/xenbus.h>
37
38/** @file
39 *
40 * Xen device bus
41 *
42 */
43
44/* Disambiguate the various error causes */
45#define ETIMEDOUT_UNKNOWN \
46 __einfo_error ( EINFO_ETIMEDOUT_UNKNOWN )
47#define EINFO_ETIMEDOUT_UNKNOWN \
48 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateUnknown, \
49 "Unknown" )
50#define ETIMEDOUT_INITIALISING \
51 __einfo_error ( EINFO_ETIMEDOUT_INITIALISING )
52#define EINFO_ETIMEDOUT_INITIALISING \
53 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateInitialising, \
54 "Initialising" )
55#define ETIMEDOUT_INITWAIT \
56 __einfo_error ( EINFO_ETIMEDOUT_INITWAIT )
57#define EINFO_ETIMEDOUT_INITWAIT \
58 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateInitWait, \
59 "InitWait" )
60#define ETIMEDOUT_INITIALISED \
61 __einfo_error ( EINFO_ETIMEDOUT_INITIALISED )
62#define EINFO_ETIMEDOUT_INITIALISED \
63 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateInitialised, \
64 "Initialised" )
65#define ETIMEDOUT_CONNECTED \
66 __einfo_error ( EINFO_ETIMEDOUT_CONNECTED )
67#define EINFO_ETIMEDOUT_CONNECTED \
68 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateConnected, \
69 "Connected" )
70#define ETIMEDOUT_CLOSING \
71 __einfo_error ( EINFO_ETIMEDOUT_CLOSING )
72#define EINFO_ETIMEDOUT_CLOSING \
73 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateClosing, \
74 "Closing" )
75#define ETIMEDOUT_CLOSED \
76 __einfo_error ( EINFO_ETIMEDOUT_CLOSED )
77#define EINFO_ETIMEDOUT_CLOSED \
78 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateClosed, \
79 "Closed" )
80#define ETIMEDOUT_RECONFIGURING \
81 __einfo_error ( EINFO_ETIMEDOUT_RECONFIGURING )
82#define EINFO_ETIMEDOUT_RECONFIGURING \
83 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateReconfiguring, \
84 "Reconfiguring" )
85#define ETIMEDOUT_RECONFIGURED \
86 __einfo_error ( EINFO_ETIMEDOUT_RECONFIGURED )
87#define EINFO_ETIMEDOUT_RECONFIGURED \
88 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateReconfigured, \
89 "Reconfigured" )
90#define ETIMEDOUT_STATE( state ) \
91 EUNIQ ( EINFO_ETIMEDOUT, (state), ETIMEDOUT_UNKNOWN, \
92 ETIMEDOUT_INITIALISING, ETIMEDOUT_INITWAIT, \
93 ETIMEDOUT_INITIALISED, ETIMEDOUT_CONNECTED, \
94 ETIMEDOUT_CLOSING, ETIMEDOUT_CLOSED, \
95 ETIMEDOUT_RECONFIGURING, ETIMEDOUT_RECONFIGURED )
96
97/** Maximum time to wait for backend to reach a given state, in ticks */
98#define XENBUS_BACKEND_TIMEOUT ( 5 * TICKS_PER_SEC )
99
100/**
101 * Set device state
102 *
103 * @v xendev Xen device
104 * @v state New state
105 * @ret rc Return status code
106 */
107int xenbus_set_state ( struct xen_device *xendev, int state ) {
108 int rc;
109
110 /* Attempt to set state */
111 if ( ( rc = xenstore_write_num ( xendev->xen, state, xendev->key,
112 "state", NULL ) ) != 0 ) {
113 DBGC ( xendev, "XENBUS %s could not set state=\"%d\": %s\n",
114 xendev->key, state, strerror ( rc ) );
115 return rc;
116 }
117
118 return 0;
119}
120
121/**
122 * Get backend state
123 *
124 * @v xendev Xen device
125 * @ret state Backend state, or negative error
126 */
127int xenbus_backend_state ( struct xen_device *xendev ) {
128 unsigned long state;
129 int rc;
130
131 /* Attempt to get backend state */
132 if ( ( rc = xenstore_read_num ( xendev->xen, &state, xendev->backend,
133 "state", NULL ) ) != 0 ) {
134 DBGC ( xendev, "XENBUS %s could not read %s/state: %s\n",
135 xendev->key, xendev->backend, strerror ( rc ) );
136 return rc;
137 }
138
139 return state;
140}
141
142/**
143 * Wait for backend to reach a given state
144 *
145 * @v xendev Xen device
146 * @v state Desired backend state
147 * @ret rc Return status code
148 */
149int xenbus_backend_wait ( struct xen_device *xendev, int state ) {
150 unsigned long started = currticks();
151 unsigned long elapsed;
152 unsigned int attempts = 0;
153 int current_state;
154 int rc;
155
156 /* Wait for backend to reach this state */
157 do {
158
159 /* Get current backend state */
160 current_state = xenbus_backend_state ( xendev );
161 if ( current_state < 0 ) {
162 rc = current_state;
163 return rc;
164 }
165 if ( current_state == state )
166 return 0;
167
168 /* Allow time for backend to react */
169 cpu_nap();
170
171 /* XenStore is a very slow interface; any fixed delay
172 * time would be dwarfed by the XenStore access time.
173 * We therefore use wall clock to time out this
174 * operation.
175 */
176 elapsed = ( currticks() - started );
177 attempts++;
178
179 } while ( elapsed < XENBUS_BACKEND_TIMEOUT );
180
181 /* Construct status code from current backend state */
182 rc = -ETIMEDOUT_STATE ( current_state );
183 DBGC ( xendev, "XENBUS %s timed out after %d attempts waiting for "
184 "%s/state=\"%d\": %s\n", xendev->key, attempts, xendev->backend,
185 state, strerror ( rc ) );
186
187 return rc;
188}
189
190/**
191 * Find driver for Xen device
192 *
193 * @v type Device type
194 * @ret driver Driver, or NULL
195 */
196static struct xen_driver * xenbus_find_driver ( const char *type ) {
197 struct xen_driver *xendrv;
198
200 if ( strcmp ( xendrv->type, type ) == 0 )
201 return xendrv;
202 }
203 return NULL;
204}
205
206/**
207 * Probe Xen device
208 *
209 * @v xen Xen hypervisor
210 * @v parent Parent device
211 * @v instance Device instance
212 * @v driver Device driver
213 * @ret rc Return status code
214 */
215static int xenbus_probe_device ( struct xen_hypervisor *xen,
216 struct device *parent, const char *instance,
217 struct xen_driver *driver ) {
218 const char *type = driver->type;
219 struct xen_device *xendev;
220 size_t key_len;
221 int rc;
222
223 /* Allocate and initialise structure */
224 key_len = ( 7 /* "device/" */ + strlen ( type ) + 1 /* "/" */ +
225 strlen ( instance ) + 1 /* NUL */ );
226 xendev = zalloc ( sizeof ( *xendev ) + key_len );
227 if ( ! xendev ) {
228 rc = -ENOMEM;
229 goto err_alloc;
230 }
231 snprintf ( xendev->dev.name, sizeof ( xendev->dev.name ), "%s/%s",
232 type, instance );
233 xendev->dev.desc.bus_type = BUS_TYPE_XEN;
234 INIT_LIST_HEAD ( &xendev->dev.children );
235 list_add_tail ( &xendev->dev.siblings, &parent->children );
236 xendev->dev.parent = parent;
237 xendev->xen = xen;
238 xendev->key = ( ( void * ) ( xendev + 1 ) );
239 snprintf ( xendev->key, key_len, "device/%s/%s", type, instance );
240 xendev->driver = driver;
241 xendev->dev.driver_name = driver->name;
242 DBGC ( xendev, "XENBUS %s has driver \"%s\"\n", xendev->key,
243 xendev->driver->name );
244
245 /* Read backend key */
246 if ( ( rc = xenstore_read ( xen, &xendev->backend, xendev->key,
247 "backend", NULL ) ) != 0 ) {
248 DBGC ( xendev, "XENBUS %s could not read backend: %s\n",
249 xendev->key, strerror ( rc ) );
250 goto err_read_backend;
251 }
252
253 /* Read backend domain ID */
254 if ( ( rc = xenstore_read_num ( xen, &xendev->backend_id, xendev->key,
255 "backend-id", NULL ) ) != 0 ) {
256 DBGC ( xendev, "XENBUS %s could not read backend-id: %s\n",
257 xendev->key, strerror ( rc ) );
258 goto err_read_backend_id;
259 }
260 DBGC ( xendev, "XENBUS %s backend=\"%s\" in domain %ld\n",
261 xendev->key, xendev->backend, xendev->backend_id );
262
263 /* Probe driver */
264 if ( ( rc = xendev->driver->probe ( xendev ) ) != 0 ) {
265 DBGC ( xendev, "XENBUS could not probe %s: %s\n",
266 xendev->key, strerror ( rc ) );
267 goto err_probe;
268 }
269
270 return 0;
271
272 xendev->driver->remove ( xendev );
273 err_probe:
274 err_read_backend_id:
275 free ( xendev->backend );
276 err_read_backend:
277 list_del ( &xendev->dev.siblings );
278 free ( xendev );
279 err_alloc:
280 return rc;
281}
282
283/**
284 * Remove Xen device
285 *
286 * @v xendev Xen device
287 */
288static void xenbus_remove_device ( struct xen_device *xendev ) {
289
290 /* Remove device */
291 xendev->driver->remove ( xendev );
292 free ( xendev->backend );
293 list_del ( &xendev->dev.siblings );
294 free ( xendev );
295}
296
297/**
298 * Probe Xen devices of a given type
299 *
300 * @v xen Xen hypervisor
301 * @v parent Parent device
302 * @v type Device type
303 * @ret rc Return status code
304 */
306 struct device *parent, const char *type ) {
307 struct xen_driver *driver;
308 char *children;
309 char *child;
310 size_t len;
311 int rc;
312
313 /* Look for a driver */
314 driver = xenbus_find_driver ( type );
315 if ( ! driver ) {
316 DBGC ( xen, "XENBUS has no driver for \"%s\" devices\n", type );
317 /* Not a fatal error */
318 rc = 0;
319 goto err_no_driver;
320 }
321
322 /* Get children of this key */
323 if ( ( rc = xenstore_directory ( xen, &children, &len, "device",
324 type, NULL ) ) != 0 ) {
325 DBGC ( xen, "XENBUS could not list \"%s\" devices: %s\n",
326 type, strerror ( rc ) );
327 goto err_directory;
328 }
329
330 /* Probe each child */
331 for ( child = children ; child < ( children + len ) ;
332 child += ( strlen ( child ) + 1 /* NUL */ ) ) {
333 if ( ( rc = xenbus_probe_device ( xen, parent, child,
334 driver ) ) != 0 )
335 goto err_probe_device;
336 }
337
338 free ( children );
339 return 0;
340
341 err_probe_device:
342 free ( children );
343 err_directory:
344 err_no_driver:
345 return rc;
346}
347
348/**
349 * Probe Xen bus
350 *
351 * @v xen Xen hypervisor
352 * @v parent Parent device
353 * @ret rc Return status code
354 */
355int xenbus_probe ( struct xen_hypervisor *xen, struct device *parent ) {
356 char *types;
357 char *type;
358 size_t len;
359 int rc;
360
361 /* Get children of "device" key */
362 if ( ( rc = xenstore_directory ( xen, &types, &len, "device",
363 NULL ) ) != 0 ) {
364 DBGC ( xen, "XENBUS could not list device types: %s\n",
365 strerror ( rc ) );
366 goto err_directory;
367 }
368
369 /* Probe each child type */
370 for ( type = types ; type < ( types + len ) ;
371 type += ( strlen ( type ) + 1 /* NUL */ ) ) {
372 if ( ( rc = xenbus_probe_type ( xen, parent, type ) ) != 0 )
373 goto err_probe_type;
374 }
375
376 free ( types );
377 return 0;
378
379 xenbus_remove ( xen, parent );
380 err_probe_type:
381 free ( types );
382 err_directory:
383 return rc;
384}
385
386/**
387 * Remove Xen bus
388 *
389 * @v xen Xen hypervisor
390 * @v parent Parent device
391 */
393 struct device *parent ) {
394 struct xen_device *xendev;
395 struct xen_device *tmp;
396
397 /* Remove devices */
398 list_for_each_entry_safe ( xendev, tmp, &parent->children,
399 dev.siblings ) {
400 xenbus_remove_device ( xendev );
401 }
402}
403
404/* Drag in objects via xenbus_set_state() */
406
407/* Drag in backing hardware device */
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
Device model.
#define BUS_TYPE_XEN
Xen bus type.
Definition device.h:65
ring len
Length.
Definition dwmac.h:226
uint32_t type
Operating system type.
Definition ena.h:1
Error codes.
uint8_t state
State.
Definition eth_slow.h:36
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define REQUIRE_OBJECT(object)
Require an object.
Definition compiler.h:202
#define ENOMEM
Not enough space.
Definition errno.h:535
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define REQUIRING_SYMBOL(symbol)
Specify the file's requiring symbol.
Definition compiler.h:140
CPU sleeping.
void cpu_nap(void)
Sleep with interrupts enabled until next CPU interrupt.
iPXE timers
Xen interface.
String functions.
static int started
"startup() has been called" flag
Definition init.c:38
Xen device bus.
#define XEN_DRIVERS
Xen device driver table.
Definition xenbus.h:56
unsigned long tmp
Definition linux_pci.h:65
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
Dynamic memory allocation.
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int strcmp(const char *first, const char *second)
Compare strings.
Definition string.c:174
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
unsigned int bus_type
Bus type.
Definition device.h:25
A hardware device.
Definition device.h:77
struct device_description desc
Device description.
Definition device.h:83
struct device * parent
Bus device.
Definition device.h:89
struct list_head children
Devices attached to this device.
Definition device.h:87
struct list_head siblings
Devices on the same bus.
Definition device.h:85
const char * driver_name
Driver name.
Definition device.h:81
char name[40]
Name.
Definition device.h:79
A Xen device.
Definition xenbus.h:19
struct xen_driver * driver
Driver.
Definition xenbus.h:31
unsigned long backend_id
Backend domain ID.
Definition xenbus.h:29
struct device dev
Generic iPXE device.
Definition xenbus.h:21
char * key
XenStore key.
Definition xenbus.h:25
struct xen_hypervisor * xen
Xen hypervisor.
Definition xenbus.h:23
char * backend
Backend XenStore key.
Definition xenbus.h:27
A Xen device driver.
Definition xenbus.h:37
const char * type
Device type.
Definition xenbus.h:41
const char * name
Name.
Definition xenbus.h:39
void(* remove)(struct xen_device *xendev)
Remove device.
Definition xenbus.h:52
int(* probe)(struct xen_device *xendev)
Probe device.
Definition xenbus.h:47
A Xen hypervisor.
Definition xen.h:51
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386
unsigned long currticks(void)
Get current system time in ticks.
Definition timer.c:43
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383
int xenbus_backend_state(struct xen_device *xendev)
Get backend state.
Definition xenbus.c:127
#define XENBUS_BACKEND_TIMEOUT
Maximum time to wait for backend to reach a given state, in ticks.
Definition xenbus.c:98
static void xenbus_remove_device(struct xen_device *xendev)
Remove Xen device.
Definition xenbus.c:288
void xenbus_remove(struct xen_hypervisor *xen __unused, struct device *parent)
Remove Xen bus.
Definition xenbus.c:392
int xenbus_set_state(struct xen_device *xendev, int state)
Set device state.
Definition xenbus.c:107
static int xenbus_probe_type(struct xen_hypervisor *xen, struct device *parent, const char *type)
Probe Xen devices of a given type.
Definition xenbus.c:305
static struct xen_driver * xenbus_find_driver(const char *type)
Find driver for Xen device.
Definition xenbus.c:196
int xenbus_backend_wait(struct xen_device *xendev, int state)
Wait for backend to reach a given state.
Definition xenbus.c:149
#define ETIMEDOUT_STATE(state)
Definition xenbus.c:90
static int xenbus_probe_device(struct xen_hypervisor *xen, struct device *parent, const char *instance, struct xen_driver *driver)
Probe Xen device.
Definition xenbus.c:215
int xenbus_probe(struct xen_hypervisor *xen, struct device *parent)
Probe Xen bus.
Definition xenbus.c:355
int xenstore_directory(struct xen_hypervisor *xen, char **children, size_t *len,...)
Read XenStore directory.
Definition xenstore.c:504
int xenstore_read(struct xen_hypervisor *xen, char **value,...)
Read XenStore value.
Definition xenstore.c:372
int xenstore_read_num(struct xen_hypervisor *xen, unsigned long *num,...)
Read XenStore numeric value.
Definition xenstore.c:391
int xenstore_write_num(struct xen_hypervisor *xen, unsigned long num,...)
Write XenStore numeric value.
Definition xenstore.c:461
XenStore interface.
char unsigned long const char unsigned long char ** children
Definition xenstore.h:26