From 768a9ebe188bd0a6172a9a4e64777d21fff7f014 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 9 Feb 2012 09:53:32 +0100 Subject: qdev: accept both strings and integers for PCI addresses Visitors allow a limited form of polymorphism. Exploit it to support setting the non-legacy PCI address property both as a DD.F string and as an 8-bit integer. The 8-bit integer form is just too clumsy, it is unlikely that we will ever drop it. Signed-off-by: Paolo Bonzini --- hw/qdev-properties.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) (limited to 'hw') diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 7b74dd5be..0deb37800 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -943,25 +943,40 @@ PropertyInfo qdev_prop_losttickpolicy = { /* * bus-local address, i.e. "$slot" or "$slot.$fn" */ -static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str) +static void set_pci_devfn(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) { + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; uint32_t *ptr = qdev_get_prop_ptr(dev, prop); unsigned int slot, fn, n; + Error *local_err = NULL; + char *str = (char *)""; + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_str(v, &str, name, &local_err); + if (local_err) { + return set_int32(obj, v, opaque, name, errp); + } if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) { fn = 0; if (sscanf(str, "%x%n", &slot, &n) != 1) { - return -EINVAL; + goto invalid; } } - if (str[n] != '\0') - return -EINVAL; - if (fn > 7) - return -EINVAL; - if (slot > 31) - return -EINVAL; + if (str[n] != '\0' || fn > 7 || slot > 31) { + goto invalid; + } *ptr = slot << 3 | fn; - return 0; + return; + +invalid: + error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); } static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len) @@ -978,10 +993,9 @@ static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t PropertyInfo qdev_prop_pci_devfn = { .name = "int32", .legacy_name = "pci-devfn", - .parse = parse_pci_devfn, .print = print_pci_devfn, .get = get_int32, - .set = set_int32, + .set = set_pci_devfn, /* FIXME: this should be -1...255, but the address is stored * into an uint32_t rather than int32_t. */ -- cgit v1.2.3 From 97aa6e9b8f9df37add21d86fac1a9ca6ce7df9b7 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 9 Feb 2012 10:07:38 +0100 Subject: qdev: accept hex properties only if prefixed by 0x Hex properties are an obstacle to removal of old qdev string parsing, but even here we can lay down the foundations for future simplification. In general, they are rarely used and their printed form is more interesting than the parsing. For example you'd usually set isa-serial.index instead of isa-serial.iobase. And luckily our main client, libvirt only cares about few of these, and always sets them with a 0x prefix. So the series stops accepting bare hexadecimal numbers, preparing for making legacy properties read-only in 1.3 or so. The read side will stay as long as "info qtree" is with us. Signed-off-by: Paolo Bonzini --- hw/qdev-properties.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'hw') diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 0deb37800..a4545f796 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -164,6 +164,10 @@ static int parse_hex8(DeviceState *dev, Property *prop, const char *str) uint8_t *ptr = qdev_get_prop_ptr(dev, prop); char *end; + if (str[0] != '0' || str[1] != 'x') { + return -EINVAL; + } + *ptr = strtoul(str, &end, 16); if ((*end != '\0') || (end == str)) { return -EINVAL; @@ -369,6 +373,10 @@ static int parse_hex32(DeviceState *dev, Property *prop, const char *str) uint32_t *ptr = qdev_get_prop_ptr(dev, prop); char *end; + if (str[0] != '0' || str[1] != 'x') { + return -EINVAL; + } + *ptr = strtoul(str, &end, 16); if ((*end != '\0') || (end == str)) { return -EINVAL; @@ -456,6 +464,10 @@ static int parse_hex64(DeviceState *dev, Property *prop, const char *str) uint64_t *ptr = qdev_get_prop_ptr(dev, prop); char *end; + if (str[0] != '0' || str[1] != 'x') { + return -EINVAL; + } + *ptr = strtoull(str, &end, 16); if ((*end != '\0') || (end == str)) { return -EINVAL; -- cgit v1.2.3 From 0c96e2856e30d9d3eba68e2c87f6163b6ffdf0db Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 9 Feb 2012 10:12:08 +0100 Subject: qdev: use built-in QOM string parser object_property_parse lets us drop the legacy setters when their task is done just as well by the string visitors. Signed-off-by: Paolo Bonzini --- hw/qdev-properties.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index a4545f796..e13d80bba 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -1080,9 +1080,9 @@ int qdev_prop_parse(DeviceState *dev, const char *name, const char *value) legacy_name = g_strdup_printf("legacy-%s", name); if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) { - object_property_set_str(OBJECT(dev), value, legacy_name, &err); + object_property_parse(OBJECT(dev), value, legacy_name, &err); } else { - object_property_set_str(OBJECT(dev), value, name, &err); + object_property_parse(OBJECT(dev), value, name, &err); } g_free(legacy_name); -- cgit v1.2.3 From 5cb9b56acfc0b50acf7ccd2d044ab4991c47fdde Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 9 Feb 2012 10:12:21 +0100 Subject: qdev: drop unnecessary parse/print methods More qdev printers could have been removed in the previous series, and object_property_parse also made several parsers unnecessary. In fact, the new code is even more robust with respect to overflows, so clean them up! Signed-off-by: Paolo Bonzini --- hw/qdev-properties.c | 134 --------------------------------------------------- 1 file changed, 134 deletions(-) (limited to 'hw') diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index e13d80bba..0423af1c3 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -27,16 +27,6 @@ static void bit_prop_set(DeviceState *dev, Property *props, bool val) } /* Bit */ -static int parse_bit(DeviceState *dev, Property *prop, const char *str) -{ - if (!strcasecmp(str, "on")) - bit_prop_set(dev, prop, true); - else if (!strcasecmp(str, "off")) - bit_prop_set(dev, prop, false); - else - return -EINVAL; - return 0; -} static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len) { @@ -79,7 +69,6 @@ static void set_bit(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_bit = { .name = "boolean", .legacy_name = "on/off", - .parse = parse_bit, .print = print_bit, .get = get_bit, .set = set_bit, @@ -87,26 +76,6 @@ PropertyInfo qdev_prop_bit = { /* --- 8bit integer --- */ -static int parse_uint8(DeviceState *dev, Property *prop, const char *str) -{ - uint8_t *ptr = qdev_get_prop_ptr(dev, prop); - char *end; - - /* accept both hex and decimal */ - *ptr = strtoul(str, &end, 0); - if ((*end != '\0') || (end == str)) { - return -EINVAL; - } - - return 0; -} - -static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len) -{ - uint8_t *ptr = qdev_get_prop_ptr(dev, prop); - return snprintf(dest, len, "%" PRIu8, *ptr); -} - static void get_int8(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { @@ -149,8 +118,6 @@ static void set_int8(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_uint8 = { .name = "uint8", - .parse = parse_uint8, - .print = print_uint8, .get = get_int8, .set = set_int8, .min = 0, @@ -195,26 +162,6 @@ PropertyInfo qdev_prop_hex8 = { /* --- 16bit integer --- */ -static int parse_uint16(DeviceState *dev, Property *prop, const char *str) -{ - uint16_t *ptr = qdev_get_prop_ptr(dev, prop); - char *end; - - /* accept both hex and decimal */ - *ptr = strtoul(str, &end, 0); - if ((*end != '\0') || (end == str)) { - return -EINVAL; - } - - return 0; -} - -static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len) -{ - uint16_t *ptr = qdev_get_prop_ptr(dev, prop); - return snprintf(dest, len, "%" PRIu16, *ptr); -} - static void get_int16(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { @@ -257,8 +204,6 @@ static void set_int16(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_uint16 = { .name = "uint16", - .parse = parse_uint16, - .print = print_uint16, .get = get_int16, .set = set_int16, .min = 0, @@ -267,26 +212,6 @@ PropertyInfo qdev_prop_uint16 = { /* --- 32bit integer --- */ -static int parse_uint32(DeviceState *dev, Property *prop, const char *str) -{ - uint32_t *ptr = qdev_get_prop_ptr(dev, prop); - char *end; - - /* accept both hex and decimal */ - *ptr = strtoul(str, &end, 0); - if ((*end != '\0') || (end == str)) { - return -EINVAL; - } - - return 0; -} - -static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len) -{ - uint32_t *ptr = qdev_get_prop_ptr(dev, prop); - return snprintf(dest, len, "%" PRIu32, *ptr); -} - static void get_int32(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { @@ -329,37 +254,14 @@ static void set_int32(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_uint32 = { .name = "uint32", - .parse = parse_uint32, - .print = print_uint32, .get = get_int32, .set = set_int32, .min = 0, .max = 0xFFFFFFFFULL, }; -static int parse_int32(DeviceState *dev, Property *prop, const char *str) -{ - int32_t *ptr = qdev_get_prop_ptr(dev, prop); - char *end; - - *ptr = strtol(str, &end, 10); - if ((*end != '\0') || (end == str)) { - return -EINVAL; - } - - return 0; -} - -static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len) -{ - int32_t *ptr = qdev_get_prop_ptr(dev, prop); - return snprintf(dest, len, "%" PRId32, *ptr); -} - PropertyInfo qdev_prop_int32 = { .name = "int32", - .parse = parse_int32, - .print = print_int32, .get = get_int32, .set = set_int32, .min = -0x80000000LL, @@ -404,26 +306,6 @@ PropertyInfo qdev_prop_hex32 = { /* --- 64bit integer --- */ -static int parse_uint64(DeviceState *dev, Property *prop, const char *str) -{ - uint64_t *ptr = qdev_get_prop_ptr(dev, prop); - char *end; - - /* accept both hex and decimal */ - *ptr = strtoull(str, &end, 0); - if ((*end != '\0') || (end == str)) { - return -EINVAL; - } - - return 0; -} - -static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len) -{ - uint64_t *ptr = qdev_get_prop_ptr(dev, prop); - return snprintf(dest, len, "%" PRIu64, *ptr); -} - static void get_int64(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { @@ -451,8 +333,6 @@ static void set_int64(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_uint64 = { .name = "uint64", - .parse = parse_uint64, - .print = print_uint64, .get = get_int64, .set = set_int64, }; @@ -749,19 +629,6 @@ PropertyInfo qdev_prop_netdev = { /* --- vlan --- */ -static int parse_vlan(DeviceState *dev, Property *prop, const char *str) -{ - VLANState **ptr = qdev_get_prop_ptr(dev, prop); - int id; - - if (sscanf(str, "%d", &id) != 1) - return -EINVAL; - *ptr = qemu_find_vlan(id, 1); - if (*ptr == NULL) - return -ENOENT; - return 0; -} - static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len) { VLANState **ptr = qdev_get_prop_ptr(dev, prop); @@ -820,7 +687,6 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_vlan = { .name = "vlan", - .parse = parse_vlan, .print = print_vlan, .get = get_vlan, .set = set_vlan, -- cgit v1.2.3