Statistics
| Branch: | Revision:

root / hw / qdev-properties.c @ a005d073

History | View | Annotate | Download (30.9 kB)

1
#include "net.h"
2
#include "qdev.h"
3
#include "qerror.h"
4
#include "blockdev.h"
5
#include "hw/block-common.h"
6
#include "net/hub.h"
7

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

    
15
static void get_pointer(Object *obj, Visitor *v, Property *prop,
16
                        const char *(*print)(void *ptr),
17
                        const char *name, Error **errp)
18
{
19
    DeviceState *dev = DEVICE(obj);
20
    void **ptr = qdev_get_prop_ptr(dev, prop);
21
    char *p;
22

    
23
    p = (char *) (*ptr ? print(*ptr) : "");
24
    visit_type_str(v, &p, name, errp);
25
}
26

    
27
static void set_pointer(Object *obj, Visitor *v, Property *prop,
28
                        int (*parse)(DeviceState *dev, const char *str,
29
                                     void **ptr),
30
                        const char *name, Error **errp)
31
{
32
    DeviceState *dev = DEVICE(obj);
33
    Error *local_err = NULL;
34
    void **ptr = qdev_get_prop_ptr(dev, prop);
35
    char *str;
36
    int ret;
37

    
38
    if (dev->state != DEV_STATE_CREATED) {
39
        error_set(errp, QERR_PERMISSION_DENIED);
40
        return;
41
    }
42

    
43
    visit_type_str(v, &str, name, &local_err);
44
    if (local_err) {
45
        error_propagate(errp, local_err);
46
        return;
47
    }
48
    if (!*str) {
49
        g_free(str);
50
        *ptr = NULL;
51
        return;
52
    }
53
    ret = parse(dev, str, ptr);
54
    error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
55
    g_free(str);
56
}
57

    
58
static void get_enum(Object *obj, Visitor *v, void *opaque,
59
                     const char *name, Error **errp)
60
{
61
    DeviceState *dev = DEVICE(obj);
62
    Property *prop = opaque;
63
    int *ptr = qdev_get_prop_ptr(dev, prop);
64

    
65
    visit_type_enum(v, ptr, prop->info->enum_table,
66
                    prop->info->name, prop->name, errp);
67
}
68

    
69
static void set_enum(Object *obj, Visitor *v, void *opaque,
70
                     const char *name, Error **errp)
71
{
72
    DeviceState *dev = DEVICE(obj);
73
    Property *prop = opaque;
74
    int *ptr = qdev_get_prop_ptr(dev, prop);
75

    
76
    if (dev->state != DEV_STATE_CREATED) {
77
        error_set(errp, QERR_PERMISSION_DENIED);
78
        return;
79
    }
80

    
81
    visit_type_enum(v, ptr, prop->info->enum_table,
82
                    prop->info->name, prop->name, errp);
83
}
84

    
85
/* Bit */
86

    
87
static uint32_t qdev_get_prop_mask(Property *prop)
88
{
89
    assert(prop->info == &qdev_prop_bit);
90
    return 0x1 << prop->bitnr;
91
}
92

    
93
static void bit_prop_set(DeviceState *dev, Property *props, bool val)
94
{
95
    uint32_t *p = qdev_get_prop_ptr(dev, props);
96
    uint32_t mask = qdev_get_prop_mask(props);
97
    if (val)
98
        *p |= mask;
99
    else
100
        *p &= ~mask;
101
}
102

    
103
static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
104
{
105
    uint32_t *p = qdev_get_prop_ptr(dev, prop);
106
    return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
107
}
108

    
109
static void get_bit(Object *obj, Visitor *v, void *opaque,
110
                    const char *name, Error **errp)
111
{
112
    DeviceState *dev = DEVICE(obj);
113
    Property *prop = opaque;
114
    uint32_t *p = qdev_get_prop_ptr(dev, prop);
115
    bool value = (*p & qdev_get_prop_mask(prop)) != 0;
116

    
117
    visit_type_bool(v, &value, name, errp);
118
}
119

    
120
static void set_bit(Object *obj, Visitor *v, void *opaque,
121
                    const char *name, Error **errp)
122
{
123
    DeviceState *dev = DEVICE(obj);
124
    Property *prop = opaque;
125
    Error *local_err = NULL;
126
    bool value;
127

    
128
    if (dev->state != DEV_STATE_CREATED) {
129
        error_set(errp, QERR_PERMISSION_DENIED);
130
        return;
131
    }
132

    
133
    visit_type_bool(v, &value, name, &local_err);
134
    if (local_err) {
135
        error_propagate(errp, local_err);
136
        return;
137
    }
138
    bit_prop_set(dev, prop, value);
139
}
140

    
141
PropertyInfo qdev_prop_bit = {
142
    .name  = "boolean",
143
    .legacy_name  = "on/off",
144
    .print = print_bit,
145
    .get   = get_bit,
146
    .set   = set_bit,
147
};
148

    
149
/* --- 8bit integer --- */
150

    
151
static void get_uint8(Object *obj, Visitor *v, void *opaque,
152
                      const char *name, Error **errp)
