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