]> git.ipfire.org Git - thirdparty/qemu.git/blame - hw/core/qdev-properties.c
Merge tag 'pull-request-2025-07-02' of https://gitlab.com/thuth/qemu into staging
[thirdparty/qemu.git] / hw / core / qdev-properties.c
CommitLineData
18c86e2b 1#include "qemu/osdep.h"
a27bd6c7 2#include "hw/qdev-properties.h"
da34e65c 3#include "qapi/error.h"
2ae16a6a 4#include "qapi/qapi-types-misc.h"
407bc4bf 5#include "qobject/qlist.h"
856dfd8a 6#include "qemu/ctype.h"
d49b6836 7#include "qemu/error-report.h"
7b1b5d19 8#include "qapi/visitor.h"
645b55d1 9#include "qemu/units.h"
f7806925 10#include "qemu/cutils.h"
a2974439 11#include "qdev-prop-internal.h"
32400a7e 12#include "qom/qom-qobject.h"
ee6847d1 13
b000dfbd
PM
14void 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
ea7c1e5c
EH
28/* returns: true if property is allowed to be set, false otherwise */
29static bool qdev_prop_allow_set(Object *obj, const char *name,
deb2bb16 30 const PropertyInfo *info, Error **errp)
ea7c1e5c
EH
31{
32 DeviceState *dev = DEVICE(obj);
33
deb2bb16 34 if (dev->realized && !info->realized_set_allowed) {
ea7c1e5c
EH
35 qdev_prop_set_after_realize(dev, name, errp);
36 return false;
37 }
38 return true;
39}
40
8f5d58ef
IM
41void qdev_prop_allow_set_link_before_realize(const Object *obj,
42 const char *name,
39f72ef9
SH
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
e9c0346a 54void *object_field_prop_ptr(Object *obj, const Property *prop)
ee6847d1 55{
828ade86 56 void *ptr = obj;
ee6847d1
GH
57 ptr += prop->offset;
58 return ptr;
59}
60
7ed854af
EH
61static void field_prop_get(Object *obj, Visitor *v, const char *name,
62 void *opaque, Error **errp)
63{
b1987a25 64 const Property *prop = opaque;
7ed854af
EH
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 */
73static ObjectPropertyAccessor *field_prop_getter(const PropertyInfo *info)
74{
75 return info->get ? field_prop_get : NULL;
76}
77
78static void field_prop_set(Object *obj, Visitor *v, const char *name,
79 void *opaque, Error **errp)
80{
b1987a25 81 const Property *prop = opaque;
ea7c1e5c 82
deb2bb16 83 if (!qdev_prop_allow_set(obj, name, prop->info, errp)) {
ea7c1e5c
EH
84 return;
85 }
86
7ed854af
EH
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 */
95static ObjectPropertyAccessor *field_prop_setter(const PropertyInfo *info)
96{
97 return info->set ? field_prop_set : NULL;
98}
99
a2974439
PMD
100void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name,
101 void *opaque, Error **errp)
d4d34b0d 102{
b1987a25 103 const Property *prop = opaque;
1e198715 104 int *ptr = object_field_prop_ptr(obj, prop);
d4d34b0d 105
991f0ac9 106 visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
d4d34b0d
MA
107}
108
a2974439
PMD
109void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name,
110 void *opaque, Error **errp)
d4d34b0d 111{
b1987a25 112 const Property *prop = opaque;
1e198715 113 int *ptr = object_field_prop_ptr(obj, prop);
d4d34b0d 114
991f0ac9 115 visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
d4d34b0d
MA
116}
117
a2974439
PMD
118void qdev_propinfo_set_default_value_enum(ObjectProperty *op,
119 const Property *prop)
a2740ad5 120{
77b06bba
MAL
121 object_property_set_default_str(op,
122 qapi_enum_lookup(prop->info->enum_table, prop->defval.i));
a2740ad5
MAL
123}
124
d4d34b0d
MA
125/* Bit */
126
b1987a25 127static uint32_t qdev_get_prop_mask(const Property *prop)
d2364ee4 128{
a3d4a1b0 129 assert(prop->info == &qdev_prop_bit);
d2364ee4
MT
130 return 0x1 << prop->bitnr;
131}
132
b1987a25 133static void bit_prop_set(Object *obj, const Property *props, bool val)
d2364ee4 134{
1e198715 135 uint32_t *p = object_field_prop_ptr(obj, props);
d2364ee4 136 uint32_t mask = qdev_get_prop_mask(props);
04a2d61e 137 if (val) {
dbd48324 138 *p |= mask;
04a2d61e 139 } else {
d2364ee4 140 *p &= ~mask;
04a2d61e 141 }
d2364ee4
MT
142}
143
d7bce999
EB
144static void prop_get_bit(Object *obj, Visitor *v, const char *name,
145 void *opaque, Error **errp)
80e555c2 146{
b1987a25 147 const Property *prop = opaque;
1e198715 148 uint32_t *p = object_field_prop_ptr(obj, prop);
80e555c2
PB
149 bool value = (*p & qdev_get_prop_mask(prop)) != 0;
150
51e72bc1 151 visit_type_bool(v, name, &value, errp);
80e555c2
PB
152}
153
d7bce999
EB
154static void prop_set_bit(Object *obj, Visitor *v, const char *name,
155 void *opaque, Error **errp)
80e555c2 156{
b1987a25 157 const Property *prop = opaque;
80e555c2
PB
158 bool value;
159
668f62ec 160 if (!visit_type_bool(v, name, &value, errp)) {
80e555c2
PB
161 return;
162 }
605d9fc0 163 bit_prop_set(obj, prop, value);
80e555c2
PB
164}
165
77b06bba 166static void set_default_value_bool(ObjectProperty *op, const Property *prop)
a2740ad5 167{
77b06bba 168 object_property_set_default_bool(op, prop->defval.u);
a2740ad5
MAL
169}
170
1b6b7d10 171const PropertyInfo qdev_prop_bit = {
c98dac16 172 .type = "bool",
51b2e8c3 173 .description = "on/off",
949fc823
MA
174 .get = prop_get_bit,
175 .set = prop_set_bit,
a2740ad5 176 .set_default_value = set_default_value_bool,
d2364ee4
MT
177};
178
fdba6d96
GH
179/* Bit64 */
180
b1987a25 181static uint64_t qdev_get_prop_mask64(const Property *prop)
fdba6d96 182{
8aedc369 183 assert(prop->info == &qdev_prop_bit64);
1fa795a8 184 return 0x1ull << prop->bitnr;
fdba6d96
GH
185}
186
b1987a25 187static void bit64_prop_set(Object *obj, const Property *props, bool val)
fdba6d96 188{
1e198715 189 uint64_t *p = object_field_prop_ptr(obj, props);
fdba6d96
GH
190 uint64_t mask = qdev_get_prop_mask64(props);
191 if (val) {
192 *p |= mask;
193 } else {
194 *p &= ~mask;
195 }
196}
197
d7bce999
EB
198static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
199 void *opaque, Error **errp)
fdba6d96 200{
b1987a25 201 const Property *prop = opaque;
1e198715 202 uint64_t *p = object_field_prop_ptr(obj, prop);
fdba6d96
GH
203 bool value = (*p & qdev_get_prop_mask64(prop)) != 0;
204
51e72bc1 205 visit_type_bool(v, name, &value, errp);
fdba6d96
GH
206}
207
d7bce999
EB
208static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
209 void *opaque, Error **errp)
fdba6d96 210{
b1987a25 211 const Property *prop = opaque;
fdba6d96
GH
212 bool value;
213
668f62ec 214 if (!visit_type_bool(v, name, &value, errp)) {
fdba6d96
GH
215 return;
216 }
605d9fc0 217 bit64_prop_set(obj, prop, value);
fdba6d96
GH
218}
219
1b6b7d10 220const PropertyInfo qdev_prop_bit64 = {
c98dac16 221 .type = "bool",
fdba6d96
GH
222 .description = "on/off",
223 .get = prop_get_bit64,
224 .set = prop_set_bit64,
a2740ad5 225 .set_default_value = set_default_value_bool,
fdba6d96
GH
226};
227
72cc5137
IM
228/* --- bool --- */
229
d7bce999
EB
230static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,
231 Error **errp)
72cc5137 232{
b1987a25 233 const Property *prop = opaque;
1e198715 234 bool *ptr = object_field_prop_ptr(obj, prop);
72cc5137 235
51e72bc1 236 visit_type_bool(v, name, ptr, errp);
72cc5137
IM
237}
238
d7bce999
EB
239static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
240 Error **errp)
72cc5137 241{
b1987a25 242 const Property *prop = opaque;
1e198715 243 bool *ptr = object_field_prop_ptr(obj, prop);
72cc5137 244
51e72bc1 245 visit_type_bool(v, name, ptr, errp);
72cc5137
IM
246}
247
1b6b7d10 248const PropertyInfo qdev_prop_bool = {
c98dac16 249 .type = "bool",
45e5b493 250 .description = "on/off",
72cc5137
IM
251 .get = get_bool,
252 .set = set_bool,
a2740ad5 253 .set_default_value = set_default_value_bool,
72cc5137
IM
254};
255
c7cc172d
JQ
256/* --- 8bit integer --- */
257
d7bce999
EB
258static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
259 Error **errp)
80e555c2 260{
b1987a25 261 const Property *prop = opaque;
1e198715 262 uint8_t *ptr = object_field_prop_ptr(obj, prop);
80e555c2 263
51e72bc1 264 visit_type_uint8(v, name, ptr, errp);
80e555c2
PB
265}
266
d7bce999
EB
267static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
268 Error **errp)
80e555c2 269{
b1987a25 270 const Property *prop = opaque;
1e198715 271 uint8_t *ptr = object_field_prop_ptr(obj, prop);
80e555c2 272
51e72bc1 273 visit_type_uint8(v, name, ptr, errp);
80e555c2
PB
274}
275
93e163e4
PMD
276void qdev_propinfo_set_default_value_int(ObjectProperty *op,
277 const Property *prop)
a2740ad5 278{
77b06bba 279 object_property_set_default_int(op, prop->defval.i);
a2740ad5
MAL
280}
281
93e163e4
PMD
282void qdev_propinfo_set_default_value_uint(ObjectProperty *op,
283 const Property *prop)
3fb2111f 284{
77b06bba 285 object_property_set_default_uint(op, prop->defval.u);
3fb2111f
MAL
286}
287
1b6b7d10 288const PropertyInfo qdev_prop_uint8 = {
c98dac16 289 .type = "uint8",
c08fb2ac
MR
290 .get = get_uint8,
291 .set = set_uint8,
93e163e4 292 .set_default_value = qdev_propinfo_set_default_value_uint,
c7cc172d
JQ
293};
294
ee6847d1
GH
295/* --- 16bit integer --- */
296
364f7e83
EH
297static void get_uint16(Object *obj, Visitor *v, const char *name,
298 void *opaque, Error **errp)
80e555c2 299{
b1987a25 300 const Property *prop = opaque;
1e198715 301 uint16_t *ptr = object_field_prop_ptr(obj, prop);
80e555c2 302
51e72bc1 303 visit_type_uint16(v, name, ptr, errp);
80e555c2
PB
304}
305
d7bce999
EB
306static void set_uint16(Object *obj, Visitor *v, const char *name,
307 void *opaque, Error **errp)
80e555c2 308{
b1987a25 309 const Property *prop = opaque;
1e198715 310 uint16_t *ptr = object_field_prop_ptr(obj, prop);
80e555c2 311
51e72bc1 312 visit_type_uint16(v, name, ptr, errp);
80e555c2
PB
313}
314
1b6b7d10 315const PropertyInfo qdev_prop_uint16 = {
c98dac16 316 .type = "uint16",
364f7e83 317 .get = get_uint16,
c08fb2ac 318 .set = set_uint16,
93e163e4 319 .set_default_value = qdev_propinfo_set_default_value_uint,
ee6847d1
GH
320};
321
322/* --- 32bit integer --- */
323
d7bce999
EB
324static void get_uint32(Object *obj, Visitor *v, const char *name,
325 void *opaque, Error **errp)
c08fb2ac 326{
b1987a25 327 const Property *prop = opaque;
1e198715 328 uint32_t *ptr = object_field_prop_ptr(obj, prop);
c08fb2ac 329
51e72bc1 330 visit_type_uint32(v, name, ptr, errp);
c08fb2ac
MR
331}
332
d7bce999
EB
333static void set_uint32(Object *obj, Visitor *v, const char *name,
334 void *opaque, Error **errp)
c08fb2ac 335{
b1987a25 336 const Property *prop = opaque;
1e198715 337 uint32_t *ptr = object_field_prop_ptr(obj, prop);
c08fb2ac 338
51e72bc1 339 visit_type_uint32(v, name, ptr, errp);
c08fb2ac
MR
340}
341
93e163e4
PMD
342void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name,
343 void *opaque, Error **errp)
80e555c2 344{
b1987a25 345 const Property *prop = opaque;
1e198715 346 int32_t *ptr = object_field_prop_ptr(obj, prop);
80e555c2 347
51e72bc1 348 visit_type_int32(v, name, ptr, errp);
80e555c2
PB
349}
350
d7bce999
EB
351static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
352 Error **errp)
80e555c2 353{
b1987a25 354 const Property *prop = opaque;
1e198715 355 int32_t *ptr = object_field_prop_ptr(obj, prop);
80e555c2 356
51e72bc1 357 visit_type_int32(v, name, ptr, errp);
80e555c2
PB
358}
359
1b6b7d10 360const PropertyInfo qdev_prop_uint32 = {
c98dac16 361 .type = "uint32",
c08fb2ac
MR
362 .get = get_uint32,
363 .set = set_uint32,
93e163e4 364 .set_default_value = qdev_propinfo_set_default_value_uint,
ee6847d1
GH
365};
366
1b6b7d10 367const PropertyInfo qdev_prop_int32 = {
c98dac16 368 .type = "int32",
93e163e4 369 .get = qdev_propinfo_get_int32,
80e555c2 370 .set = set_int32,
93e163e4 371 .set_default_value = qdev_propinfo_set_default_value_int,
316940b0
GH
372};
373
5a053d1f
BS
374/* --- 64bit integer --- */
375
d7bce999
EB
376static void get_uint64(Object *obj, Visitor *v, const char *name,
377 void *opaque, Error **errp)
80e555c2 378{
b1987a25 379 const Property *prop = opaque;
1e198715 380 uint64_t *ptr = object_field_prop_ptr(obj, prop);
80e555c2 381
51e72bc1 382 visit_type_uint64(v, name, ptr, errp);
80e555c2
PB
383}
384
d7bce999
EB
385static void set_uint64(Object *obj, Visitor *v, const char *name,
386 void *opaque, Error **errp)
80e555c2 387{
b1987a25 388 const Property *prop = opaque;
1e198715 389 uint64_t *ptr = object_field_prop_ptr(obj, prop);
80e555c2 390
51e72bc1 391 visit_type_uint64(v, name, ptr, errp);
80e555c2
PB
392}
393
07d1d063
PX
394static void get_int64(Object *obj, Visitor *v, const char *name,
395 void *opaque, Error **errp)
396{
b1987a25 397 const Property *prop = opaque;
1e198715 398 int64_t *ptr = object_field_prop_ptr(obj, prop);
07d1d063
PX
399
400 visit_type_int64(v, name, ptr, errp);
401}
402
403static void set_int64(Object *obj, Visitor *v, const char *name,
404 void *opaque, Error **errp)
405{
b1987a25 406 const Property *prop = opaque;
1e198715 407 int64_t *ptr = object_field_prop_ptr(obj, prop);
07d1d063 408
07d1d063
PX
409 visit_type_int64(v, name, ptr, errp);
410}
411
1b6b7d10 412const PropertyInfo qdev_prop_uint64 = {
c98dac16 413 .type = "uint64",
c08fb2ac
MR
414 .get = get_uint64,
415 .set = set_uint64,
93e163e4 416 .set_default_value = qdev_propinfo_set_default_value_uint,
5a053d1f
BS
417};
418
07d1d063 419const PropertyInfo qdev_prop_int64 = {
c98dac16 420 .type = "int64",
07d1d063
PX
421 .get = get_int64,
422 .set = set_int64,
93e163e4 423 .set_default_value = qdev_propinfo_set_default_value_int,
07d1d063
PX
424};
425
18c22d71
YW
426static void set_uint64_checkmask(Object *obj, Visitor *v, const char *name,
427 void *opaque, Error **errp)
428{
b1987a25 429 const Property *prop = opaque;
18c22d71
YW
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
439const PropertyInfo qdev_prop_uint64_checkmask = {
c98dac16 440 .type = "uint64",
18c22d71
YW
441 .get = get_uint64,
442 .set = set_uint64_checkmask,
443};
444
7bda68e8
PB
445/* --- pointer-size integer --- */
446
447static 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
461static 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
475const 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
59419663
GH
482/* --- string --- */
483
dd0ba250 484static void release_string(Object *obj, const char *name, void *opaque)
d21357df 485{
b1987a25 486 const Property *prop = opaque;
1e198715 487 g_free(*(char **)object_field_prop_ptr(obj, prop));
d21357df
MA
488}
489
d7bce999
EB
490static void get_string(Object *obj, Visitor *v, const char *name,
491 void *opaque, Error **errp)
80e555c2 492{
b1987a25 493 const Property *prop = opaque;
1e198715 494 char **ptr = object_field_prop_ptr(obj, prop);
80e555c2
PB
495
496 if (!*ptr) {
497 char *str = (char *)"";
51e72bc1 498 visit_type_str(v, name, &str, errp);
80e555c2 499 } else {
51e72bc1 500 visit_type_str(v, name, ptr, errp);
80e555c2
PB
501 }
502}
503
d7bce999
EB
504static void set_string(Object *obj, Visitor *v, const char *name,
505 void *opaque, Error **errp)
80e555c2 506{
b1987a25 507 const Property *prop = opaque;
1e198715 508 char **ptr = object_field_prop_ptr(obj, prop);
80e555c2
PB
509 char *str;
510
668f62ec 511 if (!visit_type_str(v, name, &str, errp)) {
80e555c2
PB
512 return;
513 }
ef1e1e07 514 g_free(*ptr);
80e555c2
PB
515 *ptr = str;
516}
517
1b6b7d10 518const PropertyInfo qdev_prop_string = {
c98dac16 519 .type = "str",
dd0ba250 520 .release = release_string,
80e555c2
PB
521 .get = get_string,
522 .set = set_string,
59419663
GH
523};
524
55e8a154
MA
525/* --- on/off/auto --- */
526
1b6b7d10 527const PropertyInfo qdev_prop_on_off_auto = {
c98dac16 528 .type = "OnOffAuto",
55e8a154 529 .description = "on/off/auto",
f7abe0ec 530 .enum_table = &OnOffAuto_lookup,
a2974439
PMD
531 .get = qdev_propinfo_get_enum,
532 .set = qdev_propinfo_set_enum,
533 .set_default_value = qdev_propinfo_set_default_value_enum,
55e8a154
MA
534};
535
914e74cd
RK
536/* --- 32bit unsigned int 'size' type --- */
537
93e163e4
PMD
538void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name,
539 void *opaque, Error **errp)
031ffd9a 540{
b1987a25 541 const Property *prop = opaque;
1e198715 542 uint32_t *ptr = object_field_prop_ptr(obj, prop);
031ffd9a
RK
543 uint64_t value = *ptr;
544
545 visit_type_size(v, name, &value, errp);
546}
547
914e74cd
RK
548static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,
549 Error **errp)
550{
b1987a25 551 const Property *prop = opaque;
1e198715 552 uint32_t *ptr = object_field_prop_ptr(obj, prop);
914e74cd 553 uint64_t value;
914e74cd 554
668f62ec 555 if (!visit_type_size(v, name, &value, errp)) {
914e74cd
RK
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)",
5eb32b21 563 object_get_typename(obj), name, value, UINT32_MAX);
914e74cd
RK
564 return;
565 }
566
567 *ptr = value;
568}
569
570const PropertyInfo qdev_prop_size32 = {
c98dac16 571 .type = "size",
93e163e4 572 .get = qdev_propinfo_get_size32,
914e74cd 573 .set = set_size32,
93e163e4 574 .set_default_value = qdev_propinfo_set_default_value_uint,
914e74cd
RK
575};
576
0be6bfac
PM
577/* --- support for array properties --- */
578
b06f8b50
KW
579typedef struct ArrayElementList ArrayElementList;
580
581struct 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.
0be6bfac 590 */
b1987a25 591static Property array_elem_prop(Object *obj, const Property *parent_prop,
b06f8b50
KW
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.
0be6bfac 613 */
b06f8b50 614static void release_prop_array(Object *obj, const char *name, void *opaque)
0be6bfac 615{
b1987a25 616 const Property *prop = opaque;
b06f8b50
KW
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;
0be6bfac 630 }
0be6bfac
PM
631}
632
b06f8b50
KW
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 */
639static void set_prop_array(Object *obj, Visitor *v, const char *name,
640 void *opaque, Error **errp)
0be6bfac 641{
b06f8b50 642 ERRP_GUARD();
b1987a25 643 const Property *prop = opaque;
1e198715 644 uint32_t *alenptr = object_field_prop_ptr(obj, prop);
f405e3cd 645 void **arrayptr = (void *)obj + prop->arrayoffset;
b06f8b50
KW
646 ArrayElementList *list, *elem, *next;
647 const size_t size = sizeof(*list);
648 char *elemptr;
649 bool ok = true;
0be6bfac 650
0be6bfac
PM
651 if (*alenptr) {
652 error_setg(errp, "array size property %s may not be set more than once",
653 name);
654 return;
655 }
b06f8b50
KW
656
657 if (!visit_start_list(v, name, (GenericList **) &list, size, errp)) {
0be6bfac
PM
658 return;
659 }
b06f8b50
KW
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);
683out_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 }
0be6bfac
PM
697 return;
698 }
699
b06f8b50
KW
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.
0be6bfac 703 */
b06f8b50
KW
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}
0be6bfac 714
b06f8b50
KW
715static void get_prop_array(Object *obj, Visitor *v, const char *name,
716 void *opaque, Error **errp)
717{
718 ERRP_GUARD();
b1987a25 719 const Property *prop = opaque;
b06f8b50
KW
720 uint32_t *alenptr = object_field_prop_ptr(obj, prop);
721 void **arrayptr = (void *)obj + prop->arrayoffset;
50571883
KW
722 char *elemptr = *arrayptr;
723 ArrayElementList *list = NULL, *elem;
724 ArrayElementList **tail = &list;
725 const size_t size = sizeof(*list);
b06f8b50
KW
726 int i;
727 bool ok;
728
50571883
KW
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)) {
b06f8b50 740 return;
0be6bfac 741 }
b06f8b50 742
50571883
KW
743 elem = list;
744 while (elem) {
745 Property elem_prop = array_elem_prop(obj, prop, name, elem->value);
b06f8b50
KW
746 prop->arrayinfo->get(obj, v, NULL, &elem_prop, errp);
747 if (*errp) {
748 goto out_obj;
749 }
50571883
KW
750 elem = (ArrayElementList *) visit_next_list(v, (GenericList*) elem,
751 size);
b06f8b50
KW
752 }
753
754 /* visit_check_list() can only fail for input visitors */
755 ok = visit_check_list(v, errp);
756 assert(ok);
757
758out_obj:
759 visit_end_list(v, (void**) &list);
50571883
KW
760
761 while (list) {
762 elem = list;
763 list = elem->next;
764 g_free(elem);
765 }
0be6bfac
PM
766}
767
b06f8b50
KW
768static void default_prop_array(ObjectProperty *op, const Property *prop)
769{
770 object_property_set_default_list(op);
771}
772
773const PropertyInfo qdev_prop_array = {
c98dac16 774 .type = "list",
b06f8b50
KW
775 .get = get_prop_array,
776 .set = set_prop_array,
777 .release = release_prop_array,
778 .set_default_value = default_prop_array,
0be6bfac
PM
779};
780
ee6847d1
GH
781/* --- public helpers --- */
782
cb9f4b28 783static const Property *qdev_prop_walk(DeviceClass *cls, const char *name)
ee6847d1 784{
cb9f4b28
RH
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;
04a2d61e 789 }
ee6847d1
GH
790 }
791 return NULL;
792}
793
d36f165d 794static const Property *qdev_prop_find(DeviceState *dev, const char *name)
ee6847d1 795{
bce54474 796 ObjectClass *class;
d36f165d 797 const Property *prop;
ee6847d1
GH
798
799 /* device properties */
bce54474
PB
800 class = object_get_class(OBJECT(dev));
801 do {
cb9f4b28 802 prop = qdev_prop_walk(DEVICE_CLASS(class), name);
bce54474
PB
803 if (prop) {
804 return prop;
805 }
806 class = object_class_get_parent(class);
807 } while (class != object_class_by_name(TYPE_DEVICE));
ee6847d1
GH
808
809 return NULL;
810}
811
c7525b18 812void error_set_from_qdev_prop_error(Error **errp, int ret, Object *obj,
e68c2cb7 813 const char *name, const char *value)
7db4c4e8
PB
814{
815 switch (ret) {
816 case -EEXIST:
f231b88d 817 error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
e68c2cb7 818 object_get_typename(obj), name, value);
7db4c4e8
PB
819 break;
820 default:
821 case -EINVAL:
be842efb 822 error_setg(errp, "Property '%s.%s' doesn't take value '%s'",
e68c2cb7 823 object_get_typename(obj), name, value);
7db4c4e8
PB
824 break;
825 case -ENOENT:
f231b88d 826 error_setg(errp, "Property '%s.%s' can't find value '%s'",
e68c2cb7 827 object_get_typename(obj), name, value);
7db4c4e8
PB
828 break;
829 case 0:
830 break;
831 }
832}
833
f4594a3b
IY
834void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
835{
5325cc34 836 object_property_set_bool(OBJECT(dev), name, value, &error_abort);
f4594a3b
IY
837}
838
c7cc172d
JQ
839void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
840{
5325cc34 841 object_property_set_int(OBJECT(dev), name, value, &error_abort);
c7cc172d
JQ
842}
843
ee6847d1
GH
844void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
845{
5325cc34 846 object_property_set_int(OBJECT(dev), name, value, &error_abort);
ee6847d1
GH
847}
848
849void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
850{
5325cc34 851 object_property_set_int(OBJECT(dev), name, value, &error_abort);
ee6847d1
GH
852}
853
316940b0
GH
854void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
855{
5325cc34 856 object_property_set_int(OBJECT(dev), name, value, &error_abort);
316940b0
GH
857}
858
5a053d1f
BS
859void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
860{
5325cc34 861 object_property_set_int(OBJECT(dev), name, value, &error_abort);
5a053d1f
BS
862}
863
3b25597b 864void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
cc984673 865{
5325cc34 866 object_property_set_str(OBJECT(dev), name, value, &error_abort);
cc984673
MA
867}
868
9b170e60 869void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
4e4fa398 870{
d36f165d 871 const Property *prop;
9b170e60
PB
872
873 prop = qdev_prop_find(dev, name);
5325cc34 874 object_property_set_str(OBJECT(dev), name,
788b305c 875 qapi_enum_lookup(prop->info->enum_table, value),
5325cc34 876 &error_abort);
4e4fa398
JK
877}
878
32400a7e
KW
879void qdev_prop_set_array(DeviceState *dev, const char *name, QList *values)
880{
b06f8b50
KW
881 object_property_set_qobject(OBJECT(dev), name, QOBJECT(values),
882 &error_abort);
32400a7e
KW
883 qobject_unref(values);
884}
885
e12ca3ce
MAL
886static 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}
b6b61144 896
a404b612 897void qdev_prop_register_global(GlobalProperty *prop)
b6b61144 898{
e12ca3ce 899 g_ptr_array_add(global_props(), prop);
b6b61144
GH
900}
901
39501275 902const GlobalProperty *qdev_find_global_prop(Object *obj,
1bc13336
MA
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);
39501275 911 if (object_dynamic_cast(obj, p->driver)
1bc13336
MA
912 && !strcmp(p->property, name)) {
913 return p;
914 }
915 }
916 return NULL;
917}
918
d828c430 919int qdev_prop_check_globals(void)
9f9260a3 920{
e12ca3ce 921 int i, ret = 0;
9f9260a3 922
e12ca3ce
MAL
923 for (i = 0; i < global_props()->len; i++) {
924 GlobalProperty *prop;
b3ce84fe
EH
925 ObjectClass *oc;
926 DeviceClass *dc;
e12ca3ce
MAL
927
928 prop = g_ptr_array_index(global_props(), i);
b3ce84fe
EH
929 if (prop->used) {
930 continue;
931 }
b3ce84fe
EH
932 oc = object_class_by_name(prop->driver);
933 oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
934 if (!oc) {
3dc6f869
AF
935 warn_report("global %s.%s has invalid class name",
936 prop->driver, prop->property);
b3ce84fe
EH
937 ret = 1;
938 continue;
939 }
940 dc = DEVICE_CLASS(oc);
941 if (!dc->hotpluggable && !prop->used) {
3dc6f869
AF
942 warn_report("global %s.%s=%s not used",
943 prop->driver, prop->property, prop->value);
b3ce84fe 944 ret = 1;
9f9260a3
DS
945 continue;
946 }
9f9260a3
DS
947 }
948 return ret;
949}
950
5eb6a3c5 951void qdev_prop_set_globals(DeviceState *dev)
868d378b 952{
50545b2c
MAL
953 object_apply_global_props(OBJECT(dev), global_props(),
954 dev->hotplugged ? NULL : &error_fatal);
868d378b
AF
955}
956
e8cd45c7
VL
957/* --- 64bit unsigned int 'size' type --- */
958
d7bce999
EB
959static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
960 Error **errp)
e8cd45c7 961{
b1987a25 962 const Property *prop = opaque;
1e198715 963 uint64_t *ptr = object_field_prop_ptr(obj, prop);
e8cd45c7 964
51e72bc1 965 visit_type_size(v, name, ptr, errp);
e8cd45c7
VL
966}
967
d7bce999
EB
968static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
969 Error **errp)
e8cd45c7 970{
b1987a25 971 const Property *prop = opaque;
1e198715 972 uint64_t *ptr = object_field_prop_ptr(obj, prop);
e8cd45c7 973
51e72bc1 974 visit_type_size(v, name, ptr, errp);
e8cd45c7
VL
975}
976
1b6b7d10 977const PropertyInfo qdev_prop_size = {
c98dac16 978 .type = "size",
e8cd45c7
VL
979 .get = get_size,
980 .set = set_size,
93e163e4 981 .set_default_value = qdev_propinfo_set_default_value_uint,
e8cd45c7 982};
5b4ff3c6
FZ
983
984/* --- object link property --- */
985
f59c6d22 986static ObjectProperty *create_link_property(ObjectClass *oc, const char *name,
d36f165d 987 const Property *prop)
5b4ff3c6 988{
f59c6d22
EH
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);
5b4ff3c6
FZ
993}
994
1b6b7d10 995const PropertyInfo qdev_prop_link = {
c98dac16 996 .type = "link",
5b4ff3c6
FZ
997 .create = create_link_property,
998};
d3fd6e73 999
d36f165d 1000void qdev_property_add_static(DeviceState *dev, const Property *prop)
d3fd6e73
EH
1001{
1002 Object *obj = OBJECT(dev);
1003 ObjectProperty *op;
1004
1005 assert(!prop->info->create);
1006
c98dac16 1007 op = object_property_add(obj, prop->name, prop->info->type,
7ed854af
EH
1008 field_prop_getter(prop->info),
1009 field_prop_setter(prop->info),
d3fd6e73 1010 prop->info->release,
d36f165d 1011 (Property *)prop);
d3fd6e73
EH
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
23a1dae8 1024static void qdev_class_add_property(DeviceClass *klass, const char *name,
d36f165d 1025 const Property *prop)
d3fd6e73
EH
1026{
1027 ObjectClass *oc = OBJECT_CLASS(klass);
0d5d5bc5 1028 ObjectProperty *op;
d3fd6e73
EH
1029
1030 if (prop->info->create) {
0d5d5bc5 1031 op = prop->info->create(oc, name, prop);
d3fd6e73 1032 } else {
d3fd6e73 1033 op = object_class_property_add(oc,
c98dac16 1034 name, prop->info->type,
7ed854af
EH
1035 field_prop_getter(prop->info),
1036 field_prop_setter(prop->info),
d3fd6e73 1037 prop->info->release,
d36f165d 1038 (Property *)prop);
d3fd6e73 1039 }
0d5d5bc5
EH
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);
d3fd6e73
EH
1044}
1045
1046/**
1047 * Legacy property handling
1048 */
1049
1050static void qdev_get_legacy_property(Object *obj, Visitor *v,
1051 const char *name, void *opaque,
1052 Error **errp)
1053{
b1987a25 1054 const Property *prop = opaque;
d3fd6e73
EH
1055
1056 char buffer[1024];
1057 char *ptr = buffer;
1058
40ea00b0 1059 prop->info->print(obj, prop, buffer, sizeof(buffer));
d3fd6e73
EH
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 */
d36f165d 1077static void qdev_class_add_legacy_property(DeviceClass *dc, const Property *prop)
d3fd6e73
EH
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,
d36f165d 1089 NULL, NULL, (Property *)prop);
d3fd6e73
EH
1090}
1091
cb9f4b28
RH
1092void 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);
d3fd6e73
EH
1097
1098 dc->props_ = props;
cb9f4b28
RH
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);
d3fd6e73 1104 qdev_class_add_legacy_property(dc, prop);
23a1dae8 1105 qdev_class_add_property(dc, prop->name, prop);
d3fd6e73
EH
1106 }
1107}
1108
1109void qdev_alias_all_properties(DeviceState *target, Object *source)
1110{
1111 ObjectClass *class;
350147a8
SH
1112 ObjectPropertyIterator iter;
1113 ObjectProperty *prop;
d3fd6e73
EH
1114
1115 class = object_get_class(OBJECT(target));
d3fd6e73 1116
350147a8
SH
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 */
d3fd6e73 1121 }
350147a8
SH
1122
1123 object_property_add_alias(source, prop->name,
1124 OBJECT(target), prop->name);
1125 }
d3fd6e73 1126}