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 /* --- pointer-size integer --- */ 446 447 static void get_usize(Object *obj, Visitor *v, const char *name, void *opaque, 448 Error **errp) 449 { 450 const Property *prop = opaque; 451 452 #if HOST_LONG_BITS == 32 453 uint32_t *ptr = object_field_prop_ptr(obj, prop); 454 visit_type_uint32(v, name, ptr, errp); 455 #else 456 uint64_t *ptr = object_field_prop_ptr(obj, prop); 457 visit_type_uint64(v, name, ptr, errp); 458 #endif 459 } 460 461 static void set_usize(Object *obj, Visitor *v, const char *name, void *opaque, 462 Error **errp) 463 { 464 const Property *prop = opaque; 465 466 #if HOST_LONG_BITS == 32 467 uint32_t *ptr = object_field_prop_ptr(obj, prop); 468 visit_type_uint32(v, name, ptr, errp); 469 #else 470 uint64_t *ptr = object_field_prop_ptr(obj, prop); 471 visit_type_uint64(v, name, ptr, errp); 472 #endif 473 } 474 475 const PropertyInfo qdev_prop_usize = { 476 .type = "usize", 477 .get = get_usize, 478 .set = set_usize, 479 .set_default_value = qdev_propinfo_set_default_value_uint, 480 }; 481 482 /* --- string --- */ 483 484 static void release_string(Object *obj, const char *name, void *opaque) 485 { 486 const Property *prop = opaque; 487 g_free(*(char **)object_field_prop_ptr(obj, prop)); 488 } 489 490 static void get_string(Object *obj, Visitor *v, const char *name, 491 void *opaque, Error **errp) 492 { 493 const Property *prop = opaque; 494 char **ptr = object_field_prop_ptr(obj, prop); 495 496 if (!*ptr) { 497 char *str = (char *)""; 498 visit_type_str(v, name, &str, errp); 499 } else { 500 visit_type_str(v, name, ptr, errp); 501 } 502 } 503 504 static void set_string(Object *obj, Visitor *v, const char *name, 505 void *opaque, Error **errp) 506 { 507 const Property *prop = opaque; 508 char **ptr = object_field_prop_ptr(obj, prop); 509 char *str; 510 511 if (!visit_type_str(v, name, &str, errp)) { 512 return; 513 } 514 g_free(*ptr); 515 *ptr = str; 516 } 517 518 const PropertyInfo qdev_prop_string = { 519 .type = "str", 520 .release = release_string, 521 .get = get_string, 522 .set = set_string, 523 }; 524 525 /* --- on/off/auto --- */ 526 527 const PropertyInfo qdev_prop_on_off_auto = { 528 .type = "OnOffAuto", 529 .description = "on/off/auto", 530 .enum_table = &OnOffAuto_lookup, 531 .get = qdev_propinfo_get_enum, 532 .set = qdev_propinfo_set_enum, 533 .set_default_value = qdev_propinfo_set_default_value_enum, 534 }; 535 536 /* --- 32bit unsigned int 'size' type --- */ 537 538 void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name, 539 void *opaque, Error **errp) 540 { 541 const Property *prop = opaque; 542 uint32_t *ptr = object_field_prop_ptr(obj, prop); 543 uint64_t value = *ptr; 544 545 visit_type_size(v, name, &value, errp); 546 } 547 548 static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque, 549 Error **errp) 550 { 551 const Property *prop = opaque; 552 uint32_t *ptr = object_field_prop_ptr(obj, prop); 553 uint64_t value; 554 555 if (!visit_type_size(v, name, &value, errp)) { 556 return; 557 } 558 559 if (value > UINT32_MAX) { 560 error_setg(errp, 561 "Property %s.%s doesn't take value %" PRIu64 562 " (maximum: %u)", 563 object_get_typename(obj), name, value, UINT32_MAX); 564 return; 565 } 566 567 *ptr = value; 568 } 569 570 const PropertyInfo qdev_prop_size32 = { 571 .type = "size", 572 .get = qdev_propinfo_get_size32, 573 .set = set_size32, 574 .set_default_value = qdev_propinfo_set_default_value_uint, 575 }; 576 577 /* --- support for array properties --- */ 578 579 typedef struct ArrayElementList ArrayElementList; 580 581 struct ArrayElementList { 582 ArrayElementList *next; 583 void *value; 584 }; 585 586 /* 587 * Given an array property @parent_prop in @obj, return a Property for a 588 * specific element of the array. Arrays are backed by an uint32_t length field 589 * and an element array. @elem points at an element in this element array. 590 */ 591 static Property array_elem_prop(Object *obj, const Property *parent_prop, 592 const char *name, char *elem) 593 { 594 return (Property) { 595 .info = parent_prop->arrayinfo, 596 .name = name, 597 /* 598 * This ugly piece of pointer arithmetic sets up the offset so 599 * that when the underlying release hook calls qdev_get_prop_ptr 600 * they get the right answer despite the array element not actually 601 * being inside the device struct. 602 */ 603 .offset = (uintptr_t)elem - (uintptr_t)obj, 604 }; 605 } 606 607 /* 608 * Object property release callback for array properties: We call the 609 * underlying element's property release hook for each element. 610 * 611 * Note that it is the responsibility of the individual device's deinit 612 * to free the array proper. 613 */ 614 static void release_prop_array(Object *obj, const char *name, void *opaque) 615 { 616 const Property *prop = opaque; 617 uint32_t *alenptr = object_field_prop_ptr(obj, prop); 618 void **arrayptr = (void *)obj + prop->arrayoffset; 619 char *elem = *arrayptr; 620 int i; 621 622 if (!prop->arrayinfo->release) { 623 return; 624 } 625 626 for (i = 0; i < *alenptr; i++) { 627 Property elem_prop = array_elem_prop(obj, prop, name, elem); 628 prop->arrayinfo->release(obj, NULL, &elem_prop); 629 elem += prop->arrayfieldsize; 630 } 631 } 632 633 /* 634 * Setter for an array property. This sets both the array length (which 635 * is technically the property field in the object) and the array itself 636 * (a pointer to which is stored in the additional field described by 637 * prop->arrayoffset). 638 */ 639 static void set_prop_array(Object *obj, Visitor *v, const char *name, 640 void *opaque, Error **errp) 641 { 642 ERRP_GUARD(); 643 const Property *prop = opaque; 644 uint32_t *alenptr = object_field_prop_ptr(obj, prop); 645 void **arrayptr = (void *)obj + prop->arrayoffset; 646 ArrayElementList *list, *elem, *next; 647 const size_t size = sizeof(*list); 648 char *elemptr; 649 bool ok = true; 650 651 if (*alenptr) { 652 error_setg(errp, "array size property %s may not be set more than once", 653 name); 654 return; 655 } 656 657 if (!visit_start_list(v, name, (GenericList **) &list, size, errp)) { 658 return; 659 } 660 661 /* Read the whole input into a temporary list */ 662 elem = list; 663 while (elem) { 664 Property elem_prop; 665 666 elem->value = g_malloc0(prop->arrayfieldsize); 667 elem_prop = array_elem_prop(obj, prop, name, elem->value); 668 prop->arrayinfo->set(obj, v, NULL, &elem_prop, errp); 669 if (*errp) { 670 ok = false; 671 goto out_obj; 672 } 673 if (*alenptr == INT_MAX) { 674 error_setg(errp, "array is too big"); 675 return; 676 } 677 (*alenptr)++; 678 elem = (ArrayElementList *) visit_next_list(v, (GenericList*) elem, 679 size); 680 } 681 682 ok = visit_check_list(v, errp); 683 out_obj: 684 visit_end_list(v, (void**) &list); 685 686 if (!ok) { 687 for (elem = list; elem; elem = next) { 688 Property elem_prop = array_elem_prop(obj, prop, name, 689 elem->value); 690 if (prop->arrayinfo->release) { 691 prop->arrayinfo->release(obj, NULL, &elem_prop); 692 } 693 next = elem->next; 694 g_free(elem->value); 695 g_free(elem); 696 } 697 return; 698 } 699 700 /* 701 * Now that we know how big the array has to be, move the data over to a 702 * linear array and free the temporary list. 703 */ 704 *arrayptr = g_malloc_n(*alenptr, prop->arrayfieldsize); 705 elemptr = *arrayptr; 706 for (elem = list; elem; elem = next) { 707 memcpy(elemptr, elem->value, prop->arrayfieldsize); 708 elemptr += prop->arrayfieldsize; 709 next = elem->next; 710 g_free(elem->value); 711 g_free(elem); 712 } 713 } 714 715 static void get_prop_array(Object *obj, Visitor *v, const char *name, 716 void *opaque, Error **errp) 717 { 718 ERRP_GUARD(); 719 const Property *prop = opaque; 720 uint32_t *alenptr = object_field_prop_ptr(obj, prop); 721 void **arrayptr = (void *)obj + prop->arrayoffset; 722 char *elemptr = *arrayptr; 723 ArrayElementList *list = NULL, *elem; 724 ArrayElementList **tail = &list; 725 const size_t size = sizeof(*list); 726 int i; 727 bool ok; 728 729 /* At least the string output visitor needs a real list */ 730 for (i = 0; i < *alenptr; i++) { 731 elem = g_new0(ArrayElementList, 1); 732 elem->value = elemptr; 733 elemptr += prop->arrayfieldsize; 734 735 *tail = elem; 736 tail = &elem->next; 737 } 738 739 if (!visit_start_list(v, name, (GenericList **) &list, size, errp)) { 740 return; 741 } 742 743 elem = list; 744 while (elem) { 745 Property elem_prop = array_elem_prop(obj, prop, name, elem->value); 746 prop->arrayinfo->get(obj, v, NULL, &elem_prop, errp); 747 if (*errp) { 748 goto out_obj; 749 } 750 elem = (ArrayElementList *) visit_next_list(v, (GenericList*) elem, 751 size); 752 } 753 754 /* visit_check_list() can only fail for input visitors */ 755 ok = visit_check_list(v, errp); 756 assert(ok); 757 758 out_obj: 759 visit_end_list(v, (void**) &list); 760 761 while (list) { 762 elem = list; 763 list = elem->next; 764 g_free(elem); 765 } 766 } 767 768 static void default_prop_array(ObjectProperty *op, const Property *prop) 769 { 770 object_property_set_default_list(op); 771 } 772 773 const PropertyInfo qdev_prop_array = { 774 .type = "list", 775 .get = get_prop_array, 776 .set = set_prop_array, 777 .release = release_prop_array, 778 .set_default_value = default_prop_array, 779 }; 780 781 /* --- public helpers --- */ 782 783 static const Property *qdev_prop_walk(DeviceClass *cls, const char *name) 784 { 785 for (int i = 0, n = cls->props_count_; i < n; ++i) { 786 const Property *prop = &cls->props_[i]; 787 if (strcmp(prop->name, name) == 0) { 788 return prop; 789 } 790 } 791 return NULL; 792 } 793 794 static const Property *qdev_prop_find(DeviceState *dev, const char *name) 795 { 796 ObjectClass *class; 797 const Property *prop; 798 799 /* device properties */ 800 class = object_get_class(OBJECT(dev)); 801 do { 802 prop = qdev_prop_walk(DEVICE_CLASS(class), name); 803 if (prop) { 804 return prop; 805 } 806 class = object_class_get_parent(class); 807 } while (class != object_class_by_name(TYPE_DEVICE)); 808 809 return NULL; 810 } 811 812 void error_set_from_qdev_prop_error(Error **errp, int ret, Object *obj, 813 const char *name, const char *value) 814 { 815 switch (ret) { 816 case -EEXIST: 817 error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use", 818 object_get_typename(obj), name, value); 819 break; 820 default: 821 case -EINVAL: 822 error_setg(errp, "Property '%s.%s' doesn't take value '%s'", 823 object_get_typename(obj), name, value); 824 break; 825 case -ENOENT: 826 error_setg(errp, "Property '%s.%s' can't find value '%s'", 827 object_get_typename(obj), name, value); 828 break; 829 case 0: 830 break; 831 } 832 } 833 834 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value) 835 { 836 object_property_set_bool(OBJECT(dev), name, value, &error_abort); 837 } 838 839 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value) 840 { 841 object_property_set_int(OBJECT(dev), name, value, &error_abort); 842 } 843 844 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value) 845 { 846 object_property_set_int(OBJECT(dev), name, value, &error_abort); 847 } 848 849 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value) 850 { 851 object_property_set_int(OBJECT(dev), name, value, &error_abort); 852 } 853 854 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value) 855 { 856 object_property_set_int(OBJECT(dev), name, value, &error_abort); 857 } 858 859 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value) 860 { 861 object_property_set_int(OBJECT(dev), name, value, &error_abort); 862 } 863 864 void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value) 865 { 866 object_property_set_str(OBJECT(dev), name, value, &error_abort); 867 } 868 869 void qdev_prop_set_enum(DeviceState *dev, const char *name, int value) 870 { 871 const Property *prop; 872 873 prop = qdev_prop_find(dev, name); 874 object_property_set_str(OBJECT(dev), name, 875 qapi_enum_lookup(prop->info->enum_table, value), 876 &error_abort); 877 } 878 879 void qdev_prop_set_array(DeviceState *dev, const char *name, QList *values) 880 { 881 object_property_set_qobject(OBJECT(dev), name, QOBJECT(values), 882 &error_abort); 883 qobject_unref(values); 884 } 885 886 static GPtrArray *global_props(void) 887 { 888 static GPtrArray *gp; 889 890 if (!gp) { 891 gp = g_ptr_array_new(); 892 } 893 894 return gp; 895 } 896 897 void qdev_prop_register_global(GlobalProperty *prop) 898 { 899 g_ptr_array_add(global_props(), prop); 900 } 901 902 const GlobalProperty *qdev_find_global_prop(Object *obj, 903 const char *name) 904 { 905 GPtrArray *props = global_props(); 906 const GlobalProperty *p; 907 int i; 908 909 for (i = 0; i < props->len; i++) { 910 p = g_ptr_array_index(props, i); 911 if (object_dynamic_cast(obj, p->driver) 912 && !strcmp(p->property, name)) { 913 return p; 914 } 915 } 916 return NULL; 917 } 918 919 int qdev_prop_check_globals(void) 920 { 921 int i, ret = 0; 922 923 for (i = 0; i < global_props()->len; i++) { 924 GlobalProperty *prop; 925 ObjectClass *oc; 926 DeviceClass *dc; 927 928 prop = g_ptr_array_index(global_props(), i); 929 if (prop->used) { 930 continue; 931 } 932 oc = object_class_by_name(prop->driver); 933 oc = object_class_dynamic_cast(oc, TYPE_DEVICE); 934 if (!oc) { 935 warn_report("global %s.%s has invalid class name", 936 prop->driver, prop->property); 937 ret = 1; 938 continue; 939 } 940 dc = DEVICE_CLASS(oc); 941 if (!dc->hotpluggable && !prop->used) { 942 warn_report("global %s.%s=%s not used", 943 prop->driver, prop->property, prop->value); 944 ret = 1; 945 continue; 946 } 947 } 948 return ret; 949 } 950 951 void qdev_prop_set_globals(DeviceState *dev) 952 { 953 object_apply_global_props(OBJECT(dev), global_props(), 954 dev->hotplugged ? NULL : &error_fatal); 955 } 956 957 /* --- 64bit unsigned int 'size' type --- */ 958 959 static void get_size(Object *obj, Visitor *v, const char *name, void *opaque, 960 Error **errp) 961 { 962 const Property *prop = opaque; 963 uint64_t *ptr = object_field_prop_ptr(obj, prop); 964 965 visit_type_size(v, name, ptr, errp); 966 } 967 968 static void set_size(Object *obj, Visitor *v, const char *name, void *opaque, 969 Error **errp) 970 { 971 const Property *prop = opaque; 972 uint64_t *ptr = object_field_prop_ptr(obj, prop); 973 974 visit_type_size(v, name, ptr, errp); 975 } 976 977 const PropertyInfo qdev_prop_size = { 978 .type = "size", 979 .get = get_size, 980 .set = set_size, 981 .set_default_value = qdev_propinfo_set_default_value_uint, 982 }; 983 984 /* --- object link property --- */ 985 986 static ObjectProperty *create_link_property(ObjectClass *oc, const char *name, 987 const Property *prop) 988 { 989 return object_class_property_add_link(oc, name, prop->link_type, 990 prop->offset, 991 qdev_prop_allow_set_link_before_realize, 992 OBJ_PROP_LINK_STRONG); 993 } 994 995 const PropertyInfo qdev_prop_link = { 996 .type = "link", 997 .create = create_link_property, 998 }; 999 1000 void qdev_property_add_static(DeviceState *dev, const Property *prop) 1001 { 1002 Object *obj = OBJECT(dev); 1003 ObjectProperty *op; 1004 1005 assert(!prop->info->create); 1006 1007 op = object_property_add(obj, prop->name, prop->info->type, 1008 field_prop_getter(prop->info), 1009 field_prop_setter(prop->info), 1010 prop->info->release, 1011 (Property *)prop); 1012 1013 object_property_set_description(obj, prop->name, 1014 prop->info->description); 1015 1016 if (prop->set_default) { 1017 prop->info->set_default_value(op, prop); 1018 if (op->init) { 1019 op->init(obj, op); 1020 } 1021 } 1022 } 1023 1024 static void qdev_class_add_property(DeviceClass *klass, const char *name, 1025 const Property *prop) 1026 { 1027 ObjectClass *oc = OBJECT_CLASS(klass); 1028 ObjectProperty *op; 1029 1030 if (prop->info->create) { 1031 op = prop->info->create(oc, name, prop); 1032 } else { 1033 op = object_class_property_add(oc, 1034 name, prop->info->type, 1035 field_prop_getter(prop->info), 1036 field_prop_setter(prop->info), 1037 prop->info->release, 1038 (Property *)prop); 1039 } 1040 if (prop->set_default) { 1041 prop->info->set_default_value(op, prop); 1042 } 1043 object_class_property_set_description(oc, name, prop->info->description); 1044 } 1045 1046 /** 1047 * Legacy property handling 1048 */ 1049 1050 static void qdev_get_legacy_property(Object *obj, Visitor *v, 1051 const char *name, void *opaque, 1052 Error **errp) 1053 { 1054 const Property *prop = opaque; 1055 1056 char buffer[1024]; 1057 char *ptr = buffer; 1058 1059 prop->info->print(obj, prop, buffer, sizeof(buffer)); 1060 visit_type_str(v, name, &ptr, errp); 1061 } 1062 1063 /** 1064 * qdev_class_add_legacy_property: 1065 * @dev: Device to add the property to. 1066 * @prop: The qdev property definition. 1067 * 1068 * Add a legacy QOM property to @dev for qdev property @prop. 1069 * 1070 * Legacy properties are string versions of QOM properties. The format of 1071 * the string depends on the property type. Legacy properties are only 1072 * needed for "info qtree". 1073 * 1074 * Do not use this in new code! QOM Properties added through this interface 1075 * will be given names in the "legacy" namespace. 1076 */ 1077 static void qdev_class_add_legacy_property(DeviceClass *dc, const Property *prop) 1078 { 1079 g_autofree char *name = NULL; 1080 1081 /* Register pointer properties as legacy properties */ 1082 if (!prop->info->print && prop->info->get) { 1083 return; 1084 } 1085 1086 name = g_strdup_printf("legacy-%s", prop->name); 1087 object_class_property_add(OBJECT_CLASS(dc), name, "str", 1088 prop->info->print ? qdev_get_legacy_property : prop->info->get, 1089 NULL, NULL, (Property *)prop); 1090 } 1091 1092 void device_class_set_props_n(DeviceClass *dc, const Property *props, size_t n) 1093 { 1094 /* We used a hole in DeviceClass because that's still a lot. */ 1095 assert(n <= UINT16_MAX); 1096 assert(n != 0); 1097 1098 dc->props_ = props; 1099 dc->props_count_ = n; 1100 1101 for (size_t i = 0; i < n; ++i) { 1102 const Property *prop = &props[i]; 1103 assert(prop->name); 1104 qdev_class_add_legacy_property(dc, prop); 1105 qdev_class_add_property(dc, prop->name, prop); 1106 } 1107 } 1108 1109 void qdev_alias_all_properties(DeviceState *target, Object *source) 1110 { 1111 ObjectClass *class; 1112 ObjectPropertyIterator iter; 1113 ObjectProperty *prop; 1114 1115 class = object_get_class(OBJECT(target)); 1116 1117 object_class_property_iter_init(&iter, class); 1118 while ((prop = object_property_iter_next(&iter))) { 1119 if (object_property_find(source, prop->name)) { 1120 continue; /* skip duplicate properties */ 1121 } 1122 1123 object_property_add_alias(source, prop->name, 1124 OBJECT(target), prop->name); 1125 } 1126 } 1127