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