Statistics
| Branch: | Revision:

root / hw / qdev-properties.c @ d8ed79ae

History | View | Annotate | Download (14.6 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
/* --- 8bit integer --- */
13

    
14
static int parse_uint8(DeviceState *dev, Property *prop, const char *str)
15
{
16
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
17
    const char *fmt;
18

    
19
    /* accept both hex and decimal */
20
    fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx8 : "%" PRIu8;
21
    if (sscanf(str, fmt, ptr) != 1)
22
        return -1;
23
    return 0;
24
}
25

    
26
static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len)
27
{
28
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
29
    return snprintf(dest, len, "%" PRIu8, *ptr);
30
}
31

    
32
PropertyInfo qdev_prop_uint8 = {
33
    .name  = "uint8",
34
    .type  = PROP_TYPE_UINT8,
35
    .size  = sizeof(uint8_t),
36
    .parse = parse_uint8,
37
    .print = print_uint8,
38
};
39

    
40
/* --- 16bit integer --- */
41

    
42
static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
43
{
44
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
45
    const char *fmt;
46

    
47
    /* accept both hex and decimal */
48
    fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx16 : "%" PRIu16;
49
    if (sscanf(str, fmt, ptr) != 1)
50
        return -1;
51
    return 0;
52
}
53

    
54
static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len)
55
{
56
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
57
    return snprintf(dest, len, "%" PRIu16, *ptr);
58
}
59

    
60
PropertyInfo qdev_prop_uint16 = {
61
    .name  = "uint16",
62
    .type  = PROP_TYPE_UINT16,
63
    .size  = sizeof(uint16_t),
64
    .parse = parse_uint16,
65
    .print = print_uint16,
66
};
67

    
68
/* --- 32bit integer --- */
69

    
70
static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
71
{
72
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
73
    const char *fmt;
74

    
75
    /* accept both hex and decimal */
76
    fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx32 : "%" PRIu32;
77
    if (sscanf(str, fmt, ptr) != 1)
78
        return -1;
79
    return 0;
80
}
81

    
82
static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
83
{
84
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
85
    return snprintf(dest, len, "%" PRIu32, *ptr);
86
}
87

    
88
PropertyInfo qdev_prop_uint32 = {
89
    .name  = "uint32",
90
    .type  = PROP_TYPE_UINT32,
91
    .size  = sizeof(uint32_t),
92
    .parse = parse_uint32,
93
    .print = print_uint32,
94
};
95

    
96
static int parse_int32(DeviceState *dev, Property *prop, const char *str)
97
{
98
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
99

    
100
    if (sscanf(str, "%" PRId32, ptr) != 1)
101
        return -1;
102
    return 0;
103
}
104

    
105
static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len)
106
{
107
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
108
    return snprintf(dest, len, "%" PRId32, *ptr);
109
}
110

    
111
PropertyInfo qdev_prop_int32 = {
112
    .name  = "int32",
113
    .type  = PROP_TYPE_INT32,
114
    .size  = sizeof(int32_t),
115
    .parse = parse_int32,
116
    .print = print_int32,
117
};
118

    
119
/* --- 32bit hex value --- */
120

    
121
static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
122
{
123
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
124

    
125
    if (sscanf(str, "%" PRIx32, ptr) != 1)
126
        return -1;
127
    return 0;
128
}
129

    
130
static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
131
{
132
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
133
    return snprintf(dest, len, "0x%" PRIx32, *ptr);
134
}
135

    
136
PropertyInfo qdev_prop_hex32 = {
137
    .name  = "hex32",
138
    .type  = PROP_TYPE_UINT32,
139
    .size  = sizeof(uint32_t),
140
    .parse = parse_hex32,
141
    .print = print_hex32,
142
};
143

    
144
/* --- 64bit integer --- */
145

    
146
static int parse_uint64(DeviceState *dev, Property *prop, const char *str)
147
{
148
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
149
    const char *fmt;
150

    
151
    /* accept both hex and decimal */
152
    fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx64 : "%" PRIu64;
153
    if (sscanf(str, fmt, ptr) != 1)
154
        return -1;
155
    return 0;
156
}
157

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

    
164
PropertyInfo qdev_prop_uint64 = {
165
    .name  = "uint64",
166
    .type  = PROP_TYPE_UINT64,
167
    .size  = sizeof(uint64_t),
168
    .parse = parse_uint64,
169
    .print = print_uint64,
170
};
171

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

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

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

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

    
189
PropertyInfo qdev_prop_hex64 = {
190
    .name  = "hex64",
191
    .type  = PROP_TYPE_UINT64,
192
    .size  = sizeof(uint64_t),
193
    .parse = parse_hex64,
194
    .print = print_hex64,
195
};
196

    
197
/* --- string --- */
198

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

    
203
    if (*ptr)
