]> Git Repo - qemu.git/blob - hw/qdev-monitor.c
qdev: add children before qdev_init
[qemu.git] / hw / qdev-monitor.c
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
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "qdev.h"
21 #include "monitor.h"
22
23 /*
24  * Aliases were a bad idea from the start.  Let's keep them
25  * from spreading further.
26  */
27 typedef struct QDevAlias
28 {
29     const char *typename;
30     const char *alias;
31 } QDevAlias;
32
33 static const QDevAlias qdev_alias_table[] = {
34     { "virtio-blk-pci", "virtio-blk" },
35     { "virtio-net-pci", "virtio-net" },
36     { "virtio-serial-pci", "virtio-serial" },
37     { "virtio-balloon-pci", "virtio-balloon" },
38     { "virtio-blk-s390", "virtio-blk" },
39     { "virtio-net-s390", "virtio-net" },
40     { "virtio-serial-s390", "virtio-serial" },
41     { "lsi53c895a", "lsi" },
42     { "ich9-ahci", "ahci" },
43     { }
44 };
45
46 static const char *qdev_class_get_alias(DeviceClass *dc)
47 {
48     const char *typename = object_class_get_name(OBJECT_CLASS(dc));
49     int i;
50
51     for (i = 0; qdev_alias_table[i].typename; i++) {
52         if (strcmp(qdev_alias_table[i].typename, typename) == 0) {
53             return qdev_alias_table[i].alias;
54         }
55     }
56
57     return NULL;
58 }
59
60 static bool qdev_class_has_alias(DeviceClass *dc)
61 {
62     return (qdev_class_get_alias(dc) != NULL);
63 }
64
65 static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
66 {
67     DeviceClass *dc;
68     bool *show_no_user = opaque;
69
70     dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
71
72     if (!dc || (show_no_user && !*show_no_user && dc->no_user)) {
73         return;
74     }
75
76     error_printf("name \"%s\"", object_class_get_name(klass));
77     if (dc->bus_info) {
78         error_printf(", bus %s", dc->bus_info->name);
79     }
80     if (qdev_class_has_alias(dc)) {
81         error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
82     }
83     if (dc->desc) {
84         error_printf(", desc \"%s\"", dc->desc);
85     }
86     if (dc->no_user) {
87         error_printf(", no-user");
88     }
89     error_printf("\n");
90 }
91
92 static int set_property(const char *name, const char *value, void *opaque)
93 {
94     DeviceState *dev = opaque;
95
96     if (strcmp(name, "driver") == 0)
97         return 0;
98     if (strcmp(name, "bus") == 0)
99         return 0;
100
101     if (qdev_prop_parse(dev, name, value) == -1) {
102         return -1;
103     }
104     return 0;
105 }
106
107 static const char *find_typename_by_alias(const char *alias)
108 {
109     int i;
110
111     for (i = 0; qdev_alias_table[i].alias; i++) {
112         if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
113             return qdev_alias_table[i].typename;
114         }
115     }
116
117     return NULL;
118 }
119
120 int qdev_device_help(QemuOpts *opts)
121 {
122     const char *driver;
123     Property *prop;
124     ObjectClass *klass;
125     DeviceClass *info;
126
127     driver = qemu_opt_get(opts, "driver");
128     if (driver && !strcmp(driver, "?")) {
129         bool show_no_user = false;
130         object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
131         return 1;
132     }
133
134     if (!driver || !qemu_opt_get(opts, "?")) {
135         return 0;
136     }
137
138     klass = object_class_by_name(driver);
139     if (!klass) {
140         const char *typename = find_typename_by_alias(driver);
141
142         if (typename) {
143             driver = typename;
144             klass = object_class_by_name(driver);
145         }
146     }
147
148     if (!klass) {
149         return 0;
150     }
151     info = DEVICE_CLASS(klass);
152
153     for (prop = info->props; prop && prop->name; prop++) {
154         /*
155          * TODO Properties without a parser are just for dirty hacks.
156          * qdev_prop_ptr is the only such PropertyInfo.  It's marked
157          * for removal.  This conditional should be removed along with
158          * it.
159          */
160         if (!prop->info->parse) {
161             continue;           /* no way to set it, don't show */
162         }
163         error_printf("%s.%s=%s\n", driver, prop->name,
164                      prop->info->legacy_name ?: prop->info->name);
165     }
166     if (info->bus_info) {
167         for (prop = info->bus_info->props; prop && prop->name; prop++) {
168             if (!prop->info->parse) {
169                 continue;           /* no way to set it, don't show */
170             }
171             error_printf("%s.%s=%s\n", driver, prop->name,
172                          prop->info->legacy_name ?: prop->info->name);
173         }
174     }
175     return 1;
176 }
177
178 static Object *qdev_get_peripheral(void)
179 {
180     static Object *dev;
181
182     if (dev == NULL) {
183         dev = container_get("/peripheral");
184     }
185
186     return dev;
187 }
188
189 static Object *qdev_get_peripheral_anon(void)
190 {
191     static Object *dev;
192
193     if (dev == NULL) {
194         dev = container_get("/peripheral-anon");
195     }
196
197     return dev;
198 }
199
200 static void qbus_list_bus(DeviceState *dev)
201 {
202     BusState *child;
203     const char *sep = " ";
204
205     error_printf("child busses at \"%s\":",
206                  dev->id ? dev->id : object_get_typename(OBJECT(dev)));
207     QLIST_FOREACH(child, &dev->child_bus, sibling) {
208         error_printf("%s\"%s\"", sep, child->name);
209         sep = ", ";
210     }
211     error_printf("\n");
212 }
213
214 static void qbus_list_dev(BusState *bus)
215 {
216     DeviceState *dev;
217     const char *sep = " ";
218
219     error_printf("devices at \"%s\":", bus->name);
220     QTAILQ_FOREACH(dev, &bus->children, sibling) {
221         error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
222         if (dev->id)
223             error_printf("/\"%s\"", dev->id);
224         sep = ", ";
225     }
226     error_printf("\n");
227 }
228
229 static BusState *qbus_find_bus(DeviceState *dev, char *elem)
230 {
231     BusState *child;
232
233     QLIST_FOREACH(child, &dev->child_bus, sibling) {
234         if (strcmp(child->name, elem) == 0) {
235             return child;
236         }
237     }
238     return NULL;
239 }
240
241 static DeviceState *qbus_find_dev(BusState *bus, char *elem)
242 {
243     DeviceState *dev;
244
245     /*
246      * try to match in order:
247      *   (1) instance id, if present
248      *   (2) driver name
249      *   (3) driver alias, if present
250      */
251     QTAILQ_FOREACH(dev, &bus->children, sibling) {
252         if (dev->id  &&  strcmp(dev->id, elem) == 0) {
253             return dev;
254         }
255     }
256     QTAILQ_FOREACH(dev, &bus->children, sibling) {
257         if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
258             return dev;
259         }
260     }
261     QTAILQ_FOREACH(dev, &bus->children, sibling) {
262         DeviceClass *dc = DEVICE_GET_CLASS(dev);
263
264         if (qdev_class_has_alias(dc) &&
265             strcmp(qdev_class_get_alias(dc), elem) == 0) {
266             return dev;
267         }
268     }
269     return NULL;
270 }
271
272 static BusState *qbus_find_recursive(BusState *bus, const char *name,
273                                      const BusInfo *info)
274 {
275     DeviceState *dev;
276     BusState *child, *ret;
277     int match = 1;
278
279     if (name && (strcmp(bus->name, name) != 0)) {
280         match = 0;
281     }
282     if (info && (bus->info != info)) {
283         match = 0;
284     }
285     if (match) {
286         return bus;
287     }
288
289     QTAILQ_FOREACH(dev, &bus->children, sibling) {
290         QLIST_FOREACH(child, &dev->child_bus, sibling) {
291             ret = qbus_find_recursive(child, name, info);
292             if (ret) {
293                 return ret;
294             }
295         }
296     }
297     return NULL;
298 }
299
300 static BusState *qbus_find(const char *path)
301 {
302     DeviceState *dev;
303     BusState *bus;
304     char elem[128];
305     int pos, len;
306
307     /* find start element */
308     if (path[0] == '/') {
309         bus = sysbus_get_default();
310         pos = 0;
311     } else {
312         if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
313             assert(!path[0]);
314             elem[0] = len = 0;
315         }
316         bus = qbus_find_recursive(sysbus_get_default(), elem, NULL);
317         if (!bus) {
318             qerror_report(QERR_BUS_NOT_FOUND, elem);
319             return NULL;
320         }
321         pos = len;
322     }
323
324     for (;;) {
325         assert(path[pos] == '/' || !path[pos]);
326         while (path[pos] == '/') {
327             pos++;
328         }
329         if (path[pos] == '\0') {
330             return bus;
331         }
332
333         /* find device */
334         if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
335             assert(0);
336             elem[0] = len = 0;
337         }
338         pos += len;
339         dev = qbus_find_dev(bus, elem);
340         if (!dev) {
341             qerror_report(QERR_DEVICE_NOT_FOUND, elem);
342             if (!monitor_cur_is_qmp()) {
343                 qbus_list_dev(bus);
344             }
345             return NULL;
346         }
347
348         assert(path[pos] == '/' || !path[pos]);
349         while (path[pos] == '/') {
350             pos++;
351         }
352         if (path[pos] == '\0') {
353             /* last specified element is a device.  If it has exactly
354              * one child bus accept it nevertheless */
355             switch (dev->num_child_bus) {
356             case 0:
357                 qerror_report(QERR_DEVICE_NO_BUS, elem);
358                 return NULL;
359             case 1:
360                 return QLIST_FIRST(&dev->child_bus);
361             default:
362                 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
363                 if (!monitor_cur_is_qmp()) {
364                     qbus_list_bus(dev);
365                 }
366                 return NULL;
367             }
368         }
369
370         /* find bus */
371         if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
372             assert(0);
373             elem[0] = len = 0;
374         }
375         pos += len;
376         bus = qbus_find_bus(dev, elem);
377         if (!bus) {
378             qerror_report(QERR_BUS_NOT_FOUND, elem);
379             if (!monitor_cur_is_qmp()) {
380                 qbus_list_bus(dev);
381             }
382             return NULL;
383         }
384     }
385 }
386
387 DeviceState *qdev_device_add(QemuOpts *opts)
388 {
389     ObjectClass *obj;
390     DeviceClass *k;
391     const char *driver, *path, *id;
392     DeviceState *qdev;
393     BusState *bus;
394
395     driver = qemu_opt_get(opts, "driver");
396     if (!driver) {
397         qerror_report(QERR_MISSING_PARAMETER, "driver");
398         return NULL;
399     }
400
401     /* find driver */
402     obj = object_class_by_name(driver);
403     if (!obj) {
404         const char *typename = find_typename_by_alias(driver);
405
406         if (typename) {
407             driver = typename;
408             obj = object_class_by_name(driver);
409         }
410     }
411
412     if (!obj) {
413         qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
414         return NULL;
415     }
416
417     k = DEVICE_CLASS(obj);
418
419     /* find bus */
420     path = qemu_opt_get(opts, "bus");
421     if (path != NULL) {
422         bus = qbus_find(path);
423         if (!bus) {
424             return NULL;
425         }
426         if (bus->info != k->bus_info) {
427             qerror_report(QERR_BAD_BUS_FOR_DEVICE,
428                            driver, bus->info->name);
429             return NULL;
430         }
431     } else {
432         bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_info);
433         if (!bus) {
434             qerror_report(QERR_NO_BUS_FOR_DEVICE,
435                           driver, k->bus_info->name);
436             return NULL;
437         }
438     }
439     if (qdev_hotplug && !bus->allow_hotplug) {
440         qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
441         return NULL;
442     }
443
444     if (!bus) {
445         bus = sysbus_get_default();
446     }
447
448     /* create device, set properties */
449     qdev = DEVICE(object_new(driver));
450     qdev_set_parent_bus(qdev, bus);
451     qdev_prop_set_globals(qdev);
452
453     id = qemu_opts_id(opts);
454     if (id) {
455         qdev->id = id;
456     }
457     if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
458         qdev_free(qdev);
459         return NULL;
460     }
461     if (qdev->id) {
462         object_property_add_child(qdev_get_peripheral(), qdev->id,
463                                   OBJECT(qdev), NULL);
464     } else {
465         static int anon_count;
466         gchar *name = g_strdup_printf("device[%d]", anon_count++);
467         object_property_add_child(qdev_get_peripheral_anon(), name,
468                                   OBJECT(qdev), NULL);
469         g_free(name);
470     }        
471     if (qdev_init(qdev) < 0) {
472         qerror_report(QERR_DEVICE_INIT_FAILED, driver);
473         return NULL;
474     }
475     qdev->opts = opts;
476     return qdev;
477 }
478
479
480 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
481 static void qbus_print(Monitor *mon, BusState *bus, int indent);
482
483 static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
484                              const char *prefix, int indent)
485 {
486     if (!props)
487         return;
488     for (; props->name; props++) {
489         Error *err = NULL;
490         char *value;
491         char *legacy_name = g_strdup_printf("legacy-%s", props->name);
492         if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
493             value = object_property_get_str(OBJECT(dev), legacy_name, &err);
494         } else {
495             value = object_property_get_str(OBJECT(dev), props->name, &err);
496         }
497         g_free(legacy_name);
498
499         if (err) {
500             error_free(err);
501             continue;
502         }
503         qdev_printf("%s-prop: %s = %s\n", prefix, props->name,
504                     value && *value ? value : "<null>");
505         g_free(value);
506     }
507 }
508
509 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
510 {
511     BusState *child;
512     qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
513                 dev->id ? dev->id : "");
514     indent += 2;
515     if (dev->num_gpio_in) {
516         qdev_printf("gpio-in %d\n", dev->num_gpio_in);
517     }
518     if (dev->num_gpio_out) {
519         qdev_printf("gpio-out %d\n", dev->num_gpio_out);
520     }
521     qdev_print_props(mon, dev, qdev_get_props(dev), "dev", indent);
522     qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
523     if (dev->parent_bus->info->print_dev)
524         dev->parent_bus->info->print_dev(mon, dev, indent);
525     QLIST_FOREACH(child, &dev->child_bus, sibling) {
526         qbus_print(mon, child, indent);
527     }
528 }
529
530 static void qbus_print(Monitor *mon, BusState *bus, int indent)
531 {
532     struct DeviceState *dev;
533
534     qdev_printf("bus: %s\n", bus->name);
535     indent += 2;
536     qdev_printf("type %s\n", bus->info->name);
537     QTAILQ_FOREACH(dev, &bus->children, sibling) {
538         qdev_print(mon, dev, indent);
539     }
540 }
541 #undef qdev_printf
542
543 void do_info_qtree(Monitor *mon)
544 {
545     if (sysbus_get_default())
546         qbus_print(mon, sysbus_get_default(), 0);
547 }
548
549 void do_info_qdm(Monitor *mon)
550 {
551     object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, NULL);
552 }
553
554 int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
555 {
556     QemuOpts *opts;
557
558     opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
559     if (!opts) {
560         return -1;
561     }
562     if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
563         qemu_opts_del(opts);
564         return 0;
565     }
566     if (!qdev_device_add(opts)) {
567         qemu_opts_del(opts);
568         return -1;
569     }
570     return 0;
571 }
572
573 int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
574 {
575     const char *id = qdict_get_str(qdict, "id");
576     DeviceState *dev;
577
578     dev = qdev_find_recursive(sysbus_get_default(), id);
579     if (NULL == dev) {
580         qerror_report(QERR_DEVICE_NOT_FOUND, id);
581         return -1;
582     }
583     return qdev_unplug(dev);
584 }
585
586 void qdev_machine_init(void)
587 {
588     qdev_get_peripheral_anon();
589     qdev_get_peripheral();
590 }
This page took 0.057495 seconds and 4 git commands to generate.