xref: /openbmc/qemu/hw/core/qdev-properties.c (revision c63ca4ff)
1 #include "qemu/osdep.h"
2 #include "hw/qdev-properties.h"
3 #include "qapi/error.h"
4 #include "qapi/qapi-types-misc.h"
5 #include "qapi/qmp/qerror.h"
6 #include "qemu/ctype.h"
7 #include "qemu/error-report.h"
8 #include "qapi/visitor.h"
9 #include "qemu/units.h"
10 #include "qemu/cutils.h"
11 #include "qdev-prop-internal.h"
12 
13 void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
14                                   Error **errp)
15 {
16     if (dev->id) {
17         error_setg(errp, "Attempt to set property '%s' on device '%s' "
18                    "(type '%s') after it was realized", name, dev->id,
19                    object_get_typename(OBJECT(dev)));
20     } else {
21         error_setg(errp, "Attempt to set property '%s' on anonymous device "
22                    "(type '%s') after it was realized", name,
23                    object_get_typename(OBJECT(dev)));
24     }
25 }
26 
27 void qdev_prop_allow_set_link_before_realize(const Object *obj,
28                                              const char *name,
29                                              Object *val, Error **errp)
30 {
31     DeviceState *dev = DEVICE(obj);
32 
33     if (dev->realized) {
34         error_setg(errp, "Attempt to set link property '%s' on device '%s' "
35                    "(type '%s') after it was realized",
36                    name, dev->id, object_get_typename(obj));
37     }
38 }
39 
40 void *qdev_get_prop_ptr(Object *obj, Property *prop)
41 {
42     void *ptr = obj;
43     ptr += prop->offset;
44     return ptr;
45 }
46 
47 void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name,
48                             void *opaque, Error **errp)
49 {
50     Property *prop = opaque;
51     int *ptr = qdev_get_prop_ptr(obj, prop);
52 
53     visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
54 }
55 
56 void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name,
57                             void *opaque, Error **errp)
58 {
59     DeviceState *dev = DEVICE(obj);
60     Property *prop = opaque;
61     int *ptr = qdev_get_prop_ptr(obj, prop);
62 
63     if (dev->realized) {
64         qdev_prop_set_after_realize(dev, name, errp);
65         return;
66     }
67 
68     visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
69 }
70 
71 void qdev_propinfo_set_default_value_enum(ObjectProperty *op,
72                                           const Property *prop)
73 {
74     object_property_set_default_str(op,
75         qapi_enum_lookup(prop->info->enum_table, prop->defval.i));
76 }
77 
78 const PropertyInfo qdev_prop_enum = {
79     .name  = "enum",
80     .get   = qdev_propinfo_get_enum,
81     .set   = qdev_propinfo_set_enum,
82     .set_default_value = qdev_propinfo_set_default_value_enum,
83 };
84 
85 /* Bit */
86 
87 static uint32_t qdev_get_prop_mask(Property *prop)
88 {
89     assert(prop->info == &qdev_prop_bit);
90     return 0x1 << prop->bitnr;
91 }
92 
93 static void bit_prop_set(Object *obj, Property *props, bool val)
94 {
95     uint32_t *p = qdev_get_prop_ptr(obj, props);
96     uint32_t mask = qdev_get_prop_mask(props);
97     if (val) {
98         *p |= mask;
99     } else {
100         *p &= ~mask;
101     }
102 }
103 
104 static void prop_get_bit(Object *obj, Visitor *v, const char *name,
105                          void *opaque, Error **errp)
106 {
107     Property *prop = opaque;
108     uint32_t *p = qdev_get_prop_ptr(obj, prop);
109     bool value = (*p & qdev_get_prop_mask(prop)) != 0;
110 
111     visit_type_bool(v, name, &value, errp);
112 }
113 
114 static void prop_set_bit(Object *obj, Visitor *v, const char *name,
115                          void *opaque, Error **errp)
116 {
117     DeviceState *dev = DEVICE(obj);
118     Property *prop = opaque;
119     bool value;
120 
121     if (dev->realized) {
122         qdev_prop_set_after_realize(dev, name, errp);
123         return;
124     }
125 
126     if (!visit_type_bool(v, name, &value, errp)) {
127         return;
128     }
129     bit_prop_set(obj, prop, value);
130 }
131 
132 static void set_default_value_bool(ObjectProperty *op, const Property *prop)
133 {
134     object_property_set_default_bool(op, prop->defval.u);
135 }
136 
137 const PropertyInfo qdev_prop_bit = {
138     .name  = "bool",
139     .description = "on/off",
140     .get   = prop_get_bit,
141     .set   = prop_set_bit,
142     .set_default_value = set_default_value_bool,
143 };
144 
145 /* Bit64 */
146 
147 static uint64_t qdev_get_prop_mask64(Property *prop)
148 {
149     assert(prop->info == &qdev_prop_bit64);
150     return 0x1ull << prop->bitnr;
151 }
152 
153 static void bit64_prop_set(Object *obj, Property *props, bool val)
154 {
155     uint64_t *p = qdev_get_prop_ptr(obj, props);
156     uint64_t mask = qdev_get_prop_mask64(props);
157     if (val) {
158         *p |= mask;
159     } else {
160         *p &= ~mask;
161     }
162 }
163 
164 static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
165                            void *opaque, Error **errp)
166 {
167     Property *prop = opaque;
168     uint64_t *p = qdev_get_prop_ptr(obj, prop);
169     bool value = (*p & qdev_get_prop_mask64(prop)) != 0;
170 
171     visit_type_bool(v, name, &value, errp);
172 }
173 
174 static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
175                            void *opaque, Error **errp)
176 {
177     DeviceState *dev = DEVICE(obj);
178     Property *prop = opaque;
179     bool value;
180 
181     if (dev->realized) {
182         qdev_prop_set_after_realize(dev, name, errp);
183         return;
184     }
185 
186     if (!visit_type_bool(v, name, &value, errp)) {
187         return;
188     }
189     bit64_prop_set(obj, prop, value);
190 }
191 
192 const PropertyInfo qdev_prop_bit64 = {
193     .name  = "bool",
194     .description = "on/off",
195     .get   = prop_get_bit64,
196     .set   = prop_set_bit64,
197     .set_default_value = set_default_value_bool,
198 };
199 
200 /* --- bool --- */
201 
202 static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,
203                      Error **errp)
204 {
205     Property *prop = opaque;
206     bool *ptr = qdev_get_prop_ptr(obj, prop);
207 
208     visit_type_bool(v, name, ptr, errp);
209 }
210 
211 static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
212                      Error **errp)
213 {
214     DeviceState *dev = DEVICE(obj);
215     Property *prop = opaque;
216     bool *ptr = qdev_get_prop_ptr(obj, prop);
217 
218     if (dev->realized) {
219         qdev_prop_set_after_realize(dev, name, errp);
220         return;
221     }
222 
223     visit_type_bool(v, name, ptr, errp);
224 }
225 
226 const PropertyInfo qdev_prop_bool = {
227     .name  = "bool",
228     .get   = get_bool,
229     .set   = set_bool,
230     .set_default_value = set_default_value_bool,
231 };
232 
233 /* --- 8bit integer --- */
234 
235 static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
236                       Error **errp)
237 {
238     Property *prop = opaque;
239     uint8_t *ptr = qdev_get_prop_ptr(obj, prop);
240 
241     visit_type_uint8(v, name, ptr, errp);
242 }
243 
244 static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
245                       Error **errp)
246 {
247     DeviceState *dev = DEVICE(obj);
248     Property *prop = opaque;
249     uint8_t *ptr = qdev_get_prop_ptr(obj, prop);
250 
251     if (dev->realized) {
252         qdev_prop_set_after_realize(dev, name, errp);
253         return;
254     }
255 
256     visit_type_uint8(v, name, ptr, errp);
257 }
258 
259 void qdev_propinfo_set_default_value_int(ObjectProperty *op,
260                                          const Property *prop)
261 {
262     object_property_set_default_int(op, prop->defval.i);
263 }
264 
265 void qdev_propinfo_set_default_value_uint(ObjectProperty *op,
266                                           const Property *prop)
267 {
268     object_property_set_default_uint(op, prop->defval.u);
269 }
270 
271 const PropertyInfo qdev_prop_uint8 = {
272     .name  = "uint8",
273     .get   = get_uint8,
274     .set   = set_uint8,
275     .set_default_value = qdev_propinfo_set_default_value_uint,
276 };
277 
278 /* --- 16bit integer --- */
279 
280 static void get_uint16(Object *obj, Visitor *v, const char *name,
281                        void *opaque, Error **errp)
282 {
283     Property *prop = opaque;
284     uint16_t *ptr = qdev_get_prop_ptr(obj, prop);
285 
286     visit_type_uint16(v, name, ptr, errp);
287 }
288 
289 static void set_uint16(Object *obj, Visitor *v, const char *name,
290                        void *opaque, Error **errp)
291 {
292     DeviceState *dev = DEVICE(obj);
293     Property *prop = opaque;
294     uint16_t *ptr = qdev_get_prop_ptr(obj, prop);
295 
296     if (dev->realized) {
297         qdev_prop_set_after_realize(dev, name, errp);
298         return;
299     }
300 
301     visit_type_uint16(v, name, ptr, errp);
302 }
303 
304 const PropertyInfo qdev_prop_uint16 = {
305     .name  = "uint16",
306     .get   = get_uint16,
307     .set   = set_uint16,
308     .set_default_value = qdev_propinfo_set_default_value_uint,
309 };
310 
311 /* --- 32bit integer --- */
312 
313 static void get_uint32(Object *obj, Visitor *v, const char *name,
314                        void *opaque, Error **errp)
315 {
316     Property *prop = opaque;
317     uint32_t *ptr = qdev_get_prop_ptr(obj, prop);
318 
319     visit_type_uint32(v, name, ptr, errp);
320 }
321 
322 static void set_uint32(Object *obj, Visitor *v, const char *name,
323                        void *opaque, Error **errp)
324 {
325     DeviceState *dev = DEVICE(obj);
326     Property *prop = opaque;
327     uint32_t *ptr = qdev_get_prop_ptr(obj, prop);
328 
329     if (dev->realized) {
330         qdev_prop_set_after_realize(dev, name, errp);
331         return;
332     }
333 
334     visit_type_uint32(v, name, ptr, errp);
335 }
336 
337 void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name,
338                              void *opaque, Error **errp)
339 {
340     Property *prop = opaque;
341     int32_t *ptr = qdev_get_prop_ptr(obj, prop);
342 
343     visit_type_int32(v, name, ptr, errp);
344 }
345 
346 static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
347                       Error **errp)
348 {
349     DeviceState *dev = DEVICE(obj);
350     Property *prop = opaque;
351     int32_t *ptr = qdev_get_prop_ptr(obj, prop);
352 
353     if (dev->realized) {
354         qdev_prop_set_after_realize(dev, name, errp);
355         return;
356     }
357 
358     visit_type_int32(v, name, ptr, errp);
359 }
360 
361 const PropertyInfo qdev_prop_uint32 = {
362     .name  = "uint32",
363     .get   = get_uint32,
364     .set   = set_uint32,
365     .set_default_value = qdev_propinfo_set_default_value_uint,
366 };
367 
368 const PropertyInfo qdev_prop_int32 = {
369     .name  = "int32",
370     .get   = qdev_propinfo_get_int32,
371     .set   = set_int32,
372     .set_default_value = qdev_propinfo_set_default_value_int,
373 };
374 
375 /* --- 64bit integer --- */
376 
377 static void get_uint64(Object *obj, Visitor *v, const char *name,
378                        void *opaque, Error **errp)
379 {
380     Property *prop = opaque;
381     uint64_t *ptr = qdev_get_prop_ptr(obj, prop);
382 
383     visit_type_uint64(v, name, ptr, errp);
384 }
385 
386 static void set_uint64(Object *obj, Visitor *v, const char *name,
387                        void *opaque, Error **errp)
388 {
389     DeviceState *dev = DEVICE(obj);
390     Property *prop = opaque;
391     uint64_t *ptr = qdev_get_prop_ptr(obj, prop);
392 
393     if (dev->realized) {
394         qdev_prop_set_after_realize(dev, name, errp);
395         return;
396     }
397 
398     visit_type_uint64(v, name, ptr, errp);
399 }
400 
401 static void get_int64(Object *obj, Visitor *v, const char *name,
402                       void *opaque, Error **errp)
403 {
404     Property *prop = opaque;
405     int64_t *ptr = qdev_get_prop_ptr(obj, prop);
406 
407     visit_type_int64(v, name, ptr, errp);
408 }
409 
410 static void set_int64(Object *obj, Visitor *v, const char *name,
411                       void *opaque, Error **errp)
412 {
413     DeviceState *dev = DEVICE(obj);
414     Property *prop = opaque;
415     int64_t *ptr = qdev_get_prop_ptr(obj, prop);
416 
417     if (dev->realized) {
418         qdev_prop_set_after_realize(dev, name, errp);
419         return;
420     }
421 
422     visit_type_int64(v, name, ptr, errp);
423 }
424 
425 const PropertyInfo qdev_prop_uint64 = {
426     .name  = "uint64",
427     .get   = get_uint64,
428     .set   = set_uint64,
429     .set_default_value = qdev_propinfo_set_default_value_uint,
430 };
431 
432 const PropertyInfo qdev_prop_int64 = {
433     .name  = "int64",
434     .get   = get_int64,
435     .set   = set_int64,
436     .set_default_value = qdev_propinfo_set_default_value_int,
437 };
438 
439 /* --- string --- */
440 
441 static void release_string(Object *obj, const char *name, void *opaque)
442 {
443     Property *prop = opaque;
444     g_free(*(char **)qdev_get_prop_ptr(obj, prop));
445 }
446 
447 static void get_string(Object *obj, Visitor *v, const char *name,
448                        void *opaque, Error **errp)
449 {
450     Property *prop = opaque;
451     char **ptr = qdev_get_prop_ptr(obj, prop);
452 
453     if (!*ptr) {
454         char *str = (char *)"";
455         visit_type_str(v, name, &str, errp);
456     } else {
457         visit_type_str(v, name, ptr, errp);
458     }
459 }
460 
461 static void set_string(Object *obj, Visitor *v, const char *name,
462                        void *opaque, Error **errp)
463 {
464     DeviceState *dev = DEVICE(obj);
465     Property *prop = opaque;
466     char **ptr = qdev_get_prop_ptr(obj, prop);
467     char *str;
468 
469     if (dev->realized) {
470         qdev_prop_set_after_realize(dev, name, errp);
471         return;
472     }
473 
474     if (!visit_type_str(v, name, &str, errp)) {
475         return;
476     }
477     g_free(*ptr);
478     *ptr = str;
479 }
480 
481 const PropertyInfo qdev_prop_string = {
482     .name  = "str",
483     .release = release_string,
484     .get   = get_string,
485     .set   = set_string,
486 };
487 
488 /* --- on/off/auto --- */
489 
490 const PropertyInfo qdev_prop_on_off_auto = {
491     .name = "OnOffAuto",
492     .description = "on/off/auto",
493     .enum_table = &OnOffAuto_lookup,
494     .get = qdev_propinfo_get_enum,
495     .set = qdev_propinfo_set_enum,
496     .set_default_value = qdev_propinfo_set_default_value_enum,
497 };
498 
499 /* --- 32bit unsigned int 'size' type --- */
500 
501 void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name,
502                               void *opaque, Error **errp)
503 {
504     Property *prop = opaque;
505     uint32_t *ptr = qdev_get_prop_ptr(obj, prop);
506     uint64_t value = *ptr;
507 
508     visit_type_size(v, name, &value, errp);
509 }
510 
511 static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,
512                        Error **errp)
513 {
514     DeviceState *dev = DEVICE(obj);
515     Property *prop = opaque;
516     uint32_t *ptr = qdev_get_prop_ptr(obj, prop);
517     uint64_t value;
518 
519     if (dev->realized) {
520         qdev_prop_set_after_realize(dev, name, errp);
521         return;
522     }
523 
524     if (!visit_type_size(v, name, &value, errp)) {
525         return;
526     }
527 
528     if (value > UINT32_MAX) {
529         error_setg(errp,
530                    "Property %s.%s doesn't take value %" PRIu64
531                    " (maximum: %u)",
532                    object_get_typename(obj), name, value, UINT32_MAX);
533         return;
534     }
535 
536     *ptr = value;
537 }
538 
539 const PropertyInfo qdev_prop_size32 = {
540     .name  = "size",
541     .get = qdev_propinfo_get_size32,
542     .set = set_size32,
543     .set_default_value = qdev_propinfo_set_default_value_uint,
544 };
545 
546 /* --- support for array properties --- */
547 
548 /* Used as an opaque for the object properties we add for each
549  * array element. Note that the struct Property must be first
550  * in the struct so that a pointer to this works as the opaque
551  * for the underlying element's property hooks as well as for
552  * our own release callback.
553  */
554 typedef struct {
555     struct Property prop;
556     char *propname;
557     ObjectPropertyRelease *release;
558 } ArrayElementProperty;
559 
560 /* object property release callback for array element properties:
561  * we call the underlying element's property release hook, and
562  * then free the memory we allocated when we added the property.
563  */
564 static void array_element_release(Object *obj, const char *name, void *opaque)
565 {
566     ArrayElementProperty *p = opaque;
567     if (p->release) {
568         p->release(obj, name, opaque);
569     }
570     g_free(p->propname);
571     g_free(p);
572 }
573 
574 static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
575                               void *opaque, Error **errp)
576 {
577     /* Setter for the property which defines the length of a
578      * variable-sized property array. As well as actually setting the
579      * array-length field in the device struct, we have to create the
580      * array itself and dynamically add the corresponding properties.
581      */
582     DeviceState *dev = DEVICE(obj);
583     Property *prop = opaque;
584     uint32_t *alenptr = qdev_get_prop_ptr(obj, prop);
585     void **arrayptr = (void *)dev + prop->arrayoffset;
586     void *eltptr;
587     const char *arrayname;
588     int i;
589 
590     if (dev->realized) {
591         qdev_prop_set_after_realize(dev, name, errp);
592         return;
593     }
594     if (*alenptr) {
595         error_setg(errp, "array size property %s may not be set more than once",
596                    name);
597         return;
598     }
599     if (!visit_type_uint32(v, name, alenptr, errp)) {
600         return;
601     }
602     if (!*alenptr) {
603         return;
604     }
605 
606     /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
607      * strip it off so we can get the name of the array itself.
608      */
609     assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
610                    strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
611     arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
612 
613     /* Note that it is the responsibility of the individual device's deinit
614      * to free the array proper.
615      */
616     *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
617     for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
618         char *propname = g_strdup_printf("%s[%d]", arrayname, i);
619         ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
620         arrayprop->release = prop->arrayinfo->release;
621         arrayprop->propname = propname;
622         arrayprop->prop.info = prop->arrayinfo;
623         arrayprop->prop.name = propname;
624         /* This ugly piece of pointer arithmetic sets up the offset so
625          * that when the underlying get/set hooks call qdev_get_prop_ptr
626          * they get the right answer despite the array element not actually
627          * being inside the device struct.
628          */
629         arrayprop->prop.offset = eltptr - (void *)dev;
630         assert(qdev_get_prop_ptr(obj, &arrayprop->prop) == eltptr);
631         object_property_add(obj, propname,
632                             arrayprop->prop.info->name,
633                             arrayprop->prop.info->get,
634                             arrayprop->prop.info->set,
635                             array_element_release,
636                             arrayprop);
637     }
638 }
639 
640 const PropertyInfo qdev_prop_arraylen = {
641     .name = "uint32",
642     .get = get_uint32,
643     .set = set_prop_arraylen,
644     .set_default_value = qdev_propinfo_set_default_value_uint,
645 };
646 
647 /* --- public helpers --- */
648 
649 static Property *qdev_prop_walk(Property *props, const char *name)
650 {
651     if (!props) {
652         return NULL;
653     }
654     while (props->name) {
655         if (strcmp(props->name, name) == 0) {
656             return props;
657         }
658         props++;
659     }
660     return NULL;
661 }
662 
663 static Property *qdev_prop_find(DeviceState *dev, const char *name)
664 {
665     ObjectClass *class;
666     Property *prop;
667 
668     /* device properties */
669     class = object_get_class(OBJECT(dev));
670     do {
671         prop = qdev_prop_walk(DEVICE_CLASS(class)->props_, name);
672         if (prop) {
673             return prop;
674         }
675         class = object_class_get_parent(class);
676     } while (class != object_class_by_name(TYPE_DEVICE));
677 
678     return NULL;
679 }
680 
681 void error_set_from_qdev_prop_error(Error **errp, int ret, Object *obj,
682                                     Property *prop, const char *value)
683 {
684     switch (ret) {
685     case -EEXIST:
686         error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
687                   object_get_typename(obj), prop->name, value);
688         break;
689     default:
690     case -EINVAL:
691         error_setg(errp, QERR_PROPERTY_VALUE_BAD,
692                    object_get_typename(obj), prop->name, value);
693         break;
694     case -ENOENT:
695         error_setg(errp, "Property '%s.%s' can't find value '%s'",
696                   object_get_typename(obj), prop->name, value);
697         break;
698     case 0:
699         break;
700     }
701 }
702 
703 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
704 {
705     object_property_set_bool(OBJECT(dev), name, value, &error_abort);
706 }
707 
708 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
709 {
710     object_property_set_int(OBJECT(dev), name, value, &error_abort);
711 }
712 
713 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
714 {
715     object_property_set_int(OBJECT(dev), name, value, &error_abort);
716 }
717 
718 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
719 {
720     object_property_set_int(OBJECT(dev), name, value, &error_abort);
721 }
722 
723 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
724 {
725     object_property_set_int(OBJECT(dev), name, value, &error_abort);
726 }
727 
728 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
729 {
730     object_property_set_int(OBJECT(dev), name, value, &error_abort);
731 }
732 
733 void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
734 {
735     object_property_set_str(OBJECT(dev), name, value, &error_abort);
736 }
737 
738 void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
739 {
740     Property *prop;
741 
742     prop = qdev_prop_find(dev, name);
743     object_property_set_str(OBJECT(dev), name,
744                             qapi_enum_lookup(prop->info->enum_table, value),
745                             &error_abort);
746 }
747 
748 static GPtrArray *global_props(void)
749 {
750     static GPtrArray *gp;
751 
752     if (!gp) {
753         gp = g_ptr_array_new();
754     }
755 
756     return gp;
757 }
758 
759 void qdev_prop_register_global(GlobalProperty *prop)
760 {
761     g_ptr_array_add(global_props(), prop);
762 }
763 
764 const GlobalProperty *qdev_find_global_prop(Object *obj,
765                                             const char *name)
766 {
767     GPtrArray *props = global_props();
768     const GlobalProperty *p;
769     int i;
770 
771     for (i = 0; i < props->len; i++) {
772         p = g_ptr_array_index(props, i);
773         if (object_dynamic_cast(obj, p->driver)
774             && !strcmp(p->property, name)) {
775             return p;
776         }
777     }
778     return NULL;
779 }
780 
781 int qdev_prop_check_globals(void)
782 {
783     int i, ret = 0;
784 
785     for (i = 0; i < global_props()->len; i++) {
786         GlobalProperty *prop;
787         ObjectClass *oc;
788         DeviceClass *dc;
789 
790         prop = g_ptr_array_index(global_props(), i);
791         if (prop->used) {
792             continue;
793         }
794         oc = object_class_by_name(prop->driver);
795         oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
796         if (!oc) {
797             warn_report("global %s.%s has invalid class name",
798                         prop->driver, prop->property);
799             ret = 1;
800             continue;
801         }
802         dc = DEVICE_CLASS(oc);
803         if (!dc->hotpluggable && !prop->used) {
804             warn_report("global %s.%s=%s not used",
805                         prop->driver, prop->property, prop->value);
806             ret = 1;
807             continue;
808         }
809     }
810     return ret;
811 }
812 
813 void qdev_prop_set_globals(DeviceState *dev)
814 {
815     object_apply_global_props(OBJECT(dev), global_props(),
816                               dev->hotplugged ? NULL : &error_fatal);
817 }
818 
819 /* --- 64bit unsigned int 'size' type --- */
820 
821 static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
822                      Error **errp)
823 {
824     Property *prop = opaque;
825     uint64_t *ptr = qdev_get_prop_ptr(obj, prop);
826 
827     visit_type_size(v, name, ptr, errp);
828 }
829 
830 static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
831                      Error **errp)
832 {
833     DeviceState *dev = DEVICE(obj);
834     Property *prop = opaque;
835     uint64_t *ptr = qdev_get_prop_ptr(obj, prop);
836 
837     if (dev->realized) {
838         qdev_prop_set_after_realize(dev, name, errp);
839         return;
840     }
841 
842     visit_type_size(v, name, ptr, errp);
843 }
844 
845 const PropertyInfo qdev_prop_size = {
846     .name  = "size",
847     .get = get_size,
848     .set = set_size,
849     .set_default_value = qdev_propinfo_set_default_value_uint,
850 };
851 
852 /* --- object link property --- */
853 
854 static void create_link_property(ObjectClass *oc, Property *prop)
855 {
856     object_class_property_add_link(oc, prop->name, prop->link_type,
857                                    prop->offset,
858                                    qdev_prop_allow_set_link_before_realize,
859                                    OBJ_PROP_LINK_STRONG);
860 }
861 
862 const PropertyInfo qdev_prop_link = {
863     .name = "link",
864     .create = create_link_property,
865 };
866 
867 void qdev_property_add_static(DeviceState *dev, Property *prop)
868 {
869     Object *obj = OBJECT(dev);
870     ObjectProperty *op;
871 
872     assert(!prop->info->create);
873 
874     op = object_property_add(obj, prop->name, prop->info->name,
875                              prop->info->get, prop->info->set,
876                              prop->info->release,
877                              prop);
878 
879     object_property_set_description(obj, prop->name,
880                                     prop->info->description);
881 
882     if (prop->set_default) {
883         prop->info->set_default_value(op, prop);
884         if (op->init) {
885             op->init(obj, op);
886         }
887     }
888 }
889 
890 static void qdev_class_add_property(DeviceClass *klass, Property *prop)
891 {
892     ObjectClass *oc = OBJECT_CLASS(klass);
893 
894     if (prop->info->create) {
895         prop->info->create(oc, prop);
896     } else {
897         ObjectProperty *op;
898 
899         op = object_class_property_add(oc,
900                                        prop->name, prop->info->name,
901                                        prop->info->get, prop->info->set,
902                                        prop->info->release,
903                                        prop);
904         if (prop->set_default) {
905             prop->info->set_default_value(op, prop);
906         }
907     }
908     object_class_property_set_description(oc, prop->name,
909                                           prop->info->description);
910 }
911 
912 /**
913  * Legacy property handling
914  */
915 
916 static void qdev_get_legacy_property(Object *obj, Visitor *v,
917                                      const char *name, void *opaque,
918                                      Error **errp)
919 {
920     Property *prop = opaque;
921 
922     char buffer[1024];
923     char *ptr = buffer;
924 
925     prop->info->print(obj, prop, buffer, sizeof(buffer));
926     visit_type_str(v, name, &ptr, errp);
927 }
928 
929 /**
930  * qdev_class_add_legacy_property:
931  * @dev: Device to add the property to.
932  * @prop: The qdev property definition.
933  *
934  * Add a legacy QOM property to @dev for qdev property @prop.
935  *
936  * Legacy properties are string versions of QOM properties.  The format of
937  * the string depends on the property type.  Legacy properties are only
938  * needed for "info qtree".
939  *
940  * Do not use this in new code!  QOM Properties added through this interface
941  * will be given names in the "legacy" namespace.
942  */
943 static void qdev_class_add_legacy_property(DeviceClass *dc, Property *prop)
944 {
945     g_autofree char *name = NULL;
946 
947     /* Register pointer properties as legacy properties */
948     if (!prop->info->print && prop->info->get) {
949         return;
950     }
951 
952     name = g_strdup_printf("legacy-%s", prop->name);
953     object_class_property_add(OBJECT_CLASS(dc), name, "str",
954         prop->info->print ? qdev_get_legacy_property : prop->info->get,
955         NULL, NULL, prop);
956 }
957 
958 void device_class_set_props(DeviceClass *dc, Property *props)
959 {
960     Property *prop;
961 
962     dc->props_ = props;
963     for (prop = props; prop && prop->name; prop++) {
964         qdev_class_add_legacy_property(dc, prop);
965         qdev_class_add_property(dc, prop);
966     }
967 }
968 
969 void qdev_alias_all_properties(DeviceState *target, Object *source)
970 {
971     ObjectClass *class;
972     Property *prop;
973 
974     class = object_get_class(OBJECT(target));
975     do {
976         DeviceClass *dc = DEVICE_CLASS(class);
977 
978         for (prop = dc->props_; prop && prop->name; prop++) {
979             object_property_add_alias(source, prop->name,
980                                       OBJECT(target), prop->name);
981         }
982         class = object_class_get_parent(class);
983     } while (class != object_class_by_name(TYPE_DEVICE));
984 }
985