204
        qemu_free(*ptr);
205
    *ptr = qemu_strdup(str);
206
    return 0;
207
}
208

    
209
static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
210
{
211
    char **ptr = qdev_get_prop_ptr(dev, prop);
212
    if (!*ptr)
213
        return snprintf(dest, len, "<null>");
214
    return snprintf(dest, len, "\"%s\"", *ptr);
215
}
216

    
217
PropertyInfo qdev_prop_string = {
218
    .name  = "string",
219
    .type  = PROP_TYPE_STRING,
220
    .size  = sizeof(char*),
221
    .parse = parse_string,
222
    .print = print_string,
223
};
224

    
225
/* --- drive --- */
226

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

    
231
    *ptr = drive_get_by_id(str);
232
    if (*ptr == NULL)
233
        return -1;
234
    return 0;
235
}
236

    
237
static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len)
238
{
239
    DriveInfo **ptr = qdev_get_prop_ptr(dev, prop);
240
    return snprintf(dest, len, "%s", (*ptr) ? (*ptr)->id : "<null>");
241
}
242

    
243
PropertyInfo qdev_prop_drive = {
244
    .name  = "drive",
245
    .type  = PROP_TYPE_DRIVE,
246
    .size  = sizeof(DriveInfo*),
247
    .parse = parse_drive,
248
    .print = print_drive,
249
};
250

    
251
/* --- character device --- */
252

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

    
257
    *ptr = qemu_chr_find(str);
258
    if (*ptr == NULL)
259
        return -1;
260
    return 0;
261
}
262

    
263
static int print_chr(DeviceState *dev, Property *prop, char *dest, size_t len)
264
{
265
    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
266

    
267
    if (*ptr && (*ptr)->label) {
268
        return snprintf(dest, len, "%s", (*ptr)->label);
269
    } else {
270
        return snprintf(dest, len, "<null>");
271
    }
272
}
273

    
274
PropertyInfo qdev_prop_chr = {
275
    .name  = "chr",
276
    .type  = PROP_TYPE_CHR,
277
    .size  = sizeof(CharDriverState*),
278
    .parse = parse_chr,
279
    .print = print_chr,
280
};
281

    
282
/* --- netdev device --- */
283

    
284
static int parse_netdev(DeviceState *dev, Property *prop, const char *str)
285
{
286
    VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
287

    
288
    *ptr = qemu_find_netdev(str);
289
    if (*ptr == NULL)
290
        return -1;
291
    return 0;
292
}
293

    
294
static int print_netdev(DeviceState *dev, Property *prop, char *dest, size_t len)
295
{
296
    VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
297

    
298
    if (*ptr && (*ptr)->name) {
299
        return snprintf(dest, len, "%s", (*ptr)->name);
300
    } else {
301
        return snprintf(dest, len, "<null>");
302
    }
303
}
304

    
305
PropertyInfo qdev_prop_netdev = {
306
    .name  = "netdev",
307
    .type  = PROP_TYPE_NETDEV,
308
    .size  = sizeof(VLANClientState*),
309
    .parse = parse_netdev,
310
    .print = print_netdev,
311
};
312

    
313
/* --- vlan --- */
314

    
315
static int parse_vlan(DeviceState *dev, Property *prop, const char *str)
316
{
317
    VLANState **ptr = qdev_get_prop_ptr(dev, prop);
318
    int id;
319

    
320
    if (sscanf(str, "%d", &id) != 1)
321
        return -1;
322
    *ptr = qemu_find_vlan(id, 1);
323
    if (*ptr == NULL)
324
        return -1;
325
    return 0;
326
}
327

    
328
static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
329
{
330
    VLANState **ptr = qdev_get_prop_ptr(dev, prop);
331

    
332
    if (*ptr) {
333
        return snprintf(dest, len, "%d", (*ptr)->id);
334
    } else {
335
        return snprintf(dest, len, "<null>");
336
    }
337
}
338

    
339
PropertyInfo qdev_prop_vlan = {
340
    .name  = "vlan",
341
    .type  = PROP_TYPE_VLAN,
342
    .size  = sizeof(VLANClientState*),
343
    .parse = parse_vlan,
344
    .print = print_vlan,
345
};
346

    
347
/* --- pointer --- */
348

    
349
static int print_ptr(DeviceState *dev, Property *prop, char *dest, size_t len)
350
{
351
    void **ptr = qdev_get_prop_ptr(dev, prop);
352
    return snprintf(dest, len, "<%p>", *ptr);
353
}
354

    
355
PropertyInfo qdev_prop_ptr = {
356
    .name  = "ptr",
357
    .type  = PROP_TYPE_PTR,
358
    .size  = sizeof(void*),
359
    .print = print_ptr,
360
};
361

    
362
/* --- mac address --- */
363

    
364
/*
365
 * accepted syntax versions:
366
 *   01:02:03:04:05:06
367
 *   01-02-03-04-05-06
368
 */
