xref: /illumos-kvm-cmd/hw/qdev-properties.c (revision 68396ea9)
1 #include "net.h"
2 #include "qdev.h"
3 #include "qerror.h"
4 #include "blockdev.h"
5 
qdev_get_prop_ptr(DeviceState * dev,Property * prop)6 void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
7 {
8     void *ptr = dev;
9     ptr += prop->offset;
10     return ptr;
11 }
12 
qdev_get_prop_mask(Property * prop)13 static uint32_t qdev_get_prop_mask(Property *prop)
14 {
15     assert(prop->info->type == PROP_TYPE_BIT);
16     return 0x1 << prop->bitnr;
17 }
18 
bit_prop_set(DeviceState * dev,Property * props,bool val)19 static void bit_prop_set(DeviceState *dev, Property *props, bool val)
20 {
21     uint32_t *p = qdev_get_prop_ptr(dev, props);
22     uint32_t mask = qdev_get_prop_mask(props);
23     if (val)
24         *p |= mask;
25     else
26         *p &= ~mask;
27 }
28 
qdev_prop_cpy(DeviceState * dev,Property * props,void * src)29 static void qdev_prop_cpy(DeviceState *dev, Property *props, void *src)
30 {
31     if (props->info->type == PROP_TYPE_BIT) {
32         bool *defval = src;
33         bit_prop_set(dev, props, *defval);
34     } else {
35         char *dst = qdev_get_prop_ptr(dev, props);
36         memcpy(dst, src, props->info->size);
37     }
38 }
39 
40 /* Bit */
parse_bit(DeviceState * dev,Property * prop,const char * str)41 static int parse_bit(DeviceState *dev, Property *prop, const char *str)
42 {
43     if (!strncasecmp(str, "on", 2))
44         bit_prop_set(dev, prop, true);
45     else if (!strncasecmp(str, "off", 3))
46         bit_prop_set(dev, prop, false);
47     else
48         return -EINVAL;
49     return 0;
50 }
51 
print_bit(DeviceState * dev,Property * prop,char * dest,size_t len)52 static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
53 {
54     uint8_t *p = qdev_get_prop_ptr(dev, prop);
55     return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
56 }
57 
58 PropertyInfo qdev_prop_bit = {
59     .name  = "on/off",
60     .type  = PROP_TYPE_BIT,
61     .size  = sizeof(uint32_t),
62     .parse = parse_bit,
63     .print = print_bit,
64 };
65 
66 /* --- 8bit integer --- */
67 
parse_uint8(DeviceState * dev,Property * prop,const char * str)68 static int parse_uint8(DeviceState *dev, Property *prop, const char *str)
69 {
70     uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
71     char *end;
72 
73     /* accept both hex and decimal */
74     *ptr = strtoul(str, &end, 0);
75     if ((*end != '\0') || (end == str)) {
76         return -EINVAL;
77     }
78 
79     return 0;
80 }
81 
print_uint8(DeviceState * dev,Property * prop,char * dest,size_t len)82 static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len)
83 {
84     uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
85     return snprintf(dest, len, "%" PRIu8, *ptr);
86 }
87 
88 PropertyInfo qdev_prop_uint8 = {
89     .name  = "uint8",
90     .type  = PROP_TYPE_UINT8,
91     .size  = sizeof(uint8_t),
92     .parse = parse_uint8,
93     .print = print_uint8,
94 };
95 
96 /* --- 16bit integer --- */
97 
parse_uint16(DeviceState * dev,Property * prop,const char * str)98 static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
99 {
100     uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
101     char *end;
102 
103     /* accept both hex and decimal */
104     *ptr = strtoul(str, &end, 0);
105     if ((*end != '\0') || (end == str)) {
106         return -EINVAL;
107     }
108 
109     return 0;
110 }
111 
print_uint16(DeviceState * dev,Property * prop,char * dest,size_t len)112 static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len)
113 {
114     uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
115     return snprintf(dest, len, "%" PRIu16, *ptr);
116 }
117 
118 PropertyInfo qdev_prop_uint16 = {
119     .name  = "uint16",
120     .type  = PROP_TYPE_UINT16,
121     .size  = sizeof(uint16_t),
122     .parse = parse_uint16,
123     .print = print_uint16,
124 };
125 
126 /* --- 32bit integer --- */
127 
parse_uint32(DeviceState * dev,Property * prop,const char * str)128 static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
129 {
130     uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
131     char *end;
132 
133     /* accept both hex and decimal */
134     *ptr = strtoul(str, &end, 0);
135     if ((*end != '\0') || (end == str)) {
136         return -EINVAL;
137     }
138 
139     return 0;
140 }
141 
print_uint32(DeviceState * dev,Property * prop,char * dest,size_t len)142 static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
143 {
144     uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
145     return snprintf(dest, len, "%" PRIu32, *ptr);
146 }
147 
148 PropertyInfo qdev_prop_uint32 = {
149     .name  = "uint32",
150     .type  = PROP_TYPE_UINT32,
151     .size  = sizeof(uint32_t),
152     .parse = parse_uint32,
153     .print = print_uint32,
154 };
155 
parse_int32(DeviceState * dev,Property * prop,const char * str)156 static int parse_int32(DeviceState *dev, Property *prop, const char *str)
157 {
158     int32_t *ptr = qdev_get_prop_ptr(dev, prop);
159     char *end;
160 
161     *ptr = strtol(str, &end, 10);
162     if ((*end != '\0') || (end == str)) {
163         return -EINVAL;
164     }
165 
166     return 0;
167 }
168 
print_int32(DeviceState * dev,Property * prop,char * dest,size_t len)169 static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len)
170 {
171     int32_t *ptr = qdev_get_prop_ptr(dev, prop);
172     return snprintf(dest, len, "%" PRId32, *ptr);
173 }
174 
175 PropertyInfo qdev_prop_int32 = {
176     .name  = "int32",
177     .type  = PROP_TYPE_INT32,
178     .size  = sizeof(int32_t),
179     .parse = parse_int32,
180     .print = print_int32,
181 };
182 
183 /* --- 32bit hex value --- */
184 
parse_hex32(DeviceState * dev,Property * prop,const char * str)185 static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
186 {
187     uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
188     char *end;
189 
190     *ptr = strtoul(str, &end, 16);
191     if ((*end != '\0') || (end == str)) {
192         return -EINVAL;
193     }
194 
195     return 0;
196 }
197 
print_hex32(DeviceState * dev,Property * prop,char * dest,size_t len)198 static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
199 {
200     uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
201     return snprintf(dest, len, "0x%" PRIx32, *ptr);
202 }
203 
204 PropertyInfo qdev_prop_hex32 = {
205     .name  = "hex32",
206     .type  = PROP_TYPE_UINT32,
207     .size  = sizeof(uint32_t),
208     .parse = parse_hex32,
209     .print = print_hex32,
210 };
211 
212 /* --- 64bit integer --- */
213 
parse_uint64(DeviceState * dev,Property * prop,const char * str)214 static int parse_uint64(DeviceState *dev, Property *prop, const char *str)
215 {
216     uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
217     char *end;
218 
219     /* accept both hex and decimal */
220     *ptr = strtoull(str, &end, 0);
221     if ((*end != '\0') || (end == str)) {
222         return -EINVAL;
223     }
224 
225     return 0;
226 }
227 
print_uint64(DeviceState * dev,Property * prop,char * dest,size_t len)228 static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len)
229 {
230     uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
231     return snprintf(dest, len, "%" PRIu64, *ptr);
232 }
233 
234 PropertyInfo qdev_prop_uint64 = {
235     .name  = "uint64",
236     .type  = PROP_TYPE_UINT64,
237     .size  = sizeof(uint64_t),
238     .parse = parse_uint64,
239     .print = print_uint64,
240 };
241 
242 /* --- 64bit hex value --- */
243 
parse_hex64(DeviceState * dev,Property * prop,const char * str)244 static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
245 {
246     uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
247     char *end;
248 
249     *ptr = strtoull(str, &end, 16);
250     if ((*end != '\0') || (end == str)) {
251         return -EINVAL;
252     }
253 
254     return 0;
255 }
256 
print_hex64(DeviceState * dev,Property * prop,char * dest,size_t len)257 static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
258 {
259     uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
260     return snprintf(dest, len, "0x%" PRIx64, *ptr);
261 }
262 
263 PropertyInfo qdev_prop_hex64 = {
264     .name  = "hex64",
265     .type  = PROP_TYPE_UINT64,
266     .size  = sizeof(uint64_t),
267     .parse = parse_hex64,
268     .print = print_hex64,
269 };
270 
271 /* --- string --- */
272 
parse_string(DeviceState * dev,Property * prop,const char * str)273 static int parse_string(DeviceState *dev, Property *prop, const char *str)
274 {
275     char **ptr = qdev_get_prop_ptr(dev, prop);
276 
277     if (*ptr)
278         qemu_free(*ptr);
279     *ptr = qemu_strdup(str);
280     return 0;
281 }
282 
free_string(DeviceState * dev,Property * prop)283 static void free_string(DeviceState *dev, Property *prop)
284 {
285     qemu_free(*(char **)qdev_get_prop_ptr(dev, prop));
286 }
287 
print_string(DeviceState * dev,Property * prop,char * dest,size_t len)288 static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
289 {
290     char **ptr = qdev_get_prop_ptr(dev, prop);
291     if (!*ptr)
292         return snprintf(dest, len, "<null>");
293     return snprintf(dest, len, "\"%s\"", *ptr);
294 }
295 
296 PropertyInfo qdev_prop_string = {
297     .name  = "string",
298     .type  = PROP_TYPE_STRING,
299     .size  = sizeof(char*),
300     .parse = parse_string,
301     .print = print_string,
302     .free  = free_string,
303 };
304 
305 /* --- drive --- */
306 
parse_drive(DeviceState * dev,Property * prop,const char * str)307 static int parse_drive(DeviceState *dev, Property *prop, const char *str)
308 {
309     BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
310     BlockDriverState *bs;
311 
312     bs = bdrv_find(str);
313     if (bs == NULL)
314         return -ENOENT;
315     if (bdrv_attach(bs, dev) < 0)
316         return -EEXIST;
317     *ptr = bs;
318     return 0;
319 }
320 
free_drive(DeviceState * dev,Property * prop)321 static void free_drive(DeviceState *dev, Property *prop)
322 {
323     BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
324 
325     if (*ptr) {
326         bdrv_detach(*ptr, dev);
327         blockdev_auto_del(*ptr);
328     }
329 }
330 
print_drive(DeviceState * dev,Property * prop,char * dest,size_t len)331 static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len)
332 {
333     BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
334     return snprintf(dest, len, "%s",
335                     *ptr ? bdrv_get_device_name(*ptr) : "<null>");
336 }
337 
338 PropertyInfo qdev_prop_drive = {
339     .name  = "drive",
340     .type  = PROP_TYPE_DRIVE,
341     .size  = sizeof(BlockDriverState *),
342     .parse = parse_drive,
343     .print = print_drive,
344     .free  = free_drive,
345 };
346 
347 /* --- character device --- */
348 
parse_chr(DeviceState * dev,Property * prop,const char * str)349 static int parse_chr(DeviceState *dev, Property *prop, const char *str)
350 {
351     CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
352 
353     *ptr = qemu_chr_find(str);
354     if (*ptr == NULL)
355         return -ENOENT;
356     return 0;
357 }
358 
print_chr(DeviceState * dev,Property * prop,char * dest,size_t len)359 static int print_chr(DeviceState *dev, Property *prop, char *dest, size_t len)
360 {
361     CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
362 
363     if (*ptr && (*ptr)->label) {
364         return snprintf(dest, len, "%s", (*ptr)->label);
365     } else {
366         return snprintf(dest, len, "<null>");
367     }
368 }
369 
370 PropertyInfo qdev_prop_chr = {
371     .name  = "chr",
372     .type  = PROP_TYPE_CHR,
373     .size  = sizeof(CharDriverState*),
374     .parse = parse_chr,
375     .print = print_chr,
376 };
377 
378 /* --- netdev device --- */
379 
parse_netdev(DeviceState * dev,Property * prop,const char * str)380 static int parse_netdev(DeviceState *dev, Property *prop, const char *str)
381 {
382     VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
383 
384     *ptr = qemu_find_netdev(str);
385     if (*ptr == NULL)
386         return -ENOENT;
387     if ((*ptr)->peer) {
388         return -EEXIST;
389     }
390     return 0;
391 }
392 
print_netdev(DeviceState * dev,Property * prop,char * dest,size_t len)393 static int print_netdev(DeviceState *dev, Property *prop, char *dest, size_t len)
394 {
395     VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
396 
397     if (*ptr && (*ptr)->name) {
398         return snprintf(dest, len, "%s", (*ptr)->name);
399     } else {
400         return snprintf(dest, len, "<null>");
401     }
402 }
403 
404 PropertyInfo qdev_prop_netdev = {
405     .name  = "netdev",
406     .type  = PROP_TYPE_NETDEV,
407     .size  = sizeof(VLANClientState*),
408     .parse = parse_netdev,
409     .print = print_netdev,
410 };
411 
412 /* --- vlan --- */
413 
parse_vlan(DeviceState * dev,Property * prop,const char * str)414 static int parse_vlan(DeviceState *dev, Property *prop, const char *str)
415 {
416     VLANState **ptr = qdev_get_prop_ptr(dev, prop);
417     int id;
418 
419     if (sscanf(str, "%d", &id) != 1)
420         return -EINVAL;
421     *ptr = qemu_find_vlan(id, 1);
422     if (*ptr == NULL)
423         return -ENOENT;
424     return 0;
425 }
426 
print_vlan(DeviceState * dev,Property * prop,char * dest,size_t len)427 static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
428 {
429     VLANState **ptr = qdev_get_prop_ptr(dev, prop);
430 
431     if (*ptr) {
432         return snprintf(dest, len, "%d", (*ptr)->id);
433     } else {
434         return snprintf(dest, len, "<null>");
435     }
436 }
437 
438 PropertyInfo qdev_prop_vlan = {
439     .name  = "vlan",
440     .type  = PROP_TYPE_VLAN,
441     .size  = sizeof(VLANClientState*),
442     .parse = parse_vlan,
443     .print = print_vlan,
444 };
445 
446 /* --- pointer --- */
447 
448 /* Not a proper property, just for dirty hacks.  TODO Remove it!  */
449 PropertyInfo qdev_prop_ptr = {
450     .name  = "ptr",
451     .type  = PROP_TYPE_PTR,
452     .size  = sizeof(void*),
453 };
454 
455 /* --- mac address --- */
456 
457 /*
458  * accepted syntax versions:
459  *   01:02:03:04:05:06
460  *   01-02-03-04-05-06
461  */
parse_mac(DeviceState * dev,Property * prop,const char * str)462 static int parse_mac(DeviceState *dev, Property *prop, const char *str)
463 {
464     MACAddr *mac = qdev_get_prop_ptr(dev, prop);
465     int i, pos;
466     char *p;
467 
468     for (i = 0, pos = 0; i < 6; i++, pos += 3) {
469         if (!qemu_isxdigit(str[pos]))
470             return -EINVAL;
471         if (!qemu_isxdigit(str[pos+1]))
472             return -EINVAL;
473         if (i == 5) {
474             if (str[pos+2] != '\0')
475                 return -EINVAL;
476         } else {
477             if (str[pos+2] != ':' && str[pos+2] != '-')
478                 return -EINVAL;
479         }
480         mac->a[i] = strtol(str+pos, &p, 16);
481     }
482     return 0;
483 }
484 
print_mac(DeviceState * dev,Property * prop,char * dest,size_t len)485 static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len)
486 {
487     MACAddr *mac = qdev_get_prop_ptr(dev, prop);
488 
489     return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x",
490                     mac->a[0], mac->a[1], mac->a[2],
491                     mac->a[3], mac->a[4], mac->a[5]);
492 }
493 
494 PropertyInfo qdev_prop_macaddr = {
495     .name  = "macaddr",
496     .type  = PROP_TYPE_MACADDR,
497     .size  = sizeof(MACAddr),
498     .parse = parse_mac,
499     .print = print_mac,
500 };
501 
502 /* --- pci address --- */
503 
504 /*
505  * bus-local address, i.e. "$slot" or "$slot.$fn"
506  */
parse_pci_devfn(DeviceState * dev,Property * prop,const char * str)507 static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str)
508 {
509     uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
510     unsigned int slot, fn, n;
511 
512     if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
513         fn = 0;
514         if (sscanf(str, "%x%n", &slot, &n) != 1) {
515             return -EINVAL;
516         }
517     }
518     if (str[n] != '\0')
519         return -EINVAL;
520     if (fn > 7)
521         return -EINVAL;
522     *ptr = slot << 3 | fn;
523     return 0;
524 }
525 
print_pci_devfn(DeviceState * dev,Property * prop,char * dest,size_t len)526 static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
527 {
528     uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
529 
530     if (*ptr == -1) {
531         return snprintf(dest, len, "<unset>");
532     } else {
533         return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
534     }
535 }
536 
537 PropertyInfo qdev_prop_pci_devfn = {
538     .name  = "pci-devfn",
539     .type  = PROP_TYPE_UINT32,
540     .size  = sizeof(uint32_t),
541     .parse = parse_pci_devfn,
542     .print = print_pci_devfn,
543 };
544 
545 /* --- public helpers --- */
546 
qdev_prop_walk(Property * props,const char * name)547 static Property *qdev_prop_walk(Property *props, const char *name)
548 {
549     if (!props)
550         return NULL;
551     while (props->name) {
552         if (strcmp(props->name, name) == 0)
553             return props;
554         props++;
555     }
556     return NULL;
557 }
558 
qdev_prop_find(DeviceState * dev,const char * name)559 static Property *qdev_prop_find(DeviceState *dev, const char *name)
560 {
561     Property *prop;
562 
563     /* device properties */
564     prop = qdev_prop_walk(dev->info->props, name);
565     if (prop)
566         return prop;
567 
568     /* bus properties */
569     prop = qdev_prop_walk(dev->parent_bus->info->props, name);
570     if (prop)
571         return prop;
572 
573     return NULL;
574 }
575 
qdev_prop_exists(DeviceState * dev,const char * name)576 int qdev_prop_exists(DeviceState *dev, const char *name)
577 {
578     return qdev_prop_find(dev, name) ? true : false;
579 }
580 
qdev_prop_parse(DeviceState * dev,const char * name,const char * value)581 int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
582 {
583     Property *prop;
584     int ret;
585 
586     prop = qdev_prop_find(dev, name);
587     /*
588      * TODO Properties without a parse method are just for dirty
589      * hacks.  qdev_prop_ptr is the only such PropertyInfo.  It's
590      * marked for removal.  The test !prop->info->parse should be
591      * removed along with it.
592      */
593     if (!prop || !prop->info->parse) {
594         qerror_report(QERR_PROPERTY_NOT_FOUND, dev->info->name, name);
595         return -1;
596     }
597     ret = prop->info->parse(dev, prop, value);
598     if (ret < 0) {
599         switch (ret) {
600         case -EEXIST:
601             qerror_report(QERR_PROPERTY_VALUE_IN_USE,
602                           dev->info->name, name, value);
603             break;
604         default:
605         case -EINVAL:
606             qerror_report(QERR_PROPERTY_VALUE_BAD,
607                           dev->info->name, name, value);
608             break;
609         case -ENOENT:
610             qerror_report(QERR_PROPERTY_VALUE_NOT_FOUND,
611                           dev->info->name, name, value);
612             break;
613         }
614         return -1;
615     }
616     return 0;
617 }
618 
qdev_prop_set(DeviceState * dev,const char * name,void * src,enum PropertyType type)619 void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type)
620 {
621     Property *prop;
622 
623     prop = qdev_prop_find(dev, name);
624     if (!prop) {
625         fprintf(stderr, "%s: property \"%s.%s\" not found\n",
626                 __FUNCTION__, dev->info->name, name);
627         abort();
628     }
629     if (prop->info->type != type) {
630         fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n",
631                 __FUNCTION__, dev->info->name, name);
632         abort();
633     }
634     qdev_prop_cpy(dev, prop, src);
635 }
636 
qdev_prop_set_bit(DeviceState * dev,const char * name,bool value)637 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
638 {
639     qdev_prop_set(dev, name, &value, PROP_TYPE_BIT);
640 }
641 
qdev_prop_set_uint8(DeviceState * dev,const char * name,uint8_t value)642 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
643 {
644     qdev_prop_set(dev, name, &value, PROP_TYPE_UINT8);
645 }
646 
qdev_prop_set_uint16(DeviceState * dev,const char * name,uint16_t value)647 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
648 {
649     qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16);
650 }
651 
qdev_prop_set_uint32(DeviceState * dev,const char * name,uint32_t value)652 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
653 {
654     qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32);
655 }
656 
qdev_prop_set_int32(DeviceState * dev,const char * name,int32_t value)657 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
658 {
659     qdev_prop_set(dev, name, &value, PROP_TYPE_INT32);
660 }
661 
qdev_prop_set_uint64(DeviceState * dev,const char * name,uint64_t value)662 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
663 {
664     qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64);
665 }
666 
qdev_prop_set_string(DeviceState * dev,const char * name,char * value)667 void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
668 {
669     qdev_prop_set(dev, name, &value, PROP_TYPE_STRING);
670 }
671 
qdev_prop_set_drive(DeviceState * dev,const char * name,BlockDriverState * value)672 int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
673 {
674     int res;
675 
676     res = bdrv_attach(value, dev);
677     if (res < 0) {
678         error_report("Can't attach drive %s to %s.%s: %s",
679                      bdrv_get_device_name(value),
680                      dev->id ? dev->id : dev->info->name,
681                      name, strerror(-res));
682         return -1;
683     }
684     qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
685     return 0;
686 }
687 
qdev_prop_set_drive_nofail(DeviceState * dev,const char * name,BlockDriverState * value)688 void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
689 {
690     if (qdev_prop_set_drive(dev, name, value) < 0) {
691         exit(1);
692     }
693 }
qdev_prop_set_chr(DeviceState * dev,const char * name,CharDriverState * value)694 void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
695 {
696     qdev_prop_set(dev, name, &value, PROP_TYPE_CHR);
697 }
698 
qdev_prop_set_netdev(DeviceState * dev,const char * name,VLANClientState * value)699 void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
700 {
701     qdev_prop_set(dev, name, &value, PROP_TYPE_NETDEV);
702 }
703 
qdev_prop_set_vlan(DeviceState * dev,const char * name,VLANState * value)704 void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
705 {
706     qdev_prop_set(dev, name, &value, PROP_TYPE_VLAN);
707 }
708 
qdev_prop_set_macaddr(DeviceState * dev,const char * name,uint8_t * value)709 void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
710 {
711     qdev_prop_set(dev, name, value, PROP_TYPE_MACADDR);
712 }
713 
qdev_prop_set_ptr(DeviceState * dev,const char * name,void * value)714 void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
715 {
716     qdev_prop_set(dev, name, &value, PROP_TYPE_PTR);
717 }
718 
qdev_prop_set_defaults(DeviceState * dev,Property * props)719 void qdev_prop_set_defaults(DeviceState *dev, Property *props)
720 {
721     if (!props)
722         return;
723     while (props->name) {
724         if (props->defval) {
725             qdev_prop_cpy(dev, props, props->defval);
726         }
727         props++;
728     }
729 }
730 
731 static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
732 
qdev_prop_register_global(GlobalProperty * prop)733 static void qdev_prop_register_global(GlobalProperty *prop)
734 {
735     QTAILQ_INSERT_TAIL(&global_props, prop, next);
736 }
737 
qdev_prop_register_global_list(GlobalProperty * props)738 void qdev_prop_register_global_list(GlobalProperty *props)
739 {
740     int i;
741 
742     for (i = 0; props[i].driver != NULL; i++) {
743         qdev_prop_register_global(props+i);
744     }
745 }
746 
qdev_prop_set_globals(DeviceState * dev)747 void qdev_prop_set_globals(DeviceState *dev)
748 {
749     GlobalProperty *prop;
750 
751     QTAILQ_FOREACH(prop, &global_props, next) {
752         if (strcmp(dev->info->name, prop->driver) != 0 &&
753             strcmp(dev->info->bus_info->name, prop->driver) != 0) {
754             continue;
755         }
756         if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
757             exit(1);
758         }
759     }
760 }
761 
qdev_add_one_global(QemuOpts * opts,void * opaque)762 static int qdev_add_one_global(QemuOpts *opts, void *opaque)
763 {
764     GlobalProperty *g;
765 
766     g = qemu_mallocz(sizeof(*g));
767     g->driver   = qemu_opt_get(opts, "driver");
768     g->property = qemu_opt_get(opts, "property");
769     g->value    = qemu_opt_get(opts, "value");
770     qdev_prop_register_global(g);
771     return 0;
772 }
773 
qemu_add_globals(void)774 void qemu_add_globals(void)
775 {
776     qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
777 }
778