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