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