Statistics
| Branch: | Revision:

root / hw / core / qdev-properties.c @ dccfcd0e

History | View | Annotate | Download (27.5 kB)

1
#include "net/net.h"
2
#include "hw/qdev.h"
3
#include "qapi/qmp/qerror.h"
4
#include "sysemu/blockdev.h"
5
#include "hw/block/block.h"
6
#include "net/hub.h"
7
#include "qapi/visitor.h"
8
#include "sysemu/char.h"
9

    
10
void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
11
                                  Error **errp)
12
{
13
    if (dev->id) {
14
        error_setg(errp, "Attempt to set property '%s' on device '%s' "
15
                   "(type '%s') after it was realized", name, dev->id,
16
                   object_get_typename(OBJECT(dev)));
17
    } else {
18
        error_setg(errp, "Attempt to set property '%s' on anonymous device "
19
                   "(type '%s') after it was realized", name,
20
                   object_get_typename(OBJECT(dev)));
21
    }
22
}
23

    
24
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
25
{
26
    void *ptr = dev;
27
    ptr += prop->offset;
28
    return ptr;
29
}
30

    
31
static void get_enum(Object *obj, Visitor *v, void *opaque,
32
                     const char *name, Error **errp)
33
{
34
    DeviceState *dev = DEVICE(obj);
35
    Property *prop = opaque;
36
    int *ptr = qdev_get_prop_ptr(dev, prop);
37

    
38
    visit_type_enum(v, ptr, prop->info->enum_table,
39
                    prop->info->name, prop->name, errp);
40
}
41

    
42
static void set_enum(Object *obj, Visitor *v, void *opaque,
43
                     const char *name, Error **errp)
44
{
45
    DeviceState *dev = DEVICE(obj);
46
    Property *prop = opaque;
47
    int *ptr = qdev_get_prop_ptr(dev, prop);
48

    
49
    if (dev->realized) {
50
        qdev_prop_set_after_realize(dev, name, errp);
51
        return;
52
    }
53

    
54
    visit_type_enum(v, ptr, prop->info->enum_table,
55
                    prop->info->name, prop->name, errp);
56
}
57

    
58
/* Bit */
59

    
60
static uint32_t qdev_get_prop_mask(Property *prop)
61
{
62
    assert(prop->info == &qdev_prop_bit);
63
    return 0x1 << prop->bitnr;
64
}
65

    
66
static void bit_prop_set(DeviceState *dev, Property *props, bool val)
67
{
68
    uint32_t *p = qdev_get_prop_ptr(dev, props);
69
    uint32_t mask = qdev_get_prop_mask(props);
70
    if (val) {
71
        *p |= mask;
72
    } else {
73
        *p &= ~mask;
74
    }
75
}
76

    
77
static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
78
{
79
    uint32_t *p = qdev_get_prop_ptr(dev, prop);
80
    return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
81
}
82

    
83
static void get_bit(Object *obj, Visitor *v, void *opaque,
84
                    const char *name, Error **errp)
85
{
86
    DeviceState *dev = DEVICE(obj);
87
    Property *prop = opaque;
88
    uint32_t *p = qdev_get_prop_ptr(dev, prop);
89
    bool value = (*p & qdev_get_prop_mask(prop)) != 0;
90

    
91
    visit_type_bool(v, &value, name, errp);
92
}
93

    
94
static void set_bit(Object *obj, Visitor *v, void *opaque,
95
                    const char *name, Error **errp)
96
{
97
    DeviceState *dev = DEVICE(obj);
98
    Property *prop = opaque;
99
    Error *local_err = NULL;
100
    bool value;
101

    
102
    if (dev->realized) {
103
        qdev_prop_set_after_realize(dev, name, errp);
104
        return;
105
    }
106

    
107
    visit_type_bool(v, &value, name, &local_err);
108
    if (local_err) {
109
        error_propagate(errp, local_err);
110
        return;
111
    }
112
    bit_prop_set(dev, prop, value);
113
}
114

    
115
PropertyInfo qdev_prop_bit = {
116
    .name  = "boolean",
117
    .legacy_name  = "on/off",
118
    .print = print_bit,
119
    .get   = get_bit,
120
    .set   = set_bit,
121
};
122

    
123
/* --- 8bit integer --- */
124

    
125
static void get_uint8(Object *obj, Visitor *v, void *opaque,
126
                      const char *name, Error **errp)