153
{
154
    DeviceState *dev = DEVICE(obj);
155
    Property *prop = opaque;
156
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
157

    
158
    visit_type_uint8(v, ptr, name, errp);
159
}
160

    
161
static void set_uint8(Object *obj, Visitor *v, void *opaque,
162
                      const char *name, Error **errp)
163
{
164
    DeviceState *dev = DEVICE(obj);
165
    Property *prop = opaque;
166
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
167

    
168
    if (dev->state != DEV_STATE_CREATED) {
169
        error_set(errp, QERR_PERMISSION_DENIED);
170
        return;
171
    }
172

    
173
    visit_type_uint8(v, ptr, name, errp);
174
}
175

    
176
PropertyInfo qdev_prop_uint8 = {
177
    .name  = "uint8",
178
    .get   = get_uint8,
179
    .set   = set_uint8,
180
};
181

    
182
/* --- 8bit hex value --- */
183

    
184
static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
185
{
186
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
187
    char *end;
188

    
189
    if (str[0] != '0' || str[1] != 'x') {
190
        return -EINVAL;
191
    }
192

    
193
    *ptr = strtoul(str, &end, 16);
194
    if ((*end != '\0') || (end == str)) {
195
        return -EINVAL;
196
    }
197

    
198
    return 0;
199
}
200

    
201
static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
202
{
203
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
204
    return snprintf(dest, len, "0x%" PRIx8, *ptr);
205
}
206

    
207
PropertyInfo qdev_prop_hex8 = {
208
    .name  = "uint8",
209
    .legacy_name  = "hex8",
210
    .parse = parse_hex8,
211
    .print = print_hex8,
212
    .get   = get_uint8,
213
    .set   = set_uint8,
214
};
215

    
216
/* --- 16bit integer --- */
217

    
218
static void get_uint16(Object *obj, Visitor *v, void *opaque,
219
                       const char *name, Error **errp)
220
{
221
    DeviceState *dev = DEVICE(obj);
222
    Property *prop = opaque;
223
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
224

    
225
    visit_type_uint16(v, ptr, name, errp);
226
}
227

    
228
static void set_uint16(Object *obj, Visitor *v, void *opaque,
229
                       const char *name, Error **errp)
230
{
231
    DeviceState *dev = DEVICE(obj);
232
    Property *prop = opaque;
233
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
234

    
235
    if (dev->state != DEV_STATE_CREATED) {
236
        error_set(errp, QERR_PERMISSION_DENIED);
237
        return;
238
    }
239

    
240
    visit_type_uint16(v, ptr, name, errp);
241
}
242

    
243
PropertyInfo qdev_prop_uint16 = {
244
    .name  = "uint16",
245
    .get   = get_uint16,
246
    .set   = set_uint16,
247
};
248

    
249
/* --- 32bit integer --- */
250

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

    
258
    visit_type_uint32(v, ptr, name, errp);
259
}
260

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

    
268
    if (dev->state != DEV_STATE_CREATED) {
269
        error_set(errp, QERR_PERMISSION_DENIED);
270
        return;
271
    }
272

    
273
    visit_type_uint32(v, ptr, name, errp);
274
}
275

    
276
static void get_int32(Object *obj, Visitor *v, void *opaque,
277
                      const char *name, Error **errp)
278
{
279
    DeviceState *dev = DEVICE(obj);
280
    Property *prop = opaque;
281
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
282

    
283
    visit_type_int32(v, ptr, name, errp);
284
}
285

    
286
static void set_int32(Object *obj, Visitor *v, void *opaque,
287
                      const char *name, Error **errp)
