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
qmp_qom_set(const char * path,const char * property,QObject * value,Error ** errp)72 void qmp_qom_set(const char *path, const char *property, QObject *value,
73 Error **errp)
74 {
75 Object *obj;
76
77 obj = object_resolve_path(path, NULL);
78 if (!obj) {
79 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
80 "Device '%s' not found", path);
81 return;
82 }
83
84 object_property_set_qobject(obj, property, value, errp);
85 }
86
qmp_qom_get(const char * path,const char * property,Error ** errp)87 QObject *qmp_qom_get(const char *path, const char *property, Error **errp)
88 {
89 Object *obj;
90
91 obj = object_resolve_path(path, NULL);
92 if (!obj) {
93 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
94 "Device '%s' not found", path);
95 return NULL;
96 }
97
98 return object_property_get_qobject(obj, property, errp);
99 }
100
qom_list_types_tramp(ObjectClass * klass,void * data)101 static void qom_list_types_tramp(ObjectClass *klass, void *data)
102 {
103 ObjectTypeInfoList **pret = data;
104 ObjectTypeInfo *info;
105 ObjectClass *parent = object_class_get_parent(klass);
106
107 info = g_malloc0(sizeof(*info));
108 info->name = g_strdup(object_class_get_name(klass));
109 info->has_abstract = info->abstract = object_class_is_abstract(klass);
110 if (parent) {
111 info->parent = g_strdup(object_class_get_name(parent));
112 }
113
114 QAPI_LIST_PREPEND(*pret, info);
115 }
116
qmp_qom_list_types(const char * implements,bool has_abstract,bool abstract,Error ** errp)117 ObjectTypeInfoList *qmp_qom_list_types(const char *implements,
118 bool has_abstract,
119 bool abstract,
120 Error **errp)
121 {
122 ObjectTypeInfoList *ret = NULL;
123
124 module_load_qom_all();
125 object_class_foreach(qom_list_types_tramp, implements, abstract, &ret);
126
127 return ret;
128 }
129
qmp_device_list_properties(const char * typename,Error ** errp)130 ObjectPropertyInfoList *qmp_device_list_properties(const char *typename,
131 Error **errp)
132 {
133 ObjectClass *klass;
134 Object *obj;
135 ObjectProperty *prop;
136 ObjectPropertyIterator iter;
137 ObjectPropertyInfoList *prop_list = NULL;
138
139 klass = module_object_class_by_name(typename);
140 if (klass == NULL) {
141 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
142 "Device '%s' not found", typename);
143 return NULL;
144 }
145
146 if (!object_class_dynamic_cast(klass, TYPE_DEVICE)
147 || object_class_is_abstract(klass)) {
148 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename",
149 "a non-abstract device type");
150 return NULL;
151 }
152
153 obj = object_new_with_class(klass);
154
155 object_property_iter_init(&iter, obj);
156 while ((prop = object_property_iter_next(&iter))) {
157 ObjectPropertyInfo *info;
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->description = g_strdup(prop->description);
179 info->default_value = qobject_ref(prop->defval);
180
181 QAPI_LIST_PREPEND(prop_list, info);
182 }
183
184 object_unref(obj);
185
186 return prop_list;
187 }
188
qmp_qom_list_properties(const char * typename,Error ** errp)189 ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename,
190 Error **errp)
191 {
192 ObjectClass *klass;
193 Object *obj = NULL;
194 ObjectProperty *prop;
195 ObjectPropertyIterator iter;
196 ObjectPropertyInfoList *prop_list = NULL;
197
198 klass = module_object_class_by_name(typename);
199 if (klass == NULL) {
200 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
201 "Class '%s' not found", typename);
202 return NULL;
203 }
204
205 if (!object_class_dynamic_cast(klass, TYPE_OBJECT)) {
206 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename",
207 "a QOM type");
208 return NULL;
209 }
210
211 if (object_class_is_abstract(klass)) {
212 object_class_property_iter_init(&iter, klass);
213 } else {
214 obj = object_new(typename);
215 object_property_iter_init(&iter, obj);
216 }
217 while ((prop = object_property_iter_next(&iter))) {
218 ObjectPropertyInfo *info;
219
220 info = g_malloc0(sizeof(*info));
221 info->name = g_strdup(prop->name);
222 info->type = g_strdup(prop->type);
223 info->description = g_strdup(prop->description);
224 info->default_value = qobject_ref(prop->defval);
225
226 QAPI_LIST_PREPEND(prop_list, info);
227 }
228
229 object_unref(obj);
230
231 return prop_list;
232 }
233
qmp_object_add(ObjectOptions * options,Error ** errp)234 void qmp_object_add(ObjectOptions *options, Error **errp)
235 {
236 user_creatable_add_qapi(options, errp);
237 }
238
qmp_object_del(const char * id,Error ** errp)239 void qmp_object_del(const char *id, Error **errp)
240 {
241 user_creatable_del(id, errp);
242 }
243