127
{
128
    DeviceState *dev = DEVICE(obj);
129
    Property *prop = opaque;
130
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
131

    
132
    visit_type_uint8(v, ptr, name, errp);
133
}
134

    
135
static void set_uint8(Object *obj, Visitor *v, void *opaque,
136
                      const char *name, Error **errp)
137
{
138
    DeviceState *dev = DEVICE(obj);
139
    Property *prop = opaque;
140
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
141

    
142
    if (dev->realized) {
143
        qdev_prop_set_after_realize(dev, name, errp);
144
        return;
145
    }
146

    
147
    visit_type_uint8(v, ptr, name, errp);
148
}
149

    
150
PropertyInfo qdev_prop_uint8 = {
151
    .name  = "uint8",
152
    .get   = get_uint8,
153
    .set   = set_uint8,
154
};
155

    
156
/* --- 8bit hex value --- */
157

    
158
static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
159
{
160
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
161
    char *end;
162

    
163
    if (str[0] != '0' || str[1] != 'x') {
164
        return -EINVAL;
165
    }
166

    
167
    *ptr = strtoul(str, &end, 16);
168
    if ((*end != '\0') || (end == str)) {
169
        return -EINVAL;
170
    }
171

    
172
    return 0;
173
}
174

    
175
static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
176
{
177
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
178
    return snprintf(dest, len, "0x%" PRIx8, *ptr);
179
}
180

    
181
PropertyInfo qdev_prop_hex8 = {
182
    .name  = "uint8",
183
    .legacy_name  = "hex8",
184
    .parse = parse_hex8,
185
    .print = print_hex8,
186
    .get   = get_uint8,
187
    .set   = set_uint8,
188
};
189

    
190
/* --- 16bit integer --- */
191

    
192
static void get_uint16(Object *obj, Visitor *v, void *opaque,
193
                       const char *name, Error **errp)
194
{
195
    DeviceState *dev = DEVICE(obj);
196
    Property *prop = opaque;
197
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
198

    
199
    visit_type_uint16(v, ptr, name, errp);
200
}
201

    
202
static void set_uint16(Object *obj, Visitor *v, void *opaque,
203
                       const char *name, Error **errp)
204
{
205
    DeviceState *dev = DEVICE(obj);
206
    Property *prop = opaque;
207
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
208

    
209
    if (dev->realized) {
210
        qdev_prop_set_after_realize(dev, name, errp);
211
        return;
212
    }
213

    
214
    visit_type_uint16(v, ptr, name, errp);
215
}
216

    
217
PropertyInfo qdev_prop_uint16 = {
218
    .name  = "uint16",
219
    .get   = get_uint16,
220
    .set   = set_uint16,
221
};
222

    
223
/* --- 32bit integer --- */
224

    
225
static void get_uint32(Object *obj, Visitor *v, void *opaque,
226
                       const char *name, Error **errp)
227
{
228
    DeviceState *dev = DEVICE(obj);
229
    Property *prop = opaque;
230
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
231

    
232
    visit_type_uint32(v, ptr, name, errp);
233
}
234

    
235
static void set_uint32(Object *obj, Visitor *v, void *opaque,
236
                       const char *name, Error **errp)
237
{
238
    DeviceState *dev = DEVICE(obj);
239
    Property *prop = opaque;
240
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
241

    
242
    if (dev->realized) {
243
        qdev_prop_set_after_realize(dev, name, errp);
244
        return;
245
    }
246

    
247
    visit_type_uint32(v, ptr, name, errp);
248
}
249

    
250
static void get_int32(Object *obj, Visitor *v, void *opaque,
251
                      const char *name, Error **errp)
