Statistics
| Branch: | Revision:

root / qdev-monitor.c @ 2fa4e56d

History | View | Annotate | Download (19.6 kB)

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 "hw/qdev.h"
21
#include "hw/sysbus.h"
22
#include "monitor/monitor.h"
23
#include "monitor/qdev.h"
24
#include "qmp-commands.h"
25
#include "sysemu/arch_init.h"
26
#include "qemu/config-file.h"
27

    
28
/*
29
 * Aliases were a bad idea from the start.  Let's keep them
30
 * from spreading further.
31
 */
32
typedef struct QDevAlias
33
{
34
    const char *typename;
35
    const char *alias;
36
    uint32_t arch_mask;
37
} QDevAlias;
38

    
39
static const QDevAlias qdev_alias_table[] = {
40
    { "virtio-blk-pci", "virtio-blk", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
41
    { "virtio-net-pci", "virtio-net", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
42
    { "virtio-serial-pci", "virtio-serial", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
43
    { "virtio-balloon-pci", "virtio-balloon",
44
            QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
45
    { "virtio-blk-s390", "virtio-blk", QEMU_ARCH_S390X },
46
    { "virtio-net-s390", "virtio-net", QEMU_ARCH_S390X },
47
    { "virtio-serial-s390", "virtio-serial", QEMU_ARCH_S390X },
48
    { "lsi53c895a", "lsi" },
49
    { "ich9-ahci", "ahci" },
50
    { "kvm-pci-assign", "pci-assign" },
51
    { }
52
};
53

    
54
static const char *qdev_class_get_alias(DeviceClass *dc)
55
{
56
    const char *typename = object_class_get_name(OBJECT_CLASS(dc));
57
    int i;
58

    
59
    for (i = 0; qdev_alias_table[i].typename; i++) {
60
        if (qdev_alias_table[i].arch_mask &&
61
            !(qdev_alias_table[i].arch_mask & arch_type)) {
62
            continue;
63
        }
64

    
65
        if (strcmp(qdev_alias_table[i].typename, typename) == 0) {
66
            return qdev_alias_table[i].alias;
67
        }
68
    }
69

    
70
    return NULL;
71
}
72

    
73
static bool qdev_class_has_alias(DeviceClass *dc)
74
{
75
    return (qdev_class_get_alias(dc) != NULL);
76
}
77

    
78
static void qdev_print_devinfo(DeviceClass *dc)
79
{
80
    error_printf("name \"%s\"", object_class_get_name(OBJECT_CLASS(dc)));
81
    if (dc->bus_type) {
82
        error_printf(", bus %s", dc->bus_type);
83
    }
84
    if (qdev_class_has_alias(dc)) {
85
        error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
86
    }
87
    if (dc->desc) {
88
        error_printf(", desc \"%s\"", dc->desc);
89
    }
90
    if (dc->no_user) {
91
        error_printf(", no-user");
92
    }
93
    error_printf("\n");
94
}
95

    
96
static gint devinfo_cmp(gconstpointer a, gconstpointer b)
97
{
98
    return strcasecmp(object_class_get_name((ObjectClass *)a),
99
                      object_class_get_name((ObjectClass *)b));
100
}
101

    
102
static void qdev_print_devinfos(bool show_no_user)
103
{
104
    static const char *cat_name[DEVICE_CATEGORY_MAX + 1] = {
105
        [DEVICE_CATEGORY_BRIDGE]  = "Controller/Bridge/Hub",
106
        [DEVICE_CATEGORY_USB]     = "USB",
107
        [DEVICE_CATEGORY_STORAGE] = "Storage",
108
        [DEVICE_CATEGORY_NETWORK] = "Network",
109
        [DEVICE_CATEGORY_INPUT]   = "Input",
110
        [DEVICE_CATEGORY_DISPLAY] = "Display",
111
        [DEVICE_CATEGORY_SOUND]   = "Sound",
112
        [DEVICE_CATEGORY_MISC]    = "Misc",
113
        [DEVICE_CATEGORY_MAX]     = "Uncategorized",
114
    };
115
    GSList *list, *elt;
116
    int i;
117
    bool cat_printed;
118

    
119
    list = g_slist_sort(object_class_get_list(TYPE_DEVICE, false),
120
                        devinfo_cmp);
121

    
122
    for (i = 0; i <= DEVICE_CATEGORY_MAX; i++) {
123
        cat_printed = false;
124
        for (elt = list; elt; elt = elt->next) {
125
            DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, elt->data,
126
                                                 TYPE_DEVICE);
127
            if ((i < DEVICE_CATEGORY_MAX
128
                 ? !test_bit(i, dc->categories)
129
                 : !bitmap_empty(dc->categories, DEVICE_CATEGORY_MAX))
130
                || (!show_no_user && dc->no_user)) {
131
                continue;
132
            }
133
            if (!cat_printed) {
134
                error_printf("%s%s devices:\n", i ? "\n" : "",
135
                             cat_name[i]);
136
                cat_printed = true;
137
            }
138
            qdev_print_devinfo(dc);
139
        }
140
    }
141

    
142
    g_slist_free(list);
143
}
144

    
145
static int set_property(const char *name, const char *value, void *opaque)
146
{
147
    DeviceState *dev = opaque;
148
    Error *err = NULL;
149

    
150
    if (strcmp(name, "driver") == 0)
151
        return 0;
152
    if (strcmp(name, "bus") == 0)
153
        return 0;
154

    
155
    qdev_prop_parse(dev, name, value, &err);
156
    if (err != NULL) {
157
        qerror_report_err(err);
158
        error_free(err);
159
        return -1;
160
    }
161
    return 0;
162
}
163

    
164
static const char *find_typename_by_alias(const char *alias)
165
{
166
    int i;
167

    
168
    for (i = 0; qdev_alias_table[i].alias; i++) {
169
        if (qdev_alias_table[i].arch_mask &&
170
            !(qdev_alias_table[i].arch_mask & arch_type)) {
171
            continue;
172
        }
173

    
174
        if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
175
            return qdev_alias_table[i].typename;
176
        }
177
    }
178

    
179
    return NULL;
180
}
181

    
182
int qdev_device_help(QemuOpts *opts)
183
{
184
    const char *driver;
185
    Property *prop;
186
    ObjectClass *klass;
187

    
188
    driver = qemu_opt_get(opts, "driver");
189
    if (driver && is_help_option(driver)) {
190
        qdev_print_devinfos(false);
191
        return 1;
192
    }
193

    
194
    if (!driver || !qemu_opt_has_help_opt(opts)) {
195
        return 0;
196
    }
197

    
198
    klass = object_class_by_name(driver);
199
    if (!klass) {
200
        const char *typename = find_typename_by_alias(driver);
201

    
202
        if (typename) {
203
            driver = typename;
204
            klass = object_class_by_name(driver);
205
        }
206
    }
207

    
208
    if (!klass) {
209
        return 0;
210
    }
211
    do {
212
        for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
213
            /*
214
             * TODO Properties without a parser are just for dirty hacks.
215
             * qdev_prop_ptr is the only such PropertyInfo.  It's marked
216
             * for removal.  This conditional should be removed along with
217
             * it.
218
             */
219
            if (!prop->info->set) {
220
                continue;           /* no way to set it, don't show */
221
            }
222
            error_printf("%s.%s=%s\n", driver, prop->name,
223
                         prop->info->legacy_name ?: prop->info->name);
224
        }
225
        klass = object_class_get_parent(klass);
226
    } while (klass != object_class_by_name(TYPE_DEVICE));
227
    return 1;
228
}
229

    
230
static Object *qdev_get_peripheral(void)
231
{
232
    static Object *dev;
233

    
234
    if (dev == NULL) {
235
        dev = container_get(qdev_get_machine(), "/peripheral");
236
    }
237

    
238
    return dev;
239
}
240

    
241
static Object *qdev_get_peripheral_anon(void)
242
{
243
    static Object *dev;
244

    
245
    if (dev == NULL) {
246
        dev = container_get(qdev_get_machine(), "/peripheral-anon");
247
    }
248

    
249
    return dev;
250
}
251

    
252
static void qbus_list_bus(DeviceState *dev)
253
{
254
    BusState *child;
255
    const char *sep = " ";
256

    
257
    error_printf("child busses at \"%s\":",
258
                 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
259
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
260
        error_printf("%s\"%s\"", sep, child->name);
261
        sep = ", ";
262
    }
263
    error_printf("\n");
264
}
265

    
266
static void qbus_list_dev(BusState *bus)
267
{
268
    BusChild *kid;
269
    const char *sep = " ";
270

    
271
    error_printf("devices at \"%s\":", bus->name);
272
    QTAILQ_FOREACH(kid, &bus->children, sibling) {
273
        DeviceState *dev = kid->child;
274
        error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
275
        if (dev->id)
276
            error_printf("/\"%s\"", dev->id);
277
        sep = ", ";
278
    }
279
    error_printf("\n");
280
}
281

    
282
static BusState *qbus_find_bus(DeviceState *dev, char *elem)
283
{
284
    BusState *child;
285

    
286
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
287
        if (strcmp(child->name, elem) == 0) {
288
            return child;
289
        }
290
    }
291
    return NULL;
292
}
293

    
294
static DeviceState *qbus_find_dev(BusState *bus, char *elem)
295
{
296
    BusChild *kid;
297

    
298
    /*
299
     * try to match in order:
300
     *   (1) instance id, if present
301
     *   (2) driver name
302
     *   (3) driver alias, if present
303
     */
304
    QTAILQ_FOREACH(kid, &bus->children, sibling) {
305
        DeviceState *dev = kid->child;
306
        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
307
            return dev;
308
        }
309
    }
