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