252
{
253
    DeviceState *dev = DEVICE(obj);
254
    Property *prop = opaque;
255
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
256

    
257
    visit_type_int32(v, ptr, name, errp);
258
}
259

    
260
static void set_int32(Object *obj, Visitor *v, void *opaque,
261
                      const char *name, Error **errp)
262
{
263
    DeviceState *dev = DEVICE(obj);
264
    Property *prop = opaque;
265
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
266

    
267
    if (dev->realized) {
268
        qdev_prop_set_after_realize(dev, name, errp);
269
        return;
270
    }
271

    
272
    visit_type_int32(v, ptr, name, errp);
273
}
274

    
275
PropertyInfo qdev_prop_uint32 = {
276
    .name  = "uint32",
277
    .get   = get_uint32,
278
    .set   = set_uint32,
279
};
280

    
281
PropertyInfo qdev_prop_int32 = {
282
    .name  = "int32",
283
    .get   = get_int32,
284
    .set   = set_int32,
285
};
286

    
287
/* --- 32bit hex value --- */
288

    
289
static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
290
{
291
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
292
    char *end;
293

    
294
    if (str[0] != '0' || str[1] != 'x') {
295
        return -EINVAL;
296
    }
297

    
298
    *ptr = strtoul(str, &end, 16);
299
    if ((*end != '\0') || (end == str)) {
300
        return -EINVAL;
301
    }
302

    
303
    return 0;
304
}
305

    
306
static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
307
{
308
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
309
    return snprintf(dest, len, "0x%" PRIx32, *ptr);
310
}
311

    
312
PropertyInfo qdev_prop_hex32 = {
313
    .name  = "uint32",
314
    .legacy_name  = "hex32",
315
    .parse = parse_hex32,
316
    .print = print_hex32,
317
    .get   = get_uint32,
318
    .set   = set_uint32,
319
};
320

    
321
/* --- 64bit integer --- */
322

    
323
static void get_uint64(Object *obj, Visitor *v, void *opaque,
324
                       const char *name, Error **errp)
325
{
326
    DeviceState *dev = DEVICE(obj);
327
    Property *prop = opaque;
328
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
329

    
330
    visit_type_uint64(v, ptr, name, errp);
331
}
332

    
333
static void set_uint64(Object *obj, Visitor *v, void *opaque,
334
                       const char *name, Error **errp)
335
{
336
    DeviceState *dev = DEVICE(obj);
337
    Property *prop = opaque;
338
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
339

    
340
    if (dev->realized) {
341
        qdev_prop_set_after_realize(dev, name, errp);
342
        return;
343
    }
344

    
345
    visit_type_uint64(v, ptr, name, errp);
346
}
347

    
348
PropertyInfo qdev_prop_uint64 = {
349
    .name  = "uint64",
350
    .get   = get_uint64,
351
    .set   = set_uint64,
352
};
353

    
354
/* --- 64bit hex value --- */
355

    
356
static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
357
{
358
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
359
    char *end;
360

    
361
    if (str[0] != '0' || str[1] != 'x') {
362
        return -EINVAL;
363
    }
364

    
365
    *ptr = strtoull(str, &end, 16);
366
    if ((*end != '\0') || (end == str)) {
367
        return -EINVAL;
368
    }
369

    
370
    return 0;
371
}
372

    
373
static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
374
{
375
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
376
    return snprintf(dest, len, "0x%" PRIx64, *ptr);
377
}
378

    
379
PropertyInfo qdev_prop_hex64 = {
380
    .name  = "uint64",
381
    .legacy_name  = "hex64",
382
    .parse = parse_hex64,
383
    .print = print_hex64,
384
    .get   = get_uint64,
385
    .set   = set_uint64,
386
};
387

    
388
/* --- string --- */
389

    
390
static void release_string(Object *obj, const char *name, void *opaque)
391
{
392
    Property *prop = opaque;
393
    g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
394
}
395

    
396
static int print_string(DeviceState *dev, Property *prop, char *dest,
397
                        size_t len)