288
{
289
    DeviceState *dev = DEVICE(obj);
290
    Property *prop = opaque;
291
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
292

    
293
    if (dev->state != DEV_STATE_CREATED) {
294
        error_set(errp, QERR_PERMISSION_DENIED);
295
        return;
296
    }
297

    
298
    visit_type_int32(v, ptr, name, errp);
299
}
300

    
301
PropertyInfo qdev_prop_uint32 = {
302
    .name  = "uint32",
303
    .get   = get_uint32,
304
    .set   = set_uint32,
305
};
306

    
307
PropertyInfo qdev_prop_int32 = {
308
    .name  = "int32",
309
    .get   = get_int32,
310
    .set   = set_int32,
311
};
312

    
313
/* --- 32bit hex value --- */
314

    
315
static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
316
{
317
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
318
    char *end;
319

    
320
    if (str[0] != '0' || str[1] != 'x') {
321
        return -EINVAL;
322
    }
323

    
324
    *ptr = strtoul(str, &end, 16);
325
    if ((*end != '\0') || (end == str)) {
326
        return -EINVAL;
327
    }
328

    
329
    return 0;
330
}
331

    
332
static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
333
{
334
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
335
    return snprintf(dest, len, "0x%" PRIx32, *ptr);
336
}
337

    
338
PropertyInfo qdev_prop_hex32 = {
339
    .name  = "uint32",
340
    .legacy_name  = "hex32",
341
    .parse = parse_hex32,
342
    .print = print_hex32,
343
    .get   = get_uint32,
344
    .set   = set_uint32,
345
};
346

    
347
/* --- 64bit integer --- */
348

    
349
static void get_uint64(Object *obj, Visitor *v, void *opaque,
350
                       const char *name, Error **errp)
351
{
352
    DeviceState *dev = DEVICE(obj);
353
    Property *prop = opaque;
354
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
355

    
356
    visit_type_uint64(v, ptr, name, errp);
357
}
358

    
359
static void set_uint64(Object *obj, Visitor *v, void *opaque,
360
                       const char *name, Error **errp)
361
{
362
    DeviceState *dev = DEVICE(obj);
363
    Property *prop = opaque;
364
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
365

    
366
    if (dev->state != DEV_STATE_CREATED) {
367
        error_set(errp, QERR_PERMISSION_DENIED);
368
        return;
369
    }
370

    
371
    visit_type_uint64(v, ptr, name, errp);
372
}
373

    
374
PropertyInfo qdev_prop_uint64 = {
375
    .name  = "uint64",
376
    .get   = get_uint64,
377
    .set   = set_uint64,
378
};
379

    
380
/* --- 64bit hex value --- */
381

    
382
static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
383
{
384
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
385
    char *end;
386

    
387
    if (str[0] != '0' || str[1] != 'x') {
388
        return -EINVAL;
389
    }
390

    
391
    *ptr = strtoull(str, &end, 16);
392
    if ((*end != '\0') || (end == str)) {
393
        return -EINVAL;
394
    }
395

    
396
    return 0;
397
}
398

    
399
static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
400
{
401
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
402
    return snprintf(dest, len, "0x%" PRIx64, *ptr);
403
}
404

    
405
PropertyInfo qdev_prop_hex64 = {
406
    .name  = "uint64",
407
    .legacy_name  = "hex64",
408
    .parse = parse_hex64,
409
    .print = print_hex64,
410
    .get   = get_uint64,
411
    .set   = set_uint64,
412
};
413

    
414
/* --- string --- */
415

    
416
static void release_string(Object *obj, const char *name, void *opaque)
417
{
418
    Property *prop = opaque;
419
    g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
420
}
421

    
422
static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
423
{
424
    char **ptr = qdev_get_prop_ptr(dev, prop);
425
    if (!*ptr)
426
        return snprintf(dest, len, "<null>");
427
    return snprintf(dest, len, "\"%s\"", *ptr);
428
}
429

    
430
static void get_string(Object *obj, Visitor *v, void *opaque,
431
                       const char *name, Error **errp)
432
{
433
    DeviceState *dev = DEVICE(obj);
434
    Property *prop = opaque;
435
    char **ptr = qdev_get_prop_ptr(dev, prop);
436

    
437
    if (!*ptr) {
438
        char *str = (char *)"";
439
        visit_type_str(v, &str, name, errp);
440
    } else {
441
        visit_type_str(v, ptr, name, errp);
442
    }
443
}
444

    
445
static void set_string(Object *obj, Visitor *v, void *opaque,
446
                       const char *name, Error **errp)
