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 = "boolean", 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 = "boolean", 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 = "string", 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 = "macaddr", 446 .get = get_mac, 447 .set = set_mac, 448 }; 449 450 /* --- lost tick policy --- */ 451 452 static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = { 453 [LOST_TICK_DISCARD] = "discard", 454 [LOST_TICK_DELAY] = "delay", 455 [LOST_TICK_MERGE] = "merge", 456 [LOST_TICK_SLEW] = "slew", 457 [LOST_TICK_MAX] = NULL, 458 }; 459 460 QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int)); 461 462 PropertyInfo qdev_prop_losttickpolicy = { 463 .name = "LostTickPolicy", 464 .enum_table = lost_tick_policy_table, 465 .get = get_enum, 466 .set = set_enum, 467 }; 468 469 /* --- BIOS CHS translation */ 470 471 static const char *bios_chs_trans_table[] = { 472 [BIOS_ATA_TRANSLATION_AUTO] = "auto", 473 [BIOS_ATA_TRANSLATION_NONE] = "none", 474 [BIOS_ATA_TRANSLATION_LBA] = "lba", 475 }; 476 477 PropertyInfo qdev_prop_bios_chs_trans = { 478 .name = "bios-chs-trans", 479 .enum_table = bios_chs_trans_table, 480 .get = get_enum, 481 .set = set_enum, 482 }; 483 484 /* --- pci address --- */ 485 486 /* 487 * bus-local address, i.e. "$slot" or "$slot.$fn" 488 */ 489 static void set_pci_devfn(Object *obj, Visitor *v, void *opaque, 490 const char *name, Error **errp) 491 { 492 DeviceState *dev = DEVICE(obj); 493 Property *prop = opaque; 494 int32_t value, *ptr = qdev_get_prop_ptr(dev, prop); 495 unsigned int slot, fn, n; 496 Error *local_err = NULL; 497 char *str; 498 499 if (dev->realized) { 500 qdev_prop_set_after_realize(dev, name, errp); 501 return; 502 } 503 504 visit_type_str(v, &str, name, &local_err); 505 if (local_err) { 506 error_free(local_err); 507 local_err = NULL; 508 visit_type_int32(v, &value, name, &local_err); 509 if (local_err) { 510 error_propagate(errp, local_err); 511 } else if (value < -1 || value > 255) { 512 error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null", 513 "pci_devfn"); 514 } else { 515 *ptr = value; 516 } 517 return; 518 } 519 520 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) { 521 fn = 0; 522 if (sscanf(str, "%x%n", &slot, &n) != 1) { 523 goto invalid; 524 } 525 } 526 if (str[n] != '\0' || fn > 7 || slot > 31) { 527 goto invalid; 528 } 529 *ptr = slot << 3 | fn; 530 g_free(str); 531 return; 532 533 invalid: 534 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); 535 g_free(str); 536 } 537 538 static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, 539 size_t len) 540 { 541 int32_t *ptr = qdev_get_prop_ptr(dev, prop); 542 543 if (*ptr == -1) { 544 return snprintf(dest, len, "<unset>"); 545 } else { 546 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7); 547 } 548 } 549 550 PropertyInfo qdev_prop_pci_devfn = { 551 .name = "int32", 552 .legacy_name = "pci-devfn", 553 .print = print_pci_devfn, 554 .get = get_int32, 555 .set = set_pci_devfn, 556 }; 557 558 /* --- blocksize --- */ 559 560 static void set_blocksize(Object *obj, Visitor *v, void *opaque, 561 const char *name, Error **errp) 562 { 563 DeviceState *dev = DEVICE(obj); 564 Property *prop = opaque; 565 uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop); 566 Error *local_err = NULL; 567 const int64_t min = 512; 568 const int64_t max = 32768; 569 570 if (dev->realized) { 571 qdev_prop_set_after_realize(dev, name, errp); 572 return; 573 } 574 575 visit_type_uint16(v, &value, name, &local_err); 576 if (local_err) { 577 error_propagate(errp, local_err); 578 return; 579 } 580 if (value < min || value > max) { 581 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, 582 dev->id?:"", name, (int64_t)value, min, max); 583 return; 584 } 585 586 /* We rely on power-of-2 blocksizes for bitmasks */ 587 if ((value & (value - 1)) != 0) { 588 error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2, 589 dev->id?:"", name, (int64_t)value); 590 return; 591 } 592 593 *ptr = value; 594 } 595 596 PropertyInfo qdev_prop_blocksize = { 597 .name = "blocksize", 598 .get = get_uint16, 599 .set = set_blocksize, 600 }; 601 602 /* --- pci host address --- */ 603 604 static void get_pci_host_devaddr(Object *obj, Visitor *v, void *opaque, 605 const char *name, Error **errp) 606 { 607 DeviceState *dev = DEVICE(obj); 608 Property *prop = opaque; 609 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); 610 char buffer[] = "xxxx:xx:xx.x"; 611 char *p = buffer; 612 int rc = 0; 613 614 rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d", 615 addr->domain, addr->bus, addr->slot, addr->function); 616 assert(rc == sizeof(buffer) - 1); 617 618 visit_type_str(v, &p, name, errp); 619 } 620 621 /* 622 * Parse [<domain>:]<bus>:<slot>.<func> 623 * if <domain> is not supplied, it's assumed to be 0. 624 */ 625 static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque, 626 const char *name, Error **errp) 627 { 628 DeviceState *dev = DEVICE(obj); 629 Property *prop = opaque; 630 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); 631 Error *local_err = NULL; 632 char *str, *p; 633 char *e; 634 unsigned long val; 635 unsigned long dom = 0, bus = 0; 636 unsigned int slot = 0, func = 0; 637 638 if (dev->realized) { 639 qdev_prop_set_after_realize(dev, name, errp); 640 return; 641 } 642 643 visit_type_str(v, &str, name, &local_err); 644 if (local_err) { 645 error_propagate(errp, local_err); 646 return; 647 } 648 649 p = str; 650 val = strtoul(p, &e, 16); 651 if (e == p || *e != ':') { 652 goto inval; 653 } 654 bus = val; 655 656 p = e + 1; 657 val = strtoul(p, &e, 16); 658 if (e == p) { 659 goto inval; 660 } 661 if (*e == ':') { 662 dom = bus; 663 bus = val; 664 p = e + 1; 665 val = strtoul(p, &e, 16); 666 if (e == p) { 667 goto inval; 668 } 669 } 670 slot = val; 671 672 if (*e != '.') { 673 goto inval; 674 } 675 p = e + 1; 676 val = strtoul(p, &e, 10); 677 if (e == p) { 678 goto inval; 679 } 680 func = val; 681 682 if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) { 683 goto inval; 684 } 685 686 if (*e) { 687 goto inval; 688 } 689 690 addr->domain = dom; 691 addr->bus = bus; 692 addr->slot = slot; 693 addr->function = func; 694 695 g_free(str); 696 return; 697 698 inval: 699 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); 700 g_free(str); 701 } 702 703 PropertyInfo qdev_prop_pci_host_devaddr = { 704 .name = "pci-host-devaddr", 705 .get = get_pci_host_devaddr, 706 .set = set_pci_host_devaddr, 707 }; 708 709 /* --- support for array properties --- */ 710 711 /* Used as an opaque for the object properties we add for each 712 * array element. Note that the struct Property must be first 713 * in the struct so that a pointer to this works as the opaque 714 * for the underlying element's property hooks as well as for 715 * our own release callback. 716 */ 717 typedef struct { 718 struct Property prop; 719 char *propname; 720 ObjectPropertyRelease *release; 721 } ArrayElementProperty; 722 723 /* object property release callback for array element properties: 724 * we call the underlying element's property release hook, and 725 * then free the memory we allocated when we added the property. 726 */ 727 static void array_element_release(Object *obj, const char *name, void *opaque) 728 { 729 ArrayElementProperty *p = opaque; 730 if (p->release) { 731 p->release(obj, name, opaque); 732 } 733 g_free(p->propname); 734 g_free(p); 735 } 736 737 static void set_prop_arraylen(Object *obj, Visitor *v, void *opaque, 738 const char *name, Error **errp) 739 { 740 /* Setter for the property which defines the length of a 741 * variable-sized property array. As well as actually setting the 742 * array-length field in the device struct, we have to create the 743 * array itself and dynamically add the corresponding properties. 744 */ 745 DeviceState *dev = DEVICE(obj); 746 Property *prop = opaque; 747 uint32_t *alenptr = qdev_get_prop_ptr(dev, prop); 748 void **arrayptr = (void *)dev + prop->arrayoffset; 749 void *eltptr; 750 const char *arrayname; 751 int i; 752 753 if (dev->realized) { 754 qdev_prop_set_after_realize(dev, name, errp); 755 return; 756 } 757 if (*alenptr) { 758 error_setg(errp, "array size property %s may not be set more than once", 759 name); 760 return; 761 } 762 visit_type_uint32(v, alenptr, name, errp); 763 if (error_is_set(errp)) { 764 return; 765 } 766 if (!*alenptr) { 767 return; 768 } 769 770 /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix; 771 * strip it off so we can get the name of the array itself. 772 */ 773 assert(strncmp(name, PROP_ARRAY_LEN_PREFIX, 774 strlen(PROP_ARRAY_LEN_PREFIX)) == 0); 775 arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX); 776 777 /* Note that it is the responsibility of the individual device's deinit 778 * to free the array proper. 779 */ 780 *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize); 781 for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) { 782 char *propname = g_strdup_printf("%s[%d]", arrayname, i); 783 ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1); 784 arrayprop->release = prop->arrayinfo->release; 785 arrayprop->propname = propname; 786 arrayprop->prop.info = prop->arrayinfo; 787 arrayprop->prop.name = propname; 788 /* This ugly piece of pointer arithmetic sets up the offset so 789 * that when the underlying get/set hooks call qdev_get_prop_ptr 790 * they get the right answer despite the array element not actually 791 * being inside the device struct. 792 */ 793 arrayprop->prop.offset = eltptr - (void *)dev; 794 assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr); 795 object_property_add(obj, propname, 796 arrayprop->prop.info->name, 797 arrayprop->prop.info->get, 798 arrayprop->prop.info->set, 799 array_element_release, 800 arrayprop, errp); 801 if (error_is_set(errp)) { 802 return; 803 } 804 } 805 } 806 807 PropertyInfo qdev_prop_arraylen = { 808 .name = "uint32", 809 .get = get_uint32, 810 .set = set_prop_arraylen, 811 }; 812 813 /* --- public helpers --- */ 814 815 static Property *qdev_prop_walk(Property *props, const char *name) 816 { 817 if (!props) { 818 return NULL; 819 } 820 while (props->name) { 821 if (strcmp(props->name, name) == 0) { 822 return props; 823 } 824 props++; 825 } 826 return NULL; 827 } 828 829 static Property *qdev_prop_find(DeviceState *dev, const char *name) 830 { 831 ObjectClass *class; 832 Property *prop; 833 834 /* device properties */ 835 class = object_get_class(OBJECT(dev)); 836 do { 837 prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name); 838 if (prop) { 839 return prop; 840 } 841 class = object_class_get_parent(class); 842 } while (class != object_class_by_name(TYPE_DEVICE)); 843 844 return NULL; 845 } 846 847 void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, 848 Property *prop, const char *value) 849 { 850 switch (ret) { 851 case -EEXIST: 852 error_set(errp, QERR_PROPERTY_VALUE_IN_USE, 853 object_get_typename(OBJECT(dev)), prop->name, value); 854 break; 855 default: 856 case -EINVAL: 857 error_set(errp, QERR_PROPERTY_VALUE_BAD, 858 object_get_typename(OBJECT(dev)), prop->name, value); 859 break; 860 case -ENOENT: 861 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND, 862 object_get_typename(OBJECT(dev)), prop->name, value); 863 break; 864 case 0: 865 break; 866 } 867 } 868 869 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value) 870 { 871 object_property_set_bool(OBJECT(dev), value, name, &error_abort); 872 } 873 874 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value) 875 { 876 object_property_set_int(OBJECT(dev), value, name, &error_abort); 877 } 878 879 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value) 880 { 881 object_property_set_int(OBJECT(dev), value, name, &error_abort); 882 } 883 884 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value) 885 { 886 object_property_set_int(OBJECT(dev), value, name, &error_abort); 887 } 888 889 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value) 890 { 891 object_property_set_int(OBJECT(dev), value, name, &error_abort); 892 } 893 894 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value) 895 { 896 object_property_set_int(OBJECT(dev), value, name, &error_abort); 897 } 898 899 void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value) 900 { 901 object_property_set_str(OBJECT(dev), value, name, &error_abort); 902 } 903 904 void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value) 905 { 906 char str[2 * 6 + 5 + 1]; 907 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x", 908 value[0], value[1], value[2], value[3], value[4], value[5]); 909 910 object_property_set_str(OBJECT(dev), str, name, &error_abort); 911 } 912 913 void qdev_prop_set_enum(DeviceState *dev, const char *name, int value) 914 { 915 Property *prop; 916 917 prop = qdev_prop_find(dev, name); 918 object_property_set_str(OBJECT(dev), prop->info->enum_table[value], 919 name, &error_abort); 920 } 921 922 void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value) 923 { 924 Property *prop; 925 void **ptr; 926 927 prop = qdev_prop_find(dev, name); 928 assert(prop && prop->info == &qdev_prop_ptr); 929 ptr = qdev_get_prop_ptr(dev, prop); 930 *ptr = value; 931 } 932 933 static QTAILQ_HEAD(, GlobalProperty) global_props = 934 QTAILQ_HEAD_INITIALIZER(global_props); 935 936 void qdev_prop_register_global(GlobalProperty *prop) 937 { 938 QTAILQ_INSERT_TAIL(&global_props, prop, next); 939 } 940 941 void qdev_prop_register_global_list(GlobalProperty *props) 942 { 943 int i; 944 945 for (i = 0; props[i].driver != NULL; i++) { 946 qdev_prop_register_global(props+i); 947 } 948 } 949 950 void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename, 951 Error **errp) 952 { 953 GlobalProperty *prop; 954 955 QTAILQ_FOREACH(prop, &global_props, next) { 956 Error *err = NULL; 957 958 if (strcmp(typename, prop->driver) != 0) { 959 continue; 960 } 961 object_property_parse(OBJECT(dev), prop->value, prop->property, &err); 962 if (err != NULL) { 963 error_propagate(errp, err); 964 return; 965 } 966 } 967 } 968 969 void qdev_prop_set_globals(DeviceState *dev, Error **errp) 970 { 971 ObjectClass *class = object_get_class(OBJECT(dev)); 972 973 do { 974 Error *err = NULL; 975 976 qdev_prop_set_globals_for_type(dev, object_class_get_name(class), 977 &err); 978 if (err != NULL) { 979 error_propagate(errp, err); 980 return; 981 } 982 class = object_class_get_parent(class); 983 } while (class); 984 } 985 986 /* --- 64bit unsigned int 'size' type --- */ 987 988 static void get_size(Object *obj, Visitor *v, void *opaque, 989 const char *name, Error **errp) 990 { 991 DeviceState *dev = DEVICE(obj); 992 Property *prop = opaque; 993 uint64_t *ptr = qdev_get_prop_ptr(dev, prop); 994 995 visit_type_size(v, ptr, name, errp); 996 } 997 998 static void set_size(Object *obj, Visitor *v, void *opaque, 999 const char *name, Error **errp) 1000 { 1001 DeviceState *dev = DEVICE(obj); 1002 Property *prop = opaque; 1003 uint64_t *ptr = qdev_get_prop_ptr(dev, prop); 1004 1005 visit_type_size(v, ptr, name, errp); 1006 } 1007 1008 PropertyInfo qdev_prop_size = { 1009 .name = "size", 1010 .get = get_size, 1011 .set = set_size, 1012 }; 1013