1 /* 2 * qdev property parsing 3 * (parts specific for qemu-system-*) 4 * 5 * This file is based on code from hw/qdev-properties.c from 6 * commit 074a86fccd185616469dfcdc0e157f438aebba18, 7 * Copyright (c) Gerd Hoffmann <kraxel@redhat.com> and other contributors. 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 #include "qemu/osdep.h" 14 #include "audio/audio.h" 15 #include "net/net.h" 16 #include "hw/qdev-properties.h" 17 #include "qapi/error.h" 18 #include "qapi/qmp/qerror.h" 19 #include "sysemu/block-backend.h" 20 #include "sysemu/blockdev.h" 21 #include "hw/block/block.h" 22 #include "net/hub.h" 23 #include "qapi/visitor.h" 24 #include "chardev/char-fe.h" 25 #include "sysemu/iothread.h" 26 #include "sysemu/tpm_backend.h" 27 28 static bool check_prop_still_unset(DeviceState *dev, const char *name, 29 const void *old_val, const char *new_val, 30 Error **errp) 31 { 32 const GlobalProperty *prop = qdev_find_global_prop(dev, name); 33 34 if (!old_val) { 35 return true; 36 } 37 38 if (prop) { 39 error_setg(errp, "-global %s.%s=... conflicts with %s=%s", 40 prop->driver, prop->property, name, new_val); 41 } else { 42 /* Error message is vague, but a better one would be hard */ 43 error_setg(errp, "%s=%s conflicts, and override is not implemented", 44 name, new_val); 45 } 46 return false; 47 } 48 49 50 /* --- drive --- */ 51 52 static void get_drive(Object *obj, Visitor *v, const char *name, void *opaque, 53 Error **errp) 54 { 55 DeviceState *dev = DEVICE(obj); 56 Property *prop = opaque; 57 void **ptr = qdev_get_prop_ptr(dev, prop); 58 const char *value; 59 char *p; 60 61 if (*ptr) { 62 value = blk_name(*ptr); 63 if (!*value) { 64 BlockDriverState *bs = blk_bs(*ptr); 65 if (bs) { 66 value = bdrv_get_node_name(bs); 67 } 68 } 69 } else { 70 value = ""; 71 } 72 73 p = g_strdup(value); 74 visit_type_str(v, name, &p, errp); 75 g_free(p); 76 } 77 78 static void set_drive_helper(Object *obj, Visitor *v, const char *name, 79 void *opaque, bool iothread, Error **errp) 80 { 81 DeviceState *dev = DEVICE(obj); 82 Property *prop = opaque; 83 Error *local_err = NULL; 84 void **ptr = qdev_get_prop_ptr(dev, prop); 85 char *str; 86 BlockBackend *blk; 87 bool blk_created = false; 88 int ret; 89 90 if (dev->realized) { 91 qdev_prop_set_after_realize(dev, name, errp); 92 return; 93 } 94 95 if (!visit_type_str(v, name, &str, &local_err)) { 96 error_propagate(errp, local_err); 97 return; 98 } 99 100 /* 101 * TODO Should this really be an error? If no, the old value 102 * needs to be released before we store the new one. 103 */ 104 if (!check_prop_still_unset(dev, name, *ptr, str, errp)) { 105 return; 106 } 107 108 if (!*str) { 109 g_free(str); 110 *ptr = NULL; 111 return; 112 } 113 114 blk = blk_by_name(str); 115 if (!blk) { 116 BlockDriverState *bs = bdrv_lookup_bs(NULL, str, NULL); 117 if (bs) { 118 /* 119 * If the device supports iothreads, it will make sure to move the 120 * block node to the right AioContext if necessary (or fail if this 121 * isn't possible because of other users). Devices that are not 122 * aware of iothreads require their BlockBackends to be in the main 123 * AioContext. 124 */ 125 AioContext *ctx = iothread ? bdrv_get_aio_context(bs) : 126 qemu_get_aio_context(); 127 blk = blk_new(ctx, 0, BLK_PERM_ALL); 128 blk_created = true; 129 130 ret = blk_insert_bs(blk, bs, errp); 131 if (ret < 0) { 132 goto fail; 133 } 134 } 135 } 136 if (!blk) { 137 error_setg(errp, "Property '%s.%s' can't find value '%s'", 138 object_get_typename(OBJECT(dev)), prop->name, str); 139 goto fail; 140 } 141 if (blk_attach_dev(blk, dev) < 0) { 142 DriveInfo *dinfo = blk_legacy_dinfo(blk); 143 144 if (dinfo && dinfo->type != IF_NONE) { 145 error_setg(errp, "Drive '%s' is already in use because " 146 "it has been automatically connected to another " 147 "device (did you need 'if=none' in the drive options?)", 148 str); 149 } else { 150 error_setg(errp, "Drive '%s' is already in use by another device", 151 str); 152 } 153 goto fail; 154 } 155 156 *ptr = blk; 157 158 fail: 159 if (blk_created) { 160 /* If we need to keep a reference, blk_attach_dev() took it */ 161 blk_unref(blk); 162 } 163 164 g_free(str); 165 } 166 167 static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque, 168 Error **errp) 169 { 170 set_drive_helper(obj, v, name, opaque, false, errp); 171 } 172 173 static void set_drive_iothread(Object *obj, Visitor *v, const char *name, 174 void *opaque, Error **errp) 175 { 176 set_drive_helper(obj, v, name, opaque, true, errp); 177 } 178 179 static void release_drive(Object *obj, const char *name, void *opaque) 180 { 181 DeviceState *dev = DEVICE(obj); 182 Property *prop = opaque; 183 BlockBackend **ptr = qdev_get_prop_ptr(dev, prop); 184 185 if (*ptr) { 186 AioContext *ctx = blk_get_aio_context(*ptr); 187 188 aio_context_acquire(ctx); 189 blockdev_auto_del(*ptr); 190 blk_detach_dev(*ptr, dev); 191 aio_context_release(ctx); 192 } 193 } 194 195 const PropertyInfo qdev_prop_drive = { 196 .name = "str", 197 .description = "Node name or ID of a block device to use as a backend", 198 .get = get_drive, 199 .set = set_drive, 200 .release = release_drive, 201 }; 202 203 const PropertyInfo qdev_prop_drive_iothread = { 204 .name = "str", 205 .description = "Node name or ID of a block device to use as a backend", 206 .get = get_drive, 207 .set = set_drive_iothread, 208 .release = release_drive, 209 }; 210 211 /* --- character device --- */ 212 213 static void get_chr(Object *obj, Visitor *v, const char *name, void *opaque, 214 Error **errp) 215 { 216 DeviceState *dev = DEVICE(obj); 217 CharBackend *be = qdev_get_prop_ptr(dev, opaque); 218 char *p; 219 220 p = g_strdup(be->chr && be->chr->label ? be->chr->label : ""); 221 visit_type_str(v, name, &p, errp); 222 g_free(p); 223 } 224 225 static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque, 226 Error **errp) 227 { 228 DeviceState *dev = DEVICE(obj); 229 Error *local_err = NULL; 230 Property *prop = opaque; 231 CharBackend *be = qdev_get_prop_ptr(dev, prop); 232 Chardev *s; 233 char *str; 234 235 if (dev->realized) { 236 qdev_prop_set_after_realize(dev, name, errp); 237 return; 238 } 239 240 if (!visit_type_str(v, name, &str, &local_err)) { 241 error_propagate(errp, local_err); 242 return; 243 } 244 245 /* 246 * TODO Should this really be an error? If no, the old value 247 * needs to be released before we store the new one. 248 */ 249 if (!check_prop_still_unset(dev, name, be->chr, str, errp)) { 250 return; 251 } 252 253 if (!*str) { 254 g_free(str); 255 be->chr = NULL; 256 return; 257 } 258 259 s = qemu_chr_find(str); 260 if (s == NULL) { 261 error_setg(errp, "Property '%s.%s' can't find value '%s'", 262 object_get_typename(obj), prop->name, str); 263 } else if (!qemu_chr_fe_init(be, s, errp)) { 264 error_prepend(errp, "Property '%s.%s' can't take value '%s': ", 265 object_get_typename(obj), prop->name, str); 266 } 267 g_free(str); 268 } 269 270 static void release_chr(Object *obj, const char *name, void *opaque) 271 { 272 DeviceState *dev = DEVICE(obj); 273 Property *prop = opaque; 274 CharBackend *be = qdev_get_prop_ptr(dev, prop); 275 276 qemu_chr_fe_deinit(be, false); 277 } 278 279 const PropertyInfo qdev_prop_chr = { 280 .name = "str", 281 .description = "ID of a chardev to use as a backend", 282 .get = get_chr, 283 .set = set_chr, 284 .release = release_chr, 285 }; 286 287 /* --- netdev device --- */ 288 static void get_netdev(Object *obj, Visitor *v, const char *name, 289 void *opaque, Error **errp) 290 { 291 DeviceState *dev = DEVICE(obj); 292 Property *prop = opaque; 293 NICPeers *peers_ptr = qdev_get_prop_ptr(dev, prop); 294 char *p = g_strdup(peers_ptr->ncs[0] ? peers_ptr->ncs[0]->name : ""); 295 296 visit_type_str(v, name, &p, errp); 297 g_free(p); 298 } 299 300 static void set_netdev(Object *obj, Visitor *v, const char *name, 301 void *opaque, Error **errp) 302 { 303 DeviceState *dev = DEVICE(obj); 304 Property *prop = opaque; 305 NICPeers *peers_ptr = qdev_get_prop_ptr(dev, prop); 306 NetClientState **ncs = peers_ptr->ncs; 307 NetClientState *peers[MAX_QUEUE_NUM]; 308 Error *local_err = NULL; 309 int queues, err = 0, i = 0; 310 char *str; 311 312 if (dev->realized) { 313 qdev_prop_set_after_realize(dev, name, errp); 314 return; 315 } 316 317 if (!visit_type_str(v, name, &str, &local_err)) { 318 error_propagate(errp, local_err); 319 return; 320 } 321 322 queues = qemu_find_net_clients_except(str, peers, 323 NET_CLIENT_DRIVER_NIC, 324 MAX_QUEUE_NUM); 325 if (queues == 0) { 326 err = -ENOENT; 327 goto out; 328 } 329 330 if (queues > MAX_QUEUE_NUM) { 331 error_setg(errp, "queues of backend '%s'(%d) exceeds QEMU limitation(%d)", 332 str, queues, MAX_QUEUE_NUM); 333 goto out; 334 } 335 336 for (i = 0; i < queues; i++) { 337 if (peers[i]->peer) { 338 err = -EEXIST; 339 goto out; 340 } 341 342 /* 343 * TODO Should this really be an error? If no, the old value 344 * needs to be released before we store the new one. 345 */ 346 if (!check_prop_still_unset(dev, name, ncs[i], str, errp)) { 347 goto out; 348 } 349 350 ncs[i] = peers[i]; 351 ncs[i]->queue_index = i; 352 } 353 354 peers_ptr->queues = queues; 355 356 out: 357 error_set_from_qdev_prop_error(errp, err, dev, prop, str); 358 g_free(str); 359 } 360 361 const PropertyInfo qdev_prop_netdev = { 362 .name = "str", 363 .description = "ID of a netdev to use as a backend", 364 .get = get_netdev, 365 .set = set_netdev, 366 }; 367 368 369 /* --- audiodev --- */ 370 static void get_audiodev(Object *obj, Visitor *v, const char* name, 371 void *opaque, Error **errp) 372 { 373 DeviceState *dev = DEVICE(obj); 374 Property *prop = opaque; 375 QEMUSoundCard *card = qdev_get_prop_ptr(dev, prop); 376 char *p = g_strdup(audio_get_id(card)); 377 378 visit_type_str(v, name, &p, errp); 379 g_free(p); 380 } 381 382 static void set_audiodev(Object *obj, Visitor *v, const char* name, 383 void *opaque, Error **errp) 384 { 385 DeviceState *dev = DEVICE(obj); 386 Property *prop = opaque; 387 QEMUSoundCard *card = qdev_get_prop_ptr(dev, prop); 388 AudioState *state; 389 Error *local_err = NULL; 390 int err = 0; 391 char *str; 392 393 if (dev->realized) { 394 qdev_prop_set_after_realize(dev, name, errp); 395 return; 396 } 397 398 if (!visit_type_str(v, name, &str, &local_err)) { 399 error_propagate(errp, local_err); 400 return; 401 } 402 403 state = audio_state_by_name(str); 404 405 if (!state) { 406 err = -ENOENT; 407 goto out; 408 } 409 card->state = state; 410 411 out: 412 error_set_from_qdev_prop_error(errp, err, dev, prop, str); 413 g_free(str); 414 } 415 416 const PropertyInfo qdev_prop_audiodev = { 417 .name = "str", 418 .description = "ID of an audiodev to use as a backend", 419 /* release done on shutdown */ 420 .get = get_audiodev, 421 .set = set_audiodev, 422 }; 423 424 void qdev_prop_set_drive_err(DeviceState *dev, const char *name, 425 BlockBackend *value, Error **errp) 426 { 427 const char *ref = ""; 428 429 if (value) { 430 ref = blk_name(value); 431 if (!*ref) { 432 const BlockDriverState *bs = blk_bs(value); 433 if (bs) { 434 ref = bdrv_get_node_name(bs); 435 } 436 } 437 } 438 439 object_property_set_str(OBJECT(dev), ref, name, errp); 440 } 441 442 void qdev_prop_set_drive(DeviceState *dev, const char *name, 443 BlockBackend *value) 444 { 445 qdev_prop_set_drive_err(dev, name, value, &error_abort); 446 } 447 448 void qdev_prop_set_chr(DeviceState *dev, const char *name, 449 Chardev *value) 450 { 451 assert(!value || value->label); 452 object_property_set_str(OBJECT(dev), 453 value ? value->label : "", name, &error_abort); 454 } 455 456 void qdev_prop_set_netdev(DeviceState *dev, const char *name, 457 NetClientState *value) 458 { 459 assert(!value || value->name); 460 object_property_set_str(OBJECT(dev), 461 value ? value->name : "", name, &error_abort); 462 } 463 464 void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) 465 { 466 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a); 467 if (nd->netdev) { 468 qdev_prop_set_netdev(dev, "netdev", nd->netdev); 469 } 470 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && 471 object_property_find(OBJECT(dev), "vectors", NULL)) { 472 qdev_prop_set_uint32(dev, "vectors", nd->nvectors); 473 } 474 nd->instantiated = 1; 475 } 476