]> Git Repo - qemu.git/blob - hw/qdev-monitor.c
qom: move properties from qdev to object
[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     for (prop = info->bus_info->props; prop && prop->name; prop++) {
167         if (!prop->info->parse) {
168             continue;           /* no way to set it, don't show */
169         }
170         error_printf("%s.%s=%s\n", driver, prop->name,
171                      prop->info->legacy_name ?: prop->info->name);
172     }
173     return 1;
174 }
175
176 static Object *qdev_get_peripheral(void)
177 {
178     static DeviceState *dev;
179
180     if (dev == NULL) {
181         dev = qdev_create(NULL, "container");
182         object_property_add_child(object_get_root(), "peripheral",
183                                   OBJECT(dev), NULL);
184         qdev_init_nofail(dev);
185     }
186
187     return OBJECT(dev);
188 }
189
190 static Object *qdev_get_peripheral_anon(void)
191 {
192     static DeviceState *dev;
193
194     if (dev == NULL) {
195         dev = qdev_create(NULL, "container");
196         object_property_add_child(object_get_root(), "peripheral-anon",
197                                   OBJECT(dev), NULL);
198         qdev_init_nofail(dev);
199     }
200
201     return OBJECT(dev);
202 }
203
204 static void qbus_list_bus(DeviceState *dev)
205 {
206     BusState *child;
207     const char *sep = " ";
208
209     error_printf("child busses at \"%s\":",
210                  dev->id ? dev->id : object_get_typename(OBJECT(dev)));
211     QLIST_FOREACH(child, &dev->child_bus, sibling) {
212         error_printf("%s\"%s\"", sep, child->name);
213         sep = ", ";
214     }
215     error_printf("\n");
216 }
217
218 static void qbus_list_dev(BusState *bus)
219 {
220     DeviceState *dev;
221     const char *sep = " ";
222
223     error_printf("devices at \"%s\":", bus->name);
224     QTAILQ_FOREACH(dev, &bus->children, sibling) {
225         error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
226         if (dev->id)
227             error_printf("/\"%s\"", dev->id);
228         sep = ", ";
229     }
230     error_printf("\n");
231 }
232
233 static BusState *qbus_find_bus(DeviceState *dev, char *elem)
234 {
235     BusState *child;
236
237     QLIST_FOREACH(child, &dev->child_bus, sibling) {
238         if (strcmp(child->name, elem) == 0) {
239             return child;
240         }
241     }
242     return NULL;
243 }
244
245 static DeviceState *qbus_find_dev(BusState *bus, char *elem)
246 {
247     DeviceState *dev;
248
249     /*
250      * try to match in order:
251      *   (1) instance id, if present
252      *   (2) driver name
253      *   (3) driver alias, if present
254      */
255     QTAILQ_FOREACH(dev, &bus->children, sibling) {
256         if (dev->id  &&  strcmp(dev->id, elem) == 0) {
257             return dev;
258         }
259     }
260     QTAILQ_FOREACH(dev, &bus->children, sibling) {
261         if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
262             return dev;
263         }
264     }
265     QTAILQ_FOREACH(dev, &bus->children, sibling) {
266         DeviceClass *dc = DEVICE_GET_CLASS(dev);
267
268         if (qdev_class_has_alias(dc) &&
269             strcmp(qdev_class_get_alias(dc), elem) == 0) {
270             return dev;
271         }
272     }
273     return NULL;
274 }
275
276 static BusState *qbus_find_recursive(BusState *bus, const char *name,
277                                      const BusInfo *info)
278 {
279     DeviceState *dev;
280     BusState *child, *ret;
281     int match = 1;
282
283     if (name && (strcmp(bus->name, name) != 0)) {
284         match = 0;
285     }
286     if (info && (bus->info != info)) {
287         match = 0;
288     }
289     if (match) {
290         return bus;
291     }
292
293     QTAILQ_FOREACH(dev, &bus->children, sibling) {
294         QLIST_FOREACH(child, &dev->child_bus, sibling) {
295             ret = qbus_find_recursive(child, name, info);
296             if (ret) {
297                 return ret;
298             }
299         }
300     }
301     return NULL;
302 }
303
304 static BusState *qbus_find(const char *path)
305 {
306     DeviceState *dev;
307     BusState *bus;
308     char elem[128];
309     int pos, len;
310
311     /* find start element */
312     if (path[0] == '/') {
313         bus = sysbus_get_default();
314         pos = 0;
315     } else {
316         if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
317             assert(!path[0]);
318             elem[0] = len = 0;
319         }
320         bus = qbus_find_recursive(sysbus_get_default(), elem, NULL);
321         if (!bus) {
322             qerror_report(QERR_BUS_NOT_FOUND, elem);
323             return NULL;
324         }
325         pos = len;
326     }
327
328     for (;;) {
329         assert(path[pos] == '/' || !path[pos]);
330         while (path[pos] == '/') {
331             pos++;
332         }
333         if (path[pos] == '\0') {
334             return bus;
335         }
336
337         /* find device */
338         if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
339             assert(0);
340             elem[0] = len = 0;
341         }
342         pos += len;
343         dev = qbus_find_dev(bus, elem);
344         if (!dev) {
345             qerror_report(QERR_DEVICE_NOT_FOUND, elem);
346             if (!monitor_cur_is_qmp()) {
347                 qbus_list_dev(bus);
348             }
349             return NULL;
350         }
351
352         assert(path[pos] == '/' || !path[pos]);
353         while (path[pos] == '/') {
354             pos++;
355         }
356         if (path[pos] == '\0') {
357             /* last specified element is a device.  If it has exactly
358              * one child bus accept it nevertheless */
359             switch (dev->num_child_bus) {
360             case 0:
361                 qerror_report(QERR_DEVICE_NO_BUS, elem);
362                 return NULL;
363             case 1:
364                 return QLIST_FIRST(&dev->child_bus);
365             default:
366                 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
367                 if (!monitor_cur_is_qmp()) {
368                     qbus_list_bus(dev);
369                 }
370                 return NULL;
371             }
372         }
373
374         /* find bus */
375         if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
376             assert(0);
377             elem[0] = len = 0;
378         }
379         pos += len;
380         bus = qbus_find_bus(dev, elem);
381         if (!bus) {
382             qerror_report(QERR_BUS_NOT_FOUND, elem);
383             if (!monitor_cur_is_qmp()) {
384                 qbus_list_bus(dev);
385             }
386             return NULL;
387         }
388     }
389 }
390
391 DeviceState *qdev_device_add(QemuOpts *opts)
392 {
393     ObjectClass *obj;
394     DeviceClass *k;
395     const char *driver, *path, *id;
396     DeviceState *qdev;
397     BusState *bus;
398
399     driver = qemu_opt_get(opts, "driver");
400     if (!driver) {
401         qerror_report(QERR_MISSING_PARAMETER, "driver");
402         return NULL;
403     }
404
405     /* find driver */
406     obj = object_class_by_name(driver);
407     if (!obj) {
408         const char *typename = find_typename_by_alias(driver);
409
410         if (typename) {
411             driver = typename;
412             obj = object_class_by_name(driver);
413         }
414     }
415
416     if (!obj) {
417         qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
418         return NULL;
419     }
420
421     k = DEVICE_CLASS(obj);
422
423     /* find bus */
424     path = qemu_opt_get(opts, "bus");
425     if (path != NULL) {
426         bus = qbus_find(path);
427         if (!bus) {
428             return NULL;
429         }
430         if (bus->info != k->bus_info) {
431             qerror_report(QERR_BAD_BUS_FOR_DEVICE,
432                            driver, bus->info->name);
433             return NULL;
434         }
435     } else {
436         bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_info);
437         if (!bus) {
438             qerror_report(QERR_NO_BUS_FOR_DEVICE,
439                           driver, k->bus_info->name);
440             return NULL;
441         }
442     }
443     if (qdev_hotplug && !bus->allow_hotplug) {
444         qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
445         return NULL;
446     }
447
448     if (!bus) {
449         bus = sysbus_get_default();
450     }
451
452     /* create device, set properties */
453     qdev = DEVICE(object_new(driver));
454     qdev_set_parent_bus(qdev, bus);
455     qdev_prop_set_globals(qdev);
456
457     id = qemu_opts_id(opts);
458     if (id) {
459         qdev->id = id;
460         object_property_add_child(qdev_get_peripheral(), qdev->id,
461                                   OBJECT(qdev), NULL);
462     } else {
463         static int anon_count;
464         gchar *name = g_strdup_printf("device[%d]", anon_count++);
465         object_property_add_child(qdev_get_peripheral_anon(), name,
466                                   OBJECT(qdev), NULL);
467         g_free(name);
468     }        
469     if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
470         qdev_free(qdev);
471         return NULL;
472     }
473     if (qdev_init(qdev) < 0) {
474         qerror_report(QERR_DEVICE_INIT_FAILED, driver);
475         return NULL;
476     }
477     qdev->opts = opts;
478     return qdev;
479 }
480
481
482 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
483 static void qbus_print(Monitor *mon, BusState *bus, int indent);
484
485 static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
486                              const char *prefix, int indent)
487 {
488     char buf[64];
489
490     if (!props)
491         return;
492     while (props->name) {
493         /*
494          * TODO Properties without a print method are just for dirty
495          * hacks.  qdev_prop_ptr is the only such PropertyInfo.  It's
496          * marked for removal.  The test props->info->print should be
497          * removed along with it.
498          */
499         if (props->info->print) {
500             props->info->print(dev, props, buf, sizeof(buf));
501             qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
502         }
503         props++;
504     }
505 }
506
507 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
508 {
509     BusState *child;
510     qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
511                 dev->id ? dev->id : "");
512     indent += 2;
513     if (dev->num_gpio_in) {
514         qdev_printf("gpio-in %d\n", dev->num_gpio_in);
515     }
516     if (dev->num_gpio_out) {
517         qdev_printf("gpio-out %d\n", dev->num_gpio_out);
518     }
519     qdev_print_props(mon, dev, qdev_get_props(dev), "dev", indent);
520     qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
521     if (dev->parent_bus->info->print_dev)
522         dev->parent_bus->info->print_dev(mon, dev, indent);
523     QLIST_FOREACH(child, &dev->child_bus, sibling) {
524         qbus_print(mon, child, indent);
525     }
526 }
527
528 static void qbus_print(Monitor *mon, BusState *bus, int indent)
529 {
530     struct DeviceState *dev;
531
532     qdev_printf("bus: %s\n", bus->name);
533     indent += 2;
534     qdev_printf("type %s\n", bus->info->name);
535     QTAILQ_FOREACH(dev, &bus->children, sibling) {
536         qdev_print(mon, dev, indent);
537     }
538 }
539 #undef qdev_printf
540
541 void do_info_qtree(Monitor *mon)
542 {
543     if (sysbus_get_default())
544         qbus_print(mon, sysbus_get_default(), 0);
545 }
546
547 void do_info_qdm(Monitor *mon)
548 {
549     object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, NULL);
550 }
551
552 int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
553 {
554     QemuOpts *opts;
555
556     opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
557     if (!opts) {
558         return -1;
559     }
560     if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
561         qemu_opts_del(opts);
562         return 0;
563     }
564     if (!qdev_device_add(opts)) {
565         qemu_opts_del(opts);
566         return -1;
567     }
568     return 0;
569 }
570
571 int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
572 {
573     const char *id = qdict_get_str(qdict, "id");
574     DeviceState *dev;
575
576     dev = qdev_find_recursive(sysbus_get_default(), id);
577     if (NULL == dev) {
578         qerror_report(QERR_DEVICE_NOT_FOUND, id);
579         return -1;
580     }
581     return qdev_unplug(dev);
582 }
583
584 void qdev_machine_init(void)
585 {
586     qdev_get_peripheral_anon();
587     qdev_get_peripheral();
588 }
This page took 0.057246 seconds and 4 git commands to generate.