398
{
399
    char **ptr = qdev_get_prop_ptr(dev, prop);
400
    if (!*ptr) {
401
        return snprintf(dest, len, "<null>");
402
    }
403
    return snprintf(dest, len, "\"%s\"", *ptr);
404
}
405

    
406
static void get_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

    
413
    if (!*ptr) {
414
        char *str = (char *)"";
415
        visit_type_str(v, &str, name, errp);
416
    } else {
417
        visit_type_str(v, ptr, name, errp);
418
    }
419
}
420

    
421
static void set_string(Object *obj, Visitor *v, void *opaque,
422
                       const char *name, Error **errp)
423
{
424
    DeviceState *dev = DEVICE(obj);
425
    Property *prop = opaque;
426
    char **ptr = qdev_get_prop_ptr(dev, prop);
427
    Error *local_err = NULL;
428
    char *str;
429

    
430
    if (dev->realized) {
431
        qdev_prop_set_after_realize(dev, name, errp);
432
        return;
433
    }
434

    
435
    visit_type_str(v, &str, name, &local_err);
436
    if (local_err) {
437
        error_propagate(errp, local_err);
438
        return;
439
    }
440
    if (*ptr) {
441
        g_free(*ptr);
442
    }
443
    *ptr = str;
444
}
445

    
446
PropertyInfo qdev_prop_string = {
447
    .name  = "string",
448
    .print = print_string,
449
    .release = release_string,
450
    .get   = get_string,
451
    .set   = set_string,
452
};
453

    
454
/* --- pointer --- */
455

    
456
/* Not a proper property, just for dirty hacks.  TODO Remove it!  */
457
PropertyInfo qdev_prop_ptr = {
458
    .name  = "ptr",
459
};
460

    
461
/* --- mac address --- */
462

    
463
/*
464
 * accepted syntax versions:
465
 *   01:02:03:04:05:06
466
 *   01-02-03-04-05-06
467
 */
468
static void get_mac(Object *obj, Visitor *v, void *opaque,
469
                    const char *name, Error **errp)
470
{
471
    DeviceState *dev = DEVICE(obj);
472
    Property *prop = opaque;
473
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
474
    char buffer[2 * 6 + 5 + 1];
475
    char *p = buffer;
476

    
477
    snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
478
             mac->a[0], mac->a[1], mac->a[2],
479
             mac->a[3], mac->a[4], mac->a[5]);
480

    
481
    visit_type_str(v, &p, name, errp);
482
}
483

    
484
static void set_mac(Object *obj, Visitor *v, void *opaque,
485
                    const char *name, Error **errp)
486
{
487
    DeviceState *dev = DEVICE(obj);
488
    Property *prop = opaque;
489
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
490
    Error *local_err = NULL;
491
    int i, pos;
492
    char *str, *p;
493

    
494
    if (dev->realized) {
495
        qdev_prop_set_after_realize(dev, name, errp);
496
        return;
497
    }
498

    
499
    visit_type_str(v, &str, name, &local_err);
500
    if (local_err) {
501
        error_propagate(errp, local_err);
502
        return;
503
    }
504

    
505
    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
506
        if (!qemu_isxdigit(str[pos])) {
507
            goto inval;
508
        }
509
        if (!qemu_isxdigit(str[pos+1])) {
510
            goto inval;
511
        }
512
        if (i == 5) {
513
            if (str[pos+2] != '\0') {
514
                goto inval;
515
            }
516
        } else {
517
            if (str[pos+2] != ':' && str[pos+2] != '-') {
518
                goto inval;
519
            }
520
        }
521
        mac->a[i] = strtol(str+pos, &p, 16);
522
    }
523
    g_free(str);
524
    return;
525

    
526
inval:
527
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
528
    g_free(str);
529
}
530

    
531
PropertyInfo qdev_prop_macaddr = {
532
    .name  = "macaddr",
533
    .get   = get_mac,
534
    .set   = set_mac,
535
};
536

    
537
/* --- lost tick policy --- */
538

    
539
static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
540
    [LOST_TICK_DISCARD] = "discard",
541
    [LOST_TICK_DELAY] = "delay",
542
    [LOST_TICK_MERGE] = "merge",
543
    [LOST_TICK_SLEW] = "slew",