447
{
448
    DeviceState *dev = DEVICE(obj);
449
    Property *prop = opaque;
450
    char **ptr = qdev_get_prop_ptr(dev, prop);
451
    Error *local_err = NULL;
452
    char *str;
453

    
454
    if (dev->state != DEV_STATE_CREATED) {
455
        error_set(errp, QERR_PERMISSION_DENIED);
456
        return;
457
    }
458

    
459
    visit_type_str(v, &str, name, &local_err);
460
    if (local_err) {
461
        error_propagate(errp, local_err);
462
        return;
463
    }
464
    if (*ptr) {
465
        g_free(*ptr);
466
    }
467
    *ptr = str;
468
}
469

    
470
PropertyInfo qdev_prop_string = {
471
    .name  = "string",
472
    .print = print_string,
473
    .release = release_string,
474
    .get   = get_string,
475
    .set   = set_string,
476
};
477

    
478
/* --- drive --- */
479

    
480
static int parse_drive(DeviceState *dev, const char *str, void **ptr)
481
{
482
    BlockDriverState *bs;
483

    
484
    bs = bdrv_find(str);
485
    if (bs == NULL)
486
        return -ENOENT;
487
    if (bdrv_attach_dev(bs, dev) < 0)
488
        return -EEXIST;
489
    *ptr = bs;
490
    return 0;
491
}
492

    
493
static void release_drive(Object *obj, const char *name, void *opaque)
494
{
495
    DeviceState *dev = DEVICE(obj);
496
    Property *prop = opaque;
497
    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
498

    
499
    if (*ptr) {
500
        bdrv_detach_dev(*ptr, dev);
501
        blockdev_auto_del(*ptr);
502
    }
503
}
504

    
505
static const char *print_drive(void *ptr)
506
{
507
    return bdrv_get_device_name(ptr);
508
}
509

    
510
static void get_drive(Object *obj, Visitor *v, void *opaque,
511
                      const char *name, Error **errp)
512
{
513
    get_pointer(obj, v, opaque, print_drive, name, errp);
514
}
515

    
516
static void set_drive(Object *obj, Visitor *v, void *opaque,
517
                      const char *name, Error **errp)
518
{
519
    set_pointer(obj, v, opaque, parse_drive, name, errp);
520
}
521

    
522
PropertyInfo qdev_prop_drive = {
523
    .name  = "drive",
524
    .get   = get_drive,
525
    .set   = set_drive,
526
    .release = release_drive,
527
};
528

    
529
/* --- character device --- */
530

    
531
static int parse_chr(DeviceState *dev, const char *str, void **ptr)
532
{
533
    CharDriverState *chr = qemu_chr_find(str);
534
    if (chr == NULL) {
535
        return -ENOENT;
536
    }
537
    if (chr->avail_connections < 1) {
538
        return -EEXIST;
539
    }
540
    *ptr = chr;
541
    --chr->avail_connections;
542
    return 0;
543
}
544

    
545
static void release_chr(Object *obj, const char *name, void *opaque)
546
{
547
    DeviceState *dev = DEVICE(obj);
548
    Property *prop = opaque;
549
    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
550

    
551
    if (*ptr) {
552
        qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
553
    }
554
}
555

    
556

    
557
static const char *print_chr(void *ptr)
558
{
559
    CharDriverState *chr = ptr;
560

    
561
    return chr->label ? chr->label : "";
562
}
563

    
564
static void get_chr(Object *obj, Visitor *v, void *opaque,
565
                    const char *name, Error **errp)
566
{
567
    get_pointer(obj, v, opaque, print_chr, name, errp);
568
}
569

    
570
static void set_chr(Object *obj, Visitor *v, void *opaque,
571
                    const char *name, Error **errp)
572
{
573
    set_pointer(obj, v, opaque, parse_chr, name, errp);
574
}
575

    
576
PropertyInfo qdev_prop_chr = {
577
    .name  = "chr",
578
    .get   = get_chr,
579
    .set   = set_chr,
580
    .release = release_chr,
581
};
582

    
583
/* --- netdev device --- */
584

    
585
static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
586
{
587
    VLANClientState *netdev = qemu_find_netdev(str);
588

    
589
    if (netdev == NULL) {
590
        return -ENOENT;
591
    }
592
    if (netdev->peer) {
593
        return -EEXIST;
594
    }
595
    *ptr = netdev;
596
    return 0;
597
}
598

    
599
static const char *print_netdev(void *ptr)
600
{
601
    VLANClientState *netdev = ptr;
602

    
603
    return netdev->name ? netdev->name : "";
604
}
605

    
606
static void get_netdev(Object *obj, Visitor *v, void *opaque,
607
                       const char *name, Error **errp)
608
{
609
    get_pointer(obj, v, opaque, print_netdev, name, errp);
610
}
611

    
612
static void set_netdev(Object *obj, Visitor *v, void *opaque,
613
                       const char *name, Error **errp)
614
{
615
    set_pointer(obj, v, opaque, parse_netdev, name, errp);
616
}
617

    
618
PropertyInfo qdev_prop_netdev = {
619
    .name  = "netdev",
620
    .get   = get_netdev,
621
    .set   = set_netdev,
622
};
623

    
624
/* --- vlan --- */
625

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

    
630
    if (*ptr) {
631
        int id;
632
        if (!net_hub_id_for_client(*ptr, &id)) {
633
            return snprintf(dest, len, "%d", id);
634
        }
635
    }
636

    
637
    return snprintf(dest, len, "<null>");
638
}
639

    
640
static void get_vlan(Object *obj, Visitor *v, void *opaque,
641
                     const char *name, Error **errp)
