Statistics
| Branch: | Revision:

root / hw / qdev-properties.c @ 922910ce

History | View | Annotate | Download (16.8 kB)

1
#include "sysemu.h"
2
#include "net.h"
3
#include "qdev.h"
4

    
5
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
6
{
7
    void *ptr = dev;
8
    ptr += prop->offset;
9
    return ptr;
10
}
11

    
12
static uint32_t qdev_get_prop_mask(Property *prop)
13
{
14
    assert(prop->info->type == PROP_TYPE_BIT);
15
    return 0x1 << prop->bitnr;
16
}
17

    
18
static void bit_prop_set(DeviceState *dev, Property *props, bool val)
19
{
20
    uint32_t *p = qdev_get_prop_ptr(dev, props);
21
    uint32_t mask = qdev_get_prop_mask(props);
22
    if (val)
23
        *p |= mask;
24
    else
25
        *p &= ~mask;
26
}
27

    
28
static void qdev_prop_cpy(DeviceState *dev, Property *props, void *src)
29
{
30
    if (props->info->type == PROP_TYPE_BIT) {
31
        bool *defval = src;
32
        bit_prop_set(dev, props, *defval);
33
    } else {
34
        char *dst = qdev_get_prop_ptr(dev, props);
35
        memcpy(dst, src, props->info->size);
36
    }
37
}
38

    
39
/* Bit */
40
static int parse_bit(DeviceState *dev, Property *prop, const char *str)
41
{
42
    if (!strncasecmp(str, "on", 2))
43
        bit_prop_set(dev, prop, true);
44
    else if (!strncasecmp(str, "off", 3))
45
        bit_prop_set(dev, prop, false);
46
    else
47
        return -1;
48
    return 0;
49
}
50

    
51
static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
52
{
53
    uint8_t *p = qdev_get_prop_ptr(dev, prop);
54
    return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
55
}
56

    
57
PropertyInfo qdev_prop_bit = {
58
    .name  = "on/off",
59
    .type  = PROP_TYPE_BIT,
60
    .size  = sizeof(uint32_t),
61
    .parse = parse_bit,
62
    .print = print_bit,
63
};
64

    
65
/* --- 8bit integer --- */
66

    
67
static int parse_uint8(DeviceState *dev, Property *prop, const char *str)
68
{
69
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
70
    const char *fmt;
71

    
72
    /* accept both hex and decimal */
73
    fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx8 : "%" PRIu8;
74
    if (sscanf(str, fmt, ptr) != 1)
75
        return -1;
76
    return 0;
77
}
78

    
79
static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len)
80
{
81
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
82
    return snprintf(dest, len, "%" PRIu8, *ptr);
83
}
84

    
85
PropertyInfo qdev_prop_uint8 = {
86
    .name  = "uint8",
87
    .type  = PROP_TYPE_UINT8,
88
    .size  = sizeof(uint8_t),
89
    .parse = parse_uint8,
90
    .print = print_uint8,
91
};
92

    
93
/* --- 16bit integer --- */
94

    
95
static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
96
{
97
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
98
    const char *fmt;
99

    
100
    /* accept both hex and decimal */
101
    fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx16 : "%" PRIu16;
102
    if (sscanf(str, fmt, ptr) != 1)
103
        return -1;
104
    return 0;
105
}
106

    
107
static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len)
108
{
109
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
110
    return snprintf(dest, len, "%" PRIu16, *ptr);
111
}
112

    
113
PropertyInfo qdev_prop_uint16 = {
114
    .name  = "uint16",
115
    .type  = PROP_TYPE_UINT16,
116
    .size  = sizeof(uint16_t),
117
    .parse = parse_uint16,
118
    .print = print_uint16,
119
};
120

    
121
/* --- 32bit integer --- */
122

    
123
static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
124
{
125
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
126
    const char *fmt;
127

    
128
    /* accept both hex and decimal */
129
    fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx32 : "%" PRIu32;
130
    if (sscanf(str, fmt, ptr) != 1)
131
        return -1;
132
    return 0;
133
}
134

    
135
static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
136
{
137
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
138
    return snprintf(dest, len, "%" PRIu32, *ptr);
139
}
140

    
141
PropertyInfo qdev_prop_uint32 = {
142
    .name  = "uint32",
143
    .type  = PROP_TYPE_UINT32,
144
    .size  = sizeof(uint32_t),
145
    .parse = parse_uint32,
146
    .print = print_uint32,
147
};
148

    
149
static int parse_int32(DeviceState *dev, Property *prop, const char *str)
150
{
151
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
152

    
153
    if (sscanf(str, "%" PRId32, ptr) != 1)
154
        return -1;
155
    return 0;
156
}
157

    
158
static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len)
159
{
160
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
161
    return snprintf(dest, len, "%" PRId32, *ptr);
162
}
163

    
164
PropertyInfo qdev_prop_int32 = {
165
    .name  = "int32",
166
    .type  = PROP_TYPE_INT32,
167
    .size  = sizeof(int32_t),
168
    .parse = parse_int32,
169
    .print = print_int32,
170
};
171

    
172
/* --- 32bit hex value --- */
173

    
174
static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
175
{
176
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
177

    
178
    if (sscanf(str, "%" PRIx32, ptr) != 1)
179
        return -1;
180
    return 0;
181
}
182

    
183
static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
184
{
185
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
186
    return snprintf(dest, len, "0x%" PRIx32, *ptr);
187
}
188

    
189
PropertyInfo qdev_prop_hex32 = {
190
    .name  = "hex32",
191
    .type  = PROP_TYPE_UINT32,
192
    .size  = sizeof(uint32_t),
193
    .parse = parse_hex32,
194
    .print = print_hex32,
195
};
196

    
197
/* --- 64bit integer --- */
198

    
199
static int parse_uint64(DeviceState *dev, Property *prop, const char *str)
200
{
201
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
202
    const char *fmt;
203

    
204
    /* accept both hex and decimal */
205
    fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx64 : "%" PRIu64;
206
    if (sscanf(str, fmt, ptr) != 1)
207
        return -1;
208
    return 0;
209
}
210

    
211
static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len)
212
{
213
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
214
    return snprintf(dest, len, "%" PRIu64, *ptr);
215
}
216

    
217
PropertyInfo qdev_prop_uint64 = {
218
    .name  = "uint64",
219
    .type  = PROP_TYPE_UINT64,
220
    .size  = sizeof(uint64_t),
221
    .parse = parse_uint64,
222
    .print = print_uint64,
223
};
224

    
225
/* --- 64bit hex value --- */
226

    
227
static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
228
{
229
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
230

    
231
    if (sscanf(str, "%" PRIx64, ptr) != 1)
232
        return -1;
233
    return 0;
234
}
235

    
236
static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
237
{
238
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
239
    return snprintf(dest, len, "0x%" PRIx64, *ptr);
240
}
241

    
242
PropertyInfo qdev_prop_hex64 = {
243
    .name  = "hex64",
244
    .type  = PROP_TYPE_UINT64,
245
    .size  = sizeof(uint64_t),
246
    .parse = parse_hex64,
247
    .print = print_hex64,
248
};
249

    
250
/* --- string --- */
251

    
252
static int parse_string(DeviceState *dev, Property *prop, const char *str)
253
{
254
    char **ptr = qdev_get_prop_ptr(dev, prop);
255

    
256
    if (*ptr)
257
        qemu_free(*ptr);
258
    *ptr = qemu_strdup(str);
259
    return 0;
260
}
261

    
262
static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
263
{
264
    char **ptr = qdev_get_prop_ptr(dev, prop);
265
    if (!*ptr)
266
        return snprintf(dest, len, "<null>");
267
    return snprintf(dest, len, "\"%s\"", *ptr);
268
}
269

    
270
PropertyInfo qdev_prop_string = {
271
    .name  = "string",
272
    .type  = PROP_TYPE_STRING,
273
    .size  = sizeof(char*),
274
    .parse = parse_string,
275
    .print = print_string,
276
};
277

    
278
/* --- drive --- */
279

    
280
static int parse_drive(DeviceState *dev, Property *prop, const char *str)
281
{
282
    DriveInfo **ptr = qdev_get_prop_ptr(dev, prop);
283

    
284
    *ptr = drive_get_by_id(str);
285
    if (*ptr == NULL)
286
        return -1;
287
    return 0;
288
}
289

    
290
static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len)
291
{
292
    DriveInfo **ptr = qdev_get_prop_ptr(dev, prop);
293
    return snprintf(dest, len, "%s", (*ptr) ? (*ptr)->id : "<null>");
294
}
295

    
296
PropertyInfo qdev_prop_drive = {
297
    .name  = "drive",
298
    .type  = PROP_TYPE_DRIVE,
299
    .size  = sizeof(DriveInfo*),
300
    .parse = parse_drive,
301
    .print = print_drive,
302
};
303

    
304
/* --- character device --- */
305

    
306
static int parse_chr(DeviceState *dev, Property *prop, const char *str)
307
{
308
    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
309

    
310
    *ptr = qemu_chr_find(str);
311
    if (*ptr == NULL)
312
        return -1;
313
    return 0;
314
}
315

    
316
static int print_chr(DeviceState *dev, Property *prop, char *dest, size_t len)
317
{
318
    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
319

    
320
    if (*ptr && (*ptr)->label) {
321
        return snprintf(dest, len, "%s", (*ptr)->label);
322
    } else {
323
        return snprintf(dest, len, "<null>");
324
    }
325
}
326

    
327
PropertyInfo qdev_prop_chr = {
328
    .name  = "chr",
329
    .type  = PROP_TYPE_CHR,
330
    .size  = sizeof(CharDriverState*),
331
    .parse = parse_chr,
332
    .print = print_chr,
333
};
334

    
335
/* --- netdev device --- */
336

    
337
static int parse_netdev(DeviceState *dev, Property *prop, const char *str)
338
{
339
    VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
340

    
341
    *ptr = qemu_find_netdev(str);
342
    if (*ptr == NULL)
343
        return -1;
344
    return 0;
345
}
346

    
347
static int print_netdev(DeviceState *dev, Property *prop, char *dest, size_t len)
348
{
349
    VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
350

    
351
    if (*ptr && (*ptr)->name) {
352
        return snprintf(dest, len, "%s", (*ptr)->name);
353
    } else {
354
        return snprintf(dest, len, "<null>");
355
    }
356
}
357

    
358
PropertyInfo qdev_prop_netdev = {
359
    .name  = "netdev",
360
    .type  = PROP_TYPE_NETDEV,
361
    .size  = sizeof(VLANClientState*),
362
    .parse = parse_netdev,
363
    .print = print_netdev,
364
};
365

    
366
/* --- vlan --- */
367

    
368
static int parse_vlan(DeviceState *dev, Property *prop, const char *str)
369
{
370
    VLANState **ptr = qdev_get_prop_ptr(dev, prop);
371
    int id;
372

    
373
    if (sscanf(str, "%d", &id) != 1)
374
        return -1;
375
    *ptr = qemu_find_vlan(id, 1);
376
    if (*ptr == NULL)
377
        return -1;
378
    return 0;
379
}
380

    
381
static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
382
{
383
    VLANState **ptr = qdev_get_prop_ptr(dev, prop);
384

    
385
    if (*ptr) {
386
        return snprintf(dest, len, "%d", (*ptr)->id);
387
    } else {
388
        return snprintf(dest, len, "<null>");
389
    }
390
}
391

    
392
PropertyInfo qdev_prop_vlan = {
393
    .name  = "vlan",
394
    .type  = PROP_TYPE_VLAN,
395
    .size  = sizeof(VLANClientState*),
396
    .parse = parse_vlan,
397
    .print = print_vlan,
398
};
399

    
400
/* --- pointer --- */
401

    
402
static int print_ptr(DeviceState *dev, Property *prop, char *dest, size_t len)
403
{
404
    void **ptr = qdev_get_prop_ptr(dev, prop);
405
    return snprintf(dest, len, "<%p>", *ptr);
406
}
407

    
408
PropertyInfo qdev_prop_ptr = {
409
    .name  = "ptr",
410
    .type  = PROP_TYPE_PTR,
411
    .size  = sizeof(void*),
412
    .print = print_ptr,
413
};
414

    
415
/* --- mac address --- */
416

    
417
/*
418
 * accepted syntax versions:
419
 *   01:02:03:04:05:06
420
 *   01-02-03-04-05-06
421
 */
