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