xref: /openbmc/qemu/qom/qom-qmp-cmds.c (revision 988717b46b6424907618cb845ace9d69062703af)
1  /*
2   * QMP commands related to QOM
3   *
4   * Copyright IBM, Corp. 2011
5   *
6   * Authors:
7   *  Anthony Liguori   <aliguori@us.ibm.com>
8   *
9   * This work is licensed under the terms of the GNU GPL, version 2.  See
10   * the COPYING file in the top-level directory.
11   *
12   * Contributions after 2012-01-13 are licensed under the terms of the
13   * GNU GPL, version 2 or (at your option) any later version.
14   */
15  
16  #include "qemu/osdep.h"
17  #include "hw/qdev-core.h"
18  #include "qapi/error.h"
19  #include "qapi/qapi-commands-qdev.h"
20  #include "qapi/qapi-commands-qom.h"
21  #include "qapi/qmp/qdict.h"
22  #include "qapi/qmp/qerror.h"
23  #include "qapi/qobject-input-visitor.h"
24  #include "qemu/cutils.h"
25  #include "qom/object_interfaces.h"
26  #include "qom/qom-qobject.h"
27  
28  ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
29  {
30      Object *obj;
31      bool ambiguous = false;
32      ObjectPropertyInfoList *props = NULL;
33      ObjectProperty *prop;
34      ObjectPropertyIterator iter;
35  
36      obj = object_resolve_path(path, &ambiguous);
37      if (obj == NULL) {
38          if (ambiguous) {
39              error_setg(errp, "Path '%s' is ambiguous", path);
40          } else {
41              error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
42                        "Device '%s' not found", path);
43          }
44          return NULL;
45      }
46  
47      object_property_iter_init(&iter, obj);
48      while ((prop = object_property_iter_next(&iter))) {
49          ObjectPropertyInfoList *entry = g_malloc0(sizeof(*entry));
50  
51          entry->value = g_malloc0(sizeof(ObjectPropertyInfo));
52          entry->next = props;
53          props = entry;
54  
55          entry->value->name = g_strdup(prop->name);
56          entry->value->type = g_strdup(prop->type);
57      }
58  
59      return props;
60  }
61  
62  void qmp_qom_set(const char *path, const char *property, QObject *value,
63                   Error **errp)
64  {
65      Object *obj;
66  
67      obj = object_resolve_path(path, NULL);
68      if (!obj) {
69          error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
70                    "Device '%s' not found", path);
71          return;
72      }
73  
74      object_property_set_qobject(obj, value, property, errp);
75  }
76  
77  QObject *qmp_qom_get(const char *path, const char *property, Error **errp)
78  {
79      Object *obj;
80  
81      obj = object_resolve_path(path, NULL);
82      if (!obj) {
83          error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
84                    "Device '%s' not found", path);
85          return NULL;
86      }
87  
88      return object_property_get_qobject(obj, property, errp);
89  }
90  
91  static void qom_list_types_tramp(ObjectClass *klass, void *data)
92  {
93      ObjectTypeInfoList *e, **pret = data;
94      ObjectTypeInfo *info;
95      ObjectClass *parent = object_class_get_parent(klass);
96  
97      info = g_malloc0(sizeof(*info));
98      info->name = g_strdup(object_class_get_name(klass));
99      info->has_abstract = info->abstract = object_class_is_abstract(klass);
100      if (parent) {
101          info->has_parent = true;
102          info->parent = g_strdup(object_class_get_name(parent));
103      }
104  
105      e = g_malloc0(sizeof(*e));
106      e->value = info;
107      e->next = *pret;
108      *pret = e;
109  }
110  
111  ObjectTypeInfoList *qmp_qom_list_types(bool has_implements,
112                                         const char *implements,
113                                         bool has_abstract,
114                                         bool abstract,
115                                         Error **errp)
116  {
117      ObjectTypeInfoList *ret = NULL;
118  
119      object_class_foreach(qom_list_types_tramp, implements, abstract, &ret);
120  
121      return ret;
122  }
123  
124  ObjectPropertyInfoList *qmp_device_list_properties(const char *typename,
125                                                  Error **errp)
126  {
127      ObjectClass *klass;
128      Object *obj;
129      ObjectProperty *prop;
130      ObjectPropertyIterator iter;
131      ObjectPropertyInfoList *prop_list = NULL;
132  
133      klass = object_class_by_name(typename);
134      if (klass == NULL) {
135          error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
136                    "Device '%s' not found", typename);
137          return NULL;
138      }
139  
140      klass = object_class_dynamic_cast(klass, TYPE_DEVICE);
141      if (klass == NULL) {
142          error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", TYPE_DEVICE);
143          return NULL;
144      }
145  
146      if (object_class_is_abstract(klass)) {
147          error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename",
148                     "non-abstract device type");
149          return NULL;
150      }
151  
152      obj = object_new(typename);
153  
154      object_property_iter_init(&iter, obj);
155      while ((prop = object_property_iter_next(&iter))) {
156          ObjectPropertyInfo *info;
157          ObjectPropertyInfoList *entry;
158  
159          /* Skip Object and DeviceState properties */
160          if (strcmp(prop->name, "type") == 0 ||
161              strcmp(prop->name, "realized") == 0 ||
162              strcmp(prop->name, "hotpluggable") == 0 ||
163              strcmp(prop->name, "hotplugged") == 0 ||
164              strcmp(prop->name, "parent_bus") == 0) {
165              continue;
166          }
167  
168          /* Skip legacy properties since they are just string versions of
169           * properties that we already list.
170           */
171          if (strstart(prop->name, "legacy-", NULL)) {
172              continue;
173          }
174  
175          info = g_new0(ObjectPropertyInfo, 1);
176          info->name = g_strdup(prop->name);
177          info->type = g_strdup(prop->type);
178          info->has_description = !!prop->description;
179          info->description = g_strdup(prop->description);
180          info->default_value = qobject_ref(prop->defval);
181          info->has_default_value = !!info->default_value;
182  
183          entry = g_malloc0(sizeof(*entry));
184          entry->value = info;
185          entry->next = prop_list;
186          prop_list = entry;
187      }
188  
189      object_unref(obj);
190  
191      return prop_list;
192  }
193  
194  ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename,
195                                               Error **errp)
196  {
197      ObjectClass *klass;
198      Object *obj = NULL;
199      ObjectProperty *prop;
200      ObjectPropertyIterator iter;
201      ObjectPropertyInfoList *prop_list = NULL;
202  
203      klass = object_class_by_name(typename);
204      if (klass == NULL) {
205          error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
206                    "Class '%s' not found", typename);
207          return NULL;
208      }
209  
210      klass = object_class_dynamic_cast(klass, TYPE_OBJECT);
211      if (klass == NULL) {
212          error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", TYPE_OBJECT);
213          return NULL;
214      }
215  
216      if (object_class_is_abstract(klass)) {
217          object_class_property_iter_init(&iter, klass);
218      } else {
219          obj = object_new(typename);
220          object_property_iter_init(&iter, obj);
221      }
222      while ((prop = object_property_iter_next(&iter))) {
223          ObjectPropertyInfo *info;
224          ObjectPropertyInfoList *entry;
225  
226          info = g_malloc0(sizeof(*info));
227          info->name = g_strdup(prop->name);
228          info->type = g_strdup(prop->type);
229          info->has_description = !!prop->description;
230          info->description = g_strdup(prop->description);
231  
232          entry = g_malloc0(sizeof(*entry));
233          entry->value = info;
234          entry->next = prop_list;
235          prop_list = entry;
236      }
237  
238      object_unref(obj);
239  
240      return prop_list;
241  }
242  
243  void qmp_object_add(const char *type, const char *id,
244                      bool has_props, QObject *props, Error **errp)
245  {
246      QDict *pdict;
247      Visitor *v;
248      Object *obj;
249  
250      if (props) {
251          pdict = qobject_to(QDict, props);
252          if (!pdict) {
253              error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
254              return;
255          }
256          qobject_ref(pdict);
257      } else {
258          pdict = qdict_new();
259      }
260  
261      v = qobject_input_visitor_new(QOBJECT(pdict));
262      obj = user_creatable_add_type(type, id, pdict, v, errp);
263      visit_free(v);
264      if (obj) {
265          object_unref(obj);
266      }
267      qobject_unref(pdict);
268  }
269  
270  void qmp_object_del(const char *id, Error **errp)
271  {
272      user_creatable_del(id, errp);
273  }
274