qemu/hw/core/qdev-properties.c
<<
>>
Prefs
   1#include "qemu/osdep.h"
   2#include "net/net.h"
   3#include "hw/qdev.h"
   4#include "qapi/error.h"
   5#include "hw/pci/pci.h"
   6#include "qapi/qmp/qerror.h"
   7#include "qemu/error-report.h"
   8#include "sysemu/block-backend.h"
   9#include "hw/block/block.h"
  10#include "net/hub.h"
  11#include "qapi/visitor.h"
  12#include "sysemu/char.h"
  13
  14void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
  15                                  Error **errp)
  16{
  17    if (dev->id) {
  18        error_setg(errp, "Attempt to set property '%s' on device '%s' "
  19                   "(type '%s') after it was realized", name, dev->id,
  20                   object_get_typename(OBJECT(dev)));
  21    } else {
  22        error_setg(errp, "Attempt to set property '%s' on anonymous device "
  23                   "(type '%s') after it was realized", name,
  24                   object_get_typename(OBJECT(dev)));
  25    }
  26}
  27
  28void qdev_prop_allow_set_link_before_realize(Object *obj, const char *name,
  29                                             Object *val, Error **errp)
  30{
  31    DeviceState *dev = DEVICE(obj);
  32
  33    if (dev->realized) {
  34        error_setg(errp, "Attempt to set link property '%s' on device '%s' "
  35                   "(type '%s') after it was realized",
  36                   name, dev->id, object_get_typename(obj));
  37    }
  38}
  39
  40
  41void qdev_prop_allow_set_link(Object *obj, const char *name,
  42                              Object *val, Error **errp)
  43{
  44}
  45
  46void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
  47{
  48    void *ptr = dev;
  49    ptr += prop->offset;
  50    return ptr;
  51}
  52
  53static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque,
  54                     Error **errp)
  55{
  56    DeviceState *dev = DEVICE(obj);
  57    Property *prop = opaque;
  58    int *ptr = qdev_get_prop_ptr(dev, prop);
  59
  60    visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
  61}
  62
  63static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque,
  64                     Error **errp)
  65{
  66    DeviceState *dev = DEVICE(obj);
  67    Property *prop = opaque;
  68    int *ptr = qdev_get_prop_ptr(dev, prop);
  69
  70    if (dev->realized) {
  71        qdev_prop_set_after_realize(dev, name, errp);
  72        return;
  73    }
  74
  75    visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
  76}
  77
  78/* Bit */
  79
  80static uint32_t qdev_get_prop_mask(Property *prop)
  81{
  82    assert(prop->info == &qdev_prop_bit);
  83    return 0x1 << prop->bitnr;
  84}
  85
  86static void bit_prop_set(DeviceState *dev, Property *props, bool val)
  87{
  88    uint32_t *p = qdev_get_prop_ptr(dev, props);
  89    uint32_t mask = qdev_get_prop_mask(props);
  90    if (val) {
  91        *p |= mask;
  92    } else {
  93        *p &= ~mask;
  94    }
  95}
  96
  97static void prop_get_bit(Object *obj, Visitor *v, const char *name,
  98                         void *opaque, Error **errp)
  99{
 100    DeviceState *dev = DEVICE(obj);
 101    Property *prop = opaque;
 102    uint32_t *p = qdev_get_prop_ptr(dev, prop);
 103    bool value = (*p & qdev_get_prop_mask(prop)) != 0;
 104
 105    visit_type_bool(v, name, &value, errp);
 106}
 107
 108static void prop_set_bit(Object *obj, Visitor *v, const char *name,
 109                         void *opaque, Error **errp)
 110{
 111    DeviceState *dev = DEVICE(obj);
 112    Property *prop = opaque;
 113    Error *local_err = NULL;
 114    bool value;
 115
 116    if (dev->realized) {
 117        qdev_prop_set_after_realize(dev, name, errp);
 118        return;
 119    }
 120
 121    visit_type_bool(v, name, &value, &local_err);
 122    if (local_err) {
 123        error_propagate(errp, local_err);
 124        return;
 125    }
 126    bit_prop_set(dev, prop, value);
 127}
 128
 129PropertyInfo qdev_prop_bit = {
 130    .name  = "bool",
 131    .description = "on/off",
 132    .get   = prop_get_bit,
 133    .set   = prop_set_bit,
 134};
 135
 136/* Bit64 */
 137
 138static uint64_t qdev_get_prop_mask64(Property *prop)
 139{
 140    assert(prop->info == &qdev_prop_bit64);
 141    return 0x1ull << prop->bitnr;
 142}
 143
 144static void bit64_prop_set(DeviceState *dev, Property *props, bool val)
 145{
 146    uint64_t *p = qdev_get_prop_ptr(dev, props);
 147    uint64_t mask = qdev_get_prop_mask64(props);
 148    if (val) {
 149        *p |= mask;
 150    } else {
 151        *p &= ~mask;
 152    }
 153}
 154
 155static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
 156                           void *opaque, Error **errp)
 157{
 158    DeviceState *dev = DEVICE(obj);
 159    Property *prop = opaque;
 160    uint64_t *p = qdev_get_prop_ptr(dev, prop);
 161    bool value = (*p & qdev_get_prop_mask64(prop)) != 0;
 162
 163    visit_type_bool(v, name, &value, errp);
 164}
 165
 166static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
 167                           void *opaque, Error **errp)
 168{
 169    DeviceState *dev = DEVICE(obj);
 170    Property *prop = opaque;
 171    Error *local_err = NULL;
 172    bool value;
 173
 174    if (dev->realized) {
 175        qdev_prop_set_after_realize(dev, name, errp);
 176        return;
 177    }
 178
 179    visit_type_bool(v, name, &value, &local_err);
 180    if (local_err) {
 181        error_propagate(errp, local_err);
 182        return;
 183    }
 184    bit64_prop_set(dev, prop, value);
 185}
 186
 187PropertyInfo qdev_prop_bit64 = {
 188    .name  = "bool",
 189    .description = "on/off",
 190    .get   = prop_get_bit64,
 191    .set   = prop_set_bit64,
 192};
 193
 194/* --- bool --- */
 195
 196static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,
 197                     Error **errp)
 198{
 199    DeviceState *dev = DEVICE(obj);
 200    Property *prop = opaque;
 201    bool *ptr = qdev_get_prop_ptr(dev, prop);
 202
 203    visit_type_bool(v, name, ptr, errp);
 204}
 205
 206static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
 207                     Error **errp)
 208{
 209    DeviceState *dev = DEVICE(obj);
 210    Property *prop = opaque;
 211    bool *ptr = qdev_get_prop_ptr(dev, prop);
 212
 213    if (dev->realized) {
 214        qdev_prop_set_after_realize(dev, name, errp);
 215        return;
 216    }
 217
 218    visit_type_bool(v, name, ptr, errp);
 219}
 220
 221PropertyInfo qdev_prop_bool = {
 222    .name  = "bool",
 223    .get   = get_bool,
 224    .set   = set_bool,
 225};
 226
 227/* --- 8bit integer --- */
 228
 229static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
 230                      Error **errp)
 231{
 232    DeviceState *dev = DEVICE(obj);
 233    Property *prop = opaque;
 234    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
 235
 236    visit_type_uint8(v, name, ptr, errp);
 237}
 238
 239static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
 240                      Error **errp)
 241{
 242    DeviceState *dev = DEVICE(obj);
 243    Property *prop = opaque;
 244    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
 245
 246    if (dev->realized) {
 247        qdev_prop_set_after_realize(dev, name, errp);
 248        return;
 249    }
 250
 251    visit_type_uint8(v, name, ptr, errp);
 252}
 253
 254PropertyInfo qdev_prop_uint8 = {
 255    .name  = "uint8",
 256    .get   = get_uint8,
 257    .set   = set_uint8,
 258};
 259
 260/* --- 16bit integer --- */
 261
 262static void get_uint16(Object *obj, Visitor *v, const char *name,
 263                       void *opaque, Error **errp)
 264{
 265    DeviceState *dev = DEVICE(obj);
 266    Property *prop = opaque;
 267    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
 268
 269    visit_type_uint16(v, name, ptr, errp);
 270}
 271
 272static void set_uint16(Object *obj, Visitor *v, const char *name,
 273                       void *opaque, Error **errp)
 274{
 275    DeviceState *dev = DEVICE(obj);
 276    Property *prop = opaque;
 277    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
 278
 279    if (dev->realized) {
 280        qdev_prop_set_after_realize(dev, name, errp);
 281        return;
 282    }
 283
 284    visit_type_uint16(v, name, ptr, errp);
 285}
 286
 287PropertyInfo qdev_prop_uint16 = {
 288    .name  = "uint16",
 289    .get   = get_uint16,
 290    .set   = set_uint16,
 291};
 292
 293/* --- 32bit integer --- */
 294
 295static void get_uint32(Object *obj, Visitor *v, const char *name,
 296                       void *opaque, Error **errp)
 297{
 298    DeviceState *dev = DEVICE(obj);
 299    Property *prop = opaque;
 300    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
 301
 302    visit_type_uint32(v, name, ptr, errp);
 303}
 304
 305static void set_uint32(Object *obj, Visitor *v, const char *name,
 306                       void *opaque, Error **errp)
 307{
 308    DeviceState *dev = DEVICE(obj);
 309    Property *prop = opaque;
 310    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
 311
 312    if (dev->realized) {
 313        qdev_prop_set_after_realize(dev, name, errp);
 314        return;
 315    }
 316
 317    visit_type_uint32(v, name, ptr, errp);
 318}
 319
 320static void get_int32(Object *obj, Visitor *v, const char *name, void *opaque,
 321                      Error **errp)
 322{
 323    DeviceState *dev = DEVICE(obj);
 324    Property *prop = opaque;
 325    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
 326
 327    visit_type_int32(v, name, ptr, errp);
 328}
 329
 330static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
 331                      Error **errp)
 332{
 333    DeviceState *dev = DEVICE(obj);
 334    Property *prop = opaque;
 335    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
 336
 337    if (dev->realized) {
 338        qdev_prop_set_after_realize(dev, name, errp);
 339        return;
 340    }
 341
 342    visit_type_int32(v, name, ptr, errp);
 343}
 344
 345PropertyInfo qdev_prop_uint32 = {
 346    .name  = "uint32",
 347    .get   = get_uint32,
 348    .set   = set_uint32,
 349};
 350
 351PropertyInfo qdev_prop_int32 = {
 352    .name  = "int32",
 353    .get   = get_int32,
 354    .set   = set_int32,
 355};
 356
 357/* --- 64bit integer --- */
 358
 359static void get_uint64(Object *obj, Visitor *v, const char *name,
 360                       void *opaque, Error **errp)
 361{
 362    DeviceState *dev = DEVICE(obj);
 363    Property *prop = opaque;
 364    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
 365
 366    visit_type_uint64(v, name, ptr, errp);
 367}
 368
 369static void set_uint64(Object *obj, Visitor *v, const char *name,
 370                       void *opaque, Error **errp)
 371{
 372    DeviceState *dev = DEVICE(obj);
 373    Property *prop = opaque;
 374    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
 375
 376    if (dev->realized) {
 377        qdev_prop_set_after_realize(dev, name, errp);
 378        return;
 379    }
 380
 381    visit_type_uint64(v, name, ptr, errp);
 382}
 383
 384PropertyInfo qdev_prop_uint64 = {
 385    .name  = "uint64",
 386    .get   = get_uint64,
 387    .set   = set_uint64,
 388};
 389
 390/* --- string --- */
 391
 392static void release_string(Object *obj, const char *name, void *opaque)
 393{
 394    Property *prop = opaque;
 395    g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
 396}
 397
 398static void get_string(Object *obj, Visitor *v, const char *name,
 399                       void *opaque, Error **errp)
 400{
 401    DeviceState *dev = DEVICE(obj);
 402    Property *prop = opaque;
 403    char **ptr = qdev_get_prop_ptr(dev, prop);
 404
 405    if (!*ptr) {
 406        char *str = (char *)"";
 407        visit_type_str(v, name, &str, errp);
 408    } else {
 409        visit_type_str(v, name, ptr, errp);
 410    }
 411}
 412
 413static void set_string(Object *obj, Visitor *v, const char *name,
 414                       void *opaque, Error **errp)
 415{
 416    DeviceState *dev = DEVICE(obj);
 417    Property *prop = opaque;
 418    char **ptr = qdev_get_prop_ptr(dev, prop);
 419    Error *local_err = NULL;
 420    char *str;
 421
 422    if (dev->realized) {
 423        qdev_prop_set_after_realize(dev, name, errp);
 424        return;
 425    }
 426
 427    visit_type_str(v, name, &str, &local_err);
 428    if (local_err) {
 429        error_propagate(errp, local_err);
 430        return;
 431    }
 432    g_free(*ptr);
 433    *ptr = str;
 434}
 435
 436PropertyInfo qdev_prop_string = {
 437    .name  = "str",
 438    .release = release_string,
 439    .get   = get_string,
 440    .set   = set_string,
 441};
 442
 443/* --- pointer --- */
 444
 445/* Not a proper property, just for dirty hacks.  TODO Remove it!  */
 446PropertyInfo qdev_prop_ptr = {
 447    .name  = "ptr",
 448};
 449
 450/* --- mac address --- */
 451
 452/*
 453 * accepted syntax versions:
 454 *   01:02:03:04:05:06
 455 *   01-02-03-04-05-06
 456 */
 457static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
 458                    Error **errp)
 459{
 460    DeviceState *dev = DEVICE(obj);
 461    Property *prop = opaque;
 462    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
 463    char buffer[2 * 6 + 5 + 1];
 464    char *p = buffer;
 465
 466    snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
 467             mac->a[0], mac->a[1], mac->a[2],
 468             mac->a[3], mac->a[4], mac->a[5]);
 469
 470    visit_type_str(v, name, &p, errp);
 471}
 472
 473static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
 474                    Error **errp)
 475{
 476    DeviceState *dev = DEVICE(obj);
 477    Property *prop = opaque;
 478    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
 479    Error *local_err = NULL;
 480    int i, pos;
 481    char *str, *p;
 482
 483    if (dev->realized) {
 484        qdev_prop_set_after_realize(dev, name, errp);
 485        return;
 486    }
 487
 488    visit_type_str(v, name, &str, &local_err);
 489    if (local_err) {
 490        error_propagate(errp, local_err);
 491        return;
 492    }
 493
 494    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
 495        if (!qemu_isxdigit(str[pos])) {
 496            goto inval;
 497        }
 498        if (!qemu_isxdigit(str[pos+1])) {
 499            goto inval;
 500        }
 501        if (i == 5) {
 502            if (str[pos+2] != '\0') {
 503                goto inval;
 504            }
 505        } else {
 506            if (str[pos+2] != ':' && str[pos+2] != '-') {
 507                goto inval;
 508            }
 509        }
 510        mac->a[i] = strtol(str+pos, &p, 16);
 511    }
 512    g_free(str);
 513    return;
 514
 515inval:
 516    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
 517    g_free(str);
 518}
 519
 520PropertyInfo qdev_prop_macaddr = {
 521    .name  = "str",
 522    .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
 523    .get   = get_mac,
 524    .set   = set_mac,
 525};
 526
 527/* --- on/off/auto --- */
 528
 529PropertyInfo qdev_prop_on_off_auto = {
 530    .name = "OnOffAuto",
 531    .description = "on/off/auto",
 532    .enum_table = OnOffAuto_lookup,
 533    .get = get_enum,
 534    .set = set_enum,
 535};
 536
 537/* --- lost tick policy --- */
 538
 539QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
 540
 541PropertyInfo qdev_prop_losttickpolicy = {
 542    .name  = "LostTickPolicy",
 543    .enum_table  = LostTickPolicy_lookup,
 544    .get   = get_enum,
 545    .set   = set_enum,
 546};
 547
 548/* --- BIOS CHS translation */
 549
 550QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
 551
 552PropertyInfo qdev_prop_bios_chs_trans = {
 553    .name = "BiosAtaTranslation",
 554    .description = "Logical CHS translation algorithm, "
 555                   "auto/none/lba/large/rechs",
 556    .enum_table = BiosAtaTranslation_lookup,
 557    .get = get_enum,
 558    .set = set_enum,
 559};
 560
 561/* --- FDC default drive types */
 562
 563PropertyInfo qdev_prop_fdc_drive_type = {
 564    .name = "FdcDriveType",
 565    .description = "FDC drive type, "
 566                   "144/288/120/none/auto",
 567    .enum_table = FloppyDriveType_lookup,
 568    .get = get_enum,
 569    .set = set_enum
 570};
 571
 572/* --- pci address --- */
 573
 574/*
 575 * bus-local address, i.e. "$slot" or "$slot.$fn"
 576 */
 577static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
 578                          void *opaque, Error **errp)
 579{
 580    DeviceState *dev = DEVICE(obj);
 581    Property *prop = opaque;
 582    int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
 583    unsigned int slot, fn, n;
 584    Error *local_err = NULL;
 585    char *str;
 586
 587    if (dev->realized) {
 588        qdev_prop_set_after_realize(dev, name, errp);
 589        return;
 590    }
 591
 592    visit_type_str(v, name, &str, &local_err);
 593    if (local_err) {
 594        error_free(local_err);
 595        local_err = NULL;
 596        visit_type_int32(v, name, &value, &local_err);
 597        if (local_err) {
 598            error_propagate(errp, local_err);
 599        } else if (value < -1 || value > 255) {
 600            error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
 601                       name ? name : "null", "pci_devfn");
 602        } else {
 603            *ptr = value;
 604        }
 605        return;
 606    }
 607
 608    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
 609        fn = 0;
 610        if (sscanf(str, "%x%n", &slot, &n) != 1) {
 611            goto invalid;
 612        }
 613    }
 614    if (str[n] != '\0' || fn > 7 || slot > 31) {
 615        goto invalid;
 616    }
 617    *ptr = slot << 3 | fn;
 618    g_free(str);
 619    return;
 620
 621invalid:
 622    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
 623    g_free(str);
 624}
 625
 626static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
 627                           size_t len)
 628{
 629    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
 630
 631    if (*ptr == -1) {
 632        return snprintf(dest, len, "<unset>");
 633    } else {
 634        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
 635    }
 636}
 637
 638PropertyInfo qdev_prop_pci_devfn = {
 639    .name  = "int32",
 640    .description = "Slot and optional function number, example: 06.0 or 06",
 641    .print = print_pci_devfn,
 642    .get   = get_int32,
 643    .set   = set_pci_devfn,
 644};
 645
 646/* --- blocksize --- */
 647
 648static void set_blocksize(Object *obj, Visitor *v, const char *name,
 649                          void *opaque, Error **errp)
 650{
 651    DeviceState *dev = DEVICE(obj);
 652    Property *prop = opaque;
 653    uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
 654    Error *local_err = NULL;
 655    const int64_t min = 512;
 656    const int64_t max = 32768;
 657
 658    if (dev->realized) {
 659        qdev_prop_set_after_realize(dev, name, errp);
 660        return;
 661    }
 662
 663    visit_type_uint16(v, name, &value, &local_err);
 664    if (local_err) {
 665        error_propagate(errp, local_err);
 666        return;
 667    }
 668    /* value of 0 means "unset" */
 669    if (value && (value < min || value > max)) {
 670        error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
 671                   dev->id ? : "", name, (int64_t)value, min, max);
 672        return;
 673    }
 674
 675    /* We rely on power-of-2 blocksizes for bitmasks */
 676    if ((value & (value - 1)) != 0) {
 677        error_setg(errp,
 678                  "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2",
 679                  dev->id ?: "", name, (int64_t)value);
 680        return;
 681    }
 682
 683    *ptr = value;
 684}
 685
 686PropertyInfo qdev_prop_blocksize = {
 687    .name  = "uint16",
 688    .description = "A power of two between 512 and 32768",
 689    .get   = get_uint16,
 690    .set   = set_blocksize,
 691};
 692
 693/* --- pci host address --- */
 694
 695static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
 696                                 void *opaque, Error **errp)
 697{
 698    DeviceState *dev = DEVICE(obj);
 699    Property *prop = opaque;
 700    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
 701    char buffer[] = "xxxx:xx:xx.x";
 702    char *p = buffer;
 703    int rc = 0;
 704
 705    rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
 706                  addr->domain, addr->bus, addr->slot, addr->function);
 707    assert(rc == sizeof(buffer) - 1);
 708
 709    visit_type_str(v, name, &p, errp);
 710}
 711
 712/*
 713 * Parse [<domain>:]<bus>:<slot>.<func>
 714 *   if <domain> is not supplied, it's assumed to be 0.
 715 */
 716static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
 717                                 void *opaque, Error **errp)
 718{
 719    DeviceState *dev = DEVICE(obj);
 720    Property *prop = opaque;
 721    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
 722    Error *local_err = NULL;
 723    char *str, *p;
 724    char *e;
 725    unsigned long val;
 726    unsigned long dom = 0, bus = 0;
 727    unsigned int slot = 0, func = 0;
 728
 729    if (dev->realized) {
 730        qdev_prop_set_after_realize(dev, name, errp);
 731        return;
 732    }
 733
 734    visit_type_str(v, name, &str, &local_err);
 735    if (local_err) {
 736        error_propagate(errp, local_err);
 737        return;
 738    }
 739
 740    p = str;
 741    val = strtoul(p, &e, 16);
 742    if (e == p || *e != ':') {
 743        goto inval;
 744    }
 745    bus = val;
 746
 747    p = e + 1;
 748    val = strtoul(p, &e, 16);
 749    if (e == p) {
 750        goto inval;
 751    }
 752    if (*e == ':') {
 753        dom = bus;
 754        bus = val;
 755        p = e + 1;
 756        val = strtoul(p, &e, 16);
 757        if (e == p) {
 758            goto inval;
 759        }
 760    }
 761    slot = val;
 762
 763    if (*e != '.') {
 764        goto inval;
 765    }
 766    p = e + 1;
 767    val = strtoul(p, &e, 10);
 768    if (e == p) {
 769        goto inval;
 770    }
 771    func = val;
 772
 773    if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
 774        goto inval;
 775    }
 776
 777    if (*e) {
 778        goto inval;
 779    }
 780
 781    addr->domain = dom;
 782    addr->bus = bus;
 783    addr->slot = slot;
 784    addr->function = func;
 785
 786    g_free(str);
 787    return;
 788
 789inval:
 790    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
 791    g_free(str);
 792}
 793
 794PropertyInfo qdev_prop_pci_host_devaddr = {
 795    .name = "str",
 796    .description = "Address (bus/device/function) of "
 797                   "the host device, example: 04:10.0",
 798    .get = get_pci_host_devaddr,
 799    .set = set_pci_host_devaddr,
 800};
 801
 802/* --- support for array properties --- */
 803
 804/* Used as an opaque for the object properties we add for each
 805 * array element. Note that the struct Property must be first
 806 * in the struct so that a pointer to this works as the opaque
 807 * for the underlying element's property hooks as well as for
 808 * our own release callback.
 809 */
 810typedef struct {
 811    struct Property prop;
 812    char *propname;
 813    ObjectPropertyRelease *release;
 814} ArrayElementProperty;
 815
 816/* object property release callback for array element properties:
 817 * we call the underlying element's property release hook, and
 818 * then free the memory we allocated when we added the property.
 819 */
 820static void array_element_release(Object *obj, const char *name, void *opaque)
 821{
 822    ArrayElementProperty *p = opaque;
 823    if (p->release) {
 824        p->release(obj, name, opaque);
 825    }
 826    g_free(p->propname);
 827    g_free(p);
 828}
 829
 830static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
 831                              void *opaque, Error **errp)
 832{
 833    /* Setter for the property which defines the length of a
 834     * variable-sized property array. As well as actually setting the
 835     * array-length field in the device struct, we have to create the
 836     * array itself and dynamically add the corresponding properties.
 837     */
 838    DeviceState *dev = DEVICE(obj);
 839    Property *prop = opaque;
 840    uint32_t *alenptr = qdev_get_prop_ptr(dev, prop);
 841    void **arrayptr = (void *)dev + prop->arrayoffset;
 842    Error *local_err = NULL;
 843    void *eltptr;
 844    const char *arrayname;
 845    int i;
 846
 847    if (dev->realized) {
 848        qdev_prop_set_after_realize(dev, name, errp);
 849        return;
 850    }
 851    if (*alenptr) {
 852        error_setg(errp, "array size property %s may not be set more than once",
 853                   name);
 854        return;
 855    }
 856    visit_type_uint32(v, name, alenptr, &local_err);
 857    if (local_err) {
 858        error_propagate(errp, local_err);
 859        return;
 860    }
 861    if (!*alenptr) {
 862        return;
 863    }
 864
 865    /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
 866     * strip it off so we can get the name of the array itself.
 867     */
 868    assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
 869                   strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
 870    arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
 871
 872    /* Note that it is the responsibility of the individual device's deinit
 873     * to free the array proper.
 874     */
 875    *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
 876    for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
 877        char *propname = g_strdup_printf("%s[%d]", arrayname, i);
 878        ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
 879        arrayprop->release = prop->arrayinfo->release;
 880        arrayprop->propname = propname;
 881        arrayprop->prop.info = prop->arrayinfo;
 882        arrayprop->prop.name = propname;
 883        /* This ugly piece of pointer arithmetic sets up the offset so
 884         * that when the underlying get/set hooks call qdev_get_prop_ptr
 885         * they get the right answer despite the array element not actually
 886         * being inside the device struct.
 887         */
 888        arrayprop->prop.offset = eltptr - (void *)dev;
 889        assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr);
 890        object_property_add(obj, propname,
 891                            arrayprop->prop.info->name,
 892                            arrayprop->prop.info->get,
 893                            arrayprop->prop.info->set,
 894                            array_element_release,
 895                            arrayprop, &local_err);
 896        if (local_err) {
 897            error_propagate(errp, local_err);
 898            return;
 899        }
 900    }
 901}
 902
 903PropertyInfo qdev_prop_arraylen = {
 904    .name = "uint32",
 905    .get = get_uint32,
 906    .set = set_prop_arraylen,
 907};
 908
 909/* --- public helpers --- */
 910
 911static Property *qdev_prop_walk(Property *props, const char *name)
 912{
 913    if (!props) {
 914        return NULL;
 915    }
 916    while (props->name) {
 917        if (strcmp(props->name, name) == 0) {
 918            return props;
 919        }
 920        props++;
 921    }
 922    return NULL;
 923}
 924
 925static Property *qdev_prop_find(DeviceState *dev, const char *name)
 926{
 927    ObjectClass *class;
 928    Property *prop;
 929
 930    /* device properties */
 931    class = object_get_class(OBJECT(dev));
 932    do {
 933        prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
 934        if (prop) {
 935            return prop;
 936        }
 937        class = object_class_get_parent(class);
 938    } while (class != object_class_by_name(TYPE_DEVICE));
 939
 940    return NULL;
 941}
 942
 943void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
 944                                    Property *prop, const char *value)
 945{
 946    switch (ret) {
 947    case -EEXIST:
 948        error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
 949                  object_get_typename(OBJECT(dev)), prop->name, value);
 950        break;
 951    default:
 952    case -EINVAL:
 953        error_setg(errp, QERR_PROPERTY_VALUE_BAD,
 954                   object_get_typename(OBJECT(dev)), prop->name, value);
 955        break;
 956    case -ENOENT:
 957        error_setg(errp, "Property '%s.%s' can't find value '%s'",
 958                  object_get_typename(OBJECT(dev)), prop->name, value);
 959        break;
 960    case 0:
 961        break;
 962    }
 963}
 964
 965void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
 966{
 967    object_property_set_bool(OBJECT(dev), value, name, &error_abort);
 968}
 969
 970void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
 971{
 972    object_property_set_int(OBJECT(dev), value, name, &error_abort);
 973}
 974
 975void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
 976{
 977    object_property_set_int(OBJECT(dev), value, name, &error_abort);
 978}
 979
 980void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
 981{
 982    object_property_set_int(OBJECT(dev), value, name, &error_abort);
 983}
 984
 985void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
 986{
 987    object_property_set_int(OBJECT(dev), value, name, &error_abort);
 988}
 989
 990void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
 991{
 992    object_property_set_int(OBJECT(dev), value, name, &error_abort);
 993}
 994
 995void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
 996{
 997    object_property_set_str(OBJECT(dev), value, name, &error_abort);
 998}
 999