310
    QTAILQ_FOREACH(kid, &bus->children, sibling) {
311
        DeviceState *dev = kid->child;
312
        if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
313
            return dev;
314
        }
315
    }
316
    QTAILQ_FOREACH(kid, &bus->children, sibling) {
317
        DeviceState *dev = kid->child;
318
        DeviceClass *dc = DEVICE_GET_CLASS(dev);
319

    
320
        if (qdev_class_has_alias(dc) &&
321
            strcmp(qdev_class_get_alias(dc), elem) == 0) {
322
            return dev;
323
        }
324
    }
325
    return NULL;
326
}
327

    
328
static BusState *qbus_find_recursive(BusState *bus, const char *name,
329
                                     const char *bus_typename)
330
{
331
    BusClass *bus_class = BUS_GET_CLASS(bus);
332
    BusChild *kid;
333
    BusState *child, *ret;
334
    int match = 1;
335

    
336
    if (name && (strcmp(bus->name, name) != 0)) {
337
        match = 0;
338
    } else if (bus_typename && !object_dynamic_cast(OBJECT(bus), bus_typename)) {
339
        match = 0;
340
    } else if ((bus_class->max_dev != 0) && (bus_class->max_dev <= bus->max_index)) {
341
        if (name != NULL) {
342
            /* bus was explicitly specified: return an error. */
343
            qerror_report(ERROR_CLASS_GENERIC_ERROR, "Bus '%s' is full",
344
                          bus->name);
345
            return NULL;
346
        } else {
347
            /* bus was not specified: try to find another one. */
348
            match = 0;
349
        }
350
    }
351
    if (match) {
352
        return bus;
353
    }
354

    
355
    QTAILQ_FOREACH(kid, &bus->children, sibling) {
356
        DeviceState *dev = kid->child;
357
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
358
            ret = qbus_find_recursive(child, name, bus_typename);
359
            if (ret) {
360
                return ret;
361
            }
362
        }
363
    }
