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
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.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
28 #include <ipxe/malloc.h>
29 #include <ipxe/device.h>
30 #include <ipxe/timer.h>
33 #include <ipxe/xenstore.h>
34 #include <ipxe/xenbus.h>
42 /* Disambiguate the various error causes */
43 #define ETIMEDOUT_UNKNOWN \
44 __einfo_error ( EINFO_ETIMEDOUT_UNKNOWN )
45 #define EINFO_ETIMEDOUT_UNKNOWN \
46 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateUnknown, \
48 #define ETIMEDOUT_INITIALISING \
49 __einfo_error ( EINFO_ETIMEDOUT_INITIALISING )
50 #define EINFO_ETIMEDOUT_INITIALISING \
51 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateInitialising, \
53 #define ETIMEDOUT_INITWAIT \
54 __einfo_error ( EINFO_ETIMEDOUT_INITWAIT )
55 #define EINFO_ETIMEDOUT_INITWAIT \
56 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateInitWait, \
58 #define ETIMEDOUT_INITIALISED \
59 __einfo_error ( EINFO_ETIMEDOUT_INITIALISED )
60 #define EINFO_ETIMEDOUT_INITIALISED \
61 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateInitialised, \
63 #define ETIMEDOUT_CONNECTED \
64 __einfo_error ( EINFO_ETIMEDOUT_CONNECTED )
65 #define EINFO_ETIMEDOUT_CONNECTED \
66 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateConnected, \
68 #define ETIMEDOUT_CLOSING \
69 __einfo_error ( EINFO_ETIMEDOUT_CLOSING )
70 #define EINFO_ETIMEDOUT_CLOSING \
71 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateClosing, \
73 #define ETIMEDOUT_CLOSED \
74 __einfo_error ( EINFO_ETIMEDOUT_CLOSED )
75 #define EINFO_ETIMEDOUT_CLOSED \
76 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateClosed, \
78 #define ETIMEDOUT_RECONFIGURING \
79 __einfo_error ( EINFO_ETIMEDOUT_RECONFIGURING )
80 #define EINFO_ETIMEDOUT_RECONFIGURING \
81 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateReconfiguring, \
83 #define ETIMEDOUT_RECONFIGURED \
84 __einfo_error ( EINFO_ETIMEDOUT_RECONFIGURED )
85 #define EINFO_ETIMEDOUT_RECONFIGURED \
86 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateReconfigured, \
88 #define ETIMEDOUT_STATE( state ) \
89 EUNIQ ( EINFO_ETIMEDOUT, (state), ETIMEDOUT_UNKNOWN, \
90 ETIMEDOUT_INITIALISING, ETIMEDOUT_INITWAIT, \
91 ETIMEDOUT_INITIALISED, ETIMEDOUT_CONNECTED, \
92 ETIMEDOUT_CLOSING, ETIMEDOUT_CLOSED, \
93 ETIMEDOUT_RECONFIGURING, ETIMEDOUT_RECONFIGURED )
95 /** Maximum time to wait for backend to reach a given state, in ticks */
96 #define XENBUS_BACKEND_TIMEOUT ( 5 * TICKS_PER_SEC )
101 * @v xendev Xen device
103 * @ret rc Return status code
105 int xenbus_set_state ( struct xen_device *xendev, int state ) {
108 /* Attempt to set state */
109 if ( ( rc = xenstore_write_num ( xendev->xen, state, xendev->key,
110 "state", NULL ) ) != 0 ) {
111 DBGC ( xendev, "XENBUS %s could not set state=\"%d\": %s\n",
112 xendev->key, state, strerror ( rc ) );
122 * @v xendev Xen device
123 * @ret state Backend state, or negative error
125 int xenbus_backend_state ( struct xen_device *xendev ) {
129 /* Attempt to get backend state */
130 if ( ( rc = xenstore_read_num ( xendev->xen, &state, xendev->backend,
131 "state", NULL ) ) != 0 ) {
132 DBGC ( xendev, "XENBUS %s could not read %s/state: %s\n",
133 xendev->key, xendev->backend, strerror ( rc ) );
141 * Wait for backend to reach a given state
143 * @v xendev Xen device
144 * @v state Desired backend state
145 * @ret rc Return status code
147 int xenbus_backend_wait ( struct xen_device *xendev, int state ) {
148 unsigned long started = currticks();
149 unsigned long elapsed;
150 unsigned int attempts = 0;
154 /* Wait for backend to reach this state */
157 /* Get current backend state */
158 current_state = xenbus_backend_state ( xendev );
159 if ( current_state < 0 ) {
163 if ( current_state == state )
166 /* Allow time for backend to react */
169 /* XenStore is a very slow interface; any fixed delay
170 * time would be dwarfed by the XenStore access time.
171 * We therefore use wall clock to time out this
174 elapsed = ( currticks() - started );
177 } while ( elapsed < XENBUS_BACKEND_TIMEOUT );
179 /* Construct status code from current backend state */
180 rc = -ETIMEDOUT_STATE ( current_state );
181 DBGC ( xendev, "XENBUS %s timed out after %d attempts waiting for "
182 "%s/state=\"%d\": %s\n", xendev->key, attempts, xendev->backend,
183 state, strerror ( rc ) );
189 * Find driver for Xen device
191 * @v type Device type
192 * @ret driver Driver, or NULL
194 static struct xen_driver * xenbus_find_driver ( const char *type ) {
195 struct xen_driver *xendrv;
197 for_each_table_entry ( xendrv, XEN_DRIVERS ) {
198 if ( strcmp ( xendrv->type, type ) == 0 )
207 * @v xen Xen hypervisor
208 * @v parent Parent device
209 * @v type Device type
210 * @v instance Device instance
211 * @ret rc Return status code
213 static int xenbus_probe_device ( struct xen_hypervisor *xen,
214 struct device *parent, const char *type,
215 const char *instance ) {
216 struct xen_device *xendev;
220 /* Allocate and initialise structure */
221 key_len = ( 7 /* "device/" */ + strlen ( type ) + 1 /* "/" */ +
222 strlen ( instance ) + 1 /* NUL */ );
223 xendev = zalloc ( sizeof ( *xendev ) + key_len );
228 snprintf ( xendev->dev.name, sizeof ( xendev->dev.name ), "%s/%s",
230 xendev->dev.desc.bus_type = BUS_TYPE_XEN;
231 INIT_LIST_HEAD ( &xendev->dev.children );
232 list_add_tail ( &xendev->dev.siblings, &parent->children );
233 xendev->dev.parent = parent;
235 xendev->key = ( ( void * ) ( xendev + 1 ) );
236 snprintf ( xendev->key, key_len, "device/%s/%s", type, instance );
238 /* Read backend key */
239 if ( ( rc = xenstore_read ( xen, &xendev->backend, xendev->key,
240 "backend", NULL ) ) != 0 ) {
241 DBGC ( xendev, "XENBUS %s could not read backend: %s\n",
242 xendev->key, strerror ( rc ) );
243 goto err_read_backend;
246 /* Read backend domain ID */
247 if ( ( rc = xenstore_read_num ( xen, &xendev->backend_id, xendev->key,
248 "backend-id", NULL ) ) != 0 ) {
249 DBGC ( xendev, "XENBUS %s could not read backend-id: %s\n",
250 xendev->key, strerror ( rc ) );
251 goto err_read_backend_id;
253 DBGC ( xendev, "XENBUS %s backend=\"%s\" in domain %ld\n",
254 xendev->key, xendev->backend, xendev->backend_id );
256 /* Look for a driver */
257 xendev->driver = xenbus_find_driver ( type );
258 if ( ! xendev->driver ) {
259 DBGC ( xendev, "XENBUS %s has no driver\n", xendev->key );
260 /* Not a fatal error */
264 xendev->dev.driver_name = xendev->driver->name;
265 DBGC ( xendev, "XENBUS %s has driver \"%s\"\n", xendev->key,
266 xendev->driver->name );
269 if ( ( rc = xendev->driver->probe ( xendev ) ) != 0 ) {
270 DBGC ( xendev, "XENBUS could not probe %s: %s\n",
271 xendev->key, strerror ( rc ) );
277 xendev->driver->remove ( xendev );
281 free ( xendev->backend );
283 list_del ( &xendev->dev.siblings );
292 * @v xendev Xen device
294 static void xenbus_remove_device ( struct xen_device *xendev ) {
297 xendev->driver->remove ( xendev );
298 free ( xendev->backend );
299 list_del ( &xendev->dev.siblings );
304 * Probe Xen devices of a given type
306 * @v xen Xen hypervisor
307 * @v parent Parent device
308 * @v type Device type
309 * @ret rc Return status code
311 static int xenbus_probe_type ( struct xen_hypervisor *xen,
312 struct device *parent, const char *type ) {
318 /* Get children of this key */
319 if ( ( rc = xenstore_directory ( xen, &children, &len, "device",
320 type, NULL ) ) != 0 ) {
321 DBGC ( xen, "XENBUS could not list \"%s\" devices: %s\n",
322 type, strerror ( rc ) );
326 /* Probe each child */
327 for ( child = children ; child < ( children + len ) ;
328 child += ( strlen ( child ) + 1 /* NUL */ ) ) {
329 if ( ( rc = xenbus_probe_device ( xen, parent, type,
331 goto err_probe_device;
346 * @v xen Xen hypervisor
347 * @v parent Parent device
348 * @ret rc Return status code
350 int xenbus_probe ( struct xen_hypervisor *xen, struct device *parent ) {
356 /* Get children of "device" key */
357 if ( ( rc = xenstore_directory ( xen, &types, &len, "device",
359 DBGC ( xen, "XENBUS could not list device types: %s\n",
364 /* Probe each child type */
365 for ( type = types ; type < ( types + len ) ;
366 type += ( strlen ( type ) + 1 /* NUL */ ) ) {
367 if ( ( rc = xenbus_probe_type ( xen, parent, type ) ) != 0 )
374 xenbus_remove ( xen, parent );
384 * @v xen Xen hypervisor
385 * @v parent Parent device
387 void xenbus_remove ( struct xen_hypervisor *xen __unused,
388 struct device *parent ) {
389 struct xen_device *xendev;
390 struct xen_device *tmp;
393 list_for_each_entry_safe ( xendev, tmp, &parent->children,
395 xenbus_remove_device ( xendev );