1000void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1001{
1002    char str[2 * 6 + 5 + 1];
1003    snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
1004             value[0], value[1], value[2], value[3], value[4], value[5]);
1005
1006    object_property_set_str(OBJECT(dev), str, name, &error_abort);
1007}
1008
1009void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
1010{
1011    Property *prop;
1012
1013    prop = qdev_prop_find(dev, name);
1014    object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1015                            name, &error_abort);
1016}
1017
1018void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1019{
1020    Property *prop;
1021    void **ptr;
1022
1023    prop = qdev_prop_find(dev, name);
1024    assert(prop && prop->info == &qdev_prop_ptr);
1025    ptr = qdev_get_prop_ptr(dev, prop);
1026    *ptr = value;
1027}
1028
1029static QTAILQ_HEAD(, GlobalProperty) global_props =
1030        QTAILQ_HEAD_INITIALIZER(global_props);
1031
1032void qdev_prop_register_global(GlobalProperty *prop)
1033{
1034    QTAILQ_INSERT_TAIL(&global_props, prop, next);
1035}
1036
1037void qdev_prop_register_global_list(GlobalProperty *props)
1038{
1039    int i;
1040
1041    for (i = 0; props[i].driver != NULL; i++) {
1042        qdev_prop_register_global(props+i);
1043    }
1044}
1045
1046int qdev_prop_check_globals(void)
1047{
1048    GlobalProperty *prop;
1049    int ret = 0;
1050
1051    QTAILQ_FOREACH(prop, &global_props, next) {
1052        ObjectClass *oc;
1053        DeviceClass *dc;
1054        if (prop->used) {
1055            continue;
1056        }
1057        if (!prop->user_provided) {
1058            continue;
1059        }
1060        oc = object_class_by_name(prop->driver);
1061        oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
1062        if (!oc) {
1063            error_report("Warning: global %s.%s has invalid class name",
1064                       prop->driver, prop->property);
1065            ret = 1;
1066            continue;
1067        }
1068        dc = DEVICE_CLASS(oc);
1069        if (!dc->hotpluggable && !prop->used) {
1070            error_report("Warning: global %s.%s=%s not used",
1071                       prop->driver, prop->property, prop->value);
1072            ret = 1;
1073            continue;
1074        }
1075    }
1076    return ret;
1077}
1078
1079static void qdev_prop_set_globals_for_type(DeviceState *dev,
1080                                const char *typename)
1081{
1082    GlobalProperty *prop;
1083
1084    QTAILQ_FOREACH(prop, &global_props, next) {
1085        Error *err = NULL;
1086
1087        if (strcmp(typename, prop->driver) != 0) {
1088            continue;
1089        }
1090        prop->used = true;
1091        object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
1092        if (err != NULL) {
1093            assert(prop->user_provided);
1094            error_reportf_err(err, "Warning: global %s.%s=%s ignored: ",
1095                              prop->driver, prop->property, prop->value);
1096            return;
1097        }
1098    }
1099}
1100
1101void qdev_prop_set_globals(DeviceState *dev)
1102{
1103    ObjectClass *class = object_get_class(OBJECT(dev));
1104
1105    do {
1106        qdev_prop_set_globals_for_type(dev, object_class_get_name(class));
1107        class = object_class_get_parent(class);
1108    } while (class);
1109}
1110
1111/* --- 64bit unsigned int 'size' type --- */
1112
1113static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
1114                     Error **errp)
1115{
1116    DeviceState *dev = DEVICE(obj);
1117    Property *prop = opaque;
1118    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
1119
1120    visit_type_size(v, name, ptr, errp);
1121}
1122
1123static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
1124                     Error **errp)
1125{
1126    DeviceState *dev = DEVICE(obj);
1127    Property *prop = opaque;
1128    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
1129
1130    visit_type_size(v, name, ptr, errp);
1131}
1132
1133PropertyInfo qdev_prop_size = {
1134    .name  = "size",
1135    .get = get_size,
1136    .set = set_size,
1137};
1138