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 "qapi/qmp/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 ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp) 32 { 33 Object *obj; 34 bool ambiguous = false; 35 ObjectPropertyInfoList *props = NULL; 36 ObjectProperty *prop; 37 ObjectPropertyIterator iter; 38 39 obj = object_resolve_path(path, &ambiguous); 40 if (obj == NULL) { 41 if (ambiguous) { 42 error_setg(errp, "Path '%s' is ambiguous", path); 43 } else { 44 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 45 "Device '%s' not found", path); 46 } 47 return NULL; 48 } 49 50 object_property_iter_init(&iter, obj); 51 while ((prop = object_property_iter_next(&iter))) { 52 ObjectPropertyInfo *value = g_new0(ObjectPropertyInfo, 1); 53 54 QAPI_LIST_PREPEND(props, value); 55 56 value->name = g_strdup(prop->name); 57 value->type = g_strdup(prop->type); 58 } 59 60 return props; 61 } 62 63 void qmp_qom_set(const char *path, const char *property, QObject *value, 64 Error **errp) 65 { 66 Object *obj; 67 68 obj = object_resolve_path(path, NULL); 69 if (!obj) { 70 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 71 "Device '%s' not found", path); 72 return; 73 } 74 75 object_property_set_qobject(obj, property, value, errp); 76 } 77 78 QObject *qmp_qom_get(const char *path, const char *property, Error **errp) 79 { 80 Object *obj; 81 82 obj = object_resolve_path(path, NULL); 83 if (!obj) { 84 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 85 "Device '%s' not found", path); 86 return NULL; 87 } 88 89 return object_property_get_qobject(obj, property, errp); 90 } 91 92 static void qom_list_types_tramp(ObjectClass *klass, void *data) 93 { 94 ObjectTypeInfoList **pret = data; 95 ObjectTypeInfo *info; 96 ObjectClass *parent = object_class_get_parent(klass); 97 98 info = g_malloc0(sizeof(*info)); 99 info->name = g_strdup(object_class_get_name(klass)); 100 info->has_abstract = info->abstract = object_class_is_abstract(klass); 101 if (parent) { 102 info->has_parent = true; 103 info->parent = g_strdup(object_class_get_name(parent)); 104 } 105 106 QAPI_LIST_PREPEND(*pret, info); 107 } 108 109 ObjectTypeInfoList *qmp_qom_list_types(bool has_implements, 110 const char *implements, 111 bool has_abstract, 112 bool abstract, 113 Error **errp) 114 { 115 ObjectTypeInfoList *ret = NULL; 116 117 module_load_qom_all(); 118 object_class_foreach(qom_list_types_tramp, implements, abstract, &ret); 119 120 return ret; 121 } 122 123 ObjectPropertyInfoList *qmp_device_list_properties(const char *typename, 124 Error **errp) 125 { 126 ObjectClass *klass; 127 Object *obj; 128 ObjectProperty *prop; 129 ObjectPropertyIterator iter; 130 ObjectPropertyInfoList *prop_list = NULL; 131 132 klass = module_object_class_by_name(typename); 133 if (klass == NULL) { 134 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 135 "Device '%s' not found", typename); 136 return NULL; 137 } 138 139 if (!object_class_dynamic_cast(klass, TYPE_DEVICE) 140 || object_class_is_abstract(klass)) { 141 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", 142 "a non-abstract device type"); 143 return NULL; 144 } 145 146 obj = object_new(typename); 147 148 object_property_iter_init(&iter, obj); 149 while ((prop = object_property_iter_next(&iter))) { 150 ObjectPropertyInfo *info; 151 152 /* Skip Object and DeviceState properties */ 153 if (strcmp(prop->name, "type") == 0 || 154 strcmp(prop->name, "realized") == 0 || 155 strcmp(prop->name, "hotpluggable") == 0 || 156 strcmp(prop->name, "hotplugged") == 0 || 157 strcmp(prop->name, "parent_bus") == 0) { 158 continue; 159 } 160 161 /* Skip legacy properties since they are just string versions of 162 * properties that we already list. 163 */ 164 if (strstart(prop->name, "legacy-", NULL)) { 165 continue; 166 } 167 168 info = g_new0(ObjectPropertyInfo, 1); 169 info->name = g_strdup(prop->name); 170 info->type = g_strdup(prop->type); 171 info->has_description = !!prop->description; 172 info->description = g_strdup(prop->description); 173 info->default_value = qobject_ref(prop->defval); 174 info->has_default_value = !!info->default_value; 175 176 QAPI_LIST_PREPEND(prop_list, info); 177 } 178 179 object_unref(obj); 180 181 return prop_list; 182 } 183 184 ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename, 185 Error **errp) 186 { 187 ObjectClass *klass; 188 Object *obj = NULL; 189 ObjectProperty *prop; 190 ObjectPropertyIterator iter; 191 ObjectPropertyInfoList *prop_list = NULL; 192 193 klass = object_class_by_name(typename); 194 if (klass == NULL) { 195 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 196 "Class '%s' not found", typename); 197 return NULL; 198 } 199 200 if (!object_class_dynamic_cast(klass, TYPE_OBJECT)) { 201 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", 202 "a QOM type"); 203 return NULL; 204 } 205 206 if (object_class_is_abstract(klass)) { 207 object_class_property_iter_init(&iter, klass); 208 } else { 209 obj = object_new(typename); 210 object_property_iter_init(&iter, obj); 211 } 212 while ((prop = object_property_iter_next(&iter))) { 213 ObjectPropertyInfo *info; 214 215 info = g_malloc0(sizeof(*info)); 216 info->name = g_strdup(prop->name); 217 info->type = g_strdup(prop->type); 218 info->has_description = !!prop->description; 219 info->description = g_strdup(prop->description); 220 221 QAPI_LIST_PREPEND(prop_list, info); 222 } 223 224 object_unref(obj); 225 226 return prop_list; 227 } 228 229 void qmp_object_add(ObjectOptions *options, Error **errp) 230 { 231 user_creatable_add_qapi(options, errp); 232 } 233 234 void qmp_object_del(const char *id, Error **errp) 235 { 236 user_creatable_del(id, errp); 237 } 238