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