642
{
643
    DeviceState *dev = DEVICE(obj);
644
    Property *prop = opaque;
645
    VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
646
    int32_t id = -1;
647

    
648
    if (*ptr) {
649
        int hub_id;
650
        if (!net_hub_id_for_client(*ptr, &hub_id)) {
651
            id = hub_id;
652
        }
653
    }
654

    
655
    visit_type_int32(v, &id, name, errp);
656
}
657

    
658
static void set_vlan(Object *obj, Visitor *v, void *opaque,
659
                     const char *name, Error **errp)
660
{
661
    DeviceState *dev = DEVICE(obj);
662
    Property *prop = opaque;
663
    VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
664
    Error *local_err = NULL;
665
    int32_t id;
666
    VLANClientState *hubport;
667

    
668
    if (dev->state != DEV_STATE_CREATED) {
669
        error_set(errp, QERR_PERMISSION_DENIED);
670
        return;
671
    }
672

    
673
    visit_type_int32(v, &id, name, &local_err);
674
    if (local_err) {
675
        error_propagate(errp, local_err);
676
        return;
677
    }
678
    if (id == -1) {
679
        *ptr = NULL;
680
        return;
681
    }
682

    
683
    hubport = net_hub_port_find(id);
684
    if (!hubport) {
685
        error_set(errp, QERR_INVALID_PARAMETER_VALUE,
686
                  name, prop->info->name);
687
        return;
688
    }
689
    *ptr = hubport;
690
}
691

    
692
PropertyInfo qdev_prop_vlan = {
693
    .name  = "vlan",
694
    .print = print_vlan,
695
    .get   = get_vlan,
696
    .set   = set_vlan,
697
};
698

    
699
/* --- pointer --- */
700

    
701
/* Not a proper property, just for dirty hacks.  TODO Remove it!  */
702
PropertyInfo qdev_prop_ptr = {
703
    .name  = "ptr",
704
};
705

    
706
/* --- mac address --- */
707

    
708
/*
709
 * accepted syntax versions:
710
 *   01:02:03:04:05:06
711
 *   01-02-03-04-05-06
712
 */
713
static void get_mac(Object *obj, Visitor *v, void *opaque,
714
                    const char *name, Error **errp)
715
{
716
    DeviceState *dev = DEVICE(obj);
717
    Property *prop = opaque;
718
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
719
    char buffer[2 * 6 + 5 + 1];
720
    char *p = buffer;
721

    
722
    snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
723
             mac->a[0], mac->a[1], mac->a[2],
724
             mac->a[3], mac->a[4], mac->a[5]);
725

    
726
    visit_type_str(v, &p, name, errp);
727
}
728

    
729
static void set_mac(Object *obj, Visitor *v, void *opaque,
730
                    const char *name, Error **errp)
731
{
732
    DeviceState *dev = DEVICE(obj);
733
    Property *prop = opaque;
734
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
735
    Error *local_err = NULL;
736
    int i, pos;
737
    char *str, *p;
738

    
739
    if (dev->state != DEV_STATE_CREATED) {
740
        error_set(errp, QERR_PERMISSION_DENIED);
741
        return;
742
    }
743

    
744
    visit_type_str(v, &str, name, &local_err);
745
    if (local_err) {
746
        error_propagate(errp, local_err);
747
        return;
748
    }
749

    
750
    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
751
        if (!qemu_isxdigit(str[pos]))
752
            goto inval;
753
        if (!qemu_isxdigit(str[pos+1]))
754
            goto inval;
755
        if (i == 5) {
756
            if (str[pos+2] != '\0')
757
                goto inval;
758
        } else {
759
            if (str[pos+2] != ':' && str[pos+2] != '-')
760
                goto inval;
761
        }
762
        mac->a[i] = strtol(str+pos, &p, 16);
763
    }
764
    g_free(str);
765
    return;
766

    
767
inval:
768
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
769
    g_free(str);
770
}
771

    
772
PropertyInfo qdev_prop_macaddr = {
773
    .name  = "macaddr",
774
    .get   = get_mac,
775
    .set   = set_mac,
776
};
777

    
778
/* --- lost tick policy --- */
779

    
780
static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
781
    [LOST_TICK_DISCARD] = "discard",
782
    [LOST_TICK_DELAY] = "delay",
783
    [LOST_TICK_MERGE] = "merge",
784
    [LOST_TICK_SLEW] = "slew",
785
    [LOST_TICK_MAX] = NULL,
