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->parent = g_strdup(object_class_get_name(parent)); 103 } 104 105 QAPI_LIST_PREPEND(*pret, info); 106 } 107 108 ObjectTypeInfoList *qmp_qom_list_types(const char *implements, 109 bool has_abstract, 110 bool abstract, 111 Error **errp) 112 { 113 ObjectTypeInfoList *ret = NULL; 114 115 module_load_qom_all(); 116 object_class_foreach(qom_list_types_tramp, implements, abstract, &ret); 117 118 return ret; 119 } 120 121 ObjectPropertyInfoList *qmp_device_list_properties(const char *typename, 122 Error **errp) 123 { 124 ObjectClass *klass; 125 Object *obj; 126 ObjectProperty *prop; 127 ObjectPropertyIterator iter; 128 ObjectPropertyInfoList *prop_list = NULL; 129 130 klass = module_object_class_by_name(typename); 131 if (klass == NULL) { 132 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 133 "Device '%s' not found", typename); 134 return NULL; 135 } 136 137 if (!object_class_dynamic_cast(klass, TYPE_DEVICE) 138 || object_class_is_abstract(klass)) { 139 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", 140 "a non-abstract device type"); 141 return NULL; 142 } 143 144 obj = object_new(typename); 145 146 object_property_iter_init(&iter, obj); 147 while ((prop = object_property_iter_next(&iter))) { 148 ObjectPropertyInfo *info; 149 150 /* Skip Object and DeviceState properties */ 151 if (strcmp(prop->name, "type") == 0 || 152 strcmp(prop->name, "realized") == 0 || 153 strcmp(prop->name, "hotpluggable") == 0 || 154 strcmp(prop->name, "hotplugged") == 0 || 155 strcmp(prop->name, "parent_bus") == 0) { 156 continue; 157 } 158 159 /* Skip legacy properties since they are just string versions of 160 * properties that we already list. 161 */ 162 if (strstart(prop->name, "legacy-", NULL)) { 163 continue; 164 } 165 166 info = g_new0(ObjectPropertyInfo, 1); 167 info->name = g_strdup(prop->name); 168 info->type = g_strdup(prop->type); 169 info->description = g_strdup(prop->description); 170 info->default_value = qobject_ref(prop->defval); 171 172 QAPI_LIST_PREPEND(prop_list, info); 173 } 174 175 object_unref(obj); 176 177 return prop_list; 178 } 179 180 ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename, 181 Error **errp) 182 { 183 ObjectClass *klass; 184 Object *obj = NULL; 185 ObjectProperty *prop; 186 ObjectPropertyIterator iter; 187 ObjectPropertyInfoList *prop_list = NULL; 188 189 klass = object_class_by_name(typename); 190 if (klass == NULL) { 191 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 192 "Class '%s' not found", typename); 193 return NULL; 194 } 195 196 if (!object_class_dynamic_cast(klass, TYPE_OBJECT)) { 197 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", 198 "a QOM type"); 199 return NULL; 200 } 201 202 if (object_class_is_abstract(klass)) { 203 object_class_property_iter_init(&iter, klass); 204 } else { 205 obj = object_new(typename); 206 object_property_iter_init(&iter, obj); 207 } 208 while ((prop = object_property_iter_next(&iter))) { 209 ObjectPropertyInfo *info; 210 211 info = g_malloc0(sizeof(*info)); 212 info->name = g_strdup(prop->name); 213 info->type = g_strdup(prop->type); 214 info->description = g_strdup(prop->description); 215 216 QAPI_LIST_PREPEND(prop_list, info); 217 } 218 219 object_unref(obj); 220 221 return prop_list; 222 } 223 224 void qmp_object_add(ObjectOptions *options, Error **errp) 225 { 226 user_creatable_add_qapi(options, errp); 227 } 228 229 void qmp_object_del(const char *id, Error **errp) 230 { 231 user_creatable_del(id, errp); 232 } 233