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