xref: /qemu/hw/core/qdev-properties.c (revision 6f061ea1)
1 #include "qemu/osdep.h"
2 #include "net/net.h"
3 #include "hw/qdev.h"
4 #include "qapi/error.h"
5 #include "qapi/qmp/qerror.h"
6 #include "qemu/error-report.h"
7 #include "sysemu/block-backend.h"
8 #include "hw/block/block.h"
9 #include "net/hub.h"
10 #include "qapi/visitor.h"
11 #include "sysemu/char.h"
12 
13 void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
14                                   Error **errp)
15 {
16     if (dev->id) {
17         error_setg(errp, "Attempt to set property '%s' on device '%s' "
18                    "(type '%s') after it was realized", name, dev->id,
19                    object_get_typename(OBJECT(dev)));
20     } else {
21         error_setg(errp, "Attempt to set property '%s' on anonymous device "
22                    "(type '%s') after it was realized", name,
23                    object_get_typename(OBJECT(dev)));
24     }
25 }
26 
27 void qdev_prop_allow_set_link_before_realize(Object *obj, const char *name,
28                                              Object *val, Error **errp)
29 {
30     DeviceState *dev = DEVICE(obj);
31 
32     if (dev->realized) {
33         error_setg(errp, "Attempt to set link property '%s' on device '%s' "
34                    "(type '%s') after it was realized",
35                    name, dev->id, object_get_typename(obj));
36     }
37 }
38 
39 void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
40 {
41     void *ptr = dev;
42     ptr += prop->offset;
43     return ptr;
44 }
45 
46 static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque,
47                      Error **errp)
48 {
49     DeviceState *dev = DEVICE(obj);
50     Property *prop = opaque;
51     int *ptr = qdev_get_prop_ptr(dev, prop);
52 
53     visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
54 }
55 
56 static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque,
57                      Error **errp)
58 {
59     DeviceState *dev = DEVICE(obj);
60     Property *prop = opaque;
61     int *ptr = qdev_get_prop_ptr(dev, prop);
62 
63     if (dev->realized) {
64         qdev_prop_set_after_realize(dev, name, errp);
65         return;
66     }
67 
68     visit_type_enum(v, prop->name, ptr, prop->info->enum_table, 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, const char *name,
91                          void *opaque, 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, name, &value, errp);
99 }
100 
101 static void prop_set_bit(Object *obj, Visitor *v, const char *name,
102                          void *opaque, 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, name, &value, &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, const char *name,
149                            void *opaque, 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, name, &value, errp);
157 }
158 
159 static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
160                            void *opaque, 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, name, &value, &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, const char *name, void *opaque,
190                      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, name, ptr, errp);
197 }
198 
199 static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
200                      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, name, ptr, 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, const char *name, void *opaque,
223                       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, name, ptr, errp);
230 }
231 
232 static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
233                       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, name, ptr, 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, const char *name,
256                        void *opaque, 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, name, ptr, errp);
263 }
264 
265 static void set_uint16(Object *obj, Visitor *v, const char *name,
266                        void *opaque, 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, name, ptr, 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, const char *name,
289                        void *opaque, 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, name, ptr, errp);
296 }
297 
298 static void set_uint32(Object *obj, Visitor *v, const char *name,
299                        void *opaque, 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, name, ptr, errp);
311 }
312 
313 static void get_int32(Object *obj, Visitor *v, const char *name, void *opaque,
314                       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, name, ptr, errp);
321 }
322 
323 static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
324                       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, name, ptr, 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, const char *name,
353                        void *opaque, 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, name, ptr, errp);
360 }
361 
362 static void set_uint64(Object *obj, Visitor *v, const char *name,
363                        void *opaque, 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, name, ptr, 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, const char *name,
392                        void *opaque, 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, name, &str, errp);
401     } else {
402         visit_type_str(v, name, ptr, errp);
403     }
404 }
405 
406 static void set_string(Object *obj, Visitor *v, const char *name,
407                        void *opaque, 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, name, &str, &local_err);
421     if (local_err) {
422         error_propagate(errp, local_err);
423         return;
424     }
425     g_free(*ptr);
426     *ptr = str;
427 }
428 
429 PropertyInfo qdev_prop_string = {
430     .name  = "str",
431     .release = release_string,
432     .get   = get_string,
433     .set   = set_string,
434 };
435 
436 /* --- pointer --- */
437 
438 /* Not a proper property, just for dirty hacks.  TODO Remove it!  */
439 PropertyInfo qdev_prop_ptr = {
440     .name  = "ptr",
441 };
442 
443 /* --- mac address --- */
444 
445 /*
446  * accepted syntax versions:
447  *   01:02:03:04:05:06
448  *   01-02-03-04-05-06
449  */
450 static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
451                     Error **errp)
452 {
453     DeviceState *dev = DEVICE(obj);
454     Property *prop = opaque;
455     MACAddr *mac = qdev_get_prop_ptr(dev, prop);
456     char buffer[2 * 6 + 5 + 1];
457     char *p = buffer;
458 
459     snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
460              mac->a[0], mac->a[1], mac->a[2],
461              mac->a[3], mac->a[4], mac->a[5]);
462 
463     visit_type_str(v, name, &p, errp);
464 }
465 
466 static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
467                     Error **errp)
468 {
469     DeviceState *dev = DEVICE(obj);
470     Property *prop = opaque;
471     MACAddr *mac = qdev_get_prop_ptr(dev, prop);
472     Error *local_err = NULL;
473     int i, pos;
474     char *str, *p;
475 
476     if (dev->realized) {
477         qdev_prop_set_after_realize(dev, name, errp);
478         return;
479     }
480 
481     visit_type_str(v, name, &str, &local_err);
482     if (local_err) {
483         error_propagate(errp, local_err);
484         return;
485     }
486 
487     for (i = 0, pos = 0; i < 6; i++, pos += 3) {
488         if (!qemu_isxdigit(str[pos])) {
489             goto inval;
490         }
491         if (!qemu_isxdigit(str[pos+1])) {
492             goto inval;
493         }
494         if (i == 5) {
495             if (str[pos+2] != '\0') {
496                 goto inval;
497             }
498         } else {
499             if (str[pos+2] != ':' && str[pos+2] != '-') {
500                 goto inval;
501             }
502         }
503         mac->a[i] = strtol(str+pos, &p, 16);
504     }
505     g_free(str);
506     return;
507 
508 inval:
509     error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
510     g_free(str);
511 }
512 
513 PropertyInfo qdev_prop_macaddr = {
514     .name  = "str",
515     .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
516     .get   = get_mac,
517     .set   = set_mac,
518 };
519 
520 /* --- lost tick policy --- */
521 
522 QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
523 
524 PropertyInfo qdev_prop_losttickpolicy = {
525     .name  = "LostTickPolicy",
526     .enum_table  = LostTickPolicy_lookup,
527     .get   = get_enum,
528     .set   = set_enum,
529 };
530 
531 /* --- BIOS CHS translation */
532 
533 QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
534 
535 PropertyInfo qdev_prop_bios_chs_trans = {
536     .name = "BiosAtaTranslation",
537     .description = "Logical CHS translation algorithm, "
538                    "auto/none/lba/large/rechs",
539     .enum_table = BiosAtaTranslation_lookup,
540     .get = get_enum,
541     .set = set_enum,
542 };
543 
544 /* --- FDC default drive types */
545 
546 PropertyInfo qdev_prop_fdc_drive_type = {
547     .name = "FdcDriveType",
548     .description = "FDC drive type, "
549                    "144/288/120/none/auto",
550     .enum_table = FloppyDriveType_lookup,
551     .get = get_enum,
552     .set = set_enum
553 };
554 
555 /* --- pci address --- */
556 
557 /*
558  * bus-local address, i.e. "$slot" or "$slot.$fn"
559  */
560 static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
561                           void *opaque, Error **errp)
562 {
563     DeviceState *dev = DEVICE(obj);
564     Property *prop = opaque;
565     int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
566     unsigned int slot, fn, n;
567     Error *local_err = NULL;
568     char *str;
569 
570     if (dev->realized) {
571         qdev_prop_set_after_realize(dev, name, errp);
572         return;
573     }
574 
575     visit_type_str(v, name, &str, &local_err);
576     if (local_err) {
577         error_free(local_err);
578         local_err = NULL;
579         visit_type_int32(v, name, &value, &local_err);
580         if (local_err) {
581             error_propagate(errp, local_err);
582         } else if (value < -1 || value > 255) {
583             error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
584                        name ? name : "null", "pci_devfn");
585         } else {
586             *ptr = value;
587         }
588         return;
589     }
590 
591     if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
592         fn = 0;
593         if (sscanf(str, "%x%n", &slot, &n) != 1) {
594             goto invalid;
595         }
596     }
597     if (str[n] != '\0' || fn > 7 || slot > 31) {
598         goto invalid;
599     }
600     *ptr = slot << 3 | fn;
601     g_free(str);
602     return;
603 
604 invalid:
605     error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
606     g_free(str);
607 }
608 
609 static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
610                            size_t len)
611 {
612     int32_t *ptr = qdev_get_prop_ptr(dev, prop);
613 
614     if (*ptr == -1) {
615         return snprintf(dest, len, "<unset>");
616     } else {
617         return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
618     }
619 }
620 
621 PropertyInfo qdev_prop_pci_devfn = {
622     .name  = "int32",
623     .description = "Slot and optional function number, example: 06.0 or 06",
624     .print = print_pci_devfn,
625     .get   = get_int32,
626     .set   = set_pci_devfn,
627 };
628 
629 /* --- blocksize --- */
630 
631 static void set_blocksize(Object *obj, Visitor *v, const char *name,
632                           void *opaque, Error **errp)
633 {
634     DeviceState *dev = DEVICE(obj);
635     Property *prop = opaque;
636     uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
637     Error *local_err = NULL;
638     const int64_t min = 512;
639     const int64_t max = 32768;
640 
641     if (dev->realized) {
642         qdev_prop_set_after_realize(dev, name, errp);
643         return;
644     }
645 
646     visit_type_uint16(v, name, &value, &local_err);
647     if (local_err) {
648         error_propagate(errp, local_err);
649         return;
650     }
651     /* value of 0 means "unset" */
652     if (value && (value < min || value > max)) {
653         error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
654                    dev->id ? : "", name, (int64_t)value, min, max);
655         return;
656     }
657 
658     /* We rely on power-of-2 blocksizes for bitmasks */
659     if ((value & (value - 1)) != 0) {
660         error_setg(errp,
661                   "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2",
662                   dev->id ?: "", name, (int64_t)value);
663         return;
664     }
665 
666     *ptr = value;
667 }
668 
669 PropertyInfo qdev_prop_blocksize = {
670     .name  = "uint16",
671     .description = "A power of two between 512 and 32768",
672     .get   = get_uint16,
673     .set   = set_blocksize,
674 };
675 
676 /* --- pci host address --- */
677 
678 static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
679                                  void *opaque, Error **errp)
680 {
681     DeviceState *dev = DEVICE(obj);
682     Property *prop = opaque;
683     PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
684     char buffer[] = "xxxx:xx:xx.x";
685     char *p = buffer;
686     int rc = 0;
687 
688     rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
689                   addr->domain, addr->bus, addr->slot, addr->function);
690     assert(rc == sizeof(buffer) - 1);
691 
692     visit_type_str(v, name, &p, errp);
693 }
694 
695 /*
696  * Parse [<domain>:]<bus>:<slot>.<func>
697  *   if <domain> is not supplied, it's assumed to be 0.
698  */
699 static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
700                                  void *opaque, Error **errp)
701 {
702     DeviceState *dev = DEVICE(obj);
703     Property *prop = opaque;
704     PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
705     Error *local_err = NULL;
706     char *str, *p;
707     char *e;
708     unsigned long val;
709     unsigned long dom = 0, bus = 0;
710     unsigned int slot = 0, func = 0;
711 
712     if (dev->realized) {
713         qdev_prop_set_after_realize(dev, name, errp);
714         return;
715     }
716 
717     visit_type_str(v, name, &str, &local_err);
718     if (local_err) {
719         error_propagate(errp, local_err);
720         return;
721     }
722 
723     p = str;
724     val = strtoul(p, &e, 16);
725     if (e == p || *e != ':') {
726         goto inval;
727     }
728     bus = val;
729 
730     p = e + 1;
731     val = strtoul(p, &e, 16);
732     if (e == p) {
733         goto inval;
734     }
735     if (*e == ':') {
736         dom = bus;
737         bus = val;
738         p = e + 1;
739         val = strtoul(p, &e, 16);
740         if (e == p) {
741             goto inval;
742         }
743     }
744     slot = val;
745 
746     if (*e != '.') {
747         goto inval;
748     }
749     p = e + 1;
750     val = strtoul(p, &e, 10);
751     if (e == p) {
752         goto inval;
753     }
754     func = val;
755 
756     if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
757         goto inval;
758     }
759 
760     if (*e) {
761         goto inval;
762     }
763 
764     addr->domain = dom;
765     addr->bus = bus;
766     addr->slot = slot;
767     addr->function = func;
768 
769     g_free(str);
770     return;
771 
772 inval:
773     error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
774     g_free(str);
775 }
776 
777 PropertyInfo qdev_prop_pci_host_devaddr = {
778     .name = "str",
779     .description = "Address (bus/device/function) of "
780                    "the host device, example: 04:10.0",
781     .get = get_pci_host_devaddr,
782     .set = set_pci_host_devaddr,
783 };
784 
785 /* --- support for array properties --- */
786 
787 /* Used as an opaque for the object properties we add for each
788  * array element. Note that the struct Property must be first
789  * in the struct so that a pointer to this works as the opaque
790  * for the underlying element's property hooks as well as for
791  * our own release callback.
792  */
793 typedef struct {
794     struct Property prop;
795     char *propname;
796     ObjectPropertyRelease *release;
797 } ArrayElementProperty;
798 
799 /* object property release callback for array element properties:
800  * we call the underlying element's property release hook, and
801  * then free the memory we allocated when we added the property.
802  */
803 static void array_element_release(Object *obj, const char *name, void *opaque)
804 {
805     ArrayElementProperty *p = opaque;
806     if (p->release) {
807         p->release(obj, name, opaque);
808     }
809     g_free(p->propname);
810     g_free(p);
811 }
812 
813 static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
814                               void *opaque, Error **errp)
815 {
816     /* Setter for the property which defines the length of a
817      * variable-sized property array. As well as actually setting the
818      * array-length field in the device struct, we have to create the
819      * array itself and dynamically add the corresponding properties.
820      */
821     DeviceState *dev = DEVICE(obj);
822     Property *prop = opaque;
823     uint32_t *alenptr = qdev_get_prop_ptr(dev, prop);
824     void **arrayptr = (void *)dev + prop->arrayoffset;
825     Error *local_err = NULL;
826     void *eltptr;
827     const char *arrayname;
828     int i;
829 
830     if (dev->realized) {
831         qdev_prop_set_after_realize(dev, name, errp);
832         return;
833     }
834     if (*alenptr) {
835         error_setg(errp, "array size property %s may not be set more than once",
836                    name);
837         return;
838     }
839     visit_type_uint32(v, name, alenptr, &local_err);
840     if (local_err) {
841         error_propagate(errp, local_err);
842         return;
843     }
844     if (!*alenptr) {
845         return;
846     }
847 
848     /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
849      * strip it off so we can get the name of the array itself.
850      */
851     assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
852                    strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
853     arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
854 
855     /* Note that it is the responsibility of the individual device's deinit
856      * to free the array proper.
857      */
858     *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
859     for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
860         char *propname = g_strdup_printf("%s[%d]", arrayname, i);
861         ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
862         arrayprop->release = prop->arrayinfo->release;
863         arrayprop->propname = propname;
864         arrayprop->prop.info = prop->arrayinfo;
865         arrayprop->prop.name = propname;
866         /* This ugly piece of pointer arithmetic sets up the offset so
867          * that when the underlying get/set hooks call qdev_get_prop_ptr
868          * they get the right answer despite the array element not actually
869          * being inside the device struct.
870          */
871         arrayprop->prop.offset = eltptr - (void *)dev;
872         assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr);
873         object_property_add(obj, propname,
874                             arrayprop->prop.info->name,
875                             arrayprop->prop.info->get,
876                             arrayprop->prop.info->set,
877                             array_element_release,
878                             arrayprop, &local_err);
879         if (local_err) {
880             error_propagate(errp, local_err);
881             return;
882         }
883     }
884 }
885 
886 PropertyInfo qdev_prop_arraylen = {
887     .name = "uint32",
888     .get = get_uint32,
889     .set = set_prop_arraylen,
890 };
891 
892 /* --- public helpers --- */
893 
894 static Property *qdev_prop_walk(Property *props, const char *name)
895 {
896     if (!props) {
897         return NULL;
898     }
899     while (props->name) {
900         if (strcmp(props->name, name) == 0) {
901             return props;
902         }
903         props++;
904     }
905     return NULL;
906 }
907 
908 static Property *qdev_prop_find(DeviceState *dev, const char *name)
909 {
910     ObjectClass *class;
911     Property *prop;
912 
913     /* device properties */
914     class = object_get_class(OBJECT(dev));
915     do {
916         prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
917         if (prop) {
918             return prop;
919         }
920         class = object_class_get_parent(class);
921     } while (class != object_class_by_name(TYPE_DEVICE));
922 
923     return NULL;
924 }
925 
926 void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
927                                     Property *prop, const char *value)
928 {
929     switch (ret) {
930     case -EEXIST:
931         error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
932                   object_get_typename(OBJECT(dev)), prop->name, value);
933         break;
934     default:
935     case -EINVAL:
936         error_setg(errp, QERR_PROPERTY_VALUE_BAD,
937                    object_get_typename(OBJECT(dev)), prop->name, value);
938         break;
939     case -ENOENT:
940         error_setg(errp, "Property '%s.%s' can't find value '%s'",
941                   object_get_typename(OBJECT(dev)), prop->name, value);
942         break;
943     case 0:
944         break;
945     }
946 }
947 
948 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
949 {
950     object_property_set_bool(OBJECT(dev), value, name, &error_abort);
951 }
952 
953 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
954 {
955     object_property_set_int(OBJECT(dev), value, name, &error_abort);
956 }
957 
958 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
959 {
960     object_property_set_int(OBJECT(dev), value, name, &error_abort);
961 }
962 
963 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
964 {
965     object_property_set_int(OBJECT(dev), value, name, &error_abort);
966 }
967 
968 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
969 {
970     object_property_set_int(OBJECT(dev), value, name, &error_abort);
971 }
972 
973 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
974 {
975     object_property_set_int(OBJECT(dev), value, name, &error_abort);
976 }
977 
978 void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
979 {
980     object_property_set_str(OBJECT(dev), value, name, &error_abort);
981 }
982 
983 void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
984 {
985     char str[2 * 6 + 5 + 1];
986     snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
987              value[0], value[1], value[2], value[3], value[4], value[5]);
988 
989     object_property_set_str(OBJECT(dev), str, name, &error_abort);
990 }
991 
992 void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
993 {
994     Property *prop;
995 
996     prop = qdev_prop_find(dev, name);
997     object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
998                             name, &error_abort);
999 }
1000 
1001 void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1002 {
1003     Property *prop;
1004     void **ptr;
1005 
1006     prop = qdev_prop_find(dev, name);
1007     assert(prop && prop->info == &qdev_prop_ptr);
1008     ptr = qdev_get_prop_ptr(dev, prop);
1009     *ptr = value;
1010 }
1011 
1012 static QTAILQ_HEAD(, GlobalProperty) global_props =
1013         QTAILQ_HEAD_INITIALIZER(global_props);
1014 
1015 void qdev_prop_register_global(GlobalProperty *prop)
1016 {
1017     QTAILQ_INSERT_TAIL(&global_props, prop, next);
1018 }
1019 
1020 void qdev_prop_register_global_list(GlobalProperty *props)
1021 {
1022     int i;
1023 
1024     for (i = 0; props[i].driver != NULL; i++) {
1025         qdev_prop_register_global(props+i);
1026     }
1027 }
1028 
1029 int qdev_prop_check_globals(void)
1030 {
1031     GlobalProperty *prop;
1032     int ret = 0;
1033 
1034     QTAILQ_FOREACH(prop, &global_props, next) {
1035         ObjectClass *oc;
1036         DeviceClass *dc;
1037         if (prop->used) {
1038             continue;
1039         }
1040         if (!prop->user_provided) {
1041             continue;
1042         }
1043         oc = object_class_by_name(prop->driver);
1044         oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
1045         if (!oc) {
1046             error_report("Warning: global %s.%s has invalid class name",
1047                        prop->driver, prop->property);
1048             ret = 1;
1049             continue;
1050         }
1051         dc = DEVICE_CLASS(oc);
1052         if (!dc->hotpluggable && !prop->used) {
1053             error_report("Warning: global %s.%s=%s not used",
1054                        prop->driver, prop->property, prop->value);
1055             ret = 1;
1056             continue;
1057         }
1058     }
1059     return ret;
1060 }
1061 
1062 static void qdev_prop_set_globals_for_type(DeviceState *dev,
1063                                 const char *typename)
1064 {
1065     GlobalProperty *prop;
1066 
1067     QTAILQ_FOREACH(prop, &global_props, next) {
1068         Error *err = NULL;
1069 
1070         if (strcmp(typename, prop->driver) != 0) {
1071             continue;
1072         }
1073         prop->used = true;
1074         object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
1075         if (err != NULL) {
1076             assert(prop->user_provided);
1077             error_reportf_err(err, "Warning: global %s.%s=%s ignored: ",
1078                               prop->driver, prop->property, prop->value);
1079             return;
1080         }
1081     }
1082 }
1083 
1084 void qdev_prop_set_globals(DeviceState *dev)
1085 {
1086     ObjectClass *class = object_get_class(OBJECT(dev));
1087 
1088     do {
1089         qdev_prop_set_globals_for_type(dev, object_class_get_name(class));
1090         class = object_class_get_parent(class);
1091     } while (class);
1092 }
1093 
1094 /* --- 64bit unsigned int 'size' type --- */
1095 
1096 static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
1097                      Error **errp)
1098 {
1099     DeviceState *dev = DEVICE(obj);
1100     Property *prop = opaque;
1101     uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
1102 
1103     visit_type_size(v, name, ptr, errp);
1104 }
1105 
1106 static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
1107                      Error **errp)
1108 {
1109     DeviceState *dev = DEVICE(obj);
1110     Property *prop = opaque;
1111     uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
1112 
1113     visit_type_size(v, name, ptr, errp);
1114 }
1115 
1116 PropertyInfo qdev_prop_size = {
1117     .name  = "size",
1118     .get = get_size,
1119     .set = set_size,
1120 };
1121