544
    [LOST_TICK_MAX] = NULL,
545
};
546

    
547
QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
548

    
549
PropertyInfo qdev_prop_losttickpolicy = {
550
    .name  = "LostTickPolicy",
551
    .enum_table  = lost_tick_policy_table,
552
    .get   = get_enum,
553
    .set   = set_enum,
554
};
555

    
556
/* --- BIOS CHS translation */
557

    
558
static const char *bios_chs_trans_table[] = {
559
    [BIOS_ATA_TRANSLATION_AUTO] = "auto",
560
    [BIOS_ATA_TRANSLATION_NONE] = "none",
561
    [BIOS_ATA_TRANSLATION_LBA]  = "lba",
562
};
563

    
564
PropertyInfo qdev_prop_bios_chs_trans = {
565
    .name = "bios-chs-trans",
566
    .enum_table = bios_chs_trans_table,
567
    .get = get_enum,
568
    .set = set_enum,
569
};
570

    
571
/* --- pci address --- */
572

    
573
/*
574
 * bus-local address, i.e. "$slot" or "$slot.$fn"
575
 */
576
static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
577
                          const char *name, Error **errp)
578
{
579
    DeviceState *dev = DEVICE(obj);
580
    Property *prop = opaque;
581
    int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
582
    unsigned int slot, fn, n;
583
    Error *local_err = NULL;
584
    char *str;
585

    
586
    if (dev->realized) {
587
        qdev_prop_set_after_realize(dev, name, errp);
588
        return;
589
    }
590

    
591
    visit_type_str(v, &str, name, &local_err);
592
    if (local_err) {
593
        error_free(local_err);
594
        local_err = NULL;
595
        visit_type_int32(v, &value, name, &local_err);
596
        if (local_err) {
597
            error_propagate(errp, local_err);
598
        } else if (value < -1 || value > 255) {
599
            error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
600
                      "pci_devfn");
601
        } else {
602
            *ptr = value;
603
        }
604
        return;
605
    }
606

    
607
    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
608
        fn = 0;
609
        if (sscanf(str, "%x%n", &slot, &n) != 1) {
610
            goto invalid;
611
        }
612
    }
613
    if (str[n] != '\0' || fn > 7 || slot > 31) {
614
        goto invalid;
615
    }
616
    *ptr = slot << 3 | fn;
617
    g_free(str);
618
    return;
619

    
620
invalid:
621
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
622
    g_free(str);
623
}
624

    
625
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
626
                           size_t len)
627
{
628
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
629

    
630
    if (*ptr == -1) {
631
        return snprintf(dest, len, "<unset>");
632
    } else {
633
        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
634
    }
635
}
636

    
637
PropertyInfo qdev_prop_pci_devfn = {
638
    .name  = "int32",
639
    .legacy_name  = "pci-devfn",
640
    .print = print_pci_devfn,
641
    .get   = get_int32,
642
    .set   = set_pci_devfn,
643
};
644

    
645
/* --- blocksize --- */
646

    
647
static void set_blocksize(Object *obj, Visitor *v, void *opaque,
648
                          const char *name, Error **errp)
649
{
650
    DeviceState *dev = DEVICE(obj);
651
    Property *prop = opaque;
652
    uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
653
    Error *local_err = NULL;
654
    const int64_t min = 512;
655
    const int64_t max = 32768;
656

    
657
    if (dev->realized) {
658
        qdev_prop_set_after_realize(dev, name, errp);
659
        return;
660
    }
661

    
662
    visit_type_uint16(v, &value, name, &local_err);
663
    if (local_err) {
664
        error_propagate(errp, local_err);
665
        return;
666
    }
667
    if (value < min || value > max) {
668
        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
669
                  dev->id?:"", name, (int64_t)value, min, max);
670
        return;
671
    }
672

    
673
    /* We rely on power-of-2 blocksizes for bitmasks */
674
    if ((value & (value - 1)) != 0) {
675
        error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
676
                  dev->id?:"", name, (int64_t)value);
677
        return;
678
    }
679

    
680
    *ptr = value;
