From c0d67ade53a6db090a1c17676ffcdcf16052dfb4 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Wed, 30 Sep 2020 18:49:40 +0200 Subject: hw/core/qdev-properties: Use qemu_strtol() in set_mac() handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MACAddr structure contains an array of uint8_t. Previously if a value was out of the [0..255] range, it was silently casted and no input validation was done. Replace strtol() by qemu_strtol() -- so checkpatch.pl won't complain if we move this code later -- and return EINVAL if the input is invalid. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200930164949.1425294-3-philmd@redhat.com> Signed-off-by: Eduardo Habkost --- hw/core/qdev-properties.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'hw/core/qdev-properties.c') diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 343c824da0..080ba319a1 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -1,4 +1,5 @@ #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "net/net.h" #include "hw/qdev-properties.h" #include "qapi/error.h" @@ -524,7 +525,8 @@ static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque, Property *prop = opaque; MACAddr *mac = qdev_get_prop_ptr(dev, prop); int i, pos; - char *str, *p; + char *str; + const char *p; if (dev->realized) { qdev_prop_set_after_realize(dev, name, errp); @@ -536,6 +538,8 @@ static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque, } for (i = 0, pos = 0; i < 6; i++, pos += 3) { + long val; + if (!qemu_isxdigit(str[pos])) { goto inval; } @@ -551,7 +555,10 @@ static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque, goto inval; } } - mac->a[i] = strtol(str+pos, &p, 16); + if (qemu_strtol(str + pos, &p, 16, &val) < 0 || val > 0xff) { + goto inval; + } + mac->a[i] = val; } g_free(str); return; -- cgit 1.4.1 From bccb20c49df1bd683248a366021973901c11982f Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Wed, 30 Sep 2020 18:49:41 +0200 Subject: hw/core/qdev-properties: Use qemu_strtoul() in set_pci_host_devaddr() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace strtoul() by qemu_strtoul() so checkpatch.pl won't complain if we move this code later. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200930164949.1425294-4-philmd@redhat.com> Signed-off-by: Eduardo Habkost --- hw/core/qdev-properties.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'hw/core/qdev-properties.c') diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 080ba319a1..a1190a5db9 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -951,7 +951,7 @@ static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name, Property *prop = opaque; PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); char *str, *p; - char *e; + const char *e; unsigned long val; unsigned long dom = 0, bus = 0; unsigned int slot = 0, func = 0; @@ -966,23 +966,23 @@ static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name, } p = str; - val = strtoul(p, &e, 16); - if (e == p || *e != ':') { + if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0xffff || e == p) { + goto inval; + } + if (*e != ':') { goto inval; } bus = val; - p = e + 1; - val = strtoul(p, &e, 16); - if (e == p) { + p = (char *)e + 1; + if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) { goto inval; } if (*e == ':') { dom = bus; bus = val; - p = e + 1; - val = strtoul(p, &e, 16); - if (e == p) { + p = (char *)e + 1; + if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) { goto inval; } } @@ -991,14 +991,13 @@ static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name, if (*e != '.') { goto inval; } - p = e + 1; - val = strtoul(p, &e, 10); - if (e == p) { + p = (char *)e + 1; + if (qemu_strtoul(p, &e, 10, &val) < 0 || val > 7 || e == p) { goto inval; } func = val; - if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) { + if (bus > 0xff) { goto inval; } -- cgit 1.4.1 From 9ee468f3295e080abe8aed6ffddc339a94590d65 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Wed, 30 Sep 2020 18:49:42 +0200 Subject: hw/core/qdev-properties: Fix code style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We will soon move this code, fix its style to avoid checkpatch.pl to complain. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200930164949.1425294-5-philmd@redhat.com> Signed-off-by: Eduardo Habkost --- hw/core/qdev-properties.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'hw/core/qdev-properties.c') diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index a1190a5db9..071fd5864a 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -543,15 +543,15 @@ static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque, if (!qemu_isxdigit(str[pos])) { goto inval; } - if (!qemu_isxdigit(str[pos+1])) { + if (!qemu_isxdigit(str[pos + 1])) { goto inval; } if (i == 5) { - if (str[pos+2] != '\0') { + if (str[pos + 2] != '\0') { goto inval; } } else { - if (str[pos+2] != ':' && str[pos+2] != '-') { + if (str[pos + 2] != ':' && str[pos + 2] != '-') { goto inval; } } @@ -898,8 +898,8 @@ static void set_blocksize(Object *obj, Visitor *v, const char *name, /* We rely on power-of-2 blocksizes for bitmasks */ if ((value & (value - 1)) != 0) { error_setg(errp, - "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2", - dev->id ?: "", name, (int64_t)value); + "Property %s.%s doesn't take value '%" PRId64 "', " + "it's not a power of 2", dev->id ?: "", name, (int64_t)value); return; } -- cgit 1.4.1 From a2974439ada0a3eda1fed7d80c8670ce94cbceef Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Wed, 30 Sep 2020 18:49:43 +0200 Subject: hw/core/qdev-properties: Export enum-related functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are going to split this file and reuse these static functions. Add the local "qdev-prop-internal.h" header declaring them. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200930164949.1425294-6-philmd@redhat.com> Signed-off-by: Eduardo Habkost --- hw/core/qdev-prop-internal.h | 19 +++++++++++++++ hw/core/qdev-properties.c | 58 +++++++++++++++++++++++--------------------- 2 files changed, 49 insertions(+), 28 deletions(-) create mode 100644 hw/core/qdev-prop-internal.h (limited to 'hw/core/qdev-properties.c') diff --git a/hw/core/qdev-prop-internal.h b/hw/core/qdev-prop-internal.h new file mode 100644 index 0000000000..2a8c9a306a --- /dev/null +++ b/hw/core/qdev-prop-internal.h @@ -0,0 +1,19 @@ +/* + * qdev property parsing + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef HW_CORE_QDEV_PROP_INTERNAL_H +#define HW_CORE_QDEV_PROP_INTERNAL_H + +void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp); +void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp); + +void qdev_propinfo_set_default_value_enum(ObjectProperty *op, + const Property *prop); + +#endif diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 071fd5864a..76417d0936 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -18,6 +18,7 @@ #include "qemu/uuid.h" #include "qemu/units.h" #include "qemu/cutils.h" +#include "qdev-prop-internal.h" void qdev_prop_set_after_realize(DeviceState *dev, const char *name, Error **errp) @@ -53,8 +54,8 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) return ptr; } -static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) +void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { DeviceState *dev = DEVICE(obj); Property *prop = opaque; @@ -63,8 +64,8 @@ static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque, visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp); } -static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) +void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { DeviceState *dev = DEVICE(obj); Property *prop = opaque; @@ -78,7 +79,8 @@ static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque, visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp); } -static void set_default_value_enum(ObjectProperty *op, const Property *prop) +void qdev_propinfo_set_default_value_enum(ObjectProperty *op, + const Property *prop) { object_property_set_default_str(op, qapi_enum_lookup(prop->info->enum_table, prop->defval.i)); @@ -669,9 +671,9 @@ const PropertyInfo qdev_prop_on_off_auto = { .name = "OnOffAuto", .description = "on/off/auto", .enum_table = &OnOffAuto_lookup, - .get = get_enum, - .set = set_enum, - .set_default_value = set_default_value_enum, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, }; /* --- lost tick policy --- */ @@ -681,9 +683,9 @@ QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int)); const PropertyInfo qdev_prop_losttickpolicy = { .name = "LostTickPolicy", .enum_table = &LostTickPolicy_lookup, - .get = get_enum, - .set = set_enum, - .set_default_value = set_default_value_enum, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, }; /* --- Block device error handling policy --- */ @@ -695,9 +697,9 @@ const PropertyInfo qdev_prop_blockdev_on_error = { .description = "Error handling policy, " "report/ignore/enospc/stop/auto", .enum_table = &BlockdevOnError_lookup, - .get = get_enum, - .set = set_enum, - .set_default_value = set_default_value_enum, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, }; /* --- BIOS CHS translation */ @@ -709,9 +711,9 @@ const PropertyInfo qdev_prop_bios_chs_trans = { .description = "Logical CHS translation algorithm, " "auto/none/lba/large/rechs", .enum_table = &BiosAtaTranslation_lookup, - .get = get_enum, - .set = set_enum, - .set_default_value = set_default_value_enum, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, }; /* --- FDC default drive types */ @@ -721,9 +723,9 @@ const PropertyInfo qdev_prop_fdc_drive_type = { .description = "FDC drive type, " "144/288/120/none/auto", .enum_table = &FloppyDriveType_lookup, - .get = get_enum, - .set = set_enum, - .set_default_value = set_default_value_enum, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, }; /* --- MultiFDCompression --- */ @@ -733,9 +735,9 @@ const PropertyInfo qdev_prop_multifd_compression = { .description = "multifd_compression values, " "none/zlib/zstd", .enum_table = &MultiFDCompression_lookup, - .get = get_enum, - .set = set_enum, - .set_default_value = set_default_value_enum, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, }; /* --- pci address --- */ @@ -1416,9 +1418,9 @@ const PropertyInfo qdev_prop_off_auto_pcibar = { .name = "OffAutoPCIBAR", .description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5", .enum_table = &OffAutoPCIBAR_lookup, - .get = get_enum, - .set = set_enum, - .set_default_value = set_default_value_enum, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, }; /* --- PCIELinkSpeed 2_5/5/8/16 -- */ @@ -1495,7 +1497,7 @@ const PropertyInfo qdev_prop_pcie_link_speed = { .enum_table = &PCIELinkSpeed_lookup, .get = get_prop_pcielinkspeed, .set = set_prop_pcielinkspeed, - .set_default_value = set_default_value_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, }; /* --- PCIELinkWidth 1/2/4/8/12/16/32 -- */ @@ -1590,5 +1592,5 @@ const PropertyInfo qdev_prop_pcie_link_width = { .enum_table = &PCIELinkWidth_lookup, .get = get_prop_pcielinkwidth, .set = set_prop_pcielinkwidth, - .set_default_value = set_default_value_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, }; -- cgit 1.4.1 From 79bdf29c08a592a4c5d2f9b7bb462e71ee568988 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Wed, 30 Sep 2020 18:49:44 +0200 Subject: hw/core/qdev-properties: Export qdev_prop_enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200930164949.1425294-7-philmd@redhat.com> Signed-off-by: Eduardo Habkost --- hw/core/qdev-properties.c | 7 +++++++ include/hw/qdev-properties.h | 1 + 2 files changed, 8 insertions(+) (limited to 'hw/core/qdev-properties.c') diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 76417d0936..31dfe441e2 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -86,6 +86,13 @@ void qdev_propinfo_set_default_value_enum(ObjectProperty *op, qapi_enum_lookup(prop->info->enum_table, prop->defval.i)); } +const PropertyInfo qdev_prop_enum = { + .name = "enum", + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + /* Bit */ static uint32_t qdev_get_prop_mask(Property *prop) diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index 528310bb22..4437450065 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -8,6 +8,7 @@ extern const PropertyInfo qdev_prop_bit; extern const PropertyInfo qdev_prop_bit64; extern const PropertyInfo qdev_prop_bool; +extern const PropertyInfo qdev_prop_enum; extern const PropertyInfo qdev_prop_uint8; extern const PropertyInfo qdev_prop_uint16; extern const PropertyInfo qdev_prop_uint32; -- cgit 1.4.1 From 93e163e4ef9e714830c5a84a8ac554fa41fed7b5 Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Wed, 30 Sep 2020 18:49:45 +0200 Subject: hw/core/qdev-properties: Export some integer-related functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are going to split this file and reuse these static functions. Declare them in the local "qdev-prop-internal.h" header. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200930164949.1425294-8-philmd@redhat.com> Signed-off-by: Eduardo Habkost --- hw/core/qdev-prop-internal.h | 11 +++++++++++ hw/core/qdev-properties.c | 46 +++++++++++++++++++++++--------------------- 2 files changed, 35 insertions(+), 22 deletions(-) (limited to 'hw/core/qdev-properties.c') diff --git a/hw/core/qdev-prop-internal.h b/hw/core/qdev-prop-internal.h index 2a8c9a306a..9cf5cc1d51 100644 --- a/hw/core/qdev-prop-internal.h +++ b/hw/core/qdev-prop-internal.h @@ -15,5 +15,16 @@ void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name, void qdev_propinfo_set_default_value_enum(ObjectProperty *op, const Property *prop); +void qdev_propinfo_set_default_value_int(ObjectProperty *op, + const Property *prop); +void qdev_propinfo_set_default_value_uint(ObjectProperty *op, + const Property *prop); + +void qdev_propinfo_get_uint16(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp); +void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp); +void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp); #endif diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 31dfe441e2..37e309077a 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -271,12 +271,14 @@ static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque, visit_type_uint8(v, name, ptr, errp); } -static void set_default_value_int(ObjectProperty *op, const Property *prop) +void qdev_propinfo_set_default_value_int(ObjectProperty *op, + const Property *prop) { object_property_set_default_int(op, prop->defval.i); } -static void set_default_value_uint(ObjectProperty *op, const Property *prop) +void qdev_propinfo_set_default_value_uint(ObjectProperty *op, + const Property *prop) { object_property_set_default_uint(op, prop->defval.u); } @@ -285,13 +287,13 @@ const PropertyInfo qdev_prop_uint8 = { .name = "uint8", .get = get_uint8, .set = set_uint8, - .set_default_value = set_default_value_uint, + .set_default_value = qdev_propinfo_set_default_value_uint, }; /* --- 16bit integer --- */ -static void get_uint16(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) +void qdev_propinfo_get_uint16(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { DeviceState *dev = DEVICE(obj); Property *prop = opaque; @@ -317,9 +319,9 @@ static void set_uint16(Object *obj, Visitor *v, const char *name, const PropertyInfo qdev_prop_uint16 = { .name = "uint16", - .get = get_uint16, + .get = qdev_propinfo_get_uint16, .set = set_uint16, - .set_default_value = set_default_value_uint, + .set_default_value = qdev_propinfo_set_default_value_uint, }; /* --- 32bit integer --- */ @@ -349,8 +351,8 @@ static void set_uint32(Object *obj, Visitor *v, const char *name, visit_type_uint32(v, name, ptr, errp); } -static void get_int32(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) +void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { DeviceState *dev = DEVICE(obj); Property *prop = opaque; @@ -378,14 +380,14 @@ const PropertyInfo qdev_prop_uint32 = { .name = "uint32", .get = get_uint32, .set = set_uint32, - .set_default_value = set_default_value_uint, + .set_default_value = qdev_propinfo_set_default_value_uint, }; const PropertyInfo qdev_prop_int32 = { .name = "int32", - .get = get_int32, + .get = qdev_propinfo_get_int32, .set = set_int32, - .set_default_value = set_default_value_int, + .set_default_value = qdev_propinfo_set_default_value_int, }; /* --- 64bit integer --- */ @@ -444,14 +446,14 @@ const PropertyInfo qdev_prop_uint64 = { .name = "uint64", .get = get_uint64, .set = set_uint64, - .set_default_value = set_default_value_uint, + .set_default_value = qdev_propinfo_set_default_value_uint, }; const PropertyInfo qdev_prop_int64 = { .name = "int64", .get = get_int64, .set = set_int64, - .set_default_value = set_default_value_int, + .set_default_value = qdev_propinfo_set_default_value_int, }; /* --- string --- */ @@ -820,8 +822,8 @@ const PropertyInfo qdev_prop_pci_devfn = { /* --- 32bit unsigned int 'size' type --- */ -static void get_size32(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) +void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { DeviceState *dev = DEVICE(obj); Property *prop = opaque; @@ -861,9 +863,9 @@ static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque, const PropertyInfo qdev_prop_size32 = { .name = "size", - .get = get_size32, + .get = qdev_propinfo_get_size32, .set = set_size32, - .set_default_value = set_default_value_uint, + .set_default_value = qdev_propinfo_set_default_value_uint, }; /* --- blocksize --- */ @@ -919,9 +921,9 @@ const PropertyInfo qdev_prop_blocksize = { .name = "size", .description = "A power of two between " MIN_BLOCK_SIZE_STR " and " MAX_BLOCK_SIZE_STR, - .get = get_size32, + .get = qdev_propinfo_get_size32, .set = set_blocksize, - .set_default_value = set_default_value_uint, + .set_default_value = qdev_propinfo_set_default_value_uint, }; /* --- pci host address --- */ @@ -1190,7 +1192,7 @@ const PropertyInfo qdev_prop_arraylen = { .name = "uint32", .get = get_uint32, .set = set_prop_arraylen, - .set_default_value = set_default_value_uint, + .set_default_value = qdev_propinfo_set_default_value_uint, }; /* --- public helpers --- */ @@ -1401,7 +1403,7 @@ const PropertyInfo qdev_prop_size = { .name = "size", .get = get_size, .set = set_size, - .set_default_value = set_default_value_uint, + .set_default_value = qdev_propinfo_set_default_value_uint, }; /* --- object link property --- */ -- cgit 1.4.1 From aa1859cc77df9f547cded0b906a0c47f1760be2b Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Wed, 30 Sep 2020 18:49:46 +0200 Subject: hw/core/qdev-properties: Extract system-mode specific properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move properties specific to machines into a separate file. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20200930164949.1425294-9-philmd@redhat.com> Signed-off-by: Eduardo Habkost --- hw/core/qdev-properties-system.c | 687 ++++++++++++++++++++++++++++++++++++++- hw/core/qdev-properties.c | 674 -------------------------------------- 2 files changed, 679 insertions(+), 682 deletions(-) (limited to 'hw/core/qdev-properties.c') diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index b29daf4fb5..49bdd12581 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -11,19 +11,25 @@ */ #include "qemu/osdep.h" -#include "audio/audio.h" -#include "net/net.h" #include "hw/qdev-properties.h" #include "qapi/error.h" +#include "qapi/visitor.h" +#include "qapi/qapi-types-block.h" +#include "qapi/qapi-types-machine.h" +#include "qapi/qapi-types-migration.h" #include "qapi/qmp/qerror.h" +#include "qemu/ctype.h" +#include "qemu/cutils.h" +#include "qemu/units.h" +#include "qemu/error-report.h" +#include "qdev-prop-internal.h" + +#include "audio/audio.h" +#include "chardev/char-fe.h" #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" -#include "hw/block/block.h" -#include "net/hub.h" -#include "qapi/visitor.h" -#include "chardev/char-fe.h" -#include "sysemu/iothread.h" -#include "sysemu/tpm_backend.h" +#include "net/net.h" +#include "hw/pci/pci.h" static bool check_prop_still_unset(DeviceState *dev, const char *name, const void *old_val, const char *new_val, @@ -280,6 +286,96 @@ const PropertyInfo qdev_prop_chr = { .release = release_chr, }; +/* --- mac address --- */ + +/* + * accepted syntax versions: + * 01:02:03:04:05:06 + * 01-02-03-04-05-06 + */ +static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque, + Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + MACAddr *mac = qdev_get_prop_ptr(dev, prop); + char buffer[2 * 6 + 5 + 1]; + char *p = buffer; + + snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x", + mac->a[0], mac->a[1], mac->a[2], + mac->a[3], mac->a[4], mac->a[5]); + + visit_type_str(v, name, &p, errp); +} + +static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque, + Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + MACAddr *mac = qdev_get_prop_ptr(dev, prop); + int i, pos; + char *str; + const char *p; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + if (!visit_type_str(v, name, &str, errp)) { + return; + } + + for (i = 0, pos = 0; i < 6; i++, pos += 3) { + long val; + + if (!qemu_isxdigit(str[pos])) { + goto inval; + } + if (!qemu_isxdigit(str[pos + 1])) { + goto inval; + } + if (i == 5) { + if (str[pos + 2] != '\0') { + goto inval; + } + } else { + if (str[pos + 2] != ':' && str[pos + 2] != '-') { + goto inval; + } + } + if (qemu_strtol(str + pos, &p, 16, &val) < 0 || val > 0xff) { + goto inval; + } + mac->a[i] = val; + } + g_free(str); + return; + +inval: + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); + g_free(str); +} + +const PropertyInfo qdev_prop_macaddr = { + .name = "str", + .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56", + .get = get_mac, + .set = set_mac, +}; + +void qdev_prop_set_macaddr(DeviceState *dev, const char *name, + const uint8_t *value) +{ + char str[2 * 6 + 5 + 1]; + snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x", + value[0], value[1], value[2], value[3], value[4], value[5]); + + object_property_set_str(OBJECT(dev), name, str, &error_abort); +} + /* --- netdev device --- */ static void get_netdev(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) @@ -465,3 +561,578 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) } nd->instantiated = 1; } + +/* --- lost tick policy --- */ + +QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int)); + +const PropertyInfo qdev_prop_losttickpolicy = { + .name = "LostTickPolicy", + .enum_table = &LostTickPolicy_lookup, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + +/* --- blocksize --- */ + +/* lower limit is sector size */ +#define MIN_BLOCK_SIZE 512 +#define MIN_BLOCK_SIZE_STR "512 B" +/* + * upper limit is arbitrary, 2 MiB looks sufficient for all sensible uses, and + * matches qcow2 cluster size limit + */ +#define MAX_BLOCK_SIZE (2 * MiB) +#define MAX_BLOCK_SIZE_STR "2 MiB" + +static void set_blocksize(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + uint32_t *ptr = qdev_get_prop_ptr(dev, prop); + uint64_t value; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + if (!visit_type_size(v, name, &value, errp)) { + return; + } + /* value of 0 means "unset" */ + if (value && (value < MIN_BLOCK_SIZE || value > MAX_BLOCK_SIZE)) { + error_setg(errp, + "Property %s.%s doesn't take value %" PRIu64 + " (minimum: " MIN_BLOCK_SIZE_STR + ", maximum: " MAX_BLOCK_SIZE_STR ")", + dev->id ? : "", name, value); + return; + } + + /* We rely on power-of-2 blocksizes for bitmasks */ + if ((value & (value - 1)) != 0) { + error_setg(errp, + "Property %s.%s doesn't take value '%" PRId64 "', " + "it's not a power of 2", dev->id ?: "", name, (int64_t)value); + return; + } + + *ptr = value; +} + +const PropertyInfo qdev_prop_blocksize = { + .name = "size", + .description = "A power of two between " MIN_BLOCK_SIZE_STR + " and " MAX_BLOCK_SIZE_STR, + .get = qdev_propinfo_get_size32, + .set = set_blocksize, + .set_default_value = qdev_propinfo_set_default_value_uint, +}; + +/* --- Block device error handling policy --- */ + +QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int)); + +const PropertyInfo qdev_prop_blockdev_on_error = { + .name = "BlockdevOnError", + .description = "Error handling policy, " + "report/ignore/enospc/stop/auto", + .enum_table = &BlockdevOnError_lookup, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + +/* --- BIOS CHS translation */ + +QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int)); + +const PropertyInfo qdev_prop_bios_chs_trans = { + .name = "BiosAtaTranslation", + .description = "Logical CHS translation algorithm, " + "auto/none/lba/large/rechs", + .enum_table = &BiosAtaTranslation_lookup, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + +/* --- FDC default drive types */ + +const PropertyInfo qdev_prop_fdc_drive_type = { + .name = "FdcDriveType", + .description = "FDC drive type, " + "144/288/120/none/auto", + .enum_table = &FloppyDriveType_lookup, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + +/* --- MultiFDCompression --- */ + +const PropertyInfo qdev_prop_multifd_compression = { + .name = "MultiFDCompression", + .description = "multifd_compression values, " + "none/zlib/zstd", + .enum_table = &MultiFDCompression_lookup, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + +/* --- Reserved Region --- */ + +/* + * Accepted syntax: + * :: + * where low/high addresses are uint64_t in hexadecimal + * and type is a non-negative decimal integer + */ +static void get_reserved_region(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + ReservedRegion *rr = qdev_get_prop_ptr(dev, prop); + char buffer[64]; + char *p = buffer; + int rc; + + rc = snprintf(buffer, sizeof(buffer), "0x%"PRIx64":0x%"PRIx64":%u", + rr->low, rr->high, rr->type); + assert(rc < sizeof(buffer)); + + visit_type_str(v, name, &p, errp); +} + +static void set_reserved_region(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + ReservedRegion *rr = qdev_get_prop_ptr(dev, prop); + Error *local_err = NULL; + const char *endptr; + char *str; + int ret; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + visit_type_str(v, name, &str, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + ret = qemu_strtou64(str, &endptr, 16, &rr->low); + if (ret) { + error_setg(errp, "start address of '%s'" + " must be a hexadecimal integer", name); + goto out; + } + if (*endptr != ':') { + goto separator_error; + } + + ret = qemu_strtou64(endptr + 1, &endptr, 16, &rr->high); + if (ret) { + error_setg(errp, "end address of '%s'" + " must be a hexadecimal integer", name); + goto out; + } + if (*endptr != ':') { + goto separator_error; + } + + ret = qemu_strtoui(endptr + 1, &endptr, 10, &rr->type); + if (ret) { + error_setg(errp, "type of '%s'" + " must be a non-negative decimal integer", name); + } + goto out; + +separator_error: + error_setg(errp, "reserved region fields must be separated with ':'"); +out: + g_free(str); + return; +} + +const PropertyInfo qdev_prop_reserved_region = { + .name = "reserved_region", + .description = "Reserved Region, example: 0xFEE00000:0xFEEFFFFF:0", + .get = get_reserved_region, + .set = set_reserved_region, +}; + +/* --- pci address --- */ + +/* + * bus-local address, i.e. "$slot" or "$slot.$fn" + */ +static void set_pci_devfn(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + int32_t value, *ptr = qdev_get_prop_ptr(dev, prop); + unsigned int slot, fn, n; + char *str; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + if (!visit_type_str(v, name, &str, NULL)) { + if (!visit_type_int32(v, name, &value, errp)) { + return; + } + if (value < -1 || value > 255) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, + name ? name : "null", "pci_devfn"); + return; + } + *ptr = value; + return; + } + + if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) { + fn = 0; + if (sscanf(str, "%x%n", &slot, &n) != 1) { + goto invalid; + } + } + if (str[n] != '\0' || fn > 7 || slot > 31) { + goto invalid; + } + *ptr = slot << 3 | fn; + g_free(str); + return; + +invalid: + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); + g_free(str); +} + +static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, + size_t len) +{ + int32_t *ptr = qdev_get_prop_ptr(dev, prop); + + if (*ptr == -1) { + return snprintf(dest, len, ""); + } else { + return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7); + } +} + +const PropertyInfo qdev_prop_pci_devfn = { + .name = "int32", + .description = "Slot and optional function number, example: 06.0 or 06", + .print = print_pci_devfn, + .get = qdev_propinfo_get_int32, + .set = set_pci_devfn, + .set_default_value = qdev_propinfo_set_default_value_int, +}; + +/* --- pci host address --- */ + +static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); + char buffer[] = "ffff:ff:ff.f"; + char *p = buffer; + int rc = 0; + + /* + * Catch "invalid" device reference from vfio-pci and allow the + * default buffer representing the non-existent device to be used. + */ + if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) { + rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d", + addr->domain, addr->bus, addr->slot, addr->function); + assert(rc == sizeof(buffer) - 1); + } + + visit_type_str(v, name, &p, errp); +} + +/* + * Parse [:]:. + * if is not supplied, it's assumed to be 0. + */ +static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); + char *str, *p; + const char *e; + unsigned long val; + unsigned long dom = 0, bus = 0; + unsigned int slot = 0, func = 0; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + if (!visit_type_str(v, name, &str, errp)) { + return; + } + + p = str; + if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0xffff || e == p) { + goto inval; + } + if (*e != ':') { + goto inval; + } + bus = val; + + p = (char *)e + 1; + if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) { + goto inval; + } + if (*e == ':') { + dom = bus; + bus = val; + p = (char *)e + 1; + if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) { + goto inval; + } + } + slot = val; + + if (*e != '.') { + goto inval; + } + p = (char *)e + 1; + if (qemu_strtoul(p, &e, 10, &val) < 0 || val > 7 || e == p) { + goto inval; + } + func = val; + + if (bus > 0xff) { + goto inval; + } + + if (*e) { + goto inval; + } + + addr->domain = dom; + addr->bus = bus; + addr->slot = slot; + addr->function = func; + + g_free(str); + return; + +inval: + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); + g_free(str); +} + +const PropertyInfo qdev_prop_pci_host_devaddr = { + .name = "str", + .description = "Address (bus/device/function) of " + "the host device, example: 04:10.0", + .get = get_pci_host_devaddr, + .set = set_pci_host_devaddr, +}; + +/* --- OffAutoPCIBAR off/auto/bar0/bar1/bar2/bar3/bar4/bar5 --- */ + +const PropertyInfo qdev_prop_off_auto_pcibar = { + .name = "OffAutoPCIBAR", + .description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5", + .enum_table = &OffAutoPCIBAR_lookup, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + +/* --- PCIELinkSpeed 2_5/5/8/16 -- */ + +static void get_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop); + int speed; + + switch (*p) { + case QEMU_PCI_EXP_LNK_2_5GT: + speed = PCIE_LINK_SPEED_2_5; + break; + case QEMU_PCI_EXP_LNK_5GT: + speed = PCIE_LINK_SPEED_5; + break; + case QEMU_PCI_EXP_LNK_8GT: + speed = PCIE_LINK_SPEED_8; + break; + case QEMU_PCI_EXP_LNK_16GT: + speed = PCIE_LINK_SPEED_16; + break; + default: + /* Unreachable */ + abort(); + } + + visit_type_enum(v, prop->name, &speed, prop->info->enum_table, errp); +} + +static void set_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop); + int speed; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + if (!visit_type_enum(v, prop->name, &speed, prop->info->enum_table, + errp)) { + return; + } + + switch (speed) { + case PCIE_LINK_SPEED_2_5: + *p = QEMU_PCI_EXP_LNK_2_5GT; + break; + case PCIE_LINK_SPEED_5: + *p = QEMU_PCI_EXP_LNK_5GT; + break; + case PCIE_LINK_SPEED_8: + *p = QEMU_PCI_EXP_LNK_8GT; + break; + case PCIE_LINK_SPEED_16: + *p = QEMU_PCI_EXP_LNK_16GT; + break; + default: + /* Unreachable */ + abort(); + } +} + +const PropertyInfo qdev_prop_pcie_link_speed = { + .name = "PCIELinkSpeed", + .description = "2_5/5/8/16", + .enum_table = &PCIELinkSpeed_lookup, + .get = get_prop_pcielinkspeed, + .set = set_prop_pcielinkspeed, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; + +/* --- PCIELinkWidth 1/2/4/8/12/16/32 -- */ + +static void get_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop); + int width; + + switch (*p) { + case QEMU_PCI_EXP_LNK_X1: + width = PCIE_LINK_WIDTH_1; + break; + case QEMU_PCI_EXP_LNK_X2: + width = PCIE_LINK_WIDTH_2; + break; + case QEMU_PCI_EXP_LNK_X4: + width = PCIE_LINK_WIDTH_4; + break; + case QEMU_PCI_EXP_LNK_X8: + width = PCIE_LINK_WIDTH_8; + break; + case QEMU_PCI_EXP_LNK_X12: + width = PCIE_LINK_WIDTH_12; + break; + case QEMU_PCI_EXP_LNK_X16: + width = PCIE_LINK_WIDTH_16; + break; + case QEMU_PCI_EXP_LNK_X32: + width = PCIE_LINK_WIDTH_32; + break; + default: + /* Unreachable */ + abort(); + } + + visit_type_enum(v, prop->name, &width, prop->info->enum_table, errp); +} + +static void set_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop); + int width; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + if (!visit_type_enum(v, prop->name, &width, prop->info->enum_table, + errp)) { + return; + } + + switch (width) { + case PCIE_LINK_WIDTH_1: + *p = QEMU_PCI_EXP_LNK_X1; + break; + case PCIE_LINK_WIDTH_2: + *p = QEMU_PCI_EXP_LNK_X2; + break; + case PCIE_LINK_WIDTH_4: + *p = QEMU_PCI_EXP_LNK_X4; + break; + case PCIE_LINK_WIDTH_8: + *p = QEMU_PCI_EXP_LNK_X8; + break; + case PCIE_LINK_WIDTH_12: + *p = QEMU_PCI_EXP_LNK_X12; + break; + case PCIE_LINK_WIDTH_16: + *p = QEMU_PCI_EXP_LNK_X16; + break; + case PCIE_LINK_WIDTH_32: + *p = QEMU_PCI_EXP_LNK_X32; + break; + default: + /* Unreachable */ + abort(); + } +} + +const PropertyInfo qdev_prop_pcie_link_width = { + .name = "PCIELinkWidth", + .description = "1/2/4/8/12/16/32", + .enum_table = &PCIELinkWidth_lookup, + .get = get_prop_pcielinkwidth, + .set = set_prop_pcielinkwidth, + .set_default_value = qdev_propinfo_set_default_value_enum, +}; diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 37e309077a..509cbf155d 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -1,20 +1,11 @@ #include "qemu/osdep.h" -#include "qemu/cutils.h" -#include "net/net.h" #include "hw/qdev-properties.h" #include "qapi/error.h" -#include "hw/pci/pci.h" -#include "qapi/qapi-types-block.h" -#include "qapi/qapi-types-machine.h" #include "qapi/qapi-types-misc.h" #include "qapi/qmp/qerror.h" #include "qemu/ctype.h" #include "qemu/error-report.h" -#include "qapi/qapi-types-migration.h" -#include "hw/block/block.h" -#include "net/hub.h" #include "qapi/visitor.h" -#include "chardev/char.h" #include "qemu/uuid.h" #include "qemu/units.h" #include "qemu/cutils.h" @@ -506,174 +497,6 @@ const PropertyInfo qdev_prop_string = { .set = set_string, }; -/* --- mac address --- */ - -/* - * accepted syntax versions: - * 01:02:03:04:05:06 - * 01-02-03-04-05-06 - */ -static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - MACAddr *mac = qdev_get_prop_ptr(dev, prop); - char buffer[2 * 6 + 5 + 1]; - char *p = buffer; - - snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x", - mac->a[0], mac->a[1], mac->a[2], - mac->a[3], mac->a[4], mac->a[5]); - - visit_type_str(v, name, &p, errp); -} - -static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - MACAddr *mac = qdev_get_prop_ptr(dev, prop); - int i, pos; - char *str; - const char *p; - - if (dev->realized) { - qdev_prop_set_after_realize(dev, name, errp); - return; - } - - if (!visit_type_str(v, name, &str, errp)) { - return; - } - - for (i = 0, pos = 0; i < 6; i++, pos += 3) { - long val; - - if (!qemu_isxdigit(str[pos])) { - goto inval; - } - if (!qemu_isxdigit(str[pos + 1])) { - goto inval; - } - if (i == 5) { - if (str[pos + 2] != '\0') { - goto inval; - } - } else { - if (str[pos + 2] != ':' && str[pos + 2] != '-') { - goto inval; - } - } - if (qemu_strtol(str + pos, &p, 16, &val) < 0 || val > 0xff) { - goto inval; - } - mac->a[i] = val; - } - g_free(str); - return; - -inval: - error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); - g_free(str); -} - -const PropertyInfo qdev_prop_macaddr = { - .name = "str", - .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56", - .get = get_mac, - .set = set_mac, -}; - -/* --- Reserved Region --- */ - -/* - * Accepted syntax: - * :: - * where low/high addresses are uint64_t in hexadecimal - * and type is a non-negative decimal integer - */ -static void get_reserved_region(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - ReservedRegion *rr = qdev_get_prop_ptr(dev, prop); - char buffer[64]; - char *p = buffer; - int rc; - - rc = snprintf(buffer, sizeof(buffer), "0x%"PRIx64":0x%"PRIx64":%u", - rr->low, rr->high, rr->type); - assert(rc < sizeof(buffer)); - - visit_type_str(v, name, &p, errp); -} - -static void set_reserved_region(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - ReservedRegion *rr = qdev_get_prop_ptr(dev, prop); - Error *local_err = NULL; - const char *endptr; - char *str; - int ret; - - if (dev->realized) { - qdev_prop_set_after_realize(dev, name, errp); - return; - } - - visit_type_str(v, name, &str, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - - ret = qemu_strtou64(str, &endptr, 16, &rr->low); - if (ret) { - error_setg(errp, "start address of '%s'" - " must be a hexadecimal integer", name); - goto out; - } - if (*endptr != ':') { - goto separator_error; - } - - ret = qemu_strtou64(endptr + 1, &endptr, 16, &rr->high); - if (ret) { - error_setg(errp, "end address of '%s'" - " must be a hexadecimal integer", name); - goto out; - } - if (*endptr != ':') { - goto separator_error; - } - - ret = qemu_strtoui(endptr + 1, &endptr, 10, &rr->type); - if (ret) { - error_setg(errp, "type of '%s'" - " must be a non-negative decimal integer", name); - } - goto out; - -separator_error: - error_setg(errp, "reserved region fields must be separated with ':'"); -out: - g_free(str); - return; -} - -const PropertyInfo qdev_prop_reserved_region = { - .name = "reserved_region", - .description = "Reserved Region, example: 0xFEE00000:0xFEEFFFFF:0", - .get = get_reserved_region, - .set = set_reserved_region, -}; - /* --- on/off/auto --- */ const PropertyInfo qdev_prop_on_off_auto = { @@ -685,141 +508,6 @@ const PropertyInfo qdev_prop_on_off_auto = { .set_default_value = qdev_propinfo_set_default_value_enum, }; -/* --- lost tick policy --- */ - -QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int)); - -const PropertyInfo qdev_prop_losttickpolicy = { - .name = "LostTickPolicy", - .enum_table = &LostTickPolicy_lookup, - .get = qdev_propinfo_get_enum, - .set = qdev_propinfo_set_enum, - .set_default_value = qdev_propinfo_set_default_value_enum, -}; - -/* --- Block device error handling policy --- */ - -QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int)); - -const PropertyInfo qdev_prop_blockdev_on_error = { - .name = "BlockdevOnError", - .description = "Error handling policy, " - "report/ignore/enospc/stop/auto", - .enum_table = &BlockdevOnError_lookup, - .get = qdev_propinfo_get_enum, - .set = qdev_propinfo_set_enum, - .set_default_value = qdev_propinfo_set_default_value_enum, -}; - -/* --- BIOS CHS translation */ - -QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int)); - -const PropertyInfo qdev_prop_bios_chs_trans = { - .name = "BiosAtaTranslation", - .description = "Logical CHS translation algorithm, " - "auto/none/lba/large/rechs", - .enum_table = &BiosAtaTranslation_lookup, - .get = qdev_propinfo_get_enum, - .set = qdev_propinfo_set_enum, - .set_default_value = qdev_propinfo_set_default_value_enum, -}; - -/* --- FDC default drive types */ - -const PropertyInfo qdev_prop_fdc_drive_type = { - .name = "FdcDriveType", - .description = "FDC drive type, " - "144/288/120/none/auto", - .enum_table = &FloppyDriveType_lookup, - .get = qdev_propinfo_get_enum, - .set = qdev_propinfo_set_enum, - .set_default_value = qdev_propinfo_set_default_value_enum, -}; - -/* --- MultiFDCompression --- */ - -const PropertyInfo qdev_prop_multifd_compression = { - .name = "MultiFDCompression", - .description = "multifd_compression values, " - "none/zlib/zstd", - .enum_table = &MultiFDCompression_lookup, - .get = qdev_propinfo_get_enum, - .set = qdev_propinfo_set_enum, - .set_default_value = qdev_propinfo_set_default_value_enum, -}; - -/* --- pci address --- */ - -/* - * bus-local address, i.e. "$slot" or "$slot.$fn" - */ -static void set_pci_devfn(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - int32_t value, *ptr = qdev_get_prop_ptr(dev, prop); - unsigned int slot, fn, n; - char *str; - - if (dev->realized) { - qdev_prop_set_after_realize(dev, name, errp); - return; - } - - if (!visit_type_str(v, name, &str, NULL)) { - if (!visit_type_int32(v, name, &value, errp)) { - return; - } - if (value < -1 || value > 255) { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, - name ? name : "null", "pci_devfn"); - return; - } - *ptr = value; - return; - } - - if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) { - fn = 0; - if (sscanf(str, "%x%n", &slot, &n) != 1) { - goto invalid; - } - } - if (str[n] != '\0' || fn > 7 || slot > 31) { - goto invalid; - } - *ptr = slot << 3 | fn; - g_free(str); - return; - -invalid: - error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); - g_free(str); -} - -static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, - size_t len) -{ - int32_t *ptr = qdev_get_prop_ptr(dev, prop); - - if (*ptr == -1) { - return snprintf(dest, len, ""); - } else { - return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7); - } -} - -const PropertyInfo qdev_prop_pci_devfn = { - .name = "int32", - .description = "Slot and optional function number, example: 06.0 or 06", - .print = print_pci_devfn, - .get = get_int32, - .set = set_pci_devfn, - .set_default_value = set_default_value_int, -}; - /* --- 32bit unsigned int 'size' type --- */ void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name, @@ -868,175 +556,6 @@ const PropertyInfo qdev_prop_size32 = { .set_default_value = qdev_propinfo_set_default_value_uint, }; -/* --- blocksize --- */ - -/* lower limit is sector size */ -#define MIN_BLOCK_SIZE 512 -#define MIN_BLOCK_SIZE_STR "512 B" -/* - * upper limit is arbitrary, 2 MiB looks sufficient for all sensible uses, and - * matches qcow2 cluster size limit - */ -#define MAX_BLOCK_SIZE (2 * MiB) -#define MAX_BLOCK_SIZE_STR "2 MiB" - -static void set_blocksize(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - uint32_t *ptr = qdev_get_prop_ptr(dev, prop); - uint64_t value; - - if (dev->realized) { - qdev_prop_set_after_realize(dev, name, errp); - return; - } - - if (!visit_type_size(v, name, &value, errp)) { - return; - } - /* value of 0 means "unset" */ - if (value && (value < MIN_BLOCK_SIZE || value > MAX_BLOCK_SIZE)) { - error_setg(errp, - "Property %s.%s doesn't take value %" PRIu64 - " (minimum: " MIN_BLOCK_SIZE_STR - ", maximum: " MAX_BLOCK_SIZE_STR ")", - dev->id ? : "", name, value); - return; - } - - /* We rely on power-of-2 blocksizes for bitmasks */ - if ((value & (value - 1)) != 0) { - error_setg(errp, - "Property %s.%s doesn't take value '%" PRId64 "', " - "it's not a power of 2", dev->id ?: "", name, (int64_t)value); - return; - } - - *ptr = value; -} - -const PropertyInfo qdev_prop_blocksize = { - .name = "size", - .description = "A power of two between " MIN_BLOCK_SIZE_STR - " and " MAX_BLOCK_SIZE_STR, - .get = qdev_propinfo_get_size32, - .set = set_blocksize, - .set_default_value = qdev_propinfo_set_default_value_uint, -}; - -/* --- pci host address --- */ - -static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); - char buffer[] = "ffff:ff:ff.f"; - char *p = buffer; - int rc = 0; - - /* - * Catch "invalid" device reference from vfio-pci and allow the - * default buffer representing the non-existent device to be used. - */ - if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) { - rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d", - addr->domain, addr->bus, addr->slot, addr->function); - assert(rc == sizeof(buffer) - 1); - } - - visit_type_str(v, name, &p, errp); -} - -/* - * Parse [:]:. - * if is not supplied, it's assumed to be 0. - */ -static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); - char *str, *p; - const char *e; - unsigned long val; - unsigned long dom = 0, bus = 0; - unsigned int slot = 0, func = 0; - - if (dev->realized) { - qdev_prop_set_after_realize(dev, name, errp); - return; - } - - if (!visit_type_str(v, name, &str, errp)) { - return; - } - - p = str; - if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0xffff || e == p) { - goto inval; - } - if (*e != ':') { - goto inval; - } - bus = val; - - p = (char *)e + 1; - if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) { - goto inval; - } - if (*e == ':') { - dom = bus; - bus = val; - p = (char *)e + 1; - if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) { - goto inval; - } - } - slot = val; - - if (*e != '.') { - goto inval; - } - p = (char *)e + 1; - if (qemu_strtoul(p, &e, 10, &val) < 0 || val > 7 || e == p) { - goto inval; - } - func = val; - - if (bus > 0xff) { - goto inval; - } - - if (*e) { - goto inval; - } - - addr->domain = dom; - addr->bus = bus; - addr->slot = slot; - addr->function = func; - - g_free(str); - return; - -inval: - error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); - g_free(str); -} - -const PropertyInfo qdev_prop_pci_host_devaddr = { - .name = "str", - .description = "Address (bus/device/function) of " - "the host device, example: 04:10.0", - .get = get_pci_host_devaddr, - .set = set_pci_host_devaddr, -}; - /* --- UUID --- */ static void get_uuid(Object *obj, Visitor *v, const char *name, void *opaque, @@ -1286,16 +805,6 @@ void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value) object_property_set_str(OBJECT(dev), name, value, &error_abort); } -void qdev_prop_set_macaddr(DeviceState *dev, const char *name, - const uint8_t *value) -{ - char str[2 * 6 + 5 + 1]; - snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x", - value[0], value[1], value[2], value[3], value[4], value[5]); - - object_property_set_str(OBJECT(dev), name, str, &error_abort); -} - void qdev_prop_set_enum(DeviceState *dev, const char *name, int value) { Property *prop; @@ -1420,186 +929,3 @@ const PropertyInfo qdev_prop_link = { .name = "link", .create = create_link_property, }; - -/* --- OffAutoPCIBAR off/auto/bar0/bar1/bar2/bar3/bar4/bar5 --- */ - -const PropertyInfo qdev_prop_off_auto_pcibar = { - .name = "OffAutoPCIBAR", - .description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5", - .enum_table = &OffAutoPCIBAR_lookup, - .get = qdev_propinfo_get_enum, - .set = qdev_propinfo_set_enum, - .set_default_value = qdev_propinfo_set_default_value_enum, -}; - -/* --- PCIELinkSpeed 2_5/5/8/16 -- */ - -static void get_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop); - int speed; - - switch (*p) { - case QEMU_PCI_EXP_LNK_2_5GT: - speed = PCIE_LINK_SPEED_2_5; - break; - case QEMU_PCI_EXP_LNK_5GT: - speed = PCIE_LINK_SPEED_5; - break; - case QEMU_PCI_EXP_LNK_8GT: - speed = PCIE_LINK_SPEED_8; - break; - case QEMU_PCI_EXP_LNK_16GT: - speed = PCIE_LINK_SPEED_16; - break; - default: - /* Unreachable */ - abort(); - } - - visit_type_enum(v, prop->name, &speed, prop->info->enum_table, errp); -} - -static void set_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop); - int speed; - - if (dev->realized) { - qdev_prop_set_after_realize(dev, name, errp); - return; - } - - if (!visit_type_enum(v, prop->name, &speed, prop->info->enum_table, - errp)) { - return; - } - - switch (speed) { - case PCIE_LINK_SPEED_2_5: - *p = QEMU_PCI_EXP_LNK_2_5GT; - break; - case PCIE_LINK_SPEED_5: - *p = QEMU_PCI_EXP_LNK_5GT; - break; - case PCIE_LINK_SPEED_8: - *p = QEMU_PCI_EXP_LNK_8GT; - break; - case PCIE_LINK_SPEED_16: - *p = QEMU_PCI_EXP_LNK_16GT; - break; - default: - /* Unreachable */ - abort(); - } -} - -const PropertyInfo qdev_prop_pcie_link_speed = { - .name = "PCIELinkSpeed", - .description = "2_5/5/8/16", - .enum_table = &PCIELinkSpeed_lookup, - .get = get_prop_pcielinkspeed, - .set = set_prop_pcielinkspeed, - .set_default_value = qdev_propinfo_set_default_value_enum, -}; - -/* --- PCIELinkWidth 1/2/4/8/12/16/32 -- */ - -static void get_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop); - int width; - - switch (*p) { - case QEMU_PCI_EXP_LNK_X1: - width = PCIE_LINK_WIDTH_1; - break; - case QEMU_PCI_EXP_LNK_X2: - width = PCIE_LINK_WIDTH_2; - break; - case QEMU_PCI_EXP_LNK_X4: - width = PCIE_LINK_WIDTH_4; - break; - case QEMU_PCI_EXP_LNK_X8: - width = PCIE_LINK_WIDTH_8; - break; - case QEMU_PCI_EXP_LNK_X12: - width = PCIE_LINK_WIDTH_12; - break; - case QEMU_PCI_EXP_LNK_X16: - width = PCIE_LINK_WIDTH_16; - break; - case QEMU_PCI_EXP_LNK_X32: - width = PCIE_LINK_WIDTH_32; - break; - default: - /* Unreachable */ - abort(); - } - - visit_type_enum(v, prop->name, &width, prop->info->enum_table, errp); -} - -static void set_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - DeviceState *dev = DEVICE(obj); - Property *prop = opaque; - PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop); - int width; - - if (dev->realized) { - qdev_prop_set_after_realize(dev, name, errp); - return; - } - - if (!visit_type_enum(v, prop->name, &width, prop->info->enum_table, - errp)) { - return; - } - - switch (width) { - case PCIE_LINK_WIDTH_1: - *p = QEMU_PCI_EXP_LNK_X1; - break; - case PCIE_LINK_WIDTH_2: - *p = QEMU_PCI_EXP_LNK_X2; - break; - case PCIE_LINK_WIDTH_4: - *p = QEMU_PCI_EXP_LNK_X4; - break; - case PCIE_LINK_WIDTH_8: - *p = QEMU_PCI_EXP_LNK_X8; - break; - case PCIE_LINK_WIDTH_12: - *p = QEMU_PCI_EXP_LNK_X12; - break; - case PCIE_LINK_WIDTH_16: - *p = QEMU_PCI_EXP_LNK_X16; - break; - case PCIE_LINK_WIDTH_32: - *p = QEMU_PCI_EXP_LNK_X32; - break; - default: - /* Unreachable */ - abort(); - } -} - -const PropertyInfo qdev_prop_pcie_link_width = { - .name = "PCIELinkWidth", - .description = "1/2/4/8/12/16/32", - .enum_table = &PCIELinkWidth_lookup, - .get = get_prop_pcielinkwidth, - .set = set_prop_pcielinkwidth, - .set_default_value = qdev_propinfo_set_default_value_enum, -}; -- cgit 1.4.1