]> git.proxmox.com Git - qemu.git/blame - hw/qdev-properties.c
qdev: print error message before aborting
[qemu.git] / hw / qdev-properties.c
CommitLineData
1503fff3 1#include "net.h"
ee6847d1 2#include "qdev.h"
9f59b566 3#include "qerror.h"
2446333c 4#include "blockdev.h"
ee6847d1
GH
5
6void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
7{
8 void *ptr = dev;
9 ptr += prop->offset;
10 return ptr;
11}
12
d2364ee4
MT
13static uint32_t qdev_get_prop_mask(Property *prop)
14{
a3d4a1b0 15 assert(prop->info == &qdev_prop_bit);
d2364ee4
MT
16 return 0x1 << prop->bitnr;
17}
18
19static void bit_prop_set(DeviceState *dev, Property *props, bool val)
20{
21 uint32_t *p = qdev_get_prop_ptr(dev, props);
22 uint32_t mask = qdev_get_prop_mask(props);
23 if (val)
dbd48324 24 *p |= mask;
d2364ee4
MT
25 else
26 *p &= ~mask;
27}
28
d2364ee4
MT
29/* Bit */
30static int parse_bit(DeviceState *dev, Property *prop, const char *str)
31{
c455d17c 32 if (!strcasecmp(str, "on"))
d2364ee4 33 bit_prop_set(dev, prop, true);
c455d17c 34 else if (!strcasecmp(str, "off"))
d2364ee4
MT
35 bit_prop_set(dev, prop, false);
36 else
6bf38816 37 return -EINVAL;
d2364ee4
MT
38 return 0;
39}
40
41static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
42{
5a5e3d55 43 uint32_t *p = qdev_get_prop_ptr(dev, prop);
d2364ee4
MT
44 return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
45}
46
57c9fafe 47static void get_bit(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
48 const char *name, Error **errp)
49{
57c9fafe 50 DeviceState *dev = DEVICE(obj);
80e555c2
PB
51 Property *prop = opaque;
52 uint32_t *p = qdev_get_prop_ptr(dev, prop);
53 bool value = (*p & qdev_get_prop_mask(prop)) != 0;
54
55 visit_type_bool(v, &value, name, errp);
56}
57
57c9fafe 58static void set_bit(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
59 const char *name, Error **errp)
60{
57c9fafe 61 DeviceState *dev = DEVICE(obj);
80e555c2
PB
62 Property *prop = opaque;
63 Error *local_err = NULL;
64 bool value;
65
66 if (dev->state != DEV_STATE_CREATED) {
67 error_set(errp, QERR_PERMISSION_DENIED);
68 return;
69 }
70
71 visit_type_bool(v, &value, name, &local_err);
72 if (local_err) {
73 error_propagate(errp, local_err);
74 return;
75 }
76 bit_prop_set(dev, prop, value);
77}
78
d2364ee4 79PropertyInfo qdev_prop_bit = {
cafe5bdb
PB
80 .name = "boolean",
81 .legacy_name = "on/off",
d2364ee4
MT
82 .parse = parse_bit,
83 .print = print_bit,
80e555c2
PB
84 .get = get_bit,
85 .set = set_bit,
d2364ee4
MT
86};
87
c7cc172d
JQ
88/* --- 8bit integer --- */
89
90static int parse_uint8(DeviceState *dev, Property *prop, const char *str)
91{
92 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
449041d4 93 char *end;
c7cc172d
JQ
94
95 /* accept both hex and decimal */
449041d4
KW
96 *ptr = strtoul(str, &end, 0);
97 if ((*end != '\0') || (end == str)) {
6bf38816 98 return -EINVAL;
449041d4
KW
99 }
100
c7cc172d
JQ
101 return 0;
102}
103
104static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len)
105{
106 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
107 return snprintf(dest, len, "%" PRIu8, *ptr);
108}
109
57c9fafe 110static void get_int8(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
111 const char *name, Error **errp)
112{
57c9fafe 113 DeviceState *dev = DEVICE(obj);
80e555c2
PB
114 Property *prop = opaque;
115 int8_t *ptr = qdev_get_prop_ptr(dev, prop);
116 int64_t value;
117
118 value = *ptr;
119 visit_type_int(v, &value, name, errp);
120}
121
57c9fafe
AL
122static void set_int8(Object *obj, Visitor *v, void *opaque,
123 const char *name, Error **errp)
80e555c2 124{
57c9fafe 125 DeviceState *dev = DEVICE(obj);
80e555c2
PB
126 Property *prop = opaque;
127 int8_t *ptr = qdev_get_prop_ptr(dev, prop);
128 Error *local_err = NULL;
129 int64_t value;
130
131 if (dev->state != DEV_STATE_CREATED) {
132 error_set(errp, QERR_PERMISSION_DENIED);
133 return;
134 }
135
136 visit_type_int(v, &value, name, &local_err);
137 if (local_err) {
138 error_propagate(errp, local_err);
139 return;
140 }
6350b090 141 if (value >= prop->info->min && value <= prop->info->max) {
80e555c2
PB
142 *ptr = value;
143 } else {
144 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
145 dev->id?:"", name, value, prop->info->min,
146 prop->info->max);
147 }
148}
149
c7cc172d
JQ
150PropertyInfo qdev_prop_uint8 = {
151 .name = "uint8",
c7cc172d
JQ
152 .parse = parse_uint8,
153 .print = print_uint8,
80e555c2
PB
154 .get = get_int8,
155 .set = set_int8,
156 .min = 0,
157 .max = 255,
c7cc172d
JQ
158};
159
6835678c
JK
160/* --- 8bit hex value --- */
161
162static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
163{
164 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
165 char *end;
166
167 *ptr = strtoul(str, &end, 16);
168 if ((*end != '\0') || (end == str)) {
169 return -EINVAL;
170 }
171
172 return 0;
173}
174
175static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
176{
177 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
178 return snprintf(dest, len, "0x%" PRIx8, *ptr);
179}
180
181PropertyInfo qdev_prop_hex8 = {
cafe5bdb
PB
182 .name = "uint8",
183 .legacy_name = "hex8",
6835678c
JK
184 .parse = parse_hex8,
185 .print = print_hex8,
80e555c2
PB
186 .get = get_int8,
187 .set = set_int8,
188 .min = 0,
189 .max = 255,
6835678c
JK
190};
191
ee6847d1
GH
192/* --- 16bit integer --- */
193
194static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
195{
196 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
449041d4 197 char *end;
ee6847d1
GH
198
199 /* accept both hex and decimal */
449041d4
KW
200 *ptr = strtoul(str, &end, 0);
201 if ((*end != '\0') || (end == str)) {
6bf38816 202 return -EINVAL;
449041d4
KW
203 }
204
ee6847d1
GH
205 return 0;
206}
207
208static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len)
209{
210 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
211 return snprintf(dest, len, "%" PRIu16, *ptr);
212}
213
57c9fafe 214static void get_int16(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
215 const char *name, Error **errp)
216{
57c9fafe 217 DeviceState *dev = DEVICE(obj);
80e555c2
PB
218 Property *prop = opaque;
219 int16_t *ptr = qdev_get_prop_ptr(dev, prop);
220 int64_t value;
221
222 value = *ptr;
223 visit_type_int(v, &value, name, errp);
224}
225
57c9fafe 226static void set_int16(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
227 const char *name, Error **errp)
228{
57c9fafe 229 DeviceState *dev = DEVICE(obj);
80e555c2
PB
230 Property *prop = opaque;
231 int16_t *ptr = qdev_get_prop_ptr(dev, prop);
232 Error *local_err = NULL;
233 int64_t value;
234
235 if (dev->state != DEV_STATE_CREATED) {
236 error_set(errp, QERR_PERMISSION_DENIED);
237 return;
238 }
239
240 visit_type_int(v, &value, name, &local_err);
241 if (local_err) {
242 error_propagate(errp, local_err);
243 return;
244 }
6350b090 245 if (value >= prop->info->min && value <= prop->info->max) {
80e555c2
PB
246 *ptr = value;
247 } else {
248 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
249 dev->id?:"", name, value, prop->info->min,
250 prop->info->max);
251 }
252}
253
ee6847d1
GH
254PropertyInfo qdev_prop_uint16 = {
255 .name = "uint16",
ee6847d1
GH
256 .parse = parse_uint16,
257 .print = print_uint16,
80e555c2
PB
258 .get = get_int16,
259 .set = set_int16,
260 .min = 0,
261 .max = 65535,
ee6847d1
GH
262};
263
264/* --- 32bit integer --- */
265
266static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
267{
268 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
449041d4 269 char *end;
ee6847d1
GH
270
271 /* accept both hex and decimal */
449041d4
KW
272 *ptr = strtoul(str, &end, 0);
273 if ((*end != '\0') || (end == str)) {
6bf38816 274 return -EINVAL;
449041d4
KW
275 }
276
ee6847d1
GH
277 return 0;
278}
279
280static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
281{
282 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
283 return snprintf(dest, len, "%" PRIu32, *ptr);
284}
285
57c9fafe 286static void get_int32(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
287 const char *name, Error **errp)
288{
57c9fafe 289 DeviceState *dev = DEVICE(obj);
80e555c2
PB
290 Property *prop = opaque;
291 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
292 int64_t value;
293
294 value = *ptr;
295 visit_type_int(v, &value, name, errp);
296}
297
57c9fafe 298static void set_int32(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
299 const char *name, Error **errp)
300{
57c9fafe 301 DeviceState *dev = DEVICE(obj);
80e555c2
PB
302 Property *prop = opaque;
303 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
304 Error *local_err = NULL;
305 int64_t value;
306
307 if (dev->state != DEV_STATE_CREATED) {
308 error_set(errp, QERR_PERMISSION_DENIED);
309 return;
310 }
311
312 visit_type_int(v, &value, name, &local_err);
313 if (local_err) {
314 error_propagate(errp, local_err);
315 return;
316 }
6350b090 317 if (value >= prop->info->min && value <= prop->info->max) {
80e555c2
PB
318 *ptr = value;
319 } else {
320 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
321 dev->id?:"", name, value, prop->info->min,
322 prop->info->max);
323 }
324}
325
ee6847d1
GH
326PropertyInfo qdev_prop_uint32 = {
327 .name = "uint32",
ee6847d1
GH
328 .parse = parse_uint32,
329 .print = print_uint32,
80e555c2
PB
330 .get = get_int32,
331 .set = set_int32,
332 .min = 0,
333 .max = 0xFFFFFFFFULL,
ee6847d1
GH
334};
335
316940b0
GH
336static int parse_int32(DeviceState *dev, Property *prop, const char *str)
337{
338 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
449041d4 339 char *end;
316940b0 340
449041d4
KW
341 *ptr = strtol(str, &end, 10);
342 if ((*end != '\0') || (end == str)) {
6bf38816 343 return -EINVAL;
449041d4
KW
344 }
345
316940b0
GH
346 return 0;
347}
348
349static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len)
350{
351 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
352 return snprintf(dest, len, "%" PRId32, *ptr);
353}
354
355PropertyInfo qdev_prop_int32 = {
356 .name = "int32",
316940b0
GH
357 .parse = parse_int32,
358 .print = print_int32,
80e555c2
PB
359 .get = get_int32,
360 .set = set_int32,
361 .min = -0x80000000LL,
362 .max = 0x7FFFFFFFLL,
316940b0
GH
363};
364
ee6847d1
GH
365/* --- 32bit hex value --- */
366
367static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
368{
369 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
449041d4 370 char *end;
ee6847d1 371
449041d4
KW
372 *ptr = strtoul(str, &end, 16);
373 if ((*end != '\0') || (end == str)) {
6bf38816 374 return -EINVAL;
449041d4
KW
375 }
376
ee6847d1
GH
377 return 0;
378}
379
380static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
381{
382 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
383 return snprintf(dest, len, "0x%" PRIx32, *ptr);
384}
385
386PropertyInfo qdev_prop_hex32 = {
cafe5bdb
PB
387 .name = "uint32",
388 .legacy_name = "hex32",
ee6847d1
GH
389 .parse = parse_hex32,
390 .print = print_hex32,
80e555c2
PB
391 .get = get_int32,
392 .set = set_int32,
393 .min = 0,
394 .max = 0xFFFFFFFFULL,
ee6847d1
GH
395};
396
5a053d1f
BS
397/* --- 64bit integer --- */
398
399static int parse_uint64(DeviceState *dev, Property *prop, const char *str)
400{
401 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
449041d4 402 char *end;
5a053d1f
BS
403
404 /* accept both hex and decimal */
449041d4
KW
405 *ptr = strtoull(str, &end, 0);
406 if ((*end != '\0') || (end == str)) {
6bf38816 407 return -EINVAL;
449041d4
KW
408 }
409
5a053d1f
BS
410 return 0;
411}
412
413static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len)
414{
415 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
416 return snprintf(dest, len, "%" PRIu64, *ptr);
417}
418
57c9fafe 419static void get_int64(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
420 const char *name, Error **errp)
421{
57c9fafe 422 DeviceState *dev = DEVICE(obj);
80e555c2
PB
423 Property *prop = opaque;
424 int64_t *ptr = qdev_get_prop_ptr(dev, prop);
425
426 visit_type_int(v, ptr, name, errp);
427}
428
57c9fafe 429static void set_int64(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
430 const char *name, Error **errp)
431{
57c9fafe 432 DeviceState *dev = DEVICE(obj);
80e555c2
PB
433 Property *prop = opaque;
434 int64_t *ptr = qdev_get_prop_ptr(dev, prop);
435
436 if (dev->state != DEV_STATE_CREATED) {
437 error_set(errp, QERR_PERMISSION_DENIED);
438 return;
439 }
440
441 visit_type_int(v, ptr, name, errp);
442}
443
5a053d1f
BS
444PropertyInfo qdev_prop_uint64 = {
445 .name = "uint64",
5a053d1f
BS
446 .parse = parse_uint64,
447 .print = print_uint64,
80e555c2
PB
448 .get = get_int64,
449 .set = set_int64,
5a053d1f
BS
450};
451
452/* --- 64bit hex value --- */
453
454static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
455{
456 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
449041d4 457 char *end;
5a053d1f 458
449041d4
KW
459 *ptr = strtoull(str, &end, 16);
460 if ((*end != '\0') || (end == str)) {
6bf38816 461 return -EINVAL;
449041d4
KW
462 }
463
5a053d1f
BS
464 return 0;
465}
466
467static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
468{
469 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
470 return snprintf(dest, len, "0x%" PRIx64, *ptr);
471}
472
473PropertyInfo qdev_prop_hex64 = {
cafe5bdb
PB
474 .name = "uint64",
475 .legacy_name = "hex64",
5a053d1f
BS
476 .parse = parse_hex64,
477 .print = print_hex64,
80e555c2
PB
478 .get = get_int64,
479 .set = set_int64,
5a053d1f
BS
480};
481
59419663
GH
482/* --- string --- */
483
dd0ba250 484static void release_string(Object *obj, const char *name, void *opaque)
d21357df 485{
dd0ba250
PB
486 Property *prop = opaque;
487 g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
d21357df
MA
488}
489
59419663
GH
490static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
491{
492 char **ptr = qdev_get_prop_ptr(dev, prop);
493 if (!*ptr)
494 return snprintf(dest, len, "<null>");
495 return snprintf(dest, len, "\"%s\"", *ptr);
496}
497
57c9fafe 498static void get_string(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
499 const char *name, Error **errp)
500{
57c9fafe 501 DeviceState *dev = DEVICE(obj);
80e555c2
PB
502 Property *prop = opaque;
503 char **ptr = qdev_get_prop_ptr(dev, prop);
504
505 if (!*ptr) {
506 char *str = (char *)"";
507 visit_type_str(v, &str, name, errp);
508 } else {
509 visit_type_str(v, ptr, name, errp);
510 }
511}
512
57c9fafe 513static void set_string(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
514 const char *name, Error **errp)
515{
57c9fafe 516 DeviceState *dev = DEVICE(obj);
80e555c2
PB
517 Property *prop = opaque;
518 char **ptr = qdev_get_prop_ptr(dev, prop);
519 Error *local_err = NULL;
520 char *str;
521
522 if (dev->state != DEV_STATE_CREATED) {
523 error_set(errp, QERR_PERMISSION_DENIED);
524 return;
525 }
526
527 visit_type_str(v, &str, name, &local_err);
528 if (local_err) {
529 error_propagate(errp, local_err);
530 return;
531 }
532 if (!*str) {
533 g_free(str);
534 str = NULL;
535 }
536 if (*ptr) {
537 g_free(*ptr);
538 }
539 *ptr = str;
540}
541
59419663
GH
542PropertyInfo qdev_prop_string = {
543 .name = "string",
59419663 544 .print = print_string,
dd0ba250 545 .release = release_string,
80e555c2
PB
546 .get = get_string,
547 .set = set_string,
59419663
GH
548};
549
14b41872
GH
550/* --- drive --- */
551
7b009e5d 552static int parse_drive(DeviceState *dev, const char *str, void **ptr)
14b41872 553{
f8b6cc00 554 BlockDriverState *bs;
14b41872 555
f8b6cc00
MA
556 bs = bdrv_find(str);
557 if (bs == NULL)
6bf38816 558 return -ENOENT;
fa879d62 559 if (bdrv_attach_dev(bs, dev) < 0)
18846dee 560 return -EEXIST;
f8b6cc00 561 *ptr = bs;
14b41872
GH
562 return 0;
563}
564
dd0ba250 565static void release_drive(Object *obj, const char *name, void *opaque)
14bafc54 566{
dd0ba250
PB
567 DeviceState *dev = DEVICE(obj);
568 Property *prop = opaque;
f8b6cc00 569 BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
14bafc54
MA
570
571 if (*ptr) {
fa879d62 572 bdrv_detach_dev(*ptr, dev);
f8b6cc00 573 blockdev_auto_del(*ptr);
14bafc54
MA
574 }
575}
576
7b009e5d 577static const char *print_drive(void *ptr)
14b41872 578{
7b009e5d 579 return bdrv_get_device_name(ptr);
14b41872
GH
580}
581
7b009e5d
PB
582static void get_pointer(Object *obj, Visitor *v, Property *prop,
583 const char *(*print)(void *ptr),
584 const char *name, Error **errp)
80e555c2 585{
57c9fafe 586 DeviceState *dev = DEVICE(obj);
80e555c2 587 void **ptr = qdev_get_prop_ptr(dev, prop);
7b009e5d 588 char *p;
80e555c2 589
7b009e5d 590 p = (char *) (*ptr ? print(*ptr) : "");
80e555c2
PB
591 visit_type_str(v, &p, name, errp);
592}
593
7b009e5d
PB
594static void set_pointer(Object *obj, Visitor *v, Property *prop,
595 int (*parse)(DeviceState *dev, const char *str, void **ptr),
80e555c2
PB
596 const char *name, Error **errp)
597{
57c9fafe 598 DeviceState *dev = DEVICE(obj);
80e555c2 599 Error *local_err = NULL;
7b009e5d 600 void **ptr = qdev_get_prop_ptr(dev, prop);
80e555c2
PB
601 char *str;
602 int ret;
603
604 if (dev->state != DEV_STATE_CREATED) {
605 error_set(errp, QERR_PERMISSION_DENIED);
606 return;
607 }
608
609 visit_type_str(v, &str, name, &local_err);
610 if (local_err) {
611 error_propagate(errp, local_err);
612 return;
613 }
614 if (!*str) {
615 g_free(str);
0a54a0ce 616 *ptr = NULL;
80e555c2
PB
617 return;
618 }
7b009e5d 619 ret = parse(dev, str, ptr);
80e555c2
PB
620 error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
621 g_free(str);
622}
623
7b009e5d
PB
624static void get_drive(Object *obj, Visitor *v, void *opaque,
625 const char *name, Error **errp)
626{
627 get_pointer(obj, v, opaque, print_drive, name, errp);
628}
629
630static void set_drive(Object *obj, Visitor *v, void *opaque,
631 const char *name, Error **errp)
632{
633 set_pointer(obj, v, opaque, parse_drive, name, errp);
634}
635
14b41872
GH
636PropertyInfo qdev_prop_drive = {
637 .name = "drive",
7b009e5d
PB
638 .get = get_drive,
639 .set = set_drive,
dd0ba250 640 .release = release_drive,
14b41872
GH
641};
642
313feaab
GH
643/* --- character device --- */
644
7b009e5d 645static int parse_chr(DeviceState *dev, const char *str, void **ptr)
06113719 646{
7b009e5d
PB
647 CharDriverState *chr = qemu_chr_find(str);
648 if (chr == NULL) {
6bf38816 649 return -ENOENT;
2d6c1ef4 650 }
7b009e5d 651 if (chr->avail_connections < 1) {
2d6c1ef4
AS
652 return -EEXIST;
653 }
7b009e5d
PB
654 *ptr = chr;
655 --chr->avail_connections;
06113719
GH
656 return 0;
657}
658
dd0ba250 659static void release_chr(Object *obj, const char *name, void *opaque)
a87f3e8b 660{
dd0ba250
PB
661 DeviceState *dev = DEVICE(obj);
662 Property *prop = opaque;
a87f3e8b
AS
663 CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
664
665 if (*ptr) {
666 qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
667 }
668}
669
670
7b009e5d 671static const char *print_chr(void *ptr)
313feaab 672{
7b009e5d 673 CharDriverState *chr = ptr;
bc19fcaa 674
7b009e5d
PB
675 return chr->label ? chr->label : "";
676}
677
678static void get_chr(Object *obj, Visitor *v, void *opaque,
679 const char *name, Error **errp)
680{
681 get_pointer(obj, v, opaque, print_chr, name, errp);
682}
683
684static void set_chr(Object *obj, Visitor *v, void *opaque,
685 const char *name, Error **errp)
686{
687 set_pointer(obj, v, opaque, parse_chr, name, errp);
313feaab
GH
688}
689
690PropertyInfo qdev_prop_chr = {
691 .name = "chr",
7b009e5d
PB
692 .get = get_chr,
693 .set = set_chr,
dd0ba250 694 .release = release_chr,
313feaab
GH
695};
696
2ef924b4
GH
697/* --- netdev device --- */
698
7b009e5d 699static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
2ef924b4 700{
7b009e5d 701 VLANClientState *netdev = qemu_find_netdev(str);
2ef924b4 702
7b009e5d 703 if (netdev == NULL) {
6bf38816 704 return -ENOENT;
7b009e5d
PB
705 }
706 if (netdev->peer) {
27f3f8a3
MA
707 return -EEXIST;
708 }
7b009e5d 709 *ptr = netdev;
2ef924b4
GH
710 return 0;
711}
712
7b009e5d 713static const char *print_netdev(void *ptr)
2ef924b4 714{
7b009e5d 715 VLANClientState *netdev = ptr;
2ef924b4 716
7b009e5d
PB
717 return netdev->name ? netdev->name : "";
718}
719
720static void get_netdev(Object *obj, Visitor *v, void *opaque,
721 const char *name, Error **errp)
722{
723 get_pointer(obj, v, opaque, print_netdev, name, errp);
724}
725
726static void set_netdev(Object *obj, Visitor *v, void *opaque,
727 const char *name, Error **errp)
728{
729 set_pointer(obj, v, opaque, parse_netdev, name, errp);
2ef924b4
GH
730}
731
732PropertyInfo qdev_prop_netdev = {
733 .name = "netdev",
7b009e5d
PB
734 .get = get_netdev,
735 .set = set_netdev,
2ef924b4
GH
736};
737
851bec09
GH
738/* --- vlan --- */
739
740static int parse_vlan(DeviceState *dev, Property *prop, const char *str)
741{
742 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
743 int id;
744
745 if (sscanf(str, "%d", &id) != 1)
6bf38816 746 return -EINVAL;
851bec09
GH
747 *ptr = qemu_find_vlan(id, 1);
748 if (*ptr == NULL)
6bf38816 749 return -ENOENT;
851bec09
GH
750 return 0;
751}
752
753static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
754{
755 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
756
757 if (*ptr) {
758 return snprintf(dest, len, "%d", (*ptr)->id);
759 } else {
760 return snprintf(dest, len, "<null>");
761 }
762}
763
57c9fafe 764static void get_vlan(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
765 const char *name, Error **errp)
766{
57c9fafe 767 DeviceState *dev = DEVICE(obj);
80e555c2
PB
768 Property *prop = opaque;
769 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
770 int64_t id;
771
772 id = *ptr ? (*ptr)->id : -1;
773 visit_type_int(v, &id, name, errp);
774}
775
57c9fafe 776static void set_vlan(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
777 const char *name, Error **errp)
778{
57c9fafe 779 DeviceState *dev = DEVICE(obj);
80e555c2
PB
780 Property *prop = opaque;
781 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
782 Error *local_err = NULL;
783 int64_t id;
784 VLANState *vlan;
785
786 if (dev->state != DEV_STATE_CREATED) {
787 error_set(errp, QERR_PERMISSION_DENIED);
788 return;
789 }
790
791 visit_type_int(v, &id, name, &local_err);
792 if (local_err) {
793 error_propagate(errp, local_err);
794 return;
795 }
796 if (id == -1) {
797 *ptr = NULL;
798 return;
799 }
800 vlan = qemu_find_vlan(id, 1);
801 if (!vlan) {
802 error_set(errp, QERR_INVALID_PARAMETER_VALUE,
803 name, prop->info->name);
804 return;
805 }
806 *ptr = vlan;
807}
808
851bec09
GH
809PropertyInfo qdev_prop_vlan = {
810 .name = "vlan",
851bec09
GH
811 .parse = parse_vlan,
812 .print = print_vlan,
80e555c2
PB
813 .get = get_vlan,
814 .set = set_vlan,
851bec09
GH
815};
816
ee6847d1
GH
817/* --- pointer --- */
818
036f7166 819/* Not a proper property, just for dirty hacks. TODO Remove it! */
ee6847d1
GH
820PropertyInfo qdev_prop_ptr = {
821 .name = "ptr",
ee6847d1
GH
822};
823
824/* --- mac address --- */
825
826/*
827 * accepted syntax versions:
828 * 01:02:03:04:05:06
829 * 01-02-03-04-05-06
830 */
e39e5d60
PB
831static void get_mac(Object *obj, Visitor *v, void *opaque,
832 const char *name, Error **errp)
ee6847d1 833{
e39e5d60
PB
834 DeviceState *dev = DEVICE(obj);
835 Property *prop = opaque;
1503fff3 836 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
e39e5d60
PB
837 char buffer[2 * 6 + 5 + 1];
838 char *p = buffer;
839
840 snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
841 mac->a[0], mac->a[1], mac->a[2],
842 mac->a[3], mac->a[4], mac->a[5]);
843
844 visit_type_str(v, &p, name, errp);
845}
846
847static void set_mac(Object *obj, Visitor *v, void *opaque,
848 const char *name, Error **errp)
849{
850 DeviceState *dev = DEVICE(obj);
851 Property *prop = opaque;
852 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
853 Error *local_err = NULL;
ee6847d1 854 int i, pos;
e39e5d60
PB
855 char *str, *p;
856
857 if (dev->state != DEV_STATE_CREATED) {
858 error_set(errp, QERR_PERMISSION_DENIED);
859 return;
860 }
861
862 visit_type_str(v, &str, name, &local_err);
863 if (local_err) {
864 error_propagate(errp, local_err);
865 return;
866 }
ee6847d1
GH
867
868 for (i = 0, pos = 0; i < 6; i++, pos += 3) {
88e150a5 869 if (!qemu_isxdigit(str[pos]))
e39e5d60 870 goto inval;
88e150a5 871 if (!qemu_isxdigit(str[pos+1]))
e39e5d60 872 goto inval;
1503fff3
GH
873 if (i == 5) {
874 if (str[pos+2] != '\0')
e39e5d60 875 goto inval;
1503fff3
GH
876 } else {
877 if (str[pos+2] != ':' && str[pos+2] != '-')
e39e5d60 878 goto inval;
1503fff3
GH
879 }
880 mac->a[i] = strtol(str+pos, &p, 16);
ee6847d1 881 }
e39e5d60 882 return;
1503fff3 883
e39e5d60
PB
884inval:
885 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
ee6847d1
GH
886}
887
888PropertyInfo qdev_prop_macaddr = {
1503fff3 889 .name = "macaddr",
e39e5d60
PB
890 .get = get_mac,
891 .set = set_mac,
ee6847d1
GH
892};
893
4e4fa398
JK
894
895/* --- lost tick policy --- */
896
1ce05125
PB
897static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
898 [LOST_TICK_DISCARD] = "discard",
899 [LOST_TICK_DELAY] = "delay",
900 [LOST_TICK_MERGE] = "merge",
901 [LOST_TICK_SLEW] = "slew",
902 [LOST_TICK_MAX] = NULL,
4e4fa398
JK
903};
904
1ce05125
PB
905QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
906
907static void get_enum(Object *obj, Visitor *v, void *opaque,
908 const char *name, Error **errp)
4e4fa398 909{
1ce05125
PB
910 DeviceState *dev = DEVICE(obj);
911 Property *prop = opaque;
912 int *ptr = qdev_get_prop_ptr(dev, prop);
4e4fa398 913
1ce05125
PB
914 visit_type_enum(v, ptr, prop->info->enum_table,
915 prop->info->name, prop->name, errp);
4e4fa398
JK
916}
917
1ce05125
PB
918static void set_enum(Object *obj, Visitor *v, void *opaque,
919 const char *name, Error **errp)
4e4fa398 920{
1ce05125
PB
921 DeviceState *dev = DEVICE(obj);
922 Property *prop = opaque;
923 int *ptr = qdev_get_prop_ptr(dev, prop);
4e4fa398 924
1ce05125
PB
925 if (dev->state != DEV_STATE_CREATED) {
926 error_set(errp, QERR_PERMISSION_DENIED);
927 return;
928 }
929
930 visit_type_enum(v, ptr, prop->info->enum_table,
931 prop->info->name, prop->name, errp);
4e4fa398
JK
932}
933
934PropertyInfo qdev_prop_losttickpolicy = {
1ce05125 935 .name = "LostTickPolicy",
1ce05125
PB
936 .enum_table = lost_tick_policy_table,
937 .get = get_enum,
938 .set = set_enum,
4e4fa398
JK
939};
940
05cb5fe4
GH
941/* --- pci address --- */
942
943/*
944 * bus-local address, i.e. "$slot" or "$slot.$fn"
945 */
946static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str)
947{
948 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
949 unsigned int slot, fn, n;
950
951 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
952 fn = 0;
953 if (sscanf(str, "%x%n", &slot, &n) != 1) {
6bf38816 954 return -EINVAL;
05cb5fe4
GH
955 }
956 }
957 if (str[n] != '\0')
6bf38816 958 return -EINVAL;
05cb5fe4 959 if (fn > 7)
6bf38816 960 return -EINVAL;
ffe3ce11
DD
961 if (slot > 31)
962 return -EINVAL;
05cb5fe4
GH
963 *ptr = slot << 3 | fn;
964 return 0;
965}
966
967static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
968{
969 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
970
73538c31 971 if (*ptr == -1) {
05cb5fe4
GH
972 return snprintf(dest, len, "<unset>");
973 } else {
974 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
975 }
976}
977
978PropertyInfo qdev_prop_pci_devfn = {
b403298a
PB
979 .name = "int32",
980 .legacy_name = "pci-devfn",
05cb5fe4
GH
981 .parse = parse_pci_devfn,
982 .print = print_pci_devfn,
b403298a
PB
983 .get = get_int32,
984 .set = set_int32,
985 /* FIXME: this should be -1...255, but the address is stored
986 * into an uint32_t rather than int32_t.
987 */
988 .min = 0,
989 .max = 0xFFFFFFFFULL,
05cb5fe4
GH
990};
991
ee6847d1
GH
992/* --- public helpers --- */
993
994static Property *qdev_prop_walk(Property *props, const char *name)
995{
996 if (!props)
997 return NULL;
998 while (props->name) {
999 if (strcmp(props->name, name) == 0)
1000 return props;
1001 props++;
1002 }
1003 return NULL;
1004}
1005
1006static Property *qdev_prop_find(DeviceState *dev, const char *name)
1007{
1008 Property *prop;
1009
1010 /* device properties */
4be9f0d1 1011 prop = qdev_prop_walk(qdev_get_props(dev), name);
ee6847d1
GH
1012 if (prop)
1013 return prop;
1014
1015 /* bus properties */
1016 prop = qdev_prop_walk(dev->parent_bus->info->props, name);
1017 if (prop)
1018 return prop;
1019
1020 return NULL;
1021}
1022
d8ed79ae
GH
1023int qdev_prop_exists(DeviceState *dev, const char *name)
1024{
1025 return qdev_prop_find(dev, name) ? true : false;
1026}
1027
7db4c4e8
PB
1028void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
1029 Property *prop, const char *value)
1030{
1031 switch (ret) {
1032 case -EEXIST:
1033 error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
f79f2bfc 1034 object_get_typename(OBJECT(dev)), prop->name, value);
7db4c4e8
PB
1035 break;
1036 default:
1037 case -EINVAL:
1038 error_set(errp, QERR_PROPERTY_VALUE_BAD,
f79f2bfc 1039 object_get_typename(OBJECT(dev)), prop->name, value);
7db4c4e8
PB
1040 break;
1041 case -ENOENT:
1042 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
f79f2bfc 1043 object_get_typename(OBJECT(dev)), prop->name, value);
7db4c4e8
PB
1044 break;
1045 case 0:
1046 break;
1047 }
1048}
1049
ee6847d1
GH
1050int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
1051{
d822979b
PB
1052 char *legacy_name;
1053 Error *err = NULL;
ee6847d1 1054
d822979b
PB
1055 legacy_name = g_strdup_printf("legacy-%s", name);
1056 if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
1057 object_property_set_str(OBJECT(dev), value, legacy_name, &err);
1058 } else {
1059 object_property_set_str(OBJECT(dev), value, name, &err);
ee6847d1 1060 }
d822979b
PB
1061 g_free(legacy_name);
1062
1063 if (err) {
7db4c4e8
PB
1064 qerror_report_err(err);
1065 error_free(err);
9ef5c4bf
GH
1066 return -1;
1067 }
1068 return 0;
ee6847d1
GH
1069}
1070
f4594a3b
IY
1071void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
1072{
9b170e60
PB
1073 Error *errp = NULL;
1074 object_property_set_bool(OBJECT(dev), value, name, &errp);
59f971d4 1075 assert_no_error(errp);
f4594a3b
IY
1076}
1077
c7cc172d
JQ
1078void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
1079{
9b170e60
PB
1080 Error *errp = NULL;
1081 object_property_set_int(OBJECT(dev), value, name, &errp);
59f971d4 1082 assert_no_error(errp);
c7cc172d
JQ
1083}
1084
ee6847d1
GH
1085void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
1086{
9b170e60
PB
1087 Error *errp = NULL;
1088 object_property_set_int(OBJECT(dev), value, name, &errp);
59f971d4 1089 assert_no_error(errp);
ee6847d1
GH
1090}
1091
1092void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
1093{
9b170e60
PB
1094 Error *errp = NULL;
1095 object_property_set_int(OBJECT(dev), value, name, &errp);
59f971d4 1096 assert_no_error(errp);
ee6847d1
GH
1097}
1098
316940b0
GH
1099void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1100{
9b170e60
PB
1101 Error *errp = NULL;
1102 object_property_set_int(OBJECT(dev), value, name, &errp);
59f971d4 1103 assert_no_error(errp);
316940b0
GH
1104}
1105
5a053d1f
BS
1106void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1107{
9b170e60
PB
1108 Error *errp = NULL;
1109 object_property_set_int(OBJECT(dev), value, name, &errp);
59f971d4 1110 assert_no_error(errp);
5a053d1f
BS
1111}
1112
cc984673
MA
1113void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
1114{
9b170e60
PB
1115 Error *errp = NULL;
1116 object_property_set_str(OBJECT(dev), value, name, &errp);
59f971d4 1117 assert_no_error(errp);
cc984673
MA
1118}
1119
18846dee 1120int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
14b41872 1121{
9b170e60 1122 Error *errp = NULL;
0a54a0ce
PB
1123 const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
1124 object_property_set_str(OBJECT(dev), bdrv_name,
9b170e60
PB
1125 name, &errp);
1126 if (errp) {
1127 qerror_report_err(errp);
1128 error_free(errp);
18846dee
MA
1129 return -1;
1130 }
18846dee 1131 return 0;
14b41872
GH
1132}
1133
18846dee
MA
1134void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
1135{
1136 if (qdev_prop_set_drive(dev, name, value) < 0) {
1137 exit(1);
1138 }
1139}
313feaab
GH
1140void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
1141{
9b170e60 1142 Error *errp = NULL;
0a54a0ce
PB
1143 assert(!value || value->label);
1144 object_property_set_str(OBJECT(dev),
1145 value ? value->label : "", name, &errp);
59f971d4 1146 assert_no_error(errp);
313feaab
GH
1147}
1148
2ef924b4
GH
1149void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
1150{
9b170e60 1151 Error *errp = NULL;
0a54a0ce
PB
1152 assert(!value || value->name);
1153 object_property_set_str(OBJECT(dev),
1154 value ? value->name : "", name, &errp);
59f971d4 1155 assert_no_error(errp);
2ef924b4
GH
1156}
1157
851bec09
GH
1158void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
1159{
9b170e60
PB
1160 Error *errp = NULL;
1161 object_property_set_int(OBJECT(dev), value ? value->id : -1, name, &errp);
59f971d4 1162 assert_no_error(errp);
851bec09
GH
1163}
1164
1503fff3
GH
1165void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1166{
9b170e60
PB
1167 Error *errp = NULL;
1168 char str[2 * 6 + 5 + 1];
1169 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
1170 value[0], value[1], value[2], value[3], value[4], value[5]);
1171
1172 object_property_set_str(OBJECT(dev), str, name, &errp);
59f971d4 1173 assert_no_error(errp);
1503fff3
GH
1174}
1175
9b170e60 1176void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
4e4fa398 1177{
9b170e60
PB
1178 Property *prop;
1179 Error *errp = NULL;
1180
1181 prop = qdev_prop_find(dev, name);
1182 object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1183 name, &errp);
59f971d4 1184 assert_no_error(errp);
4e4fa398
JK
1185}
1186
ee6847d1
GH
1187void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1188{
7a7aae21
PB
1189 Property *prop;
1190 void **ptr;
1191
1192 prop = qdev_prop_find(dev, name);
1193 assert(prop && prop->info == &qdev_prop_ptr);
1194 ptr = qdev_get_prop_ptr(dev, prop);
1195 *ptr = value;
ee6847d1
GH
1196}
1197
1198void qdev_prop_set_defaults(DeviceState *dev, Property *props)
1199{
4f2d3d70 1200 Object *obj = OBJECT(dev);
ee6847d1
GH
1201 if (!props)
1202 return;
4f2d3d70
PB
1203 for (; props->name; props++) {
1204 Error *errp = NULL;
1205 if (props->qtype == QTYPE_NONE) {
1206 continue;
ee6847d1 1207 }
4f2d3d70
PB
1208 if (props->qtype == QTYPE_QBOOL) {
1209 object_property_set_bool(obj, props->defval, props->name, &errp);
1210 } else if (props->info->enum_table) {
1211 object_property_set_str(obj, props->info->enum_table[props->defval],
1212 props->name, &errp);
1213 } else if (props->qtype == QTYPE_QINT) {
1214 object_property_set_int(obj, props->defval, props->name, &errp);
1215 }
59f971d4 1216 assert_no_error(errp);
ee6847d1
GH
1217 }
1218}
1219
458fb679 1220static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
b6b61144 1221
25920d6a 1222static void qdev_prop_register_global(GlobalProperty *prop)
b6b61144 1223{
458fb679 1224 QTAILQ_INSERT_TAIL(&global_props, prop, next);
b6b61144
GH
1225}
1226
458fb679 1227void qdev_prop_register_global_list(GlobalProperty *props)
b6b61144 1228{
458fb679 1229 int i;
b6b61144 1230
458fb679
GH
1231 for (i = 0; props[i].driver != NULL; i++) {
1232 qdev_prop_register_global(props+i);
b6b61144 1233 }
458fb679
GH
1234}
1235
1236void qdev_prop_set_globals(DeviceState *dev)
1237{
1238 GlobalProperty *prop;
1239
1240 QTAILQ_FOREACH(prop, &global_props, next) {
f79f2bfc 1241 if (strcmp(object_get_typename(OBJECT(dev)), prop->driver) != 0 &&
4be9f0d1 1242 strcmp(qdev_get_bus_info(dev)->name, prop->driver) != 0) {
b6b61144
GH
1243 continue;
1244 }
1245 if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
9ef5c4bf 1246 exit(1);
b6b61144
GH
1247 }
1248 }
1249}
25920d6a
KW
1250
1251static int qdev_add_one_global(QemuOpts *opts, void *opaque)
1252{
1253 GlobalProperty *g;
1254
7267c094 1255 g = g_malloc0(sizeof(*g));
25920d6a
KW
1256 g->driver = qemu_opt_get(opts, "driver");
1257 g->property = qemu_opt_get(opts, "property");
1258 g->value = qemu_opt_get(opts, "value");
1259 qdev_prop_register_global(g);
1260 return 0;
1261}
1262
1263void qemu_add_globals(void)
1264{
3329f07b 1265 qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
25920d6a 1266}