369
static int parse_mac(DeviceState *dev, Property *prop, const char *str)
370
{
371
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
372
    int i, pos;
373
    char *p;
374

    
375
    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
376
        if (!qemu_isxdigit(str[pos]))
377
            return -1;
378
        if (!qemu_isxdigit(str[pos+1]))
379
            return -1;
380
        if (i == 5) {
381
            if (str[pos+2] != '\0')
382
                return -1;
383
        } else {
384
            if (str[pos+2] != ':' && str[pos+2] != '-')
385
                return -1;
386
        }
387
        mac->a[i] = strtol(str+pos, &p, 16);
388
    }
389
    return 0;
390
}
391

    
392
static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len)
393
{
394
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
395

    
396
    return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x",
397
                    mac->a[0], mac->a[1], mac->a[2],
398
                    mac->a[3], mac->a[4], mac->a[5]);
399
}
400

    
401
PropertyInfo qdev_prop_macaddr = {
402
    .name  = "macaddr",
403
    .type  = PROP_TYPE_MACADDR,
404
    .size  = sizeof(MACAddr),
405
    .parse = parse_mac,
406
    .print = print_mac,
407
};
408

    
409
/* --- pci address --- */
410

    
411
/*
412
 * bus-local address, i.e. "$slot" or "$slot.$fn"
413
 */
414
static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str)
415
{
416
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
417
    unsigned int slot, fn, n;
418

    
419
    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
420
        fn = 0;
421
        if (sscanf(str, "%x%n", &slot, &n) != 1) {
422
            return -1;
423
        }
424
    }
425
    if (str[n] != '\0')
426
        return -1;
427
    if (fn > 7)
428
        return -1;
429
    *ptr = slot << 3 | fn;
430
    return 0;
