xref: /openbmc/qemu/hw/core/qdev-properties.c (revision be842efb)
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/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 
qdev_prop_set_after_realize(DeviceState * dev,const char * name,Error ** errp)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 */
qdev_prop_allow_set(Object * obj,const char * name,const PropertyInfo * info,Error ** errp)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 
qdev_prop_allow_set_link_before_realize(const Object * obj,const char * name,Object * val,Error ** errp)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 
object_field_prop_ptr(Object * obj,Property * prop)54 void *object_field_prop_ptr(Object *obj, Property *prop)
55 {
56     void *ptr = obj;
57     ptr += prop->offset;
58     return ptr;
59 }
60 
field_prop_get(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)61 static void field_prop_get(Object *obj, Visitor *v, const char *name,
62                            void *opaque, Error **errp)
63 {
64     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  */
field_prop_getter(const PropertyInfo * info)73 static ObjectPropertyAccessor *field_prop_getter(const PropertyInfo *info)
74 {
75     return info->get ? field_prop_get : NULL;
76 }
77 
field_prop_set(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)78 static void field_prop_set(Object *obj, Visitor *v, const char *name,
79                            void *opaque, Error **errp)
80 {
81     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  */
field_prop_setter(const PropertyInfo * info)95 static ObjectPropertyAccessor *field_prop_setter(const PropertyInfo *info)
96 {
97     return info->set ? field_prop_set : NULL;
98 }
99 
qdev_propinfo_get_enum(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)100 void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name,
101                             void *opaque, Error **errp)
102 {
103     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 
qdev_propinfo_set_enum(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)109 void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name,
110                             void *opaque, Error **errp)
111 {
112     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 
qdev_propinfo_set_default_value_enum(ObjectProperty * op,const Property * prop)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 
qdev_get_prop_mask(Property * prop)134 static uint32_t qdev_get_prop_mask(Property *prop)
135 {
136     assert(prop->info == &qdev_prop_bit);
137     return 0x1 << prop->bitnr;
138 }
139 
bit_prop_set(Object * obj,Property * props,bool val)140 static void bit_prop_set(Object *obj, 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 
prop_get_bit(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)151 static void prop_get_bit(Object *obj, Visitor *v, const char *name,
152                          void *opaque, Error **errp)
153 {
154     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 
prop_set_bit(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)161 static void prop_set_bit(Object *obj, Visitor *v, const char *name,
162                          void *opaque, Error **errp)
163 {
164     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 
set_default_value_bool(ObjectProperty * op,const Property * prop)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 
qdev_get_prop_mask64(Property * prop)188 static uint64_t qdev_get_prop_mask64(Property *prop)
189 {
190     assert(prop->info == &qdev_prop_bit64);
191     return 0x1ull << prop->bitnr;
192 }
193 
bit64_prop_set(Object * obj,Property * props,bool val)194 static void bit64_prop_set(Object *obj, 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 
prop_get_bit64(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)205 static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
206                            void *opaque, Error **errp)
207 {
208     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 
prop_set_bit64(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)215 static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
216                            void *opaque, Error **errp)
217 {
218     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 
get_bool(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)237 static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,
238                      Error **errp)
239 {
240     Property *prop = opaque;
241     bool *ptr = object_field_prop_ptr(obj, prop);
242 
243     visit_type_bool(v, name, ptr, errp);
244 }
245 
set_bool(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)246 static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
247                      Error **errp)
248 {
249     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 
get_uint8(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)264 static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
265                       Error **errp)
266 {
267     Property *prop = opaque;
268     uint8_t *ptr = object_field_prop_ptr(obj, prop);
269 
270     visit_type_uint8(v, name, ptr, errp);
271 }
272 
set_uint8(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)273 static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
274                       Error **errp)
275 {
276     Property *prop = opaque;
277     uint8_t *ptr = object_field_prop_ptr(obj, prop);
278 
279     visit_type_uint8(v, name, ptr, errp);
280 }
281 
qdev_propinfo_set_default_value_int(ObjectProperty * op,const Property * prop)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 
qdev_propinfo_set_default_value_uint(ObjectProperty * op,const Property * prop)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 
get_uint16(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)303 static void get_uint16(Object *obj, Visitor *v, const char *name,
304                        void *opaque, Error **errp)
305 {
306     Property *prop = opaque;
307     uint16_t *ptr = object_field_prop_ptr(obj, prop);
308 
309     visit_type_uint16(v, name, ptr, errp);
310 }
311 
set_uint16(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)312 static void set_uint16(Object *obj, Visitor *v, const char *name,
313                        void *opaque, Error **errp)
314 {
315     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 
get_uint32(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)330 static void get_uint32(Object *obj, Visitor *v, const char *name,
331                        void *opaque, Error **errp)
332 {
333     Property *prop = opaque;
334     uint32_t *ptr = object_field_prop_ptr(obj, prop);
335 
336     visit_type_uint32(v, name, ptr, errp);
337 }
338 
set_uint32(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)339 static void set_uint32(Object *obj, Visitor *v, const char *name,
340                        void *opaque, Error **errp)
341 {
342     Property *prop = opaque;
343     uint32_t *ptr = object_field_prop_ptr(obj, prop);
344 
345     visit_type_uint32(v, name, ptr, errp);
346 }
347 
qdev_propinfo_get_int32(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)348 void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name,
349                              void *opaque, Error **errp)
350 {
351     Property *prop = opaque;
352     int32_t *ptr = object_field_prop_ptr(obj, prop);
353 
354     visit_type_int32(v, name, ptr, errp);
355 }
356 
set_int32(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)357 static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
358                       Error **errp)
359 {
360     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 
get_uint64(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)382 static void get_uint64(Object *obj, Visitor *v, const char *name,
383                        void *opaque, Error **errp)
384 {
385     Property *prop = opaque;
386     uint64_t *ptr = object_field_prop_ptr(obj, prop);
387 
388     visit_type_uint64(v, name, ptr, errp);
389 }
390 
set_uint64(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)391 static void set_uint64(Object *obj, Visitor *v, const char *name,
392                        void *opaque, Error **errp)
393 {
394     Property *prop = opaque;
395     uint64_t *ptr = object_field_prop_ptr(obj, prop);
396 
397     visit_type_uint64(v, name, ptr, errp);
398 }
399 
get_int64(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)400 static void get_int64(Object *obj, Visitor *v, const char *name,
401                       void *opaque, Error **errp)
402 {
403     Property *prop = opaque;
404     int64_t *ptr = object_field_prop_ptr(obj, prop);
405 
406     visit_type_int64(v, name, ptr, errp);
407 }
408 
set_int64(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)409 static void set_int64(Object *obj, Visitor *v, const char *name,
410                       void *opaque, Error **errp)
411 {
412     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 
set_uint64_checkmask(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)432 static void set_uint64_checkmask(Object *obj, Visitor *v, const char *name,
433                       void *opaque, Error **errp)
434 {
435     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 
release_string(Object * obj,const char * name,void * opaque)453 static void release_string(Object *obj, const char *name, void *opaque)
454 {
455     Property *prop = opaque;
456     g_free(*(char **)object_field_prop_ptr(obj, prop));
457 }
458 
get_string(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)459 static void get_string(Object *obj, Visitor *v, const char *name,
460                        void *opaque, Error **errp)
461 {
462     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 
set_string(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)473 static void set_string(Object *obj, Visitor *v, const char *name,
474                        void *opaque, Error **errp)
475 {
476     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 
qdev_propinfo_get_size32(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)507 void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name,
508                               void *opaque, Error **errp)
509 {
510     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 
set_size32(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)517 static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,
518                        Error **errp)
519 {
520     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  */
array_elem_prop(Object * obj,Property * parent_prop,const char * name,char * elem)560 static Property array_elem_prop(Object *obj, 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  */
release_prop_array(Object * obj,const char * name,void * opaque)583 static void release_prop_array(Object *obj, const char *name, void *opaque)
584 {
585     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  */
set_prop_array(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)608 static void set_prop_array(Object *obj, Visitor *v, const char *name,
609                            void *opaque, Error **errp)
610 {
611     ERRP_GUARD();
612     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 
get_prop_array(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)684 static void get_prop_array(Object *obj, Visitor *v, const char *name,
685                            void *opaque, Error **errp)
686 {
687     ERRP_GUARD();
688     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 
default_prop_array(ObjectProperty * op,const Property * prop)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 
qdev_prop_walk(Property * props,const char * name)752 static Property *qdev_prop_walk(Property *props, const char *name)
753 {
754     if (!props) {
755         return NULL;
756     }
757     while (props->name) {
758         if (strcmp(props->name, name) == 0) {
759             return props;
760         }
761         props++;
762     }
763     return NULL;
764 }
765 
qdev_prop_find(DeviceState * dev,const char * name)766 static Property *qdev_prop_find(DeviceState *dev, const char *name)
767 {
768     ObjectClass *class;
769     Property *prop;
770 
771     /* device properties */
772     class = object_get_class(OBJECT(dev));
773     do {
774         prop = qdev_prop_walk(DEVICE_CLASS(class)->props_, name);
775         if (prop) {
776             return prop;
777         }
778         class = object_class_get_parent(class);
779     } while (class != object_class_by_name(TYPE_DEVICE));
780 
781     return NULL;
782 }
783 
error_set_from_qdev_prop_error(Error ** errp,int ret,Object * obj,const char * name,const char * value)784 void error_set_from_qdev_prop_error(Error **errp, int ret, Object *obj,
785                                     const char *name, const char *value)
786 {
787     switch (ret) {
788     case -EEXIST:
789         error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
790                   object_get_typename(obj), name, value);
791         break;
792     default:
793     case -EINVAL:
794         error_setg(errp, "Property '%s.%s' doesn't take value '%s'",
795                    object_get_typename(obj), name, value);
796         break;
797     case -ENOENT:
798         error_setg(errp, "Property '%s.%s' can't find value '%s'",
799                   object_get_typename(obj), name, value);
800         break;
801     case 0:
802         break;
803     }
804 }
805 
qdev_prop_set_bit(DeviceState * dev,const char * name,bool value)806 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
807 {
808     object_property_set_bool(OBJECT(dev), name, value, &error_abort);
809 }
810 
qdev_prop_set_uint8(DeviceState * dev,const char * name,uint8_t value)811 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
812 {
813     object_property_set_int(OBJECT(dev), name, value, &error_abort);
814 }
815 
qdev_prop_set_uint16(DeviceState * dev,const char * name,uint16_t value)816 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
817 {
818     object_property_set_int(OBJECT(dev), name, value, &error_abort);
819 }
820 
qdev_prop_set_uint32(DeviceState * dev,const char * name,uint32_t value)821 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
822 {
823     object_property_set_int(OBJECT(dev), name, value, &error_abort);
824 }
825 
qdev_prop_set_int32(DeviceState * dev,const char * name,int32_t value)826 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
827 {
828     object_property_set_int(OBJECT(dev), name, value, &error_abort);
829 }
830 
qdev_prop_set_uint64(DeviceState * dev,const char * name,uint64_t value)831 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
832 {
833     object_property_set_int(OBJECT(dev), name, value, &error_abort);
834 }
835 
qdev_prop_set_string(DeviceState * dev,const char * name,const char * value)836 void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
837 {
838     object_property_set_str(OBJECT(dev), name, value, &error_abort);
839 }
840 
qdev_prop_set_enum(DeviceState * dev,const char * name,int value)841 void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
842 {
843     Property *prop;
844 
845     prop = qdev_prop_find(dev, name);
846     object_property_set_str(OBJECT(dev), name,
847                             qapi_enum_lookup(prop->info->enum_table, value),
848                             &error_abort);
849 }
850 
qdev_prop_set_array(DeviceState * dev,const char * name,QList * values)851 void qdev_prop_set_array(DeviceState *dev, const char *name, QList *values)
852 {
853     object_property_set_qobject(OBJECT(dev), name, QOBJECT(values),
854                                 &error_abort);
855     qobject_unref(values);
856 }
857 
global_props(void)858 static GPtrArray *global_props(void)
859 {
860     static GPtrArray *gp;
861 
862     if (!gp) {
863         gp = g_ptr_array_new();
864     }
865 
866     return gp;
867 }
868 
qdev_prop_register_global(GlobalProperty * prop)869 void qdev_prop_register_global(GlobalProperty *prop)
870 {
871     g_ptr_array_add(global_props(), prop);
872 }
873 
qdev_find_global_prop(Object * obj,const char * name)874 const GlobalProperty *qdev_find_global_prop(Object *obj,
875                                             const char *name)
876 {
877     GPtrArray *props = global_props();
878     const GlobalProperty *p;
879     int i;
880 
881     for (i = 0; i < props->len; i++) {
882         p = g_ptr_array_index(props, i);
883         if (object_dynamic_cast(obj, p->driver)
884             && !strcmp(p->property, name)) {
885             return p;
886         }
887     }
888     return NULL;
889 }
890 
qdev_prop_check_globals(void)891 int qdev_prop_check_globals(void)
892 {
893     int i, ret = 0;
894 
895     for (i = 0; i < global_props()->len; i++) {
896         GlobalProperty *prop;
897         ObjectClass *oc;
898         DeviceClass *dc;
899 
900         prop = g_ptr_array_index(global_props(), i);
901         if (prop->used) {
902             continue;
903         }
904         oc = object_class_by_name(prop->driver);
905         oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
906         if (!oc) {
907             warn_report("global %s.%s has invalid class name",
908                         prop->driver, prop->property);
909             ret = 1;
910             continue;
911         }
912         dc = DEVICE_CLASS(oc);
913         if (!dc->hotpluggable && !prop->used) {
914             warn_report("global %s.%s=%s not used",
915                         prop->driver, prop->property, prop->value);
916             ret = 1;
917             continue;
918         }
919     }
920     return ret;
921 }
922 
qdev_prop_set_globals(DeviceState * dev)923 void qdev_prop_set_globals(DeviceState *dev)
924 {
925     object_apply_global_props(OBJECT(dev), global_props(),
926                               dev->hotplugged ? NULL : &error_fatal);
927 }
928 
929 /* --- 64bit unsigned int 'size' type --- */
930 
get_size(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)931 static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
932                      Error **errp)
933 {
934     Property *prop = opaque;
935     uint64_t *ptr = object_field_prop_ptr(obj, prop);
936 
937     visit_type_size(v, name, ptr, errp);
938 }
939 
set_size(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)940 static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
941                      Error **errp)
942 {
943     Property *prop = opaque;
944     uint64_t *ptr = object_field_prop_ptr(obj, prop);
945 
946     visit_type_size(v, name, ptr, errp);
947 }
948 
949 const PropertyInfo qdev_prop_size = {
950     .name  = "size",
951     .get = get_size,
952     .set = set_size,
953     .set_default_value = qdev_propinfo_set_default_value_uint,
954 };
955 
956 /* --- object link property --- */
957 
create_link_property(ObjectClass * oc,const char * name,Property * prop)958 static ObjectProperty *create_link_property(ObjectClass *oc, const char *name,
959                                             Property *prop)
960 {
961     return object_class_property_add_link(oc, name, prop->link_type,
962                                           prop->offset,
963                                           qdev_prop_allow_set_link_before_realize,
964                                           OBJ_PROP_LINK_STRONG);
965 }
966 
967 const PropertyInfo qdev_prop_link = {
968     .name = "link",
969     .create = create_link_property,
970 };
971 
qdev_property_add_static(DeviceState * dev,Property * prop)972 void qdev_property_add_static(DeviceState *dev, Property *prop)
973 {
974     Object *obj = OBJECT(dev);
975     ObjectProperty *op;
976 
977     assert(!prop->info->create);
978 
979     op = object_property_add(obj, prop->name, prop->info->name,
980                              field_prop_getter(prop->info),
981                              field_prop_setter(prop->info),
982                              prop->info->release,
983                              prop);
984 
985     object_property_set_description(obj, prop->name,
986                                     prop->info->description);
987 
988     if (prop->set_default) {
989         prop->info->set_default_value(op, prop);
990         if (op->init) {
991             op->init(obj, op);
992         }
993     }
994 }
995 
qdev_class_add_property(DeviceClass * klass,const char * name,Property * prop)996 static void qdev_class_add_property(DeviceClass *klass, const char *name,
997                                     Property *prop)
998 {
999     ObjectClass *oc = OBJECT_CLASS(klass);
1000     ObjectProperty *op;
1001 
1002     if (prop->info->create) {
1003         op = prop->info->create(oc, name, prop);
1004     } else {
1005         op = object_class_property_add(oc,
1006                                        name, prop->info->name,
1007                                        field_prop_getter(prop->info),
1008                                        field_prop_setter(prop->info),
1009                                        prop->info->release,
1010                                        prop);
1011     }
1012     if (prop->set_default) {
1013         prop->info->set_default_value(op, prop);
1014     }
1015     object_class_property_set_description(oc, name, prop->info->description);
1016 }
1017 
1018 /**
1019  * Legacy property handling
1020  */
1021 
qdev_get_legacy_property(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)1022 static void qdev_get_legacy_property(Object *obj, Visitor *v,
1023                                      const char *name, void *opaque,
1024                                      Error **errp)
1025 {
1026     Property *prop = opaque;
1027 
1028     char buffer[1024];
1029     char *ptr = buffer;
1030 
1031     prop->info->print(obj, prop, buffer, sizeof(buffer));
1032     visit_type_str(v, name, &ptr, errp);
1033 }
1034 
1035 /**
1036  * qdev_class_add_legacy_property:
1037  * @dev: Device to add the property to.
1038  * @prop: The qdev property definition.
1039  *
1040  * Add a legacy QOM property to @dev for qdev property @prop.
1041  *
1042  * Legacy properties are string versions of QOM properties.  The format of
1043  * the string depends on the property type.  Legacy properties are only
1044  * needed for "info qtree".
1045  *
1046  * Do not use this in new code!  QOM Properties added through this interface
1047  * will be given names in the "legacy" namespace.
1048  */
qdev_class_add_legacy_property(DeviceClass * dc,Property * prop)1049 static void qdev_class_add_legacy_property(DeviceClass *dc, Property *prop)
1050 {
1051     g_autofree char *name = NULL;
1052 
1053     /* Register pointer properties as legacy properties */
1054     if (!prop->info->print && prop->info->get) {
1055         return;
1056     }
1057 
1058     name = g_strdup_printf("legacy-%s", prop->name);
1059     object_class_property_add(OBJECT_CLASS(dc), name, "str",
1060         prop->info->print ? qdev_get_legacy_property : prop->info->get,
1061         NULL, NULL, prop);
1062 }
1063 
device_class_set_props(DeviceClass * dc,Property * props)1064 void device_class_set_props(DeviceClass *dc, Property *props)
1065 {
1066     Property *prop;
1067 
1068     dc->props_ = props;
1069     for (prop = props; prop && prop->name; prop++) {
1070         qdev_class_add_legacy_property(dc, prop);
1071         qdev_class_add_property(dc, prop->name, prop);
1072     }
1073 }
1074 
qdev_alias_all_properties(DeviceState * target,Object * source)1075 void qdev_alias_all_properties(DeviceState *target, Object *source)
1076 {
1077     ObjectClass *class;
1078     ObjectPropertyIterator iter;
1079     ObjectProperty *prop;
1080 
1081     class = object_get_class(OBJECT(target));
1082 
1083     object_class_property_iter_init(&iter, class);
1084     while ((prop = object_property_iter_next(&iter))) {
1085         if (object_property_find(source, prop->name)) {
1086             continue; /* skip duplicate properties */
1087         }
1088 
1089         object_property_add_alias(source, prop->name,
1090                                   OBJECT(target), prop->name);
1091     }
1092 }
1093