]> git.proxmox.com Git - qemu.git/blob - hw/qdev-properties.c
qdev-properties.c: Separate core from the code used only by qemu-system-*
[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_enum(Object *obj, Visitor *v, void *opaque,
17 const char *name, Error **errp)
18 {
19 DeviceState *dev = DEVICE(obj);
20 Property *prop = opaque;
21 int *ptr = qdev_get_prop_ptr(dev, prop);
22
23 visit_type_enum(v, ptr, prop->info->enum_table,
24 prop->info->name, prop->name, errp);
25 }
26
27 static void set_enum(Object *obj, Visitor *v, void *opaque,
28 const char *name, Error **errp)
29 {
30 DeviceState *dev = DEVICE(obj);
31 Property *prop = opaque;
32 int *ptr = qdev_get_prop_ptr(dev, prop);
33
34 if (dev->state != DEV_STATE_CREATED) {
35 error_set(errp, QERR_PERMISSION_DENIED);
36 return;
37 }
38
39 visit_type_enum(v, ptr, prop->info->enum_table,
40 prop->info->name, prop->name, errp);
41 }
42
43 /* Bit */
44
45 static uint32_t qdev_get_prop_mask(Property *prop)
46 {
47 assert(prop->info == &qdev_prop_bit);
48 return 0x1 << prop->bitnr;
49 }
50
51 static void bit_prop_set(DeviceState *dev, Property *props, bool val)
52 {
53 uint32_t *p = qdev_get_prop_ptr(dev, props);
54 uint32_t mask = qdev_get_prop_mask(props);
55 if (val) {
56 *p |= mask;
57 } else {
58 *p &= ~mask;
59 }
60 }
61
62 static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
63 {
64 uint32_t *p = qdev_get_prop_ptr(dev, prop);
65 return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
66 }
67
68 static void get_bit(Object *obj, Visitor *v, void *opaque,
69 const char *name, Error **errp)
70 {
71 DeviceState *dev = DEVICE(obj);
72 Property *prop = opaque;
73 uint32_t *p = qdev_get_prop_ptr(dev, prop);
74 bool value = (*p & qdev_get_prop_mask(prop)) != 0;
75
76 visit_type_bool(v, &value, name, errp);
77 }
78
79 static void set_bit(Object *obj, Visitor *v, void *opaque,
80 const char *name, Error **errp)
81 {
82 DeviceState *dev = DEVICE(obj);
83 Property *prop = opaque;
84 Error *local_err = NULL;
85 bool value;
86
87 if (dev->state != DEV_STATE_CREATED) {
88 error_set(errp, QERR_PERMISSION_DENIED);
89 return;
90 }
91
92 visit_type_bool(v, &value, name, &local_err);
93 if (local_err) {
94 error_propagate(errp, local_err);
95 return;
96 }
97 bit_prop_set(dev, prop, value);
98 }
99
100 PropertyInfo qdev_prop_bit = {
101 .name = "boolean",
102 .legacy_name = "on/off",
103 .print = print_bit,
104 .get = get_bit,
105 .set = set_bit,
106 };
107
108 /* --- 8bit integer --- */
109
110 static void get_uint8(Object *obj, Visitor *v, void *opaque,
111 const char *name, Error **errp)
112 {
113 DeviceState *dev = DEVICE(obj);
114 Property *prop = opaque;
115 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
116
117 visit_type_uint8(v, ptr, name, errp);
118 }
119
120 static void set_uint8(Object *obj, Visitor *v, void *opaque,
121 const char *name, Error **errp)
122 {
123 DeviceState *dev = DEVICE(obj);
124 Property *prop = opaque;
125 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
126
127 if (dev->state != DEV_STATE_CREATED) {
128 error_set(errp, QERR_PERMISSION_DENIED);
129 return;
130 }
131
132 visit_type_uint8(v, ptr, name, errp);
133 }
134
135 PropertyInfo qdev_prop_uint8 = {
136 .name = "uint8",
137 .get = get_uint8,
138 .set = set_uint8,
139 };
140
141 /* --- 8bit hex value --- */
142
143 static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
144 {
145 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
146 char *end;
147
148 if (str[0] != '0' || str[1] != 'x') {
149 return -EINVAL;
150 }
151
152 *ptr = strtoul(str, &end, 16);
153 if ((*end != '\0') || (end == str)) {
154 return -EINVAL;
155 }
156
157 return 0;
158 }
159
160 static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
161 {
162 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
163 return snprintf(dest, len, "0x%" PRIx8, *ptr);
164 }
165
166 PropertyInfo qdev_prop_hex8 = {
167 .name = "uint8",
168 .legacy_name = "hex8",
169 .parse = parse_hex8,
170 .print = print_hex8,
171 .get = get_uint8,
172 .set = set_uint8,
173 };
174
175 /* --- 16bit integer --- */
176
177 static void get_uint16(Object *obj, Visitor *v, void *opaque,
178 const char *name, Error **errp)
179 {
180 DeviceState *dev = DEVICE(obj);
181 Property *prop = opaque;
182 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
183
184 visit_type_uint16(v, ptr, name, errp);
185 }
186
187 static void set_uint16(Object *obj, Visitor *v, void *opaque,
188 const char *name, Error **errp)
189 {
190 DeviceState *dev = DEVICE(obj);
191 Property *prop = opaque;
192 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
193
194 if (dev->state != DEV_STATE_CREATED) {
195 error_set(errp, QERR_PERMISSION_DENIED);
196 return;
197 }
198
199 visit_type_uint16(v, ptr, name, errp);
200 }
201
202 PropertyInfo qdev_prop_uint16 = {
203 .name = "uint16",
204 .get = get_uint16,
205 .set = set_uint16,
206 };
207
208 /* --- 32bit integer --- */
209
210 static void get_uint32(Object *obj, Visitor *v, void *opaque,
211 const char *name, Error **errp)
212 {
213 DeviceState *dev = DEVICE(obj);
214 Property *prop = opaque;
215 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
216
217 visit_type_uint32(v, ptr, name, errp);
218 }
219
220 static void set_uint32(Object *obj, Visitor *v, void *opaque,
221 const char *name, Error **errp)
222 {
223 DeviceState *dev = DEVICE(obj);
224 Property *prop = opaque;
225 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
226
227 if (dev->state != DEV_STATE_CREATED) {
228 error_set(errp, QERR_PERMISSION_DENIED);
229 return;
230 }
231
232 visit_type_uint32(v, ptr, name, errp);
233 }
234
235 static void get_int32(Object *obj, Visitor *v, void *opaque,
236 const char *name, Error **errp)
237 {
238 DeviceState *dev = DEVICE(obj);
239 Property *prop = opaque;
240 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
241
242 visit_type_int32(v, ptr, name, errp);
243 }
244
245 static void set_int32(Object *obj, Visitor *v, void *opaque,
246 const char *name, Error **errp)
247 {
248 DeviceState *dev = DEVICE(obj);
249 Property *prop = opaque;
250 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
251
252 if (dev->state != DEV_STATE_CREATED) {
253 error_set(errp, QERR_PERMISSION_DENIED);
254 return;
255 }
256
257 visit_type_int32(v, ptr, name, errp);
258 }
259
260 PropertyInfo qdev_prop_uint32 = {
261 .name = "uint32",
262 .get = get_uint32,
263 .set = set_uint32,
264 };
265
266 PropertyInfo qdev_prop_int32 = {
267 .name = "int32",
268 .get = get_int32,
269 .set = set_int32,
270 };
271
272 /* --- 32bit hex value --- */
273
274 static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
275 {
276 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
277 char *end;
278
279 if (str[0] != '0' || str[1] != 'x') {
280 return -EINVAL;
281 }
282
283 *ptr = strtoul(str, &end, 16);
284 if ((*end != '\0') || (end == str)) {
285 return -EINVAL;
286 }
287
288 return 0;
289 }
290
291 static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
292 {
293 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
294 return snprintf(dest, len, "0x%" PRIx32, *ptr);
295 }
296
297 PropertyInfo qdev_prop_hex32 = {
298 .name = "uint32",
299 .legacy_name = "hex32",
300 .parse = parse_hex32,
301 .print = print_hex32,
302 .get = get_uint32,
303 .set = set_uint32,
304 };
305
306 /* --- 64bit integer --- */
307
308 static void get_uint64(Object *obj, Visitor *v, void *opaque,
309 const char *name, Error **errp)
310 {
311 DeviceState *dev = DEVICE(obj);
312 Property *prop = opaque;
313 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
314
315 visit_type_uint64(v, ptr, name, errp);
316 }
317
318 static void set_uint64(Object *obj, Visitor *v, void *opaque,
319 const char *name, Error **errp)
320 {
321 DeviceState *dev = DEVICE(obj);
322 Property *prop = opaque;
323 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
324
325 if (dev->state != DEV_STATE_CREATED) {
326 error_set(errp, QERR_PERMISSION_DENIED);
327 return;
328 }
329
330 visit_type_uint64(v, ptr, name, errp);
331 }
332
333 PropertyInfo qdev_prop_uint64 = {
334 .name = "uint64",
335 .get = get_uint64,
336 .set = set_uint64,
337 };
338
339 /* --- 64bit hex value --- */
340
341 static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
342 {
343 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
344 char *end;
345
346 if (str[0] != '0' || str[1] != 'x') {
347 return -EINVAL;
348 }
349
350 *ptr = strtoull(str, &end, 16);
351 if ((*end != '\0') || (end == str)) {
352 return -EINVAL;
353 }
354
355 return 0;
356 }
357
358 static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
359 {
360 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
361 return snprintf(dest, len, "0x%" PRIx64, *ptr);
362 }
363
364 PropertyInfo qdev_prop_hex64 = {
365 .name = "uint64",
366 .legacy_name = "hex64",
367 .parse = parse_hex64,
368 .print = print_hex64,
369 .get = get_uint64,
370 .set = set_uint64,
371 };
372
373 /* --- string --- */
374
375 static void release_string(Object *obj, const char *name, void *opaque)
376 {
377 Property *prop = opaque;
378 g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
379 }
380
381 static int print_string(DeviceState *dev, Property *prop, char *dest,
382 size_t len)
383 {
384 char **ptr = qdev_get_prop_ptr(dev, prop);
385 if (!*ptr) {
386 return snprintf(dest, len, "<null>");
387 }
388 return snprintf(dest, len, "\"%s\"", *ptr);
389 }
390
391 static void get_string(Object *obj, Visitor *v, void *opaque,
392 const char *name, Error **errp)
393 {
394 DeviceState *dev = DEVICE(obj);
395 Property *prop = opaque;
396 char **ptr = qdev_get_prop_ptr(dev, prop);
397
398 if (!*ptr) {
399 char *str = (char *)"";
400 visit_type_str(v, &str, name, errp);
401 } else {
402 visit_type_str(v, ptr, name, errp);
403 }
404 }
405
406 static void set_string(Object *obj, Visitor *v, void *opaque,
407 const char *name, Error **errp)
408 {
409 DeviceState *dev = DEVICE(obj);
410 Property *prop = opaque;
411 char **ptr = qdev_get_prop_ptr(dev, prop);
412 Error *local_err = NULL;
413 char *str;
414
415 if (dev->state != DEV_STATE_CREATED) {
416 error_set(errp, QERR_PERMISSION_DENIED);
417 return;
418 }
419
420 visit_type_str(v, &str, name, &local_err);
421 if (local_err) {
422 error_propagate(errp, local_err);
423 return;
424 }
425 if (*ptr) {
426 g_free(*ptr);
427 }
428 *ptr = str;
429 }
430
431 PropertyInfo qdev_prop_string = {
432 .name = "string",
433 .print = print_string,
434 .release = release_string,
435 .get = get_string,
436 .set = set_string,
437 };
438
439 /* --- pointer --- */
440
441 /* Not a proper property, just for dirty hacks. TODO Remove it! */
442 PropertyInfo qdev_prop_ptr = {
443 .name = "ptr",
444 };
445
446 /* --- mac address --- */
447
448 /*
449 * accepted syntax versions:
450 * 01:02:03:04:05:06
451 * 01-02-03-04-05-06
452 */
453 static void get_mac(Object *obj, Visitor *v, void *opaque,
454 const char *name, Error **errp)
455 {
456 DeviceState *dev = DEVICE(obj);
457 Property *prop = opaque;
458 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
459 char buffer[2 * 6 + 5 + 1];
460 char *p = buffer;
461
462 snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
463 mac->a[0], mac->a[1], mac->a[2],
464 mac->a[3], mac->a[4], mac->a[5]);
465
466 visit_type_str(v, &p, name, errp);
467 }
468
469 static void set_mac(Object *obj, Visitor *v, void *opaque,
470 const char *name, Error **errp)
471 {
472 DeviceState *dev = DEVICE(obj);
473 Property *prop = opaque;
474 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
475 Error *local_err = NULL;
476 int i, pos;
477 char *str, *p;
478
479 if (dev->state != DEV_STATE_CREATED) {
480 error_set(errp, QERR_PERMISSION_DENIED);
481 return;
482 }
483
484 visit_type_str(v, &str, name, &local_err);
485 if (local_err) {
486 error_propagate(errp, local_err);
487 return;
488 }
489
490 for (i = 0, pos = 0; i < 6; i++, pos += 3) {
491 if (!qemu_isxdigit(str[pos])) {
492 goto inval;
493 }
494 if (!qemu_isxdigit(str[pos+1])) {
495 goto inval;
496 }
497 if (i == 5) {
498 if (str[pos+2] != '\0') {
499 goto inval;
500 }
501 } else {
502 if (str[pos+2] != ':' && str[pos+2] != '-') {
503 goto inval;
504 }
505 }
506 mac->a[i] = strtol(str+pos, &p, 16);
507 }
508 g_free(str);
509 return;
510
511 inval:
512 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
513 g_free(str);
514 }
515
516 PropertyInfo qdev_prop_macaddr = {
517 .name = "macaddr",
518 .get = get_mac,
519 .set = set_mac,
520 };
521
522 /* --- lost tick policy --- */
523
524 static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
525 [LOST_TICK_DISCARD] = "discard",
526 [LOST_TICK_DELAY] = "delay",
527 [LOST_TICK_MERGE] = "merge",
528 [LOST_TICK_SLEW] = "slew",
529 [LOST_TICK_MAX] = NULL,
530 };
531
532 QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
533
534 PropertyInfo qdev_prop_losttickpolicy = {
535 .name = "LostTickPolicy",
536 .enum_table = lost_tick_policy_table,
537 .get = get_enum,
538 .set = set_enum,
539 };
540
541 /* --- BIOS CHS translation */
542
543 static const char *bios_chs_trans_table[] = {
544 [BIOS_ATA_TRANSLATION_AUTO] = "auto",
545 [BIOS_ATA_TRANSLATION_NONE] = "none",
546 [BIOS_ATA_TRANSLATION_LBA] = "lba",
547 };
548
549 PropertyInfo qdev_prop_bios_chs_trans = {
550 .name = "bios-chs-trans",
551 .enum_table = bios_chs_trans_table,
552 .get = get_enum,
553 .set = set_enum,
554 };
555
556 /* --- pci address --- */
557
558 /*
559 * bus-local address, i.e. "$slot" or "$slot.$fn"
560 */
561 static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
562 const char *name, Error **errp)
563 {
564 DeviceState *dev = DEVICE(obj);
565 Property *prop = opaque;
566 int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
567 unsigned int slot, fn, n;
568 Error *local_err = NULL;
569 char *str;
570
571 if (dev->state != DEV_STATE_CREATED) {
572 error_set(errp, QERR_PERMISSION_DENIED);
573 return;
574 }
575
576 visit_type_str(v, &str, name, &local_err);
577 if (local_err) {
578 error_free(local_err);
579 local_err = NULL;
580 visit_type_int32(v, &value, name, &local_err);
581 if (local_err) {
582 error_propagate(errp, local_err);
583 } else if (value < -1 || value > 255) {
584 error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
585 "pci_devfn");
586 } else {
587 *ptr = value;
588 }
589 return;
590 }
591
592 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
593 fn = 0;
594 if (sscanf(str, "%x%n", &slot, &n) != 1) {
595 goto invalid;
596 }
597 }
598 if (str[n] != '\0' || fn > 7 || slot > 31) {
599 goto invalid;
600 }
601 *ptr = slot << 3 | fn;
602 g_free(str);
603 return;
604
605 invalid:
606 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
607 g_free(str);
608 }
609
610 static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
611 size_t len)
612 {
613 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
614
615 if (*ptr == -1) {
616 return snprintf(dest, len, "<unset>");
617 } else {
618 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
619 }
620 }
621
622 PropertyInfo qdev_prop_pci_devfn = {
623 .name = "int32",
624 .legacy_name = "pci-devfn",
625 .print = print_pci_devfn,
626 .get = get_int32,
627 .set = set_pci_devfn,
628 };
629
630 /* --- blocksize --- */
631
632 static void set_blocksize(Object *obj, Visitor *v, void *opaque,
633 const char *name, Error **errp)
634 {
635 DeviceState *dev = DEVICE(obj);
636 Property *prop = opaque;
637 uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
638 Error *local_err = NULL;
639 const int64_t min = 512;
640 const int64_t max = 32768;
641
642 if (dev->state != DEV_STATE_CREATED) {
643 error_set(errp, QERR_PERMISSION_DENIED);
644 return;
645 }
646
647 visit_type_uint16(v, &value, name, &local_err);
648 if (local_err) {
649 error_propagate(errp, local_err);
650 return;
651 }
652 if (value < min || value > max) {
653 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
654 dev->id?:"", name, (int64_t)value, min, max);
655 return;
656 }
657
658 /* We rely on power-of-2 blocksizes for bitmasks */
659 if ((value & (value - 1)) != 0) {
660 error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
661 dev->id?:"", name, (int64_t)value);
662 return;
663 }
664
665 *ptr = value;
666 }
667
668 PropertyInfo qdev_prop_blocksize = {
669 .name = "blocksize",
670 .get = get_uint16,
671 .set = set_blocksize,
672 };
673
674 /* --- pci host address --- */
675
676 static void get_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
677 const char *name, Error **errp)
678 {
679 DeviceState *dev = DEVICE(obj);
680 Property *prop = opaque;
681 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
682 char buffer[] = "xxxx:xx:xx.x";
683 char *p = buffer;
684 int rc = 0;
685
686 rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
687 addr->domain, addr->bus, addr->slot, addr->function);
688 assert(rc == sizeof(buffer) - 1);
689
690 visit_type_str(v, &p, name, errp);
691 }
692
693 /*
694 * Parse [<domain>:]<bus>:<slot>.<func>
695 * if <domain> is not supplied, it's assumed to be 0.
696 */
697 static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
698 const char *name, Error **errp)
699 {
700 DeviceState *dev = DEVICE(obj);
701 Property *prop = opaque;
702 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
703 Error *local_err = NULL;
704 char *str, *p;
705 char *e;
706 unsigned long val;
707 unsigned long dom = 0, bus = 0;
708 unsigned int slot = 0, func = 0;
709
710 if (dev->state != DEV_STATE_CREATED) {
711 error_set(errp, QERR_PERMISSION_DENIED);
712 return;
713 }
714
715 visit_type_str(v, &str, name, &local_err);
716 if (local_err) {
717 error_propagate(errp, local_err);
718 return;
719 }
720
721 p = str;
722 val = strtoul(p, &e, 16);
723 if (e == p || *e != ':') {
724 goto inval;
725 }
726 bus = val;
727
728 p = e + 1;
729 val = strtoul(p, &e, 16);
730 if (e == p) {
731 goto inval;
732 }
733 if (*e == ':') {
734 dom = bus;
735 bus = val;
736 p = e + 1;
737 val = strtoul(p, &e, 16);
738 if (e == p) {
739 goto inval;
740 }
741 }
742 slot = val;
743
744 if (*e != '.') {
745 goto inval;
746 }
747 p = e + 1;
748 val = strtoul(p, &e, 10);
749 if (e == p) {
750 goto inval;
751 }
752 func = val;
753
754 if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
755 goto inval;
756 }
757
758 if (*e) {
759 goto inval;
760 }
761
762 addr->domain = dom;
763 addr->bus = bus;
764 addr->slot = slot;
765 addr->function = func;
766
767 g_free(str);
768 return;
769
770 inval:
771 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
772 g_free(str);
773 }
774
775 PropertyInfo qdev_prop_pci_host_devaddr = {
776 .name = "pci-host-devaddr",
777 .get = get_pci_host_devaddr,
778 .set = set_pci_host_devaddr,
779 };
780
781 /* --- public helpers --- */
782
783 static Property *qdev_prop_walk(Property *props, const char *name)
784 {
785 if (!props) {
786 return NULL;
787 }
788 while (props->name) {
789 if (strcmp(props->name, name) == 0) {
790 return props;
791 }
792 props++;
793 }
794 return NULL;
795 }
796
797 static Property *qdev_prop_find(DeviceState *dev, const char *name)
798 {
799 ObjectClass *class;
800 Property *prop;
801
802 /* device properties */
803 class = object_get_class(OBJECT(dev));
804 do {
805 prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
806 if (prop) {
807 return prop;
808 }
809 class = object_class_get_parent(class);
810 } while (class != object_class_by_name(TYPE_DEVICE));
811
812 return NULL;
813 }
814
815 void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
816 Property *prop, const char *value)
817 {
818 switch (ret) {
819 case -EEXIST:
820 error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
821 object_get_typename(OBJECT(dev)), prop->name, value);
822 break;
823 default:
824 case -EINVAL:
825 error_set(errp, QERR_PROPERTY_VALUE_BAD,
826 object_get_typename(OBJECT(dev)), prop->name, value);
827 break;
828 case -ENOENT:
829 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
830 object_get_typename(OBJECT(dev)), prop->name, value);
831 break;
832 case 0:
833 break;
834 }
835 }
836
837 int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
838 {
839 char *legacy_name;
840 Error *err = NULL;
841
842 legacy_name = g_strdup_printf("legacy-%s", name);
843 if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
844 object_property_parse(OBJECT(dev), value, legacy_name, &err);
845 } else {
846 object_property_parse(OBJECT(dev), value, name, &err);
847 }
848 g_free(legacy_name);
849
850 if (err) {
851 qerror_report_err(err);
852 error_free(err);
853 return -1;
854 }
855 return 0;
856 }
857
858 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
859 {
860 Error *errp = NULL;
861 object_property_set_bool(OBJECT(dev), value, name, &errp);
862 assert_no_error(errp);
863 }
864
865 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
866 {
867 Error *errp = NULL;
868 object_property_set_int(OBJECT(dev), value, name, &errp);
869 assert_no_error(errp);
870 }
871
872 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
873 {
874 Error *errp = NULL;
875 object_property_set_int(OBJECT(dev), value, name, &errp);
876 assert_no_error(errp);
877 }
878
879 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
880 {
881 Error *errp = NULL;
882 object_property_set_int(OBJECT(dev), value, name, &errp);
883 assert_no_error(errp);
884 }
885
886 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
887 {
888 Error *errp = NULL;
889 object_property_set_int(OBJECT(dev), value, name, &errp);
890 assert_no_error(errp);
891 }
892
893 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
894 {
895 Error *errp = NULL;
896 object_property_set_int(OBJECT(dev), value, name, &errp);
897 assert_no_error(errp);
898 }
899
900 void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
901 {
902 Error *errp = NULL;
903 object_property_set_str(OBJECT(dev), value, name, &errp);
904 assert_no_error(errp);
905 }
906
907 void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
908 {
909 Error *errp = NULL;
910 char str[2 * 6 + 5 + 1];
911 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
912 value[0], value[1], value[2], value[3], value[4], value[5]);
913
914 object_property_set_str(OBJECT(dev), str, name, &errp);
915 assert_no_error(errp);
916 }
917
918 void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
919 {
920 Property *prop;
921 Error *errp = NULL;
922
923 prop = qdev_prop_find(dev, name);
924 object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
925 name, &errp);
926 assert_no_error(errp);
927 }
928
929 void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
930 {
931 Property *prop;
932 void **ptr;
933
934 prop = qdev_prop_find(dev, name);
935 assert(prop && prop->info == &qdev_prop_ptr);
936 ptr = qdev_get_prop_ptr(dev, prop);
937 *ptr = value;
938 }
939
940 static QTAILQ_HEAD(, GlobalProperty) global_props =
941 QTAILQ_HEAD_INITIALIZER(global_props);
942
943 void qdev_prop_register_global(GlobalProperty *prop)
944 {
945 QTAILQ_INSERT_TAIL(&global_props, prop, next);
946 }
947
948 void qdev_prop_register_global_list(GlobalProperty *props)
949 {
950 int i;
951
952 for (i = 0; props[i].driver != NULL; i++) {
953 qdev_prop_register_global(props+i);
954 }
955 }
956
957 void qdev_prop_set_globals(DeviceState *dev)
958 {
959 ObjectClass *class = object_get_class(OBJECT(dev));
960
961 do {
962 GlobalProperty *prop;
963 QTAILQ_FOREACH(prop, &global_props, next) {
964 if (strcmp(object_class_get_name(class), prop->driver) != 0) {
965 continue;
966 }
967 if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
968 exit(1);
969 }
970 }
971 class = object_class_get_parent(class);
972 } while (class);
973 }