422
static int parse_mac(DeviceState *dev, Property *prop, const char *str)
423
{
424
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
425
    int i, pos;
426
    char *p;
427

    
428
    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
429
        if (!qemu_isxdigit(str[pos]))
430
            return -1;
431
        if (!qemu_isxdigit(str[pos+1]))
432
            return -1;
433
        if (i == 5) {
434
            if (str[pos+2] != '\0')
435
                return -1;
436
        } else {
437
            if (str[pos+2] != ':' && str[pos+2] != '-')
438
                return -1;
439
        }
440
        mac->a[i] = strtol(str+pos, &p, 16);
441
    }
442
    return 0;
443
}
444

    
445
static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len)
446
{
447
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
448

    
449
    return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x",
450
                    mac->a[0], mac->a[1], mac->a[2],
451
                    mac->a[3], mac->a[4], mac->a[5]);
452
}
453

    
454
PropertyInfo qdev_prop_macaddr = {
455
    .name  = "macaddr",
456
    .type  = PROP_TYPE_MACADDR,
457
    .size  = sizeof(MACAddr),
458
    .parse = parse_mac,
459
    .print = print_mac,
460
};
461

    
462
/* --- pci address --- */
463

    
464
/*
465
 * bus-local address, i.e. "$slot" or "$slot.$fn"
466
 */
