Statistics
| Branch: | Revision:

root / hw / qdev-properties.c @ 927d4878

History | View | Annotate | Download (30.9 kB)

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

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

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

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

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

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

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

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

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

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

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

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

    
87
/* Bit */
88

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

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

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

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

    
119
    visit_type_bool(v, &value, name, errp);
120
}
121

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

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

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

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

    
151
/* --- 8bit integer --- */
152

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

    
160
    visit_type_uint8(v, ptr, name, errp);
161
}
162

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

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

    
175
    visit_type_uint8(v, ptr, name, errp);
176
}
177

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

    
184
/* --- 8bit hex value --- */
185

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

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

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

    
200
    return 0;
201
}
202

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

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

    
218
/* --- 16bit integer --- */
219

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

    
227
    visit_type_uint16(v, ptr, name, errp);
228
}
229

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

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

    
242
    visit_type_uint16(v, ptr, name, errp);
243
}
244

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

    
251
/* --- 32bit integer --- */
252

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

    
260
    visit_type_uint32(v, ptr, name, errp);
261
}
262

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

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

    
275
    visit_type_uint32(v, ptr, name, errp);
276
}
277

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

    
285
    visit_type_int32(v, ptr, name, errp);
286
}
287

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

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

    
300
    visit_type_int32(v, ptr, name, errp);
301
}
302

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

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

    
315
/* --- 32bit hex value --- */
316

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

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

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

    
331
    return 0;
332
}
333

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

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

    
349
/* --- 64bit integer --- */
350

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

    
358
    visit_type_uint64(v, ptr, name, errp);
359
}
360

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

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

    
373
    visit_type_uint64(v, ptr, name, errp);
374
}
375

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

    
382
/* --- 64bit hex value --- */
383

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

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

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

    
398
    return 0;
399
}
400

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

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

    
416
/* --- string --- */
417

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

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

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

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

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

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

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

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

    
480
/* --- drive --- */
481

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

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

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

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

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

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

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

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

    
531
/* --- character device --- */
532

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

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

    
553
    if (*ptr) {
554
        qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
555
    }
556
}
557

    
558

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

    
563
    return chr->label ? chr->label : "";
564
}
565

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

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

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

    
585
/* --- netdev device --- */
586

    
587
static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
588
{
589
    NetClientState *netdev = qemu_find_netdev(str);
590

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

    
601
static const char *print_netdev(void *ptr)
602
{
603
    NetClientState *netdev = ptr;
604

    
605
    return netdev->name ? netdev->name : "";
606
}
607

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

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

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

    
626
/* --- vlan --- */
627

    
628
static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
629
{
630
    NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
631

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

    
639
    return snprintf(dest, len, "<null>");
640
}
641

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

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

    
657
    visit_type_int32(v, &id, name, errp);
658
}
659

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

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

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

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

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

    
701
/* --- pointer --- */
702

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

    
708
/* --- mac address --- */
709

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

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

    
728
    visit_type_str(v, &p, name, errp);
729
}
730

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

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

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

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

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

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

    
780
/* --- lost tick policy --- */
781

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

    
790
QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
791

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

    
799
/* --- BIOS CHS translation */
800

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

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

    
814
/* --- pci address --- */
815

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

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

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

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

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

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

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

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

    
887
/* --- blocksize --- */
888

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

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

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

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

    
922
    *ptr = value;
923
}
924

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

    
931
/* --- pci host address --- */
932

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

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

    
947
    visit_type_str(v, &p, name, errp);
948
}
949

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

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

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

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

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

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

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

    
1015
    if (*e) {
1016
        goto inval;
1017
    }
1018

    
1019
    addr->domain = dom;
1020
    addr->bus = bus;
1021
    addr->slot = slot;
1022
    addr->function = func;
1023

    
1024
    g_free(str);
1025
    return;
1026

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

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

    
1038
/* --- public helpers --- */
1039

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

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

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

    
1067
    return NULL;
1068
}
1069

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1207
    object_property_set_str(OBJECT(dev), str, name, &errp);
1208
    assert_no_error(errp);
1209
}
1210

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

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

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

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

    
1233
static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
1234

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

    
1240
void qdev_prop_register_global_list(GlobalProperty *props)
1241
{
1242
    int i;
1243

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

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

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

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

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

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