431
}
432

    
433
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
434
{
435
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
436

    
437
    if (*ptr == -1) {
438
        return snprintf(dest, len, "<unset>");
439
    } else {
440
        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
441
    }
442
}
443

    
444
PropertyInfo qdev_prop_pci_devfn = {
445
    .name  = "pci-devfn",
446
    .type  = PROP_TYPE_UINT32,
447
    .size  = sizeof(uint32_t),
448
    .parse = parse_pci_devfn,
449
    .print = print_pci_devfn,
450
};
451

    
452
/* --- public helpers --- */
453

    
454
static Property *qdev_prop_walk(Property *props, const char *name)
455
{
456
    if (!props)
457
        return NULL;
458
    while (props->name) {
459
        if (strcmp(props->name, name) == 0)
460
            return props;
461
        props++;
462
    }
463
    return NULL;
464
}
465

    
466
static Property *qdev_prop_find(DeviceState *dev, const char *name)
467
{
468
    Property *prop;
469

    
470
    /* device properties */
471
    prop = qdev_prop_walk(dev->info->props, name);
472
    if (prop)
473
        return prop;
474

    
475
    /* bus properties */
476
    prop = qdev_prop_walk(dev->parent_bus->info->props, name);
477
    if (prop)
478
        return prop;
479

    
480
    return NULL;
481
}
482

    
483
int qdev_prop_exists(DeviceState *dev, const char *name)
484
{
485
    return qdev_prop_find(dev, name) ? true : false;
486
}
487

    
488
int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
489
{
490
    Property *prop;
491

    
492
    prop = qdev_prop_find(dev, name);
493
    if (!prop) {
494
        fprintf(stderr, "property \"%s.%s\" not found\n",
495
                dev->info->name, name);
496
        return -1;
497
    }
498
    if (!prop->info->parse) {
499
        fprintf(stderr, "property \"%s.%s\" has no parser\n",
500
                dev->info->name, name);
501
        return -1;
502
    }
503
    return prop->info->parse(dev, prop, value);
504
}
505

    
506
void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type)
507
{
508
    Property *prop;
509
    void *dst;
510

    
511
    prop = qdev_prop_find(dev, name);
512
    if (!prop) {
513
        fprintf(stderr, "%s: property \"%s.%s\" not found\n",
514
                __FUNCTION__, dev->info->name, name);
515
        abort();
516
    }
517
    if (prop->info->type != type) {
518
        fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n",
519
                __FUNCTION__, dev->info->name, name);
520
        abort();
521
    }
522
    dst = qdev_get_prop_ptr(dev, prop);
523
    memcpy(dst, src, prop->info->size);
524
}
525

    
526
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
527
{
528
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT8);
529
}
530

    
531
void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
532
{
533
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16);
534
}
535

    
536
void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
537
{
538
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32);
539
}
540

    
541
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
542
{
543
    qdev_prop_set(dev, name, &value, PROP_TYPE_INT32);
544
}
545

    
546
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
547
{
548
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64);
549
}
550

    
551
void qdev_prop_set_drive(DeviceState *dev, const char *name, DriveInfo *value)
552
{
553
    qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
554
}
555

    
556
void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
557
{
558
    qdev_prop_set(dev, name, &value, PROP_TYPE_CHR);
559
}
560

    
561
void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
562
{
563
    qdev_prop_set(dev, name, &value, PROP_TYPE_NETDEV);
564
}
565

    
566
void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
567
{
568
    qdev_prop_set(dev, name, &value, PROP_TYPE_VLAN);
569
}
570

    
571
void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
572
{
573
    qdev_prop_set(dev, name, value, PROP_TYPE_MACADDR);
574
}
575

    
576
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
577
{
578
    qdev_prop_set(dev, name, &value, PROP_TYPE_PTR);
579
}
580

    
581
void qdev_prop_set_defaults(DeviceState *dev, Property *props)
582
{
583
    char *dst;
584

    
585
    if (!props)
586
        return;
587
    while (props->name) {
588
        if (props->defval) {
589
            dst = qdev_get_prop_ptr(dev, props);
590
            memcpy(dst, props->defval, props->info->size);
591
        }
592
        props++;
593
    }
594
}
595

    
596
static CompatProperty *compat_props;
597

    
598
void qdev_prop_register_compat(CompatProperty *props)
599
{
600
    compat_props = props;
601
}
602

    
603
void qdev_prop_set_compat(DeviceState *dev)
604
{
605
    CompatProperty *prop;
606

    
607
    if (!compat_props) {
608
        return;
609
    }
610
    for (prop = compat_props; prop->driver != NULL; prop++) {
611
        if (strcmp(dev->info->name, prop->driver) != 0) {
612
            continue;
613
        }
614
        if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
615
            abort();
616
        }
617
    }
618
}