1cfbe46fcSMarkus Armbruster /*
2cfbe46fcSMarkus Armbruster * QMP commands related to QOM
3cfbe46fcSMarkus Armbruster *
4cfbe46fcSMarkus Armbruster * Copyright IBM, Corp. 2011
5cfbe46fcSMarkus Armbruster *
6cfbe46fcSMarkus Armbruster * Authors:
7cfbe46fcSMarkus Armbruster * Anthony Liguori <aliguori@us.ibm.com>
8cfbe46fcSMarkus Armbruster *
9cfbe46fcSMarkus Armbruster * This work is licensed under the terms of the GNU GPL, version 2. See
10cfbe46fcSMarkus Armbruster * the COPYING file in the top-level directory.
11cfbe46fcSMarkus Armbruster *
12cfbe46fcSMarkus Armbruster * Contributions after 2012-01-13 are licensed under the terms of the
13cfbe46fcSMarkus Armbruster * GNU GPL, version 2 or (at your option) any later version.
14cfbe46fcSMarkus Armbruster */
15cfbe46fcSMarkus Armbruster
16cfbe46fcSMarkus Armbruster #include "qemu/osdep.h"
175f07c4d6SKevin Wolf #include "block/qdict.h"
18a27bd6c7SMarkus Armbruster #include "hw/qdev-core.h"
19cfbe46fcSMarkus Armbruster #include "qapi/error.h"
20cfbe46fcSMarkus Armbruster #include "qapi/qapi-commands-qdev.h"
21cfbe46fcSMarkus Armbruster #include "qapi/qapi-commands-qom.h"
229151e59aSKevin Wolf #include "qapi/qapi-visit-qom.h"
23cfbe46fcSMarkus Armbruster #include "qapi/qmp/qdict.h"
24cfbe46fcSMarkus Armbruster #include "qapi/qmp/qerror.h"
259151e59aSKevin Wolf #include "qapi/qobject-input-visitor.h"
269151e59aSKevin Wolf #include "qapi/qobject-output-visitor.h"
27cfbe46fcSMarkus Armbruster #include "qemu/cutils.h"
28cfbe46fcSMarkus Armbruster #include "qom/object_interfaces.h"
29cfbe46fcSMarkus Armbruster #include "qom/qom-qobject.h"
30cfbe46fcSMarkus Armbruster
qmp_qom_list(const char * path,Error ** errp)31cfbe46fcSMarkus Armbruster ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
32cfbe46fcSMarkus Armbruster {
33cfbe46fcSMarkus Armbruster Object *obj;
34cfbe46fcSMarkus Armbruster bool ambiguous = false;
35cfbe46fcSMarkus Armbruster ObjectPropertyInfoList *props = NULL;
36cfbe46fcSMarkus Armbruster ObjectProperty *prop;
37cfbe46fcSMarkus Armbruster ObjectPropertyIterator iter;
38cfbe46fcSMarkus Armbruster
39cfbe46fcSMarkus Armbruster obj = object_resolve_path(path, &ambiguous);
40cfbe46fcSMarkus Armbruster if (obj == NULL) {
41cfbe46fcSMarkus Armbruster if (ambiguous) {
42cfbe46fcSMarkus Armbruster error_setg(errp, "Path '%s' is ambiguous", path);
43cfbe46fcSMarkus Armbruster } else {
44cfbe46fcSMarkus Armbruster error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
45cfbe46fcSMarkus Armbruster "Device '%s' not found", path);
46cfbe46fcSMarkus Armbruster }
47cfbe46fcSMarkus Armbruster return NULL;
48cfbe46fcSMarkus Armbruster }
49cfbe46fcSMarkus Armbruster
50cfbe46fcSMarkus Armbruster object_property_iter_init(&iter, obj);
51cfbe46fcSMarkus Armbruster while ((prop = object_property_iter_next(&iter))) {
52b21e2380SMarkus Armbruster ObjectPropertyInfo *value = g_new0(ObjectPropertyInfo, 1);
53cfbe46fcSMarkus Armbruster
5454aa3de7SEric Blake QAPI_LIST_PREPEND(props, value);
55cfbe46fcSMarkus Armbruster
5654aa3de7SEric Blake value->name = g_strdup(prop->name);
5754aa3de7SEric Blake value->type = g_strdup(prop->type);
58cfbe46fcSMarkus Armbruster }
59cfbe46fcSMarkus Armbruster
60cfbe46fcSMarkus Armbruster return props;
61cfbe46fcSMarkus Armbruster }
62cfbe46fcSMarkus Armbruster
qmp_qom_set(const char * path,const char * property,QObject * value,Error ** errp)63cfbe46fcSMarkus Armbruster void qmp_qom_set(const char *path, const char *property, QObject *value,
64cfbe46fcSMarkus Armbruster Error **errp)
65cfbe46fcSMarkus Armbruster {
66cfbe46fcSMarkus Armbruster Object *obj;
67cfbe46fcSMarkus Armbruster
68cfbe46fcSMarkus Armbruster obj = object_resolve_path(path, NULL);
69cfbe46fcSMarkus Armbruster if (!obj) {
70cfbe46fcSMarkus Armbruster error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
71cfbe46fcSMarkus Armbruster "Device '%s' not found", path);
72cfbe46fcSMarkus Armbruster return;
73cfbe46fcSMarkus Armbruster }
74cfbe46fcSMarkus Armbruster
755325cc34SMarkus Armbruster object_property_set_qobject(obj, property, value, errp);
76cfbe46fcSMarkus Armbruster }
77cfbe46fcSMarkus Armbruster
qmp_qom_get(const char * path,const char * property,Error ** errp)78cfbe46fcSMarkus Armbruster QObject *qmp_qom_get(const char *path, const char *property, Error **errp)
79cfbe46fcSMarkus Armbruster {
80cfbe46fcSMarkus Armbruster Object *obj;
81cfbe46fcSMarkus Armbruster
82cfbe46fcSMarkus Armbruster obj = object_resolve_path(path, NULL);
83cfbe46fcSMarkus Armbruster if (!obj) {
84cfbe46fcSMarkus Armbruster error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
85cfbe46fcSMarkus Armbruster "Device '%s' not found", path);
86cfbe46fcSMarkus Armbruster return NULL;
87cfbe46fcSMarkus Armbruster }
88cfbe46fcSMarkus Armbruster
89cfbe46fcSMarkus Armbruster return object_property_get_qobject(obj, property, errp);
90cfbe46fcSMarkus Armbruster }
91cfbe46fcSMarkus Armbruster
qom_list_types_tramp(ObjectClass * klass,void * data)92cfbe46fcSMarkus Armbruster static void qom_list_types_tramp(ObjectClass *klass, void *data)
93cfbe46fcSMarkus Armbruster {
9454aa3de7SEric Blake ObjectTypeInfoList **pret = data;
95cfbe46fcSMarkus Armbruster ObjectTypeInfo *info;
96cfbe46fcSMarkus Armbruster ObjectClass *parent = object_class_get_parent(klass);
97cfbe46fcSMarkus Armbruster
98cfbe46fcSMarkus Armbruster info = g_malloc0(sizeof(*info));
99cfbe46fcSMarkus Armbruster info->name = g_strdup(object_class_get_name(klass));
100cfbe46fcSMarkus Armbruster info->has_abstract = info->abstract = object_class_is_abstract(klass);
101cfbe46fcSMarkus Armbruster if (parent) {
102cfbe46fcSMarkus Armbruster info->parent = g_strdup(object_class_get_name(parent));
103cfbe46fcSMarkus Armbruster }
104cfbe46fcSMarkus Armbruster
10554aa3de7SEric Blake QAPI_LIST_PREPEND(*pret, info);
106cfbe46fcSMarkus Armbruster }
107cfbe46fcSMarkus Armbruster
qmp_qom_list_types(const char * implements,bool has_abstract,bool abstract,Error ** errp)108047f2ca1SMarkus Armbruster ObjectTypeInfoList *qmp_qom_list_types(const char *implements,
109cfbe46fcSMarkus Armbruster bool has_abstract,
110cfbe46fcSMarkus Armbruster bool abstract,
111cfbe46fcSMarkus Armbruster Error **errp)
112cfbe46fcSMarkus Armbruster {
113cfbe46fcSMarkus Armbruster ObjectTypeInfoList *ret = NULL;
114cfbe46fcSMarkus Armbruster
1157ab6e7fcSGerd Hoffmann module_load_qom_all();
116cfbe46fcSMarkus Armbruster object_class_foreach(qom_list_types_tramp, implements, abstract, &ret);
117cfbe46fcSMarkus Armbruster
118cfbe46fcSMarkus Armbruster return ret;
119cfbe46fcSMarkus Armbruster }
120cfbe46fcSMarkus Armbruster
qmp_device_list_properties(const char * typename,Error ** errp)121cfbe46fcSMarkus Armbruster ObjectPropertyInfoList *qmp_device_list_properties(const char *typename,
122cfbe46fcSMarkus Armbruster Error **errp)
123cfbe46fcSMarkus Armbruster {
124cfbe46fcSMarkus Armbruster ObjectClass *klass;
125cfbe46fcSMarkus Armbruster Object *obj;
126cfbe46fcSMarkus Armbruster ObjectProperty *prop;
127cfbe46fcSMarkus Armbruster ObjectPropertyIterator iter;
128cfbe46fcSMarkus Armbruster ObjectPropertyInfoList *prop_list = NULL;
129cfbe46fcSMarkus Armbruster
1307ab6e7fcSGerd Hoffmann klass = module_object_class_by_name(typename);
131cfbe46fcSMarkus Armbruster if (klass == NULL) {
132cfbe46fcSMarkus Armbruster error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
133cfbe46fcSMarkus Armbruster "Device '%s' not found", typename);
134cfbe46fcSMarkus Armbruster return NULL;
135cfbe46fcSMarkus Armbruster }
136cfbe46fcSMarkus Armbruster
13774b97760SMarkus Armbruster if (!object_class_dynamic_cast(klass, TYPE_DEVICE)
13874b97760SMarkus Armbruster || object_class_is_abstract(klass)) {
139cfbe46fcSMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename",
14074b97760SMarkus Armbruster "a non-abstract device type");
141cfbe46fcSMarkus Armbruster return NULL;
142cfbe46fcSMarkus Armbruster }
143cfbe46fcSMarkus Armbruster
144b801e3cbSPaolo Bonzini obj = object_new_with_class(klass);
145cfbe46fcSMarkus Armbruster
146cfbe46fcSMarkus Armbruster object_property_iter_init(&iter, obj);
147cfbe46fcSMarkus Armbruster while ((prop = object_property_iter_next(&iter))) {
148cfbe46fcSMarkus Armbruster ObjectPropertyInfo *info;
149cfbe46fcSMarkus Armbruster
150cfbe46fcSMarkus Armbruster /* Skip Object and DeviceState properties */
151cfbe46fcSMarkus Armbruster if (strcmp(prop->name, "type") == 0 ||
152cfbe46fcSMarkus Armbruster strcmp(prop->name, "realized") == 0 ||
153cfbe46fcSMarkus Armbruster strcmp(prop->name, "hotpluggable") == 0 ||
154cfbe46fcSMarkus Armbruster strcmp(prop->name, "hotplugged") == 0 ||
155cfbe46fcSMarkus Armbruster strcmp(prop->name, "parent_bus") == 0) {
156cfbe46fcSMarkus Armbruster continue;
157cfbe46fcSMarkus Armbruster }
158cfbe46fcSMarkus Armbruster
159cfbe46fcSMarkus Armbruster /* Skip legacy properties since they are just string versions of
160cfbe46fcSMarkus Armbruster * properties that we already list.
161cfbe46fcSMarkus Armbruster */
162cfbe46fcSMarkus Armbruster if (strstart(prop->name, "legacy-", NULL)) {
163cfbe46fcSMarkus Armbruster continue;
164cfbe46fcSMarkus Armbruster }
165cfbe46fcSMarkus Armbruster
166c1f472eaSPaolo Bonzini info = g_new0(ObjectPropertyInfo, 1);
167c1f472eaSPaolo Bonzini info->name = g_strdup(prop->name);
168c1f472eaSPaolo Bonzini info->type = g_strdup(prop->type);
169c1f472eaSPaolo Bonzini info->description = g_strdup(prop->description);
1701bb3d7d9SMarc-André Lureau info->default_value = qobject_ref(prop->defval);
171cfbe46fcSMarkus Armbruster
17254aa3de7SEric Blake QAPI_LIST_PREPEND(prop_list, info);
173cfbe46fcSMarkus Armbruster }
174cfbe46fcSMarkus Armbruster
175cfbe46fcSMarkus Armbruster object_unref(obj);
176cfbe46fcSMarkus Armbruster
177cfbe46fcSMarkus Armbruster return prop_list;
178cfbe46fcSMarkus Armbruster }
179cfbe46fcSMarkus Armbruster
qmp_qom_list_properties(const char * typename,Error ** errp)180cfbe46fcSMarkus Armbruster ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename,
181cfbe46fcSMarkus Armbruster Error **errp)
182cfbe46fcSMarkus Armbruster {
183cfbe46fcSMarkus Armbruster ObjectClass *klass;
184cfbe46fcSMarkus Armbruster Object *obj = NULL;
185cfbe46fcSMarkus Armbruster ObjectProperty *prop;
186cfbe46fcSMarkus Armbruster ObjectPropertyIterator iter;
187cfbe46fcSMarkus Armbruster ObjectPropertyInfoList *prop_list = NULL;
188cfbe46fcSMarkus Armbruster
189*f41823e0SPaolo Bonzini klass = module_object_class_by_name(typename);
190cfbe46fcSMarkus Armbruster if (klass == NULL) {
191cfbe46fcSMarkus Armbruster error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
192cfbe46fcSMarkus Armbruster "Class '%s' not found", typename);
193cfbe46fcSMarkus Armbruster return NULL;
194cfbe46fcSMarkus Armbruster }
195cfbe46fcSMarkus Armbruster
19674b97760SMarkus Armbruster if (!object_class_dynamic_cast(klass, TYPE_OBJECT)) {
19774b97760SMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename",
19874b97760SMarkus Armbruster "a QOM type");
199cfbe46fcSMarkus Armbruster return NULL;
200cfbe46fcSMarkus Armbruster }
201cfbe46fcSMarkus Armbruster
202cfbe46fcSMarkus Armbruster if (object_class_is_abstract(klass)) {
203cfbe46fcSMarkus Armbruster object_class_property_iter_init(&iter, klass);
204cfbe46fcSMarkus Armbruster } else {
205cfbe46fcSMarkus Armbruster obj = object_new(typename);
206cfbe46fcSMarkus Armbruster object_property_iter_init(&iter, obj);
207cfbe46fcSMarkus Armbruster }
208cfbe46fcSMarkus Armbruster while ((prop = object_property_iter_next(&iter))) {
209cfbe46fcSMarkus Armbruster ObjectPropertyInfo *info;
210cfbe46fcSMarkus Armbruster
211cfbe46fcSMarkus Armbruster info = g_malloc0(sizeof(*info));
212cfbe46fcSMarkus Armbruster info->name = g_strdup(prop->name);
213cfbe46fcSMarkus Armbruster info->type = g_strdup(prop->type);
214cfbe46fcSMarkus Armbruster info->description = g_strdup(prop->description);
215443df40cSMaksim Davydov info->default_value = qobject_ref(prop->defval);
216cfbe46fcSMarkus Armbruster
21754aa3de7SEric Blake QAPI_LIST_PREPEND(prop_list, info);
218cfbe46fcSMarkus Armbruster }
219cfbe46fcSMarkus Armbruster
220cfbe46fcSMarkus Armbruster object_unref(obj);
221cfbe46fcSMarkus Armbruster
222cfbe46fcSMarkus Armbruster return prop_list;
223cfbe46fcSMarkus Armbruster }
224cfbe46fcSMarkus Armbruster
qmp_object_add(ObjectOptions * options,Error ** errp)2259151e59aSKevin Wolf void qmp_object_add(ObjectOptions *options, Error **errp)
226cfbe46fcSMarkus Armbruster {
227f3750266SKevin Wolf user_creatable_add_qapi(options, errp);
228cfbe46fcSMarkus Armbruster }
229cfbe46fcSMarkus Armbruster
qmp_object_del(const char * id,Error ** errp)230cfbe46fcSMarkus Armbruster void qmp_object_del(const char *id, Error **errp)
231cfbe46fcSMarkus Armbruster {
232cfbe46fcSMarkus Armbruster user_creatable_del(id, errp);
233cfbe46fcSMarkus Armbruster }
234