xref: /openbmc/qemu/qom/qom-qmp-cmds.c (revision 3656e761bcdd207b7759cdcd608212d2a6f9c12d)
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 "block/qdict.h"
18 #include "hw/qdev-core.h"
19 #include "qapi/error.h"
20 #include "qapi/qapi-commands-qdev.h"
21 #include "qapi/qapi-commands-qom.h"
22 #include "qapi/qapi-visit-qom.h"
23 #include "qobject/qdict.h"
24 #include "qapi/qmp/qerror.h"
25 #include "qapi/qobject-input-visitor.h"
26 #include "qapi/qobject-output-visitor.h"
27 #include "qemu/cutils.h"
28 #include "qom/object_interfaces.h"
29 #include "qom/qom-qobject.h"
30 
qom_resolve_path(const char * path,Error ** errp)31 static Object *qom_resolve_path(const char *path, Error **errp)
32 {
33     bool ambiguous = false;
34     Object *obj = object_resolve_path(path, &ambiguous);
35 
36     if (obj == NULL) {
37         if (ambiguous) {
38             error_setg(errp, "Path '%s' is ambiguous", path);
39         } else {
40             error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
41                       "Device '%s' not found", path);
42         }
43     }
44     return obj;
45 }
46 
qmp_qom_list(const char * path,Error ** errp)47 ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
48 {
49     Object *obj;
50     ObjectPropertyInfoList *props = NULL;
51     ObjectProperty *prop;
52     ObjectPropertyIterator iter;
53 
54     obj = qom_resolve_path(path, errp);
55     if (obj == NULL) {
56         return NULL;
57     }
58 
59     object_property_iter_init(&iter, obj);
60     while ((prop = object_property_iter_next(&iter))) {
61         ObjectPropertyInfo *value = g_new0(ObjectPropertyInfo, 1);
62 
63         QAPI_LIST_PREPEND(props, value);
64 
65         value->name = g_strdup(prop->name);
66         value->type = g_strdup(prop->type);
67     }
68 
69     return props;
70 }
71 
qom_list_add_property_value(Object * obj,ObjectProperty * prop,ObjectPropertyValueList ** props)72 static void qom_list_add_property_value(Object *obj, ObjectProperty *prop,
73                                         ObjectPropertyValueList **props)
74 {
75     ObjectPropertyValue *item = g_new0(ObjectPropertyValue, 1);
76 
77     QAPI_LIST_PREPEND(*props, item);
78 
79     item->name = g_strdup(prop->name);
80     item->type = g_strdup(prop->type);
81     item->value = object_property_get_qobject(obj, prop->name, NULL);
82 }
83 
qom_get_property_value_list(const char * path,Error ** errp)84 static ObjectPropertyValueList *qom_get_property_value_list(const char *path,
85                                                             Error **errp)
86 {
87     Object *obj;
88     ObjectProperty *prop;
89     ObjectPropertyIterator iter;
90     ObjectPropertyValueList *props = NULL;
91 
92     obj = qom_resolve_path(path, errp);
93     if (obj == NULL) {
94         return NULL;
95     }
96 
97     object_property_iter_init(&iter, obj);
98     while ((prop = object_property_iter_next(&iter))) {
99         qom_list_add_property_value(obj, prop, &props);
100     }
101 
102     return props;
103 }
104 
qmp_qom_list_get(strList * paths,Error ** errp)105 ObjectPropertiesValuesList *qmp_qom_list_get(strList *paths, Error **errp)
106 {
107     ObjectPropertiesValuesList *head = NULL, **tail = &head;
108     strList *path;
109 
110     for (path = paths; path; path = path->next) {
111         ObjectPropertiesValues *item = g_new0(ObjectPropertiesValues, 1);
112 
113         QAPI_LIST_APPEND(tail, item);
114 
115         item->properties = qom_get_property_value_list(path->value, errp);
116         if (!item->properties) {
117             qapi_free_ObjectPropertiesValuesList(head);
118             return NULL;
119         }
120     }
121 
122     return head;
123 }
124 
qmp_qom_set(const char * path,const char * property,QObject * value,Error ** errp)125 void qmp_qom_set(const char *path, const char *property, QObject *value,
126                  Error **errp)
127 {
128     Object *obj;
129 
130     obj = object_resolve_path(path, NULL);
131     if (!obj) {
132         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
133                   "Device '%s' not found", path);
134         return;
135     }
136 
137     object_property_set_qobject(obj, property, value, errp);
138 }
139 
qmp_qom_get(const char * path,const char * property,Error ** errp)140 QObject *qmp_qom_get(const char *path, const char *property, Error **errp)
141 {
142     Object *obj;
143 
144     obj = object_resolve_path(path, NULL);
145     if (!obj) {
146         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
147                   "Device '%s' not found", path);
148         return NULL;
149     }
150 
151     return object_property_get_qobject(obj, property, errp);
152 }
153 
qom_list_types_tramp(ObjectClass * klass,void * data)154 static void qom_list_types_tramp(ObjectClass *klass, void *data)
155 {
156     ObjectTypeInfoList **pret = data;
157     ObjectTypeInfo *info;
158     ObjectClass *parent = object_class_get_parent(klass);
159 
160     info = g_malloc0(sizeof(*info));
161     info->name = g_strdup(object_class_get_name(klass));
162     info->has_abstract = info->abstract = object_class_is_abstract(klass);
163     if (parent) {
164         info->parent = g_strdup(object_class_get_name(parent));
165     }
166 
167     QAPI_LIST_PREPEND(*pret, info);
168 }
169 
qmp_qom_list_types(const char * implements,bool has_abstract,bool abstract,Error ** errp)170 ObjectTypeInfoList *qmp_qom_list_types(const char *implements,
171                                        bool has_abstract,
172                                        bool abstract,
173                                        Error **errp)
174 {
175     ObjectTypeInfoList *ret = NULL;
176 
177     module_load_qom_all();
178     object_class_foreach(qom_list_types_tramp, implements, abstract, &ret);
179 
180     return ret;
181 }
182 
qmp_device_list_properties(const char * typename,Error ** errp)183 ObjectPropertyInfoList *qmp_device_list_properties(const char *typename,
184                                                 Error **errp)
185 {
186     ObjectClass *klass;
187     Object *obj;
188     ObjectProperty *prop;
189     ObjectPropertyIterator iter;
190     ObjectPropertyInfoList *prop_list = NULL;
191 
192     klass = module_object_class_by_name(typename);
193     if (klass == NULL) {
194         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
195                   "Device '%s' not found", typename);
196         return NULL;
197     }
198 
199     if (!object_class_dynamic_cast(klass, TYPE_DEVICE)
200         || object_class_is_abstract(klass)) {
201         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename",
202                    "a non-abstract device type");
203         return NULL;
204     }
205 
206     obj = object_new_with_class(klass);
207 
208     object_property_iter_init(&iter, obj);
209     while ((prop = object_property_iter_next(&iter))) {
210         ObjectPropertyInfo *info;
211 
212         /* Skip Object and DeviceState properties */
213         if (strcmp(prop->name, "type") == 0 ||
214             strcmp(prop->name, "realized") == 0 ||
215             strcmp(prop->name, "hotpluggable") == 0 ||
216             strcmp(prop->name, "hotplugged") == 0 ||
217             strcmp(prop->name, "parent_bus") == 0) {
218             continue;
219         }
220 
221         /* Skip legacy properties since they are just string versions of
222          * properties that we already list.
223          */
224         if (strstart(prop->name, "legacy-", NULL)) {
225             continue;
226         }
227 
228         info = g_new0(ObjectPropertyInfo, 1);
229         info->name = g_strdup(prop->name);
230         info->type = g_strdup(prop->type);
231         info->description = g_strdup(prop->description);
232         info->default_value = qobject_ref(prop->defval);
233 
234         QAPI_LIST_PREPEND(prop_list, info);
235     }
236 
237     object_unref(obj);
238 
239     return prop_list;
240 }
241 
qmp_qom_list_properties(const char * typename,Error ** errp)242 ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename,
243                                              Error **errp)
244 {
245     ObjectClass *klass;
246     Object *obj = NULL;
247     ObjectProperty *prop;
248     ObjectPropertyIterator iter;
249     ObjectPropertyInfoList *prop_list = NULL;
250 
251     klass = module_object_class_by_name(typename);
252     if (klass == NULL) {
253         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
254                   "Class '%s' not found", typename);
255         return NULL;
256     }
257 
258     if (!object_class_dynamic_cast(klass, TYPE_OBJECT)) {
259         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename",
260                    "a QOM type");
261         return NULL;
262     }
263 
264     if (object_class_is_abstract(klass)) {
265         object_class_property_iter_init(&iter, klass);
266     } else {
267         obj = object_new(typename);
268         object_property_iter_init(&iter, obj);
269     }
270     while ((prop = object_property_iter_next(&iter))) {
271         ObjectPropertyInfo *info;
272 
273         info = g_malloc0(sizeof(*info));
274         info->name = g_strdup(prop->name);
275         info->type = g_strdup(prop->type);
276         info->description = g_strdup(prop->description);
277         info->default_value = qobject_ref(prop->defval);
278 
279         QAPI_LIST_PREPEND(prop_list, info);
280     }
281 
282     object_unref(obj);
283 
284     return prop_list;
285 }
286 
qmp_object_add(ObjectOptions * options,Error ** errp)287 void qmp_object_add(ObjectOptions *options, Error **errp)
288 {
289     user_creatable_add_qapi(options, errp);
290 }
291 
qmp_object_del(const char * id,Error ** errp)292 void qmp_object_del(const char *id, Error **errp)
293 {
294     user_creatable_del(id, errp);
295 }
296