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