[efi] Do not raise TPL within EFI_DRIVER_BINDING_PROTOCOL.Supported()
[ipxe.git] / src / interface / xen / xenbus.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 <stdio.h>
27 #include <errno.h>
28 #include <ipxe/malloc.h>
29 #include <ipxe/device.h>
30 #include <ipxe/timer.h>
31 #include <ipxe/nap.h>
32 #include <ipxe/xen.h>
33 #include <ipxe/xenstore.h>
34 #include <ipxe/xenbus.h>
35
36 /** @file
37 *
38 * Xen device bus
39 *
40 */
41
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, \
47 "Unknown" )
48 #define ETIMEDOUT_INITIALISING \
49 __einfo_error ( EINFO_ETIMEDOUT_INITIALISING )
50 #define EINFO_ETIMEDOUT_INITIALISING \
51 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateInitialising, \
52 "Initialising" )
53 #define ETIMEDOUT_INITWAIT \
54 __einfo_error ( EINFO_ETIMEDOUT_INITWAIT )
55 #define EINFO_ETIMEDOUT_INITWAIT \
56 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateInitWait, \
57 "InitWait" )
58 #define ETIMEDOUT_INITIALISED \
59 __einfo_error ( EINFO_ETIMEDOUT_INITIALISED )
60 #define EINFO_ETIMEDOUT_INITIALISED \
61 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateInitialised, \
62 "Initialised" )
63 #define ETIMEDOUT_CONNECTED \
64 __einfo_error ( EINFO_ETIMEDOUT_CONNECTED )
65 #define EINFO_ETIMEDOUT_CONNECTED \
66 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateConnected, \
67 "Connected" )
68 #define ETIMEDOUT_CLOSING \
69 __einfo_error ( EINFO_ETIMEDOUT_CLOSING )
70 #define EINFO_ETIMEDOUT_CLOSING \
71 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateClosing, \
72 "Closing" )
73 #define ETIMEDOUT_CLOSED \
74 __einfo_error ( EINFO_ETIMEDOUT_CLOSED )
75 #define EINFO_ETIMEDOUT_CLOSED \
76 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateClosed, \
77 "Closed" )
78 #define ETIMEDOUT_RECONFIGURING \
79 __einfo_error ( EINFO_ETIMEDOUT_RECONFIGURING )
80 #define EINFO_ETIMEDOUT_RECONFIGURING \
81 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateReconfiguring, \
82 "Reconfiguring" )
83 #define ETIMEDOUT_RECONFIGURED \
84 __einfo_error ( EINFO_ETIMEDOUT_RECONFIGURED )
85 #define EINFO_ETIMEDOUT_RECONFIGURED \
86 __einfo_uniqify ( EINFO_ETIMEDOUT, XenbusStateReconfigured, \
87 "Reconfigured" )
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 )
94
95 /** Maximum time to wait for backend to reach a given state, in ticks */
96 #define XENBUS_BACKEND_TIMEOUT ( 5 * TICKS_PER_SEC )
97
98 /**
99 * Set device state
100 *
101 * @v xendev Xen device
102 * @v state New state
103 * @ret rc Return status code
104 */
105 int xenbus_set_state ( struct xen_device *xendev, int state ) {
106 int rc;
107
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 ) );
113 return rc;
114 }
115
116 return 0;
117 }
118
119 /**
120 * Get backend state
121 *
122 * @v xendev Xen device
123 * @ret state Backend state, or negative error
124 */
125 int xenbus_backend_state ( struct xen_device *xendev ) {
126 unsigned long state;
127 int rc;
128
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 ) );
134 return rc;
135 }
136
137 return state;
138 }
139
140 /**
141 * Wait for backend to reach a given state
142 *
143 * @v xendev Xen device
144 * @v state Desired backend state
145 * @ret rc Return status code
146 */
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;
151 int current_state;
152 int rc;
153
154 /* Wait for backend to reach this state */
155 do {
156
157 /* Get current backend state */
158 current_state = xenbus_backend_state ( xendev );
159 if ( current_state < 0 ) {
160 rc = current_state;
161 return rc;
162 }
163 if ( current_state == state )
164 return 0;
165
166 /* Allow time for backend to react */
167 cpu_nap();
168
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
172 * operation.
173 */
174 elapsed = ( currticks() - started );
175 attempts++;
176
177 } while ( elapsed < XENBUS_BACKEND_TIMEOUT );
178
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 ) );
184
185 return rc;
186 }
187
188 /**
189 * Find driver for Xen device
190 *
191 * @v type Device type
192 * @ret driver Driver, or NULL
193 */
194 static struct xen_driver * xenbus_find_driver ( const char *type ) {
195 struct xen_driver *xendrv;
196
197 for_each_table_entry ( xendrv, XEN_DRIVERS ) {
198 if ( strcmp ( xendrv->type, type ) == 0 )
199 return xendrv;
200 }
201 return NULL;
202 }
203
204 /**
205 * Probe Xen device
206 *
207 * @v xen Xen hypervisor
208 * @v parent Parent device
209 * @v instance Device instance
210 * @v driver Device driver
211 * @ret rc Return status code
212 */
213 static int xenbus_probe_device ( struct xen_hypervisor *xen,
214 struct device *parent, const char *instance,
215 struct xen_driver *driver ) {
216 const char *type = driver->type;
217 struct xen_device *xendev;
218 size_t key_len;
219 int rc;
220
221 /* Allocate and initialise structure */
222 key_len = ( 7 /* "device/" */ + strlen ( type ) + 1 /* "/" */ +
223 strlen ( instance ) + 1 /* NUL */ );
224 xendev = zalloc ( sizeof ( *xendev ) + key_len );
225 if ( ! xendev ) {
226 rc = -ENOMEM;
227 goto err_alloc;
228 }
229 snprintf ( xendev->dev.name, sizeof ( xendev->dev.name ), "%s/%s",
230 type, instance );
231 xendev->dev.desc.bus_type = BUS_TYPE_XEN;
232 INIT_LIST_HEAD ( &xendev->dev.children );
233 list_add_tail ( &xendev->dev.siblings, &parent->children );
234 xendev->dev.parent = parent;
235 xendev->xen = xen;
236 xendev->key = ( ( void * ) ( xendev + 1 ) );
237 snprintf ( xendev->key, key_len, "device/%s/%s", type, instance );
238 xendev->driver = driver;
239 xendev->dev.driver_name = driver->name;
240 DBGC ( xendev, "XENBUS %s has driver \"%s\"\n", xendev->key,
241 xendev->driver->name );
242
243 /* Read backend key */
244 if ( ( rc = xenstore_read ( xen, &xendev->backend, xendev->key,
245 "backend", NULL ) ) != 0 ) {
246 DBGC ( xendev, "XENBUS %s could not read backend: %s\n",
247 xendev->key, strerror ( rc ) );
248 goto err_read_backend;
249 }
250
251 /* Read backend domain ID */
252 if ( ( rc = xenstore_read_num ( xen, &xendev->backend_id, xendev->key,
253 "backend-id", NULL ) ) != 0 ) {
254 DBGC ( xendev, "XENBUS %s could not read backend-id: %s\n",
255 xendev->key, strerror ( rc ) );
256 goto err_read_backend_id;
257 }
258 DBGC ( xendev, "XENBUS %s backend=\"%s\" in domain %ld\n",
259 xendev->key, xendev->backend, xendev->backend_id );
260
261 /* Probe driver */
262 if ( ( rc = xendev->driver->probe ( xendev ) ) != 0 ) {
263 DBGC ( xendev, "XENBUS could not probe %s: %s\n",
264 xendev->key, strerror ( rc ) );
265 goto err_probe;
266 }
267
268 return 0;
269
270 xendev->driver->remove ( xendev );
271 err_probe:
272 err_read_backend_id:
273 free ( xendev->backend );
274 err_read_backend:
275 list_del ( &xendev->dev.siblings );
276 free ( xendev );
277 err_alloc:
278 return rc;
279 }
280
281 /**
282 * Remove Xen device
283 *
284 * @v xendev Xen device
285 */
286 static void xenbus_remove_device ( struct xen_device *xendev ) {
287
288 /* Remove device */
289 xendev->driver->remove ( xendev );
290 free ( xendev->backend );
291 list_del ( &xendev->dev.siblings );
292 free ( xendev );
293 }
294
295 /**
296 * Probe Xen devices of a given type
297 *
298 * @v xen Xen hypervisor
299 * @v parent Parent device
300 * @v type Device type
301 * @ret rc Return status code
302 */
303 static int xenbus_probe_type ( struct xen_hypervisor *xen,
304 struct device *parent, const char *type ) {
305 struct xen_driver *driver;
306 char *children;
307 char *child;
308 size_t len;
309 int rc;
310
311 /* Look for a driver */
312 driver = xenbus_find_driver ( type );
313 if ( ! driver ) {
314 DBGC ( xen, "XENBUS has no driver for \"%s\" devices\n", type );
315 /* Not a fatal error */
316 rc = 0;
317 goto err_no_driver;
318 }
319
320 /* Get children of this key */
321 if ( ( rc = xenstore_directory ( xen, &children, &len, "device",
322 type, NULL ) ) != 0 ) {
323 DBGC ( xen, "XENBUS could not list \"%s\" devices: %s\n",
324 type, strerror ( rc ) );
325 goto err_directory;
326 }
327
328 /* Probe each child */
329 for ( child = children ; child < ( children + len ) ;
330 child += ( strlen ( child ) + 1 /* NUL */ ) ) {
331 if ( ( rc = xenbus_probe_device ( xen, parent, child,
332 driver ) ) != 0 )
333 goto err_probe_device;
334 }
335
336 free ( children );
337 return 0;
338
339 err_probe_device:
340 free ( children );
341 err_directory:
342 err_no_driver:
343 return rc;
344 }
345
346 /**
347 * Probe Xen bus
348 *
349 * @v xen Xen hypervisor
350 * @v parent Parent device
351 * @ret rc Return status code
352 */
353 int xenbus_probe ( struct xen_hypervisor *xen, struct device *parent ) {
354 char *types;
355 char *type;
356 size_t len;
357 int rc;
358
359 /* Get children of "device" key */
360 if ( ( rc = xenstore_directory ( xen, &types, &len, "device",
361 NULL ) ) != 0 ) {
362 DBGC ( xen, "XENBUS could not list device types: %s\n",
363 strerror ( rc ) );
364 goto err_directory;
365 }
366
367 /* Probe each child type */
368 for ( type = types ; type < ( types + len ) ;
369 type += ( strlen ( type ) + 1 /* NUL */ ) ) {
370 if ( ( rc = xenbus_probe_type ( xen, parent, type ) ) != 0 )
371 goto err_probe_type;
372 }
373
374 free ( types );
375 return 0;
376
377 xenbus_remove ( xen, parent );
378 err_probe_type:
379 free ( types );
380 err_directory:
381 return rc;
382 }
383
384 /**
385 * Remove Xen bus
386 *
387 * @v xen Xen hypervisor
388 * @v parent Parent device
389 */
390 void xenbus_remove ( struct xen_hypervisor *xen __unused,
391 struct device *parent ) {
392 struct xen_device *xendev;
393 struct xen_device *tmp;
394
395 /* Remove devices */
396 list_for_each_entry_safe ( xendev, tmp, &parent->children,
397 dev.siblings ) {
398 xenbus_remove_device ( xendev );
399 }
400 }