681
}
682

    
683
PropertyInfo qdev_prop_blocksize = {
684
    .name  = "blocksize",
685
    .get   = get_uint16,
686
    .set   = set_blocksize,
687
};
688

    
689
/* --- pci host address --- */
690

    
691
static void get_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
692
                                 const char *name, Error **errp)
693
{
694
    DeviceState *dev = DEVICE(obj);
695
    Property *prop = opaque;
696
    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
697
    char buffer[] = "xxxx:xx:xx.x";
698
    char *p = buffer;
699
    int rc = 0;
700

    
701
    rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
702
                  addr->domain, addr->bus, addr->slot, addr->function);
703
    assert(rc == sizeof(buffer) - 1);
704

    
705
    visit_type_str(v, &p, name, errp);
706
}
707

    
708
/*
709
 * Parse [<domain>:]<bus>:<slot>.<func>
710
 *   if <domain> is not supplied, it's assumed to be 0.
711
 */
712
static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
713
                                 const char *name, Error **errp)
714
{
715
    DeviceState *dev = DEVICE(obj);
716
    Property *prop = opaque;
717
    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
718
    Error *local_err = NULL;
719
    char *str, *p;
720
    char *e;
721
    unsigned long val;
722
    unsigned long dom = 0, bus = 0;
723
    unsigned int slot = 0, func = 0;
724

    
725
    if (dev->realized) {
726
        qdev_prop_set_after_realize(dev, name, errp);
727
        return;
728
    }
729

    
730
    visit_type_str(v, &str, name, &local_err);
731
    if (local_err) {
732
        error_propagate(errp, local_err);
733
        return;
734
    }
735

    
736
    p = str;
737
    val = strtoul(p, &e, 16);
738
    if (e == p || *e != ':') {
739
        goto inval;
740
    }
741
    bus = val;
742

    
743
    p = e + 1;
744
    val = strtoul(p, &e, 16);
745
    if (e == p) {
746
        goto inval;
747
    }
748
    if (*e == ':') {
749
        dom = bus;
750
        bus = val;
751
        p = e + 1;
752
        val = strtoul(p, &e, 16);
753
        if (e == p) {
754
            goto inval;
755
        }
756
    }
757
    slot = val;
758

    
759
    if (*e != '.') {
760
        goto inval;
761
    }
762
    p = e + 1;
763
    val = strtoul(p, &e, 10);
764
    if (e == p) {
765
        goto inval;
766
    }
767
    func = val;
768

    
769
    if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
770
        goto inval;
771
    }
772

    
773
    if (*e) {
774
        goto inval;
775
    }
776

    
777
    addr->domain = dom;
778
    addr->bus = bus;
779
    addr->slot = slot;
780
    addr->function = func;
781

    
782
    g_free(str);
783
    return;
784

    
785
inval:
786
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
787
    g_free(str);
788
}
789

    
790
PropertyInfo qdev_prop_pci_host_devaddr = {
791
    .name = "pci-host-devaddr",
792
    .get = get_pci_host_devaddr,
793
    .set = set_pci_host_devaddr,
794
};
795

    
796
/* --- support for array properties --- */
797

    
798
/* Used as an opaque for the object properties we add for each
799
 * array element. Note that the struct Property must be first
800
 * in the struct so that a pointer to this works as the opaque
801
 * for the underlying element's property hooks as well as for
802
 * our own release callback.
803
 */
804
typedef struct {
805
    struct Property prop;
806
    char *propname;
807
    ObjectPropertyRelease *release;
808
} ArrayElementProperty;
809

    
810
/* object property release callback for array element properties:
811
 * we call the underlying element's property release hook, and
812
 * then free the memory we allocated when we added the property.
813
 */
814
static void array_element_release(Object *obj, const char *name, void *opaque)
815
{
816
    ArrayElementProperty *p = opaque;
817
    if (p->release) {
818
        p->release(obj, name, opaque);
819
    }
820
    g_free(p->propname);
821
    g_free(p);
822
}
823

    
824
static void set_prop_arraylen(Object *obj, Visitor *v, void *opaque,
825
                              const char *name, Error **errp)
