]> git.proxmox.com Git - qemu.git/blob - hw/qdev-properties.c
Merge remote-tracking branch 'amit/loadvm-irq-inj-fix' into staging
[qemu.git] / hw / qdev-properties.c
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
9 void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
10 {
11 void *ptr = dev;
12 ptr += prop->offset;
13 return ptr;
14 }
15
16 static 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
28 static 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
59 static 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
70 static 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 /* Bit */
87
88 static uint32_t qdev_get_prop_mask(Property *prop)
89 {
90 assert(prop->info == &qdev_prop_bit);
91 return 0x1 << prop->bitnr;
92 }
93
94 static 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
104 static 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
110 static 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
121 static 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
142 PropertyInfo 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 /* --- 8bit integer --- */
151
152 static 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
162 static 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
177 PropertyInfo qdev_prop_uint8 = {
178 .name = "uint8",
179 .get = get_uint8,
180 .set = set_uint8,
181 };
182
183 /* --- 8bit hex value --- */
184
185 static 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
202 static 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
208 PropertyInfo 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 /* --- 16bit integer --- */
218
219 static 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
229 static 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
244 PropertyInfo qdev_prop_uint16 = {
245 .name = "uint16",
246 .get = get_uint16,
247 .set = set_uint16,
248 };
249
250 /* --- 32bit integer --- */
251
252 static 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
262 static 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
277 static 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
287 static 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
302 PropertyInfo qdev_prop_uint32 = {
303 .name = "uint32",
304 .get = get_uint32,
305 .set = set_uint32,
306 };
307
308 PropertyInfo qdev_prop_int32 = {
309 .name = "int32",
310 .get = get_int32,
311 .set = set_int32,
312 };
313
314 /* --- 32bit hex value --- */
315
316 static 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
333 static 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
339 PropertyInfo 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 /* --- 64bit integer --- */
349
350 static 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
360 static 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
375 PropertyInfo qdev_prop_uint64 = {
376 .name = "uint64",
377 .get = get_uint64,
378 .set = set_uint64,
379 };
380
381 /* --- 64bit hex value --- */
382
383 static 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
400 static 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
406 PropertyInfo 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 /* --- string --- */
416
417 static 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
423 static 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
431 static 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
446 static 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
471 PropertyInfo 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 /* --- drive --- */
480
481 static 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
494 static 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
506 static const char *print_drive(void *ptr)
507 {
508 return bdrv_get_device_name(ptr);
509 }
510
511 static 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
517 static 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
523 PropertyInfo qdev_prop_drive = {
524 .name = "drive",
525 .get = get_drive,
526 .set = set_drive,
527 .release = release_drive,
528 };
529
530 /* --- character device --- */
531
532 static 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
546 static 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
558 static const char *print_chr(void *ptr)
559 {
560 CharDriverState *chr = ptr;
561
562 return chr->label ? chr->label : "";
563 }
564
565 static 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
571 static 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
577 PropertyInfo qdev_prop_chr = {
578 .name = "chr",
579 .get = get_chr,
580 .set = set_chr,
581 .release = release_chr,
582 };
583
584 /* --- netdev device --- */
585
586 static 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
600 static const char *print_netdev(void *ptr)
601 {
602 NetClientState *netdev = ptr;
603
604 return netdev->name ? netdev->name : "";
605 }
606
607 static 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
613 static 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
619 PropertyInfo qdev_prop_netdev = {
620 .name = "netdev",
621 .get = get_netdev,
622 .set = set_netdev,
623 };
624
625 /* --- vlan --- */
626
627 static 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
641 static 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
659 static 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
693 PropertyInfo qdev_prop_vlan = {
694 .name = "vlan",
695 .print = print_vlan,
696 .get = get_vlan,
697 .set = set_vlan,
698 };
699
700 /* --- pointer --- */
701
702 /* Not a proper property, just for dirty hacks. TODO Remove it! */
703 PropertyInfo qdev_prop_ptr = {
704 .name = "ptr",
705 };
706
707 /* --- mac address --- */
708
709 /*
710 * accepted syntax versions:
711 * 01:02:03:04:05:06
712 * 01-02-03-04-05-06
713 */
714 static 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
730 static 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
768 inval:
769 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
770 g_free(str);
771 }
772
773 PropertyInfo qdev_prop_macaddr = {
774 .name = "macaddr",
775 .get = get_mac,
776 .set = set_mac,
777 };
778
779 /* --- lost tick policy --- */
780
781 static 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
789 QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
790
791 PropertyInfo qdev_prop_losttickpolicy = {
792 .name = "LostTickPolicy",
793 .enum_table = lost_tick_policy_table,
794 .get = get_enum,
795 .set = set_enum,
796 };
797
798 /* --- BIOS CHS translation */
799
800 static 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
806 PropertyInfo 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 /* --- pci address --- */
814
815 /*
816 * bus-local address, i.e. "$slot" or "$slot.$fn"
817 */
818 static 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
862 invalid:
863 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
864 g_free(str);
865 }
866
867 static 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
878 PropertyInfo 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 /* --- blocksize --- */
887
888 static 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 /* We rely on power-of-2 blocksizes for bitmasks */
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
924 PropertyInfo qdev_prop_blocksize = {
925 .name = "blocksize",
926 .get = get_uint16,
927 .set = set_blocksize,
928 };
929
930 /* --- pci host address --- */
931
932 static 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 * Parse [<domain>:]<bus>:<slot>.<func>
951 * if <domain> is not supplied, it's assumed to be 0.
952 */
953 static 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
1026 inval:
1027 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
1028 g_free(str);
1029 }
1030
1031 PropertyInfo 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 /* --- public helpers --- */
1038
1039 static 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
1051 static Property *qdev_prop_find(DeviceState *dev, const char *name)
1052 {
1053 ObjectClass *class;
1054 Property *prop;
1055
1056 /* device properties */
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
1069 void 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
1091 int 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
1112 void 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
1119 void 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
1126 void 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
1133 void 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
1140 void 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
1147 void 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
1154 void 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
1161 int 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
1175 void 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 }
1181 void 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
1190 void 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
1199 void 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
1210 void 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
1221 void 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
1232 static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
1233
1234 static void qdev_prop_register_global(GlobalProperty *prop)
1235 {
1236 QTAILQ_INSERT_TAIL(&global_props, prop, next);
1237 }
1238
1239 void 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
1248 void 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
1266 static 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
1278 void qemu_add_globals(void)
1279 {
1280 qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
1281 }