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