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