786
};
787

    
788
QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
789

    
790
PropertyInfo qdev_prop_losttickpolicy = {
791
    .name  = "LostTickPolicy",
792
    .enum_table  = lost_tick_policy_table,
793
    .get   = get_enum,
794
    .set   = set_enum,
795
};
796

    
797
/* --- BIOS CHS translation */
798

    
799
static const char *bios_chs_trans_table[] = {
800
    [BIOS_ATA_TRANSLATION_AUTO] = "auto",
801
    [BIOS_ATA_TRANSLATION_NONE] = "none",
802
    [BIOS_ATA_TRANSLATION_LBA]  = "lba",
803
};
804

    
805
PropertyInfo qdev_prop_bios_chs_trans = {
806
    .name = "bios-chs-trans",
807
    .enum_table = bios_chs_trans_table,
808
    .get = get_enum,
809
    .set = set_enum,
810
};
811

    
812
/* --- pci address --- */
813

    
814
/*
815
 * bus-local address, i.e. "$slot" or "$slot.$fn"
816
 */
817
static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
818
                          const char *name, Error **errp)
819
{
820
    DeviceState *dev = DEVICE(obj);
821
    Property *prop = opaque;
822
    int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
823
    unsigned int slot, fn, n;
824
    Error *local_err = NULL;
825
    char *str;
826

    
827
    if (dev->state != DEV_STATE_CREATED) {
828
        error_set(errp, QERR_PERMISSION_DENIED);
829
        return;
830
    }
831

    
832
    visit_type_str(v, &str, name, &local_err);
833
    if (local_err) {
834
        error_free(local_err);
835
        local_err = NULL;
836
        visit_type_int32(v, &value, name, &local_err);
837
        if (local_err) {
838
            error_propagate(errp, local_err);
839
        } else if (value < -1 || value > 255) {
840
            error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
841
                      "pci_devfn");
842
        } else {
843
            *ptr = value;
844
        }
845
        return;
846
    }
847

    
848
    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
849
        fn = 0;
850
        if (sscanf(str, "%x%n", &slot, &n) != 1) {
851
            goto invalid;
852
        }
853
    }
854
    if (str[n] != '\0' || fn > 7 || slot > 31) {
855
        goto invalid;
856
    }
857
    *ptr = slot << 3 | fn;
858
    g_free(str);
859
    return;
860

    
861
invalid:
862
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
863
    g_free(str);
864
}
865

    
866
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
867
{
868
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
869

    
870
    if (*ptr == -1) {
871
        return snprintf(dest, len, "<unset>");
872
    } else {
873
        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
874
    }
875
}
876

    
877
PropertyInfo qdev_prop_pci_devfn = {
878
    .name  = "int32",
879
    .legacy_name  = "pci-devfn",
880
    .print = print_pci_devfn,
881
    .get   = get_int32,
882
    .set   = set_pci_devfn,
883
};
884

    
885
/* --- blocksize --- */
886

    
887
static void set_blocksize(Object *obj, Visitor *v, void *opaque,
888
                          const char *name, Error **errp)
889
{
890
    DeviceState *dev = DEVICE(obj);
891
    Property *prop = opaque;
892
    uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
893
    Error *local_err = NULL;
894
    const int64_t min = 512;
895
    const int64_t max = 32768;
896

    
897
    if (dev->state != DEV_STATE_CREATED) {
898
        error_set(errp, QERR_PERMISSION_DENIED);
899
        return;
900
    }
901

    
902
    visit_type_uint16(v, &value, name, &local_err);
903
    if (local_err) {
904
        error_propagate(errp, local_err);
905
        return;
906
    }
907
    if (value < min || value > max) {
908
        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
909
                  dev->id?:"", name, (int64_t)value, min, max);
910
        return;
911
    }
912

    
913
    /* We rely on power-of-2 blocksizes for bitmasks */
914
    if ((value & (value - 1)) != 0) {
915
        error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
916
                  dev->id?:"", name, (int64_t)value);
917
        return;
918
    }
919

    
920
    *ptr = value;
921
}
922

    
923
PropertyInfo qdev_prop_blocksize = {
924
    .name  = "blocksize",
925
    .get   = get_uint16,
926
    .set   = set_blocksize,
927
};
928

    
929
/* --- pci host address --- */
930

    
931
static void get_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
932
                                 const char *name, Error **errp)
933
{
934
    DeviceState *dev = DEVICE(obj);
935
    Property *prop = opaque;
936
    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
937
    char buffer[] = "xxxx:xx:xx.x";
938
    char *p = buffer;
939
    int rc = 0;
940

    
941
    rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
942
                  addr->domain, addr->bus, addr->slot, addr->function);
943
    assert(rc == sizeof(buffer) - 1);
944

    
945
    visit_type_str(v, &p, name, errp);
946
}
947

    
948
/*
949
 * Parse [<domain>:]<bus>:<slot>.<func>
950
 *   if <domain> is not supplied, it's assumed to be 0.
951
 */
952
static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
953
                                 const char *name, Error **errp)
