xref: /qemu/hw/core/qdev-properties-system.c (revision f917eed3)
1 /*
2  * qdev property parsing
3  * (parts specific for qemu-system-*)
4  *
5  * This file is based on code from hw/qdev-properties.c from
6  * commit 074a86fccd185616469dfcdc0e157f438aebba18,
7  * Copyright (c) Gerd Hoffmann <kraxel@redhat.com> and other contributors.
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  */
12 
13 #include "qemu/osdep.h"
14 #include "hw/qdev-properties.h"
15 #include "qapi/error.h"
16 #include "qapi/visitor.h"
17 #include "qapi/qapi-types-block.h"
18 #include "qapi/qapi-types-machine.h"
19 #include "qapi/qapi-types-migration.h"
20 #include "qapi/qmp/qerror.h"
21 #include "qemu/ctype.h"
22 #include "qemu/cutils.h"
23 #include "qemu/units.h"
24 #include "qemu/uuid.h"
25 #include "qemu/error-report.h"
26 #include "qdev-prop-internal.h"
27 
28 #include "audio/audio.h"
29 #include "chardev/char-fe.h"
30 #include "sysemu/block-backend.h"
31 #include "sysemu/blockdev.h"
32 #include "net/net.h"
33 #include "hw/pci/pci.h"
34 #include "util/block-helpers.h"
35 
36 static bool check_prop_still_unset(Object *obj, const char *name,
37                                    const void *old_val, const char *new_val,
38                                    Error **errp)
39 {
40     const GlobalProperty *prop = qdev_find_global_prop(obj, name);
41 
42     if (!old_val) {
43         return true;
44     }
45 
46     if (prop) {
47         error_setg(errp, "-global %s.%s=... conflicts with %s=%s",
48                    prop->driver, prop->property, name, new_val);
49     } else {
50         /* Error message is vague, but a better one would be hard */
51         error_setg(errp, "%s=%s conflicts, and override is not implemented",
52                    name, new_val);
53     }
54     return false;
55 }
56 
57 
58 /* --- drive --- */
59 
60 static void get_drive(Object *obj, Visitor *v, const char *name, void *opaque,
61                       Error **errp)
62 {
63     Property *prop = opaque;
64     void **ptr = qdev_get_prop_ptr(obj, prop);
65     const char *value;
66     char *p;
67 
68     if (*ptr) {
69         value = blk_name(*ptr);
70         if (!*value) {
71             BlockDriverState *bs = blk_bs(*ptr);
72             if (bs) {
73                 value = bdrv_get_node_name(bs);
74             }
75         }
76     } else {
77         value = "";
78     }
79 
80     p = g_strdup(value);
81     visit_type_str(v, name, &p, errp);
82     g_free(p);
83 }
84 
85 static void set_drive_helper(Object *obj, Visitor *v, const char *name,
86                              void *opaque, bool iothread, Error **errp)
87 {
88     DeviceState *dev = DEVICE(obj);
89     Property *prop = opaque;
90     void **ptr = qdev_get_prop_ptr(obj, prop);
91     char *str;
92     BlockBackend *blk;
93     bool blk_created = false;
94     int ret;
95 
96     if (dev->realized) {
97         qdev_prop_set_after_realize(dev, name, errp);
98         return;
99     }
100 
101     if (!visit_type_str(v, name, &str, errp)) {
102         return;
103     }
104 
105     /*
106      * TODO Should this really be an error?  If no, the old value
107      * needs to be released before we store the new one.
108      */
109     if (!check_prop_still_unset(obj, name, *ptr, str, errp)) {
110         return;
111     }
112 
113     if (!*str) {
114         g_free(str);
115         *ptr = NULL;
116         return;
117     }
118 
119     blk = blk_by_name(str);
120     if (!blk) {
121         BlockDriverState *bs = bdrv_lookup_bs(NULL, str, NULL);
122         if (bs) {
123             /*
124              * If the device supports iothreads, it will make sure to move the
125              * block node to the right AioContext if necessary (or fail if this
126              * isn't possible because of other users). Devices that are not
127              * aware of iothreads require their BlockBackends to be in the main
128              * AioContext.
129              */
130             AioContext *ctx = iothread ? bdrv_get_aio_context(bs) :
131                                          qemu_get_aio_context();
132             blk = blk_new(ctx, 0, BLK_PERM_ALL);
133             blk_created = true;
134 
135             ret = blk_insert_bs(blk, bs, errp);
136             if (ret < 0) {
137                 goto fail;
138             }
139         }
140     }
141     if (!blk) {
142         error_setg(errp, "Property '%s.%s' can't find value '%s'",
143                    object_get_typename(OBJECT(dev)), prop->name, str);
144         goto fail;
145     }
146     if (blk_attach_dev(blk, dev) < 0) {
147         DriveInfo *dinfo = blk_legacy_dinfo(blk);
148 
149         if (dinfo && dinfo->type != IF_NONE) {
150             error_setg(errp, "Drive '%s' is already in use because "
151                        "it has been automatically connected to another "
152                        "device (did you need 'if=none' in the drive options?)",
153                        str);
154         } else {
155             error_setg(errp, "Drive '%s' is already in use by another device",
156                        str);
157         }
158         goto fail;
159     }
160 
161     *ptr = blk;
162 
163 fail:
164     if (blk_created) {
165         /* If we need to keep a reference, blk_attach_dev() took it */
166         blk_unref(blk);
167     }
168 
169     g_free(str);
170 }
171 
172 static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque,
173                       Error **errp)
174 {
175     set_drive_helper(obj, v, name, opaque, false, errp);
176 }
177 
178 static void set_drive_iothread(Object *obj, Visitor *v, const char *name,
179                                void *opaque, Error **errp)
180 {
181     set_drive_helper(obj, v, name, opaque, true, errp);
182 }
183 
184 static void release_drive(Object *obj, const char *name, void *opaque)
185 {
186     DeviceState *dev = DEVICE(obj);
187     Property *prop = opaque;
188     BlockBackend **ptr = qdev_get_prop_ptr(obj, prop);
189 
190     if (*ptr) {
191         AioContext *ctx = blk_get_aio_context(*ptr);
192 
193         aio_context_acquire(ctx);
194         blockdev_auto_del(*ptr);
195         blk_detach_dev(*ptr, dev);
196         aio_context_release(ctx);
197     }
198 }
199 
200 const PropertyInfo qdev_prop_drive = {
201     .name  = "str",
202     .description = "Node name or ID of a block device to use as a backend",
203     .get   = get_drive,
204     .set   = set_drive,
205     .release = release_drive,
206 };
207 
208 const PropertyInfo qdev_prop_drive_iothread = {
209     .name  = "str",
210     .description = "Node name or ID of a block device to use as a backend",
211     .get   = get_drive,
212     .set   = set_drive_iothread,
213     .release = release_drive,
214 };
215 
216 /* --- character device --- */
217 
218 static void get_chr(Object *obj, Visitor *v, const char *name, void *opaque,
219                     Error **errp)
220 {
221     CharBackend *be = qdev_get_prop_ptr(obj, opaque);
222     char *p;
223 
224     p = g_strdup(be->chr && be->chr->label ? be->chr->label : "");
225     visit_type_str(v, name, &p, errp);
226     g_free(p);
227 }
228 
229 static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque,
230                     Error **errp)
231 {
232     DeviceState *dev = DEVICE(obj);
233     Property *prop = opaque;
234     CharBackend *be = qdev_get_prop_ptr(obj, prop);
235     Chardev *s;
236     char *str;
237 
238     if (dev->realized) {
239         qdev_prop_set_after_realize(dev, name, errp);
240         return;
241     }
242 
243     if (!visit_type_str(v, name, &str, errp)) {
244         return;
245     }
246 
247     /*
248      * TODO Should this really be an error?  If no, the old value
249      * needs to be released before we store the new one.
250      */
251     if (!check_prop_still_unset(obj, name, be->chr, str, errp)) {
252         return;
253     }
254 
255     if (!*str) {
256         g_free(str);
257         be->chr = NULL;
258         return;
259     }
260 
261     s = qemu_chr_find(str);
262     if (s == NULL) {
263         error_setg(errp, "Property '%s.%s' can't find value '%s'",
264                    object_get_typename(obj), prop->name, str);
265     } else if (!qemu_chr_fe_init(be, s, errp)) {
266         error_prepend(errp, "Property '%s.%s' can't take value '%s': ",
267                       object_get_typename(obj), prop->name, str);
268     }
269     g_free(str);
270 }
271 
272 static void release_chr(Object *obj, const char *name, void *opaque)
273 {
274     Property *prop = opaque;
275     CharBackend *be = qdev_get_prop_ptr(obj, prop);
276 
277     qemu_chr_fe_deinit(be, false);
278 }
279 
280 const PropertyInfo qdev_prop_chr = {
281     .name  = "str",
282     .description = "ID of a chardev to use as a backend",
283     .get   = get_chr,
284     .set   = set_chr,
285     .release = release_chr,
286 };
287 
288 /* --- mac address --- */
289 
290 /*
291  * accepted syntax versions:
292  *   01:02:03:04:05:06
293  *   01-02-03-04-05-06
294  */
295 static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
296                     Error **errp)
297 {
298     Property *prop = opaque;
299     MACAddr *mac = qdev_get_prop_ptr(obj, prop);
300     char buffer[2 * 6 + 5 + 1];
301     char *p = buffer;
302 
303     snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
304              mac->a[0], mac->a[1], mac->a[2],
305              mac->a[3], mac->a[4], mac->a[5]);
306 
307     visit_type_str(v, name, &p, errp);
308 }
309 
310 static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
311                     Error **errp)
312 {
313     DeviceState *dev = DEVICE(obj);
314     Property *prop = opaque;
315     MACAddr *mac = qdev_get_prop_ptr(obj, prop);
316     int i, pos;
317     char *str;
318     const char *p;
319 
320     if (dev->realized) {
321         qdev_prop_set_after_realize(dev, name, errp);
322         return;
323     }
324 
325     if (!visit_type_str(v, name, &str, errp)) {
326         return;
327     }
328 
329     for (i = 0, pos = 0; i < 6; i++, pos += 3) {
330         long val;
331 
332         if (!qemu_isxdigit(str[pos])) {
333             goto inval;
334         }
335         if (!qemu_isxdigit(str[pos + 1])) {
336             goto inval;
337         }
338         if (i == 5) {
339             if (str[pos + 2] != '\0') {
340                 goto inval;
341             }
342         } else {
343             if (str[pos + 2] != ':' && str[pos + 2] != '-') {
344                 goto inval;
345             }
346         }
347         if (qemu_strtol(str + pos, &p, 16, &val) < 0 || val > 0xff) {
348             goto inval;
349         }
350         mac->a[i] = val;
351     }
352     g_free(str);
353     return;
354 
355 inval:
356     error_set_from_qdev_prop_error(errp, EINVAL, obj, prop, str);
357     g_free(str);
358 }
359 
360 const PropertyInfo qdev_prop_macaddr = {
361     .name  = "str",
362     .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
363     .get   = get_mac,
364     .set   = set_mac,
365 };
366 
367 void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
368                            const uint8_t *value)
369 {
370     char str[2 * 6 + 5 + 1];
371     snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
372              value[0], value[1], value[2], value[3], value[4], value[5]);
373 
374     object_property_set_str(OBJECT(dev), name, str, &error_abort);
375 }
376 
377 /* --- netdev device --- */
378 static void get_netdev(Object *obj, Visitor *v, const char *name,
379                        void *opaque, Error **errp)
380 {
381     Property *prop = opaque;
382     NICPeers *peers_ptr = qdev_get_prop_ptr(obj, prop);
383     char *p = g_strdup(peers_ptr->ncs[0] ? peers_ptr->ncs[0]->name : "");
384 
385     visit_type_str(v, name, &p, errp);
386     g_free(p);
387 }
388 
389 static void set_netdev(Object *obj, Visitor *v, const char *name,
390                        void *opaque, Error **errp)
391 {
392     DeviceState *dev = DEVICE(obj);
393     Property *prop = opaque;
394     NICPeers *peers_ptr = qdev_get_prop_ptr(obj, prop);
395     NetClientState **ncs = peers_ptr->ncs;
396     NetClientState *peers[MAX_QUEUE_NUM];
397     int queues, err = 0, i = 0;
398     char *str;
399 
400     if (dev->realized) {
401         qdev_prop_set_after_realize(dev, name, errp);
402         return;
403     }
404 
405     if (!visit_type_str(v, name, &str, errp)) {
406         return;
407     }
408 
409     queues = qemu_find_net_clients_except(str, peers,
410                                           NET_CLIENT_DRIVER_NIC,
411                                           MAX_QUEUE_NUM);
412     if (queues == 0) {
413         err = -ENOENT;
414         goto out;
415     }
416 
417     if (queues > MAX_QUEUE_NUM) {
418         error_setg(errp, "queues of backend '%s'(%d) exceeds QEMU limitation(%d)",
419                    str, queues, MAX_QUEUE_NUM);
420         goto out;
421     }
422 
423     for (i = 0; i < queues; i++) {
424         if (peers[i]->peer) {
425             err = -EEXIST;
426             goto out;
427         }
428 
429         /*
430          * TODO Should this really be an error?  If no, the old value
431          * needs to be released before we store the new one.
432          */
433         if (!check_prop_still_unset(obj, name, ncs[i], str, errp)) {
434             goto out;
435         }
436 
437         ncs[i] = peers[i];
438         ncs[i]->queue_index = i;
439     }
440 
441     peers_ptr->queues = queues;
442 
443 out:
444     error_set_from_qdev_prop_error(errp, err, obj, prop, str);
445     g_free(str);
446 }
447 
448 const PropertyInfo qdev_prop_netdev = {
449     .name  = "str",
450     .description = "ID of a netdev to use as a backend",
451     .get   = get_netdev,
452     .set   = set_netdev,
453 };
454 
455 
456 /* --- audiodev --- */
457 static void get_audiodev(Object *obj, Visitor *v, const char* name,
458                          void *opaque, Error **errp)
459 {
460     Property *prop = opaque;
461     QEMUSoundCard *card = qdev_get_prop_ptr(obj, prop);
462     char *p = g_strdup(audio_get_id(card));
463 
464     visit_type_str(v, name, &p, errp);
465     g_free(p);
466 }
467 
468 static void set_audiodev(Object *obj, Visitor *v, const char* name,
469                          void *opaque, Error **errp)
470 {
471     DeviceState *dev = DEVICE(obj);
472     Property *prop = opaque;
473     QEMUSoundCard *card = qdev_get_prop_ptr(obj, prop);
474     AudioState *state;
475     int err = 0;
476     char *str;
477 
478     if (dev->realized) {
479         qdev_prop_set_after_realize(dev, name, errp);
480         return;
481     }
482 
483     if (!visit_type_str(v, name, &str, errp)) {
484         return;
485     }
486 
487     state = audio_state_by_name(str);
488 
489     if (!state) {
490         err = -ENOENT;
491         goto out;
492     }
493     card->state = state;
494 
495 out:
496     error_set_from_qdev_prop_error(errp, err, obj, prop, str);
497     g_free(str);
498 }
499 
500 const PropertyInfo qdev_prop_audiodev = {
501     .name = "str",
502     .description = "ID of an audiodev to use as a backend",
503     /* release done on shutdown */
504     .get = get_audiodev,
505     .set = set_audiodev,
506 };
507 
508 bool qdev_prop_set_drive_err(DeviceState *dev, const char *name,
509                              BlockBackend *value, Error **errp)
510 {
511     const char *ref = "";
512 
513     if (value) {
514         ref = blk_name(value);
515         if (!*ref) {
516             const BlockDriverState *bs = blk_bs(value);
517             if (bs) {
518                 ref = bdrv_get_node_name(bs);
519             }
520         }
521     }
522 
523     return object_property_set_str(OBJECT(dev), name, ref, errp);
524 }
525 
526 void qdev_prop_set_drive(DeviceState *dev, const char *name,
527                          BlockBackend *value)
528 {
529     qdev_prop_set_drive_err(dev, name, value, &error_abort);
530 }
531 
532 void qdev_prop_set_chr(DeviceState *dev, const char *name,
533                        Chardev *value)
534 {
535     assert(!value || value->label);
536     object_property_set_str(OBJECT(dev), name, value ? value->label : "",
537                             &error_abort);
538 }
539 
540 void qdev_prop_set_netdev(DeviceState *dev, const char *name,
541                           NetClientState *value)
542 {
543     assert(!value || value->name);
544     object_property_set_str(OBJECT(dev), name, value ? value->name : "",
545                             &error_abort);
546 }
547 
548 void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
549 {
550     qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
551     if (nd->netdev) {
552         qdev_prop_set_netdev(dev, "netdev", nd->netdev);
553     }
554     if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
555         object_property_find(OBJECT(dev), "vectors")) {
556         qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
557     }
558     nd->instantiated = 1;
559 }
560 
561 /* --- lost tick policy --- */
562 
563 QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
564 
565 const PropertyInfo qdev_prop_losttickpolicy = {
566     .name  = "LostTickPolicy",
567     .enum_table  = &LostTickPolicy_lookup,
568     .get   = qdev_propinfo_get_enum,
569     .set   = qdev_propinfo_set_enum,
570     .set_default_value = qdev_propinfo_set_default_value_enum,
571 };
572 
573 /* --- blocksize --- */
574 
575 static void set_blocksize(Object *obj, Visitor *v, const char *name,
576                           void *opaque, Error **errp)
577 {
578     DeviceState *dev = DEVICE(obj);
579     Property *prop = opaque;
580     uint32_t *ptr = qdev_get_prop_ptr(obj, prop);
581     uint64_t value;
582     Error *local_err = NULL;
583 
584     if (dev->realized) {
585         qdev_prop_set_after_realize(dev, name, errp);
586         return;
587     }
588 
589     if (!visit_type_size(v, name, &value, errp)) {
590         return;
591     }
592     check_block_size(dev->id ? : "", name, value, &local_err);
593     if (local_err) {
594         error_propagate(errp, local_err);
595         return;
596     }
597     *ptr = value;
598 }
599 
600 const PropertyInfo qdev_prop_blocksize = {
601     .name  = "size",
602     .description = "A power of two between " MIN_BLOCK_SIZE_STR
603                    " and " MAX_BLOCK_SIZE_STR,
604     .get   = qdev_propinfo_get_size32,
605     .set   = set_blocksize,
606     .set_default_value = qdev_propinfo_set_default_value_uint,
607 };
608 
609 /* --- Block device error handling policy --- */
610 
611 QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int));
612 
613 const PropertyInfo qdev_prop_blockdev_on_error = {
614     .name = "BlockdevOnError",
615     .description = "Error handling policy, "
616                    "report/ignore/enospc/stop/auto",
617     .enum_table = &BlockdevOnError_lookup,
618     .get = qdev_propinfo_get_enum,
619     .set = qdev_propinfo_set_enum,
620     .set_default_value = qdev_propinfo_set_default_value_enum,
621 };
622 
623 /* --- BIOS CHS translation */
624 
625 QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
626 
627 const PropertyInfo qdev_prop_bios_chs_trans = {
628     .name = "BiosAtaTranslation",
629     .description = "Logical CHS translation algorithm, "
630                    "auto/none/lba/large/rechs",
631     .enum_table = &BiosAtaTranslation_lookup,
632     .get = qdev_propinfo_get_enum,
633     .set = qdev_propinfo_set_enum,
634     .set_default_value = qdev_propinfo_set_default_value_enum,
635 };
636 
637 /* --- FDC default drive types */
638 
639 const PropertyInfo qdev_prop_fdc_drive_type = {
640     .name = "FdcDriveType",
641     .description = "FDC drive type, "
642                    "144/288/120/none/auto",
643     .enum_table = &FloppyDriveType_lookup,
644     .get = qdev_propinfo_get_enum,
645     .set = qdev_propinfo_set_enum,
646     .set_default_value = qdev_propinfo_set_default_value_enum,
647 };
648 
649 /* --- MultiFDCompression --- */
650 
651 const PropertyInfo qdev_prop_multifd_compression = {
652     .name = "MultiFDCompression",
653     .description = "multifd_compression values, "
654                    "none/zlib/zstd",
655     .enum_table = &MultiFDCompression_lookup,
656     .get = qdev_propinfo_get_enum,
657     .set = qdev_propinfo_set_enum,
658     .set_default_value = qdev_propinfo_set_default_value_enum,
659 };
660 
661 /* --- Reserved Region --- */
662 
663 /*
664  * Accepted syntax:
665  *   <low address>:<high address>:<type>
666  *   where low/high addresses are uint64_t in hexadecimal
667  *   and type is a non-negative decimal integer
668  */
669 static void get_reserved_region(Object *obj, Visitor *v, const char *name,
670                                 void *opaque, Error **errp)
671 {
672     Property *prop = opaque;
673     ReservedRegion *rr = qdev_get_prop_ptr(obj, prop);
674     char buffer[64];
675     char *p = buffer;
676     int rc;
677 
678     rc = snprintf(buffer, sizeof(buffer), "0x%"PRIx64":0x%"PRIx64":%u",
679                   rr->low, rr->high, rr->type);
680     assert(rc < sizeof(buffer));
681 
682     visit_type_str(v, name, &p, errp);
683 }
684 
685 static void set_reserved_region(Object *obj, Visitor *v, const char *name,
686                                 void *opaque, Error **errp)
687 {
688     DeviceState *dev = DEVICE(obj);
689     Property *prop = opaque;
690     ReservedRegion *rr = qdev_get_prop_ptr(obj, prop);
691     Error *local_err = NULL;
692     const char *endptr;
693     char *str;
694     int ret;
695 
696     if (dev->realized) {
697         qdev_prop_set_after_realize(dev, name, errp);
698         return;
699     }
700 
701     visit_type_str(v, name, &str, &local_err);
702     if (local_err) {
703         error_propagate(errp, local_err);
704         return;
705     }
706 
707     ret = qemu_strtou64(str, &endptr, 16, &rr->low);
708     if (ret) {
709         error_setg(errp, "start address of '%s'"
710                    " must be a hexadecimal integer", name);
711         goto out;
712     }
713     if (*endptr != ':') {
714         goto separator_error;
715     }
716 
717     ret = qemu_strtou64(endptr + 1, &endptr, 16, &rr->high);
718     if (ret) {
719         error_setg(errp, "end address of '%s'"
720                    " must be a hexadecimal integer", name);
721         goto out;
722     }
723     if (*endptr != ':') {
724         goto separator_error;
725     }
726 
727     ret = qemu_strtoui(endptr + 1, &endptr, 10, &rr->type);
728     if (ret) {
729         error_setg(errp, "type of '%s'"
730                    " must be a non-negative decimal integer", name);
731     }
732     goto out;
733 
734 separator_error:
735     error_setg(errp, "reserved region fields must be separated with ':'");
736 out:
737     g_free(str);
738     return;
739 }
740 
741 const PropertyInfo qdev_prop_reserved_region = {
742     .name  = "reserved_region",
743     .description = "Reserved Region, example: 0xFEE00000:0xFEEFFFFF:0",
744     .get   = get_reserved_region,
745     .set   = set_reserved_region,
746 };
747 
748 /* --- pci address --- */
749 
750 /*
751  * bus-local address, i.e. "$slot" or "$slot.$fn"
752  */
753 static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
754                           void *opaque, Error **errp)
755 {
756     DeviceState *dev = DEVICE(obj);
757     Property *prop = opaque;
758     int32_t value, *ptr = qdev_get_prop_ptr(obj, prop);
759     unsigned int slot, fn, n;
760     char *str;
761 
762     if (dev->realized) {
763         qdev_prop_set_after_realize(dev, name, errp);
764         return;
765     }
766 
767     if (!visit_type_str(v, name, &str, NULL)) {
768         if (!visit_type_int32(v, name, &value, errp)) {
769             return;
770         }
771         if (value < -1 || value > 255) {
772             error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
773                        name ? name : "null", "a value between -1 and 255");
774             return;
775         }
776         *ptr = value;
777         return;
778     }
779 
780     if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
781         fn = 0;
782         if (sscanf(str, "%x%n", &slot, &n) != 1) {
783             goto invalid;
784         }
785     }
786     if (str[n] != '\0' || fn > 7 || slot > 31) {
787         goto invalid;
788     }
789     *ptr = slot << 3 | fn;
790     g_free(str);
791     return;
792 
793 invalid:
794     error_set_from_qdev_prop_error(errp, EINVAL, obj, prop, str);
795     g_free(str);
796 }
797 
798 static int print_pci_devfn(Object *obj, Property *prop, char *dest,
799                            size_t len)
800 {
801     int32_t *ptr = qdev_get_prop_ptr(obj, prop);
802 
803     if (*ptr == -1) {
804         return snprintf(dest, len, "<unset>");
805     } else {
806         return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
807     }
808 }
809 
810 const PropertyInfo qdev_prop_pci_devfn = {
811     .name  = "int32",
812     .description = "Slot and optional function number, example: 06.0 or 06",
813     .print = print_pci_devfn,
814     .get   = qdev_propinfo_get_int32,
815     .set   = set_pci_devfn,
816     .set_default_value = qdev_propinfo_set_default_value_int,
817 };
818 
819 /* --- pci host address --- */
820 
821 static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
822                                  void *opaque, Error **errp)
823 {
824     Property *prop = opaque;
825     PCIHostDeviceAddress *addr = qdev_get_prop_ptr(obj, prop);
826     char buffer[] = "ffff:ff:ff.f";
827     char *p = buffer;
828     int rc = 0;
829 
830     /*
831      * Catch "invalid" device reference from vfio-pci and allow the
832      * default buffer representing the non-existent device to be used.
833      */
834     if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) {
835         rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d",
836                       addr->domain, addr->bus, addr->slot, addr->function);
837         assert(rc == sizeof(buffer) - 1);
838     }
839 
840     visit_type_str(v, name, &p, errp);
841 }
842 
843 /*
844  * Parse [<domain>:]<bus>:<slot>.<func>
845  *   if <domain> is not supplied, it's assumed to be 0.
846  */
847 static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
848                                  void *opaque, Error **errp)
849 {
850     DeviceState *dev = DEVICE(obj);
851     Property *prop = opaque;
852     PCIHostDeviceAddress *addr = qdev_get_prop_ptr(obj, prop);
853     char *str, *p;
854     char *e;
855     unsigned long val;
856     unsigned long dom = 0, bus = 0;
857     unsigned int slot = 0, func = 0;
858 
859     if (dev->realized) {
860         qdev_prop_set_after_realize(dev, name, errp);
861         return;
862     }
863 
864     if (!visit_type_str(v, name, &str, errp)) {
865         return;
866     }
867 
868     p = str;
869     val = strtoul(p, &e, 16);
870     if (e == p || *e != ':') {
871         goto inval;
872     }
873     bus = val;
874 
875     p = e + 1;
876     val = strtoul(p, &e, 16);
877     if (e == p) {
878         goto inval;
879     }
880     if (*e == ':') {
881         dom = bus;
882         bus = val;
883         p = e + 1;
884         val = strtoul(p, &e, 16);
885         if (e == p) {
886             goto inval;
887         }
888     }
889     slot = val;
890 
891     if (*e != '.') {
892         goto inval;
893     }
894     p = e + 1;
895     val = strtoul(p, &e, 10);
896     if (e == p) {
897         goto inval;
898     }
899     func = val;
900 
901     if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
902         goto inval;
903     }
904 
905     if (*e) {
906         goto inval;
907     }
908 
909     addr->domain = dom;
910     addr->bus = bus;
911     addr->slot = slot;
912     addr->function = func;
913 
914     g_free(str);
915     return;
916 
917 inval:
918     error_set_from_qdev_prop_error(errp, EINVAL, obj, prop, str);
919     g_free(str);
920 }
921 
922 const PropertyInfo qdev_prop_pci_host_devaddr = {
923     .name = "str",
924     .description = "Address (bus/device/function) of "
925                    "the host device, example: 04:10.0",
926     .get = get_pci_host_devaddr,
927     .set = set_pci_host_devaddr,
928 };
929 
930 /* --- OffAutoPCIBAR off/auto/bar0/bar1/bar2/bar3/bar4/bar5 --- */
931 
932 const PropertyInfo qdev_prop_off_auto_pcibar = {
933     .name = "OffAutoPCIBAR",
934     .description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5",
935     .enum_table = &OffAutoPCIBAR_lookup,
936     .get = qdev_propinfo_get_enum,
937     .set = qdev_propinfo_set_enum,
938     .set_default_value = qdev_propinfo_set_default_value_enum,
939 };
940 
941 /* --- PCIELinkSpeed 2_5/5/8/16 -- */
942 
943 static void get_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
944                                    void *opaque, Error **errp)
945 {
946     Property *prop = opaque;
947     PCIExpLinkSpeed *p = qdev_get_prop_ptr(obj, prop);
948     int speed;
949 
950     switch (*p) {
951     case QEMU_PCI_EXP_LNK_2_5GT:
952         speed = PCIE_LINK_SPEED_2_5;
953         break;
954     case QEMU_PCI_EXP_LNK_5GT:
955         speed = PCIE_LINK_SPEED_5;
956         break;
957     case QEMU_PCI_EXP_LNK_8GT:
958         speed = PCIE_LINK_SPEED_8;
959         break;
960     case QEMU_PCI_EXP_LNK_16GT:
961         speed = PCIE_LINK_SPEED_16;
962         break;
963     default:
964         /* Unreachable */
965         abort();
966     }
967 
968     visit_type_enum(v, prop->name, &speed, prop->info->enum_table, errp);
969 }
970 
971 static void set_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
972                                    void *opaque, Error **errp)
973 {
974     DeviceState *dev = DEVICE(obj);
975     Property *prop = opaque;
976     PCIExpLinkSpeed *p = qdev_get_prop_ptr(obj, prop);
977     int speed;
978 
979     if (dev->realized) {
980         qdev_prop_set_after_realize(dev, name, errp);
981         return;
982     }
983 
984     if (!visit_type_enum(v, prop->name, &speed, prop->info->enum_table,
985                          errp)) {
986         return;
987     }
988 
989     switch (speed) {
990     case PCIE_LINK_SPEED_2_5:
991         *p = QEMU_PCI_EXP_LNK_2_5GT;
992         break;
993     case PCIE_LINK_SPEED_5:
994         *p = QEMU_PCI_EXP_LNK_5GT;
995         break;
996     case PCIE_LINK_SPEED_8:
997         *p = QEMU_PCI_EXP_LNK_8GT;
998         break;
999     case PCIE_LINK_SPEED_16:
1000         *p = QEMU_PCI_EXP_LNK_16GT;
1001         break;
1002     default:
1003         /* Unreachable */
1004         abort();
1005     }
1006 }
1007 
1008 const PropertyInfo qdev_prop_pcie_link_speed = {
1009     .name = "PCIELinkSpeed",
1010     .description = "2_5/5/8/16",
1011     .enum_table = &PCIELinkSpeed_lookup,
1012     .get = get_prop_pcielinkspeed,
1013     .set = set_prop_pcielinkspeed,
1014     .set_default_value = qdev_propinfo_set_default_value_enum,
1015 };
1016 
1017 /* --- PCIELinkWidth 1/2/4/8/12/16/32 -- */
1018 
1019 static void get_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
1020                                    void *opaque, Error **errp)
1021 {
1022     Property *prop = opaque;
1023     PCIExpLinkWidth *p = qdev_get_prop_ptr(obj, prop);
1024     int width;
1025 
1026     switch (*p) {
1027     case QEMU_PCI_EXP_LNK_X1:
1028         width = PCIE_LINK_WIDTH_1;
1029         break;
1030     case QEMU_PCI_EXP_LNK_X2:
1031         width = PCIE_LINK_WIDTH_2;
1032         break;
1033     case QEMU_PCI_EXP_LNK_X4:
1034         width = PCIE_LINK_WIDTH_4;
1035         break;
1036     case QEMU_PCI_EXP_LNK_X8:
1037         width = PCIE_LINK_WIDTH_8;
1038         break;
1039     case QEMU_PCI_EXP_LNK_X12:
1040         width = PCIE_LINK_WIDTH_12;
1041         break;
1042     case QEMU_PCI_EXP_LNK_X16:
1043         width = PCIE_LINK_WIDTH_16;
1044         break;
1045     case QEMU_PCI_EXP_LNK_X32:
1046         width = PCIE_LINK_WIDTH_32;
1047         break;
1048     default:
1049         /* Unreachable */
1050         abort();
1051     }
1052 
1053     visit_type_enum(v, prop->name, &width, prop->info->enum_table, errp);
1054 }
1055 
1056 static void set_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
1057                                    void *opaque, Error **errp)
1058 {
1059     DeviceState *dev = DEVICE(obj);
1060     Property *prop = opaque;
1061     PCIExpLinkWidth *p = qdev_get_prop_ptr(obj, prop);
1062     int width;
1063 
1064     if (dev->realized) {
1065         qdev_prop_set_after_realize(dev, name, errp);
1066         return;
1067     }
1068 
1069     if (!visit_type_enum(v, prop->name, &width, prop->info->enum_table,
1070                          errp)) {
1071         return;
1072     }
1073 
1074     switch (width) {
1075     case PCIE_LINK_WIDTH_1:
1076         *p = QEMU_PCI_EXP_LNK_X1;
1077         break;
1078     case PCIE_LINK_WIDTH_2:
1079         *p = QEMU_PCI_EXP_LNK_X2;
1080         break;
1081     case PCIE_LINK_WIDTH_4:
1082         *p = QEMU_PCI_EXP_LNK_X4;
1083         break;
1084     case PCIE_LINK_WIDTH_8:
1085         *p = QEMU_PCI_EXP_LNK_X8;
1086         break;
1087     case PCIE_LINK_WIDTH_12:
1088         *p = QEMU_PCI_EXP_LNK_X12;
1089         break;
1090     case PCIE_LINK_WIDTH_16:
1091         *p = QEMU_PCI_EXP_LNK_X16;
1092         break;
1093     case PCIE_LINK_WIDTH_32:
1094         *p = QEMU_PCI_EXP_LNK_X32;
1095         break;
1096     default:
1097         /* Unreachable */
1098         abort();
1099     }
1100 }
1101 
1102 const PropertyInfo qdev_prop_pcie_link_width = {
1103     .name = "PCIELinkWidth",
1104     .description = "1/2/4/8/12/16/32",
1105     .enum_table = &PCIELinkWidth_lookup,
1106     .get = get_prop_pcielinkwidth,
1107     .set = set_prop_pcielinkwidth,
1108     .set_default_value = qdev_propinfo_set_default_value_enum,
1109 };
1110 
1111 /* --- UUID --- */
1112 
1113 static void get_uuid(Object *obj, Visitor *v, const char *name, void *opaque,
1114                      Error **errp)
1115 {
1116     Property *prop = opaque;
1117     QemuUUID *uuid = qdev_get_prop_ptr(obj, prop);
1118     char buffer[UUID_FMT_LEN + 1];
1119     char *p = buffer;
1120 
1121     qemu_uuid_unparse(uuid, buffer);
1122 
1123     visit_type_str(v, name, &p, errp);
1124 }
1125 
1126 #define UUID_VALUE_AUTO        "auto"
1127 
1128 static void set_uuid(Object *obj, Visitor *v, const char *name, void *opaque,
1129                     Error **errp)
1130 {
1131     DeviceState *dev = DEVICE(obj);
1132     Property *prop = opaque;
1133     QemuUUID *uuid = qdev_get_prop_ptr(obj, prop);
1134     char *str;
1135 
1136     if (dev->realized) {
1137         qdev_prop_set_after_realize(dev, name, errp);
1138         return;
1139     }
1140 
1141     if (!visit_type_str(v, name, &str, errp)) {
1142         return;
1143     }
1144 
1145     if (!strcmp(str, UUID_VALUE_AUTO)) {
1146         qemu_uuid_generate(uuid);
1147     } else if (qemu_uuid_parse(str, uuid) < 0) {
1148         error_set_from_qdev_prop_error(errp, EINVAL, obj, prop, str);
1149     }
1150     g_free(str);
1151 }
1152 
1153 static void set_default_uuid_auto(ObjectProperty *op, const Property *prop)
1154 {
1155     object_property_set_default_str(op, UUID_VALUE_AUTO);
1156 }
1157 
1158 const PropertyInfo qdev_prop_uuid = {
1159     .name  = "str",
1160     .description = "UUID (aka GUID) or \"" UUID_VALUE_AUTO
1161         "\" for random value (default)",
1162     .get   = get_uuid,
1163     .set   = set_uuid,
1164     .set_default_value = set_default_uuid_auto,
1165 };
1166