qemu/qom/object.c
<<
>>
Prefs
   1/*
   2 * QEMU Object Model
   3 *
   4 * Copyright IBM, Corp. 2011
   5 *
   6 * Authors:
   7 *  Anthony Liguori   <aliguori@us.ibm.com>
   8 *
   9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
  10 * See the COPYING file in the top-level directory.
  11 */
  12
  13#include "qemu/osdep.h"
  14#include "hw/qdev-core.h"
  15#include "qapi/error.h"
  16#include "qom/object.h"
  17#include "qom/object_interfaces.h"
  18#include "qemu/cutils.h"
  19#include "qapi/visitor.h"
  20#include "qapi/string-input-visitor.h"
  21#include "qapi/string-output-visitor.h"
  22#include "qapi/qapi-builtin-visit.h"
  23#include "qapi/qmp/qerror.h"
  24#include "trace.h"
  25
  26/* TODO: replace QObject with a simpler visitor to avoid a dependency
  27 * of the QOM core on QObject?  */
  28#include "qom/qom-qobject.h"
  29#include "qapi/qmp/qbool.h"
  30#include "qapi/qmp/qnum.h"
  31#include "qapi/qmp/qstring.h"
  32#include "qemu/error-report.h"
  33
  34#define MAX_INTERFACES 32
  35
  36typedef struct InterfaceImpl InterfaceImpl;
  37typedef struct TypeImpl TypeImpl;
  38
  39struct InterfaceImpl
  40{
  41    const char *typename;
  42};
  43
  44struct TypeImpl
  45{
  46    const char *name;
  47
  48    size_t class_size;
  49
  50    size_t instance_size;
  51
  52    void (*class_init)(ObjectClass *klass, void *data);
  53    void (*class_base_init)(ObjectClass *klass, void *data);
  54
  55    void *class_data;
  56
  57    void (*instance_init)(Object *obj);
  58    void (*instance_post_init)(Object *obj);
  59    void (*instance_finalize)(Object *obj);
  60
  61    bool abstract;
  62
  63    const char *parent;
  64    TypeImpl *parent_type;
  65
  66    ObjectClass *class;
  67
  68    int num_interfaces;
  69    InterfaceImpl interfaces[MAX_INTERFACES];
  70};
  71
  72static Type type_interface;
  73
  74static GHashTable *type_table_get(void)
  75{
  76    static GHashTable *type_table;
  77
  78    if (type_table == NULL) {
  79        type_table = g_hash_table_new(g_str_hash, g_str_equal);
  80    }
  81
  82    return type_table;
  83}
  84
  85static bool enumerating_types;
  86
  87static void type_table_add(TypeImpl *ti)
  88{
  89    assert(!enumerating_types);
  90    g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
  91}
  92
  93static TypeImpl *type_table_lookup(const char *name)
  94{
  95    return g_hash_table_lookup(type_table_get(), name);
  96}
  97
  98static TypeImpl *type_new(const TypeInfo *info)
  99{
 100    TypeImpl *ti = g_malloc0(sizeof(*ti));
 101    int i;
 102
 103    g_assert(info->name != NULL);
 104
 105    if (type_table_lookup(info->name) != NULL) {
 106        fprintf(stderr, "Registering `%s' which already exists\n", info->name);
 107        abort();
 108    }
 109
 110    ti->name = g_strdup(info->name);
 111    ti->parent = g_strdup(info->parent);
 112
 113    ti->class_size = info->class_size;
 114    ti->instance_size = info->instance_size;
 115
 116    ti->class_init = info->class_init;
 117    ti->class_base_init = info->class_base_init;
 118    ti->class_data = info->class_data;
 119
 120    ti->instance_init = info->instance_init;
 121    ti->instance_post_init = info->instance_post_init;
 122    ti->instance_finalize = info->instance_finalize;
 123
 124    ti->abstract = info->abstract;
 125
 126    for (i = 0; info->interfaces && info->interfaces[i].type; i++) {
 127        ti->interfaces[i].typename = g_strdup(info->interfaces[i].type);
 128    }
 129    ti->num_interfaces = i;
 130
 131    return ti;
 132}
 133
 134static TypeImpl *type_register_internal(const TypeInfo *info)
 135{
 136    TypeImpl *ti;
 137    ti = type_new(info);
 138
 139    type_table_add(ti);
 140    return ti;
 141}
 142
 143TypeImpl *type_register(const TypeInfo *info)
 144{
 145    assert(info->parent);
 146    return type_register_internal(info);
 147}
 148
 149TypeImpl *type_register_static(const TypeInfo *info)
 150{
 151    return type_register(info);
 152}
 153
 154void type_register_static_array(const TypeInfo *infos, int nr_infos)
 155{
 156    int i;
 157
 158    for (i = 0; i < nr_infos; i++) {
 159        type_register_static(&infos[i]);
 160    }
 161}
 162
 163static TypeImpl *type_get_by_name(const char *name)
 164{
 165    if (name == NULL) {
 166        return NULL;
 167    }
 168
 169    return type_table_lookup(name);
 170}
 171
 172static TypeImpl *type_get_parent(TypeImpl *type)
 173{
 174    if (!type->parent_type && type->parent) {
 175        type->parent_type = type_get_by_name(type->parent);
 176        g_assert(type->parent_type != NULL);
 177    }
 178
 179    return type->parent_type;
 180}
 181
 182static bool type_has_parent(TypeImpl *type)
 183{
 184    return (type->parent != NULL);
 185}
 186
 187static size_t type_class_get_size(TypeImpl *ti)
 188{
 189    if (ti->class_size) {
 190        return ti->class_size;
 191    }
 192
 193    if (type_has_parent(ti)) {
 194        return type_class_get_size(type_get_parent(ti));
 195    }
 196
 197    return sizeof(ObjectClass);
 198}
 199
 200static size_t type_object_get_size(TypeImpl *ti)
 201{
 202    if (ti->instance_size) {
 203        return ti->instance_size;
 204    }
 205
 206    if (type_has_parent(ti)) {
 207        return type_object_get_size(type_get_parent(ti));
 208    }
 209
 210    return 0;
 211}
 212
 213size_t object_type_get_instance_size(const char *typename)
 214{
 215    TypeImpl *type = type_get_by_name(typename);
 216
 217    g_assert(type != NULL);
 218    return type_object_get_size(type);
 219}
 220
 221static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
 222{
 223    assert(target_type);
 224
 225    /* Check if target_type is a direct ancestor of type */
 226    while (type) {
 227        if (type == target_type) {
 228            return true;
 229        }
 230
 231        type = type_get_parent(type);
 232    }
 233
 234    return false;
 235}
 236
 237static void type_initialize(TypeImpl *ti);
 238
 239static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type,
 240                                      TypeImpl *parent_type)
 241{
 242    InterfaceClass *new_iface;
 243    TypeInfo info = { };
 244    TypeImpl *iface_impl;
 245
 246    info.parent = parent_type->name;
 247    info.name = g_strdup_printf("%s::%s", ti->name, interface_type->name);
 248    info.abstract = true;
 249
 250    iface_impl = type_new(&info);
 251    iface_impl->parent_type = parent_type;
 252    type_initialize(iface_impl);
 253    g_free((char *)info.name);
 254
 255    new_iface = (InterfaceClass *)iface_impl->class;
 256    new_iface->concrete_class = ti->class;
 257    new_iface->interface_type = interface_type;
 258
 259    ti->class->interfaces = g_slist_append(ti->class->interfaces,
 260                                           iface_impl->class);
 261}
 262
 263static void object_property_free(gpointer data)
 264{
 265    ObjectProperty *prop = data;
 266
 267    g_free(prop->name);
 268    g_free(prop->type);
 269    g_free(prop->description);
 270    g_free(prop);
 271}
 272
 273static void type_initialize(TypeImpl *ti)
 274{
 275    TypeImpl *parent;
 276
 277    if (ti->class) {
 278        return;
 279    }
 280
 281    ti->class_size = type_class_get_size(ti);
 282    ti->instance_size = type_object_get_size(ti);
 283    /* Any type with zero instance_size is implicitly abstract.
 284     * This means interface types are all abstract.
 285     */
 286    if (ti->instance_size == 0) {
 287        ti->abstract = true;
 288    }
 289    if (type_is_ancestor(ti, type_interface)) {
 290        assert(ti->instance_size == 0);
 291        assert(ti->abstract);
 292        assert(!ti->instance_init);
 293        assert(!ti->instance_post_init);
 294        assert(!ti->instance_finalize);
 295        assert(!ti->num_interfaces);
 296    }
 297    ti->class = g_malloc0(ti->class_size);
 298
 299    parent = type_get_parent(ti);
 300    if (parent) {
 301        type_initialize(parent);
 302        GSList *e;
 303        int i;
 304
 305        g_assert(parent->class_size <= ti->class_size);
 306        memcpy(ti->class, parent->class, parent->class_size);
 307        ti->class->interfaces = NULL;
 308        ti->class->properties = g_hash_table_new_full(
 309            g_str_hash, g_str_equal, g_free, object_property_free);
 310
 311        for (e = parent->class->interfaces; e; e = e->next) {
 312            InterfaceClass *iface = e->data;
 313            ObjectClass *klass = OBJECT_CLASS(iface);
 314
 315            type_initialize_interface(ti, iface->interface_type, klass->type);
 316        }
 317
 318        for (i = 0; i < ti->num_interfaces; i++) {
 319            TypeImpl *t = type_get_by_name(ti->interfaces[i].typename);
 320            for (e = ti->class->interfaces; e; e = e->next) {
 321                TypeImpl *target_type = OBJECT_CLASS(e->data)->type;
 322
 323                if (type_is_ancestor(target_type, t)) {
 324                    break;
 325                }
 326            }
 327
 328            if (e) {
 329                continue;
 330            }
 331
 332            type_initialize_interface(ti, t, t);
 333        }
 334    } else {
 335        ti->class->properties = g_hash_table_new_full(
 336            g_str_hash, g_str_equal, g_free, object_property_free);
 337    }
 338
 339    ti->class->type = ti;
 340
 341    while (parent) {
 342        if (parent->class_base_init) {
 343            parent->class_base_init(ti->class, ti->class_data);
 344        }
 345        parent = type_get_parent(parent);
 346    }
 347
 348    if (ti->class_init) {
 349        ti->class_init(ti->class, ti->class_data);
 350    }
 351}
 352
 353static void object_init_with_type(Object *obj, TypeImpl *ti)
 354{
 355    if (type_has_parent(ti)) {
 356        object_init_with_type(obj, type_get_parent(ti));
 357    }
 358
 359    if (ti->instance_init) {
 360        ti->instance_init(obj);
 361    }
 362}
 363
 364static void object_post_init_with_type(Object *obj, TypeImpl *ti)
 365{
 366    if (ti->instance_post_init) {
 367        ti->instance_post_init(obj);
 368    }
 369
 370    if (type_has_parent(ti)) {
 371        object_post_init_with_type(obj, type_get_parent(ti));
 372    }
 373}
 374
 375void object_apply_global_props(Object *obj, const GPtrArray *props, Error **errp)
 376{
 377    int i;
 378
 379    if (!props) {
 380        return;
 381    }
 382
 383    for (i = 0; i < props->len; i++) {
 384        GlobalProperty *p = g_ptr_array_index(props, i);
 385        Error *err = NULL;
 386
 387        if (object_dynamic_cast(obj, p->driver) == NULL) {
 388            continue;
 389        }
 390        if (p->optional && !object_property_find(obj, p->property, NULL)) {
 391            continue;
 392        }
 393        p->used = true;
 394        object_property_parse(obj, p->value, p->property, &err);
 395        if (err != NULL) {
 396            error_prepend(&err, "can't apply global %s.%s=%s: ",
 397                          p->driver, p->property, p->value);
 398            /*
 399             * If errp != NULL, propagate error and return.
 400             * If errp == NULL, report a warning, but keep going
 401             * with the remaining globals.
 402             */
 403            if (errp) {
 404                error_propagate(errp, err);
 405                return;
 406            } else {
 407                warn_report_err(err);
 408            }
 409        }
 410    }
 411}
 412
 413/*
 414 * Global property defaults
 415 * Slot 0: accelerator's global property defaults
 416 * Slot 1: machine's global property defaults
 417 * Each is a GPtrArray of of GlobalProperty.
 418 * Applied in order, later entries override earlier ones.
 419 */
 420static GPtrArray *object_compat_props[2];
 421
 422/*
 423 * Set machine's global property defaults to @compat_props.
 424 * May be called at most once.
 425 */
 426void object_set_machine_compat_props(GPtrArray *compat_props)
 427{
 428    assert(!object_compat_props[1]);
 429    object_compat_props[1] = compat_props;
 430}
 431
 432/*
 433 * Set accelerator's global property defaults to @compat_props.
 434 * May be called at most once.
 435 */
 436void object_set_accelerator_compat_props(GPtrArray *compat_props)
 437{
 438    assert(!object_compat_props[0]);
 439    object_compat_props[0] = compat_props;
 440}
 441
 442void object_apply_compat_props(Object *obj)
 443{
 444    int i;
 445
 446    for (i = 0; i < ARRAY_SIZE(object_compat_props); i++) {
 447        object_apply_global_props(obj, object_compat_props[i],
 448                                  &error_abort);
 449    }
 450}
 451
 452static void object_initialize_with_type(void *data, size_t size, TypeImpl *type)
 453{
 454    Object *obj = data;
 455
 456    type_initialize(type);
 457
 458    g_assert(type->instance_size >= sizeof(Object));
 459    g_assert(type->abstract == false);
 460    g_assert(size >= type->instance_size);
 461
 462    memset(obj, 0, type->instance_size);
 463    obj->class = type->class;
 464    object_ref(obj);
 465    obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal,
 466                                            NULL, object_property_free);
 467    object_init_with_type(obj, type);
 468    object_post_init_with_type(obj, type);
 469}
 470
 471void object_initialize(void *data, size_t size, const char *typename)
 472{
 473    TypeImpl *type = type_get_by_name(typename);
 474
 475    if (!type) {
 476        error_report("missing object type '%s'", typename);
 477        abort();
 478    }
 479
 480    object_initialize_with_type(data, size, type);
 481}
 482
 483void object_initialize_child(Object *parentobj, const char *propname,
 484                             void *childobj, size_t size, const char *type,
 485                             Error **errp, ...)
 486{
 487    va_list vargs;
 488
 489    va_start(vargs, errp);
 490    object_initialize_childv(parentobj, propname, childobj, size, type, errp,
 491                             vargs);
 492    va_end(vargs);
 493}
 494
 495void object_initialize_childv(Object *parentobj, const char *propname,
 496                              void *childobj, size_t size, const char *type,
 497                              Error **errp, va_list vargs)
 498{
 499    Error *local_err = NULL;
 500    Object *obj;
 501    UserCreatable *uc;
 502
 503    object_initialize(childobj, size, type);
 504    obj = OBJECT(childobj);
 505
 506    object_set_propv(obj, &local_err, vargs);
 507    if (local_err) {
 508        goto out;
 509    }
 510
 511    object_property_add_child(parentobj, propname, obj, &local_err);
 512    if (local_err) {
 513        goto out;
 514    }
 515
 516    uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
 517    if (uc) {
 518        user_creatable_complete(uc, &local_err);
 519        if (local_err) {
 520            object_unparent(obj);
 521            goto out;
 522        }
 523    }
 524
 525    /*
 526     * Since object_property_add_child added a reference to the child object,
 527     * we can drop the reference added by object_initialize(), so the child
 528     * property will own the only reference to the object.
 529     */
 530    object_unref(obj);
 531
 532out:
 533    if (local_err) {
 534        error_propagate(errp, local_err);
 535        object_unref(obj);
 536    }
 537}
 538
 539static inline bool object_property_is_child(ObjectProperty *prop)
 540{
 541    return strstart(prop->type, "child<", NULL);
 542}
 543
 544static void object_property_del_all(Object *obj)
 545{
 546    ObjectProperty *prop;
 547    GHashTableIter iter;
 548    gpointer key, value;
 549    bool released;
 550
 551    do {
 552        released = false;
 553        g_hash_table_iter_init(&iter, obj->properties);
 554        while (g_hash_table_iter_next(&iter, &key, &value)) {
 555            prop = value;
 556            if (prop->release) {
 557                prop->release(obj, prop->name, prop->opaque);
 558                prop->release = NULL;
 559                released = true;
 560                break;
 561            }
 562            g_hash_table_iter_remove(&iter);
 563        }
 564    } while (released);
 565
 566    g_hash_table_unref(obj->properties);
 567}
 568
 569static void object_property_del_child(Object *obj, Object *child, Error **errp)
 570{
 571    ObjectProperty *prop;
 572    GHashTableIter iter;
 573    gpointer key, value;
 574
 575    g_hash_table_iter_init(&iter, obj->properties);
 576    while (g_hash_table_iter_next(&iter, &key, &value)) {
 577        prop = value;
 578        if (object_property_is_child(prop) && prop->opaque == child) {
 579            if (prop->release) {
 580                prop->release(obj, prop->name, prop->opaque);
 581                prop->release = NULL;
 582            }
 583            break;
 584        }
 585    }
 586    g_hash_table_iter_init(&iter, obj->properties);
 587    while (g_hash_table_iter_next(&iter, &key, &value)) {
 588        prop = value;
 589        if (object_property_is_child(prop) && prop->opaque == child) {
 590            g_hash_table_iter_remove(&iter);
 591            break;
 592        }
 593    }
 594}
 595
 596void object_unparent(Object *obj)
 597{
 598    if (obj->parent) {
 599        object_property_del_child(obj->parent, obj, NULL);
 600    }
 601}
 602
 603static void object_deinit(Object *obj, TypeImpl *type)
 604{
 605    if (type->instance_finalize) {
 606        type->instance_finalize(obj);
 607    }
 608
 609    if (type_has_parent(type)) {
 610        object_deinit(obj, type_get_parent(type));
 611    }
 612}
 613
 614static void object_finalize(void *data)
 615{
 616    Object *obj = data;
 617    TypeImpl *ti = obj->class->type;
 618
 619    object_property_del_all(obj);
 620    object_deinit(obj, ti);
 621
 622    g_assert(obj->ref == 0);
 623    if (obj->free) {
 624        obj->free(obj);
 625    }
 626}
 627
 628static Object *object_new_with_type(Type type)
 629{
 630    Object *obj;
 631
 632    g_assert(type != NULL);
 633    type_initialize(type);
 634
 635    obj = g_malloc(type->instance_size);
 636    object_initialize_with_type(obj, type->instance_size, type);
 637    obj->free = g_free;
 638
 639    return obj;
 640}
 641
 642Object *object_new(const char *typename)
 643{
 644    TypeImpl *ti = type_get_by_name(typename);
 645
 646    return object_new_with_type(ti);
 647}
 648
 649
 650Object *object_new_with_props(const char *typename,
 651                              Object *parent,
 652                              const char *id,
 653                              Error **errp,
 654                              ...)
 655{
 656    va_list vargs;
 657    Object *obj;
 658
 659    va_start(vargs, errp);
 660    obj = object_new_with_propv(typename, parent, id, errp, vargs);
 661    va_end(vargs);
 662
 663    return obj;
 664}
 665
 666
 667Object *object_new_with_propv(const char *typename,
 668                              Object *parent,
 669                              const char *id,
 670                              Error **errp,
 671                              va_list vargs)
 672{
 673    Object *obj;
 674    ObjectClass *klass;
 675    Error *local_err = NULL;
 676    UserCreatable *uc;
 677
 678    klass = object_class_by_name(typename);
 679    if (!klass) {
 680        error_setg(errp, "invalid object type: %s", typename);
 681        return NULL;
 682    }
 683
 684    if (object_class_is_abstract(klass)) {
 685        error_setg(errp, "object type '%s' is abstract", typename);
 686        return NULL;
 687    }
 688    obj = object_new_with_type(klass->type);
 689
 690    if (object_set_propv(obj, &local_err, vargs) < 0) {
 691        goto error;
 692    }
 693
 694    if (id != NULL) {
 695        object_property_add_child(parent, id, obj, &local_err);
 696        if (local_err) {
 697            goto error;
 698        }
 699    }
 700
 701    uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
 702    if (uc) {
 703        user_creatable_complete(uc, &local_err);
 704        if (local_err) {
 705            if (id != NULL) {
 706                object_unparent(obj);
 707            }
 708            goto error;
 709        }
 710    }
 711
 712    object_unref(OBJECT(obj));
 713    return obj;
 714
 715 error:
 716    error_propagate(errp, local_err);
 717    object_unref(obj);
 718    return NULL;
 719}
 720
 721
 722int object_set_props(Object *obj,
 723                     Error **errp,
 724                     ...)
 725{
 726    va_list vargs;
 727    int ret;
 728
 729    va_start(vargs, errp);
 730    ret = object_set_propv(obj, errp, vargs);
 731    va_end(vargs);
 732
 733    return ret;
 734}
 735
 736
 737int object_set_propv(Object *obj,
 738                     Error **errp,
 739                     va_list vargs)
 740{
 741    const char *propname;
 742    Error *local_err = NULL;
 743
 744    propname = va_arg(vargs, char *);
 745    while (propname != NULL) {
 746        const char *value = va_arg(vargs, char *);
 747
 748        g_assert(value != NULL);
 749        object_property_parse(obj, value, propname, &local_err);
 750        if (local_err) {
 751            error_propagate(errp, local_err);
 752            return -1;
 753        }
 754        propname = va_arg(vargs, char *);
 755    }
 756
 757    return 0;
 758}
 759
 760
 761Object *object_dynamic_cast(Object *obj, const char *typename)
 762{
 763    if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
 764        return obj;
 765    }
 766
 767    return NULL;
 768}
 769
 770Object *object_dynamic_cast_assert(Object *obj, const char *typename,
 771                                   const char *file, int line, const char *func)
 772{
 773    trace_object_dynamic_cast_assert(obj ? obj->class->type->name : "(null)",
 774                                     typename, file, line, func);
 775
 776#ifdef CONFIG_QOM_CAST_DEBUG
 777    int i;
 778    Object *inst;
 779
 780    for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) {
 781        if (atomic_read(&obj->class->object_cast_cache[i]) == typename) {
 782            goto out;
 783        }
 784    }
 785
 786    inst = object_dynamic_cast(obj, typename);
 787
 788    if (!inst && obj) {
 789        fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
 790                file, line, func, obj, typename);
 791        abort();
 792    }
 793
 794    assert(obj == inst);
 795
 796    if (obj && obj == inst) {
 797        for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
 798            atomic_set(&obj->class->object_cast_cache[i - 1],
 799                       atomic_read(&obj->class->object_cast_cache[i]));
 800        }
 801        atomic_set(&obj->class->object_cast_cache[i - 1], typename);
 802    }
 803
 804out:
 805#endif
 806    return obj;
 807}
 808
 809ObjectClass *object_class_dynamic_cast(ObjectClass *class,
 810                                       const char *typename)
 811{
 812    ObjectClass *ret = NULL;
 813    TypeImpl *target_type;
 814    TypeImpl *type;
 815
 816    if (!class) {
 817        return NULL;
 818    }
 819
 820    /* A simple fast path that can trigger a lot for leaf classes.  */
 821    type = class->type;
 822    if (type->name == typename) {
 823        return class;
 824    }
 825
 826    target_type = type_get_by_name(typename);
 827    if (!target_type) {
 828        /* target class type unknown, so fail the cast */
 829        return NULL;
 830    }
 831
 832    if (type->class->interfaces &&
 833            type_is_ancestor(target_type, type_interface)) {
 834        int found = 0;
 835        GSList *i;
 836
 837        for (i = class->interfaces; i; i = i->next) {
 838            ObjectClass *target_class = i->data;
 839
 840            if (type_is_ancestor(target_class->type, target_type)) {
 841                ret = target_class;
 842                found++;
 843            }
 844         }
 845
 846        /* The match was ambiguous, don't allow a cast */
 847        if (found > 1) {
 848            ret = NULL;
 849        }
 850    } else if (type_is_ancestor(type, target_type)) {
 851        ret = class;
 852    }
 853
 854    return ret;
 855}
 856
 857ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
 858                                              const char *typename,
 859                                              const char *file, int line,
 860                                              const char *func)
 861{
 862    ObjectClass *ret;
 863
 864    trace_object_class_dynamic_cast_assert(class ? class->type->name : "(null)",
 865                                           typename, file, line, func);
 866
 867#ifdef CONFIG_QOM_CAST_DEBUG
 868    int i;
 869
 870    for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) {
 871        if (atomic_read(&class->class_cast_cache[i]) == typename) {
 872            ret = class;
 873            goto out;
 874        }
 875    }
 876#else
 877    if (!class || !class->interfaces) {
 878        return class;
 879    }
 880#endif
 881
 882    ret = object_class_dynamic_cast(class, typename);
 883    if (!ret && class) {
 884        fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
 885                file, line, func, class, typename);
 886        abort();
 887    }
 888
 889#ifdef CONFIG_QOM_CAST_DEBUG
 890    if (class && ret == class) {
 891        for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
 892            atomic_set(&class->class_cast_cache[i - 1],
 893                       atomic_read(&class->class_cast_cache[i]));
 894        }
 895        atomic_set(&class->class_cast_cache[i - 1], typename);
 896    }
 897out:
 898#endif
 899    return ret;
 900}
 901
 902const char *object_get_typename(const Object *obj)
 903{
 904    return obj->class->type->name;
 905}
 906
 907ObjectClass *object_get_class(Object *obj)
 908{
 909    return obj->class;
 910}
 911
 912bool object_class_is_abstract(ObjectClass *klass)
 913{
 914    return klass->type->abstract;
 915}
 916
 917const char *object_class_get_name(ObjectClass *klass)
 918{
 919    return klass->type->name;
 920}
 921
 922ObjectClass *object_class_by_name(const char *typename)
 923{
 924    TypeImpl *type = type_get_by_name(typename);
 925
 926    if (!type) {
 927        return NULL;
 928    }
 929
 930    type_initialize(type);
 931
 932    return type->class;
 933}
 934
 935ObjectClass *object_class_get_parent(ObjectClass *class)
 936{
 937    TypeImpl *type = type_get_parent(class->type);
 938
 939    if (!type) {
 940        return NULL;
 941    }
 942
 943    type_initialize(type);
 944
 945    return type->class;
 946}
 947
 948typedef struct OCFData
 949{
 950    void (*fn)(ObjectClass *klass, void *opaque);
 951    const char *implements_type;
 952    bool include_abstract;
 953    void *opaque;
 954} OCFData;
 955
 956static void object_class_foreach_tramp(gpointer key, gpointer value,
 957                                       gpointer opaque)
 958{
 959    OCFData *data = opaque;
 960    TypeImpl *type = value;
 961    ObjectClass *k;
 962
 963    type_initialize(type);
 964    k = type->class;
 965
 966    if (!data->include_abstract && type->abstract) {
 967        return;
 968    }
 969
 970    if (data->implements_type && 
 971        !object_class_dynamic_cast(k, data->implements_type)) {
 972        return;
 973    }
 974
 975    data->fn(k, data->opaque);
 976}
 977
 978void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
 979                          const char *implements_type, bool include_abstract,
 980                          void *opaque)
 981{
 982    OCFData data = { fn, implements_type, include_abstract, opaque };
 983
 984    enumerating_types = true;
 985    g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
 986    enumerating_types = false;
 987}
 988
 989static int do_object_child_foreach(Object *obj,
 990                                   int (*fn)(Object *child, void *opaque),
 991                                   void *opaque, bool recurse)
 992{
 993    GHashTableIter iter;
 994    ObjectProperty *prop;
 995    int ret = 0;
 996
 997    g_hash_table_iter_init(&iter, obj->properties);
 998    while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
 999        if (object_property_is_child(prop)) {
1000            Object *child = prop->opaque;
1001
1002            ret = fn(child, opaque);
1003            if (ret != 0) {
1004                break;
1005            }
1006            if (recurse) {
1007                do_object_child_foreach(child, fn, opaque, true);
1008            }
1009        }
1010    }
1011    return ret;
1012}
1013
1014int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
1015                         void *opaque)
1016{
1017    return do_object_child_foreach(obj, fn, opaque, false);
1018}
1019
1020int object_child_foreach_recursive(Object *obj,
1021                                   int (*fn)(Object *child, void *opaque),
1022                                   void *opaque)
1023{
1024    return do_object_child_foreach(obj, fn, opaque, true);
1025}
1026
1027static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
1028{
1029    GSList **list = opaque;
1030
1031    *list = g_slist_prepend(*list, klass);
1032}
1033
1034GSList *object_class_get_list(const char *implements_type,
1035                              bool include_abstract)
1036{
1037    GSList *list = NULL;
1038
1039    object_class_foreach(object_class_get_list_tramp,
1040                         implements_type, include_abstract, &list);
1041    return list;
1042}
1043
1044static gint object_class_cmp(gconstpointer a, gconstpointer b)
1045{
1046    return strcasecmp(object_class_get_name((ObjectClass *)a),
1047                      object_class_get_name((ObjectClass *)b));
1048}
1049
1050GSList *object_class_get_list_sorted(const char *implements_type,
1051                                     bool include_abstract)
1052{
1053    return g_slist_sort(object_class_get_list(implements_type, include_abstract),
1054                        object_class_cmp);
1055}
1056
1057void object_ref(Object *obj)
1058{
1059    if (!obj) {
1060        return;
1061    }
1062    atomic_inc(&obj->ref);
1063}
1064
1065void object_unref(Object *obj)
1066{
1067    if (!obj) {
1068        return;
1069    }
1070    g_assert(obj->ref > 0);
1071
1072    /* parent always holds a reference to its children */
1073    if (atomic_fetch_dec(&obj->ref) == 1) {
1074        object_finalize(obj);
1075    }
1076}
1077
1078ObjectProperty *
1079object_property_add(Object *obj, const char *name, const char *type,
1080                    ObjectPropertyAccessor *get,
1081                    ObjectPropertyAccessor *set,
1082                    ObjectPropertyRelease *release,
1083                    void *opaque, Error **errp)
1084{
1085    ObjectProperty *prop;
1086    size_t name_len = strlen(name);
1087
1088    if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) {
1089        int i;
1090        ObjectProperty *ret;
1091        char *name_no_array = g_strdup(name);
1092
1093        name_no_array[name_len - 3] = '\0';
1094        for (i = 0; ; ++i) {
1095            char *full_name = g_strdup_printf("%s[%d]", name_no_array, i);
1096
1097            ret = object_property_add(obj, full_name, type, get, set,
1098                                      release, opaque, NULL);
1099            g_free(full_name);
1100            if (ret) {
1101                break;
1102            }
1103        }
1104        g_free(name_no_array);
1105        return ret;
1106    }
1107
1108    if (object_property_find(obj, name, NULL) != NULL) {
1109        error_setg(errp, "attempt to add duplicate property '%s' to object (type '%s')",
1110                   name, object_get_typename(obj));
1111        return NULL;
1112    }
1113
1114    prop = g_malloc0(sizeof(*prop));
1115
1116    prop->name = g_strdup(name);
1117    prop->type = g_strdup(type);
1118
1119    prop->get = get;
1120    prop->set = set;
1121    prop->release = release;
1122    prop->opaque = opaque;
1123
1124    g_hash_table_insert(obj->properties, prop->name, prop);
1125    return prop;
1126}
1127
1128ObjectProperty *
1129object_class_property_add(ObjectClass *klass,
1130                          const char *name,
1131                          const char *type,
1132                          ObjectPropertyAccessor *get,
1133                          ObjectPropertyAccessor *set,
1134                          ObjectPropertyRelease *release,
1135                          void *opaque,
1136                          Error **errp)
1137{
1138    ObjectProperty *prop;
1139
1140    if (object_class_property_find(klass, name, NULL) != NULL) {
1141        error_setg(errp, "attempt to add duplicate property '%s' to class (type '%s')",
1142                   name, object_class_get_name(klass));
1143        return NULL;
1144    }
1145
1146    prop = g_malloc0(sizeof(*prop));
1147
1148    prop->name = g_strdup(name);
1149    prop->type = g_strdup(type);
1150
1151    prop->get = get;
1152    prop->set = set;
1153    prop->release = release;
1154    prop->opaque = opaque;
1155
1156    g_hash_table_insert(klass->properties, g_strdup(name), prop);
1157
1158    return prop;
1159}
1160
1161ObjectProperty *object_property_find(Object *obj, const char *name,
1162                                     Error **errp)
1163{
1164    ObjectProperty *prop;
1165    ObjectClass *klass = object_get_class(obj);
1166
1167    prop = object_class_property_find(klass, name, NULL);
1168    if (prop) {
1169        return prop;
1170    }
1171
1172    prop = g_hash_table_lookup(obj->properties, name);
1173    if (prop) {
1174        return prop;
1175    }
1176
1177    error_setg(errp, "Property '.%s' not found", name);
1178    return NULL;
1179}
1180
1181void object_property_iter_init(ObjectPropertyIterator *iter,
1182                               Object *obj)
1183{
1184    g_hash_table_iter_init(&iter->iter, obj->properties);
1185    iter->nextclass = object_get_class(obj);
1186}
1187
1188ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter)
1189{
1190    gpointer key, val;
1191    while (!g_hash_table_iter_next(&iter->iter, &key, &val)) {
1192        if (!iter->nextclass) {
1193            return NULL;
1194        }
1195        g_hash_table_iter_init(&iter->iter, iter->nextclass->properties);
1196        iter->nextclass = object_class_get_parent(iter->nextclass);
1197    }
1198    return val;
1199}
1200
1201void object_class_property_iter_init(ObjectPropertyIterator *iter,
1202                                     ObjectClass *klass)
1203{
1204    g_hash_table_iter_init(&iter->iter, klass->properties);
1205    iter->nextclass = object_class_get_parent(klass);
1206}
1207
1208ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name,
1209                                           Error **errp)
1210{
1211    ObjectProperty *prop;
1212    ObjectClass *parent_klass;
1213
1214    parent_klass = object_class_get_parent(klass);
1215    if (parent_klass) {
1216        prop = object_class_property_find(parent_klass, name, NULL);
1217        if (prop) {
1218            return prop;
1219        }
1220    }
1221
1222    prop = g_hash_table_lookup(klass->properties, name);
1223    if (!prop) {
1224        error_setg(errp, "Property '.%s' not found", name);
1225    }
1226    return prop;
1227}
1228
1229void object_property_del(Object *obj, const char *name, Error **errp)
1230{
1231    ObjectProperty *prop = g_hash_table_lookup(obj->properties, name);
1232
1233    if (!prop) {
1234        error_setg(errp, "Property '.%s' not found", name);
1235        return;
1236    }
1237
1238    if (prop->release) {
1239        prop->release(obj, name, prop->opaque);
1240    }
1241    g_hash_table_remove(obj->properties, name);
1242}
1243
1244void object_property_get(Object *obj, Visitor *v, const char *name,
1245                         Error **errp)
1246{
1247    ObjectProperty *prop = object_property_find(obj, name, errp);
1248    if (prop == NULL) {
1249        return;
1250    }
1251
1252    if (!prop->get) {
1253        error_setg(errp, QERR_PERMISSION_DENIED);
1254    } else {
1255        prop->get(obj, v, name, prop->opaque, errp);
1256    }
1257}
1258
1259void object_property_set(Object *obj, Visitor *v, const char *name,
1260                         Error **errp)
1261{
1262    ObjectProperty *prop = object_property_find(obj, name, errp);
1263    if (prop == NULL) {
1264        return;
1265    }
1266
1267    if (!prop->set) {
1268        error_setg(errp, QERR_PERMISSION_DENIED);
1269    } else {
1270        prop->set(obj, v, name, prop->opaque, errp);
1271    }
1272}
1273
1274void object_property_set_str(Object *obj, const char *value,
1275                             const char *name, Error **errp)
1276{
1277    QString *qstr = qstring_from_str(value);
1278    object_property_set_qobject(obj, QOBJECT(qstr), name, errp);
1279
1280    qobject_unref(qstr);
1281}
1282
1283char *object_property_get_str(Object *obj, const char *name,
1284                              Error **errp)
1285{
1286    QObject *ret = object_property_get_qobject(obj, name, errp);
1287    char *retval;
1288
1289    if (!ret) {
1290        return NULL;
1291    }
1292
1293    retval = g_strdup(qobject_get_try_str(ret));
1294    if (!retval) {
1295        error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
1296    }
1297
1298    qobject_unref(ret);
1299    return retval;
1300}
1301
1302void object_property_set_link(Object *obj, Object *value,
1303                              const char *name, Error **errp)
1304{
1305    if (value) {
1306        gchar *path = object_get_canonical_path(value);
1307        object_property_set_str(obj, path, name, errp);
1308        g_free(path);
1309    } else {
1310        object_property_set_str(obj, "", name, errp);
1311    }
1312}
1313
1314Object *object_property_get_link(Object *obj, const char *name,
1315                                 Error **errp)
1316{
1317    char *str = object_property_get_str(obj, name, errp);
1318    Object *target = NULL;
1319
1320    if (str && *str) {
1321        target = object_resolve_path(str, NULL);
1322        if (!target) {
1323            error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
1324                      "Device '%s' not found", str);
1325        }
1326    }
1327
1328    g_free(str);
1329    return target;
1330}
1331
1332void object_property_set_bool(Object *obj, bool value,
1333                              const char *name, Error **errp)
1334{
1335    QBool *qbool = qbool_from_bool(value);
1336    object_property_set_qobject(obj, QOBJECT(qbool), name, errp);
1337
1338    qobject_unref(qbool);
1339}
1340
1341bool object_property_get_bool(Object *obj, const char *name,
1342                              Error **errp)
1343{
1344    QObject *ret = object_property_get_qobject(obj, name, errp);
1345    QBool *qbool;
1346    bool retval;
1347
1348    if (!ret) {
1349        return false;
1350    }
1351    qbool = qobject_to(QBool, ret);
1352    if (!qbool) {
1353        error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean");
1354        retval = false;
1355    } else {
1356        retval = qbool_get_bool(qbool);
1357    }
1358
1359    qobject_unref(ret);
1360    return retval;
1361}
1362
1363void object_property_set_int(Object *obj, int64_t value,
1364                             const char *name, Error **errp)
1365{
1366    QNum *qnum = qnum_from_int(value);
1367    object_property_set_qobject(obj, QOBJECT(qnum), name, errp);
1368
1369    qobject_unref(qnum);
1370}
1371
1372int64_t object_property_get_int(Object *obj, const char *name,
1373                                Error **errp)
1374{
1375    QObject *ret = object_property_get_qobject(obj, name, errp);
1376    QNum *qnum;
1377    int64_t retval;
1378
1379    if (!ret) {
1380        return -1;
1381    }
1382
1383    qnum = qobject_to(QNum, ret);
1384    if (!qnum || !qnum_get_try_int(qnum, &retval)) {
1385        error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
1386        retval = -1;
1387    }
1388
1389    qobject_unref(ret);
1390    return retval;
1391}
1392
1393void object_property_set_uint(Object *obj, uint64_t value,
1394                              const char *name, Error **errp)
1395{
1396    QNum *qnum = qnum_from_uint(value);
1397
1398    object_property_set_qobject(obj, QOBJECT(qnum), name, errp);
1399    qobject_unref(qnum);
1400}
1401
1402uint64_t object_property_get_uint(Object *obj, const char *name,
1403                                  Error **errp)
1404{
1405    QObject *ret = object_property_get_qobject(obj, name, errp);
1406    QNum *qnum;
1407    uint64_t retval;
1408
1409    if (!ret) {
1410        return 0;
1411    }
1412    qnum = qobject_to(QNum, ret);
1413    if (!qnum || !qnum_get_try_uint(qnum, &retval)) {
1414        error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "uint");
1415        retval = 0;
1416    }
1417
1418    qobject_unref(ret);
1419    return retval;
1420}
1421
1422typedef struct EnumProperty {
1423    const QEnumLookup *lookup;
1424    int (*get)(Object *, Error **);
1425    void (*set)(Object *, int, Error **);
1426} EnumProperty;
1427
1428int object_property_get_enum(Object *obj, const char *name,
1429                             const char *typename, Error **errp)
1430{
1431    Error *err = NULL;
1432    Visitor *v;
1433    char *str;
1434    int ret;
1435    ObjectProperty *prop = object_property_find(obj, name, errp);
1436    EnumProperty *enumprop;
1437
1438    if (prop == NULL) {
1439        return 0;
1440    }
1441
1442    if (!g_str_equal(prop->type, typename)) {
1443        error_setg(errp, "Property %s on %s is not '%s' enum type",
1444                   name, object_class_get_name(
1445                       object_get_class(obj)), typename);
1446        return 0;
1447    }
1448
1449    enumprop = prop->opaque;
1450
1451    v = string_output_visitor_new(false, &str);
1452    object_property_get(obj, v, name, &err);
1453    if (err) {
1454        error_propagate(errp, err);
1455        visit_free(v);
1456        return 0;
1457    }
1458    visit_complete(v, &str);
1459    visit_free(v);
1460    v = string_input_visitor_new(str);
1461    visit_type_enum(v, name, &ret, enumprop->lookup, errp);
1462
1463    g_free(str);
1464    visit_free(v);
1465
1466    return ret;
1467}
1468
1469void object_property_get_uint16List(Object *obj, const char *name,
1470                                    uint16List **list, Error **errp)
1471{
1472    Error *err = NULL;
1473    Visitor *v;
1474    char *str;
1475
1476    v = string_output_visitor_new(false, &str);
1477    object_property_get(obj, v, name, &err);
1478    if (err) {
1479        error_propagate(errp, err);
1480        goto out;
1481    }
1482    visit_complete(v, &str);
1483    visit_free(v);
1484    v = string_input_visitor_new(str);
1485    visit_type_uint16List(v, NULL, list, errp);
1486
1487    g_free(str);
1488out:
1489    visit_free(v);
1490}
1491
1492void object_property_parse(Object *obj, const char *string,
1493                           const char *name, Error **errp)
1494{
1495    Visitor *v = string_input_visitor_new(string);
1496    object_property_set(obj, v, name, errp);
1497    visit_free(v);
1498}
1499
1500char *object_property_print(Object *obj, const char *name, bool human,
1501                            Error **errp)
1502{
1503    Visitor *v;
1504    char *string = NULL;
1505    Error *local_err = NULL;
1506
1507    v = string_output_visitor_new(human, &string);
1508    object_property_get(obj, v, name, &local_err);
1509    if (local_err) {
1510        error_propagate(errp, local_err);
1511        goto out;
1512    }
1513
1514    visit_complete(v, &string);
1515
1516out:
1517    visit_free(v);
1518    return string;
1519}
1520
1521const char *object_property_get_type(Object *obj, const char *name, Error **errp)
1522{
1523    ObjectProperty *prop = object_property_find(obj, name, errp);
1524    if (prop == NULL) {
1525        return NULL;
1526    }
1527
1528    return prop->type;
1529}
1530
1531Object *object_get_root(void)
1532{
1533    static Object *root;
1534
1535    if (!root) {
1536        root = object_new("container");
1537    }
1538
1539    return root;
1540}
1541
1542Object *object_get_objects_root(void)
1543{
1544    return container_get(object_get_root(), "/objects");
1545}
1546
1547Object *object_get_internal_root(void)
1548{
1549    static Object *internal_root;
1550
1551    if (!internal_root) {
1552        internal_root = object_new("container");
1553    }
1554
1555    return internal_root;
1556}
1557
1558static void object_get_child_property(Object *obj, Visitor *v,
1559                                      const char *name, void *opaque,
1560                                      Error **errp)
1561{
1562    Object *child = opaque;
1563    gchar *path;
1564
1565    path = object_get_canonical_path(child);
1566    visit_type_str(v, name, &path, errp);
1567    g_free(path);
1568}
1569
1570static Object *object_resolve_child_property(Object *parent, void *opaque, const gchar *part)
1571{
1572    return opaque;
1573}
1574
1575static void object_finalize_child_property(Object *obj, const char *name,
1576                                           void *opaque)
1577{
1578    Object *child = opaque;
1579
1580    if (child->class->unparent) {
1581        (child->class->unparent)(child);
1582    }
1583    child->parent = NULL;
1584    object_unref(child);
1585}
1586
1587void object_property_add_child(Object *obj, const char *name,
1588                               Object *child, Error **errp)
1589{
1590    Error *local_err = NULL;
1591    gchar *type;
1592    ObjectProperty *op;
1593
1594    if (child->parent != NULL) {
1595        error_setg(errp, "child object is already parented");
1596        return;
1597    }
1598
1599    type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
1600
1601    op = object_property_add(obj, name, type, object_get_child_property, NULL,
1602                             object_finalize_child_property, child, &local_err);
1603    if (local_err) {
1604        error_propagate(errp, local_err);
1605        goto out;
1606    }
1607
1608    op->resolve = object_resolve_child_property;
1609    object_ref(child);
1610    child->parent = obj;
1611
1612out:
1613    g_free(type);
1614}
1615
1616void object_property_allow_set_link(const Object *obj, const char *name,
1617                                    Object *val, Error **errp)
1618{
1619    /* Allow the link to be set, always */
1620}
1621
1622typedef struct {
1623    Object **child;
1624    void (*check)(const Object *, const char *, Object *, Error **);
1625    ObjectPropertyLinkFlags flags;
1626} LinkProperty;
1627
1628static void object_get_link_property(Object *obj, Visitor *v,
1629                                     const char *name, void *opaque,
1630                                     Error **errp)
1631{
1632    LinkProperty *lprop = opaque;
1633    Object **child = lprop->child;
1634    gchar *path;
1635
1636    if (*child) {
1637        path = object_get_canonical_path(*child);
1638        visit_type_str(v, name, &path, errp);
1639        g_free(path);
1640    } else {
1641        path = (gchar *)"";
1642        visit_type_str(v, name, &path, errp);
1643    }
1644}
1645
1646/*
1647 * object_resolve_link:
1648 *
1649 * Lookup an object and ensure its type matches the link property type.  This
1650 * is similar to object_resolve_path() except type verification against the
1651 * link property is performed.
1652 *
1653 * Returns: The matched object or NULL on path lookup failures.
1654 */
1655static Object *object_resolve_link(Object *obj, const char *name,
1656                                   const char *path, Error **errp)
1657{
1658    const char *type;
1659    gchar *target_type;
1660    bool ambiguous = false;
1661    Object *target;
1662
1663    /* Go from link<FOO> to FOO.  */
1664    type = object_property_get_type(obj, name, NULL);
1665    target_type = g_strndup(&type[5], strlen(type) - 6);
1666    target = object_resolve_path_type(path, target_type, &ambiguous);
1667
1668    if (ambiguous) {
1669        error_setg(errp, "Path '%s' does not uniquely identify an object",
1670                   path);
1671    } else if (!target) {
1672        target = object_resolve_path(path, &ambiguous);
1673        if (target || ambiguous) {
1674            error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
1675        } else {
1676            error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
1677                      "Device '%s' not found", path);
1678        }
1679        target = NULL;
1680    }
1681    g_free(target_type);
1682
1683    return target;
1684}
1685
1686static void object_set_link_property(Object *obj, Visitor *v,
1687                                     const char *name, void *opaque,
1688                                     Error **errp)
1689{
1690    Error *local_err = NULL;
1691    LinkProperty *prop = opaque;
1692    Object **child = prop->child;
1693    Object *old_target = *child;
1694    Object *new_target = NULL;
1695    char *path = NULL;
1696
1697    visit_type_str(v, name, &path, &local_err);
1698
1699    if (!local_err && strcmp(path, "") != 0) {
1700        new_target = object_resolve_link(obj, name, path, &local_err);
1701    }
1702
1703    g_free(path);
1704    if (local_err) {
1705        error_propagate(errp, local_err);
1706        return;
1707    }
1708
1709    prop->check(obj, name, new_target, &local_err);
1710    if (local_err) {
1711        error_propagate(errp, local_err);
1712        return;
1713    }
1714
1715    *child = new_target;
1716    if (prop->flags == OBJ_PROP_LINK_STRONG) {
1717        object_ref(new_target);
1718        object_unref(old_target);
1719    }
1720}
1721
1722static Object *object_resolve_link_property(Object *parent, void *opaque, const gchar *part)
1723{
1724    LinkProperty *lprop = opaque;
1725
1726    return *lprop->child;
1727}
1728
1729static void object_release_link_property(Object *obj, const char *name,
1730                                         void *opaque)
1731{
1732    LinkProperty *prop = opaque;
1733
1734    if ((prop->flags & OBJ_PROP_LINK_STRONG) && *prop->child) {
1735        object_unref(*prop->child);
1736    }
1737    g_free(prop);
1738}
1739
1740void object_property_add_link(Object *obj, const char *name,
1741                              const char *type, Object **child,
1742                              void (*check)(const Object *, const char *,
1743                                            Object *, Error **),
1744                              ObjectPropertyLinkFlags flags,
1745                              Error **errp)
1746{
1747    Error *local_err = NULL;
1748    LinkProperty *prop = g_malloc(sizeof(*prop));
1749    gchar *full_type;
1750    ObjectProperty *op;
1751
1752    prop->child = child;
1753    prop->check = check;
1754    prop->flags = flags;
1755
1756    full_type = g_strdup_printf("link<%s>", type);
1757
1758    op = object_property_add(obj, name, full_type,
1759                             object_get_link_property,
1760                             check ? object_set_link_property : NULL,
1761                             object_release_link_property,
1762                             prop,
1763                             &local_err);
1764    if (local_err) {
1765        error_propagate(errp, local_err);
1766        g_free(prop);
1767        goto out;
1768    }
1769
1770    op->resolve = object_resolve_link_property;
1771
1772out:
1773    g_free(full_type);
1774}
1775
1776void object_property_add_const_link(Object *obj, const char *name,
1777                                    Object *target, Error **errp)
1778{
1779    char *link_type;
1780    ObjectProperty *op;
1781
1782    link_type = g_strdup_printf("link<%s>", object_get_typename(target));
1783    op = object_property_add(obj, name, link_type,
1784                             object_get_child_property, NULL,
1785                             NULL, target, errp);
1786    if (op != NULL) {
1787        op->resolve = object_resolve_child_property;
1788    }
1789    g_free(link_type);
1790}
1791
1792gchar *object_get_canonical_path_component(Object *obj)
1793{
1794    ObjectProperty *prop = NULL;
1795    GHashTableIter iter;
1796
1797    if (obj->parent == NULL) {
1798        return NULL;
1799    }
1800
1801    g_hash_table_iter_init(&iter, obj->parent->properties);
1802    while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
1803        if (!object_property_is_child(prop)) {
1804            continue;
1805        }
1806
1807        if (prop->opaque == obj) {
1808            return g_strdup(prop->name);
1809        }
1810    }
1811
1812    /* obj had a parent but was not a child, should never happen */
1813    g_assert_not_reached();
1814    return NULL;
1815}
1816
1817gchar *object_get_canonical_path(Object *obj)
1818{
1819    Object *root = object_get_root();
1820    char *newpath, *path = NULL;
1821
1822    if (obj == root) {
1823        return g_strdup("/");
1824    }
1825
1826    do {
1827        char *component = object_get_canonical_path_component(obj);
1828
1829        if (!component) {
1830            /* A canonical path must be complete, so discard what was
1831             * collected so far.
1832             */
1833            g_free(path);
1834            return NULL;
1835        }
1836
1837        newpath = g_strdup_printf("/%s%s", component, path ? path : "");
1838        g_free(path);
1839        g_free(component);
1840        path = newpath;
1841        obj = obj->parent;
1842    } while (obj != root);
1843
1844    return path;
1845}
1846
1847Object *object_resolve_path_component(Object *parent, const gchar *part)
1848{
1849    ObjectProperty *prop = object_property_find(parent, part, NULL);
1850    if (prop == NULL) {
1851        return NULL;
1852    }
1853
1854    if (prop->resolve) {
1855        return prop->resolve(parent, prop->opaque, part);
1856    } else {
1857        return NULL;
1858    }
1859}
1860
1861static Object *object_resolve_abs_path(Object *parent,
1862                                          gchar **parts,
1863                                          const char *typename,
1864                                          int index)
1865{
1866    Object *child;
1867
1868    if (parts[index] == NULL) {
1869        return object_dynamic_cast(parent, typename);
1870    }
1871
1872    if (strcmp(parts[index], "") == 0) {
1873        return object_resolve_abs_path(parent, parts, typename, index + 1);
1874    }
1875
1876    child = object_resolve_path_component(parent, parts[index]);
1877    if (!child) {
1878        return NULL;
1879    }
1880
1881    return object_resolve_abs_path(child, parts, typename, index + 1);
1882}
1883
1884static Object *object_resolve_partial_path(Object *parent,
1885                                              gchar **parts,
1886                                              const char *typename,
1887                                              bool *ambiguous)
1888{
1889    Object *obj;
1890    GHashTableIter iter;
1891    ObjectProperty *prop;
1892
1893    obj = object_resolve_abs_path(parent, parts, typename, 0);
1894
1895    g_hash_table_iter_init(&iter, parent->properties);
1896    while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
1897        Object *found;
1898
1899        if (!object_property_is_child(prop)) {
1900            continue;
1901        }
1902
1903        found = object_resolve_partial_path(prop->opaque, parts,
1904                                            typename, ambiguous);
1905        if (found) {
1906            if (obj) {
1907                *ambiguous = true;
1908                return NULL;
1909            }
1910            obj = found;
1911        }
1912
1913        if (*ambiguous) {
1914            return NULL;
1915        }
1916    }
1917
1918    return obj;
1919}
1920
1921Object *object_resolve_path_type(const char *path, const char *typename,
1922                                 bool *ambiguousp)
1923{
1924    Object *obj;
1925    gchar **parts;
1926
1927    parts = g_strsplit(path, "/", 0);
1928    assert(parts);
1929
1930    if (parts[0] == NULL || strcmp(parts[0], "") != 0) {
1931        bool ambiguous = false;
1932        obj = object_resolve_partial_path(object_get_root(), parts,
1933                                          typename, &ambiguous);
1934        if (ambiguousp) {
1935            *ambiguousp = ambiguous;
1936        }
1937    } else {
1938        obj = object_resolve_abs_path(object_get_root(), parts, typename, 1);
1939    }
1940
1941    g_strfreev(parts);
1942
1943    return obj;
1944}
1945
1946Object *object_resolve_path(const char *path, bool *ambiguous)
1947{
1948    return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
1949}
1950
1951typedef struct StringProperty
1952{
1953    char *(*get)(Object *, Error **);
1954    void (*set)(Object *, const char *, Error **);
1955} StringProperty;
1956
1957static void property_get_str(Object *obj, Visitor *v, const char *name,
1958                             void *opaque, Error **errp)
1959{
1960    StringProperty *prop = opaque;
1961    char *value;
1962    Error *err = NULL;
1963
1964    value = prop->get(obj, &err);
1965    if (err) {
1966        error_propagate(errp, err);
1967        return;
1968    }
1969
1970    visit_type_str(v, name, &value, errp);
1971    g_free(value);
1972}
1973
1974static void property_set_str(Object *obj, Visitor *v, const char *name,
1975                             void *opaque, Error **errp)
1976{
1977    StringProperty *prop = opaque;
1978    char *value;
1979    Error *local_err = NULL;
1980
1981    visit_type_str(v, name, &value, &local_err);
1982    if (local_err) {
1983        error_propagate(errp, local_err);
1984        return;
1985    }
1986
1987    prop->set(obj, value, errp);
1988    g_free(value);
1989}
1990
1991static void property_release_str(Object *obj, const char *name,
1992                                 void *opaque)
1993{
1994    StringProperty *prop = opaque;
1995    g_free(prop);
1996}
1997
1998void object_property_add_str(Object *obj, const char *name,
1999                           char *(*get)(Object *, Error **),
2000                           void (*set)(Object *, const char *, Error **),
2001                           Error **errp)
2002{
2003    Error *local_err = NULL;
2004    StringProperty *prop = g_malloc0(sizeof(*prop));
2005
2006    prop->get = get;
2007    prop->set = set;
2008
2009    object_property_add(obj, name, "string",
2010                        get ? property_get_str : NULL,
2011                        set ? property_set_str : NULL,
2012                        property_release_str,
2013                        prop, &local_err);
2014    if (local_err) {
2015        error_propagate(errp, local_err);
2016        g_free(prop);
2017    }
2018}
2019
2020void object_class_property_add_str(ObjectClass *klass, const char *name,
2021                                   char *(*get)(Object *, Error **),
2022                                   void (*set)(Object *, const char *,
2023                                               Error **),
2024                                   Error **errp)
2025{
2026    Error *local_err = NULL;
2027    StringProperty *prop = g_malloc0(sizeof(*prop));
2028
2029    prop->get = get;
2030    prop->set = set;
2031
2032    object_class_property_add(klass, name, "string",
2033                              get ? property_get_str : NULL,
2034                              set ? property_set_str : NULL,
2035                              property_release_str,
2036                              prop, &local_err);
2037    if (local_err) {
2038        error_propagate(errp, local_err);
2039        g_free(prop);
2040    }
2041}
2042
2043typedef struct BoolProperty
2044{
2045    bool (*get)(Object *, Error **);
2046    void (*set)(Object *, bool, Error **);
2047} BoolProperty;
2048
2049static void property_get_bool(Object *obj, Visitor *v, const char *name,
2050                              void *opaque, Error **errp)
2051{
2052    BoolProperty *prop = opaque;
2053    bool value;
2054    Error *err = NULL;
2055
2056    value = prop->get(obj, &err);
2057    if (err) {
2058        error_propagate(errp, err);
2059        return;
2060    }
2061
2062    visit_type_bool(v, name, &value, errp);
2063}
2064
2065static void property_set_bool(Object *obj, Visitor *v, const char *name,
2066                              void *opaque, Error **errp)
2067{
2068    BoolProperty *prop = opaque;
2069    bool value;
2070    Error *local_err = NULL;
2071
2072    visit_type_bool(v, name, &value, &local_err);
2073    if (local_err) {
2074        error_propagate(errp, local_err);
2075        return;
2076    }
2077
2078    prop->set(obj, value, errp);
2079}
2080
2081static void property_release_bool(Object *obj, const char *name,
2082                                  void *opaque)
2083{
2084    BoolProperty *prop = opaque;
2085    g_free(prop);
2086}
2087
2088void object_property_add_bool(Object *obj, const char *name,
2089                              bool (*get)(Object *, Error **),
2090                              void (*set)(Object *, bool, Error **),
2091                              Error **errp)
2092{
2093    Error *local_err = NULL;
2094    BoolProperty *prop = g_malloc0(sizeof(*prop));
2095
2096    prop->get = get;
2097    prop->set = set;
2098
2099    object_property_add(obj, name, "bool",
2100                        get ? property_get_bool : NULL,
2101                        set ? property_set_bool : NULL,
2102                        property_release_bool,
2103                        prop, &local_err);
2104    if (local_err) {
2105        error_propagate(errp, local_err);
2106        g_free(prop);
2107    }
2108}
2109
2110void object_class_property_add_bool(ObjectClass *klass, const char *name,
2111                                    bool (*get)(Object *, Error **),
2112                                    void (*set)(Object *, bool, Error **),
2113                                    Error **errp)
2114{
2115    Error *local_err = NULL;
2116    BoolProperty *prop = g_malloc0(sizeof(*prop));
2117
2118    prop->get = get;
2119    prop->set = set;
2120
2121    object_class_property_add(klass, name, "bool",
2122                              get ? property_get_bool : NULL,
2123                              set ? property_set_bool : NULL,
2124                              property_release_bool,
2125                              prop, &local_err);
2126    if (local_err) {
2127        error_propagate(errp, local_err);
2128        g_free(prop);
2129    }
2130}
2131
2132static void property_get_enum(Object *obj, Visitor *v, const char *name,
2133                              void *opaque, Error **errp)
2134{
2135    EnumProperty *prop = opaque;
2136    int value;
2137    Error *err = NULL;
2138
2139    value = prop->get(obj, &err);
2140    if (err) {
2141        error_propagate(errp, err);
2142        return;
2143    }
2144
2145    visit_type_enum(v, name, &value, prop->lookup, errp);
2146}
2147
2148static void property_set_enum(Object *obj, Visitor *v, const char *name,
2149                              void *opaque, Error **errp)
2150{
2151    EnumProperty *prop = opaque;
2152    int value;
2153    Error *err = NULL;
2154
2155    visit_type_enum(v, name, &value, prop->lookup, &err);
2156    if (err) {
2157        error_propagate(errp, err);
2158        return;
2159    }
2160    prop->set(obj, value, errp);
2161}
2162
2163static void property_release_enum(Object *obj, const char *name,
2164                                  void *opaque)
2165{
2166    EnumProperty *prop = opaque;
2167    g_free(prop);
2168}
2169
2170void object_property_add_enum(Object *obj, const char *name,
2171                              const char *typename,
2172                              const QEnumLookup *lookup,
2173                              int (*get)(Object *, Error **),
2174                              void (*set)(Object *, int, Error **),
2175                              Error **errp)
2176{
2177    Error *local_err = NULL;
2178    EnumProperty *prop = g_malloc(sizeof(*prop));
2179
2180    prop->lookup = lookup;
2181    prop->get = get;
2182    prop->set = set;
2183
2184    object_property_add(obj, name, typename,
2185                        get ? property_get_enum : NULL,
2186                        set ? property_set_enum : NULL,
2187                        property_release_enum,
2188                        prop, &local_err);
2189    if (local_err) {
2190        error_propagate(errp, local_err);
2191        g_free(prop);
2192    }
2193}
2194
2195void object_class_property_add_enum(ObjectClass *klass, const char *name,
2196                                    const char *typename,
2197                                    const QEnumLookup *lookup,
2198                                    int (*get)(Object *, Error **),
2199                                    void (*set)(Object *, int, Error **),
2200                                    Error **errp)
2201{
2202    Error *local_err = NULL;
2203    EnumProperty *prop = g_malloc(sizeof(*prop));
2204
2205    prop->lookup = lookup;
2206    prop->get = get;
2207    prop->set = set;
2208
2209    object_class_property_add(klass, name, typename,
2210                              get ? property_get_enum : NULL,
2211                              set ? property_set_enum : NULL,
2212                              property_release_enum,
2213                              prop, &local_err);
2214    if (local_err) {
2215        error_propagate(errp, local_err);
2216        g_free(prop);
2217    }
2218}
2219
2220typedef struct TMProperty {
2221    void (*get)(Object *, struct tm *, Error **);
2222} TMProperty;
2223
2224static void property_get_tm(Object *obj, Visitor *v, const char *name,
2225                            void *opaque, Error **errp)
2226{
2227    TMProperty *prop = opaque;
2228    Error *err = NULL;
2229    struct tm value;
2230
2231    prop->get(obj, &value, &err);
2232    if (err) {
2233        goto out;
2234    }
2235
2236    visit_start_struct(v, name, NULL, 0, &err);
2237    if (err) {
2238        goto out;
2239    }
2240    visit_type_int32(v, "tm_year", &value.tm_year, &err);
2241    if (err) {
2242        goto out_end;
2243    }
2244    visit_type_int32(v, "tm_mon", &value.tm_mon, &err);
2245    if (err) {
2246        goto out_end;
2247    }
2248    visit_type_int32(v, "tm_mday", &value.tm_mday, &err);
2249    if (err) {
2250        goto out_end;
2251    }
2252    visit_type_int32(v, "tm_hour", &value.tm_hour, &err);
2253    if (err) {
2254        goto out_end;
2255    }
2256    visit_type_int32(v, "tm_min", &value.tm_min, &err);
2257    if (err) {
2258        goto out_end;
2259    }
2260    visit_type_int32(v, "tm_sec", &value.tm_sec, &err);
2261    if (err) {
2262        goto out_end;
2263    }
2264    visit_check_struct(v, &err);
2265out_end:
2266    visit_end_struct(v, NULL);
2267out:
2268    error_propagate(errp, err);
2269
2270}
2271
2272static void property_release_tm(Object *obj, const char *name,
2273                                void *opaque)
2274{
2275    TMProperty *prop = opaque;
2276    g_free(prop);
2277}
2278
2279void object_property_add_tm(Object *obj, const char *name,
2280                            void (*get)(Object *, struct tm *, Error **),
2281                            Error **errp)
2282{
2283    Error *local_err = NULL;
2284    TMProperty *prop = g_malloc0(sizeof(*prop));
2285
2286    prop->get = get;
2287
2288    object_property_add(obj, name, "struct tm",
2289                        get ? property_get_tm : NULL, NULL,
2290                        property_release_tm,
2291                        prop, &local_err);
2292    if (local_err) {
2293        error_propagate(errp, local_err);
2294        g_free(prop);
2295    }
2296}
2297
2298void object_class_property_add_tm(ObjectClass *klass, const char *name,
2299                                  void (*get)(Object *, struct tm *, Error **),
2300                                  Error **errp)
2301{
2302    Error *local_err = NULL;
2303    TMProperty *prop = g_malloc0(sizeof(*prop));
2304
2305    prop->get = get;
2306
2307    object_class_property_add(klass, name, "struct tm",
2308                              get ? property_get_tm : NULL, NULL,
2309                              property_release_tm,
2310                              prop, &local_err);
2311    if (local_err) {
2312        error_propagate(errp, local_err);
2313        g_free(prop);
2314    }
2315}
2316
2317static char *qdev_get_type(Object *obj, Error **errp)
2318{
2319    return g_strdup(object_get_typename(obj));
2320}
2321
2322static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name,
2323                                   void *opaque, Error **errp)
2324{
2325    uint8_t value = *(uint8_t *)opaque;
2326    visit_type_uint8(v, name, &value, errp);
2327}
2328
2329static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name,
2330                                    void *opaque, Error **errp)
2331{
2332    uint16_t value = *(uint16_t *)opaque;
2333    visit_type_uint16(v, name, &value, errp);
2334}
2335
2336static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name,
2337                                    void *opaque, Error **errp)
2338{
2339    uint32_t value = *(uint32_t *)opaque;
2340    visit_type_uint32(v, name, &value, errp);
2341}
2342
2343static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name,
2344                                    void *opaque, Error **errp)
2345{
2346    uint64_t value = *(uint64_t *)opaque;
2347    visit_type_uint64(v, name, &value, errp);
2348}
2349
2350void object_property_add_uint8_ptr(Object *obj, const char *name,
2351                                   const uint8_t *v, Error **errp)
2352{
2353    object_property_add(obj, name, "uint8", property_get_uint8_ptr,
2354                        NULL, NULL, (void *)v, errp);
2355}
2356
2357void object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
2358                                         const uint8_t *v, Error **errp)
2359{
2360    object_class_property_add(klass, name, "uint8", property_get_uint8_ptr,
2361                              NULL, NULL, (void *)v, errp);
2362}
2363
2364void object_property_add_uint16_ptr(Object *obj, const char *name,
2365                                    const uint16_t *v, Error **errp)
2366{
2367    object_property_add(obj, name, "uint16", property_get_uint16_ptr,
2368                        NULL, NULL, (void *)v, errp);
2369}
2370
2371void object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
2372                                          const uint16_t *v, Error **errp)
2373{
2374    object_class_property_add(klass, name, "uint16", property_get_uint16_ptr,
2375                              NULL, NULL, (void *)v, errp);
2376}
2377
2378void object_property_add_uint32_ptr(Object *obj, const char *name,
2379                                    const uint32_t *v, Error **errp)
2380{
2381    object_property_add(obj, name, "uint32", property_get_uint32_ptr,
2382                        NULL, NULL, (void *)v, errp);
2383}
2384
2385void object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
2386                                          const uint32_t *v, Error **errp)
2387{
2388    object_class_property_add(klass, name, "uint32", property_get_uint32_ptr,
2389                              NULL, NULL, (void *)v, errp);
2390}
2391
2392void object_property_add_uint64_ptr(Object *obj, const char *name,
2393                                    const uint64_t *v, Error **errp)
2394{
2395    object_property_add(obj, name, "uint64", property_get_uint64_ptr,
2396                        NULL, NULL, (void *)v, errp);
2397}
2398
2399void object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
2400                                          const uint64_t *v, Error **errp)
2401{
2402    object_class_property_add(klass, name, "uint64", property_get_uint64_ptr,
2403                              NULL, NULL, (void *)v, errp);
2404}
2405
2406typedef struct {
2407    Object *target_obj;
2408    char *target_name;
2409} AliasProperty;
2410
2411static void property_get_alias(Object *obj, Visitor *v, const char *name,
2412                               void *opaque, Error **errp)
2413{
2414    AliasProperty *prop = opaque;
2415
2416    object_property_get(prop->target_obj, v, prop->target_name, errp);
2417}
2418
2419static void property_set_alias(Object *obj, Visitor *v, const char *name,
2420                               void *opaque, Error **errp)
2421{
2422    AliasProperty *prop = opaque;
2423
2424    object_property_set(prop->target_obj, v, prop->target_name, errp);
2425}
2426
2427static Object *property_resolve_alias(Object *obj, void *opaque,
2428                                      const gchar *part)
2429{
2430    AliasProperty *prop = opaque;
2431
2432    return object_resolve_path_component(prop->target_obj, prop->target_name);
2433}
2434
2435static void property_release_alias(Object *obj, const char *name, void *opaque)
2436{
2437    AliasProperty *prop = opaque;
2438
2439    g_free(prop->target_name);
2440    g_free(prop);
2441}
2442
2443void object_property_add_alias(Object *obj, const char *name,
2444                               Object *target_obj, const char *target_name,
2445                               Error **errp)
2446{
2447    AliasProperty *prop;
2448    ObjectProperty *op;
2449    ObjectProperty *target_prop;
2450    gchar *prop_type;
2451    Error *local_err = NULL;
2452
2453    target_prop = object_property_find(target_obj, target_name, errp);
2454    if (!target_prop) {
2455        return;
2456    }
2457
2458    if (object_property_is_child(target_prop)) {
2459        prop_type = g_strdup_printf("link%s",
2460                                    target_prop->type + strlen("child"));
2461    } else {
2462        prop_type = g_strdup(target_prop->type);
2463    }
2464
2465    prop = g_malloc(sizeof(*prop));
2466    prop->target_obj = target_obj;
2467    prop->target_name = g_strdup(target_name);
2468
2469    op = object_property_add(obj, name, prop_type,
2470                             property_get_alias,
2471                             property_set_alias,
2472                             property_release_alias,
2473                             prop, &local_err);
2474    if (local_err) {
2475        error_propagate(errp, local_err);
2476        g_free(prop);
2477        goto out;
2478    }
2479    op->resolve = property_resolve_alias;
2480
2481    object_property_set_description(obj, op->name,
2482                                    target_prop->description,
2483                                    &error_abort);
2484
2485out:
2486    g_free(prop_type);
2487}
2488
2489void object_property_set_description(Object *obj, const char *name,
2490                                     const char *description, Error **errp)
2491{
2492    ObjectProperty *op;
2493
2494    op = object_property_find(obj, name, errp);
2495    if (!op) {
2496        return;
2497    }
2498
2499    g_free(op->description);
2500    op->description = g_strdup(description);
2501}
2502
2503void object_class_property_set_description(ObjectClass *klass,
2504                                           const char *name,
2505                                           const char *description,
2506                                           Error **errp)
2507{
2508    ObjectProperty *op;
2509
2510    op = g_hash_table_lookup(klass->properties, name);
2511    if (!op) {
2512        error_setg(errp, "Property '.%s' not found", name);
2513        return;
2514    }
2515
2516    g_free(op->description);
2517    op->description = g_strdup(description);
2518}
2519
2520static void object_class_init(ObjectClass *klass, void *data)
2521{
2522    object_class_property_add_str(klass, "type", qdev_get_type,
2523                                  NULL, &error_abort);
2524}
2525
2526static void register_types(void)
2527{
2528    static TypeInfo interface_info = {
2529        .name = TYPE_INTERFACE,
2530        .class_size = sizeof(InterfaceClass),
2531        .abstract = true,
2532    };
2533
2534    static TypeInfo object_info = {
2535        .name = TYPE_OBJECT,
2536        .instance_size = sizeof(Object),
2537        .class_init = object_class_init,
2538        .abstract = true,
2539    };
2540
2541    type_interface = type_register_internal(&interface_info);
2542    type_register_internal(&object_info);
2543}
2544
2545type_init(register_types)
2546