954
{
955
    DeviceState *dev = DEVICE(obj);
956
    Property *prop = opaque;
957
    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
958
    Error *local_err = NULL;
959
    char *str, *p;
960
    char *e;
961
    unsigned long val;
962
    unsigned long dom = 0, bus = 0;
963
    unsigned int slot = 0, func = 0;
964

    
965
    if (dev->state != DEV_STATE_CREATED) {
966
        error_set(errp, QERR_PERMISSION_DENIED);
967
        return;
968
    }
969

    
970
    visit_type_str(v, &str, name, &local_err);
971
    if (local_err) {
972
        error_propagate(errp, local_err);
973
        return;
974
    }
975

    
976
    p = str;
977
    val = strtoul(p, &e, 16);
978
    if (e == p || *e != ':') {
979
        goto inval;
980
    }
981
    bus = val;
982

    
983
    p = e + 1;
984
    val = strtoul(p, &e, 16);
985
    if (e == p) {
986
        goto inval;
987
    }
988
    if (*e == ':') {
989
        dom = bus;
990
        bus = val;
991
        p = e + 1;
992
        val = strtoul(p, &e, 16);
993
        if (e == p) {
994
            goto inval;
995
        }
996
    }
997
    slot = val;
998

    
999
    if (*e != '.') {
1000
        goto inval;
1001
    }
1002
    p = e + 1;
1003
    val = strtoul(p, &e, 10);
1004
    if (e == p) {
1005
        goto inval;
1006
    }
1007
    func = val;
1008

    
1009
    if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
1010
        goto inval;
1011
    }
1012

    
1013
    if (*e) {
1014
        goto inval;
1015
    }
1016

    
1017
    addr->domain = dom;
1018
    addr->bus = bus;
1019
    addr->slot = slot;
1020
    addr->function = func;
1021

    
1022
    g_free(str);
1023
    return;
1024

    
1025
inval:
1026
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
1027
    g_free(str);
1028
}
1029

    
1030
PropertyInfo qdev_prop_pci_host_devaddr = {
1031
    .name = "pci-host-devaddr",
1032
    .get = get_pci_host_devaddr,
1033
    .set = set_pci_host_devaddr,
1034
};
1035

    
1036
/* --- public helpers --- */
1037

    
1038
static Property *qdev_prop_walk(Property *props, const char *name)
1039
{
1040
    if (!props)
1041
        return NULL;
1042
    while (props->name) {
1043
        if (strcmp(props->name, name) == 0)
1044
            return props;
1045
        props++;
1046
    }
1047
    return NULL;
1048
}
1049

    
1050
static Property *qdev_prop_find(DeviceState *dev, const char *name)
1051
{
1052
    ObjectClass *class;
1053
    Property *prop;
1054

    
1055
    /* device properties */
1056
    class = object_get_class(OBJECT(dev));
1057
    do {
1058
        prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
1059
        if (prop) {
1060
            return prop;
1061
        }
1062
        class = object_class_get_parent(class);
1063
    } while (class != object_class_by_name(TYPE_DEVICE));
1064

    
1065
    return NULL;
1066
}
1067

    
1068
void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
1069
                                    Property *prop, const char *value)
1070
{
1071
    switch (ret) {
1072
    case -EEXIST:
1073
        error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
1074
                  object_get_typename(OBJECT(dev)), prop->name, value);
1075
        break;
1076
    default:
1077
    case -EINVAL:
1078
        error_set(errp, QERR_PROPERTY_VALUE_BAD,
1079
                  object_get_typename(OBJECT(dev)), prop->name, value);
1080
        break;
1081
    case -ENOENT:
1082
        error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
1083
                  object_get_typename(OBJECT(dev)), prop->name, value);
1084
        break;
1085
    case 0:
1086
        break;
1087
    }
1088
}
1089

    
1090
int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
1091
{
1092
    char *legacy_name;
1093
    Error *err = NULL;
1094

    
1095
    legacy_name = g_strdup_printf("legacy-%s", name);
1096
    if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
1097
        object_property_parse(OBJECT(dev), value, legacy_name, &err);
1098
    } else {
1099
        object_property_parse(OBJECT(dev), value, name, &err);
1100
    }
1101
    g_free(legacy_name);
1102

    
1103
    if (err) {
1104
        qerror_report_err(err);
1105
        error_free(err);
1106
        return -1;
1107
    }
1108
    return 0;
