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