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