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