364
    return NULL;
365
}
366

    
367
static BusState *qbus_find(const char *path)
368
{
369
    DeviceState *dev;
370
    BusState *bus;
371
    char elem[128];
372
    int pos, len;
373

    
374
    /* find start element */
375
    if (path[0] == '/') {
376
        bus = sysbus_get_default();
377
        pos = 0;
378
    } else {
379
        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
380
            assert(!path[0]);
381
            elem[0] = len = 0;
382
        }
383
        bus = qbus_find_recursive(sysbus_get_default(), elem, NULL);
384
        if (!bus) {
385
            qerror_report(QERR_BUS_NOT_FOUND, elem);
386
            return NULL;
387
        }
388
        pos = len;
389
    }
390

    
391
    for (;;) {
392
        assert(path[pos] == '/' || !path[pos]);
393
        while (path[pos] == '/') {
394
            pos++;
395
        }
396
        if (path[pos] == '\0') {
397
            return bus;
398
        }
399

    
400
        /* find device */
401
        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
402
            g_assert_not_reached();
403
            elem[0] = len = 0;
404
        }
405
        pos += len;
406
        dev = qbus_find_dev(bus, elem);
407
        if (!dev) {
408
            qerror_report(QERR_DEVICE_NOT_FOUND, elem);
409
            if (!monitor_cur_is_qmp()) {
410
                qbus_list_dev(bus);
411
            }
412
            return NULL;
413
        }
414

    
415
        assert(path[pos] == '/' || !path[pos]);
416
        while (path[pos] == '/') {
417
            pos++;
418
        }
419
        if (path[pos] == '\0') {
420
            /* last specified element is a device.  If it has exactly
421
             * one child bus accept it nevertheless */
422
            switch (dev->num_child_bus) {
423
            case 0:
424
                qerror_report(QERR_DEVICE_NO_BUS, elem);
425
                return NULL;
426
            case 1:
427
                return QLIST_FIRST(&dev->child_bus);
428
            default:
429
                qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
430
                if (!monitor_cur_is_qmp()) {
431
                    qbus_list_bus(dev);
432
                }
433
                return NULL;
434
            }
435
        }