467
static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str)
468
{
469
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
470
    unsigned int slot, fn, n;
471

    
472
    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
473
        fn = 0;
474
        if (sscanf(str, "%x%n", &slot, &n) != 1) {
475
            return -1;
476
        }
477
    }
478
    if (str[n] != '\0')
479
        return -1;
480
    if (fn > 7)
481
        return -1;
482
    *ptr = slot << 3 | fn;
483
    return 0;
484
}
485

    
486
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
487
{
488
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
489

    
490
    if (*ptr == -1) {
491
        return snprintf(dest, len, "<unset>");
492
    } else {
493
        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
494
    }
495
}
496

    
497
PropertyInfo qdev_prop_pci_devfn = {
498
    .name  = "pci-devfn",
499
    .type  = PROP_TYPE_UINT32,
500
    .size  = sizeof(uint32_t),
501
    .parse = parse_pci_devfn,
502
    .print = print_pci_devfn,
503
};
504

    
505
/* --- public helpers --- */
506

    
507
static Property *qdev_prop_walk(Property *props, const char *name)
508
{
509
    if (!props)
510
        return NULL;
511
    while (props->name) {
512
        if (strcmp(props->name, name) == 0)
513
            return props;
514
        props++;
515
    }
516
    return NULL;
517
}
518

    
519
static Property *qdev_prop_find(DeviceState *dev, const char *name)
520
{
521
    Property *prop;
522

    
523
    /* device properties */
524
    prop = qdev_prop_walk(dev->info->props, name);
525
    if (prop)
526
        return prop;
527

    
528
    /* bus properties */
529
    prop = qdev_prop_walk(dev->parent_bus->info->props, name);
530
    if (prop)
531
        return prop;
532

    
533
    return NULL;
534
}
535

    
536
int qdev_prop_exists(DeviceState *dev, const char *name)
537
{
538
    return qdev_prop_find(dev, name) ? true : false;
539
}
540

    
541
int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
542
{
543
    Property *prop;
544

    
545
    prop = qdev_prop_find(dev, name);
546
    if (!prop) {
547
        if (strcmp(name, "?") != 0) {
548
            fprintf(stderr, "property \"%s.%s\" not found\n",
549
                    dev->info->name, name);
550
        } else {
551
            fprintf(stderr, "supported properties:\n");
552
            if (dev->info->props != NULL) {
553
                Property *props = dev->info->props;
554
                while (props->name) {
555
                    fprintf(stderr, "%s.%s\n", dev->info->name, props->name);
556
                    props++;
557
                }
558
            }
559
        }
560
        return -1;
561
    }
562
    if (!prop->info->parse) {
563
        fprintf(stderr, "property \"%s.%s\" has no parser\n",
564
                dev->info->name, name);
565
        return -1;
566
    }
567
    if (prop->info->parse(dev, prop, value) != 0) {
568
        if (strcmp(value, "?") != 0) {
569
            fprintf(stderr, "property \"%s.%s\": failed to parse \"%s\"\n",
570
                    dev->info->name, name, value);
571
        } else {
572
            fprintf(stderr, "%s.%s=%s\n",
573
                    dev->info->name, name, prop->info->name);
574
        }
575
        return -1;
576
    }
577
    return 0;
578
}
579

    
580
void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type)
581
{
582
    Property *prop;
583

    
584
    prop = qdev_prop_find(dev, name);
585
    if (!prop) {
586
        fprintf(stderr, "%s: property \"%s.%s\" not found\n",
587
                __FUNCTION__, dev->info->name, name);
588
        abort();
589
    }
590
    if (prop->info->type != type) {
591
        fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n",
592
                __FUNCTION__, dev->info->name, name);
593
        abort();
594
    }
