qemu/qdev-monitor.c
<<
>>
Prefs
   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 */
  32typedef struct QDevAlias
  33{
  34    const char *typename;
  35    const char *alias;
  36    uint32_t arch_mask;
  37} QDevAlias;
  38
  39static 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
  54static 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
  73static bool qdev_class_has_alias(DeviceClass *dc)
  74{
  75    return (qdev_class_get_alias(dc) != NULL);
  76}
  77
  78static 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->cannot_instantiate_with_device_add_yet) {
  91        error_printf(", no-user");
  92    }
  93    error_printf("\n");
  94}
  95
  96static 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
 102static 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
 131                    && dc->cannot_instantiate_with_device_add_yet)) {
 132                continue;
 133            }
 134            if (!cat_printed) {
 135                error_printf("%s%s devices:\n", i ? "\n" : "",
 136                             cat_name[i]);
 137                cat_printed = true;
 138            }
 139            qdev_print_devinfo(dc);
 140        }
 141    }
 142
 143    g_slist_free(list);
 144}
 145
 146static int set_property(const char *name, const char *value, void *opaque)
 147{
 148    Object *obj = opaque;
 149    Error *err = NULL;
 150
 151    if (strcmp(name, "driver") == 0)
 152        return 0;
 153    if (strcmp(name, "bus") == 0)
 154        return 0;
 155
 156    object_property_parse(obj, value, name, &err);
 157    if (err != NULL) {
 158        qerror_report_err(err);
 159        error_free(err);
 160        return -1;
 161    }
 162    return 0;
 163}
 164
 165static const char *find_typename_by_alias(const char *alias)
 166{
 167    int i;
 168
 169    for (i = 0; qdev_alias_table[i].alias; i++) {
 170        if (qdev_alias_table[i].arch_mask &&
 171            !(qdev_alias_table[i].arch_mask & arch_type)) {
 172            continue;
 173        }
 174
 175        if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
 176            return qdev_alias_table[i].typename;
 177        }
 178    }
 179
 180    return NULL;
 181}
 182
 183static DeviceClass *qdev_get_device_class(const char **driver, Error **errp)
 184{
 185    ObjectClass *oc;
 186    DeviceClass *dc;
 187
 188    oc = object_class_by_name(*driver);
 189    if (!oc) {
 190        const char *typename = find_typename_by_alias(*driver);
 191
 192        if (typename) {
 193            *driver = typename;
 194            oc = object_class_by_name(*driver);
 195        }
 196    }
 197
 198    if (!object_class_dynamic_cast(oc, TYPE_DEVICE)) {
 199        error_setg(errp, "'%s' is not a valid device model name", *driver);
 200        return NULL;
 201    }
 202
 203    if (object_class_is_abstract(oc)) {
 204        error_set(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
 205                  "non-abstract device type");
 206        return NULL;
 207    }
 208
 209    dc = DEVICE_CLASS(oc);
 210    if (dc->cannot_instantiate_with_device_add_yet ||
 211        (qdev_hotplug && !dc->hotpluggable)) {
 212        error_set(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
 213                  "pluggable device type");
 214        return NULL;
 215    }
 216
 217    return dc;
 218}
 219
 220
 221int qdev_device_help(QemuOpts *opts)
 222{
 223    Error *local_err = NULL;
 224    const char *driver;
 225    DevicePropertyInfoList *prop_list;
 226    DevicePropertyInfoList *prop;
 227
 228    driver = qemu_opt_get(opts, "driver");
 229    if (driver && is_help_option(driver)) {
 230        qdev_print_devinfos(false);
 231        return 1;
 232    }
 233
 234    if (!driver || !qemu_opt_has_help_opt(opts)) {
 235        return 0;
 236    }
 237
 238    qdev_get_device_class(&driver, &local_err);
 239    if (local_err) {
 240        goto error;
 241    }
 242
 243    prop_list = qmp_device_list_properties(driver, &local_err);
 244    if (local_err) {
 245        goto error;
 246    }
 247
 248    for (prop = prop_list; prop; prop = prop->next) {
 249        error_printf("%s.%s=%s", driver,
 250                     prop->value->name,
 251                     prop->value->type);
 252        if (prop->value->has_description) {
 253            error_printf(" (%s)\n", prop->value->description);
 254        } else {
 255            error_printf("\n");
 256        }
 257    }
 258
 259    qapi_free_DevicePropertyInfoList(prop_list);
 260    return 1;
 261
 262error:
 263    error_printf("%s\n", error_get_pretty(local_err));
 264    error_free(local_err);
 265    return 1;
 266}
 267
 268static Object *qdev_get_peripheral(void)
 269{
 270    static Object *dev;
 271
 272    if (dev == NULL) {
 273        dev = container_get(qdev_get_machine(), "/peripheral");
 274    }
 275
 276    return dev;
 277}
 278
 279static Object *qdev_get_peripheral_anon(void)
 280{
 281    static Object *dev;
 282
 283    if (dev == NULL) {
 284        dev = container_get(qdev_get_machine(), "/peripheral-anon");
 285    }
 286
 287    return dev;
 288}
 289
 290static void qbus_list_bus(DeviceState *dev)
 291{
 292    BusState *child;
 293    const char *sep = " ";
 294
 295    error_printf("child busses at \"%s\":",
 296                 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
 297    QLIST_FOREACH(child, &dev->child_bus, sibling) {
 298        error_printf("%s\"%s\"", sep, child->name);
 299        sep = ", ";
 300    }
 301    error_printf("\n");
 302}
 303
 304static void qbus_list_dev(BusState *bus)
 305{
 306    BusChild *kid;
 307    const char *sep = " ";
 308
 309    error_printf("devices at \"%s\":", bus->name);
 310    QTAILQ_FOREACH(kid, &bus->children, sibling) {
 311        DeviceState *dev = kid->child;
 312        error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
 313        if (dev->id)
 314            error_printf("/\"%s\"", dev->id);
 315        sep = ", ";
 316    }
 317    error_printf("\n");
 318}
 319
 320static BusState *qbus_find_bus(DeviceState *dev, char *elem)
 321{
 322    BusState *child;
 323
 324    QLIST_FOREACH(child, &dev->child_bus, sibling) {
 325        if (strcmp(child->name, elem) == 0) {
 326            return child;
 327        }
 328    }
 329    return NULL;
 330}
 331
 332static DeviceState *qbus_find_dev(BusState *bus, char *elem)
 333{
 334    BusChild *kid;
 335
 336    /*
 337     * try to match in order:
 338     *   (1) instance id, if present
 339     *   (2) driver name
 340     *   (3) driver alias, if present
 341     */
 342    QTAILQ_FOREACH(kid, &bus->children, sibling) {
 343        DeviceState *dev = kid->child;
 344        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
 345            return dev;
 346        }
 347    }
 348    QTAILQ_FOREACH(kid, &bus->children, sibling) {
 349        DeviceState *dev = kid->child;
 350        if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
 351            return dev;
 352        }
 353    }
 354    QTAILQ_FOREACH(kid, &bus->children, sibling) {
 355        DeviceState *dev = kid->child;
 356        DeviceClass *dc = DEVICE_GET_CLASS(dev);
 357
 358        if (qdev_class_has_alias(dc) &&
 359            strcmp(qdev_class_get_alias(dc), elem) == 0) {
 360            return dev;
 361        }
 362    }
 363    return NULL;
 364}
 365
 366static BusState *qbus_find_recursive(BusState *bus, const char *name,
 367                                     const char *bus_typename)
 368{
 369    BusClass *bus_class = BUS_GET_CLASS(bus);
 370    BusChild *kid;
 371    BusState *child, *ret;
 372    int match = 1;
 373
 374    if (name && (strcmp(bus->name, name) != 0)) {
 375        match = 0;
 376    } else if (bus_typename && !object_dynamic_cast(OBJECT(bus), bus_typename)) {
 377        match = 0;
 378    } else if ((bus_class->max_dev != 0) && (bus_class->max_dev <= bus->max_index)) {
 379        if (name != NULL) {
 380            /* bus was explicitly specified: return an error. */
 381            qerror_report(ERROR_CLASS_GENERIC_ERROR, "Bus '%s' is full",
 382                          bus->name);
 383            return NULL;
 384        } else {
 385            /* bus was not specified: try to find another one. */
 386            match = 0;
 387        }
 388    }
 389    if (match) {
 390        return bus;
 391    }
 392
 393    QTAILQ_FOREACH(kid, &bus->children, sibling) {
 394        DeviceState *dev = kid->child;
 395        QLIST_FOREACH(child, &dev->child_bus, sibling) {
 396            ret = qbus_find_recursive(child, name, bus_typename);
 397            if (ret) {
 398                return ret;
 399            }
 400        }
 401    }
 402    return NULL;
 403}
 404
 405static BusState *qbus_find(const char *path)
 406{
 407    DeviceState *dev;
 408    BusState *bus;
 409    char elem[128];
 410    int pos, len;
 411
 412    /* find start element */
 413    if (path[0] == '/') {
 414        bus = sysbus_get_default();
 415        pos = 0;
 416    } else {
 417        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
 418            assert(!path[0]);
 419            elem[0] = len = 0;
 420        }
 421        bus = qbus_find_recursive(sysbus_get_default(), elem, NULL);
 422        if (!bus) {
 423            qerror_report(QERR_BUS_NOT_FOUND, elem);
 424            return NULL;
 425        }
 426        pos = len;
 427    }
 428
 429    for (;;) {
 430        assert(path[pos] == '/' || !path[pos]);
 431        while (path[pos] == '/') {
 432            pos++;
 433        }
 434        if (path[pos] == '\0') {
 435            return bus;
 436        }
 437
 438        /* find device */
 439        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
 440            g_assert_not_reached();
 441            elem[0] = len = 0;
 442        }
 443        pos += len;
 444        dev = qbus_find_dev(bus, elem);
 445        if (!dev) {
 446            qerror_report(QERR_DEVICE_NOT_FOUND, elem);
 447            if (!monitor_cur_is_qmp()) {
 448                qbus_list_dev(bus);
 449            }
 450            return NULL;
 451        }
 452
 453        assert(path[pos] == '/' || !path[pos]);
 454        while (path[pos] == '/') {
 455            pos++;
 456        }
 457        if (path[pos] == '\0') {
 458            /* last specified element is a device.  If it has exactly
 459             * one child bus accept it nevertheless */
 460            switch (dev->num_child_bus) {
 461            case 0:
 462                qerror_report(ERROR_CLASS_GENERIC_ERROR,
 463                              "Device '%s' has no child bus", elem);
 464                return NULL;
 465            case 1:
 466                return QLIST_FIRST(&dev->child_bus);
 467            default:
 468                qerror_report(ERROR_CLASS_GENERIC_ERROR,
 469                              "Device '%s' has multiple child busses", elem);
 470                if (!monitor_cur_is_qmp()) {
 471                    qbus_list_bus(dev);
 472                }
 473                return NULL;
 474            }
 475        }
 476
 477        /* find bus */
 478        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
 479            g_assert_not_reached();
 480            elem[0] = len = 0;
 481        }
 482        pos += len;
 483        bus = qbus_find_bus(dev, elem);
 484        if (!bus) {
 485            qerror_report(QERR_BUS_NOT_FOUND, elem);
 486            if (!monitor_cur_is_qmp()) {
 487                qbus_list_bus(dev);
 488            }
 489            return NULL;
 490        }
 491    }
 492}
 493
 494DeviceState *qdev_device_add(QemuOpts *opts)
 495{
 496    DeviceClass *dc;
 497    const char *driver, *path, *id;
 498    DeviceState *dev;
 499    BusState *bus = NULL;
 500    Error *err = NULL;
 501
 502    driver = qemu_opt_get(opts, "driver");
 503    if (!driver) {
 504        qerror_report(QERR_MISSING_PARAMETER, "driver");
 505        return NULL;
 506    }
 507
 508    /* find driver */
 509    dc = qdev_get_device_class(&driver, &err);
 510    if (err) {
 511        qerror_report_err(err);
 512        error_free(err);
 513        return NULL;
 514    }
 515
 516    /* find bus */
 517    path = qemu_opt_get(opts, "bus");
 518    if (path != NULL) {
 519        bus = qbus_find(path);
 520        if (!bus) {
 521            return NULL;
 522        }
 523        if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) {
 524            qerror_report(ERROR_CLASS_GENERIC_ERROR,
 525                          "Device '%s' can't go on a %s bus",
 526                          driver, object_get_typename(OBJECT(bus)));
 527            return NULL;
 528        }
 529    } else if (dc->bus_type != NULL) {
 530        bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type);
 531        if (!bus) {
 532            qerror_report(ERROR_CLASS_GENERIC_ERROR,
 533                          "No '%s' bus found for device '%s'",
 534                          dc->bus_type, driver);
 535            return NULL;
 536        }
 537    }
 538    if (qdev_hotplug && bus && !qbus_is_hotpluggable(bus)) {
 539        qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
 540        return NULL;
 541    }
 542
 543    /* create device */
 544    dev = DEVICE(object_new(driver));
 545
 546    if (bus) {
 547        qdev_set_parent_bus(dev, bus);
 548    }
 549
 550    id = qemu_opts_id(opts);
 551    if (id) {
 552        dev->id = id;
 553    }
 554
 555    if (dev->id) {
 556        object_property_add_child(qdev_get_peripheral(), dev->id,
 557                                  OBJECT(dev), NULL);
 558    } else {
 559        static int anon_count;
 560        gchar *name = g_strdup_printf("device[%d]", anon_count++);
 561        object_property_add_child(qdev_get_peripheral_anon(), name,
 562                                  OBJECT(dev), NULL);
 563        g_free(name);
 564    }
 565
 566    /* set properties */
 567    if (qemu_opt_foreach(opts, set_property, dev, 1) != 0) {
 568        object_unparent(OBJECT(dev));
 569        object_unref(OBJECT(dev));
 570        return NULL;
 571    }
 572
 573    dev->opts = opts;
 574    object_property_set_bool(OBJECT(dev), true, "realized", &err);
 575    if (err != NULL) {
 576        qerror_report_err(err);
 577        error_free(err);
 578        dev->opts = NULL;
 579        object_unparent(OBJECT(dev));
 580        object_unref(OBJECT(dev));
 581        qerror_report(QERR_DEVICE_INIT_FAILED, driver);
 582        return NULL;
 583    }
 584    return dev;
 585}
 586
 587
 588#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
 589static void qbus_print(Monitor *mon, BusState *bus, int indent);
 590
 591static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
 592                             int indent)
 593{
 594    if (!props)
 595        return;
 596    for (; props->name; props++) {
 597        Error *err = NULL;
 598        char *value;
 599        char *legacy_name = g_strdup_printf("legacy-%s", props->name);
 600        if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
 601            value = object_property_get_str(OBJECT(dev), legacy_name, &err);
 602        } else {
 603            value = object_property_print(OBJECT(dev), props->name, true, &err);
 604        }
 605        g_free(legacy_name);
 606
 607        if (err) {
 608            error_free(err);
 609            continue;
 610        }
 611        qdev_printf("%s = %s\n", props->name,
 612                    value && *value ? value : "<null>");
 613        g_free(value);
 614    }
 615}
 616
 617static void bus_print_dev(BusState *bus, Monitor *mon, DeviceState *dev, int indent)
 618{
 619    BusClass *bc = BUS_GET_CLASS(bus);
 620
 621    if (bc->print_dev) {
 622        bc->print_dev(mon, dev, indent);
 623    }
 624}
 625
 626static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
 627{
 628    ObjectClass *class;
 629    BusState *child;
 630    NamedGPIOList *ngl;
 631
 632    qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
 633                dev->id ? dev->id : "");
 634    indent += 2;
 635    QLIST_FOREACH(ngl, &dev->gpios, node) {
 636        if (ngl->num_in) {
 637            qdev_printf("gpio-in \"%s\" %d\n", ngl->name ? ngl->name : "",
 638                        ngl->num_in);
 639        }
 640        if (ngl->num_out) {
 641            qdev_printf("gpio-out \"%s\" %d\n", ngl->name ? ngl->name : "",
 642                        ngl->num_out);
 643        }
 644    }
 645    class = object_get_class(OBJECT(dev));
 646    do {
 647        qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent);
 648        class = object_class_get_parent(class);
 649    } while (class != object_class_by_name(TYPE_DEVICE));
 650    bus_print_dev(dev->parent_bus, mon, dev, indent);
 651    QLIST_FOREACH(child, &dev->child_bus, sibling) {
 652        qbus_print(mon, child, indent);
 653    }
 654}
 655
 656static void qbus_print(Monitor *mon, BusState *bus, int indent)
 657{
 658    BusChild *kid;
 659
 660    qdev_printf("bus: %s\n", bus->name);
 661    indent += 2;
 662    qdev_printf("type %s\n", object_get_typename(OBJECT(bus)));
 663    QTAILQ_FOREACH(kid, &bus->children, sibling) {
 664        DeviceState *dev = kid->child;
 665        qdev_print(mon, dev, indent);
 666    }
 667}
 668#undef qdev_printf
 669
 670void hmp_info_qtree(Monitor *mon, const QDict *qdict)
 671{
 672    if (sysbus_get_default())
 673        qbus_print(mon, sysbus_get_default(), 0);
 674}
 675
 676void hmp_info_qdm(Monitor *mon, const QDict *qdict)
 677{
 678    qdev_print_devinfos(true);
 679}
 680
 681typedef struct QOMCompositionState {
 682    Monitor *mon;
 683    int indent;
 684} QOMCompositionState;
 685
 686static void print_qom_composition(Monitor *mon, Object *obj, int indent);
 687
 688static int print_qom_composition_child(Object *obj, void *opaque)
 689{
 690    QOMCompositionState *s = opaque;
 691
 692    print_qom_composition(s->mon, obj, s->indent);
 693
 694    return 0;
 695}
 696
 697static void print_qom_composition(Monitor *mon, Object *obj, int indent)
 698{
 699    QOMCompositionState s = {
 700        .mon = mon,
 701        .indent = indent + 2,
 702    };
 703    char *name;
 704
 705    if (obj == object_get_root()) {
 706        name = g_strdup("");
 707    } else {
 708        name = object_get_canonical_path_component(obj);
 709    }
 710    monitor_printf(mon, "%*s/%s (%s)\n", indent, "", name,
 711                   object_get_typename(obj));
 712    g_free(name);
 713    object_child_foreach(obj, print_qom_composition_child, &s);
 714}
 715
 716void hmp_info_qom_tree(Monitor *mon, const QDict *dict)
 717{
 718    const char *path = qdict_get_try_str(dict, "path");
 719    Object *obj;
 720    bool ambiguous = false;
 721
 722    if (path) {
 723        obj = object_resolve_path(path, &ambiguous);
 724        if (!obj) {
 725            monitor_printf(mon, "Path '%s' could not be resolved.\n", path);
 726            return;
 727        }
 728        if (ambiguous) {
 729            monitor_printf(mon, "Warning: Path '%s' is ambiguous.\n", path);
 730            return;
 731        }
 732    } else {
 733        obj = qdev_get_machine();
 734    }
 735    print_qom_composition(mon, obj, 0);
 736}
 737
 738int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
 739{
 740    Error *local_err = NULL;
 741    QemuOpts *opts;
 742    DeviceState *dev;
 743
 744    opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err);
 745    if (local_err) {
 746        qerror_report_err(local_err);
 747        error_free(local_err);
 748        return -1;
 749    }
 750    if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
 751        qemu_opts_del(opts);
 752        return 0;
 753    }
 754    dev = qdev_device_add(opts);
 755    if (!dev) {
 756        qemu_opts_del(opts);
 757        return -1;
 758    }
 759    object_unref(OBJECT(dev));
 760    return 0;
 761}
 762
 763void qmp_device_del(const char *id, Error **errp)
 764{
 765    Object *obj;
 766    char *root_path = object_get_canonical_path(qdev_get_peripheral());
 767    char *path = g_strdup_printf("%s/%s", root_path, id);
 768
 769    g_free(root_path);
 770    obj = object_resolve_path_type(path, TYPE_DEVICE, NULL);
 771    g_free(path);
 772
 773    if (!obj) {
 774        error_set(errp, QERR_DEVICE_NOT_FOUND, id);
 775        return;
 776    }
 777
 778    qdev_unplug(DEVICE(obj), errp);
 779}
 780
 781void qdev_machine_init(void)
 782{
 783    qdev_get_peripheral_anon();
 784    qdev_get_peripheral();
 785}
 786
 787QemuOptsList qemu_device_opts = {
 788    .name = "device",
 789    .implied_opt_name = "driver",
 790    .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
 791    .desc = {
 792        /*
 793         * no elements => accept any
 794         * sanity checking will happen later
 795         * when setting device properties
 796         */
 797        { /* end of list */ }
 798    },
 799};
 800
 801QemuOptsList qemu_global_opts = {
 802    .name = "global",
 803    .head = QTAILQ_HEAD_INITIALIZER(qemu_global_opts.head),
 804    .desc = {
 805        {
 806            .name = "driver",
 807            .type = QEMU_OPT_STRING,
 808        },{
 809            .name = "property",
 810            .type = QEMU_OPT_STRING,
 811        },{
 812            .name = "value",
 813            .type = QEMU_OPT_STRING,
 814        },
 815        { /* end of list */ }
 816    },
 817};
 818
 819int qemu_global_option(const char *str)
 820{
 821    char driver[64], property[64];
 822    QemuOpts *opts;
 823    int rc, offset;
 824
 825    rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
 826    if (rc < 2 || str[offset] != '=') {
 827        error_report("can't parse: \"%s\"", str);
 828        return -1;
 829    }
 830
 831    opts = qemu_opts_create(&qemu_global_opts, NULL, 0, &error_abort);
 832    qemu_opt_set(opts, "driver", driver, &error_abort);
 833    qemu_opt_set(opts, "property", property, &error_abort);
 834    qemu_opt_set(opts, "value", str + offset + 1, &error_abort);
 835    return 0;
 836}
 837