qemu/hw/qdev-properties.c
<<
>>
Prefs
   1#include "net/net.h"
   2#include "qdev.h"
   3#include "qapi/qmp/qerror.h"
   4#include "sysemu/blockdev.h"
   5#include "hw/block-common.h"
   6#include "net/hub.h"
   7#include "qapi/visitor.h"
   8#include "char/char.h"
   9
  10void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
  11{
  12    void *ptr = dev;
  13    ptr += prop->offset;
  14    return ptr;
  15}
  16
  17static void get_enum(Object *obj, Visitor *v, void *opaque,
  18                     const char *name, Error **errp)
  19{
  20    DeviceState *dev = DEVICE(obj);
  21    Property *prop = opaque;
  22    int *ptr = qdev_get_prop_ptr(dev, prop);
  23
  24    visit_type_enum(v, ptr, prop->info->enum_table,
  25                    prop->info->name, prop->name, errp);
  26}
  27
  28static void set_enum(Object *obj, Visitor *v, void *opaque,
  29                     const char *name, Error **errp)
  30{
  31    DeviceState *dev = DEVICE(obj);
  32    Property *prop = opaque;
  33    int *ptr = qdev_get_prop_ptr(dev, prop);
  34
  35    if (dev->realized) {
  36        error_set(errp, QERR_PERMISSION_DENIED);
  37        return;
  38    }
  39
  40    visit_type_enum(v, ptr, prop->info->enum_table,
  41                    prop->info->name, prop->name, errp);
  42}
  43
  44/* Bit */
  45
  46static uint32_t qdev_get_prop_mask(Property *prop)
  47{
  48    assert(prop->info == &qdev_prop_bit);
  49    return 0x1 << prop->bitnr;
  50}
  51
  52static void bit_prop_set(DeviceState *dev, Property *props, bool val)
  53{
  54    uint32_t *p = qdev_get_prop_ptr(dev, props);
  55    uint32_t mask = qdev_get_prop_mask(props);
  56    if (val) {
  57        *p |= mask;
  58    } else {
  59        *p &= ~mask;
  60    }
  61}
  62
  63static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
  64{
  65    uint32_t *p = qdev_get_prop_ptr(dev, prop);
  66    return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
  67}
  68
  69static void get_bit(Object *obj, Visitor *v, void *opaque,
  70                    const char *name, Error **errp)
  71{
  72    DeviceState *dev = DEVICE(obj);
  73    Property *prop = opaque;
  74    uint32_t *p = qdev_get_prop_ptr(dev, prop);
  75    bool value = (*p & qdev_get_prop_mask(prop)) != 0;
  76
  77    visit_type_bool(v, &value, name, errp);
  78}
  79
  80static void set_bit(Object *obj, Visitor *v, void *opaque,
  81                    const char *name, Error **errp)
  82{
  83    DeviceState *dev = DEVICE(obj);
  84    Property *prop = opaque;
  85    Error *local_err = NULL;
  86    bool value;
  87
  88    if (dev->realized) {
  89        error_set(errp, QERR_PERMISSION_DENIED);
  90        return;
  91    }
  92
  93    visit_type_bool(v, &value, name, &local_err);
  94    if (local_err) {
  95        error_propagate(errp, local_err);
  96        return;
  97    }
  98    bit_prop_set(dev, prop, value);
  99}
 100
 101PropertyInfo qdev_prop_bit = {
 102    .name  = "boolean",
 103    .legacy_name  = "on/off",
 104    .print = print_bit,
 105    .get   = get_bit,
 106    .set   = set_bit,
 107};
 108
 109/* --- 8bit integer --- */
 110
 111static void get_uint8(Object *obj, Visitor *v, void *opaque,
 112                      const char *name, Error **errp)
 113{
 114    DeviceState *dev = DEVICE(obj);
 115    Property *prop = opaque;
 116    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
 117
 118    visit_type_uint8(v, ptr, name, errp);
 119}
 120
 121static void set_uint8(Object *obj, Visitor *v, void *opaque,
 122                      const char *name, Error **errp)
 123{
 124    DeviceState *dev = DEVICE(obj);
 125    Property *prop = opaque;
 126    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
 127
 128    if (dev->realized) {
 129        error_set(errp, QERR_PERMISSION_DENIED);
 130        return;
 131    }
 132
 133    visit_type_uint8(v, ptr, name, errp);
 134}
 135
 136PropertyInfo qdev_prop_uint8 = {
 137    .name  = "uint8",
 138    .get   = get_uint8,
 139    .set   = set_uint8,
 140};
 141
 142/* --- 8bit hex value --- */
 143
 144static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
 145{
 146    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
 147    char *end;
 148
 149    if (str[0] != '0' || str[1] != 'x') {
 150        return -EINVAL;
 151    }
 152
 153    *ptr = strtoul(str, &end, 16);
 154    if ((*end != '\0') || (end == str)) {
 155        return -EINVAL;
 156    }
 157
 158    return 0;
 159}
 160
 161static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
 162{
 163    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
 164    return snprintf(dest, len, "0x%" PRIx8, *ptr);
 165}
 166
 167PropertyInfo qdev_prop_hex8 = {
 168    .name  = "uint8",
 169    .legacy_name  = "hex8",
 170    .parse = parse_hex8,
 171    .print = print_hex8,
 172    .get   = get_uint8,
 173    .set   = set_uint8,
 174};
 175
 176/* --- 16bit integer --- */
 177
 178static void get_uint16(Object *obj, Visitor *v, void *opaque,
 179                       const char *name, Error **errp)
 180{
 181    DeviceState *dev = DEVICE(obj);
 182    Property *prop = opaque;
 183    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
 184
 185    visit_type_uint16(v, ptr, name, errp);
 186}
 187
 188static void set_uint16(Object *obj, Visitor *v, void *opaque,
 189                       const char *name, Error **errp)
 190{
 191    DeviceState *dev = DEVICE(obj);
 192    Property *prop = opaque;
 193    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
 194
 195    if (dev->realized) {
 196        error_set(errp, QERR_PERMISSION_DENIED);
 197        return;
 198    }
 199
 200    visit_type_uint16(v, ptr, name, errp);
 201}
 202
 203PropertyInfo qdev_prop_uint16 = {
 204    .name  = "uint16",
 205    .get   = get_uint16,
 206    .set   = set_uint16,
 207};
 208
 209/* --- 32bit integer --- */
 210
 211static void get_uint32(Object *obj, Visitor *v, void *opaque,
 212                       const char *name, Error **errp)
 213{
 214    DeviceState *dev = DEVICE(obj);
 215    Property *prop = opaque;
 216    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
 217
 218    visit_type_uint32(v, ptr, name, errp);
 219}
 220
 221static void set_uint32(Object *obj, Visitor *v, void *opaque,
 222                       const char *name, Error **errp)
 223{
 224    DeviceState *dev = DEVICE(obj);
 225    Property *prop = opaque;
 226    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
 227
 228    if (dev->realized) {
 229        error_set(errp, QERR_PERMISSION_DENIED);
 230        return;
 231    }
 232
 233    visit_type_uint32(v, ptr, name, errp);
 234}
 235
 236static void get_int32(Object *obj, Visitor *v, void *opaque,
 237                      const char *name, Error **errp)
 238{
 239    DeviceState *dev = DEVICE(obj);
 240    Property *prop = opaque;
 241    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
 242
 243    visit_type_int32(v, ptr, name, errp);
 244}
 245
 246static void set_int32(Object *obj, Visitor *v, void *opaque,
 247                      const char *name, Error **errp)
 248{
 249    DeviceState *dev = DEVICE(obj);
 250    Property *prop = opaque;
 251    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
 252
 253    if (dev->realized) {
 254        error_set(errp, QERR_PERMISSION_DENIED);
 255        return;
 256    }
 257
 258    visit_type_int32(v, ptr, name, errp);
 259}
 260
 261PropertyInfo qdev_prop_uint32 = {
 262    .name  = "uint32",
 263    .get   = get_uint32,
 264    .set   = set_uint32,
 265};
 266
 267PropertyInfo qdev_prop_int32 = {
 268    .name  = "int32",
 269    .get   = get_int32,
 270    .set   = set_int32,
 271};
 272
 273/* --- 32bit hex value --- */
 274
 275static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
 276{
 277    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
 278    char *end;
 279
 280    if (str[0] != '0' || str[1] != 'x') {
 281        return -EINVAL;
 282    }
 283
 284    *ptr = strtoul(str, &end, 16);
 285    if ((*end != '\0') || (end == str)) {
 286        return -EINVAL;
 287    }
 288
 289    return 0;
 290}
 291
 292static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
 293{
 294    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
 295    return snprintf(dest, len, "0x%" PRIx32, *ptr);
 296}
 297
 298PropertyInfo qdev_prop_hex32 = {
 299    .name  = "uint32",
 300    .legacy_name  = "hex32",
 301    .parse = parse_hex32,
 302    .print = print_hex32,
 303    .get   = get_uint32,
 304    .set   = set_uint32,
 305};
 306
 307/* --- 64bit integer --- */
 308
 309static void get_uint64(Object *obj, Visitor *v, void *opaque,
 310                       const char *name, Error **errp)
 311{
 312    DeviceState *dev = DEVICE(obj);
 313    Property *prop = opaque;
 314    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
 315
 316    visit_type_uint64(v, ptr, name, errp);
 317}
 318
 319static void set_uint64(Object *obj, Visitor *v, void *opaque,
 320                       const char *name, Error **errp)
 321{
 322    DeviceState *dev = DEVICE(obj);
 323    Property *prop = opaque;
 324    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
 325
 326    if (dev->realized) {
 327        error_set(errp, QERR_PERMISSION_DENIED);
 328        return;
 329    }
 330
 331    visit_type_uint64(v, ptr, name, errp);
 332}
 333
 334PropertyInfo qdev_prop_uint64 = {
 335    .name  = "uint64",
 336    .get   = get_uint64,
 337    .set   = set_uint64,
 338};
 339
 340/* --- 64bit hex value --- */
 341
 342static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
 343{
 344    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
 345    char *end;
 346
 347    if (str[0] != '0' || str[1] != 'x') {
 348        return -EINVAL;
 349    }
 350
 351    *ptr = strtoull(str, &end, 16);
 352    if ((*end != '\0') || (end == str)) {
 353        return -EINVAL;
 354    }
 355
 356    return 0;
 357}
 358
 359static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
 360{
 361    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
 362    return snprintf(dest, len, "0x%" PRIx64, *ptr);
 363}
 364
 365PropertyInfo qdev_prop_hex64 = {
 366    .name  = "uint64",
 367    .legacy_name  = "hex64",
 368    .parse = parse_hex64,
 369    .print = print_hex64,
 370    .get   = get_uint64,
 371    .set   = set_uint64,
 372};
 373
 374/* --- string --- */
 375
 376static void release_string(Object *obj, const char *name, void *opaque)
 377{
 378    Property *prop = opaque;
 379    g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
 380}
 381
 382static int print_string(DeviceState *dev, Property *prop, char *dest,
 383                        size_t len)
 384{
 385    char **ptr = qdev_get_prop_ptr(dev, prop);
 386    if (!*ptr) {
 387        return snprintf(dest, len, "<null>");
 388    }
 389    return snprintf(dest, len, "\"%s\"", *ptr);
 390}
 391
 392static void get_string(Object *obj, Visitor *v, void *opaque,
 393                       const char *name, Error **errp)
 394{
 395    DeviceState *dev = DEVICE(obj);
 396    Property *prop = opaque;
 397    char **ptr = qdev_get_prop_ptr(dev, prop);
 398
 399    if (!*ptr) {
 400        char *str = (char *)"";
 401        visit_type_str(v, &str, name, errp);
 402    } else {
 403        visit_type_str(v, ptr, name, errp);
 404    }
 405}
 406
 407static void set_string(Object *obj, Visitor *v, void *opaque,
 408                       const char *name, Error **errp)
 409{
 410    DeviceState *dev = DEVICE(obj);
 411    Property *prop = opaque;
 412    char **ptr = qdev_get_prop_ptr(dev, prop);
 413    Error *local_err = NULL;
 414    char *str;
 415
 416    if (dev->realized) {
 417        error_set(errp, QERR_PERMISSION_DENIED);
 418        return;
 419    }
 420
 421    visit_type_str(v, &str, name, &local_err);
 422    if (local_err) {
 423        error_propagate(errp, local_err);
 424        return;
 425    }
 426    if (*ptr) {
 427        g_free(*ptr);
 428    }
 429    *ptr = str;
 430}
 431
 432PropertyInfo qdev_prop_string = {
 433    .name  = "string",
 434    .print = print_string,
 435    .release = release_string,
 436    .get   = get_string,
 437    .set   = set_string,
 438};
 439
 440/* --- pointer --- */
 441
 442/* Not a proper property, just for dirty hacks.  TODO Remove it!  */
 443PropertyInfo qdev_prop_ptr = {
 444    .name  = "ptr",
 445};
 446
 447/* --- mac address --- */
 448
 449/*
 450 * accepted syntax versions:
 451 *   01:02:03:04:05:06
 452 *   01-02-03-04-05-06
 453 */
 454static void get_mac(Object *obj, Visitor *v, void *opaque,
 455                    const char *name, Error **errp)
 456{
 457    DeviceState *dev = DEVICE(obj);
 458    Property *prop = opaque;
 459    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
 460    char buffer[2 * 6 + 5 + 1];
 461    char *p = buffer;
 462
 463    snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
 464             mac->a[0], mac->a[1], mac->a[2],
 465             mac->a[3], mac->a[4], mac->a[5]);
 466
 467    visit_type_str(v, &p, name, errp);
 468}
 469
 470static void set_mac(Object *obj, Visitor *v, void *opaque,
 471                    const char *name, Error **errp)
 472{
 473    DeviceState *dev = DEVICE(obj);
 474    Property *prop = opaque;
 475    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
 476    Error *local_err = NULL;
 477    int i, pos;
 478    char *str, *p;
 479
 480    if (dev->realized) {
 481        error_set(errp, QERR_PERMISSION_DENIED);
 482        return;
 483    }
 484
 485    visit_type_str(v, &str, name, &local_err);
 486    if (local_err) {
 487        error_propagate(errp, local_err);
 488        return;
 489    }
 490
 491    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
 492        if (!qemu_isxdigit(str[pos])) {
 493            goto inval;
 494        }
 495        if (!qemu_isxdigit(str[pos+1])) {
 496            goto inval;
 497        }
 498        if (i == 5) {
 499            if (str[pos+2] != '\0') {
 500                goto inval;
 501            }
 502        } else {
 503            if (str[pos+2] != ':' && str[pos+2] != '-') {
 504                goto inval;
 505            }
 506        }
 507        mac->a[i] = strtol(str+pos, &p, 16);
 508    }
 509    g_free(str);
 510    return;
 511
 512inval:
 513    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
 514    g_free(str);
 515}
 516
 517PropertyInfo qdev_prop_macaddr = {
 518    .name  = "macaddr",
 519    .get   = get_mac,
 520    .set   = set_mac,
 521};
 522
 523/* --- lost tick policy --- */
 524
 525static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
 526    [LOST_TICK_DISCARD] = "discard",
 527    [LOST_TICK_DELAY] = "delay",
 528    [LOST_TICK_MERGE] = "merge",
 529    [LOST_TICK_SLEW] = "slew",
 530    [LOST_TICK_MAX] = NULL,
 531};
 532
 533QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
 534
 535PropertyInfo qdev_prop_losttickpolicy = {
 536    .name  = "LostTickPolicy",
 537    .enum_table  = lost_tick_policy_table,
 538    .get   = get_enum,
 539    .set   = set_enum,
 540};
 541
 542/* --- BIOS CHS translation */
 543
 544static const char *bios_chs_trans_table[] = {
 545    [BIOS_ATA_TRANSLATION_AUTO] = "auto",
 546    [BIOS_ATA_TRANSLATION_NONE] = "none",
 547    [BIOS_ATA_TRANSLATION_LBA]  = "lba",
 548};
 549
 550PropertyInfo qdev_prop_bios_chs_trans = {
 551    .name = "bios-chs-trans",
 552    .enum_table = bios_chs_trans_table,
 553    .get = get_enum,
 554    .set = set_enum,
 555};
 556
 557/* --- pci address --- */
 558
 559/*
 560 * bus-local address, i.e. "$slot" or "$slot.$fn"
 561 */
 562static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
 563                          const char *name, Error **errp)
 564{
 565    DeviceState *dev = DEVICE(obj);
 566    Property *prop = opaque;
 567    int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
 568    unsigned int slot, fn, n;
 569    Error *local_err = NULL;
 570    char *str;
 571
 572    if (dev->realized) {
 573        error_set(errp, QERR_PERMISSION_DENIED);
 574        return;
 575    }
 576
 577    visit_type_str(v, &str, name, &local_err);
 578    if (local_err) {
 579        error_free(local_err);
 580        local_err = NULL;
 581        visit_type_int32(v, &value, name, &local_err);
 582        if (local_err) {
 583            error_propagate(errp, local_err);
 584        } else if (value < -1 || value > 255) {
 585            error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
 586                      "pci_devfn");
 587        } else {
 588            *ptr = value;
 589        }
 590        return;
 591    }
 592
 593    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
 594        fn = 0;
 595        if (sscanf(str, "%x%n", &slot, &n) != 1) {
 596            goto invalid;
 597        }
 598    }
 599    if (str[n] != '\0' || fn > 7 || slot > 31) {
 600        goto invalid;
 601    }
 602    *ptr = slot << 3 | fn;
 603    g_free(str);
 604    return;
 605
 606invalid:
 607    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
 608    g_free(str);
 609}
 610
 611static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
 612                           size_t len)
 613{
 614    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
 615
 616    if (*ptr == -1) {
 617        return snprintf(dest, len, "<unset>");
 618    } else {
 619        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
 620    }
 621}
 622
 623PropertyInfo qdev_prop_pci_devfn = {
 624    .name  = "int32",
 625    .legacy_name  = "pci-devfn",
 626    .print = print_pci_devfn,
 627    .get   = get_int32,
 628    .set   = set_pci_devfn,
 629};
 630
 631/* --- blocksize --- */
 632
 633static void set_blocksize(Object *obj, Visitor *v, void *opaque,
 634                          const char *name, Error **errp)
 635{
 636    DeviceState *dev = DEVICE(obj);
 637    Property *prop = opaque;
 638    uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
 639    Error *local_err = NULL;
 640    const int64_t min = 512;
 641    const int64_t max = 32768;
 642
 643    if (dev->realized) {
 644        error_set(errp, QERR_PERMISSION_DENIED);
 645        return;
 646    }
 647
 648    visit_type_uint16(v, &value, name, &local_err);
 649    if (local_err) {
 650        error_propagate(errp, local_err);
 651        return;
 652    }
 653    if (value < min || value > max) {
 654        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
 655                  dev->id?:"", name, (int64_t)value, min, max);
 656        return;
 657    }
 658
 659    /* We rely on power-of-2 blocksizes for bitmasks */
 660    if ((value & (value - 1)) != 0) {
 661        error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
 662                  dev->id?:"", name, (int64_t)value);
 663        return;
 664    }
 665
 666    *ptr = value;
 667}
 668
 669PropertyInfo qdev_prop_blocksize = {
 670    .name  = "blocksize",
 671    .get   = get_uint16,
 672    .set   = set_blocksize,
 673};
 674
 675/* --- pci host address --- */
 676
 677static void get_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
 678                                 const char *name, Error **errp)
 679{
 680    DeviceState *dev = DEVICE(obj);
 681    Property *prop = opaque;
 682    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
 683    char buffer[] = "xxxx:xx:xx.x";
 684    char *p = buffer;
 685    int rc = 0;
 686
 687    rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
 688                  addr->domain, addr->bus, addr->slot, addr->function);
 689    assert(rc == sizeof(buffer) - 1);
 690
 691    visit_type_str(v, &p, name, errp);
 692}
 693
 694/*
 695 * Parse [<domain>:]<bus>:<slot>.<func>
 696 *   if <domain> is not supplied, it's assumed to be 0.
 697 */
 698static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
 699                                 const char *name, Error **errp)
 700{
 701    DeviceState *dev = DEVICE(obj);
 702    Property *prop = opaque;
 703    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
 704    Error *local_err = NULL;
 705    char *str, *p;
 706    char *e;
 707    unsigned long val;
 708    unsigned long dom = 0, bus = 0;
 709    unsigned int slot = 0, func = 0;
 710
 711    if (dev->realized) {
 712        error_set(errp, QERR_PERMISSION_DENIED);
 713        return;
 714    }
 715
 716    visit_type_str(v, &str, name, &local_err);
 717    if (local_err) {
 718        error_propagate(errp, local_err);
 719        return;
 720    }
 721
 722    p = str;
 723    val = strtoul(p, &e, 16);
 724    if (e == p || *e != ':') {
 725        goto inval;
 726    }
 727    bus = val;
 728
 729    p = e + 1;
 730    val = strtoul(p, &e, 16);
 731    if (e == p) {
 732        goto inval;
 733    }
 734    if (*e == ':') {
 735        dom = bus;
 736        bus = val;
 737        p = e + 1;
 738        val = strtoul(p, &e, 16);
 739        if (e == p) {
 740            goto inval;
 741        }
 742    }
 743    slot = val;
 744
 745    if (*e != '.') {
 746        goto inval;
 747    }
 748    p = e + 1;
 749    val = strtoul(p, &e, 10);
 750    if (e == p) {
 751        goto inval;
 752    }
 753    func = val;
 754
 755    if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
 756        goto inval;
 757    }
 758
 759    if (*e) {
 760        goto inval;
 761    }
 762
 763    addr->domain = dom;
 764    addr->bus = bus;
 765    addr->slot = slot;
 766    addr->function = func;
 767
 768    g_free(str);
 769    return;
 770
 771inval:
 772    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
 773    g_free(str);
 774}
 775
 776PropertyInfo qdev_prop_pci_host_devaddr = {
 777    .name = "pci-host-devaddr",
 778    .get = get_pci_host_devaddr,
 779    .set = set_pci_host_devaddr,
 780};
 781
 782/* --- public helpers --- */
 783
 784static Property *qdev_prop_walk(Property *props, const char *name)
 785{
 786    if (!props) {
 787        return NULL;
 788    }
 789    while (props->name) {
 790        if (strcmp(props->name, name) == 0) {
 791            return props;
 792        }
 793        props++;
 794    }
 795    return NULL;
 796}
 797
 798static Property *qdev_prop_find(DeviceState *dev, const char *name)
 799{
 800    ObjectClass *class;
 801    Property *prop;
 802
 803    /* device properties */
 804    class = object_get_class(OBJECT(dev));
 805    do {
 806        prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
 807        if (prop) {
 808            return prop;
 809        }
 810        class = object_class_get_parent(class);
 811    } while (class != object_class_by_name(TYPE_DEVICE));
 812
 813    return NULL;
 814}
 815
 816void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
 817                                    Property *prop, const char *value)
 818{
 819    switch (ret) {
 820    case -EEXIST:
 821        error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
 822                  object_get_typename(OBJECT(dev)), prop->name, value);
 823        break;
 824    default:
 825    case -EINVAL:
 826        error_set(errp, QERR_PROPERTY_VALUE_BAD,
 827                  object_get_typename(OBJECT(dev)), prop->name, value);
 828        break;
 829    case -ENOENT:
 830        error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
 831                  object_get_typename(OBJECT(dev)), prop->name, value);
 832        break;
 833    case 0:
 834        break;
 835    }
 836}
 837
 838int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
 839{
 840    char *legacy_name;
 841    Error *err = NULL;
 842
 843    legacy_name = g_strdup_printf("legacy-%s", name);
 844    if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
 845        object_property_parse(OBJECT(dev), value, legacy_name, &err);
 846    } else {
 847        object_property_parse(OBJECT(dev), value, name, &err);
 848    }
 849    g_free(legacy_name);
 850
 851    if (err) {
 852        qerror_report_err(err);
 853        error_free(err);
 854        return -1;
 855    }
 856    return 0;
 857}
 858
 859void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
 860{
 861    Error *errp = NULL;
 862    object_property_set_bool(OBJECT(dev), value, name, &errp);
 863    assert_no_error(errp);
 864}
 865
 866void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
 867{
 868    Error *errp = NULL;
 869    object_property_set_int(OBJECT(dev), value, name, &errp);
 870    assert_no_error(errp);
 871}
 872
 873void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
 874{
 875    Error *errp = NULL;
 876    object_property_set_int(OBJECT(dev), value, name, &errp);
 877    assert_no_error(errp);
 878}
 879
 880void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
 881{
 882    Error *errp = NULL;
 883    object_property_set_int(OBJECT(dev), value, name, &errp);
 884    assert_no_error(errp);
 885}
 886
 887void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
 888{
 889    Error *errp = NULL;
 890    object_property_set_int(OBJECT(dev), value, name, &errp);
 891    assert_no_error(errp);
 892}
 893
 894void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
 895{
 896    Error *errp = NULL;
 897    object_property_set_int(OBJECT(dev), value, name, &errp);
 898    assert_no_error(errp);
 899}
 900
 901void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
 902{
 903    Error *errp = NULL;
 904    object_property_set_str(OBJECT(dev), value, name, &errp);
 905    assert_no_error(errp);
 906}
 907
 908void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
 909{
 910    Error *errp = NULL;
 911    char str[2 * 6 + 5 + 1];
 912    snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
 913             value[0], value[1], value[2], value[3], value[4], value[5]);
 914
 915    object_property_set_str(OBJECT(dev), str, name, &errp);
 916    assert_no_error(errp);
 917}
 918
 919void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
 920{
 921    Property *prop;
 922    Error *errp = NULL;
 923
 924    prop = qdev_prop_find(dev, name);
 925    object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
 926                            name, &errp);
 927    assert_no_error(errp);
 928}
 929
 930void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
 931{
 932    Property *prop;
 933    void **ptr;
 934
 935    prop = qdev_prop_find(dev, name);
 936    assert(prop && prop->info == &qdev_prop_ptr);
 937    ptr = qdev_get_prop_ptr(dev, prop);
 938    *ptr = value;
 939}
 940
 941static QTAILQ_HEAD(, GlobalProperty) global_props =
 942        QTAILQ_HEAD_INITIALIZER(global_props);
 943
 944void qdev_prop_register_global(GlobalProperty *prop)
 945{
 946    QTAILQ_INSERT_TAIL(&global_props, prop, next);
 947}
 948
 949void qdev_prop_register_global_list(GlobalProperty *props)
 950{
 951    int i;
 952
 953    for (i = 0; props[i].driver != NULL; i++) {
 954        qdev_prop_register_global(props+i);
 955    }
 956}
 957
 958void qdev_prop_set_globals(DeviceState *dev)
 959{
 960    ObjectClass *class = object_get_class(OBJECT(dev));
 961
 962    do {
 963        GlobalProperty *prop;
 964        QTAILQ_FOREACH(prop, &global_props, next) {
 965            if (strcmp(object_class_get_name(class), prop->driver) != 0) {
 966                continue;
 967            }
 968            if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
 969                exit(1);
 970            }
 971        }
 972        class = object_class_get_parent(class);
 973    } while (class);
 974}
 975