595
    qdev_prop_cpy(dev, prop, src);
596
}
597

    
598
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
599
{
600
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT8);
601
}
602

    
603
void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
604
{
605
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16);
606
}
607

    
608
void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
609
{
610
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32);
611
}
612

    
613
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
614
{
615
    qdev_prop_set(dev, name, &value, PROP_TYPE_INT32);
616
}
617

    
618
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
619
{
620
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64);
621
}
622

    
623
void qdev_prop_set_drive(DeviceState *dev, const char *name, DriveInfo *value)
624
{
625
    qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
626
}
627

    
628
void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
629
{
630
    qdev_prop_set(dev, name, &value, PROP_TYPE_CHR);
631
}
632

    
633
void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
634
{
635
    qdev_prop_set(dev, name, &value, PROP_TYPE_NETDEV);
636
}
637

    
638
void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
639
{
640
    qdev_prop_set(dev, name, &value, PROP_TYPE_VLAN);
641
}
642

    
643
void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
644
{
645
    qdev_prop_set(dev, name, value, PROP_TYPE_MACADDR);
646
}
647

    
648
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
649
{
650
    qdev_prop_set(dev, name, &value, PROP_TYPE_PTR);
651
}
652

    
653
void qdev_prop_set_defaults(DeviceState *dev, Property *props)
654
{
655
    if (!props)
656
        return;
657
    while (props->name) {
658
        if (props->defval) {
659
            qdev_prop_cpy(dev, props, props->defval);
660
        }
661
        props++;
662
    }
663
}
664

    
665
static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
666

    
667
void qdev_prop_register_global(GlobalProperty *prop)
668
{
669
    QTAILQ_INSERT_TAIL(&global_props, prop, next);
670
}
671

    
672
void qdev_prop_register_global_list(GlobalProperty *props)
673
{
674
    int i;
675

    
676
    for (i = 0; props[i].driver != NULL; i++) {
677
        qdev_prop_register_global(props+i);
678
    }
679
}
680

    
681
void qdev_prop_set_globals(DeviceState *dev)
682
{
683
    GlobalProperty *prop;
684

    
685
    QTAILQ_FOREACH(prop, &global_props, next) {
686
        if (strcmp(dev->info->name, prop->driver) != 0 &&
687
            strcmp(dev->info->bus_info->name, prop->driver) != 0) {
688
            continue;
689
        }
690
        if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
691
            exit(1);
692
        }
693
    }
694
}