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