]> git.proxmox.com Git - qemu.git/blame - hw/qdev.c
qdev: fix hotplug when no -device is specified
[qemu.git] / hw / qdev.c
CommitLineData
aae9460e
PB
1/*
2 * Dynamic device configuration and creation.
3 *
4 * Copyright (c) 2009 CodeSourcery
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
aae9460e
PB
18 */
19
20/* The theory here is that it should be possible to create a machine without
21 knowledge of specific devices. Historically board init routines have
22 passed a bunch of arguments to each device, requiring the board know
23 exactly which device it is dealing with. This file provides an abstract
24 API for device configuration and initialization. Devices will generally
25 inherit from a particular bus (e.g. PCI or I2C) rather than
26 this API directly. */
27
9d07d757 28#include "net.h"
aae9460e
PB
29#include "qdev.h"
30#include "sysemu.h"
cae4956e 31#include "monitor.h"
aae9460e 32
3418bd25 33static int qdev_hotplug = 0;
0ac8ef71
AW
34static bool qdev_hot_added = false;
35static bool qdev_hot_removed = false;
3418bd25 36
cdaed7c7 37/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
b9aaf7f8 38static BusState *main_system_bus;
2da8bb92 39static void main_system_bus_create(void);
4d6ae674 40
0958b4cc 41DeviceInfo *device_info_list;
aae9460e 42
8ffb1bcf
GH
43static BusState *qbus_find_recursive(BusState *bus, const char *name,
44 const BusInfo *info);
45static BusState *qbus_find(const char *path);
46
aae9460e 47/* Register a new device type. */
074f2fff 48void qdev_register(DeviceInfo *info)
aae9460e 49{
074f2fff 50 assert(info->size >= sizeof(DeviceState));
042f84d0 51 assert(!info->next);
aae9460e 52
042f84d0
GH
53 info->next = device_info_list;
54 device_info_list = info;
aae9460e
PB
55}
56
81ebb98b
GH
57static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
58{
59 DeviceInfo *info;
60
3320e56e 61 /* first check device names */
81ebb98b
GH
62 for (info = device_info_list; info != NULL; info = info->next) {
63 if (bus_info && info->bus_info != bus_info)
64 continue;
65 if (strcmp(info->name, name) != 0)
66 continue;
67 return info;
68 }
3320e56e
GH
69
70 /* failing that check the aliases */
71 for (info = device_info_list; info != NULL; info = info->next) {
72 if (bus_info && info->bus_info != bus_info)
73 continue;
74 if (!info->alias)
75 continue;
76 if (strcmp(info->alias, name) != 0)
77 continue;
78 return info;
79 }
81ebb98b
GH
80 return NULL;
81}
82
ca2cc788
PB
83static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
84 Error **errp);
85
0c17542d
MA
86static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
87{
88 DeviceState *dev;
a5296ca9 89 Property *prop;
0c17542d
MA
90
91 assert(bus->info == info->bus_info);
7267c094 92 dev = g_malloc0(info->size);
0c17542d
MA
93 dev->info = info;
94 dev->parent_bus = bus;
95 qdev_prop_set_defaults(dev, dev->info->props);
96 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
97 qdev_prop_set_globals(dev);
d8bb00d6 98 QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
0c17542d
MA
99 if (qdev_hotplug) {
100 assert(bus->allow_hotplug);
101 dev->hotplugged = 1;
0ac8ef71 102 qdev_hot_added = true;
0c17542d 103 }
4d2ffa08 104 dev->instance_id_alias = -1;
44677ded 105 QTAILQ_INIT(&dev->properties);
0c17542d 106 dev->state = DEV_STATE_CREATED;
a5296ca9
AL
107
108 for (prop = dev->info->props; prop && prop->name; prop++) {
109 qdev_property_add_legacy(dev, prop, NULL);
ca2cc788 110 qdev_property_add_static(dev, prop, NULL);
a5296ca9
AL
111 }
112
113 for (prop = dev->info->bus_info->props; prop && prop->name; prop++) {
114 qdev_property_add_legacy(dev, prop, NULL);
ca2cc788 115 qdev_property_add_static(dev, prop, NULL);
a5296ca9
AL
116 }
117
cd34d667
AL
118 qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
119
0c17542d
MA
120 return dev;
121}
122
aae9460e
PB
123/* Create a new device. This only initializes the device state structure
124 and allows properties to be set. qdev_init should be called to
125 initialize the actual device emulation. */
02e2da45 126DeviceState *qdev_create(BusState *bus, const char *name)
0bcdeda7
BS
127{
128 DeviceState *dev;
129
130 dev = qdev_try_create(bus, name);
131 if (!dev) {
e92714c7
PM
132 if (bus) {
133 hw_error("Unknown device '%s' for bus '%s'\n", name,
134 bus->info->name);
135 } else {
136 hw_error("Unknown device '%s' for default sysbus\n", name);
137 }
0bcdeda7
BS
138 }
139
140 return dev;
141}
142
143DeviceState *qdev_try_create(BusState *bus, const char *name)
aae9460e 144{
042f84d0 145 DeviceInfo *info;
aae9460e 146
10c4c98a 147 if (!bus) {
68694897 148 bus = sysbus_get_default();
10c4c98a
GH
149 }
150
81ebb98b 151 info = qdev_find_info(bus->info, name);
042f84d0 152 if (!info) {
0bcdeda7 153 return NULL;
aae9460e
PB
154 }
155
0c17542d 156 return qdev_create_from_info(bus, info);
aae9460e
PB
157}
158
8a9662ca 159static void qdev_print_devinfo(DeviceInfo *info)
1b524b04 160{
8a9662ca
MA
161 error_printf("name \"%s\", bus %s",
162 info->name, info->bus_info->name);
22f2e344 163 if (info->alias) {
8a9662ca 164 error_printf(", alias \"%s\"", info->alias);
22f2e344
GH
165 }
166 if (info->desc) {
8a9662ca 167 error_printf(", desc \"%s\"", info->desc);
22f2e344
GH
168 }
169 if (info->no_user) {
8a9662ca 170 error_printf(", no-user");
22f2e344 171 }
8a9662ca 172 error_printf("\n");
1b524b04
GH
173}
174
f31d07d1 175static int set_property(const char *name, const char *value, void *opaque)
8ffb1bcf 176{
f31d07d1
GH
177 DeviceState *dev = opaque;
178
179 if (strcmp(name, "driver") == 0)
180 return 0;
181 if (strcmp(name, "bus") == 0)
182 return 0;
183
3df04ac3 184 if (qdev_prop_parse(dev, name, value) == -1) {
f31d07d1
GH
185 return -1;
186 }
187 return 0;
188}
189
ff952ba2
MA
190int qdev_device_help(QemuOpts *opts)
191{
192 const char *driver;
193 DeviceInfo *info;
08350cf0 194 Property *prop;
ff952ba2
MA
195
196 driver = qemu_opt_get(opts, "driver");
197 if (driver && !strcmp(driver, "?")) {
198 for (info = device_info_list; info != NULL; info = info->next) {
c64eafaf
MA
199 if (info->no_user) {
200 continue; /* not available, don't show */
201 }
8a9662ca 202 qdev_print_devinfo(info);
ff952ba2
MA
203 }
204 return 1;
205 }
206
542379f4 207 if (!driver || !qemu_opt_get(opts, "?")) {
08350cf0
MA
208 return 0;
209 }
210
211 info = qdev_find_info(NULL, driver);
212 if (!info) {
213 return 0;
214 }
215
216 for (prop = info->props; prop && prop->name; prop++) {
036f7166
MA
217 /*
218 * TODO Properties without a parser are just for dirty hacks.
219 * qdev_prop_ptr is the only such PropertyInfo. It's marked
220 * for removal. This conditional should be removed along with
221 * it.
222 */
223 if (!prop->info->parse) {
224 continue; /* no way to set it, don't show */
225 }
cafe5bdb
PB
226 error_printf("%s.%s=%s\n", info->name, prop->name,
227 prop->info->legacy_name ?: prop->info->name);
a8467c7a
GH
228 }
229 for (prop = info->bus_info->props; prop && prop->name; prop++) {
230 if (!prop->info->parse) {
231 continue; /* no way to set it, don't show */
232 }
cafe5bdb
PB
233 error_printf("%s.%s=%s\n", info->name, prop->name,
234 prop->info->legacy_name ?: prop->info->name);
08350cf0
MA
235 }
236 return 1;
ff952ba2
MA
237}
238
1bdaacb1
AL
239static DeviceState *qdev_get_peripheral(void)
240{
241 static DeviceState *dev;
242
243 if (dev == NULL) {
244 dev = qdev_create(NULL, "container");
245 qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
246 qdev_init_nofail(dev);
247 }
248
249 return dev;
250}
251
8eb02831
AL
252static DeviceState *qdev_get_peripheral_anon(void)
253{
254 static DeviceState *dev;
255
256 if (dev == NULL) {
257 dev = qdev_create(NULL, "container");
258 qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
259 qdev_init_nofail(dev);
260 }
261
262 return dev;
263}
264
f31d07d1
GH
265DeviceState *qdev_device_add(QemuOpts *opts)
266{
267 const char *driver, *path, *id;
8ffb1bcf
GH
268 DeviceInfo *info;
269 DeviceState *qdev;
270 BusState *bus;
8ffb1bcf 271
f31d07d1
GH
272 driver = qemu_opt_get(opts, "driver");
273 if (!driver) {
0204276b 274 qerror_report(QERR_MISSING_PARAMETER, "driver");
8ffb1bcf
GH
275 return NULL;
276 }
f31d07d1
GH
277
278 /* find driver */
8ffb1bcf 279 info = qdev_find_info(NULL, driver);
c64eafaf 280 if (!info || info->no_user) {
e17ba87c 281 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
0204276b 282 error_printf_unless_qmp("Try with argument '?' for a list.\n");
8ffb1bcf
GH
283 return NULL;
284 }
8ffb1bcf 285
f31d07d1
GH
286 /* find bus */
287 path = qemu_opt_get(opts, "bus");
288 if (path != NULL) {
8ffb1bcf 289 bus = qbus_find(path);
ac8dae67
MA
290 if (!bus) {
291 return NULL;
292 }
293 if (bus->info != info->bus_info) {
0204276b
MA
294 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
295 driver, bus->info->name);
327867b6
MA
296 return NULL;
297 }
8ffb1bcf
GH
298 } else {
299 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
ac8dae67 300 if (!bus) {
0204276b
MA
301 qerror_report(QERR_NO_BUS_FOR_DEVICE,
302 info->name, info->bus_info->name);
ac8dae67
MA
303 return NULL;
304 }
75570088 305 }
3418bd25 306 if (qdev_hotplug && !bus->allow_hotplug) {
0204276b 307 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
3418bd25
GH
308 return NULL;
309 }
8ffb1bcf 310
f31d07d1 311 /* create device, set properties */
0c17542d 312 qdev = qdev_create_from_info(bus, info);
f31d07d1
GH
313 id = qemu_opts_id(opts);
314 if (id) {
315 qdev->id = id;
1bdaacb1 316 qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
8eb02831
AL
317 } else {
318 static int anon_count;
319 gchar *name = g_strdup_printf("device[%d]", anon_count++);
320 qdev_property_add_child(qdev_get_peripheral_anon(), name,
321 qdev, NULL);
322 g_free(name);
323 }
f31d07d1
GH
324 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
325 qdev_free(qdev);
326 return NULL;
8ffb1bcf 327 }
5c17ca25 328 if (qdev_init(qdev) < 0) {
0204276b 329 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
81a322d4
GH
330 return NULL;
331 }
ef80b466 332 qdev->opts = opts;
8ffb1bcf
GH
333 return qdev;
334}
335
aae9460e
PB
336/* Initialize a device. Device properties should be set before calling
337 this function. IRQs and MMIO regions should be connected/mapped after
18cfeb52
MA
338 calling this function.
339 On failure, destroy the device and return negative value.
340 Return 0 on success. */
81a322d4 341int qdev_init(DeviceState *dev)
aae9460e 342{
959f733a
GH
343 int rc;
344
131ec1bd 345 assert(dev->state == DEV_STATE_CREATED);
959f733a 346 rc = dev->info->init(dev, dev->info);
18cfeb52
MA
347 if (rc < 0) {
348 qdev_free(dev);
959f733a 349 return rc;
18cfeb52 350 }
4d2ffa08 351 if (dev->info->vmsd) {
0be71e32 352 vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
4d2ffa08
JK
353 dev->instance_id_alias,
354 dev->alias_required_for_version);
355 }
131ec1bd 356 dev->state = DEV_STATE_INITIALIZED;
5ab28c83
JK
357 if (dev->hotplugged && dev->info->reset) {
358 dev->info->reset(dev);
359 }
959f733a 360 return 0;
02e2da45
PB
361}
362
4d2ffa08
JK
363void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
364 int required_for_version)
365{
366 assert(dev->state == DEV_STATE_CREATED);
367 dev->instance_id_alias = alias_id;
368 dev->alias_required_for_version = required_for_version;
369}
370
3418bd25
GH
371int qdev_unplug(DeviceState *dev)
372{
373 if (!dev->parent_bus->allow_hotplug) {
cc601cb7 374 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
3418bd25
GH
375 return -1;
376 }
593831de
AS
377 assert(dev->info->unplug != NULL);
378
85ed303b
AL
379 if (dev->ref != 0) {
380 qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
381 return -1;
382 }
383
0ac8ef71
AW
384 qdev_hot_removed = true;
385
3418bd25
GH
386 return dev->info->unplug(dev);
387}
388
ec990eb6
AL
389static int qdev_reset_one(DeviceState *dev, void *opaque)
390{
391 if (dev->info->reset) {
392 dev->info->reset(dev);
393 }
394
395 return 0;
396}
397
398BusState *sysbus_get_default(void)
399{
68694897 400 if (!main_system_bus) {
2da8bb92 401 main_system_bus_create();
68694897 402 }
ec990eb6
AL
403 return main_system_bus;
404}
405
b4694b7c
IY
406static int qbus_reset_one(BusState *bus, void *opaque)
407{
408 if (bus->info->reset) {
409 return bus->info->reset(bus);
410 }
411 return 0;
412}
413
5af0a04b
IY
414void qdev_reset_all(DeviceState *dev)
415{
416 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
417}
418
80376c3f
IY
419void qbus_reset_all_fn(void *opaque)
420{
421 BusState *bus = opaque;
f530cce3 422 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
80376c3f
IY
423}
424
3418bd25
GH
425/* can be used as ->unplug() callback for the simple cases */
426int qdev_simple_unplug_cb(DeviceState *dev)
427{
428 /* just zap it */
429 qdev_free(dev);
430 return 0;
431}
432
3b29a101
MT
433
434/* Like qdev_init(), but terminate program via error_report() instead of
e23a1b33
MA
435 returning an error value. This is okay during machine creation.
436 Don't use for hotplug, because there callers need to recover from
437 failure. Exception: if you know the device's init() callback can't
438 fail, then qdev_init_nofail() can't fail either, and is therefore
439 usable even then. But relying on the device implementation that
440 way is somewhat unclean, and best avoided. */
441void qdev_init_nofail(DeviceState *dev)
442{
443 DeviceInfo *info = dev->info;
444
bd6c9a61 445 if (qdev_init(dev) < 0) {
6daf194d 446 error_report("Initialization of device %s failed", info->name);
bd6c9a61
MA
447 exit(1);
448 }
e23a1b33
MA
449}
450
44677ded
AL
451static void qdev_property_del_all(DeviceState *dev)
452{
453 while (!QTAILQ_EMPTY(&dev->properties)) {
454 DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
455
456 QTAILQ_REMOVE(&dev->properties, prop, node);
457
458 if (prop->release) {
459 prop->release(dev, prop->name, prop->opaque);
460 }
461
462 g_free(prop->name);
463 g_free(prop->type);
464 g_free(prop);
465 }
466}
467
02e2da45
PB
468/* Unlink device from bus and free the structure. */
469void qdev_free(DeviceState *dev)
470{
131ec1bd 471 BusState *bus;
d21357df 472 Property *prop;
131ec1bd 473
44677ded
AL
474 qdev_property_del_all(dev);
475
131ec1bd
GH
476 if (dev->state == DEV_STATE_INITIALIZED) {
477 while (dev->num_child_bus) {
478 bus = QLIST_FIRST(&dev->child_bus);
479 qbus_free(bus);
480 }
131ec1bd 481 if (dev->info->vmsd)
0be71e32 482 vmstate_unregister(dev, dev->info->vmsd, dev);
d29275f1
GH
483 if (dev->info->exit)
484 dev->info->exit(dev);
ef80b466
GH
485 if (dev->opts)
486 qemu_opts_del(dev->opts);
131ec1bd 487 }
d8bb00d6 488 QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
d21357df
MA
489 for (prop = dev->info->props; prop && prop->name; prop++) {
490 if (prop->info->free) {
491 prop->info->free(dev, prop);
492 }
493 }
7267c094 494 g_free(dev);
aae9460e
PB
495}
496
3418bd25
GH
497void qdev_machine_creation_done(void)
498{
499 /*
500 * ok, initial machine setup is done, starting from now we can
501 * only create hotpluggable devices
502 */
503 qdev_hotplug = 1;
504}
505
0ac8ef71
AW
506bool qdev_machine_modified(void)
507{
508 return qdev_hot_added || qdev_hot_removed;
509}
510
aae9460e
PB
511/* Get a character (serial) device interface. */
512CharDriverState *qdev_init_chardev(DeviceState *dev)
513{
514 static int next_serial;
98b19252
AS
515
516 /* FIXME: This function needs to go away: use chardev properties! */
517 return serial_hds[next_serial++];
aae9460e
PB
518}
519
02e2da45 520BusState *qdev_get_parent_bus(DeviceState *dev)
aae9460e 521{
02e2da45 522 return dev->parent_bus;
aae9460e
PB
523}
524
aae9460e
PB
525void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
526{
527 assert(dev->num_gpio_in == 0);
528 dev->num_gpio_in = n;
529 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
530}
531
532void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
533{
534 assert(dev->num_gpio_out == 0);
535 dev->num_gpio_out = n;
536 dev->gpio_out = pins;
537}
538
539qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
540{
541 assert(n >= 0 && n < dev->num_gpio_in);
542 return dev->gpio_in[n];
543}
544
545void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
546{
547 assert(n >= 0 && n < dev->num_gpio_out);
548 dev->gpio_out[n] = pin;
549}
550
ed16ab5a
GH
551void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
552{
6eed1856 553 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
ed16ab5a
GH
554 if (nd->vlan)
555 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
556 if (nd->netdev)
557 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
75422b0d 558 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
97b15621
GH
559 qdev_prop_exists(dev, "vectors")) {
560 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
561 }
48e2faf2 562 nd->instantiated = 1;
ed16ab5a
GH
563}
564
02e2da45 565BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
4d6ae674 566{
02e2da45 567 BusState *bus;
4d6ae674 568
72cf2d4f 569 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
4d6ae674 570 if (strcmp(name, bus->name) == 0) {
02e2da45 571 return bus;
4d6ae674
PB
572 }
573 }
574 return NULL;
575}
576
81699d8a
AL
577int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
578 qbus_walkerfn *busfn, void *opaque)
579{
580 DeviceState *dev;
581 int err;
582
583 if (busfn) {
584 err = busfn(bus, opaque);
585 if (err) {
586 return err;
587 }
588 }
589
d8bb00d6 590 QTAILQ_FOREACH(dev, &bus->children, sibling) {
81699d8a
AL
591 err = qdev_walk_children(dev, devfn, busfn, opaque);
592 if (err < 0) {
593 return err;
594 }
595 }
596
597 return 0;
598}
599
600int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
601 qbus_walkerfn *busfn, void *opaque)
602{
603 BusState *bus;
604 int err;
605
606 if (devfn) {
607 err = devfn(dev, opaque);
608 if (err) {
609 return err;
610 }
611 }
612
613 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
614 err = qbus_walk_children(bus, devfn, busfn, opaque);
615 if (err < 0) {
616 return err;
617 }
618 }
619
620 return 0;
621}
622
8ffb1bcf
GH
623static BusState *qbus_find_recursive(BusState *bus, const char *name,
624 const BusInfo *info)
625{
626 DeviceState *dev;
627 BusState *child, *ret;
628 int match = 1;
629
630 if (name && (strcmp(bus->name, name) != 0)) {
631 match = 0;
632 }
633 if (info && (bus->info != info)) {
634 match = 0;
635 }
636 if (match) {
637 return bus;
638 }
639
d8bb00d6 640 QTAILQ_FOREACH(dev, &bus->children, sibling) {
72cf2d4f 641 QLIST_FOREACH(child, &dev->child_bus, sibling) {
8ffb1bcf
GH
642 ret = qbus_find_recursive(child, name, info);
643 if (ret) {
644 return ret;
645 }
646 }
647 }
648 return NULL;
649}
650
a2ee6b4f 651DeviceState *qdev_find_recursive(BusState *bus, const char *id)
3418bd25
GH
652{
653 DeviceState *dev, *ret;
654 BusState *child;
655
d8bb00d6 656 QTAILQ_FOREACH(dev, &bus->children, sibling) {
3418bd25
GH
657 if (dev->id && strcmp(dev->id, id) == 0)
658 return dev;
659 QLIST_FOREACH(child, &dev->child_bus, sibling) {
660 ret = qdev_find_recursive(child, id);
661 if (ret) {
662 return ret;
663 }
664 }
665 }
666 return NULL;
667}
668
53db16b5 669static void qbus_list_bus(DeviceState *dev)
8ffb1bcf
GH
670{
671 BusState *child;
672 const char *sep = " ";
8ffb1bcf 673
53db16b5
MA
674 error_printf("child busses at \"%s\":",
675 dev->id ? dev->id : dev->info->name);
72cf2d4f 676 QLIST_FOREACH(child, &dev->child_bus, sibling) {
53db16b5 677 error_printf("%s\"%s\"", sep, child->name);
8ffb1bcf
GH
678 sep = ", ";
679 }
53db16b5 680 error_printf("\n");
8ffb1bcf
GH
681}
682
53db16b5 683static void qbus_list_dev(BusState *bus)
8ffb1bcf
GH
684{
685 DeviceState *dev;
686 const char *sep = " ";
8ffb1bcf 687
53db16b5 688 error_printf("devices at \"%s\":", bus->name);
d8bb00d6 689 QTAILQ_FOREACH(dev, &bus->children, sibling) {
53db16b5 690 error_printf("%s\"%s\"", sep, dev->info->name);
8ffb1bcf 691 if (dev->id)
53db16b5 692 error_printf("/\"%s\"", dev->id);
8ffb1bcf
GH
693 sep = ", ";
694 }
53db16b5 695 error_printf("\n");
8ffb1bcf
GH
696}
697
698static BusState *qbus_find_bus(DeviceState *dev, char *elem)
699{
700 BusState *child;
701
72cf2d4f 702 QLIST_FOREACH(child, &dev->child_bus, sibling) {
8ffb1bcf
GH
703 if (strcmp(child->name, elem) == 0) {
704 return child;
705 }
706 }
707 return NULL;
708}
709
710static DeviceState *qbus_find_dev(BusState *bus, char *elem)
711{
712 DeviceState *dev;
713
714 /*
715 * try to match in order:
716 * (1) instance id, if present
717 * (2) driver name
718 * (3) driver alias, if present
719 */
d8bb00d6 720 QTAILQ_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
721 if (dev->id && strcmp(dev->id, elem) == 0) {
722 return dev;
723 }
724 }
d8bb00d6 725 QTAILQ_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
726 if (strcmp(dev->info->name, elem) == 0) {
727 return dev;
728 }
729 }
d8bb00d6 730 QTAILQ_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
731 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
732 return dev;
733 }
734 }
735 return NULL;
736}
737
738static BusState *qbus_find(const char *path)
739{
740 DeviceState *dev;
741 BusState *bus;
53db16b5 742 char elem[128];
8ffb1bcf
GH
743 int pos, len;
744
745 /* find start element */
746 if (path[0] == '/') {
747 bus = main_system_bus;
748 pos = 0;
749 } else {
750 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
fc98eb43
MA
751 assert(!path[0]);
752 elem[0] = len = 0;
8ffb1bcf
GH
753 }
754 bus = qbus_find_recursive(main_system_bus, elem, NULL);
755 if (!bus) {
ac8dae67 756 qerror_report(QERR_BUS_NOT_FOUND, elem);
8ffb1bcf
GH
757 return NULL;
758 }
759 pos = len;
760 }
761
762 for (;;) {
fc98eb43
MA
763 assert(path[pos] == '/' || !path[pos]);
764 while (path[pos] == '/') {
765 pos++;
766 }
8ffb1bcf 767 if (path[pos] == '\0') {
8ffb1bcf
GH
768 return bus;
769 }
770
771 /* find device */
fc98eb43
MA
772 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
773 assert(0);
774 elem[0] = len = 0;
8ffb1bcf
GH
775 }
776 pos += len;
777 dev = qbus_find_dev(bus, elem);
778 if (!dev) {
ac8dae67 779 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
8bc27249
MA
780 if (!monitor_cur_is_qmp()) {
781 qbus_list_dev(bus);
782 }
8ffb1bcf
GH
783 return NULL;
784 }
fc98eb43
MA
785
786 assert(path[pos] == '/' || !path[pos]);
787 while (path[pos] == '/') {
788 pos++;
789 }
8ffb1bcf
GH
790 if (path[pos] == '\0') {
791 /* last specified element is a device. If it has exactly
792 * one child bus accept it nevertheless */
793 switch (dev->num_child_bus) {
794 case 0:
ac8dae67 795 qerror_report(QERR_DEVICE_NO_BUS, elem);
8ffb1bcf
GH
796 return NULL;
797 case 1:
72cf2d4f 798 return QLIST_FIRST(&dev->child_bus);
8ffb1bcf 799 default:
ac8dae67 800 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
8bc27249
MA
801 if (!monitor_cur_is_qmp()) {
802 qbus_list_bus(dev);
803 }
8ffb1bcf
GH
804 return NULL;
805 }
806 }
807
808 /* find bus */
fc98eb43
MA
809 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
810 assert(0);
811 elem[0] = len = 0;
8ffb1bcf
GH
812 }
813 pos += len;
814 bus = qbus_find_bus(dev, elem);
815 if (!bus) {
ac8dae67 816 qerror_report(QERR_BUS_NOT_FOUND, elem);
8bc27249
MA
817 if (!monitor_cur_is_qmp()) {
818 qbus_list_bus(dev);
819 }
8ffb1bcf
GH
820 return NULL;
821 }
822 }
823}
824
cd739fb6
GH
825void qbus_create_inplace(BusState *bus, BusInfo *info,
826 DeviceState *parent, const char *name)
02e2da45 827{
d271de9f
GH
828 char *buf;
829 int i,len;
02e2da45 830
10c4c98a 831 bus->info = info;
02e2da45 832 bus->parent = parent;
d271de9f
GH
833
834 if (name) {
835 /* use supplied name */
7267c094 836 bus->name = g_strdup(name);
d271de9f
GH
837 } else if (parent && parent->id) {
838 /* parent device has id -> use it for bus name */
839 len = strlen(parent->id) + 16;
7267c094 840 buf = g_malloc(len);
d271de9f
GH
841 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
842 bus->name = buf;
843 } else {
844 /* no id -> use lowercase bus type for bus name */
845 len = strlen(info->name) + 16;
7267c094 846 buf = g_malloc(len);
d271de9f
GH
847 len = snprintf(buf, len, "%s.%d", info->name,
848 parent ? parent->num_child_bus : 0);
849 for (i = 0; i < len; i++)
bb87ece5 850 buf[i] = qemu_tolower(buf[i]);
d271de9f
GH
851 bus->name = buf;
852 }
853
d8bb00d6 854 QTAILQ_INIT(&bus->children);
02e2da45 855 if (parent) {
72cf2d4f 856 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
d271de9f 857 parent->num_child_bus++;
80376c3f
IY
858 } else if (bus != main_system_bus) {
859 /* TODO: once all bus devices are qdevified,
860 only reset handler for main_system_bus should be registered here. */
861 qemu_register_reset(qbus_reset_all_fn, bus);
02e2da45 862 }
cd739fb6
GH
863}
864
865BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
866{
867 BusState *bus;
868
7267c094 869 bus = g_malloc0(info->size);
cd739fb6
GH
870 bus->qdev_allocated = 1;
871 qbus_create_inplace(bus, info, parent, name);
02e2da45
PB
872 return bus;
873}
cae4956e 874
2da8bb92
IY
875static void main_system_bus_create(void)
876{
877 /* assign main_system_bus before qbus_create_inplace()
878 * in order to make "if (bus != main_system_bus)" work */
7267c094 879 main_system_bus = g_malloc0(system_bus_info.size);
2da8bb92
IY
880 main_system_bus->qdev_allocated = 1;
881 qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
882 "main-system-bus");
883}
884
131ec1bd
GH
885void qbus_free(BusState *bus)
886{
887 DeviceState *dev;
888
d8bb00d6 889 while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
131ec1bd
GH
890 qdev_free(dev);
891 }
892 if (bus->parent) {
893 QLIST_REMOVE(bus, sibling);
894 bus->parent->num_child_bus--;
80376c3f
IY
895 } else {
896 assert(bus != main_system_bus); /* main_system_bus is never freed */
897 qemu_unregister_reset(qbus_reset_all_fn, bus);
131ec1bd 898 }
7267c094 899 g_free((void*)bus->name);
131ec1bd 900 if (bus->qdev_allocated) {
7267c094 901 g_free(bus);
131ec1bd
GH
902 }
903}
904
cae4956e
GH
905#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
906static void qbus_print(Monitor *mon, BusState *bus, int indent);
907
ee6847d1
GH
908static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
909 const char *prefix, int indent)
910{
911 char buf[64];
912
913 if (!props)
914 return;
915 while (props->name) {
036f7166
MA
916 /*
917 * TODO Properties without a print method are just for dirty
918 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
919 * marked for removal. The test props->info->print should be
920 * removed along with it.
921 */
ee6847d1
GH
922 if (props->info->print) {
923 props->info->print(dev, props, buf, sizeof(buf));
924 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
925 }
926 props++;
927 }
928}
929
cae4956e
GH
930static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
931{
cae4956e 932 BusState *child;
ccb63de3
GH
933 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
934 dev->id ? dev->id : "");
cae4956e
GH
935 indent += 2;
936 if (dev->num_gpio_in) {
937 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
938 }
939 if (dev->num_gpio_out) {
940 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
941 }
ee6847d1
GH
942 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
943 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
10c4c98a
GH
944 if (dev->parent_bus->info->print_dev)
945 dev->parent_bus->info->print_dev(mon, dev, indent);
72cf2d4f 946 QLIST_FOREACH(child, &dev->child_bus, sibling) {
cae4956e
GH
947 qbus_print(mon, child, indent);
948 }
949}
950
951static void qbus_print(Monitor *mon, BusState *bus, int indent)
952{
953 struct DeviceState *dev;
954
955 qdev_printf("bus: %s\n", bus->name);
956 indent += 2;
10c4c98a 957 qdev_printf("type %s\n", bus->info->name);
d8bb00d6 958 QTAILQ_FOREACH(dev, &bus->children, sibling) {
cae4956e
GH
959 qdev_print(mon, dev, indent);
960 }
961}
962#undef qdev_printf
963
964void do_info_qtree(Monitor *mon)
965{
966 if (main_system_bus)
967 qbus_print(mon, main_system_bus, 0);
968}
9316d30f 969
f6c64e0e 970void do_info_qdm(Monitor *mon)
9316d30f
GH
971{
972 DeviceInfo *info;
9316d30f
GH
973
974 for (info = device_info_list; info != NULL; info = info->next) {
8a9662ca 975 qdev_print_devinfo(info);
9316d30f
GH
976 }
977}
3418bd25 978
8bc27249 979int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
3418bd25
GH
980{
981 QemuOpts *opts;
982
3329f07b 983 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
8bc27249
MA
984 if (!opts) {
985 return -1;
986 }
987 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
988 qemu_opts_del(opts);
989 return 0;
0f853a38 990 }
8bc27249
MA
991 if (!qdev_device_add(opts)) {
992 qemu_opts_del(opts);
993 return -1;
994 }
995 return 0;
3418bd25
GH
996}
997
17a38eaa 998int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
3418bd25
GH
999{
1000 const char *id = qdict_get_str(qdict, "id");
1001 DeviceState *dev;
1002
1003 dev = qdev_find_recursive(main_system_bus, id);
1004 if (NULL == dev) {
17a38eaa
MA
1005 qerror_report(QERR_DEVICE_NOT_FOUND, id);
1006 return -1;
3418bd25 1007 }
17a38eaa 1008 return qdev_unplug(dev);
3418bd25 1009}
1ca4d09a
GN
1010
1011static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
1012{
1013 int l = 0;
1014
1015 if (dev && dev->parent_bus) {
1016 char *d;
1017 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
1018 if (dev->parent_bus->info->get_fw_dev_path) {
1019 d = dev->parent_bus->info->get_fw_dev_path(dev);
1020 l += snprintf(p + l, size - l, "%s", d);
7267c094 1021 g_free(d);
1ca4d09a
GN
1022 } else {
1023 l += snprintf(p + l, size - l, "%s", dev->info->name);
1024 }
1025 }
1026 l += snprintf(p + l , size - l, "/");
1027
1028 return l;
1029}
1030
1031char* qdev_get_fw_dev_path(DeviceState *dev)
1032{
1033 char path[128];
1034 int l;
1035
1036 l = qdev_get_fw_dev_path_helper(dev, path, 128);
1037
1038 path[l-1] = '\0';
1039
1040 return strdup(path);
1041}
85ed303b 1042
cd34d667
AL
1043char *qdev_get_type(DeviceState *dev, Error **errp)
1044{
1045 return g_strdup(dev->info->name);
1046}
1047
85ed303b
AL
1048void qdev_ref(DeviceState *dev)
1049{
1050 dev->ref++;
1051}
1052
1053void qdev_unref(DeviceState *dev)
1054{
1055 g_assert(dev->ref > 0);
1056 dev->ref--;
1057}
44677ded
AL
1058
1059void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1060 DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1061 DevicePropertyRelease *release,
1062 void *opaque, Error **errp)
1063{
1064 DeviceProperty *prop = g_malloc0(sizeof(*prop));
1065
1066 prop->name = g_strdup(name);
1067 prop->type = g_strdup(type);
1068
1069 prop->get = get;
1070 prop->set = set;
1071 prop->release = release;
1072 prop->opaque = opaque;
1073
1074 QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1075}
1076
1077static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1078{
1079 DeviceProperty *prop;
1080
1081 QTAILQ_FOREACH(prop, &dev->properties, node) {
1082 if (strcmp(prop->name, name) == 0) {
1083 return prop;
1084 }
1085 }
1086
1087 return NULL;
1088}
1089
1090void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1091 Error **errp)
1092{
1093 DeviceProperty *prop = qdev_property_find(dev, name);
1094
1095 if (prop == NULL) {
1096 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1097 return;
1098 }
1099
1100 if (!prop->get) {
1101 error_set(errp, QERR_PERMISSION_DENIED);
1102 } else {
1103 prop->get(dev, v, prop->opaque, name, errp);
1104 }
1105}
1106
1107void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1108 Error **errp)
1109{
1110 DeviceProperty *prop = qdev_property_find(dev, name);
1111
1112 if (prop == NULL) {
1113 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1114 return;
1115 }
1116
1117 if (!prop->set) {
1118 error_set(errp, QERR_PERMISSION_DENIED);
1119 } else {
0d41d9aa 1120 prop->set(dev, v, prop->opaque, name, errp);
44677ded
AL
1121 }
1122}
1123
1124const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1125{
1126 DeviceProperty *prop = qdev_property_find(dev, name);
1127
1128 if (prop == NULL) {
1129 error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1130 return NULL;
1131 }
1132
1133 return prop->type;
1134}
a5296ca9
AL
1135
1136/**
1137 * Legacy property handling
1138 */
1139
1140static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1141 const char *name, Error **errp)
1142{
1143 Property *prop = opaque;
1144
e3cb6ba6
PB
1145 char buffer[1024];
1146 char *ptr = buffer;
a5296ca9 1147
e3cb6ba6
PB
1148 prop->info->print(dev, prop, buffer, sizeof(buffer));
1149 visit_type_str(v, &ptr, name, errp);
a5296ca9
AL
1150}
1151
1152static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1153 const char *name, Error **errp)
1154{
1155 Property *prop = opaque;
e3cb6ba6
PB
1156 Error *local_err = NULL;
1157 char *ptr = NULL;
1158 int ret;
a5296ca9
AL
1159
1160 if (dev->state != DEV_STATE_CREATED) {
1161 error_set(errp, QERR_PERMISSION_DENIED);
1162 return;
1163 }
1164
e3cb6ba6
PB
1165 visit_type_str(v, &ptr, name, &local_err);
1166 if (local_err) {
1167 error_propagate(errp, local_err);
1168 return;
1169 }
a5296ca9 1170
e3cb6ba6 1171 ret = prop->info->parse(dev, prop, ptr);
7db4c4e8 1172 error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
e3cb6ba6 1173 g_free(ptr);
a5296ca9
AL
1174}
1175
1176/**
1177 * @qdev_add_legacy_property - adds a legacy property
1178 *
1179 * Do not use this is new code! Properties added through this interface will
ca2cc788 1180 * be given names and types in the "legacy" namespace.
a5296ca9
AL
1181 *
1182 * Legacy properties are always processed as strings. The format of the string
1183 * depends on the property type.
1184 */
1185void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1186 Error **errp)
1187{
ca2cc788 1188 gchar *name, *type;
a5296ca9 1189
ca2cc788 1190 name = g_strdup_printf("legacy-%s", prop->name);
cafe5bdb
PB
1191 type = g_strdup_printf("legacy<%s>",
1192 prop->info->legacy_name ?: prop->info->name);
a5296ca9 1193
ca2cc788 1194 qdev_property_add(dev, name, type,
e3cb6ba6
PB
1195 prop->info->print ? qdev_get_legacy_property : NULL,
1196 prop->info->parse ? qdev_set_legacy_property : NULL,
a5296ca9
AL
1197 NULL,
1198 prop, errp);
1199
1200 g_free(type);
ca2cc788
PB
1201 g_free(name);
1202}
1203
1204/**
1205 * @qdev_property_add_static - add a @Property to a device.
1206 *
1207 * Static properties access data in a struct. The actual type of the
1208 * property and the field depends on the property type.
1209 */
1210void qdev_property_add_static(DeviceState *dev, Property *prop,
1211 Error **errp)
1212{
1213 qdev_property_add(dev, prop->name, prop->info->name,
1214 prop->info->get, prop->info->set,
1215 NULL,
1216 prop, errp);
a5296ca9 1217}
a10f07a7
AL
1218
1219DeviceState *qdev_get_root(void)
1220{
1221 static DeviceState *qdev_root;
1222
1223 if (!qdev_root) {
1224 qdev_root = qdev_create(NULL, "container");
1225 qdev_init_nofail(qdev_root);
1226 }
1227
1228 return qdev_root;
1229}
f9fbd2fd 1230
3de1c3e8
AL
1231static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1232 const char *name, Error **errp)
1233{
1234 DeviceState *child = opaque;
1235 gchar *path;
1236
1237 path = qdev_get_canonical_path(child);
1238 visit_type_str(v, &path, name, errp);
1239 g_free(path);
1240}
1241
1242void qdev_property_add_child(DeviceState *dev, const char *name,
1243 DeviceState *child, Error **errp)
1244{
1245 gchar *type;
1246
1247 type = g_strdup_printf("child<%s>", child->info->name);
1248
1249 qdev_property_add(dev, name, type, qdev_get_child_property,
1250 NULL, NULL, child, errp);
1251
1252 qdev_ref(child);
b2b6c39a
AL
1253 g_assert(child->parent == NULL);
1254 child->parent = dev;
3de1c3e8
AL
1255
1256 g_free(type);
1257}
1258
83e94fb8
AL
1259static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
1260 const char *name, Error **errp)
1261{
1262 DeviceState **child = opaque;
1263 gchar *path;
1264
1265 if (*child) {
1266 path = qdev_get_canonical_path(*child);
1267 visit_type_str(v, &path, name, errp);
1268 g_free(path);
1269 } else {
1270 path = (gchar *)"";
1271 visit_type_str(v, &path, name, errp);
1272 }
1273}
1274
1275static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
1276 const char *name, Error **errp)
1277{
1278 DeviceState **child = opaque;
1279 bool ambiguous = false;
1280 const char *type;
1281 char *path;
1282
1283 type = qdev_property_get_type(dev, name, NULL);
1284
1285 visit_type_str(v, &path, name, errp);
1286
1287 if (*child) {
1288 qdev_unref(*child);
1289 }
1290
1291 if (strcmp(path, "") != 0) {
1292 DeviceState *target;
1293
1294 target = qdev_resolve_path(path, &ambiguous);
1295 if (target) {
1296 gchar *target_type;
1297
1298 target_type = g_strdup_printf("link<%s>", target->info->name);
1299 if (strcmp(target_type, type) == 0) {
1300 *child = target;
1301 qdev_ref(target);
1302 } else {
1303 error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
1304 }
1305
1306 g_free(target_type);
1307 } else {
1308 error_set(errp, QERR_DEVICE_NOT_FOUND, path);
1309 }
1310 } else {
1311 *child = NULL;
1312 }
1313
1314 g_free(path);
1315}
1316
1317void qdev_property_add_link(DeviceState *dev, const char *name,
1318 const char *type, DeviceState **child,
1319 Error **errp)
1320{
1321 gchar *full_type;
1322
1323 full_type = g_strdup_printf("link<%s>", type);
1324
1325 qdev_property_add(dev, name, full_type,
1326 qdev_get_link_property,
1327 qdev_set_link_property,
1328 NULL, child, errp);
1329
1330 g_free(full_type);
1331}
1332
b2b6c39a 1333gchar *qdev_get_canonical_path(DeviceState *dev)
f9fbd2fd 1334{
b2b6c39a
AL
1335 DeviceState *root = qdev_get_root();
1336 char *newpath = NULL, *path = NULL;
f9fbd2fd 1337
b2b6c39a
AL
1338 while (dev != root) {
1339 DeviceProperty *prop = NULL;
f9fbd2fd 1340
b2b6c39a 1341 g_assert(dev->parent != NULL);
f9fbd2fd 1342
b2b6c39a
AL
1343 QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
1344 if (!strstart(prop->type, "child<", NULL)) {
1345 continue;
1346 }
f9fbd2fd 1347
b2b6c39a
AL
1348 if (prop->opaque == dev) {
1349 if (path) {
1350 newpath = g_strdup_printf("%s/%s", prop->name, path);
1351 g_free(path);
1352 path = newpath;
1353 } else {
1354 path = g_strdup(prop->name);
1355 }
1356 break;
1357 }
f9fbd2fd
AL
1358 }
1359
b2b6c39a 1360 g_assert(prop != NULL);
f9fbd2fd 1361
b2b6c39a 1362 dev = dev->parent;
f9fbd2fd
AL
1363 }
1364
f9fbd2fd
AL
1365 newpath = g_strdup_printf("/%s", path);
1366 g_free(path);
1367
1368 return newpath;
1369}
dc45c21f
AL
1370
1371static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1372 gchar **parts,
1373 int index)
1374{
1375 DeviceProperty *prop;
1376 DeviceState *child;
1377
1378 if (parts[index] == NULL) {
1379 return parent;
1380 }
1381
1382 if (strcmp(parts[index], "") == 0) {
1383 return qdev_resolve_abs_path(parent, parts, index + 1);
1384 }
1385
1386 prop = qdev_property_find(parent, parts[index]);
1387 if (prop == NULL) {
1388 return NULL;
1389 }
1390
1391 child = NULL;
1392 if (strstart(prop->type, "link<", NULL)) {
1393 DeviceState **pchild = prop->opaque;
1394 if (*pchild) {
1395 child = *pchild;
1396 }
1397 } else if (strstart(prop->type, "child<", NULL)) {
1398 child = prop->opaque;
1399 }
1400
1401 if (!child) {
1402 return NULL;
1403 }
1404
1405 return qdev_resolve_abs_path(child, parts, index + 1);
1406}
1407
1408static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1409 gchar **parts,
1410 bool *ambiguous)
1411{
1412 DeviceState *dev;
1413 DeviceProperty *prop;
1414
1415 dev = qdev_resolve_abs_path(parent, parts, 0);
1416
1417 QTAILQ_FOREACH(prop, &parent->properties, node) {
1418 DeviceState *found;
1419
1420 if (!strstart(prop->type, "child<", NULL)) {
1421 continue;
1422 }
1423
1424 found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1425 if (found) {
1426 if (dev) {
1427 if (ambiguous) {
1428 *ambiguous = true;
1429 }
1430 return NULL;
1431 }
1432 dev = found;
1433 }
1434
1435 if (ambiguous && *ambiguous) {
1436 return NULL;
1437 }
1438 }
1439
1440 return dev;
1441}
1442
1443DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1444{
1445 bool partial_path = true;
1446 DeviceState *dev;
1447 gchar **parts;
1448
1449 parts = g_strsplit(path, "/", 0);
1450 if (parts == NULL || parts[0] == NULL) {
1451 g_strfreev(parts);
1452 return qdev_get_root();
1453 }
1454
1455 if (strcmp(parts[0], "") == 0) {
1456 partial_path = false;
1457 }
1458
1459 if (partial_path) {
1460 if (ambiguous) {
1461 *ambiguous = false;
1462 }
1463 dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1464 } else {
1465 dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1466 }
1467
1468 g_strfreev(parts);
1469
1470 return dev;
1471}
1472
6a146eba
AL
1473typedef struct StringProperty
1474{
1475 char *(*get)(DeviceState *, Error **);
1476 void (*set)(DeviceState *, const char *, Error **);
1477} StringProperty;
1478
1479static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1480 const char *name, Error **errp)
1481{
1482 StringProperty *prop = opaque;
1483 char *value;
1484
1485 value = prop->get(dev, errp);
1486 if (value) {
1487 visit_type_str(v, &value, name, errp);
1488 g_free(value);
1489 }
1490}
1491
1492static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1493 const char *name, Error **errp)
1494{
1495 StringProperty *prop = opaque;
1496 char *value;
1497 Error *local_err = NULL;
1498
1499 visit_type_str(v, &value, name, &local_err);
1500 if (local_err) {
1501 error_propagate(errp, local_err);
1502 return;
1503 }
1504
1505 prop->set(dev, value, errp);
1506 g_free(value);
1507}
1508
1509static void qdev_property_release_str(DeviceState *dev, const char *name,
1510 void *opaque)
1511{
1512 StringProperty *prop = opaque;
1513 g_free(prop);
1514}
1515
1516void qdev_property_add_str(DeviceState *dev, const char *name,
1517 char *(*get)(DeviceState *, Error **),
1518 void (*set)(DeviceState *, const char *, Error **),
1519 Error **errp)
1520{
1521 StringProperty *prop = g_malloc0(sizeof(*prop));
1522
1523 prop->get = get;
1524 prop->set = set;
1525
1526 qdev_property_add(dev, name, "string",
1527 get ? qdev_property_get_str : NULL,
1528 set ? qdev_property_set_str : NULL,
1529 qdev_property_release_str,
1530 prop, errp);
1531}
1de81d28
AL
1532
1533void qdev_machine_init(void)
1534{
1535 qdev_get_peripheral_anon();
1536 qdev_get_peripheral();
1537}