]> git.proxmox.com Git - mirror_qemu.git/blob - hw/core/qdev-properties.c
Merge remote-tracking branch 'remotes/stefanha/tags/qtest-monitor-process-pull-reques...
[mirror_qemu.git] / hw / core / qdev-properties.c
1 #include "net/net.h"
2 #include "hw/qdev.h"
3 #include "qapi/qmp/qerror.h"
4 #include "sysemu/blockdev.h"
5 #include "hw/block/block.h"
6 #include "net/hub.h"
7 #include "qapi/visitor.h"
8 #include "sysemu/char.h"
9
10 void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
11 Error **errp)
12 {
13 if (dev->id) {
14 error_setg(errp, "Attempt to set property '%s' on device '%s' "
15 "(type '%s') after it was realized", name, dev->id,
16 object_get_typename(OBJECT(dev)));
17 } else {
18 error_setg(errp, "Attempt to set property '%s' on anonymous device "
19 "(type '%s') after it was realized", name,
20 object_get_typename(OBJECT(dev)));
21 }
22 }
23
24 void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
25 {
26 void *ptr = dev;
27 ptr += prop->offset;
28 return ptr;
29 }
30
31 static void get_enum(Object *obj, Visitor *v, void *opaque,
32 const char *name, Error **errp)
33 {
34 DeviceState *dev = DEVICE(obj);
35 Property *prop = opaque;
36 int *ptr = qdev_get_prop_ptr(dev, prop);
37
38 visit_type_enum(v, ptr, prop->info->enum_table,
39 prop->info->name, prop->name, errp);
40 }
41
42 static void set_enum(Object *obj, Visitor *v, void *opaque,
43 const char *name, Error **errp)
44 {
45 DeviceState *dev = DEVICE(obj);
46 Property *prop = opaque;
47 int *ptr = qdev_get_prop_ptr(dev, prop);
48
49 if (dev->realized) {
50 qdev_prop_set_after_realize(dev, name, errp);
51 return;
52 }
53
54 visit_type_enum(v, ptr, prop->info->enum_table,
55 prop->info->name, prop->name, errp);
56 }
57
58 /* Bit */
59
60 static uint32_t qdev_get_prop_mask(Property *prop)
61 {
62 assert(prop->info == &qdev_prop_bit);
63 return 0x1 << prop->bitnr;
64 }
65
66 static void bit_prop_set(DeviceState *dev, Property *props, bool val)
67 {
68 uint32_t *p = qdev_get_prop_ptr(dev, props);
69 uint32_t mask = qdev_get_prop_mask(props);
70 if (val) {
71 *p |= mask;
72 } else {
73 *p &= ~mask;
74 }
75 }
76
77 static void prop_get_bit(Object *obj, Visitor *v, void *opaque,
78 const char *name, Error **errp)
79 {
80 DeviceState *dev = DEVICE(obj);
81 Property *prop = opaque;
82 uint32_t *p = qdev_get_prop_ptr(dev, prop);
83 bool value = (*p & qdev_get_prop_mask(prop)) != 0;
84
85 visit_type_bool(v, &value, name, errp);
86 }
87
88 static void prop_set_bit(Object *obj, Visitor *v, void *opaque,
89 const char *name, Error **errp)
90 {
91 DeviceState *dev = DEVICE(obj);
92 Property *prop = opaque;
93 Error *local_err = NULL;
94 bool value;
95
96 if (dev->realized) {
97 qdev_prop_set_after_realize(dev, name, errp);
98 return;
99 }
100
101 visit_type_bool(v, &value, name, &local_err);
102 if (local_err) {
103 error_propagate(errp, local_err);
104 return;
105 }
106 bit_prop_set(dev, prop, value);
107 }
108
109 PropertyInfo qdev_prop_bit = {
110 .name = "bool",
111 .legacy_name = "on/off",
112 .get = prop_get_bit,
113 .set = prop_set_bit,
114 };
115
116 /* --- bool --- */
117
118 static void get_bool(Object *obj, Visitor *v, void *opaque,
119 const char *name, Error **errp)
120 {
121 DeviceState *dev = DEVICE(obj);
122 Property *prop = opaque;
123 bool *ptr = qdev_get_prop_ptr(dev, prop);
124
125 visit_type_bool(v, ptr, name, errp);
126 }
127
128 static void set_bool(Object *obj, Visitor *v, void *opaque,
129 const char *name, Error **errp)
130 {
131 DeviceState *dev = DEVICE(obj);
132 Property *prop = opaque;
133 bool *ptr = qdev_get_prop_ptr(dev, prop);
134
135 if (dev->realized) {
136 qdev_prop_set_after_realize(dev, name, errp);
137 return;
138 }
139
140 visit_type_bool(v, ptr, name, errp);
141 }
142
143 PropertyInfo qdev_prop_bool = {
144 .name = "bool",
145 .get = get_bool,
146 .set = set_bool,
147 };
148
149 /* --- 8bit integer --- */
150
151 static void get_uint8(Object *obj, Visitor *v, void *opaque,
152 const char *name, Error **errp)
153 {
154 DeviceState *dev = DEVICE(obj);
155 Property *prop = opaque;
156 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
157
158 visit_type_uint8(v, ptr, name, errp);
159 }
160
161 static void set_uint8(Object *obj, Visitor *v, void *opaque,
162 const char *name, Error **errp)
163 {
164 DeviceState *dev = DEVICE(obj);
165 Property *prop = opaque;
166 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
167
168 if (dev->realized) {
169 qdev_prop_set_after_realize(dev, name, errp);
170 return;
171 }
172
173 visit_type_uint8(v, ptr, name, errp);
174 }
175
176 PropertyInfo qdev_prop_uint8 = {
177 .name = "uint8",
178 .get = get_uint8,
179 .set = set_uint8,
180 };
181
182 /* --- 16bit integer --- */
183
184 static void get_uint16(Object *obj, Visitor *v, void *opaque,
185 const char *name, Error **errp)
186 {
187 DeviceState *dev = DEVICE(obj);
188 Property *prop = opaque;
189 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
190
191 visit_type_uint16(v, ptr, name, errp);
192 }
193
194 static void set_uint16(Object *obj, Visitor *v, void *opaque,
195 const char *name, Error **errp)
196 {
197 DeviceState *dev = DEVICE(obj);
198 Property *prop = opaque;
199 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
200
201 if (dev->realized) {
202 qdev_prop_set_after_realize(dev, name, errp);
203 return;
204 }
205
206 visit_type_uint16(v, ptr, name, errp);
207 }
208
209 PropertyInfo qdev_prop_uint16 = {
210 .name = "uint16",
211 .get = get_uint16,
212 .set = set_uint16,
213 };
214
215 /* --- 32bit integer --- */
216
217 static void get_uint32(Object *obj, Visitor *v, void *opaque,
218 const char *name, Error **errp)
219 {
220 DeviceState *dev = DEVICE(obj);
221 Property *prop = opaque;
222 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
223
224 visit_type_uint32(v, ptr, name, errp);
225 }
226
227 static void set_uint32(Object *obj, Visitor *v, void *opaque,
228 const char *name, Error **errp)
229 {
230 DeviceState *dev = DEVICE(obj);
231 Property *prop = opaque;
232 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
233
234 if (dev->realized) {
235 qdev_prop_set_after_realize(dev, name, errp);
236 return;
237 }
238
239 visit_type_uint32(v, ptr, name, errp);
240 }
241
242 static void get_int32(Object *obj, Visitor *v, void *opaque,
243 const char *name, Error **errp)
244 {
245 DeviceState *dev = DEVICE(obj);
246 Property *prop = opaque;
247 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
248
249 visit_type_int32(v, ptr, name, errp);
250 }
251
252 static void set_int32(Object *obj, Visitor *v, void *opaque,
253 const char *name, Error **errp)
254 {
255 DeviceState *dev = DEVICE(obj);
256 Property *prop = opaque;
257 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
258
259 if (dev->realized) {
260 qdev_prop_set_after_realize(dev, name, errp);
261 return;
262 }
263
264 visit_type_int32(v, ptr, name, errp);
265 }
266
267 PropertyInfo qdev_prop_uint32 = {
268 .name = "uint32",
269 .get = get_uint32,
270 .set = set_uint32,
271 };
272
273 PropertyInfo qdev_prop_int32 = {
274 .name = "int32",
275 .get = get_int32,
276 .set = set_int32,
277 };
278
279 /* --- 64bit integer --- */
280
281 static void get_uint64(Object *obj, Visitor *v, void *opaque,
282 const char *name, Error **errp)
283 {
284 DeviceState *dev = DEVICE(obj);
285 Property *prop = opaque;
286 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
287
288 visit_type_uint64(v, ptr, name, errp);
289 }
290
291 static void set_uint64(Object *obj, Visitor *v, void *opaque,
292 const char *name, Error **errp)
293 {
294 DeviceState *dev = DEVICE(obj);
295 Property *prop = opaque;
296 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
297
298 if (dev->realized) {
299 qdev_prop_set_after_realize(dev, name, errp);
300 return;
301 }
302
303 visit_type_uint64(v, ptr, name, errp);
304 }
305
306 PropertyInfo qdev_prop_uint64 = {
307 .name = "uint64",
308 .get = get_uint64,
309 .set = set_uint64,
310 };
311
312 /* --- string --- */
313
314 static void release_string(Object *obj, const char *name, void *opaque)
315 {
316 Property *prop = opaque;
317 g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
318 }
319
320 static void get_string(Object *obj, Visitor *v, void *opaque,
321 const char *name, Error **errp)
322 {
323 DeviceState *dev = DEVICE(obj);
324 Property *prop = opaque;
325 char **ptr = qdev_get_prop_ptr(dev, prop);
326
327 if (!*ptr) {
328 char *str = (char *)"";
329 visit_type_str(v, &str, name, errp);
330 } else {
331 visit_type_str(v, ptr, name, errp);
332 }
333 }
334
335 static void set_string(Object *obj, Visitor *v, void *opaque,
336 const char *name, Error **errp)
337 {
338 DeviceState *dev = DEVICE(obj);
339 Property *prop = opaque;
340 char **ptr = qdev_get_prop_ptr(dev, prop);
341 Error *local_err = NULL;
342 char *str;
343
344 if (dev->realized) {
345 qdev_prop_set_after_realize(dev, name, errp);
346 return;
347 }
348
349 visit_type_str(v, &str, name, &local_err);
350 if (local_err) {
351 error_propagate(errp, local_err);
352 return;
353 }
354 if (*ptr) {
355 g_free(*ptr);
356 }
357 *ptr = str;
358 }
359
360 PropertyInfo qdev_prop_string = {
361 .name = "str",
362 .release = release_string,
363 .get = get_string,
364 .set = set_string,
365 };
366
367 /* --- pointer --- */
368
369 /* Not a proper property, just for dirty hacks. TODO Remove it! */
370 PropertyInfo qdev_prop_ptr = {
371 .name = "ptr",
372 };
373
374 /* --- mac address --- */
375
376 /*
377 * accepted syntax versions:
378 * 01:02:03:04:05:06
379 * 01-02-03-04-05-06
380 */
381 static void get_mac(Object *obj, Visitor *v, void *opaque,
382 const char *name, Error **errp)
383 {
384 DeviceState *dev = DEVICE(obj);
385 Property *prop = opaque;
386 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
387 char buffer[2 * 6 + 5 + 1];
388 char *p = buffer;
389
390 snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
391 mac->a[0], mac->a[1], mac->a[2],
392 mac->a[3], mac->a[4], mac->a[5]);
393
394 visit_type_str(v, &p, name, errp);
395 }
396
397 static void set_mac(Object *obj, Visitor *v, void *opaque,
398 const char *name, Error **errp)
399 {
400 DeviceState *dev = DEVICE(obj);
401 Property *prop = opaque;
402 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
403 Error *local_err = NULL;
404 int i, pos;
405 char *str, *p;
406
407 if (dev->realized) {
408 qdev_prop_set_after_realize(dev, name, errp);
409 return;
410 }
411
412 visit_type_str(v, &str, name, &local_err);
413 if (local_err) {
414 error_propagate(errp, local_err);
415 return;
416 }
417
418 for (i = 0, pos = 0; i < 6; i++, pos += 3) {
419 if (!qemu_isxdigit(str[pos])) {
420 goto inval;
421 }
422 if (!qemu_isxdigit(str[pos+1])) {
423 goto inval;
424 }
425 if (i == 5) {
426 if (str[pos+2] != '\0') {
427 goto inval;
428 }
429 } else {
430 if (str[pos+2] != ':' && str[pos+2] != '-') {
431 goto inval;
432 }
433 }
434 mac->a[i] = strtol(str+pos, &p, 16);
435 }
436 g_free(str);
437 return;
438
439 inval:
440 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
441 g_free(str);
442 }
443
444 PropertyInfo qdev_prop_macaddr = {
445 .name = "str",
446 .legacy_name = "macaddr",
447 .get = get_mac,
448 .set = set_mac,
449 };
450
451 /* --- lost tick policy --- */
452
453 QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
454
455 PropertyInfo qdev_prop_losttickpolicy = {
456 .name = "LostTickPolicy",
457 .enum_table = LostTickPolicy_lookup,
458 .get = get_enum,
459 .set = set_enum,
460 };
461
462 /* --- BIOS CHS translation */
463
464 QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
465
466 PropertyInfo qdev_prop_bios_chs_trans = {
467 .name = "BiosAtaTranslation",
468 .legacy_name = "bios-chs-trans",
469 .enum_table = BiosAtaTranslation_lookup,
470 .get = get_enum,
471 .set = set_enum,
472 };
473
474 /* --- pci address --- */
475
476 /*
477 * bus-local address, i.e. "$slot" or "$slot.$fn"
478 */
479 static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
480 const char *name, Error **errp)
481 {
482 DeviceState *dev = DEVICE(obj);
483 Property *prop = opaque;
484 int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
485 unsigned int slot, fn, n;
486 Error *local_err = NULL;
487 char *str;
488
489 if (dev->realized) {
490 qdev_prop_set_after_realize(dev, name, errp);
491 return;
492 }
493
494 visit_type_str(v, &str, name, &local_err);
495 if (local_err) {
496 error_free(local_err);
497 local_err = NULL;
498 visit_type_int32(v, &value, name, &local_err);
499 if (local_err) {
500 error_propagate(errp, local_err);
501 } else if (value < -1 || value > 255) {
502 error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
503 "pci_devfn");
504 } else {
505 *ptr = value;
506 }
507 return;
508 }
509
510 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
511 fn = 0;
512 if (sscanf(str, "%x%n", &slot, &n) != 1) {
513 goto invalid;
514 }
515 }
516 if (str[n] != '\0' || fn > 7 || slot > 31) {
517 goto invalid;
518 }
519 *ptr = slot << 3 | fn;
520 g_free(str);
521 return;
522
523 invalid:
524 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
525 g_free(str);
526 }
527
528 static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
529 size_t len)
530 {
531 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
532
533 if (*ptr == -1) {
534 return snprintf(dest, len, "<unset>");
535 } else {
536 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
537 }
538 }
539
540 PropertyInfo qdev_prop_pci_devfn = {
541 .name = "int32",
542 .legacy_name = "pci-devfn",
543 .print = print_pci_devfn,
544 .get = get_int32,
545 .set = set_pci_devfn,
546 };
547
548 /* --- blocksize --- */
549
550 static void set_blocksize(Object *obj, Visitor *v, void *opaque,
551 const char *name, Error **errp)
552 {
553 DeviceState *dev = DEVICE(obj);
554 Property *prop = opaque;
555 uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
556 Error *local_err = NULL;
557 const int64_t min = 512;
558 const int64_t max = 32768;
559
560 if (dev->realized) {
561 qdev_prop_set_after_realize(dev, name, errp);
562 return;
563 }
564
565 visit_type_uint16(v, &value, name, &local_err);
566 if (local_err) {
567 error_propagate(errp, local_err);
568 return;
569 }
570 if (value < min || value > max) {
571 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
572 dev->id?:"", name, (int64_t)value, min, max);
573 return;
574 }
575
576 /* We rely on power-of-2 blocksizes for bitmasks */
577 if ((value & (value - 1)) != 0) {
578 error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
579 dev->id?:"", name, (int64_t)value);
580 return;
581 }
582
583 *ptr = value;
584 }
585
586 PropertyInfo qdev_prop_blocksize = {
587 .name = "uint16",
588 .legacy_name = "blocksize",
589 .get = get_uint16,
590 .set = set_blocksize,
591 };
592
593 /* --- pci host address --- */
594
595 static void get_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
596 const char *name, Error **errp)
597 {
598 DeviceState *dev = DEVICE(obj);
599 Property *prop = opaque;
600 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
601 char buffer[] = "xxxx:xx:xx.x";
602 char *p = buffer;
603 int rc = 0;
604
605 rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
606 addr->domain, addr->bus, addr->slot, addr->function);
607 assert(rc == sizeof(buffer) - 1);
608
609 visit_type_str(v, &p, name, errp);
610 }
611
612 /*
613 * Parse [<domain>:]<bus>:<slot>.<func>
614 * if <domain> is not supplied, it's assumed to be 0.
615 */
616 static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
617 const char *name, Error **errp)
618 {
619 DeviceState *dev = DEVICE(obj);
620 Property *prop = opaque;
621 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
622 Error *local_err = NULL;
623 char *str, *p;
624 char *e;
625 unsigned long val;
626 unsigned long dom = 0, bus = 0;
627 unsigned int slot = 0, func = 0;
628
629 if (dev->realized) {
630 qdev_prop_set_after_realize(dev, name, errp);
631 return;
632 }
633
634 visit_type_str(v, &str, name, &local_err);
635 if (local_err) {
636 error_propagate(errp, local_err);
637 return;
638 }
639
640 p = str;
641 val = strtoul(p, &e, 16);
642 if (e == p || *e != ':') {
643 goto inval;
644 }
645 bus = val;
646
647 p = e + 1;
648 val = strtoul(p, &e, 16);
649 if (e == p) {
650 goto inval;
651 }
652 if (*e == ':') {
653 dom = bus;
654 bus = val;
655 p = e + 1;
656 val = strtoul(p, &e, 16);
657 if (e == p) {
658 goto inval;
659 }
660 }
661 slot = val;
662
663 if (*e != '.') {
664 goto inval;
665 }
666 p = e + 1;
667 val = strtoul(p, &e, 10);
668 if (e == p) {
669 goto inval;
670 }
671 func = val;
672
673 if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
674 goto inval;
675 }
676
677 if (*e) {
678 goto inval;
679 }
680
681 addr->domain = dom;
682 addr->bus = bus;
683 addr->slot = slot;
684 addr->function = func;
685
686 g_free(str);
687 return;
688
689 inval:
690 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
691 g_free(str);
692 }
693
694 PropertyInfo qdev_prop_pci_host_devaddr = {
695 .name = "str",
696 .legacy_name = "pci-host-devaddr",
697 .get = get_pci_host_devaddr,
698 .set = set_pci_host_devaddr,
699 };
700
701 /* --- support for array properties --- */
702
703 /* Used as an opaque for the object properties we add for each
704 * array element. Note that the struct Property must be first
705 * in the struct so that a pointer to this works as the opaque
706 * for the underlying element's property hooks as well as for
707 * our own release callback.
708 */
709 typedef struct {
710 struct Property prop;
711 char *propname;
712 ObjectPropertyRelease *release;
713 } ArrayElementProperty;
714
715 /* object property release callback for array element properties:
716 * we call the underlying element's property release hook, and
717 * then free the memory we allocated when we added the property.
718 */
719 static void array_element_release(Object *obj, const char *name, void *opaque)
720 {
721 ArrayElementProperty *p = opaque;
722 if (p->release) {
723 p->release(obj, name, opaque);
724 }
725 g_free(p->propname);
726 g_free(p);
727 }
728
729 static void set_prop_arraylen(Object *obj, Visitor *v, void *opaque,
730 const char *name, Error **errp)
731 {
732 /* Setter for the property which defines the length of a
733 * variable-sized property array. As well as actually setting the
734 * array-length field in the device struct, we have to create the
735 * array itself and dynamically add the corresponding properties.
736 */
737 DeviceState *dev = DEVICE(obj);
738 Property *prop = opaque;
739 uint32_t *alenptr = qdev_get_prop_ptr(dev, prop);
740 void **arrayptr = (void *)dev + prop->arrayoffset;
741 void *eltptr;
742 const char *arrayname;
743 int i;
744
745 if (dev->realized) {
746 qdev_prop_set_after_realize(dev, name, errp);
747 return;
748 }
749 if (*alenptr) {
750 error_setg(errp, "array size property %s may not be set more than once",
751 name);
752 return;
753 }
754 visit_type_uint32(v, alenptr, name, errp);
755 if (error_is_set(errp)) {
756 return;
757 }
758 if (!*alenptr) {
759 return;
760 }
761
762 /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
763 * strip it off so we can get the name of the array itself.
764 */
765 assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
766 strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
767 arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
768
769 /* Note that it is the responsibility of the individual device's deinit
770 * to free the array proper.
771 */
772 *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
773 for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
774 char *propname = g_strdup_printf("%s[%d]", arrayname, i);
775 ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
776 arrayprop->release = prop->arrayinfo->release;
777 arrayprop->propname = propname;
778 arrayprop->prop.info = prop->arrayinfo;
779 arrayprop->prop.name = propname;
780 /* This ugly piece of pointer arithmetic sets up the offset so
781 * that when the underlying get/set hooks call qdev_get_prop_ptr
782 * they get the right answer despite the array element not actually
783 * being inside the device struct.
784 */
785 arrayprop->prop.offset = eltptr - (void *)dev;
786 assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr);
787 object_property_add(obj, propname,
788 arrayprop->prop.info->name,
789 arrayprop->prop.info->get,
790 arrayprop->prop.info->set,
791 array_element_release,
792 arrayprop, errp);
793 if (error_is_set(errp)) {
794 return;
795 }
796 }
797 }
798
799 PropertyInfo qdev_prop_arraylen = {
800 .name = "uint32",
801 .get = get_uint32,
802 .set = set_prop_arraylen,
803 };
804
805 /* --- public helpers --- */
806
807 static Property *qdev_prop_walk(Property *props, const char *name)
808 {
809 if (!props) {
810 return NULL;
811 }
812 while (props->name) {
813 if (strcmp(props->name, name) == 0) {
814 return props;
815 }
816 props++;
817 }
818 return NULL;
819 }
820
821 static Property *qdev_prop_find(DeviceState *dev, const char *name)
822 {
823 ObjectClass *class;
824 Property *prop;
825
826 /* device properties */
827 class = object_get_class(OBJECT(dev));
828 do {
829 prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
830 if (prop) {
831 return prop;
832 }
833 class = object_class_get_parent(class);
834 } while (class != object_class_by_name(TYPE_DEVICE));
835
836 return NULL;
837 }
838
839 void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
840 Property *prop, const char *value)
841 {
842 switch (ret) {
843 case -EEXIST:
844 error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
845 object_get_typename(OBJECT(dev)), prop->name, value);
846 break;
847 default:
848 case -EINVAL:
849 error_set(errp, QERR_PROPERTY_VALUE_BAD,
850 object_get_typename(OBJECT(dev)), prop->name, value);
851 break;
852 case -ENOENT:
853 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
854 object_get_typename(OBJECT(dev)), prop->name, value);
855 break;
856 case 0:
857 break;
858 }
859 }
860
861 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
862 {
863 object_property_set_bool(OBJECT(dev), value, name, &error_abort);
864 }
865
866 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
867 {
868 object_property_set_int(OBJECT(dev), value, name, &error_abort);
869 }
870
871 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
872 {
873 object_property_set_int(OBJECT(dev), value, name, &error_abort);
874 }
875
876 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
877 {
878 object_property_set_int(OBJECT(dev), value, name, &error_abort);
879 }
880
881 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
882 {
883 object_property_set_int(OBJECT(dev), value, name, &error_abort);
884 }
885
886 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
887 {
888 object_property_set_int(OBJECT(dev), value, name, &error_abort);
889 }
890
891 void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
892 {
893 object_property_set_str(OBJECT(dev), value, name, &error_abort);
894 }
895
896 void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
897 {
898 char str[2 * 6 + 5 + 1];
899 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
900 value[0], value[1], value[2], value[3], value[4], value[5]);
901
902 object_property_set_str(OBJECT(dev), str, name, &error_abort);
903 }
904
905 void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
906 {
907 Property *prop;
908
909 prop = qdev_prop_find(dev, name);
910 object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
911 name, &error_abort);
912 }
913
914 void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
915 {
916 Property *prop;
917 void **ptr;
918
919 prop = qdev_prop_find(dev, name);
920 assert(prop && prop->info == &qdev_prop_ptr);
921 ptr = qdev_get_prop_ptr(dev, prop);
922 *ptr = value;
923 }
924
925 static QTAILQ_HEAD(, GlobalProperty) global_props =
926 QTAILQ_HEAD_INITIALIZER(global_props);
927
928 void qdev_prop_register_global(GlobalProperty *prop)
929 {
930 QTAILQ_INSERT_TAIL(&global_props, prop, next);
931 }
932
933 void qdev_prop_register_global_list(GlobalProperty *props)
934 {
935 int i;
936
937 for (i = 0; props[i].driver != NULL; i++) {
938 qdev_prop_register_global(props+i);
939 }
940 }
941
942 void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
943 Error **errp)
944 {
945 GlobalProperty *prop;
946
947 QTAILQ_FOREACH(prop, &global_props, next) {
948 Error *err = NULL;
949
950 if (strcmp(typename, prop->driver) != 0) {
951 continue;
952 }
953 object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
954 if (err != NULL) {
955 error_propagate(errp, err);
956 return;
957 }
958 }
959 }
960
961 void qdev_prop_set_globals(DeviceState *dev, Error **errp)
962 {
963 ObjectClass *class = object_get_class(OBJECT(dev));
964
965 do {
966 Error *err = NULL;
967
968 qdev_prop_set_globals_for_type(dev, object_class_get_name(class),
969 &err);
970 if (err != NULL) {
971 error_propagate(errp, err);
972 return;
973 }
974 class = object_class_get_parent(class);
975 } while (class);
976 }
977
978 /* --- 64bit unsigned int 'size' type --- */
979
980 static void get_size(Object *obj, Visitor *v, void *opaque,
981 const char *name, Error **errp)
982 {
983 DeviceState *dev = DEVICE(obj);
984 Property *prop = opaque;
985 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
986
987 visit_type_size(v, ptr, name, errp);
988 }
989
990 static void set_size(Object *obj, Visitor *v, void *opaque,
991 const char *name, Error **errp)
992 {
993 DeviceState *dev = DEVICE(obj);
994 Property *prop = opaque;
995 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
996
997 visit_type_size(v, ptr, name, errp);
998 }
999
1000 PropertyInfo qdev_prop_size = {
1001 .name = "size",
1002 .get = get_size,
1003 .set = set_size,
1004 };