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