]> git.proxmox.com Git - mirror_qemu.git/blob - hw/core/qdev-properties.c
qdev: Remove hex8/32/64 property types
[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 = "boolean",
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 = "boolean",
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 = "string",
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 = "macaddr",
446 .get = get_mac,
447 .set = set_mac,
448 };
449
450 /* --- lost tick policy --- */
451
452 static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
453 [LOST_TICK_DISCARD] = "discard",
454 [LOST_TICK_DELAY] = "delay",
455 [LOST_TICK_MERGE] = "merge",
456 [LOST_TICK_SLEW] = "slew",
457 [LOST_TICK_MAX] = NULL,
458 };
459
460 QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
461
462 PropertyInfo qdev_prop_losttickpolicy = {
463 .name = "LostTickPolicy",
464 .enum_table = lost_tick_policy_table,
465 .get = get_enum,
466 .set = set_enum,
467 };
468
469 /* --- BIOS CHS translation */
470
471 static const char *bios_chs_trans_table[] = {
472 [BIOS_ATA_TRANSLATION_AUTO] = "auto",
473 [BIOS_ATA_TRANSLATION_NONE] = "none",
474 [BIOS_ATA_TRANSLATION_LBA] = "lba",
475 };
476
477 PropertyInfo qdev_prop_bios_chs_trans = {
478 .name = "bios-chs-trans",
479 .enum_table = bios_chs_trans_table,
480 .get = get_enum,
481 .set = set_enum,
482 };
483
484 /* --- pci address --- */
485
486 /*
487 * bus-local address, i.e. "$slot" or "$slot.$fn"
488 */
489 static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
490 const char *name, Error **errp)
491 {
492 DeviceState *dev = DEVICE(obj);
493 Property *prop = opaque;
494 int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
495 unsigned int slot, fn, n;
496 Error *local_err = NULL;
497 char *str;
498
499 if (dev->realized) {
500 qdev_prop_set_after_realize(dev, name, errp);
501 return;
502 }
503
504 visit_type_str(v, &str, name, &local_err);
505 if (local_err) {
506 error_free(local_err);
507 local_err = NULL;
508 visit_type_int32(v, &value, name, &local_err);
509 if (local_err) {
510 error_propagate(errp, local_err);
511 } else if (value < -1 || value > 255) {
512 error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
513 "pci_devfn");
514 } else {
515 *ptr = value;
516 }
517 return;
518 }
519
520 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
521 fn = 0;
522 if (sscanf(str, "%x%n", &slot, &n) != 1) {
523 goto invalid;
524 }
525 }
526 if (str[n] != '\0' || fn > 7 || slot > 31) {
527 goto invalid;
528 }
529 *ptr = slot << 3 | fn;
530 g_free(str);
531 return;
532
533 invalid:
534 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
535 g_free(str);
536 }
537
538 static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
539 size_t len)
540 {
541 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
542
543 if (*ptr == -1) {
544 return snprintf(dest, len, "<unset>");
545 } else {
546 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
547 }
548 }
549
550 PropertyInfo qdev_prop_pci_devfn = {
551 .name = "int32",
552 .legacy_name = "pci-devfn",
553 .print = print_pci_devfn,
554 .get = get_int32,
555 .set = set_pci_devfn,
556 };
557
558 /* --- blocksize --- */
559
560 static void set_blocksize(Object *obj, Visitor *v, void *opaque,
561 const char *name, Error **errp)
562 {
563 DeviceState *dev = DEVICE(obj);
564 Property *prop = opaque;
565 uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
566 Error *local_err = NULL;
567 const int64_t min = 512;
568 const int64_t max = 32768;
569
570 if (dev->realized) {
571 qdev_prop_set_after_realize(dev, name, errp);
572 return;
573 }
574
575 visit_type_uint16(v, &value, name, &local_err);
576 if (local_err) {
577 error_propagate(errp, local_err);
578 return;
579 }
580 if (value < min || value > max) {
581 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
582 dev->id?:"", name, (int64_t)value, min, max);
583 return;
584 }
585
586 /* We rely on power-of-2 blocksizes for bitmasks */
587 if ((value & (value - 1)) != 0) {
588 error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
589 dev->id?:"", name, (int64_t)value);
590 return;
591 }
592
593 *ptr = value;
594 }
595
596 PropertyInfo qdev_prop_blocksize = {
597 .name = "blocksize",
598 .get = get_uint16,
599 .set = set_blocksize,
600 };
601
602 /* --- pci host address --- */
603
604 static void get_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
605 const char *name, Error **errp)
606 {
607 DeviceState *dev = DEVICE(obj);
608 Property *prop = opaque;
609 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
610 char buffer[] = "xxxx:xx:xx.x";
611 char *p = buffer;
612 int rc = 0;
613
614 rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
615 addr->domain, addr->bus, addr->slot, addr->function);
616 assert(rc == sizeof(buffer) - 1);
617
618 visit_type_str(v, &p, name, errp);
619 }
620
621 /*
622 * Parse [<domain>:]<bus>:<slot>.<func>
623 * if <domain> is not supplied, it's assumed to be 0.
624 */
625 static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
626 const char *name, Error **errp)
627 {
628 DeviceState *dev = DEVICE(obj);
629 Property *prop = opaque;
630 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
631 Error *local_err = NULL;
632 char *str, *p;
633 char *e;
634 unsigned long val;
635 unsigned long dom = 0, bus = 0;
636 unsigned int slot = 0, func = 0;
637
638 if (dev->realized) {
639 qdev_prop_set_after_realize(dev, name, errp);
640 return;
641 }
642
643 visit_type_str(v, &str, name, &local_err);
644 if (local_err) {
645 error_propagate(errp, local_err);
646 return;
647 }
648
649 p = str;
650 val = strtoul(p, &e, 16);
651 if (e == p || *e != ':') {
652 goto inval;
653 }
654 bus = val;
655
656 p = e + 1;
657 val = strtoul(p, &e, 16);
658 if (e == p) {
659 goto inval;
660 }
661 if (*e == ':') {
662 dom = bus;
663 bus = val;
664 p = e + 1;
665 val = strtoul(p, &e, 16);
666 if (e == p) {
667 goto inval;
668 }
669 }
670 slot = val;
671
672 if (*e != '.') {
673 goto inval;
674 }
675 p = e + 1;
676 val = strtoul(p, &e, 10);
677 if (e == p) {
678 goto inval;
679 }
680 func = val;
681
682 if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
683 goto inval;
684 }
685
686 if (*e) {
687 goto inval;
688 }
689
690 addr->domain = dom;
691 addr->bus = bus;
692 addr->slot = slot;
693 addr->function = func;
694
695 g_free(str);
696 return;
697
698 inval:
699 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
700 g_free(str);
701 }
702
703 PropertyInfo qdev_prop_pci_host_devaddr = {
704 .name = "pci-host-devaddr",
705 .get = get_pci_host_devaddr,
706 .set = set_pci_host_devaddr,
707 };
708
709 /* --- support for array properties --- */
710
711 /* Used as an opaque for the object properties we add for each
712 * array element. Note that the struct Property must be first
713 * in the struct so that a pointer to this works as the opaque
714 * for the underlying element's property hooks as well as for
715 * our own release callback.
716 */
717 typedef struct {
718 struct Property prop;
719 char *propname;
720 ObjectPropertyRelease *release;
721 } ArrayElementProperty;
722
723 /* object property release callback for array element properties:
724 * we call the underlying element's property release hook, and
725 * then free the memory we allocated when we added the property.
726 */
727 static void array_element_release(Object *obj, const char *name, void *opaque)
728 {
729 ArrayElementProperty *p = opaque;
730 if (p->release) {
731 p->release(obj, name, opaque);
732 }
733 g_free(p->propname);
734 g_free(p);
735 }
736
737 static void set_prop_arraylen(Object *obj, Visitor *v, void *opaque,
738 const char *name, Error **errp)
739 {
740 /* Setter for the property which defines the length of a
741 * variable-sized property array. As well as actually setting the
742 * array-length field in the device struct, we have to create the
743 * array itself and dynamically add the corresponding properties.
744 */
745 DeviceState *dev = DEVICE(obj);
746 Property *prop = opaque;
747 uint32_t *alenptr = qdev_get_prop_ptr(dev, prop);
748 void **arrayptr = (void *)dev + prop->arrayoffset;
749 void *eltptr;
750 const char *arrayname;
751 int i;
752
753 if (dev->realized) {
754 qdev_prop_set_after_realize(dev, name, errp);
755 return;
756 }
757 if (*alenptr) {
758 error_setg(errp, "array size property %s may not be set more than once",
759 name);
760 return;
761 }
762 visit_type_uint32(v, alenptr, name, errp);
763 if (error_is_set(errp)) {
764 return;
765 }
766 if (!*alenptr) {
767 return;
768 }
769
770 /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
771 * strip it off so we can get the name of the array itself.
772 */
773 assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
774 strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
775 arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
776
777 /* Note that it is the responsibility of the individual device's deinit
778 * to free the array proper.
779 */
780 *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
781 for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
782 char *propname = g_strdup_printf("%s[%d]", arrayname, i);
783 ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
784 arrayprop->release = prop->arrayinfo->release;
785 arrayprop->propname = propname;
786 arrayprop->prop.info = prop->arrayinfo;
787 arrayprop->prop.name = propname;
788 /* This ugly piece of pointer arithmetic sets up the offset so
789 * that when the underlying get/set hooks call qdev_get_prop_ptr
790 * they get the right answer despite the array element not actually
791 * being inside the device struct.
792 */
793 arrayprop->prop.offset = eltptr - (void *)dev;
794 assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr);
795 object_property_add(obj, propname,
796 arrayprop->prop.info->name,
797 arrayprop->prop.info->get,
798 arrayprop->prop.info->set,
799 array_element_release,
800 arrayprop, errp);
801 if (error_is_set(errp)) {
802 return;
803 }
804 }
805 }
806
807 PropertyInfo qdev_prop_arraylen = {
808 .name = "uint32",
809 .get = get_uint32,
810 .set = set_prop_arraylen,
811 };
812
813 /* --- public helpers --- */
814
815 static Property *qdev_prop_walk(Property *props, const char *name)
816 {
817 if (!props) {
818 return NULL;
819 }
820 while (props->name) {
821 if (strcmp(props->name, name) == 0) {
822 return props;
823 }
824 props++;
825 }
826 return NULL;
827 }
828
829 static Property *qdev_prop_find(DeviceState *dev, const char *name)
830 {
831 ObjectClass *class;
832 Property *prop;
833
834 /* device properties */
835 class = object_get_class(OBJECT(dev));
836 do {
837 prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
838 if (prop) {
839 return prop;
840 }
841 class = object_class_get_parent(class);
842 } while (class != object_class_by_name(TYPE_DEVICE));
843
844 return NULL;
845 }
846
847 void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
848 Property *prop, const char *value)
849 {
850 switch (ret) {
851 case -EEXIST:
852 error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
853 object_get_typename(OBJECT(dev)), prop->name, value);
854 break;
855 default:
856 case -EINVAL:
857 error_set(errp, QERR_PROPERTY_VALUE_BAD,
858 object_get_typename(OBJECT(dev)), prop->name, value);
859 break;
860 case -ENOENT:
861 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
862 object_get_typename(OBJECT(dev)), prop->name, value);
863 break;
864 case 0:
865 break;
866 }
867 }
868
869 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
870 {
871 object_property_set_bool(OBJECT(dev), value, name, &error_abort);
872 }
873
874 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
875 {
876 object_property_set_int(OBJECT(dev), value, name, &error_abort);
877 }
878
879 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
880 {
881 object_property_set_int(OBJECT(dev), value, name, &error_abort);
882 }
883
884 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
885 {
886 object_property_set_int(OBJECT(dev), value, name, &error_abort);
887 }
888
889 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
890 {
891 object_property_set_int(OBJECT(dev), value, name, &error_abort);
892 }
893
894 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
895 {
896 object_property_set_int(OBJECT(dev), value, name, &error_abort);
897 }
898
899 void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
900 {
901 object_property_set_str(OBJECT(dev), value, name, &error_abort);
902 }
903
904 void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
905 {
906 char str[2 * 6 + 5 + 1];
907 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
908 value[0], value[1], value[2], value[3], value[4], value[5]);
909
910 object_property_set_str(OBJECT(dev), str, name, &error_abort);
911 }
912
913 void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
914 {
915 Property *prop;
916
917 prop = qdev_prop_find(dev, name);
918 object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
919 name, &error_abort);
920 }
921
922 void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
923 {
924 Property *prop;
925 void **ptr;
926
927 prop = qdev_prop_find(dev, name);
928 assert(prop && prop->info == &qdev_prop_ptr);
929 ptr = qdev_get_prop_ptr(dev, prop);
930 *ptr = value;
931 }
932
933 static QTAILQ_HEAD(, GlobalProperty) global_props =
934 QTAILQ_HEAD_INITIALIZER(global_props);
935
936 void qdev_prop_register_global(GlobalProperty *prop)
937 {
938 QTAILQ_INSERT_TAIL(&global_props, prop, next);
939 }
940
941 void qdev_prop_register_global_list(GlobalProperty *props)
942 {
943 int i;
944
945 for (i = 0; props[i].driver != NULL; i++) {
946 qdev_prop_register_global(props+i);
947 }
948 }
949
950 void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
951 Error **errp)
952 {
953 GlobalProperty *prop;
954
955 QTAILQ_FOREACH(prop, &global_props, next) {
956 Error *err = NULL;
957
958 if (strcmp(typename, prop->driver) != 0) {
959 continue;
960 }
961 object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
962 if (err != NULL) {
963 error_propagate(errp, err);
964 return;
965 }
966 }
967 }
968
969 void qdev_prop_set_globals(DeviceState *dev, Error **errp)
970 {
971 ObjectClass *class = object_get_class(OBJECT(dev));
972
973 do {
974 Error *err = NULL;
975
976 qdev_prop_set_globals_for_type(dev, object_class_get_name(class),
977 &err);
978 if (err != NULL) {
979 error_propagate(errp, err);
980 return;
981 }
982 class = object_class_get_parent(class);
983 } while (class);
984 }
985
986 /* --- 64bit unsigned int 'size' type --- */
987
988 static void get_size(Object *obj, Visitor *v, void *opaque,
989 const char *name, Error **errp)
990 {
991 DeviceState *dev = DEVICE(obj);
992 Property *prop = opaque;
993 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
994
995 visit_type_size(v, ptr, name, errp);
996 }
997
998 static void set_size(Object *obj, Visitor *v, void *opaque,
999 const char *name, Error **errp)
1000 {
1001 DeviceState *dev = DEVICE(obj);
1002 Property *prop = opaque;
1003 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
1004
1005 visit_type_size(v, ptr, name, errp);
1006 }
1007
1008 PropertyInfo qdev_prop_size = {
1009 .name = "size",
1010 .get = get_size,
1011 .set = set_size,
1012 };