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