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