436

    
437
        /* find bus */
438
        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
439
            g_assert_not_reached();
440
            elem[0] = len = 0;
441
        }
442
        pos += len;
443
        bus = qbus_find_bus(dev, elem);
444
        if (!bus) {
445
            qerror_report(QERR_BUS_NOT_FOUND, elem);
446
            if (!monitor_cur_is_qmp()) {
447
                qbus_list_bus(dev);
448
            }
449
            return NULL;
450
        }
451
    }
452
}
453

    
454
DeviceState *qdev_device_add(QemuOpts *opts)
455
{
456
    ObjectClass *oc;
457
    DeviceClass *dc;
458
    const char *driver, *path, *id;
459
    DeviceState *qdev;
460
    BusState *bus = NULL;
461

    
462
    driver = qemu_opt_get(opts, "driver");
463
    if (!driver) {
464
        qerror_report(QERR_MISSING_PARAMETER, "driver");
465
        return NULL;
466
    }
467

    
468
    /* find driver */
469
    oc = object_class_by_name(driver);
470
    if (!oc) {
471
        const char *typename = find_typename_by_alias(driver);
472

    
473
        if (typename) {
474
            driver = typename;
475
            oc = object_class_by_name(driver);
476
        }
477
    }
478

    
479
    if (!oc) {
480
        qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
481
        return NULL;
482
    }
483

    
484
    if (object_class_is_abstract(oc)) {
485
        qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver",
486
                      "non-abstract device type");
487
        return NULL;
488
    }
489

    
490
    dc = DEVICE_CLASS(oc);
491

    
492
    /* find bus */
493
    path = qemu_opt_get(opts, "bus");
494
    if (path != NULL) {
495
        bus = qbus_find(path);
496
        if (!bus) {
497
            return NULL;
498
        }
499
        if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) {
500
            qerror_report(QERR_BAD_BUS_FOR_DEVICE,
501
                          driver, object_get_typename(OBJECT(bus)));
502
            return NULL;
503
        }
504
    } else if (dc->bus_type != NULL) {
505
        bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type);
506
        if (!bus) {
507
            qerror_report(QERR_NO_BUS_FOR_DEVICE,
508
                          dc->bus_type, driver);
509
            return NULL;
510
        }
511
    }
512
    if (qdev_hotplug && bus && !bus->allow_hotplug) {
513
        qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
514
        return NULL;
515
    }
516

    
517
    /* create device, set properties */
518
    qdev = DEVICE(object_new(driver));
519

    
520
    if (bus) {
521
        qdev_set_parent_bus(qdev, bus);
522
    }
523

    
524
    id = qemu_opts_id(opts);
525
    if (id) {
526
        qdev->id = id;
527
    }
528
    if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
529
        qdev_free(qdev);
530
        return NULL;
531
    }
532
    if (qdev->id) {
533
        object_property_add_child(qdev_get_peripheral(), qdev->id,
534
                                  OBJECT(qdev), NULL);
535
    } else {
536
        static int anon_count;
537
        gchar *name = g_strdup_printf("device[%d]", anon_count++);
538
        object_property_add_child(qdev_get_peripheral_anon(), name,
539
                                  OBJECT(qdev), NULL);
540
        g_free(name);
541
    }        
542
    if (qdev_init(qdev) < 0) {
543
        qerror_report(QERR_DEVICE_INIT_FAILED, driver);
544
        return NULL;
545
    }
546
    qdev->opts = opts;
547
    return qdev;
548
}
549

    
550

    
551
#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
552
static void qbus_print(Monitor *mon, BusState *bus, int indent);
553

    
554
static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
555
                             int indent)
556
{
557
    if (!props)
558
        return;
559
    for (; props->name; props++) {
560
        Error *err = NULL;
561
        char *value;
562
        char *legacy_name = g_strdup_printf("legacy-%s", props->name);
563
        if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
564
            value = object_property_get_str(OBJECT(dev), legacy_name, &err);
565
        } else {
566
            value = object_property_print(OBJECT(dev), props->name, &err);
567
        }
568
        g_free(legacy_name);
569

    
570
        if (err) {
571
            error_free(err);
572
            continue;
573
        }
574
        qdev_printf("%s = %s\n", props->name,
575
                    value && *value ? value : "<null>");
576
        g_free(value);
577
    }
