xref: /openbmc/qemu/hw/core/qdev-properties.c (revision 79bdf29c08a592a4c5d2f9b7bb462e71ee568988)
1 #include "qemu/osdep.h"
2 #include "qemu/cutils.h"
3 #include "net/net.h"
4 #include "hw/qdev-properties.h"
5 #include "qapi/error.h"
6 #include "hw/pci/pci.h"
7 #include "qapi/qapi-types-block.h"
8 #include "qapi/qapi-types-machine.h"
9 #include "qapi/qapi-types-misc.h"
10 #include "qapi/qmp/qerror.h"
11 #include "qemu/ctype.h"
12 #include "qemu/error-report.h"
13 #include "qapi/qapi-types-migration.h"
14 #include "hw/block/block.h"
15 #include "net/hub.h"
16 #include "qapi/visitor.h"
17 #include "chardev/char.h"
18 #include "qemu/uuid.h"
19 #include "qemu/units.h"
20 #include "qemu/cutils.h"
21 #include "qdev-prop-internal.h"
22 
23 void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
24                                   Error **errp)
25 {
26     if (dev->id) {
27         error_setg(errp, "Attempt to set property '%s' on device '%s' "
28                    "(type '%s') after it was realized", name, dev->id,
29                    object_get_typename(OBJECT(dev)));
30     } else {
31         error_setg(errp, "Attempt to set property '%s' on anonymous device "
32                    "(type '%s') after it was realized", name,
33                    object_get_typename(OBJECT(dev)));
34     }
35 }
36 
37 void qdev_prop_allow_set_link_before_realize(const Object *obj,
38                                              const char *name,
39                                              Object *val, Error **errp)
40 {
41     DeviceState *dev = DEVICE(obj);
42 
43     if (dev->realized) {
44         error_setg(errp, "Attempt to set link property '%s' on device '%s' "
45                    "(type '%s') after it was realized",
46                    name, dev->id, object_get_typename(obj));
47     }
48 }
49 
50 void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
51 {
52     void *ptr = dev;
53     ptr += prop->offset;
54     return ptr;
55 }
56 
57 void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name,
58                             void *opaque, Error **errp)
59 {
60     DeviceState *dev = DEVICE(obj);
61     Property *prop = opaque;
62     int *ptr = qdev_get_prop_ptr(dev, prop);
63 
64     visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
65 }
66 
67 void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name,
68                             void *opaque, Error **errp)
69 {
70     DeviceState *dev = DEVICE(obj);
71     Property *prop = opaque;
72     int *ptr = qdev_get_prop_ptr(dev, prop);
73 
74     if (dev->realized) {
75         qdev_prop_set_after_realize(dev, name, errp);
76         return;
77     }
78 
79     visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
80 }
81 
82 void qdev_propinfo_set_default_value_enum(ObjectProperty *op,
83                                           const Property *prop)
84 {
85     object_property_set_default_str(op,
86         qapi_enum_lookup(prop->info->enum_table, prop->defval.i));
87 }
88 
89 const PropertyInfo qdev_prop_enum = {
90     .name  = "enum",
91     .get   = qdev_propinfo_get_enum,
92     .set   = qdev_propinfo_set_enum,
93     .set_default_value = qdev_propinfo_set_default_value_enum,
94 };
95 
96 /* Bit */
97 
98 static uint32_t qdev_get_prop_mask(Property *prop)
99 {
100     assert(prop->info == &qdev_prop_bit);
101     return 0x1 << prop->bitnr;
102 }
103 
104 static void bit_prop_set(DeviceState *dev, Property *props, bool val)
105 {
106     uint32_t *p = qdev_get_prop_ptr(dev, props);
107     uint32_t mask = qdev_get_prop_mask(props);
108     if (val) {
109         *p |= mask;
110     } else {
111         *p &= ~mask;
112     }
113 }
114 
115 static void prop_get_bit(Object *obj, Visitor *v, const char *name,
116                          void *opaque, Error **errp)
117 {
118     DeviceState *dev = DEVICE(obj);
119     Property *prop = opaque;
120     uint32_t *p = qdev_get_prop_ptr(dev, prop);
121     bool value = (*p & qdev_get_prop_mask(prop)) != 0;
122 
123     visit_type_bool(v, name, &value, errp);
124 }
125 
126 static void prop_set_bit(Object *obj, Visitor *v, const char *name,
127                          void *opaque, Error **errp)
128 {
129     DeviceState *dev = DEVICE(obj);
130     Property *prop = opaque;
131     bool value;
132 
133     if (dev->realized) {
134         qdev_prop_set_after_realize(dev, name, errp);
135         return;
136     }
137 
138     if (!visit_type_bool(v, name, &value, errp)) {
139         return;
140     }
141     bit_prop_set(dev, prop, value);
142 }
143 
144 static void set_default_value_bool(ObjectProperty *op, const Property *prop)
145 {
146     object_property_set_default_bool(op, prop->defval.u);
147 }
148 
149 const PropertyInfo qdev_prop_bit = {
150     .name  = "bool",
151     .description = "on/off",
152     .get   = prop_get_bit,
153     .set   = prop_set_bit,
154     .set_default_value = set_default_value_bool,
155 };
156 
157 /* Bit64 */
158 
159 static uint64_t qdev_get_prop_mask64(Property *prop)
160 {
161     assert(prop->info == &qdev_prop_bit64);
162     return 0x1ull << prop->bitnr;
163 }
164 
165 static void bit64_prop_set(DeviceState *dev, Property *props, bool val)
166 {
167     uint64_t *p = qdev_get_prop_ptr(dev, props);
168     uint64_t mask = qdev_get_prop_mask64(props);
169     if (val) {
170         *p |= mask;
171     } else {
172         *p &= ~mask;
173     }
174 }
175 
176 static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
177                            void *opaque, Error **errp)
178 {
179     DeviceState *dev = DEVICE(obj);
180     Property *prop = opaque;
181     uint64_t *p = qdev_get_prop_ptr(dev, prop);
182     bool value = (*p & qdev_get_prop_mask64(prop)) != 0;
183 
184     visit_type_bool(v, name, &value, errp);
185 }
186 
187 static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
188                            void *opaque, Error **errp)
189 {
190     DeviceState *dev = DEVICE(obj);
191     Property *prop = opaque;
192     bool value;
193 
194     if (dev->realized) {
195         qdev_prop_set_after_realize(dev, name, errp);
196         return;
197     }
198 
199     if (!visit_type_bool(v, name, &value, errp)) {
200         return;
201     }
202     bit64_prop_set(dev, prop, value);
203 }
204 
205 const PropertyInfo qdev_prop_bit64 = {
206     .name  = "bool",
207     .description = "on/off",
208     .get   = prop_get_bit64,
209     .set   = prop_set_bit64,
210     .set_default_value = set_default_value_bool,
211 };
212 
213 /* --- bool --- */
214 
215 static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,
216                      Error **errp)
217 {
218     DeviceState *dev = DEVICE(obj);
219     Property *prop = opaque;
220     bool *ptr = qdev_get_prop_ptr(dev, prop);
221 
222     visit_type_bool(v, name, ptr, errp);
223 }
224 
225 static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
226                      Error **errp)
227 {
228     DeviceState *dev = DEVICE(obj);
229     Property *prop = opaque;
230     bool *ptr = qdev_get_prop_ptr(dev, prop);
231 
232     if (dev->realized) {
233         qdev_prop_set_after_realize(dev, name, errp);
234         return;
235     }
236 
237     visit_type_bool(v, name, ptr, errp);
238 }
239 
240 const PropertyInfo qdev_prop_bool = {
241     .name  = "bool",
242     .get   = get_bool,
243     .set   = set_bool,
244     .set_default_value = set_default_value_bool,
245 };
246 
247 /* --- 8bit integer --- */
248 
249 static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
250                       Error **errp)
251 {
252     DeviceState *dev = DEVICE(obj);
253     Property *prop = opaque;
254     uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
255 
256     visit_type_uint8(v, name, ptr, errp);
257 }
258 
259 static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
260                       Error **errp)
261 {
262     DeviceState *dev = DEVICE(obj);
263     Property *prop = opaque;
264     uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
265 
266     if (dev->realized) {
267         qdev_prop_set_after_realize(dev, name, errp);
268         return;
269     }
270 
271     visit_type_uint8(v, name, ptr, errp);
272 }
273 
274 static void set_default_value_int(ObjectProperty *op, const Property *prop)
275 {
276     object_property_set_default_int(op, prop->defval.i);
277 }
278 
279 static void set_default_value_uint(ObjectProperty *op, const Property *prop)
280 {
281     object_property_set_default_uint(op, prop->defval.u);
282 }
283 
284 const PropertyInfo qdev_prop_uint8 = {
285     .name  = "uint8",
286     .get   = get_uint8,
287     .set   = set_uint8,
288     .set_default_value = set_default_value_uint,
289 };
290 
291 /* --- 16bit integer --- */
292 
293 static void get_uint16(Object *obj, Visitor *v, const char *name,
294                        void *opaque, Error **errp)
295 {
296     DeviceState *dev = DEVICE(obj);
297     Property *prop = opaque;
298     uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
299 
300     visit_type_uint16(v, name, ptr, errp);
301 }
302 
303 static void set_uint16(Object *obj, Visitor *v, const char *name,
304                        void *opaque, Error **errp)
305 {
306     DeviceState *dev = DEVICE(obj);
307     Property *prop = opaque;
308     uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
309 
310     if (dev->realized) {
311         qdev_prop_set_after_realize(dev, name, errp);
312         return;
313     }
314 
315     visit_type_uint16(v, name, ptr, errp);
316 }
317 
318 const PropertyInfo qdev_prop_uint16 = {
319     .name  = "uint16",
320     .get   = get_uint16,
321     .set   = set_uint16,
322     .set_default_value = set_default_value_uint,
323 };
324 
325 /* --- 32bit integer --- */
326 
327 static void get_uint32(Object *obj, Visitor *v, const char *name,
328                        void *opaque, Error **errp)
329 {
330     DeviceState *dev = DEVICE(obj);
331     Property *prop = opaque;
332     uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
333 
334     visit_type_uint32(v, name, ptr, errp);
335 }
336 
337 static void set_uint32(Object *obj, Visitor *v, const char *name,
338                        void *opaque, Error **errp)
339 {
340     DeviceState *dev = DEVICE(obj);
341     Property *prop = opaque;
342     uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
343 
344     if (dev->realized) {
345         qdev_prop_set_after_realize(dev, name, errp);
346         return;
347     }
348 
349     visit_type_uint32(v, name, ptr, errp);
350 }
351 
352 static void get_int32(Object *obj, Visitor *v, const char *name, void *opaque,
353                       Error **errp)
354 {
355     DeviceState *dev = DEVICE(obj);
356     Property *prop = opaque;
357     int32_t *ptr = qdev_get_prop_ptr(dev, prop);
358 
359     visit_type_int32(v, name, ptr, errp);
360 }
361 
362 static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
363                       Error **errp)
364 {
365     DeviceState *dev = DEVICE(obj);
366     Property *prop = opaque;
367     int32_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_int32(v, name, ptr, errp);
375 }
376 
377 const PropertyInfo qdev_prop_uint32 = {
378     .name  = "uint32",
379     .get   = get_uint32,
380     .set   = set_uint32,
381     .set_default_value = set_default_value_uint,
382 };
383 
384 const PropertyInfo qdev_prop_int32 = {
385     .name  = "int32",
386     .get   = get_int32,
387     .set   = set_int32,
388     .set_default_value = set_default_value_int,
389 };
390 
391 /* --- 64bit integer --- */
392 
393 static void get_uint64(Object *obj, Visitor *v, const char *name,
394                        void *opaque, Error **errp)
395 {
396     DeviceState *dev = DEVICE(obj);
397     Property *prop = opaque;
398     uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
399 
400     visit_type_uint64(v, name, ptr, errp);
401 }
402 
403 static void set_uint64(Object *obj, Visitor *v, const char *name,
404                        void *opaque, Error **errp)
405 {
406     DeviceState *dev = DEVICE(obj);
407     Property *prop = opaque;
408     uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
409 
410     if (dev->realized) {
411         qdev_prop_set_after_realize(dev, name, errp);
412         return;
413     }
414 
415     visit_type_uint64(v, name, ptr, errp);
416 }
417 
418 static void get_int64(Object *obj, Visitor *v, const char *name,
419                       void *opaque, Error **errp)
420 {
421     DeviceState *dev = DEVICE(obj);
422     Property *prop = opaque;
423     int64_t *ptr = qdev_get_prop_ptr(dev, prop);
424 
425     visit_type_int64(v, name, ptr, errp);
426 }
427 
428 static void set_int64(Object *obj, Visitor *v, const char *name,
429                       void *opaque, Error **errp)
430 {
431     DeviceState *dev = DEVICE(obj);
432     Property *prop = opaque;
433     int64_t *ptr = qdev_get_prop_ptr(dev, prop);
434 
435     if (dev->realized) {
436         qdev_prop_set_after_realize(dev, name, errp);
437         return;
438     }
439 
440     visit_type_int64(v, name, ptr, errp);
441 }
442 
443 const PropertyInfo qdev_prop_uint64 = {
444     .name  = "uint64",
445     .get   = get_uint64,
446     .set   = set_uint64,
447     .set_default_value = set_default_value_uint,
448 };
449 
450 const PropertyInfo qdev_prop_int64 = {
451     .name  = "int64",
452     .get   = get_int64,
453     .set   = set_int64,
454     .set_default_value = set_default_value_int,
455 };
456 
457 /* --- string --- */
458 
459 static void release_string(Object *obj, const char *name, void *opaque)
460 {
461     Property *prop = opaque;
462     g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
463 }
464 
465 static void get_string(Object *obj, Visitor *v, const char *name,
466                        void *opaque, Error **errp)
467 {
468     DeviceState *dev = DEVICE(obj);
469     Property *prop = opaque;
470     char **ptr = qdev_get_prop_ptr(dev, prop);
471 
472     if (!*ptr) {
473         char *str = (char *)"";
474         visit_type_str(v, name, &str, errp);
475     } else {
476         visit_type_str(v, name, ptr, errp);
477     }
478 }
479 
480 static void set_string(Object *obj, Visitor *v, const char *name,
481                        void *opaque, Error **errp)
482 {
483     DeviceState *dev = DEVICE(obj);
484     Property *prop = opaque;
485     char **ptr = qdev_get_prop_ptr(dev, prop);
486     char *str;
487 
488     if (dev->realized) {
489         qdev_prop_set_after_realize(dev, name, errp);
490         return;
491     }
492 
493     if (!visit_type_str(v, name, &str, errp)) {
494         return;
495     }
496     g_free(*ptr);
497     *ptr = str;
498 }
499 
500 const PropertyInfo qdev_prop_string = {
501     .name  = "str",
502     .release = release_string,
503     .get   = get_string,
504     .set   = set_string,
505 };
506 
507 /* --- mac address --- */
508 
509 /*
510  * accepted syntax versions:
511  *   01:02:03:04:05:06
512  *   01-02-03-04-05-06
513  */
514 static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
515                     Error **errp)
516 {
517     DeviceState *dev = DEVICE(obj);
518     Property *prop = opaque;
519     MACAddr *mac = qdev_get_prop_ptr(dev, prop);
520     char buffer[2 * 6 + 5 + 1];
521     char *p = buffer;
522 
523     snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
524              mac->a[0], mac->a[1], mac->a[2],
525              mac->a[3], mac->a[4], mac->a[5]);
526 
527     visit_type_str(v, name, &p, errp);
528 }
529 
530 static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
531                     Error **errp)
532 {
533     DeviceState *dev = DEVICE(obj);
534     Property *prop = opaque;
535     MACAddr *mac = qdev_get_prop_ptr(dev, prop);
536     int i, pos;
537     char *str;
538     const char *p;
539 
540     if (dev->realized) {
541         qdev_prop_set_after_realize(dev, name, errp);
542         return;
543     }
544 
545     if (!visit_type_str(v, name, &str, errp)) {
546         return;
547     }
548 
549     for (i = 0, pos = 0; i < 6; i++, pos += 3) {
550         long val;
551 
552         if (!qemu_isxdigit(str[pos])) {
553             goto inval;
554         }
555         if (!qemu_isxdigit(str[pos + 1])) {
556             goto inval;
557         }
558         if (i == 5) {
559             if (str[pos + 2] != '\0') {
560                 goto inval;
561             }
562         } else {
563             if (str[pos + 2] != ':' && str[pos + 2] != '-') {
564                 goto inval;
565             }
566         }
567         if (qemu_strtol(str + pos, &p, 16, &val) < 0 || val > 0xff) {
568             goto inval;
569         }
570         mac->a[i] = val;
571     }
572     g_free(str);
573     return;
574 
575 inval:
576     error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
577     g_free(str);
578 }
579 
580 const PropertyInfo qdev_prop_macaddr = {
581     .name  = "str",
582     .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
583     .get   = get_mac,
584     .set   = set_mac,
585 };
586 
587 /* --- Reserved Region --- */
588 
589 /*
590  * Accepted syntax:
591  *   <low address>:<high address>:<type>
592  *   where low/high addresses are uint64_t in hexadecimal
593  *   and type is a non-negative decimal integer
594  */
595 static void get_reserved_region(Object *obj, Visitor *v, const char *name,
596                                 void *opaque, Error **errp)
597 {
598     DeviceState *dev = DEVICE(obj);
599     Property *prop = opaque;
600     ReservedRegion *rr = qdev_get_prop_ptr(dev, prop);
601     char buffer[64];
602     char *p = buffer;
603     int rc;
604 
605     rc = snprintf(buffer, sizeof(buffer), "0x%"PRIx64":0x%"PRIx64":%u",
606                   rr->low, rr->high, rr->type);
607     assert(rc < sizeof(buffer));
608 
609     visit_type_str(v, name, &p, errp);
610 }
611 
612 static void set_reserved_region(Object *obj, Visitor *v, const char *name,
613                                 void *opaque, Error **errp)
614 {
615     DeviceState *dev = DEVICE(obj);
616     Property *prop = opaque;
617     ReservedRegion *rr = qdev_get_prop_ptr(dev, prop);
618     Error *local_err = NULL;
619     const char *endptr;
620     char *str;
621     int ret;
622 
623     if (dev->realized) {
624         qdev_prop_set_after_realize(dev, name, errp);
625         return;
626     }
627 
628     visit_type_str(v, name, &str, &local_err);
629     if (local_err) {
630         error_propagate(errp, local_err);
631         return;
632     }
633 
634     ret = qemu_strtou64(str, &endptr, 16, &rr->low);
635     if (ret) {
636         error_setg(errp, "start address of '%s'"
637                    " must be a hexadecimal integer", name);
638         goto out;
639     }
640     if (*endptr != ':') {
641         goto separator_error;
642     }
643 
644     ret = qemu_strtou64(endptr + 1, &endptr, 16, &rr->high);
645     if (ret) {
646         error_setg(errp, "end address of '%s'"
647                    " must be a hexadecimal integer", name);
648         goto out;
649     }
650     if (*endptr != ':') {
651         goto separator_error;
652     }
653 
654     ret = qemu_strtoui(endptr + 1, &endptr, 10, &rr->type);
655     if (ret) {
656         error_setg(errp, "type of '%s'"
657                    " must be a non-negative decimal integer", name);
658     }
659     goto out;
660 
661 separator_error:
662     error_setg(errp, "reserved region fields must be separated with ':'");
663 out:
664     g_free(str);
665     return;
666 }
667 
668 const PropertyInfo qdev_prop_reserved_region = {
669     .name  = "reserved_region",
670     .description = "Reserved Region, example: 0xFEE00000:0xFEEFFFFF:0",
671     .get   = get_reserved_region,
672     .set   = set_reserved_region,
673 };
674 
675 /* --- on/off/auto --- */
676 
677 const PropertyInfo qdev_prop_on_off_auto = {
678     .name = "OnOffAuto",
679     .description = "on/off/auto",
680     .enum_table = &OnOffAuto_lookup,
681     .get = qdev_propinfo_get_enum,
682     .set = qdev_propinfo_set_enum,
683     .set_default_value = qdev_propinfo_set_default_value_enum,
684 };
685 
686 /* --- lost tick policy --- */
687 
688 QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
689 
690 const PropertyInfo qdev_prop_losttickpolicy = {
691     .name  = "LostTickPolicy",
692     .enum_table  = &LostTickPolicy_lookup,
693     .get   = qdev_propinfo_get_enum,
694     .set   = qdev_propinfo_set_enum,
695     .set_default_value = qdev_propinfo_set_default_value_enum,
696 };
697 
698 /* --- Block device error handling policy --- */
699 
700 QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int));
701 
702 const PropertyInfo qdev_prop_blockdev_on_error = {
703     .name = "BlockdevOnError",
704     .description = "Error handling policy, "
705                    "report/ignore/enospc/stop/auto",
706     .enum_table = &BlockdevOnError_lookup,
707     .get = qdev_propinfo_get_enum,
708     .set = qdev_propinfo_set_enum,
709     .set_default_value = qdev_propinfo_set_default_value_enum,
710 };
711 
712 /* --- BIOS CHS translation */
713 
714 QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
715 
716 const PropertyInfo qdev_prop_bios_chs_trans = {
717     .name = "BiosAtaTranslation",
718     .description = "Logical CHS translation algorithm, "
719                    "auto/none/lba/large/rechs",
720     .enum_table = &BiosAtaTranslation_lookup,
721     .get = qdev_propinfo_get_enum,
722     .set = qdev_propinfo_set_enum,
723     .set_default_value = qdev_propinfo_set_default_value_enum,
724 };
725 
726 /* --- FDC default drive types */
727 
728 const PropertyInfo qdev_prop_fdc_drive_type = {
729     .name = "FdcDriveType",
730     .description = "FDC drive type, "
731                    "144/288/120/none/auto",
732     .enum_table = &FloppyDriveType_lookup,
733     .get = qdev_propinfo_get_enum,
734     .set = qdev_propinfo_set_enum,
735     .set_default_value = qdev_propinfo_set_default_value_enum,
736 };
737 
738 /* --- MultiFDCompression --- */
739 
740 const PropertyInfo qdev_prop_multifd_compression = {
741     .name = "MultiFDCompression",
742     .description = "multifd_compression values, "
743                    "none/zlib/zstd",
744     .enum_table = &MultiFDCompression_lookup,
745     .get = qdev_propinfo_get_enum,
746     .set = qdev_propinfo_set_enum,
747     .set_default_value = qdev_propinfo_set_default_value_enum,
748 };
749 
750 /* --- pci address --- */
751 
752 /*
753  * bus-local address, i.e. "$slot" or "$slot.$fn"
754  */
755 static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
756                           void *opaque, Error **errp)
757 {
758     DeviceState *dev = DEVICE(obj);
759     Property *prop = opaque;
760     int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
761     unsigned int slot, fn, n;
762     char *str;
763 
764     if (dev->realized) {
765         qdev_prop_set_after_realize(dev, name, errp);
766         return;
767     }
768 
769     if (!visit_type_str(v, name, &str, NULL)) {
770         if (!visit_type_int32(v, name, &value, errp)) {
771             return;
772         }
773         if (value < -1 || value > 255) {
774             error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
775                        name ? name : "null", "pci_devfn");
776             return;
777         }
778         *ptr = value;
779         return;
780     }
781 
782     if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
783         fn = 0;
784         if (sscanf(str, "%x%n", &slot, &n) != 1) {
785             goto invalid;
786         }
787     }
788     if (str[n] != '\0' || fn > 7 || slot > 31) {
789         goto invalid;
790     }
791     *ptr = slot << 3 | fn;
792     g_free(str);
793     return;
794 
795 invalid:
796     error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
797     g_free(str);
798 }
799 
800 static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
801                            size_t len)
802 {
803     int32_t *ptr = qdev_get_prop_ptr(dev, prop);
804 
805     if (*ptr == -1) {
806         return snprintf(dest, len, "<unset>");
807     } else {
808         return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
809     }
810 }
811 
812 const PropertyInfo qdev_prop_pci_devfn = {
813     .name  = "int32",
814     .description = "Slot and optional function number, example: 06.0 or 06",
815     .print = print_pci_devfn,
816     .get   = get_int32,
817     .set   = set_pci_devfn,
818     .set_default_value = set_default_value_int,
819 };
820 
821 /* --- 32bit unsigned int 'size' type --- */
822 
823 static void get_size32(Object *obj, Visitor *v, const char *name, void *opaque,
824                        Error **errp)
825 {
826     DeviceState *dev = DEVICE(obj);
827     Property *prop = opaque;
828     uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
829     uint64_t value = *ptr;
830 
831     visit_type_size(v, name, &value, errp);
832 }
833 
834 static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,
835                        Error **errp)
836 {
837     DeviceState *dev = DEVICE(obj);
838     Property *prop = opaque;
839     uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
840     uint64_t value;
841 
842     if (dev->realized) {
843         qdev_prop_set_after_realize(dev, name, errp);
844         return;
845     }
846 
847     if (!visit_type_size(v, name, &value, errp)) {
848         return;
849     }
850 
851     if (value > UINT32_MAX) {
852         error_setg(errp,
853                    "Property %s.%s doesn't take value %" PRIu64
854                    " (maximum: %u)",
855                    dev->id ? : "", name, value, UINT32_MAX);
856         return;
857     }
858 
859     *ptr = value;
860 }
861 
862 const PropertyInfo qdev_prop_size32 = {
863     .name  = "size",
864     .get = get_size32,
865     .set = set_size32,
866     .set_default_value = set_default_value_uint,
867 };
868 
869 /* --- blocksize --- */
870 
871 /* lower limit is sector size */
872 #define MIN_BLOCK_SIZE          512
873 #define MIN_BLOCK_SIZE_STR      "512 B"
874 /*
875  * upper limit is arbitrary, 2 MiB looks sufficient for all sensible uses, and
876  * matches qcow2 cluster size limit
877  */
878 #define MAX_BLOCK_SIZE          (2 * MiB)
879 #define MAX_BLOCK_SIZE_STR      "2 MiB"
880 
881 static void set_blocksize(Object *obj, Visitor *v, const char *name,
882                           void *opaque, Error **errp)
883 {
884     DeviceState *dev = DEVICE(obj);
885     Property *prop = opaque;
886     uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
887     uint64_t value;
888 
889     if (dev->realized) {
890         qdev_prop_set_after_realize(dev, name, errp);
891         return;
892     }
893 
894     if (!visit_type_size(v, name, &value, errp)) {
895         return;
896     }
897     /* value of 0 means "unset" */
898     if (value && (value < MIN_BLOCK_SIZE || value > MAX_BLOCK_SIZE)) {
899         error_setg(errp,
900                    "Property %s.%s doesn't take value %" PRIu64
901                    " (minimum: " MIN_BLOCK_SIZE_STR
902                    ", maximum: " MAX_BLOCK_SIZE_STR ")",
903                    dev->id ? : "", name, value);
904         return;
905     }
906 
907     /* We rely on power-of-2 blocksizes for bitmasks */
908     if ((value & (value - 1)) != 0) {
909         error_setg(errp,
910                   "Property %s.%s doesn't take value '%" PRId64 "', "
911                   "it's not a power of 2", dev->id ?: "", name, (int64_t)value);
912         return;
913     }
914 
915     *ptr = value;
916 }
917 
918 const PropertyInfo qdev_prop_blocksize = {
919     .name  = "size",
920     .description = "A power of two between " MIN_BLOCK_SIZE_STR
921                    " and " MAX_BLOCK_SIZE_STR,
922     .get   = get_size32,
923     .set   = set_blocksize,
924     .set_default_value = set_default_value_uint,
925 };
926 
927 /* --- pci host address --- */
928 
929 static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
930                                  void *opaque, Error **errp)
931 {
932     DeviceState *dev = DEVICE(obj);
933     Property *prop = opaque;
934     PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
935     char buffer[] = "ffff:ff:ff.f";
936     char *p = buffer;
937     int rc = 0;
938 
939     /*
940      * Catch "invalid" device reference from vfio-pci and allow the
941      * default buffer representing the non-existent device to be used.
942      */
943     if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) {
944         rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d",
945                       addr->domain, addr->bus, addr->slot, addr->function);
946         assert(rc == sizeof(buffer) - 1);
947     }
948 
949     visit_type_str(v, name, &p, errp);
950 }
951 
952 /*
953  * Parse [<domain>:]<bus>:<slot>.<func>
954  *   if <domain> is not supplied, it's assumed to be 0.
955  */
956 static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
957                                  void *opaque, Error **errp)
958 {
959     DeviceState *dev = DEVICE(obj);
960     Property *prop = opaque;
961     PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
962     char *str, *p;
963     const char *e;
964     unsigned long val;
965     unsigned long dom = 0, bus = 0;
966     unsigned int slot = 0, func = 0;
967 
968     if (dev->realized) {
969         qdev_prop_set_after_realize(dev, name, errp);
970         return;
971     }
972 
973     if (!visit_type_str(v, name, &str, errp)) {
974         return;
975     }
976 
977     p = str;
978     if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0xffff || e == p) {
979         goto inval;
980     }
981     if (*e != ':') {
982         goto inval;
983     }
984     bus = val;
985 
986     p = (char *)e + 1;
987     if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) {
988         goto inval;
989     }
990     if (*e == ':') {
991         dom = bus;
992         bus = val;
993         p = (char *)e + 1;
994         if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) {
995             goto inval;
996         }
997     }
998     slot = val;
999 
1000     if (*e != '.') {
1001         goto inval;
1002     }
1003     p = (char *)e + 1;
1004     if (qemu_strtoul(p, &e, 10, &val) < 0 || val > 7 || e == p) {
1005         goto inval;
1006     }
1007     func = val;
1008 
1009     if (bus > 0xff) {
1010         goto inval;
1011     }
1012 
1013     if (*e) {
1014         goto inval;
1015     }
1016 
1017     addr->domain = dom;
1018     addr->bus = bus;
1019     addr->slot = slot;
1020     addr->function = func;
1021 
1022     g_free(str);
1023     return;
1024 
1025 inval:
1026     error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
1027     g_free(str);
1028 }
1029 
1030 const PropertyInfo qdev_prop_pci_host_devaddr = {
1031     .name = "str",
1032     .description = "Address (bus/device/function) of "
1033                    "the host device, example: 04:10.0",
1034     .get = get_pci_host_devaddr,
1035     .set = set_pci_host_devaddr,
1036 };
1037 
1038 /* --- UUID --- */
1039 
1040 static void get_uuid(Object *obj, Visitor *v, const char *name, void *opaque,
1041                      Error **errp)
1042 {
1043     DeviceState *dev = DEVICE(obj);
1044     Property *prop = opaque;
1045     QemuUUID *uuid = qdev_get_prop_ptr(dev, prop);
1046     char buffer[UUID_FMT_LEN + 1];
1047     char *p = buffer;
1048 
1049     qemu_uuid_unparse(uuid, buffer);
1050 
1051     visit_type_str(v, name, &p, errp);
1052 }
1053 
1054 #define UUID_VALUE_AUTO        "auto"
1055 
1056 static void set_uuid(Object *obj, Visitor *v, const char *name, void *opaque,
1057                     Error **errp)
1058 {
1059     DeviceState *dev = DEVICE(obj);
1060     Property *prop = opaque;
1061     QemuUUID *uuid = qdev_get_prop_ptr(dev, prop);
1062     char *str;
1063 
1064     if (dev->realized) {
1065         qdev_prop_set_after_realize(dev, name, errp);
1066         return;
1067     }
1068 
1069     if (!visit_type_str(v, name, &str, errp)) {
1070         return;
1071     }
1072 
1073     if (!strcmp(str, UUID_VALUE_AUTO)) {
1074         qemu_uuid_generate(uuid);
1075     } else if (qemu_uuid_parse(str, uuid) < 0) {
1076         error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
1077     }
1078     g_free(str);
1079 }
1080 
1081 static void set_default_uuid_auto(ObjectProperty *op, const Property *prop)
1082 {
1083     object_property_set_default_str(op, UUID_VALUE_AUTO);
1084 }
1085 
1086 const PropertyInfo qdev_prop_uuid = {
1087     .name  = "str",
1088     .description = "UUID (aka GUID) or \"" UUID_VALUE_AUTO
1089         "\" for random value (default)",
1090     .get   = get_uuid,
1091     .set   = set_uuid,
1092     .set_default_value = set_default_uuid_auto,
1093 };
1094 
1095 /* --- support for array properties --- */
1096 
1097 /* Used as an opaque for the object properties we add for each
1098  * array element. Note that the struct Property must be first
1099  * in the struct so that a pointer to this works as the opaque
1100  * for the underlying element's property hooks as well as for
1101  * our own release callback.
1102  */
1103 typedef struct {
1104     struct Property prop;
1105     char *propname;
1106     ObjectPropertyRelease *release;
1107 } ArrayElementProperty;
1108 
1109 /* object property release callback for array element properties:
1110  * we call the underlying element's property release hook, and
1111  * then free the memory we allocated when we added the property.
1112  */
1113 static void array_element_release(Object *obj, const char *name, void *opaque)
1114 {
1115     ArrayElementProperty *p = opaque;
1116     if (p->release) {
1117         p->release(obj, name, opaque);
1118     }
1119     g_free(p->propname);
1120     g_free(p);
1121 }
1122 
1123 static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
1124                               void *opaque, Error **errp)
1125 {
1126     /* Setter for the property which defines the length of a
1127      * variable-sized property array. As well as actually setting the
1128      * array-length field in the device struct, we have to create the
1129      * array itself and dynamically add the corresponding properties.
1130      */
1131     DeviceState *dev = DEVICE(obj);
1132     Property *prop = opaque;
1133     uint32_t *alenptr = qdev_get_prop_ptr(dev, prop);
1134     void **arrayptr = (void *)dev + prop->arrayoffset;
1135     void *eltptr;
1136     const char *arrayname;
1137     int i;
1138 
1139     if (dev->realized) {
1140         qdev_prop_set_after_realize(dev, name, errp);
1141         return;
1142     }
1143     if (*alenptr) {
1144         error_setg(errp, "array size property %s may not be set more than once",
1145                    name);
1146         return;
1147     }
1148     if (!visit_type_uint32(v, name, alenptr, errp)) {
1149         return;
1150     }
1151     if (!*alenptr) {
1152         return;
1153     }
1154 
1155     /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
1156      * strip it off so we can get the name of the array itself.
1157      */
1158     assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
1159                    strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
1160     arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
1161 
1162     /* Note that it is the responsibility of the individual device's deinit
1163      * to free the array proper.
1164      */
1165     *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
1166     for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
1167         char *propname = g_strdup_printf("%s[%d]", arrayname, i);
1168         ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
1169         arrayprop->release = prop->arrayinfo->release;
1170         arrayprop->propname = propname;
1171         arrayprop->prop.info = prop->arrayinfo;
1172         arrayprop->prop.name = propname;
1173         /* This ugly piece of pointer arithmetic sets up the offset so
1174          * that when the underlying get/set hooks call qdev_get_prop_ptr
1175          * they get the right answer despite the array element not actually
1176          * being inside the device struct.
1177          */
1178         arrayprop->prop.offset = eltptr - (void *)dev;
1179         assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr);
1180         object_property_add(obj, propname,
1181                             arrayprop->prop.info->name,
1182                             arrayprop->prop.info->get,
1183                             arrayprop->prop.info->set,
1184                             array_element_release,
1185                             arrayprop);
1186     }
1187 }
1188 
1189 const PropertyInfo qdev_prop_arraylen = {
1190     .name = "uint32",
1191     .get = get_uint32,
1192     .set = set_prop_arraylen,
1193     .set_default_value = set_default_value_uint,
1194 };
1195 
1196 /* --- public helpers --- */
1197 
1198 static Property *qdev_prop_walk(Property *props, const char *name)
1199 {
1200     if (!props) {
1201         return NULL;
1202     }
1203     while (props->name) {
1204         if (strcmp(props->name, name) == 0) {
1205             return props;
1206         }
1207         props++;
1208     }
1209     return NULL;
1210 }
1211 
1212 static Property *qdev_prop_find(DeviceState *dev, const char *name)
1213 {
1214     ObjectClass *class;
1215     Property *prop;
1216 
1217     /* device properties */
1218     class = object_get_class(OBJECT(dev));
1219     do {
1220         prop = qdev_prop_walk(DEVICE_CLASS(class)->props_, name);
1221         if (prop) {
1222             return prop;
1223         }
1224         class = object_class_get_parent(class);
1225     } while (class != object_class_by_name(TYPE_DEVICE));
1226 
1227     return NULL;
1228 }
1229 
1230 void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
1231                                     Property *prop, const char *value)
1232 {
1233     switch (ret) {
1234     case -EEXIST:
1235         error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
1236                   object_get_typename(OBJECT(dev)), prop->name, value);
1237         break;
1238     default:
1239     case -EINVAL:
1240         error_setg(errp, QERR_PROPERTY_VALUE_BAD,
1241                    object_get_typename(OBJECT(dev)), prop->name, value);
1242         break;
1243     case -ENOENT:
1244         error_setg(errp, "Property '%s.%s' can't find value '%s'",
1245                   object_get_typename(OBJECT(dev)), prop->name, value);
1246         break;
1247     case 0:
1248         break;
1249     }
1250 }
1251 
1252 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
1253 {
1254     object_property_set_bool(OBJECT(dev), name, value, &error_abort);
1255 }
1256 
1257 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
1258 {
1259     object_property_set_int(OBJECT(dev), name, value, &error_abort);
1260 }
1261 
1262 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
1263 {
1264     object_property_set_int(OBJECT(dev), name, value, &error_abort);
1265 }
1266 
1267 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
1268 {
1269     object_property_set_int(OBJECT(dev), name, value, &error_abort);
1270 }
1271 
1272 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1273 {
1274     object_property_set_int(OBJECT(dev), name, value, &error_abort);
1275 }
1276 
1277 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1278 {
1279     object_property_set_int(OBJECT(dev), name, value, &error_abort);
1280 }
1281 
1282 void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
1283 {
1284     object_property_set_str(OBJECT(dev), name, value, &error_abort);
1285 }
1286 
1287 void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
1288                            const uint8_t *value)
1289 {
1290     char str[2 * 6 + 5 + 1];
1291     snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
1292              value[0], value[1], value[2], value[3], value[4], value[5]);
1293 
1294     object_property_set_str(OBJECT(dev), name, str, &error_abort);
1295 }
1296 
1297 void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
1298 {
1299     Property *prop;
1300 
1301     prop = qdev_prop_find(dev, name);
1302     object_property_set_str(OBJECT(dev), name,
1303                             qapi_enum_lookup(prop->info->enum_table, value),
1304                             &error_abort);
1305 }
1306 
1307 static GPtrArray *global_props(void)
1308 {
1309     static GPtrArray *gp;
1310 
1311     if (!gp) {
1312         gp = g_ptr_array_new();
1313     }
1314 
1315     return gp;
1316 }
1317 
1318 void qdev_prop_register_global(GlobalProperty *prop)
1319 {
1320     g_ptr_array_add(global_props(), prop);
1321 }
1322 
1323 const GlobalProperty *qdev_find_global_prop(DeviceState *dev,
1324                                             const char *name)
1325 {
1326     GPtrArray *props = global_props();
1327     const GlobalProperty *p;
1328     int i;
1329 
1330     for (i = 0; i < props->len; i++) {
1331         p = g_ptr_array_index(props, i);
1332         if (object_dynamic_cast(OBJECT(dev), p->driver)
1333             && !strcmp(p->property, name)) {
1334             return p;
1335         }
1336     }
1337     return NULL;
1338 }
1339 
1340 int qdev_prop_check_globals(void)
1341 {
1342     int i, ret = 0;
1343 
1344     for (i = 0; i < global_props()->len; i++) {
1345         GlobalProperty *prop;
1346         ObjectClass *oc;
1347         DeviceClass *dc;
1348 
1349         prop = g_ptr_array_index(global_props(), i);
1350         if (prop->used) {
1351             continue;
1352         }
1353         oc = object_class_by_name(prop->driver);
1354         oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
1355         if (!oc) {
1356             warn_report("global %s.%s has invalid class name",
1357                         prop->driver, prop->property);
1358             ret = 1;
1359             continue;
1360         }
1361         dc = DEVICE_CLASS(oc);
1362         if (!dc->hotpluggable && !prop->used) {
1363             warn_report("global %s.%s=%s not used",
1364                         prop->driver, prop->property, prop->value);
1365             ret = 1;
1366             continue;
1367         }
1368     }
1369     return ret;
1370 }
1371 
1372 void qdev_prop_set_globals(DeviceState *dev)
1373 {
1374     object_apply_global_props(OBJECT(dev), global_props(),
1375                               dev->hotplugged ? NULL : &error_fatal);
1376 }
1377 
1378 /* --- 64bit unsigned int 'size' type --- */
1379 
1380 static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
1381                      Error **errp)
1382 {
1383     DeviceState *dev = DEVICE(obj);
1384     Property *prop = opaque;
1385     uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
1386 
1387     visit_type_size(v, name, ptr, errp);
1388 }
1389 
1390 static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
1391                      Error **errp)
1392 {
1393     DeviceState *dev = DEVICE(obj);
1394     Property *prop = opaque;
1395     uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
1396 
1397     visit_type_size(v, name, ptr, errp);
1398 }
1399 
1400 const PropertyInfo qdev_prop_size = {
1401     .name  = "size",
1402     .get = get_size,
1403     .set = set_size,
1404     .set_default_value = set_default_value_uint,
1405 };
1406 
1407 /* --- object link property --- */
1408 
1409 static void create_link_property(ObjectClass *oc, Property *prop)
1410 {
1411     object_class_property_add_link(oc, prop->name, prop->link_type,
1412                                    prop->offset,
1413                                    qdev_prop_allow_set_link_before_realize,
1414                                    OBJ_PROP_LINK_STRONG);
1415 }
1416 
1417 const PropertyInfo qdev_prop_link = {
1418     .name = "link",
1419     .create = create_link_property,
1420 };
1421 
1422 /* --- OffAutoPCIBAR off/auto/bar0/bar1/bar2/bar3/bar4/bar5 --- */
1423 
1424 const PropertyInfo qdev_prop_off_auto_pcibar = {
1425     .name = "OffAutoPCIBAR",
1426     .description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5",
1427     .enum_table = &OffAutoPCIBAR_lookup,
1428     .get = qdev_propinfo_get_enum,
1429     .set = qdev_propinfo_set_enum,
1430     .set_default_value = qdev_propinfo_set_default_value_enum,
1431 };
1432 
1433 /* --- PCIELinkSpeed 2_5/5/8/16 -- */
1434 
1435 static void get_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
1436                                    void *opaque, Error **errp)
1437 {
1438     DeviceState *dev = DEVICE(obj);
1439     Property *prop = opaque;
1440     PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop);
1441     int speed;
1442 
1443     switch (*p) {
1444     case QEMU_PCI_EXP_LNK_2_5GT:
1445         speed = PCIE_LINK_SPEED_2_5;
1446         break;
1447     case QEMU_PCI_EXP_LNK_5GT:
1448         speed = PCIE_LINK_SPEED_5;
1449         break;
1450     case QEMU_PCI_EXP_LNK_8GT:
1451         speed = PCIE_LINK_SPEED_8;
1452         break;
1453     case QEMU_PCI_EXP_LNK_16GT:
1454         speed = PCIE_LINK_SPEED_16;
1455         break;
1456     default:
1457         /* Unreachable */
1458         abort();
1459     }
1460 
1461     visit_type_enum(v, prop->name, &speed, prop->info->enum_table, errp);
1462 }
1463 
1464 static void set_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
1465                                    void *opaque, Error **errp)
1466 {
1467     DeviceState *dev = DEVICE(obj);
1468     Property *prop = opaque;
1469     PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop);
1470     int speed;
1471 
1472     if (dev->realized) {
1473         qdev_prop_set_after_realize(dev, name, errp);
1474         return;
1475     }
1476 
1477     if (!visit_type_enum(v, prop->name, &speed, prop->info->enum_table,
1478                          errp)) {
1479         return;
1480     }
1481 
1482     switch (speed) {
1483     case PCIE_LINK_SPEED_2_5:
1484         *p = QEMU_PCI_EXP_LNK_2_5GT;
1485         break;
1486     case PCIE_LINK_SPEED_5:
1487         *p = QEMU_PCI_EXP_LNK_5GT;
1488         break;
1489     case PCIE_LINK_SPEED_8:
1490         *p = QEMU_PCI_EXP_LNK_8GT;
1491         break;
1492     case PCIE_LINK_SPEED_16:
1493         *p = QEMU_PCI_EXP_LNK_16GT;
1494         break;
1495     default:
1496         /* Unreachable */
1497         abort();
1498     }
1499 }
1500 
1501 const PropertyInfo qdev_prop_pcie_link_speed = {
1502     .name = "PCIELinkSpeed",
1503     .description = "2_5/5/8/16",
1504     .enum_table = &PCIELinkSpeed_lookup,
1505     .get = get_prop_pcielinkspeed,
1506     .set = set_prop_pcielinkspeed,
1507     .set_default_value = qdev_propinfo_set_default_value_enum,
1508 };
1509 
1510 /* --- PCIELinkWidth 1/2/4/8/12/16/32 -- */
1511 
1512 static void get_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
1513                                    void *opaque, Error **errp)
1514 {
1515     DeviceState *dev = DEVICE(obj);
1516     Property *prop = opaque;
1517     PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop);
1518     int width;
1519 
1520     switch (*p) {
1521     case QEMU_PCI_EXP_LNK_X1:
1522         width = PCIE_LINK_WIDTH_1;
1523         break;
1524     case QEMU_PCI_EXP_LNK_X2:
1525         width = PCIE_LINK_WIDTH_2;
1526         break;
1527     case QEMU_PCI_EXP_LNK_X4:
1528         width = PCIE_LINK_WIDTH_4;
1529         break;
1530     case QEMU_PCI_EXP_LNK_X8:
1531         width = PCIE_LINK_WIDTH_8;
1532         break;
1533     case QEMU_PCI_EXP_LNK_X12:
1534         width = PCIE_LINK_WIDTH_12;
1535         break;
1536     case QEMU_PCI_EXP_LNK_X16:
1537         width = PCIE_LINK_WIDTH_16;
1538         break;
1539     case QEMU_PCI_EXP_LNK_X32:
1540         width = PCIE_LINK_WIDTH_32;
1541         break;
1542     default:
1543         /* Unreachable */
1544         abort();
1545     }
1546 
1547     visit_type_enum(v, prop->name, &width, prop->info->enum_table, errp);
1548 }
1549 
1550 static void set_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
1551                                    void *opaque, Error **errp)
1552 {
1553     DeviceState *dev = DEVICE(obj);
1554     Property *prop = opaque;
1555     PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop);
1556     int width;
1557 
1558     if (dev->realized) {
1559         qdev_prop_set_after_realize(dev, name, errp);
1560         return;
1561     }
1562 
1563     if (!visit_type_enum(v, prop->name, &width, prop->info->enum_table,
1564                          errp)) {
1565         return;
1566     }
1567 
1568     switch (width) {
1569     case PCIE_LINK_WIDTH_1:
1570         *p = QEMU_PCI_EXP_LNK_X1;
1571         break;
1572     case PCIE_LINK_WIDTH_2:
1573         *p = QEMU_PCI_EXP_LNK_X2;
1574         break;
1575     case PCIE_LINK_WIDTH_4:
1576         *p = QEMU_PCI_EXP_LNK_X4;
1577         break;
1578     case PCIE_LINK_WIDTH_8:
1579         *p = QEMU_PCI_EXP_LNK_X8;
1580         break;
1581     case PCIE_LINK_WIDTH_12:
1582         *p = QEMU_PCI_EXP_LNK_X12;
1583         break;
1584     case PCIE_LINK_WIDTH_16:
1585         *p = QEMU_PCI_EXP_LNK_X16;
1586         break;
1587     case PCIE_LINK_WIDTH_32:
1588         *p = QEMU_PCI_EXP_LNK_X32;
1589         break;
1590     default:
1591         /* Unreachable */
1592         abort();
1593     }
1594 }
1595 
1596 const PropertyInfo qdev_prop_pcie_link_width = {
1597     .name = "PCIELinkWidth",
1598     .description = "1/2/4/8/12/16/32",
1599     .enum_table = &PCIELinkWidth_lookup,
1600     .get = get_prop_pcielinkwidth,
1601     .set = set_prop_pcielinkwidth,
1602     .set_default_value = qdev_propinfo_set_default_value_enum,
1603 };
1604