1 #include "qemu/osdep.h" 2 #include "hw/qdev-properties.h" 3 #include "qapi/error.h" 4 #include "qapi/qapi-types-misc.h" 5 #include "qobject/qlist.h" 6 #include "qemu/ctype.h" 7 #include "qemu/error-report.h" 8 #include "qapi/visitor.h" 9 #include "qemu/units.h" 10 #include "qemu/cutils.h" 11 #include "qdev-prop-internal.h" 12 #include "qom/qom-qobject.h" 13 14 void 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 28 /* returns: true if property is allowed to be set, false otherwise */ 29 static bool qdev_prop_allow_set(Object *obj, const char *name, 30 const PropertyInfo *info, Error **errp) 31 { 32 DeviceState *dev = DEVICE(obj); 33 34 if (dev->realized && !info->realized_set_allowed) { 35 qdev_prop_set_after_realize(dev, name, errp); 36 return false; 37 } 38 return true; 39 } 40 41 void qdev_prop_allow_set_link_before_realize(const Object *obj, 42 const char *name, 43 Object *val, Error **errp) 44 { 45 DeviceState *dev = DEVICE(obj); 46 47 if (dev->realized) { 48 error_setg(errp, "Attempt to set link property '%s' on device '%s' " 49 "(type '%s') after it was realized", 50 name, dev->id, object_get_typename(obj)); 51 } 52 } 53 54 void *object_field_prop_ptr(Object *obj, const Property *prop) 55 { 56 void *ptr = obj; 57 ptr += prop->offset; 58 return ptr; 59 } 60 61 static void field_prop_get(Object *obj, Visitor *v, const char *name, 62 void *opaque, Error **errp) 63 { 64 const Property *prop = opaque; 65 return prop->info->get(obj, v, name, opaque, errp); 66 } 67 68 /** 69 * field_prop_getter: Return getter function to be used for property 70 * 71 * Return value can be NULL if @info has no getter function. 72 */ 73 static ObjectPropertyAccessor *field_prop_getter(const PropertyInfo *info) 74 { 75 return info->get ? field_prop_get : NULL; 76 } 77 78 static void field_prop_set(Object *obj, Visitor *v, const char *name, 79 void *opaque, Error **errp) 80 { 81 const Property *prop = opaque; 82 83 if (!qdev_prop_allow_set(obj, name, prop->info, errp)) { 84 return; 85 } 86 87 return prop->info->set(obj, v, name, opaque, errp); 88 } 89 90 /** 91 * field_prop_setter: Return setter function to be used for property 92 * 93 * Return value can be NULL if @info has not setter function. 94 */ 95 static ObjectPropertyAccessor *field_prop_setter(const PropertyInfo *info) 96 { 97 return info->set ? field_prop_set : NULL; 98 } 99 100 void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name, 101 void *opaque, Error **errp) 102 { 103 const Property *prop = opaque; 104 int *ptr = object_field_prop_ptr(obj, prop); 105 106 visit_type_enum(v, name, ptr, prop->info->enum_table, errp); 107 } 108 109 void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name, 110 void *opaque, Error **errp) 111 { 112 const Property *prop = opaque; 113 int *ptr = object_field_prop_ptr(obj, prop); 114 115 visit_type_enum(v, name, ptr, prop->info->enum_table, errp); 116 } 117 118 void qdev_propinfo_set_default_value_enum(ObjectProperty *op, 119 const Property *prop) 120 { 121 object_property_set_default_str(op, 122 qapi_enum_lookup(prop->info->enum_table, prop->defval.i)); 123 } 124 125 /* Bit */ 126 127 static uint32_t qdev_get_prop_mask(const Property *prop) 128 { 129 assert(prop->info == &qdev_prop_bit); 130 return 0x1 << prop->bitnr; 131 } 132 133 static void bit_prop_set(Object *obj, const Property *props, bool val) 134 { 135 uint32_t *p = object_field_prop_ptr(obj, props); 136 uint32_t mask = qdev_get_prop_mask(props); 137 if (val) { 138 *p |= mask; 139 } else { 140 *p &= ~mask; 141 } 142 } 143 144 static void prop_get_bit(Object *obj, Visitor *v, const char *name, 145 void *opaque, Error **errp) 146 { 147 const Property *prop = opaque; 148 uint32_t *p = object_field_prop_ptr(obj, prop); 149 bool value = (*p & qdev_get_prop_mask(prop)) != 0; 150 151 visit_type_bool(v, name, &value, errp); 152 } 153 154 static void prop_set_bit(Object *obj, Visitor *v, const char *name, 155 void *opaque, Error **errp) 156 { 157 const Property *prop = opaque; 158 bool value; 159 160 if (!visit_type_bool(v, name, &value, errp)) { 161 return; 162 } 163 bit_prop_set(obj, prop, value); 164 } 165 166 static void set_default_value_bool(ObjectProperty *op, const Property *prop) 167 { 168 object_property_set_default_bool(op, prop->defval.u); 169 } 170 171 const PropertyInfo qdev_prop_bit = { 172 .name = "bool", 173 .description = "on/off", 174 .get = prop_get_bit, 175 .set = prop_set_bit, 176 .set_default_value = set_default_value_bool, 177 }; 178 179 /* Bit64 */ 180 181 static uint64_t qdev_get_prop_mask64(const Property *prop) 182 { 183 assert(prop->info == &qdev_prop_bit64); 184 return 0x1ull << prop->bitnr; 185 } 186 187 static void bit64_prop_set(Object *obj, const Property *props, bool val) 188 { 189 uint64_t *p = object_field_prop_ptr(obj, props); 190 uint64_t mask = qdev_get_prop_mask64(props); 191 if (val) { 192 *p |= mask; 193 } else { 194 *p &= ~mask; 195 } 196 } 197 198 static void prop_get_bit64(Object *obj, Visitor *v, const char *name, 199 void *opaque, Error **errp) 200 { 201 const Property *prop = opaque; 202 uint64_t *p = object_field_prop_ptr(obj, prop); 203 bool value = (*p & qdev_get_prop_mask64(prop)) != 0; 204 205 visit_type_bool(v, name, &value, errp); 206 } 207 208 static void prop_set_bit64(Object *obj, Visitor *v, const char *name, 209 void *opaque, Error **errp) 210 { 211 const Property *prop = opaque; 212 bool value; 213 214 if (!visit_type_bool(v, name, &value, errp)) { 215 return; 216 } 217 bit64_prop_set(obj, prop, value); 218 } 219 220 const PropertyInfo qdev_prop_bit64 = { 221 .name = "bool", 222 .description = "on/off", 223 .get = prop_get_bit64, 224 .set = prop_set_bit64, 225 .set_default_value = set_default_value_bool, 226 }; 227 228 /* --- bool --- */ 229 230 static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque, 231 Error **errp) 232 { 233 const Property *prop = opaque; 234 bool *ptr = object_field_prop_ptr(obj, prop); 235 236 visit_type_bool(v, name, ptr, errp); 237 } 238 239 static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque, 240 Error **errp) 241 { 242 const Property *prop = opaque; 243 bool *ptr = object_field_prop_ptr(obj, prop); 244 245 visit_type_bool(v, name, ptr, errp); 246 } 247 248 const PropertyInfo qdev_prop_bool = { 249 .name = "bool", 250 .get = get_bool, 251 .set = set_bool, 252 .set_default_value = set_default_value_bool, 253 }; 254 255 /* --- 8bit integer --- */ 256 257 static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque, 258 Error **errp) 259 { 260 const Property *prop = opaque; 261 uint8_t *ptr = object_field_prop_ptr(obj, prop); 262 263 visit_type_uint8(v, name, ptr, errp); 264 } 265 266 static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque, 267 Error **errp) 268 { 269 const Property *prop = opaque; 270 uint8_t *ptr = object_field_prop_ptr(obj, prop); 271 272 visit_type_uint8(v, name, ptr, errp); 273 } 274 275 void qdev_propinfo_set_default_value_int(ObjectProperty *op, 276 const Property *prop) 277 { 278 object_property_set_default_int(op, prop->defval.i); 279 } 280 281 void qdev_propinfo_set_default_value_uint(ObjectProperty *op, 282 const Property *prop) 283 { 284 object_property_set_default_uint(op, prop->defval.u); 285 } 286 287 const PropertyInfo qdev_prop_uint8 = { 288 .name = "uint8", 289 .get = get_uint8, 290 .set = set_uint8, 291 .set_default_value = qdev_propinfo_set_default_value_uint, 292 }; 293 294 /* --- 16bit integer --- */ 295 296 static void get_uint16(Object *obj, Visitor *v, const char *name, 297 void *opaque, Error **errp) 298 { 299 const Property *prop = opaque; 300 uint16_t *ptr = object_field_prop_ptr(obj, prop); 301 302 visit_type_uint16(v, name, ptr, errp); 303 } 304 305 static void set_uint16(Object *obj, Visitor *v, const char *name, 306 void *opaque, Error **errp) 307 { 308 const Property *prop = opaque; 309 uint16_t *ptr = object_field_prop_ptr(obj, prop); 310 311 visit_type_uint16(v, name, ptr, errp); 312 } 313 314 const PropertyInfo qdev_prop_uint16 = { 315 .name = "uint16", 316 .get = get_uint16, 317 .set = set_uint16, 318 .set_default_value = qdev_propinfo_set_default_value_uint, 319 }; 320 321 /* --- 32bit integer --- */ 322 323 static void get_uint32(Object *obj, Visitor *v, const char *name, 324 void *opaque, Error **errp) 325 { 326 const Property *prop = opaque; 327 uint32_t *ptr = object_field_prop_ptr(obj, prop); 328 329 visit_type_uint32(v, name, ptr, errp); 330 } 331 332 static void set_uint32(Object *obj, Visitor *v, const char *name, 333 void *opaque, Error **errp) 334 { 335 const Property *prop = opaque; 336 uint32_t *ptr = object_field_prop_ptr(obj, prop); 337 338 visit_type_uint32(v, name, ptr, errp); 339 } 340 341 void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name, 342 void *opaque, Error **errp) 343 { 344 const Property *prop = opaque; 345 int32_t *ptr = object_field_prop_ptr(obj, prop); 346 347 visit_type_int32(v, name, ptr, errp); 348 } 349 350 static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque, 351 Error **errp) 352 { 353 const Property *prop = opaque; 354 int32_t *ptr = object_field_prop_ptr(obj, prop); 355 356 visit_type_int32(v, name, ptr, errp); 357 } 358 359 const PropertyInfo qdev_prop_uint32 = { 360 .name = "uint32", 361 .get = get_uint32, 362 .set = set_uint32, 363 .set_default_value = qdev_propinfo_set_default_value_uint, 364 }; 365 366 const PropertyInfo qdev_prop_int32 = { 367 .name = "int32", 368 .get = qdev_propinfo_get_int32, 369 .set = set_int32, 370 .set_default_value = qdev_propinfo_set_default_value_int, 371 }; 372 373 /* --- 64bit integer --- */ 374 375 static void get_uint64(Object *obj, Visitor *v, const char *name, 376 void *opaque, Error **errp) 377 { 378 const Property *prop = opaque; 379 uint64_t *ptr = object_field_prop_ptr(obj, prop); 380 381 visit_type_uint64(v, name, ptr, errp); 382 } 383 384 static void set_uint64(Object *obj, Visitor *v, const char *name, 385 void *opaque, Error **errp) 386 { 387 const Property *prop = opaque; 388 uint64_t *ptr = object_field_prop_ptr(obj, prop); 389 390 visit_type_uint64(v, name, ptr, errp); 391 } 392 393 static void get_int64(Object *obj, Visitor *v, const char *name, 394 void *opaque, Error **errp) 395 { 396 const Property *prop = opaque; 397 int64_t *ptr = object_field_prop_ptr(obj, prop); 398 399 visit_type_int64(v, name, ptr, errp); 400 } 401 402 static void set_int64(Object *obj, Visitor *v, const char *name, 403 void *opaque, Error **errp) 404 { 405 const Property *prop = opaque; 406 int64_t *ptr = object_field_prop_ptr(obj, prop); 407 408 visit_type_int64(v, name, ptr, errp); 409 } 410 411 const PropertyInfo qdev_prop_uint64 = { 412 .name = "uint64", 413 .get = get_uint64, 414 .set = set_uint64, 415 .set_default_value = qdev_propinfo_set_default_value_uint, 416 }; 417 418 const PropertyInfo qdev_prop_int64 = { 419 .name = "int64", 420 .get = get_int64, 421 .set = set_int64, 422 .set_default_value = qdev_propinfo_set_default_value_int, 423 }; 424 425 static void set_uint64_checkmask(Object *obj, Visitor *v, const char *name, 426 void *opaque, Error **errp) 427 { 428 const Property *prop = opaque; 429 uint64_t *ptr = object_field_prop_ptr(obj, prop); 430 431 visit_type_uint64(v, name, ptr, errp); 432 if (*ptr & ~prop->bitmask) { 433 error_setg(errp, "Property value for '%s' has bits outside mask '0x%" PRIx64 "'", 434 name, prop->bitmask); 435 } 436 } 437 438 const PropertyInfo qdev_prop_uint64_checkmask = { 439 .name = "uint64", 440 .get = get_uint64, 441 .set = set_uint64_checkmask, 442 }; 443 444 /* --- string --- */ 445 446 static void release_string(Object *obj, const char *name, void *opaque) 447 { 448 const Property *prop = opaque; 449 g_free(*(char **)object_field_prop_ptr(obj, prop)); 450 } 451 452 static void get_string(Object *obj, Visitor *v, const char *name, 453 void *opaque, Error **errp) 454 { 455 const Property *prop = opaque; 456 char **ptr = object_field_prop_ptr(obj, prop); 457 458 if (!*ptr) { 459 char *str = (char *)""; 460 visit_type_str(v, name, &str, errp); 461 } else { 462 visit_type_str(v, name, ptr, errp); 463 } 464 } 465 466 static void set_string(Object *obj, Visitor *v, const char *name, 467 void *opaque, Error **errp) 468 { 469 const Property *prop = opaque; 470 char **ptr = object_field_prop_ptr(obj, prop); 471 char *str; 472 473 if (!visit_type_str(v, name, &str, errp)) { 474 return; 475 } 476 g_free(*ptr); 477 *ptr = str; 478 } 479 480 const PropertyInfo qdev_prop_string = { 481 .name = "str", 482 .release = release_string, 483 .get = get_string, 484 .set = set_string, 485 }; 486 487 /* --- on/off/auto --- */ 488 489 const PropertyInfo qdev_prop_on_off_auto = { 490 .name = "OnOffAuto", 491 .description = "on/off/auto", 492 .enum_table = &OnOffAuto_lookup, 493 .get = qdev_propinfo_get_enum, 494 .set = qdev_propinfo_set_enum, 495 .set_default_value = qdev_propinfo_set_default_value_enum, 496 }; 497 498 /* --- 32bit unsigned int 'size' type --- */ 499 500 void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name, 501 void *opaque, Error **errp) 502 { 503 const Property *prop = opaque; 504 uint32_t *ptr = object_field_prop_ptr(obj, prop); 505 uint64_t value = *ptr; 506 507 visit_type_size(v, name, &value, errp); 508 } 509 510 static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque, 511 Error **errp) 512 { 513 const Property *prop = opaque; 514 uint32_t *ptr = object_field_prop_ptr(obj, prop); 515 uint64_t value; 516 517 if (!visit_type_size(v, name, &value, errp)) { 518 return; 519 } 520 521 if (value > UINT32_MAX) { 522 error_setg(errp, 523 "Property %s.%s doesn't take value %" PRIu64 524 " (maximum: %u)", 525 object_get_typename(obj), name, value, UINT32_MAX); 526 return; 527 } 528 529 *ptr = value; 530 } 531 532 const PropertyInfo qdev_prop_size32 = { 533 .name = "size", 534 .get = qdev_propinfo_get_size32, 535 .set = set_size32, 536 .set_default_value = qdev_propinfo_set_default_value_uint, 537 }; 538 539 /* --- support for array properties --- */ 540 541 typedef struct ArrayElementList ArrayElementList; 542 543 struct ArrayElementList { 544 ArrayElementList *next; 545 void *value; 546 }; 547 548 /* 549 * Given an array property @parent_prop in @obj, return a Property for a 550 * specific element of the array. Arrays are backed by an uint32_t length field 551 * and an element array. @elem points at an element in this element array. 552 */ 553 static Property array_elem_prop(Object *obj, const Property *parent_prop, 554 const char *name, char *elem) 555 { 556 return (Property) { 557 .info = parent_prop->arrayinfo, 558 .name = name, 559 /* 560 * This ugly piece of pointer arithmetic sets up the offset so 561 * that when the underlying release hook calls qdev_get_prop_ptr 562 * they get the right answer despite the array element not actually 563 * being inside the device struct. 564 */ 565 .offset = (uintptr_t)elem - (uintptr_t)obj, 566 }; 567 } 568 569 /* 570 * Object property release callback for array properties: We call the 571 * underlying element's property release hook for each element. 572 * 573 * Note that it is the responsibility of the individual device's deinit 574 * to free the array proper. 575 */ 576 static void release_prop_array(Object *obj, const char *name, void *opaque) 577 { 578 const Property *prop = opaque; 579 uint32_t *alenptr = object_field_prop_ptr(obj, prop); 580 void **arrayptr = (void *)obj + prop->arrayoffset; 581 char *elem = *arrayptr; 582 int i; 583 584 if (!prop->arrayinfo->release) { 585 return; 586 } 587 588 for (i = 0; i < *alenptr; i++) { 589 Property elem_prop = array_elem_prop(obj, prop, name, elem); 590 prop->arrayinfo->release(obj, NULL, &elem_prop); 591 elem += prop->arrayfieldsize; 592 } 593 } 594 595 /* 596 * Setter for an array property. This sets both the array length (which 597 * is technically the property field in the object) and the array itself 598 * (a pointer to which is stored in the additional field described by 599 * prop->arrayoffset). 600 */ 601 static void set_prop_array(Object *obj, Visitor *v, const char *name, 602 void *opaque, Error **errp) 603 { 604 ERRP_GUARD(); 605 const Property *prop = opaque; 606 uint32_t *alenptr = object_field_prop_ptr(obj, prop); 607 void **arrayptr = (void *)obj + prop->arrayoffset; 608 ArrayElementList *list, *elem, *next; 609 const size_t size = sizeof(*list); 610 char *elemptr; 611 bool ok = true; 612 613 if (*alenptr) { 614 error_setg(errp, "array size property %s may not be set more than once", 615 name); 616 return; 617 } 618 619 if (!visit_start_list(v, name, (GenericList **) &list, size, errp)) { 620 return; 621 } 622 623 /* Read the whole input into a temporary list */ 624 elem = list; 625 while (elem) { 626 Property elem_prop; 627 628 elem->value = g_malloc0(prop->arrayfieldsize); 629 elem_prop = array_elem_prop(obj, prop, name, elem->value); 630 prop->arrayinfo->set(obj, v, NULL, &elem_prop, errp); 631 if (*errp) { 632 ok = false; 633 goto out_obj; 634 } 635 if (*alenptr == INT_MAX) { 636 error_setg(errp, "array is too big"); 637 return; 638 } 639 (*alenptr)++; 640 elem = (ArrayElementList *) visit_next_list(v, (GenericList*) elem, 641 size); 642 } 643 644 ok = visit_check_list(v, errp); 645 out_obj: 646 visit_end_list(v, (void**) &list); 647 648 if (!ok) { 649 for (elem = list; elem; elem = next) { 650 Property elem_prop = array_elem_prop(obj, prop, name, 651 elem->value); 652 if (prop->arrayinfo->release) { 653 prop->arrayinfo->release(obj, NULL, &elem_prop); 654 } 655 next = elem->next; 656 g_free(elem->value); 657 g_free(elem); 658 } 659 return; 660 } 661 662 /* 663 * Now that we know how big the array has to be, move the data over to a 664 * linear array and free the temporary list. 665 */ 666 *arrayptr = g_malloc_n(*alenptr, prop->arrayfieldsize); 667 elemptr = *arrayptr; 668 for (elem = list; elem; elem = next) { 669 memcpy(elemptr, elem->value, prop->arrayfieldsize); 670 elemptr += prop->arrayfieldsize; 671 next = elem->next; 672 g_free(elem->value); 673 g_free(elem); 674 } 675 } 676 677 static void get_prop_array(Object *obj, Visitor *v, const char *name, 678 void *opaque, Error **errp) 679 { 680 ERRP_GUARD(); 681 const Property *prop = opaque; 682 uint32_t *alenptr = object_field_prop_ptr(obj, prop); 683 void **arrayptr = (void *)obj + prop->arrayoffset; 684 char *elemptr = *arrayptr; 685 ArrayElementList *list = NULL, *elem; 686 ArrayElementList **tail = &list; 687 const size_t size = sizeof(*list); 688 int i; 689 bool ok; 690 691 /* At least the string output visitor needs a real list */ 692 for (i = 0; i < *alenptr; i++) { 693 elem = g_new0(ArrayElementList, 1); 694 elem->value = elemptr; 695 elemptr += prop->arrayfieldsize; 696 697 *tail = elem; 698 tail = &elem->next; 699 } 700 701 if (!visit_start_list(v, name, (GenericList **) &list, size, errp)) { 702 return; 703 } 704 705 elem = list; 706 while (elem) { 707 Property elem_prop = array_elem_prop(obj, prop, name, elem->value); 708 prop->arrayinfo->get(obj, v, NULL, &elem_prop, errp); 709 if (*errp) { 710 goto out_obj; 711 } 712 elem = (ArrayElementList *) visit_next_list(v, (GenericList*) elem, 713 size); 714 } 715 716 /* visit_check_list() can only fail for input visitors */ 717 ok = visit_check_list(v, errp); 718 assert(ok); 719 720 out_obj: 721 visit_end_list(v, (void**) &list); 722 723 while (list) { 724 elem = list; 725 list = elem->next; 726 g_free(elem); 727 } 728 } 729 730 static void default_prop_array(ObjectProperty *op, const Property *prop) 731 { 732 object_property_set_default_list(op); 733 } 734 735 const PropertyInfo qdev_prop_array = { 736 .name = "list", 737 .get = get_prop_array, 738 .set = set_prop_array, 739 .release = release_prop_array, 740 .set_default_value = default_prop_array, 741 }; 742 743 /* --- public helpers --- */ 744 745 static const Property *qdev_prop_walk(DeviceClass *cls, const char *name) 746 { 747 for (int i = 0, n = cls->props_count_; i < n; ++i) { 748 const Property *prop = &cls->props_[i]; 749 if (strcmp(prop->name, name) == 0) { 750 return prop; 751 } 752 } 753 return NULL; 754 } 755 756 static const Property *qdev_prop_find(DeviceState *dev, const char *name) 757 { 758 ObjectClass *class; 759 const Property *prop; 760 761 /* device properties */ 762 class = object_get_class(OBJECT(dev)); 763 do { 764 prop = qdev_prop_walk(DEVICE_CLASS(class), name); 765 if (prop) { 766 return prop; 767 } 768 class = object_class_get_parent(class); 769 } while (class != object_class_by_name(TYPE_DEVICE)); 770 771 return NULL; 772 } 773 774 void error_set_from_qdev_prop_error(Error **errp, int ret, Object *obj, 775 const char *name, const char *value) 776 { 777 switch (ret) { 778 case -EEXIST: 779 error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use", 780 object_get_typename(obj), name, value); 781 break; 782 default: 783 case -EINVAL: 784 error_setg(errp, "Property '%s.%s' doesn't take value '%s'", 785 object_get_typename(obj), name, value); 786 break; 787 case -ENOENT: 788 error_setg(errp, "Property '%s.%s' can't find value '%s'", 789 object_get_typename(obj), name, value); 790 break; 791 case 0: 792 break; 793 } 794 } 795 796 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value) 797 { 798 object_property_set_bool(OBJECT(dev), name, value, &error_abort); 799 } 800 801 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value) 802 { 803 object_property_set_int(OBJECT(dev), name, value, &error_abort); 804 } 805 806 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value) 807 { 808 object_property_set_int(OBJECT(dev), name, value, &error_abort); 809 } 810 811 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value) 812 { 813 object_property_set_int(OBJECT(dev), name, value, &error_abort); 814 } 815 816 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value) 817 { 818 object_property_set_int(OBJECT(dev), name, value, &error_abort); 819 } 820 821 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value) 822 { 823 object_property_set_int(OBJECT(dev), name, value, &error_abort); 824 } 825 826 void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value) 827 { 828 object_property_set_str(OBJECT(dev), name, value, &error_abort); 829 } 830 831 void qdev_prop_set_enum(DeviceState *dev, const char *name, int value) 832 { 833 const Property *prop; 834 835 prop = qdev_prop_find(dev, name); 836 object_property_set_str(OBJECT(dev), name, 837 qapi_enum_lookup(prop->info->enum_table, value), 838 &error_abort); 839 } 840 841 void qdev_prop_set_array(DeviceState *dev, const char *name, QList *values) 842 { 843 object_property_set_qobject(OBJECT(dev), name, QOBJECT(values), 844 &error_abort); 845 qobject_unref(values); 846 } 847 848 static GPtrArray *global_props(void) 849 { 850 static GPtrArray *gp; 851 852 if (!gp) { 853 gp = g_ptr_array_new(); 854 } 855 856 return gp; 857 } 858 859 void qdev_prop_register_global(GlobalProperty *prop) 860 { 861 g_ptr_array_add(global_props(), prop); 862 } 863 864 const GlobalProperty *qdev_find_global_prop(Object *obj, 865 const char *name) 866 { 867 GPtrArray *props = global_props(); 868 const GlobalProperty *p; 869 int i; 870 871 for (i = 0; i < props->len; i++) { 872 p = g_ptr_array_index(props, i); 873 if (object_dynamic_cast(obj, p->driver) 874 && !strcmp(p->property, name)) { 875 return p; 876 } 877 } 878 return NULL; 879 } 880 881 int qdev_prop_check_globals(void) 882 { 883 int i, ret = 0; 884 885 for (i = 0; i < global_props()->len; i++) { 886 GlobalProperty *prop; 887 ObjectClass *oc; 888 DeviceClass *dc; 889 890 prop = g_ptr_array_index(global_props(), i); 891 if (prop->used) { 892 continue; 893 } 894 oc = object_class_by_name(prop->driver); 895 oc = object_class_dynamic_cast(oc, TYPE_DEVICE); 896 if (!oc) { 897 warn_report("global %s.%s has invalid class name", 898 prop->driver, prop->property); 899 ret = 1; 900 continue; 901 } 902 dc = DEVICE_CLASS(oc); 903 if (!dc->hotpluggable && !prop->used) { 904 warn_report("global %s.%s=%s not used", 905 prop->driver, prop->property, prop->value); 906 ret = 1; 907 continue; 908 } 909 } 910 return ret; 911 } 912 913 void qdev_prop_set_globals(DeviceState *dev) 914 { 915 object_apply_global_props(OBJECT(dev), global_props(), 916 dev->hotplugged ? NULL : &error_fatal); 917 } 918 919 /* --- 64bit unsigned int 'size' type --- */ 920 921 static void get_size(Object *obj, Visitor *v, const char *name, void *opaque, 922 Error **errp) 923 { 924 const Property *prop = opaque; 925 uint64_t *ptr = object_field_prop_ptr(obj, prop); 926 927 visit_type_size(v, name, ptr, errp); 928 } 929 930 static void set_size(Object *obj, Visitor *v, const char *name, void *opaque, 931 Error **errp) 932 { 933 const Property *prop = opaque; 934 uint64_t *ptr = object_field_prop_ptr(obj, prop); 935 936 visit_type_size(v, name, ptr, errp); 937 } 938 939 const PropertyInfo qdev_prop_size = { 940 .name = "size", 941 .get = get_size, 942 .set = set_size, 943 .set_default_value = qdev_propinfo_set_default_value_uint, 944 }; 945 946 /* --- object link property --- */ 947 948 static ObjectProperty *create_link_property(ObjectClass *oc, const char *name, 949 const Property *prop) 950 { 951 return object_class_property_add_link(oc, name, prop->link_type, 952 prop->offset, 953 qdev_prop_allow_set_link_before_realize, 954 OBJ_PROP_LINK_STRONG); 955 } 956 957 const PropertyInfo qdev_prop_link = { 958 .name = "link", 959 .create = create_link_property, 960 }; 961 962 void qdev_property_add_static(DeviceState *dev, const Property *prop) 963 { 964 Object *obj = OBJECT(dev); 965 ObjectProperty *op; 966 967 assert(!prop->info->create); 968 969 op = object_property_add(obj, prop->name, prop->info->name, 970 field_prop_getter(prop->info), 971 field_prop_setter(prop->info), 972 prop->info->release, 973 (Property *)prop); 974 975 object_property_set_description(obj, prop->name, 976 prop->info->description); 977 978 if (prop->set_default) { 979 prop->info->set_default_value(op, prop); 980 if (op->init) { 981 op->init(obj, op); 982 } 983 } 984 } 985 986 static void qdev_class_add_property(DeviceClass *klass, const char *name, 987 const Property *prop) 988 { 989 ObjectClass *oc = OBJECT_CLASS(klass); 990 ObjectProperty *op; 991 992 if (prop->info->create) { 993 op = prop->info->create(oc, name, prop); 994 } else { 995 op = object_class_property_add(oc, 996 name, prop->info->name, 997 field_prop_getter(prop->info), 998 field_prop_setter(prop->info), 999 prop->info->release, 1000 (Property *)prop); 1001 } 1002 if (prop->set_default) { 1003 prop->info->set_default_value(op, prop); 1004 } 1005 object_class_property_set_description(oc, name, prop->info->description); 1006 } 1007 1008 /** 1009 * Legacy property handling 1010 */ 1011 1012 static void qdev_get_legacy_property(Object *obj, Visitor *v, 1013 const char *name, void *opaque, 1014 Error **errp) 1015 { 1016 const Property *prop = opaque; 1017 1018 char buffer[1024]; 1019 char *ptr = buffer; 1020 1021 prop->info->print(obj, prop, buffer, sizeof(buffer)); 1022 visit_type_str(v, name, &ptr, errp); 1023 } 1024 1025 /** 1026 * qdev_class_add_legacy_property: 1027 * @dev: Device to add the property to. 1028 * @prop: The qdev property definition. 1029 * 1030 * Add a legacy QOM property to @dev for qdev property @prop. 1031 * 1032 * Legacy properties are string versions of QOM properties. The format of 1033 * the string depends on the property type. Legacy properties are only 1034 * needed for "info qtree". 1035 * 1036 * Do not use this in new code! QOM Properties added through this interface 1037 * will be given names in the "legacy" namespace. 1038 */ 1039 static void qdev_class_add_legacy_property(DeviceClass *dc, const Property *prop) 1040 { 1041 g_autofree char *name = NULL; 1042 1043 /* Register pointer properties as legacy properties */ 1044 if (!prop->info->print && prop->info->get) { 1045 return; 1046 } 1047 1048 name = g_strdup_printf("legacy-%s", prop->name); 1049 object_class_property_add(OBJECT_CLASS(dc), name, "str", 1050 prop->info->print ? qdev_get_legacy_property : prop->info->get, 1051 NULL, NULL, (Property *)prop); 1052 } 1053 1054 void device_class_set_props_n(DeviceClass *dc, const Property *props, size_t n) 1055 { 1056 /* We used a hole in DeviceClass because that's still a lot. */ 1057 assert(n <= UINT16_MAX); 1058 assert(n != 0); 1059 1060 dc->props_ = props; 1061 dc->props_count_ = n; 1062 1063 for (size_t i = 0; i < n; ++i) { 1064 const Property *prop = &props[i]; 1065 assert(prop->name); 1066 qdev_class_add_legacy_property(dc, prop); 1067 qdev_class_add_property(dc, prop->name, prop); 1068 } 1069 } 1070 1071 void qdev_alias_all_properties(DeviceState *target, Object *source) 1072 { 1073 ObjectClass *class; 1074 ObjectPropertyIterator iter; 1075 ObjectProperty *prop; 1076 1077 class = object_get_class(OBJECT(target)); 1078 1079 object_class_property_iter_init(&iter, class); 1080 while ((prop = object_property_iter_next(&iter))) { 1081 if (object_property_find(source, prop->name)) { 1082 continue; /* skip duplicate properties */ 1083 } 1084 1085 object_property_add_alias(source, prop->name, 1086 OBJECT(target), prop->name); 1087 } 1088 } 1089