578
}
579

    
580
static void bus_print_dev(BusState *bus, Monitor *mon, DeviceState *dev, int indent)
581
{
582
    BusClass *bc = BUS_GET_CLASS(bus);
583

    
584
    if (bc->print_dev) {
585
        bc->print_dev(mon, dev, indent);
586
    }
587
}
588

    
589
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
590
{
591
    ObjectClass *class;
592
    BusState *child;
593
    qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
594
                dev->id ? dev->id : "");
595
    indent += 2;
596
    if (dev->num_gpio_in) {
597
        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
598
    }
599
    if (dev->num_gpio_out) {
600
        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
601
    }
602
    class = object_get_class(OBJECT(dev));
603
    do {
604
        qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent);
605
        class = object_class_get_parent(class);
606
    } while (class != object_class_by_name(TYPE_DEVICE));
607
    bus_print_dev(dev->parent_bus, mon, dev, indent);
608
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
609
        qbus_print(mon, child, indent);
610
    }
611
}
612

    
613
static void qbus_print(Monitor *mon, BusState *bus, int indent)
614
{
615
    BusChild *kid;
616

    
617
    qdev_printf("bus: %s\n", bus->name);
618
    indent += 2;
619
    qdev_printf("type %s\n", object_get_typename(OBJECT(bus)));
620
    QTAILQ_FOREACH(kid, &bus->children, sibling) {
621
        DeviceState *dev = kid->child;
622
        qdev_print(mon, dev, indent);
623
    }
624
}
625
#undef qdev_printf
626

    
627
void do_info_qtree(Monitor *mon, const QDict *qdict)
628
{
629
    if (sysbus_get_default())
630
        qbus_print(mon, sysbus_get_default(), 0);
631
}
632

    
633
void do_info_qdm(Monitor *mon, const QDict *qdict)
634
{
635
    qdev_print_devinfos(true);
636
}
637

    
638
int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
639
{
640
    Error *local_err = NULL;
641
    QemuOpts *opts;
642
    DeviceState *dev;
643

    
644
    opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err);
645
    if (error_is_set(&local_err)) {
646
        qerror_report_err(local_err);
647
        error_free(local_err);
648
        return -1;
649
    }
650
    if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
651
        qemu_opts_del(opts);
652
        return 0;
653
    }
654
    dev = qdev_device_add(opts);
655
    if (!dev) {
656
        qemu_opts_del(opts);
657
        return -1;
658
    }
659
    object_unref(OBJECT(dev));
660
    return 0;
661
}
662

    
663
void qmp_device_del(const char *id, Error **errp)
664
{
665
    DeviceState *dev;
666

    
667
    dev = qdev_find_recursive(sysbus_get_default(), id);
668
    if (NULL == dev) {
669
        error_set(errp, QERR_DEVICE_NOT_FOUND, id);
670
        return;
671
    }
672

    
673
    qdev_unplug(dev, errp);
674
}
675

    
676
void qdev_machine_init(void)
677
{
678
    qdev_get_peripheral_anon();
679
    qdev_get_peripheral();
680
}
681

    
682
QemuOptsList qemu_device_opts = {
683
    .name = "device",
684
    .implied_opt_name = "driver",
685
    .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
686
    .desc = {
687
        /*
688
         * no elements => accept any
689
         * sanity checking will happen later
690
         * when setting device properties
691
         */
692
        { /* end of list */ }
693
    },
694
};
695

    
696
QemuOptsList qemu_global_opts = {
697
    .name = "global",
698
    .head = QTAILQ_HEAD_INITIALIZER(qemu_global_opts.head),
699
    .desc = {
700
        {
701
            .name = "driver",
702
            .type = QEMU_OPT_STRING,
703
        },{
704
            .name = "property",
705
            .type = QEMU_OPT_STRING,
706
        },{
707
            .name = "value",
708
            .type = QEMU_OPT_STRING,
709
        },
710
        { /* end of list */ }
711
    },
712
};
713

    
714
int qemu_global_option(const char *str)
715
{
716
    char driver[64], property[64];
717
    QemuOpts *opts;
718
    int rc, offset;
719

    
720
    rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
721
    if (rc < 2 || str[offset] != '=') {
722
        error_report("can't parse: \"%s\"", str);
723
        return -1;
724
    }
725

    
726
    opts = qemu_opts_create_nofail(&qemu_global_opts);
727
    qemu_opt_set(opts, "driver", driver);
728
    qemu_opt_set(opts, "property", property);
729
    qemu_opt_set(opts, "value", str+offset+1);
730
    return 0;
731
}