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