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 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 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 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 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 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 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 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 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 234 void qmp_object_add(ObjectOptions *options, Error **errp) 235 { 236 user_creatable_add_qapi(options, errp); 237 } 238 239 void qmp_object_del(const char *id, Error **errp) 240 { 241 user_creatable_del(id, errp); 242 } 243