xref: /qemu/qom/qom-qmp-cmds.c (revision f9bb7e53a341d08fd4ec8d7e810ebfd4f6f936bd)
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