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