1 /* 2 * HMP commands related to QOM 3 * 4 * This work is licensed under the terms of the GNU GPL, version 2 or 5 * later. See the COPYING file in the top-level directory. 6 */ 7 8 #include "qemu/osdep.h" 9 #include "hw/qdev-core.h" 10 #include "monitor/hmp.h" 11 #include "monitor/monitor.h" 12 #include "qapi/error.h" 13 #include "qapi/qapi-commands-qom.h" 14 #include "qapi/qmp/qdict.h" 15 #include "qapi/qmp/qjson.h" 16 #include "qom/object.h" 17 18 void hmp_qom_list(Monitor *mon, const QDict *qdict) 19 { 20 const char *path = qdict_get_try_str(qdict, "path"); 21 ObjectPropertyInfoList *list; 22 Error *err = NULL; 23 24 if (path == NULL) { 25 monitor_printf(mon, "/\n"); 26 return; 27 } 28 29 list = qmp_qom_list(path, &err); 30 if (err == NULL) { 31 ObjectPropertyInfoList *start = list; 32 while (list != NULL) { 33 ObjectPropertyInfo *value = list->value; 34 35 monitor_printf(mon, "%s (%s)\n", 36 value->name, value->type); 37 list = list->next; 38 } 39 qapi_free_ObjectPropertyInfoList(start); 40 } 41 hmp_handle_error(mon, err); 42 } 43 44 void hmp_qom_set(Monitor *mon, const QDict *qdict) 45 { 46 const bool json = qdict_get_try_bool(qdict, "json", false); 47 const char *path = qdict_get_str(qdict, "path"); 48 const char *property = qdict_get_str(qdict, "property"); 49 const char *value = qdict_get_str(qdict, "value"); 50 Error *err = NULL; 51 52 if (!json) { 53 Object *obj = object_resolve_path(path, NULL); 54 55 if (!obj) { 56 error_set(&err, ERROR_CLASS_DEVICE_NOT_FOUND, 57 "Device '%s' not found", path); 58 } else { 59 object_property_parse(obj, property, value, &err); 60 } 61 } else { 62 QObject *obj = qobject_from_json(value, &err); 63 64 if (!err) { 65 qmp_qom_set(path, property, obj, &err); 66 } 67 } 68 69 hmp_handle_error(mon, err); 70 } 71 72 void hmp_qom_get(Monitor *mon, const QDict *qdict) 73 { 74 const char *path = qdict_get_str(qdict, "path"); 75 const char *property = qdict_get_str(qdict, "property"); 76 Error *err = NULL; 77 QObject *obj = qmp_qom_get(path, property, &err); 78 79 if (err == NULL) { 80 GString *str = qobject_to_json_pretty(obj, true); 81 monitor_printf(mon, "%s\n", str->str); 82 g_string_free(str, true); 83 } 84 85 qobject_unref(obj); 86 hmp_handle_error(mon, err); 87 } 88 89 typedef struct QOMCompositionState { 90 Monitor *mon; 91 int indent; 92 } QOMCompositionState; 93 94 static void print_qom_composition(Monitor *mon, Object *obj, int indent); 95 96 static int qom_composition_compare(const void *a, const void *b) 97 { 98 return g_strcmp0(object_get_canonical_path_component(*(Object **)a), 99 object_get_canonical_path_component(*(Object **)b)); 100 } 101 102 static int insert_qom_composition_child(Object *obj, void *opaque) 103 { 104 g_array_append_val(opaque, obj); 105 return 0; 106 } 107 108 static void print_qom_composition(Monitor *mon, Object *obj, int indent) 109 { 110 GArray *children = g_array_new(false, false, sizeof(Object *)); 111 const char *name; 112 int i; 113 114 if (obj == object_get_root()) { 115 name = ""; 116 } else { 117 name = object_get_canonical_path_component(obj); 118 } 119 monitor_printf(mon, "%*s/%s (%s)\n", indent, "", name, 120 object_get_typename(obj)); 121 122 object_child_foreach(obj, insert_qom_composition_child, children); 123 g_array_sort(children, qom_composition_compare); 124 125 for (i = 0; i < children->len; i++) { 126 print_qom_composition(mon, g_array_index(children, Object *, i), 127 indent + 2); 128 } 129 g_array_free(children, TRUE); 130 } 131 132 void hmp_info_qom_tree(Monitor *mon, const QDict *dict) 133 { 134 const char *path = qdict_get_try_str(dict, "path"); 135 Object *obj; 136 bool ambiguous = false; 137 138 if (path) { 139 obj = object_resolve_path(path, &ambiguous); 140 if (!obj) { 141 monitor_printf(mon, "Path '%s' could not be resolved.\n", path); 142 return; 143 } 144 if (ambiguous) { 145 monitor_printf(mon, "Warning: Path '%s' is ambiguous.\n", path); 146 return; 147 } 148 } else { 149 obj = qdev_get_machine(); 150 } 151 print_qom_composition(mon, obj, 0); 152 } 153