826
{
827
    /* Setter for the property which defines the length of a
828
     * variable-sized property array. As well as actually setting the
829
     * array-length field in the device struct, we have to create the
830
     * array itself and dynamically add the corresponding properties.
831
     */
832
    DeviceState *dev = DEVICE(obj);
833
    Property *prop = opaque;
834
    uint32_t *alenptr = qdev_get_prop_ptr(dev, prop);
835
    void **arrayptr = (void *)dev + prop->arrayoffset;
836
    void *eltptr;
837
    const char *arrayname;
838
    int i;
839

    
840
    if (dev->realized) {
841
        qdev_prop_set_after_realize(dev, name, errp);
842
        return;
843
    }
844
    if (*alenptr) {
845
        error_setg(errp, "array size property %s may not be set more than once",
846
                   name);
847
        return;
848
    }
849
    visit_type_uint32(v, alenptr, name, errp);
850
    if (error_is_set(errp)) {
851
        return;
852
    }
853
    if (!*alenptr) {
854
        return;
855
    }
856

    
857
    /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
858
     * strip it off so we can get the name of the array itself.
859
     */
860
    assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
861
                   strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
862
    arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
863

    
864
    /* Note that it is the responsibility of the individual device's deinit
865
     * to free the array proper.
866
     */
867
    *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
868
    for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
869
        char *propname = g_strdup_printf("%s[%d]", arrayname, i);
870
        ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
871
        arrayprop->release = prop->arrayinfo->release;
872
        arrayprop->propname = propname;
873
        arrayprop->prop.info = prop->arrayinfo;
874
        arrayprop->prop.name = propname;
875
        /* This ugly piece of pointer arithmetic sets up the offset so
876
         * that when the underlying get/set hooks call qdev_get_prop_ptr
877
         * they get the right answer despite the array element not actually
878
         * being inside the device struct.
879
         */
880
        arrayprop->prop.offset = eltptr - (void *)dev;
881
        assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr);
882
        object_property_add(obj, propname,
883
                            arrayprop->prop.info->name,
884
                            arrayprop->prop.info->get,
885
                            arrayprop->prop.info->set,
886
                            array_element_release,
887
                            arrayprop, errp);
888
        if (error_is_set(errp)) {
889
            return;
890
        }
891
    }
892
}
893

    
894
PropertyInfo qdev_prop_arraylen = {
895
    .name = "uint32",
896
    .get = get_uint32,
897
    .set = set_prop_arraylen,
898
};
899

    
900
/* --- public helpers --- */
901

    
902
static Property *qdev_prop_walk(Property *props, const char *name)
903
{
904
    if (!props) {
905
        return NULL;
906
    }
907
    while (props->name) {
908
        if (strcmp(props->name, name) == 0) {
909
            return props;
910
        }
911
        props++;
912
    }
913
    return NULL;
914
}
915

    
916
static Property *qdev_prop_find(DeviceState *dev, const char *name)
917
{
918
    ObjectClass *class;
919
    Property *prop;
920

    
921
    /* device properties */
922
    class = object_get_class(OBJECT(dev));
923
    do {
924
        prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
925
        if (prop) {
926
            return prop;
927
        }
928
        class = object_class_get_parent(class);
929
    } while (class != object_class_by_name(TYPE_DEVICE));
930

    
931
    return NULL;
932
}
933

    
934
void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
935
                                    Property *prop, const char *value)
936
{
937
    switch (ret) {
938
    case -EEXIST:
939
        error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
940
                  object_get_typename(OBJECT(dev)), prop->name, value);
941
        break;
942
    default:
943
    case -EINVAL:
944
        error_set(errp, QERR_PROPERTY_VALUE_BAD,
945
                  object_get_typename(OBJECT(dev)), prop->name, value);
946
        break;
947
    case -ENOENT:
948
        error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
949
                  object_get_typename(OBJECT(dev)), prop->name, value);
950
        break;
951
    case 0:
952
        break;
953
    }
