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