1109
}
1110

    
1111
void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
1112
{
1113
    Error *errp = NULL;
1114
    object_property_set_bool(OBJECT(dev), value, name, &errp);
1115
    assert_no_error(errp);
1116
}
1117

    
1118
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
1119
{
1120
    Error *errp = NULL;
1121
    object_property_set_int(OBJECT(dev), value, name, &errp);
1122
    assert_no_error(errp);
1123
}
1124

    
1125
void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
1126
{
1127
    Error *errp = NULL;
1128
    object_property_set_int(OBJECT(dev), value, name, &errp);
1129
    assert_no_error(errp);
1130
}
1131

    
1132
void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
1133
{
1134
    Error *errp = NULL;
1135
    object_property_set_int(OBJECT(dev), value, name, &errp);
1136
    assert_no_error(errp);
1137
}
1138

    
1139
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1140
{
1141
    Error *errp = NULL;
1142
    object_property_set_int(OBJECT(dev), value, name, &errp);
1143
    assert_no_error(errp);
1144
}
1145

    
1146
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1147
{
1148
    Error *errp = NULL;
1149
    object_property_set_int(OBJECT(dev), value, name, &errp);
1150
    assert_no_error(errp);
1151
}
1152

    
1153
void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
1154
{
1155
    Error *errp = NULL;
1156
    object_property_set_str(OBJECT(dev), value, name, &errp);
1157
    assert_no_error(errp);
1158
}
1159

    
1160
int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
1161
{
1162
    Error *errp = NULL;
1163
    const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
1164
    object_property_set_str(OBJECT(dev), bdrv_name,
1165
                            name, &errp);
1166
    if (errp) {
1167
        qerror_report_err(errp);
1168
        error_free(errp);
1169
        return -1;
1170
    }
1171
    return 0;
1172
}
1173

    
1174
void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
1175
{
1176
    if (qdev_prop_set_drive(dev, name, value) < 0) {
1177
        exit(1);
1178
    }
1179
}
1180
void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
1181
{
1182
    Error *errp = NULL;
1183
    assert(!value || value->label);
1184
    object_property_set_str(OBJECT(dev),
1185
                            value ? value->label : "", name, &errp);
1186
    assert_no_error(errp);
1187
}
1188

    
1189
void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
1190
{
1191
    Error *errp = NULL;
1192
    assert(!value || value->name);
1193
    object_property_set_str(OBJECT(dev),
1194
                            value ? value->name : "", name, &errp);
1195
    assert_no_error(errp);
1196
}
1197

    
1198
void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1199
{
1200
    Error *errp = NULL;
1201
    char str[2 * 6 + 5 + 1];
1202
    snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
1203
             value[0], value[1], value[2], value[3], value[4], value[5]);
1204

    
1205
    object_property_set_str(OBJECT(dev), str, name, &errp);
1206
    assert_no_error(errp);
1207
}
1208

    
1209
void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
1210
{
1211
    Property *prop;
1212
    Error *errp = NULL;
1213

    
1214
    prop = qdev_prop_find(dev, name);
1215
    object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1216
                            name, &errp);
1217
    assert_no_error(errp);
1218
}
1219

    
1220
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1221
{
1222
    Property *prop;
1223
    void **ptr;
1224

    
1225
    prop = qdev_prop_find(dev, name);
1226
    assert(prop && prop->info == &qdev_prop_ptr);
1227
    ptr = qdev_get_prop_ptr(dev, prop);
1228
    *ptr = value;
1229
}
1230

    
1231
static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
1232

    
1233
static void qdev_prop_register_global(GlobalProperty *prop)
1234
{
1235
    QTAILQ_INSERT_TAIL(&global_props, prop, next);
1236
}
1237

    
1238
void qdev_prop_register_global_list(GlobalProperty *props)
1239
{
1240
    int i;
1241

    
1242
    for (i = 0; props[i].driver != NULL; i++) {
1243
        qdev_prop_register_global(props+i);
1244
    }
1245
}
1246

    
1247
void qdev_prop_set_globals(DeviceState *dev)
1248
{
1249
    ObjectClass *class = object_get_class(OBJECT(dev));
1250

    
1251
    do {
1252
        GlobalProperty *prop;
1253
        QTAILQ_FOREACH(prop, &global_props, next) {
1254
            if (strcmp(object_class_get_name(class), prop->driver) != 0) {
1255
                continue;
1256
            }
1257
            if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
1258
                exit(1);
1259
            }
1260
        }
1261
        class = object_class_get_parent(class);
1262
    } while (class);
1263
}
1264

    
1265
static int qdev_add_one_global(QemuOpts *opts, void *opaque)
1266
{
1267
    GlobalProperty *g;
1268

    
1269
    g = g_malloc0(sizeof(*g));
1270
    g->driver   = qemu_opt_get(opts, "driver");
1271
    g->property = qemu_opt_get(opts, "property");
1272
    g->value    = qemu_opt_get(opts, "value");
1273
    qdev_prop_register_global(g);
1274
    return 0;
1275
}
1276

    
1277
void qemu_add_globals(void)
1278
{
1279
    qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
1280
}