xref: /qemu/qom/qom-hmp-cmds.c (revision cffaca0f)
13950a377SMarkus Armbruster /*
23950a377SMarkus Armbruster  * HMP commands related to QOM
33950a377SMarkus Armbruster  *
43950a377SMarkus Armbruster  * This work is licensed under the terms of the GNU GPL, version 2 or
53950a377SMarkus Armbruster  * later.  See the COPYING file in the top-level directory.
63950a377SMarkus Armbruster  */
73950a377SMarkus Armbruster 
83950a377SMarkus Armbruster #include "qemu/osdep.h"
93950a377SMarkus Armbruster #include "hw/qdev-core.h"
103950a377SMarkus Armbruster #include "monitor/hmp.h"
113950a377SMarkus Armbruster #include "monitor/monitor.h"
123950a377SMarkus Armbruster #include "qapi/error.h"
133950a377SMarkus Armbruster #include "qapi/qapi-commands-qom.h"
143950a377SMarkus Armbruster #include "qapi/qmp/qdict.h"
1589cf4fe3SDr. David Alan Gilbert #include "qapi/qmp/qjson.h"
16*cffaca0fSMarkus Armbruster #include "qemu/readline.h"
173950a377SMarkus Armbruster #include "qom/object.h"
18*cffaca0fSMarkus Armbruster #include "qom/object_interfaces.h"
193950a377SMarkus Armbruster 
hmp_qom_list(Monitor * mon,const QDict * qdict)203950a377SMarkus Armbruster void hmp_qom_list(Monitor *mon, const QDict *qdict)
213950a377SMarkus Armbruster {
223950a377SMarkus Armbruster     const char *path = qdict_get_try_str(qdict, "path");
233950a377SMarkus Armbruster     ObjectPropertyInfoList *list;
243950a377SMarkus Armbruster     Error *err = NULL;
253950a377SMarkus Armbruster 
263950a377SMarkus Armbruster     if (path == NULL) {
273950a377SMarkus Armbruster         monitor_printf(mon, "/\n");
283950a377SMarkus Armbruster         return;
293950a377SMarkus Armbruster     }
303950a377SMarkus Armbruster 
313950a377SMarkus Armbruster     list = qmp_qom_list(path, &err);
323950a377SMarkus Armbruster     if (err == NULL) {
333950a377SMarkus Armbruster         ObjectPropertyInfoList *start = list;
343950a377SMarkus Armbruster         while (list != NULL) {
353950a377SMarkus Armbruster             ObjectPropertyInfo *value = list->value;
363950a377SMarkus Armbruster 
373950a377SMarkus Armbruster             monitor_printf(mon, "%s (%s)\n",
383950a377SMarkus Armbruster                            value->name, value->type);
393950a377SMarkus Armbruster             list = list->next;
403950a377SMarkus Armbruster         }
413950a377SMarkus Armbruster         qapi_free_ObjectPropertyInfoList(start);
423950a377SMarkus Armbruster     }
43187c6147SVladimir Sementsov-Ogievskiy     hmp_handle_error(mon, err);
443950a377SMarkus Armbruster }
453950a377SMarkus Armbruster 
hmp_qom_set(Monitor * mon,const QDict * qdict)463950a377SMarkus Armbruster void hmp_qom_set(Monitor *mon, const QDict *qdict)
473950a377SMarkus Armbruster {
482d9e3dd9SDavid Hildenbrand     const bool json = qdict_get_try_bool(qdict, "json", false);
493950a377SMarkus Armbruster     const char *path = qdict_get_str(qdict, "path");
503950a377SMarkus Armbruster     const char *property = qdict_get_str(qdict, "property");
513950a377SMarkus Armbruster     const char *value = qdict_get_str(qdict, "value");
523950a377SMarkus Armbruster     Error *err = NULL;
533950a377SMarkus Armbruster 
542d9e3dd9SDavid Hildenbrand     if (!json) {
552d9e3dd9SDavid Hildenbrand         Object *obj = object_resolve_path(path, NULL);
562d9e3dd9SDavid Hildenbrand 
572d9e3dd9SDavid Hildenbrand         if (!obj) {
582d9e3dd9SDavid Hildenbrand             error_set(&err, ERROR_CLASS_DEVICE_NOT_FOUND,
592d9e3dd9SDavid Hildenbrand                       "Device '%s' not found", path);
602d9e3dd9SDavid Hildenbrand         } else {
615325cc34SMarkus Armbruster             object_property_parse(obj, property, value, &err);
622d9e3dd9SDavid Hildenbrand         }
632d9e3dd9SDavid Hildenbrand     } else {
642d9e3dd9SDavid Hildenbrand         QObject *obj = qobject_from_json(value, &err);
652d9e3dd9SDavid Hildenbrand 
662d9e3dd9SDavid Hildenbrand         if (!err) {
677d2ef6dcSDr. David Alan Gilbert             qmp_qom_set(path, property, obj, &err);
683950a377SMarkus Armbruster         }
692d9e3dd9SDavid Hildenbrand     }
707d2ef6dcSDr. David Alan Gilbert 
71187c6147SVladimir Sementsov-Ogievskiy     hmp_handle_error(mon, err);
723950a377SMarkus Armbruster }
733950a377SMarkus Armbruster 
hmp_qom_get(Monitor * mon,const QDict * qdict)7489cf4fe3SDr. David Alan Gilbert void hmp_qom_get(Monitor *mon, const QDict *qdict)
7589cf4fe3SDr. David Alan Gilbert {
7689cf4fe3SDr. David Alan Gilbert     const char *path = qdict_get_str(qdict, "path");
7789cf4fe3SDr. David Alan Gilbert     const char *property = qdict_get_str(qdict, "property");
7889cf4fe3SDr. David Alan Gilbert     Error *err = NULL;
7989cf4fe3SDr. David Alan Gilbert     QObject *obj = qmp_qom_get(path, property, &err);
8089cf4fe3SDr. David Alan Gilbert 
8189cf4fe3SDr. David Alan Gilbert     if (err == NULL) {
82eab3a467SMarkus Armbruster         GString *str = qobject_to_json_pretty(obj, true);
83eab3a467SMarkus Armbruster         monitor_printf(mon, "%s\n", str->str);
84eab3a467SMarkus Armbruster         g_string_free(str, true);
8589cf4fe3SDr. David Alan Gilbert     }
8689cf4fe3SDr. David Alan Gilbert 
87246da7dbSPan Nengyuan     qobject_unref(obj);
8889cf4fe3SDr. David Alan Gilbert     hmp_handle_error(mon, err);
8989cf4fe3SDr. David Alan Gilbert }
9089cf4fe3SDr. David Alan Gilbert 
913950a377SMarkus Armbruster typedef struct QOMCompositionState {
923950a377SMarkus Armbruster     Monitor *mon;
933950a377SMarkus Armbruster     int indent;
943950a377SMarkus Armbruster } QOMCompositionState;
953950a377SMarkus Armbruster 
963950a377SMarkus Armbruster static void print_qom_composition(Monitor *mon, Object *obj, int indent);
973950a377SMarkus Armbruster 
qom_composition_compare(const void * a,const void * b)980dde9fd1SMarkus Armbruster static int qom_composition_compare(const void *a, const void *b)
993950a377SMarkus Armbruster {
1000dde9fd1SMarkus Armbruster     return g_strcmp0(object_get_canonical_path_component(*(Object **)a),
1010dde9fd1SMarkus Armbruster                      object_get_canonical_path_component(*(Object **)b));
102e8c9e658SMarkus Armbruster }
1033950a377SMarkus Armbruster 
insert_qom_composition_child(Object * obj,void * opaque)104e8c9e658SMarkus Armbruster static int insert_qom_composition_child(Object *obj, void *opaque)
105e8c9e658SMarkus Armbruster {
1060dde9fd1SMarkus Armbruster     g_array_append_val(opaque, obj);
1073950a377SMarkus Armbruster     return 0;
1083950a377SMarkus Armbruster }
1093950a377SMarkus Armbruster 
print_qom_composition(Monitor * mon,Object * obj,int indent)1103950a377SMarkus Armbruster static void print_qom_composition(Monitor *mon, Object *obj, int indent)
1113950a377SMarkus Armbruster {
1120dde9fd1SMarkus Armbruster     GArray *children = g_array_new(false, false, sizeof(Object *));
1137a309cc9SMarkus Armbruster     const char *name;
1140dde9fd1SMarkus Armbruster     int i;
1153950a377SMarkus Armbruster 
1163950a377SMarkus Armbruster     if (obj == object_get_root()) {
1177a309cc9SMarkus Armbruster         name = "";
1183950a377SMarkus Armbruster     } else {
1193950a377SMarkus Armbruster         name = object_get_canonical_path_component(obj);
1203950a377SMarkus Armbruster     }
1213950a377SMarkus Armbruster     monitor_printf(mon, "%*s/%s (%s)\n", indent, "", name,
1223950a377SMarkus Armbruster                    object_get_typename(obj));
123e8c9e658SMarkus Armbruster 
1240dde9fd1SMarkus Armbruster     object_child_foreach(obj, insert_qom_composition_child, children);
1250dde9fd1SMarkus Armbruster     g_array_sort(children, qom_composition_compare);
1260dde9fd1SMarkus Armbruster 
1270dde9fd1SMarkus Armbruster     for (i = 0; i < children->len; i++) {
1280dde9fd1SMarkus Armbruster         print_qom_composition(mon, g_array_index(children, Object *, i),
1290dde9fd1SMarkus Armbruster                               indent + 2);
130e8c9e658SMarkus Armbruster     }
1310dde9fd1SMarkus Armbruster     g_array_free(children, TRUE);
1323950a377SMarkus Armbruster }
1333950a377SMarkus Armbruster 
hmp_info_qom_tree(Monitor * mon,const QDict * dict)1343950a377SMarkus Armbruster void hmp_info_qom_tree(Monitor *mon, const QDict *dict)
1353950a377SMarkus Armbruster {
1363950a377SMarkus Armbruster     const char *path = qdict_get_try_str(dict, "path");
1373950a377SMarkus Armbruster     Object *obj;
1383950a377SMarkus Armbruster     bool ambiguous = false;
1393950a377SMarkus Armbruster 
1403950a377SMarkus Armbruster     if (path) {
1413950a377SMarkus Armbruster         obj = object_resolve_path(path, &ambiguous);
1423950a377SMarkus Armbruster         if (!obj) {
1433950a377SMarkus Armbruster             monitor_printf(mon, "Path '%s' could not be resolved.\n", path);
1443950a377SMarkus Armbruster             return;
1453950a377SMarkus Armbruster         }
1463950a377SMarkus Armbruster         if (ambiguous) {
1473950a377SMarkus Armbruster             monitor_printf(mon, "Warning: Path '%s' is ambiguous.\n", path);
1483950a377SMarkus Armbruster             return;
1493950a377SMarkus Armbruster         }
1503950a377SMarkus Armbruster     } else {
1513950a377SMarkus Armbruster         obj = qdev_get_machine();
1523950a377SMarkus Armbruster     }
1533950a377SMarkus Armbruster     print_qom_composition(mon, obj, 0);
1543950a377SMarkus Armbruster }
155*cffaca0fSMarkus Armbruster 
hmp_object_add(Monitor * mon,const QDict * qdict)156*cffaca0fSMarkus Armbruster void hmp_object_add(Monitor *mon, const QDict *qdict)
157*cffaca0fSMarkus Armbruster {
158*cffaca0fSMarkus Armbruster     const char *options = qdict_get_str(qdict, "object");
159*cffaca0fSMarkus Armbruster     Error *err = NULL;
160*cffaca0fSMarkus Armbruster 
161*cffaca0fSMarkus Armbruster     user_creatable_add_from_str(options, &err);
162*cffaca0fSMarkus Armbruster     hmp_handle_error(mon, err);
163*cffaca0fSMarkus Armbruster }
164*cffaca0fSMarkus Armbruster 
hmp_object_del(Monitor * mon,const QDict * qdict)165*cffaca0fSMarkus Armbruster void hmp_object_del(Monitor *mon, const QDict *qdict)
166*cffaca0fSMarkus Armbruster {
167*cffaca0fSMarkus Armbruster     const char *id = qdict_get_str(qdict, "id");
168*cffaca0fSMarkus Armbruster     Error *err = NULL;
169*cffaca0fSMarkus Armbruster 
170*cffaca0fSMarkus Armbruster     user_creatable_del(id, &err);
171*cffaca0fSMarkus Armbruster     hmp_handle_error(mon, err);
172*cffaca0fSMarkus Armbruster }
173*cffaca0fSMarkus Armbruster 
object_add_completion(ReadLineState * rs,int nb_args,const char * str)174*cffaca0fSMarkus Armbruster void object_add_completion(ReadLineState *rs, int nb_args, const char *str)
175*cffaca0fSMarkus Armbruster {
176*cffaca0fSMarkus Armbruster     GSList *list, *elt;
177*cffaca0fSMarkus Armbruster     size_t len;
178*cffaca0fSMarkus Armbruster 
179*cffaca0fSMarkus Armbruster     if (nb_args != 2) {
180*cffaca0fSMarkus Armbruster         return;
181*cffaca0fSMarkus Armbruster     }
182*cffaca0fSMarkus Armbruster 
183*cffaca0fSMarkus Armbruster     len = strlen(str);
184*cffaca0fSMarkus Armbruster     readline_set_completion_index(rs, len);
185*cffaca0fSMarkus Armbruster     list = elt = object_class_get_list(TYPE_USER_CREATABLE, false);
186*cffaca0fSMarkus Armbruster     while (elt) {
187*cffaca0fSMarkus Armbruster         const char *name;
188*cffaca0fSMarkus Armbruster 
189*cffaca0fSMarkus Armbruster         name = object_class_get_name(OBJECT_CLASS(elt->data));
190*cffaca0fSMarkus Armbruster         if (strcmp(name, TYPE_USER_CREATABLE)) {
191*cffaca0fSMarkus Armbruster             readline_add_completion_of(rs, str, name);
192*cffaca0fSMarkus Armbruster         }
193*cffaca0fSMarkus Armbruster         elt = elt->next;
194*cffaca0fSMarkus Armbruster     }
195*cffaca0fSMarkus Armbruster     g_slist_free(list);
196*cffaca0fSMarkus Armbruster }
197*cffaca0fSMarkus Armbruster 
object_del_completion(ReadLineState * rs,int nb_args,const char * str)198*cffaca0fSMarkus Armbruster void object_del_completion(ReadLineState *rs, int nb_args, const char *str)
199*cffaca0fSMarkus Armbruster {
200*cffaca0fSMarkus Armbruster     ObjectPropertyInfoList *list, *start;
201*cffaca0fSMarkus Armbruster     size_t len;
202*cffaca0fSMarkus Armbruster 
203*cffaca0fSMarkus Armbruster     if (nb_args != 2) {
204*cffaca0fSMarkus Armbruster         return;
205*cffaca0fSMarkus Armbruster     }
206*cffaca0fSMarkus Armbruster     len = strlen(str);
207*cffaca0fSMarkus Armbruster     readline_set_completion_index(rs, len);
208*cffaca0fSMarkus Armbruster 
209*cffaca0fSMarkus Armbruster     start = list = qmp_qom_list("/objects", NULL);
210*cffaca0fSMarkus Armbruster     while (list) {
211*cffaca0fSMarkus Armbruster         ObjectPropertyInfo *info = list->value;
212*cffaca0fSMarkus Armbruster 
213*cffaca0fSMarkus Armbruster         if (!strncmp(info->type, "child<", 5)) {
214*cffaca0fSMarkus Armbruster             readline_add_completion_of(rs, str, info->name);
215*cffaca0fSMarkus Armbruster         }
216*cffaca0fSMarkus Armbruster         list = list->next;
217*cffaca0fSMarkus Armbruster     }
218*cffaca0fSMarkus Armbruster     qapi_free_ObjectPropertyInfoList(start);
219*cffaca0fSMarkus Armbruster }
220