954
}
955

    
956
int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
957
{
958
    char *legacy_name;
959
    Error *err = NULL;
960

    
961
    legacy_name = g_strdup_printf("legacy-%s", name);
962
    if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
963
        object_property_parse(OBJECT(dev), value, legacy_name, &err);
964
    } else {
965
        object_property_parse(OBJECT(dev), value, name, &err);
966
    }
967
    g_free(legacy_name);
968

    
969
    if (err) {
970
        qerror_report_err(err);
971
        error_free(err);
972
        return -1;
973
    }
974
    return 0;
975
}
976

    
977
void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
978
{
979
    Error *errp = NULL;
980
    object_property_set_bool(OBJECT(dev), value, name, &errp);
981
    assert_no_error(errp);
982
}
983

    
984
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
985
{
986
    Error *errp = NULL;
987
    object_property_set_int(OBJECT(dev), value, name, &errp);
988
    assert_no_error(errp);
989
}
990

    
991
void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
992
{
993
    Error *errp = NULL;
994
    object_property_set_int(OBJECT(dev), value, name, &errp);
995
    assert_no_error(errp);
996
}
997

    
998
void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
999
{
1000
    Error *errp = NULL;
1001
    object_property_set_int(OBJECT(dev), value, name, &errp);
1002
    assert_no_error(errp);
1003
}
1004

    
1005
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1006
{
1007
    Error *errp = NULL;
1008
    object_property_set_int(OBJECT(dev), value, name, &errp);
1009
    assert_no_error(errp);
1010
}
1011

    
1012
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1013
{
1014
    Error *errp = NULL;
1015
    object_property_set_int(OBJECT(dev), value, name, &errp);
1016
    assert_no_error(errp);
1017
}
1018

    
1019
void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
1020
{
1021
    Error *errp = NULL;
1022
    object_property_set_str(OBJECT(dev), value, name, &errp);
1023
    assert_no_error(errp);
1024
}
1025

    
1026
void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1027
{
1028
    Error *errp = NULL;
1029
    char str[2 * 6 + 5 + 1];
1030
    snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
1031
             value[0], value[1], value[2], value[3], value[4], value[5]);
1032

    
1033
    object_property_set_str(OBJECT(dev), str, name, &errp);
1034
    assert_no_error(errp);
1035
}
1036

    
1037
void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
1038
{
1039
    Property *prop;
1040
    Error *errp = NULL;
1041

    
1042
    prop = qdev_prop_find(dev, name);
1043
    object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1044
                            name, &errp);
1045
    assert_no_error(errp);
1046
}
1047

    
1048
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1049
{
1050
    Property *prop;
1051
    void **ptr;
1052

    
1053
    prop = qdev_prop_find(dev, name);
1054
    assert(prop && prop->info == &qdev_prop_ptr);
1055
    ptr = qdev_get_prop_ptr(dev, prop);
1056
    *ptr = value;
1057
}
1058

    
1059
static QTAILQ_HEAD(, GlobalProperty) global_props =
1060
        QTAILQ_HEAD_INITIALIZER(global_props);
1061

    
1062
void qdev_prop_register_global(GlobalProperty *prop)
1063
{
1064
    QTAILQ_INSERT_TAIL(&global_props, prop, next);
1065
}
1066

    
1067
void qdev_prop_register_global_list(GlobalProperty *props)
1068
{
1069
    int i;
1070

    
1071
    for (i = 0; props[i].driver != NULL; i++) {
1072
        qdev_prop_register_global(props+i);
1073
    }
1074
}
1075

    
1076
void qdev_prop_set_globals(DeviceState *dev)
1077
{
1078
    ObjectClass *class = object_get_class(OBJECT(dev));
1079

    
1080
    do {
1081
        GlobalProperty *prop;
1082
        QTAILQ_FOREACH(prop, &global_props, next) {
1083
            if (strcmp(object_class_get_name(class), prop->driver) != 0) {
1084
                continue;
1085
            }
1086
            if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
1087
                exit(1);
1088
            }
1089
        }
1090
        class = object_class_get_parent(class);
1091
    } while (class);
1092
}