qdev-properties.c 32.6 KB
Newer Older
P
Peter Maydell 已提交
1
#include "qemu/osdep.h"
P
Paolo Bonzini 已提交
2
#include "net/net.h"
3
#include "hw/qdev.h"
4
#include "qapi/error.h"
5
#include "hw/pci/pci.h"
6
#include "qapi/qmp/qerror.h"
7
#include "qemu/error-report.h"
8
#include "sysemu/block-backend.h"
P
Paolo Bonzini 已提交
9
#include "hw/block/block.h"
10
#include "net/hub.h"
11
#include "qapi/visitor.h"
12
#include "chardev/char.h"
G
Gerd Hoffmann 已提交
13

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

28 29
void qdev_prop_allow_set_link_before_realize(const Object *obj,
                                             const char *name,
30 31 32 33 34 35 36 37 38 39 40
                                             Object *val, Error **errp)
{
    DeviceState *dev = DEVICE(obj);

    if (dev->realized) {
        error_setg(errp, "Attempt to set link property '%s' on device '%s' "
                   "(type '%s') after it was realized",
                   name, dev->id, object_get_typename(obj));
    }
}

G
Gerd Hoffmann 已提交
41 42 43 44 45 46 47
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
{
    void *ptr = dev;
    ptr += prop->offset;
    return ptr;
}

48 49
static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
50 51 52 53 54
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    int *ptr = qdev_get_prop_ptr(dev, prop);

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

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

65
    if (dev->realized) {
66
        qdev_prop_set_after_realize(dev, name, errp);
67 68 69
        return;
    }

70
    visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
71 72
}

73 74
static void set_default_value_enum(Object *obj, const Property *prop)
{
75
    object_property_set_str(obj, prop->info->enum_table[prop->defval.i],
76 77 78
                            prop->name, &error_abort);
}

79 80
/* Bit */

M
Michael S. Tsirkin 已提交
81 82
static uint32_t qdev_get_prop_mask(Property *prop)
{
83
    assert(prop->info == &qdev_prop_bit);
M
Michael S. Tsirkin 已提交
84 85 86 87 88 89 90
    return 0x1 << prop->bitnr;
}

static void bit_prop_set(DeviceState *dev, Property *props, bool val)
{
    uint32_t *p = qdev_get_prop_ptr(dev, props);
    uint32_t mask = qdev_get_prop_mask(props);
E
Eduardo Habkost 已提交
91
    if (val) {
92
        *p |= mask;
E
Eduardo Habkost 已提交
93
    } else {
M
Michael S. Tsirkin 已提交
94
        *p &= ~mask;
E
Eduardo Habkost 已提交
95
    }
M
Michael S. Tsirkin 已提交
96 97
}

98 99
static void prop_get_bit(Object *obj, Visitor *v, const char *name,
                         void *opaque, Error **errp)
100
{
101
    DeviceState *dev = DEVICE(obj);
102 103 104 105
    Property *prop = opaque;
    uint32_t *p = qdev_get_prop_ptr(dev, prop);
    bool value = (*p & qdev_get_prop_mask(prop)) != 0;

106
    visit_type_bool(v, name, &value, errp);
107 108
}

109 110
static void prop_set_bit(Object *obj, Visitor *v, const char *name,
                         void *opaque, Error **errp)
111
{
112
    DeviceState *dev = DEVICE(obj);
113 114 115 116
    Property *prop = opaque;
    Error *local_err = NULL;
    bool value;

117
    if (dev->realized) {
118
        qdev_prop_set_after_realize(dev, name, errp);
119 120 121
        return;
    }

122
    visit_type_bool(v, name, &value, &local_err);
123 124 125 126 127 128 129
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
    bit_prop_set(dev, prop, value);
}

130 131
static void set_default_value_bool(Object *obj, const Property *prop)
{
132
    object_property_set_bool(obj, prop->defval.u, prop->name, &error_abort);
133 134
}

135
const PropertyInfo qdev_prop_bit = {
136
    .name  = "bool",
137
    .description = "on/off",
138 139
    .get   = prop_get_bit,
    .set   = prop_set_bit,
140
    .set_default_value = set_default_value_bool,
M
Michael S. Tsirkin 已提交
141 142
};

G
Gerd Hoffmann 已提交
143 144 145 146
/* Bit64 */

static uint64_t qdev_get_prop_mask64(Property *prop)
{
C
Cornelia Huck 已提交
147
    assert(prop->info == &qdev_prop_bit64);
G
Gonglei 已提交
148
    return 0x1ull << prop->bitnr;
G
Gerd Hoffmann 已提交
149 150 151 152 153 154 155 156 157 158 159 160 161
}

static void bit64_prop_set(DeviceState *dev, Property *props, bool val)
{
    uint64_t *p = qdev_get_prop_ptr(dev, props);
    uint64_t mask = qdev_get_prop_mask64(props);
    if (val) {
        *p |= mask;
    } else {
        *p &= ~mask;
    }
}

162 163
static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
                           void *opaque, Error **errp)
G
Gerd Hoffmann 已提交
164 165 166 167 168 169
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint64_t *p = qdev_get_prop_ptr(dev, prop);
    bool value = (*p & qdev_get_prop_mask64(prop)) != 0;

170
    visit_type_bool(v, name, &value, errp);
G
Gerd Hoffmann 已提交
171 172
}

173 174
static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
                           void *opaque, Error **errp)
G
Gerd Hoffmann 已提交
175 176 177 178 179 180 181 182 183 184 185
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    Error *local_err = NULL;
    bool value;

    if (dev->realized) {
        qdev_prop_set_after_realize(dev, name, errp);
        return;
    }

186
    visit_type_bool(v, name, &value, &local_err);
G
Gerd Hoffmann 已提交
187 188 189 190 191 192 193
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
    bit64_prop_set(dev, prop, value);
}

194
const PropertyInfo qdev_prop_bit64 = {
G
Gerd Hoffmann 已提交
195 196 197 198
    .name  = "bool",
    .description = "on/off",
    .get   = prop_get_bit64,
    .set   = prop_set_bit64,
199
    .set_default_value = set_default_value_bool,
G
Gerd Hoffmann 已提交
200 201
};

202 203
/* --- bool --- */

204 205
static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
206 207 208 209 210
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    bool *ptr = qdev_get_prop_ptr(dev, prop);

211
    visit_type_bool(v, name, ptr, errp);
212 213
}

214 215
static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
216 217 218 219 220 221 222 223 224 225
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    bool *ptr = qdev_get_prop_ptr(dev, prop);

    if (dev->realized) {
        qdev_prop_set_after_realize(dev, name, errp);
        return;
    }

226
    visit_type_bool(v, name, ptr, errp);
227 228
}

229
const PropertyInfo qdev_prop_bool = {
230
    .name  = "bool",
231 232
    .get   = get_bool,
    .set   = set_bool,
233
    .set_default_value = set_default_value_bool,
234 235
};

J
Juan Quintela 已提交
236 237
/* --- 8bit integer --- */

238 239
static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
240
{
241
    DeviceState *dev = DEVICE(obj);
242
    Property *prop = opaque;
243
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
244

245
    visit_type_uint8(v, name, ptr, errp);
246 247
}

248 249
static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
250
{
251
    DeviceState *dev = DEVICE(obj);
252
    Property *prop = opaque;
253
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
254

255
    if (dev->realized) {
256
        qdev_prop_set_after_realize(dev, name, errp);
257 258 259
        return;
    }

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

263 264
static void set_default_value_int(Object *obj, const Property *prop)
{
265
    object_property_set_int(obj, prop->defval.i, prop->name, &error_abort);
266 267
}

268 269 270 271 272
static void set_default_value_uint(Object *obj, const Property *prop)
{
    object_property_set_uint(obj, prop->defval.u, prop->name, &error_abort);
}

273
const PropertyInfo qdev_prop_uint8 = {
J
Juan Quintela 已提交
274
    .name  = "uint8",
275 276
    .get   = get_uint8,
    .set   = set_uint8,
277
    .set_default_value = set_default_value_uint,
J
Juan Quintela 已提交
278 279
};

G
Gerd Hoffmann 已提交
280 281
/* --- 16bit integer --- */

282 283
static void get_uint16(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
284
{
285
    DeviceState *dev = DEVICE(obj);
286
    Property *prop = opaque;
287
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
288

289
    visit_type_uint16(v, name, ptr, errp);
290 291
}

292 293
static void set_uint16(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
294
{
295
    DeviceState *dev = DEVICE(obj);
296
    Property *prop = opaque;
297
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
298

299
    if (dev->realized) {
300
        qdev_prop_set_after_realize(dev, name, errp);
301 302 303
        return;
    }

304
    visit_type_uint16(v, name, ptr, errp);
305 306
}

307
const PropertyInfo qdev_prop_uint16 = {
G
Gerd Hoffmann 已提交
308
    .name  = "uint16",
309 310
    .get   = get_uint16,
    .set   = set_uint16,
311
    .set_default_value = set_default_value_uint,
G
Gerd Hoffmann 已提交
312 313 314 315
};

/* --- 32bit integer --- */

316 317
static void get_uint32(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
318 319 320
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
321
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
322

323
    visit_type_uint32(v, name, ptr, errp);
324 325
}

326 327
static void set_uint32(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
328 329 330
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
331
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
332

333
    if (dev->realized) {
334
        qdev_prop_set_after_realize(dev, name, errp);
335 336 337
        return;
    }

338
    visit_type_uint32(v, name, ptr, errp);
339 340
}

341 342
static void get_int32(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
343
{
344
    DeviceState *dev = DEVICE(obj);
345 346 347
    Property *prop = opaque;
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);

348
    visit_type_int32(v, name, ptr, errp);
349 350
}

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

358
    if (dev->realized) {
359
        qdev_prop_set_after_realize(dev, name, errp);
360 361 362
        return;
    }

363
    visit_type_int32(v, name, ptr, errp);
364 365
}

366
const PropertyInfo qdev_prop_uint32 = {
G
Gerd Hoffmann 已提交
367
    .name  = "uint32",
368 369
    .get   = get_uint32,
    .set   = set_uint32,
370
    .set_default_value = set_default_value_uint,
G
Gerd Hoffmann 已提交
371 372
};

373
const PropertyInfo qdev_prop_int32 = {
374
    .name  = "int32",
375 376
    .get   = get_int32,
    .set   = set_int32,
377
    .set_default_value = set_default_value_int,
378 379
};

B
Blue Swirl 已提交
380 381
/* --- 64bit integer --- */

382 383
static void get_uint64(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
384
{
385
    DeviceState *dev = DEVICE(obj);
386
    Property *prop = opaque;
387
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
388

389
    visit_type_uint64(v, name, ptr, errp);
390 391
}

392 393
static void set_uint64(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
394
{
395
    DeviceState *dev = DEVICE(obj);
396
    Property *prop = opaque;
397
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
398

399
    if (dev->realized) {
400
        qdev_prop_set_after_realize(dev, name, errp);
401 402 403
        return;
    }

404
    visit_type_uint64(v, name, ptr, errp);
405 406
}

407
const PropertyInfo qdev_prop_uint64 = {
B
Blue Swirl 已提交
408
    .name  = "uint64",
409 410
    .get   = get_uint64,
    .set   = set_uint64,
411
    .set_default_value = set_default_value_uint,
B
Blue Swirl 已提交
412 413
};

G
Gerd Hoffmann 已提交
414 415
/* --- string --- */

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

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

    if (!*ptr) {
        char *str = (char *)"";
431
        visit_type_str(v, name, &str, errp);
432
    } else {
433
        visit_type_str(v, name, ptr, errp);
434 435 436
    }
}

437 438
static void set_string(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
439
{
440
    DeviceState *dev = DEVICE(obj);
441 442 443 444 445
    Property *prop = opaque;
    char **ptr = qdev_get_prop_ptr(dev, prop);
    Error *local_err = NULL;
    char *str;

446
    if (dev->realized) {
447
        qdev_prop_set_after_realize(dev, name, errp);
448 449 450
        return;
    }

451
    visit_type_str(v, name, &str, &local_err);
452 453 454 455
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
456
    g_free(*ptr);
457 458 459
    *ptr = str;
}

460
const PropertyInfo qdev_prop_string = {
461
    .name  = "str",
P
Paolo Bonzini 已提交
462
    .release = release_string,
463 464
    .get   = get_string,
    .set   = set_string,
G
Gerd Hoffmann 已提交
465 466
};

G
Gerd Hoffmann 已提交
467 468
/* --- pointer --- */

469
/* Not a proper property, just for dirty hacks.  TODO Remove it!  */
470
const PropertyInfo qdev_prop_ptr = {
G
Gerd Hoffmann 已提交
471 472 473 474 475 476 477 478 479 480
    .name  = "ptr",
};

/* --- mac address --- */

/*
 * accepted syntax versions:
 *   01:02:03:04:05:06
 *   01-02-03-04-05-06
 */
481 482
static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
                    Error **errp)
G
Gerd Hoffmann 已提交
483
{
484 485
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
G
Gerd Hoffmann 已提交
486
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
487 488 489 490 491 492 493
    char buffer[2 * 6 + 5 + 1];
    char *p = buffer;

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

494
    visit_type_str(v, name, &p, errp);
495 496
}

497 498
static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
                    Error **errp)
499 500 501 502 503
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
    Error *local_err = NULL;
G
Gerd Hoffmann 已提交
504
    int i, pos;
505 506
    char *str, *p;

507
    if (dev->realized) {
508
        qdev_prop_set_after_realize(dev, name, errp);
509 510 511
        return;
    }

512
    visit_type_str(v, name, &str, &local_err);
513 514 515 516
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
G
Gerd Hoffmann 已提交
517 518

    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
E
Eduardo Habkost 已提交
519
        if (!qemu_isxdigit(str[pos])) {
520
            goto inval;
E
Eduardo Habkost 已提交
521 522
        }
        if (!qemu_isxdigit(str[pos+1])) {
523
            goto inval;
E
Eduardo Habkost 已提交
524
        }
G
Gerd Hoffmann 已提交
525
        if (i == 5) {
E
Eduardo Habkost 已提交
526
            if (str[pos+2] != '\0') {
527
                goto inval;
E
Eduardo Habkost 已提交
528
            }
G
Gerd Hoffmann 已提交
529
        } else {
E
Eduardo Habkost 已提交
530
            if (str[pos+2] != ':' && str[pos+2] != '-') {
531
                goto inval;
E
Eduardo Habkost 已提交
532
            }
G
Gerd Hoffmann 已提交
533 534
        }
        mac->a[i] = strtol(str+pos, &p, 16);
G
Gerd Hoffmann 已提交
535
    }
D
dunrong huang 已提交
536
    g_free(str);
537
    return;
G
Gerd Hoffmann 已提交
538

539 540
inval:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
D
dunrong huang 已提交
541
    g_free(str);
G
Gerd Hoffmann 已提交
542 543
}

544
const PropertyInfo qdev_prop_macaddr = {
545
    .name  = "str",
546
    .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
547 548
    .get   = get_mac,
    .set   = set_mac,
G
Gerd Hoffmann 已提交
549 550
};

551 552
/* --- on/off/auto --- */

553
const PropertyInfo qdev_prop_on_off_auto = {
554 555 556 557 558
    .name = "OnOffAuto",
    .description = "on/off/auto",
    .enum_table = OnOffAuto_lookup,
    .get = get_enum,
    .set = set_enum,
559
    .set_default_value = set_default_value_enum,
560 561
};

562 563
/* --- lost tick policy --- */

564 565
QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));

566
const PropertyInfo qdev_prop_losttickpolicy = {
567
    .name  = "LostTickPolicy",
568
    .enum_table  = LostTickPolicy_lookup,
569 570
    .get   = get_enum,
    .set   = set_enum,
571
    .set_default_value = set_default_value_enum,
572 573
};

574 575 576 577
/* --- Block device error handling policy --- */

QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int));

578
const PropertyInfo qdev_prop_blockdev_on_error = {
579 580 581 582 583 584
    .name = "BlockdevOnError",
    .description = "Error handling policy, "
                   "report/ignore/enospc/stop/auto",
    .enum_table = BlockdevOnError_lookup,
    .get = get_enum,
    .set = set_enum,
585
    .set_default_value = set_default_value_enum,
586 587
};

588 589
/* --- BIOS CHS translation */

590
QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
591

592
const PropertyInfo qdev_prop_bios_chs_trans = {
593
    .name = "BiosAtaTranslation",
594 595
    .description = "Logical CHS translation algorithm, "
                   "auto/none/lba/large/rechs",
596
    .enum_table = BiosAtaTranslation_lookup,
597 598
    .get = get_enum,
    .set = set_enum,
599
    .set_default_value = set_default_value_enum,
600 601
};

J
John Snow 已提交
602 603
/* --- FDC default drive types */

604
const PropertyInfo qdev_prop_fdc_drive_type = {
J
John Snow 已提交
605 606 607 608 609
    .name = "FdcDriveType",
    .description = "FDC drive type, "
                   "144/288/120/none/auto",
    .enum_table = FloppyDriveType_lookup,
    .get = get_enum,
610 611
    .set = set_enum,
    .set_default_value = set_default_value_enum,
J
John Snow 已提交
612 613
};

614 615 616 617 618
/* --- pci address --- */

/*
 * bus-local address, i.e. "$slot" or "$slot.$fn"
 */
619 620
static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
                          void *opaque, Error **errp)
621
{
622 623
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
624
    int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
625
    unsigned int slot, fn, n;
626
    Error *local_err = NULL;
D
dunrong huang 已提交
627
    char *str;
628

629
    if (dev->realized) {
630
        qdev_prop_set_after_realize(dev, name, errp);
631 632 633
        return;
    }

634
    visit_type_str(v, name, &str, &local_err);
635
    if (local_err) {
636
        error_free(local_err);
637
        local_err = NULL;
638
        visit_type_int32(v, name, &value, &local_err);
639 640 641
        if (local_err) {
            error_propagate(errp, local_err);
        } else if (value < -1 || value > 255) {
642 643
            error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
                       name ? name : "null", "pci_devfn");
644 645 646 647
        } else {
            *ptr = value;
        }
        return;
648
    }
649 650 651 652

    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
        fn = 0;
        if (sscanf(str, "%x%n", &slot, &n) != 1) {
653
            goto invalid;
654 655
        }
    }
656 657 658
    if (str[n] != '\0' || fn > 7 || slot > 31) {
        goto invalid;
    }
659
    *ptr = slot << 3 | fn;
D
dunrong huang 已提交
660
    g_free(str);
661 662 663 664
    return;

invalid:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
D
dunrong huang 已提交
665
    g_free(str);
666 667
}

E
Eduardo Habkost 已提交
668 669
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
                           size_t len)
670
{
671
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
672

B
Blue Swirl 已提交
673
    if (*ptr == -1) {
674 675 676 677 678 679
        return snprintf(dest, len, "<unset>");
    } else {
        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
    }
}

680
const PropertyInfo qdev_prop_pci_devfn = {
681
    .name  = "int32",
682
    .description = "Slot and optional function number, example: 06.0 or 06",
683
    .print = print_pci_devfn,
684
    .get   = get_int32,
685
    .set   = set_pci_devfn,
686
    .set_default_value = set_default_value_int,
687 688
};

689 690
/* --- blocksize --- */

691 692
static void set_blocksize(Object *obj, Visitor *v, const char *name,
                          void *opaque, Error **errp)
693 694 695
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
696
    uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
697
    Error *local_err = NULL;
698 699
    const int64_t min = 512;
    const int64_t max = 32768;
700

701
    if (dev->realized) {
702
        qdev_prop_set_after_realize(dev, name, errp);
703 704 705
        return;
    }

706
    visit_type_uint16(v, name, &value, &local_err);
707 708 709 710
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
711 712
    /* value of 0 means "unset" */
    if (value && (value < min || value > max)) {
713 714
        error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
                   dev->id ? : "", name, (int64_t)value, min, max);
715 716 717 718 719
        return;
    }

    /* We rely on power-of-2 blocksizes for bitmasks */
    if ((value & (value - 1)) != 0) {
720 721 722
        error_setg(errp,
                  "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2",
                  dev->id ?: "", name, (int64_t)value);
723 724 725 726 727 728
        return;
    }

    *ptr = value;
}

729
const PropertyInfo qdev_prop_blocksize = {
730
    .name  = "uint16",
731
    .description = "A power of two between 512 and 32768",
732
    .get   = get_uint16,
733
    .set   = set_blocksize,
734
    .set_default_value = set_default_value_uint,
735 736
};

737 738
/* --- pci host address --- */

739 740
static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
                                 void *opaque, Error **errp)
741 742 743 744
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
745
    char buffer[] = "ffff:ff:ff.f";
746 747 748
    char *p = buffer;
    int rc = 0;

749 750
    /*
     * Catch "invalid" device reference from vfio-pci and allow the
S
Stefan Weil 已提交
751
     * default buffer representing the non-existent device to be used.
752 753 754 755 756 757
     */
    if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) {
        rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d",
                      addr->domain, addr->bus, addr->slot, addr->function);
        assert(rc == sizeof(buffer) - 1);
    }
758

759
    visit_type_str(v, name, &p, errp);
760 761 762 763 764 765
}

/*
 * Parse [<domain>:]<bus>:<slot>.<func>
 *   if <domain> is not supplied, it's assumed to be 0.
 */
766 767
static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
                                 void *opaque, Error **errp)
768 769 770 771 772 773 774 775 776 777 778
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
    Error *local_err = NULL;
    char *str, *p;
    char *e;
    unsigned long val;
    unsigned long dom = 0, bus = 0;
    unsigned int slot = 0, func = 0;

779
    if (dev->realized) {
780
        qdev_prop_set_after_realize(dev, name, errp);
781 782 783
        return;
    }

784
    visit_type_str(v, name, &str, &local_err);
785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }

    p = str;
    val = strtoul(p, &e, 16);
    if (e == p || *e != ':') {
        goto inval;
    }
    bus = val;

    p = e + 1;
    val = strtoul(p, &e, 16);
    if (e == p) {
        goto inval;
    }
    if (*e == ':') {
        dom = bus;
        bus = val;
        p = e + 1;
        val = strtoul(p, &e, 16);
        if (e == p) {
            goto inval;
        }
    }
    slot = val;

    if (*e != '.') {
        goto inval;
    }
    p = e + 1;
    val = strtoul(p, &e, 10);
    if (e == p) {
        goto inval;
    }
    func = val;

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

    if (*e) {
        goto inval;
    }

    addr->domain = dom;
    addr->bus = bus;
    addr->slot = slot;
    addr->function = func;

    g_free(str);
    return;

inval:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
    g_free(str);
}

844
const PropertyInfo qdev_prop_pci_host_devaddr = {
845
    .name = "str",
846 847
    .description = "Address (bus/device/function) of "
                   "the host device, example: 04:10.0",
848 849 850 851
    .get = get_pci_host_devaddr,
    .set = set_pci_host_devaddr,
};

852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879
/* --- support for array properties --- */

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

/* object property release callback for array element properties:
 * we call the underlying element's property release hook, and
 * then free the memory we allocated when we added the property.
 */
static void array_element_release(Object *obj, const char *name, void *opaque)
{
    ArrayElementProperty *p = opaque;
    if (p->release) {
        p->release(obj, name, opaque);
    }
    g_free(p->propname);
    g_free(p);
}

880 881
static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
                              void *opaque, Error **errp)
882 883 884 885 886 887 888 889 890 891
{
    /* Setter for the property which defines the length of a
     * variable-sized property array. As well as actually setting the
     * array-length field in the device struct, we have to create the
     * array itself and dynamically add the corresponding properties.
     */
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint32_t *alenptr = qdev_get_prop_ptr(dev, prop);
    void **arrayptr = (void *)dev + prop->arrayoffset;
892
    Error *local_err = NULL;
893 894 895 896 897
    void *eltptr;
    const char *arrayname;
    int i;

    if (dev->realized) {
898
        qdev_prop_set_after_realize(dev, name, errp);
899 900 901 902 903 904 905
        return;
    }
    if (*alenptr) {
        error_setg(errp, "array size property %s may not be set more than once",
                   name);
        return;
    }
906
    visit_type_uint32(v, name, alenptr, &local_err);
907 908
    if (local_err) {
        error_propagate(errp, local_err);
909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944
        return;
    }
    if (!*alenptr) {
        return;
    }

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

    /* Note that it is the responsibility of the individual device's deinit
     * to free the array proper.
     */
    *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
    for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
        char *propname = g_strdup_printf("%s[%d]", arrayname, i);
        ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
        arrayprop->release = prop->arrayinfo->release;
        arrayprop->propname = propname;
        arrayprop->prop.info = prop->arrayinfo;
        arrayprop->prop.name = propname;
        /* This ugly piece of pointer arithmetic sets up the offset so
         * that when the underlying get/set hooks call qdev_get_prop_ptr
         * they get the right answer despite the array element not actually
         * being inside the device struct.
         */
        arrayprop->prop.offset = eltptr - (void *)dev;
        assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr);
        object_property_add(obj, propname,
                            arrayprop->prop.info->name,
                            arrayprop->prop.info->get,
                            arrayprop->prop.info->set,
                            array_element_release,
945 946 947
                            arrayprop, &local_err);
        if (local_err) {
            error_propagate(errp, local_err);
948 949 950 951 952
            return;
        }
    }
}

953
const PropertyInfo qdev_prop_arraylen = {
954 955 956
    .name = "uint32",
    .get = get_uint32,
    .set = set_prop_arraylen,
957
    .set_default_value = set_default_value_uint,
958 959
};

G
Gerd Hoffmann 已提交
960 961 962 963
/* --- public helpers --- */

static Property *qdev_prop_walk(Property *props, const char *name)
{
E
Eduardo Habkost 已提交
964
    if (!props) {
G
Gerd Hoffmann 已提交
965
        return NULL;
E
Eduardo Habkost 已提交
966
    }
G
Gerd Hoffmann 已提交
967
    while (props->name) {
E
Eduardo Habkost 已提交
968
        if (strcmp(props->name, name) == 0) {
G
Gerd Hoffmann 已提交
969
            return props;
E
Eduardo Habkost 已提交
970
        }
G
Gerd Hoffmann 已提交
971 972 973 974 975 976 977
        props++;
    }
    return NULL;
}

static Property *qdev_prop_find(DeviceState *dev, const char *name)
{
978
    ObjectClass *class;
G
Gerd Hoffmann 已提交
979 980 981
    Property *prop;

    /* device properties */
982 983 984 985 986 987 988 989
    class = object_get_class(OBJECT(dev));
    do {
        prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
        if (prop) {
            return prop;
        }
        class = object_class_get_parent(class);
    } while (class != object_class_by_name(TYPE_DEVICE));
G
Gerd Hoffmann 已提交
990 991 992 993

    return NULL;
}

994 995 996 997 998
void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
                                    Property *prop, const char *value)
{
    switch (ret) {
    case -EEXIST:
999
        error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
1000
                  object_get_typename(OBJECT(dev)), prop->name, value);
1001 1002 1003
        break;
    default:
    case -EINVAL:
1004 1005
        error_setg(errp, QERR_PROPERTY_VALUE_BAD,
                   object_get_typename(OBJECT(dev)), prop->name, value);
1006 1007
        break;
    case -ENOENT:
1008
        error_setg(errp, "Property '%s.%s' can't find value '%s'",
1009
                  object_get_typename(OBJECT(dev)), prop->name, value);
1010 1011 1012 1013 1014 1015
        break;
    case 0:
        break;
    }
}

1016 1017
void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
{
1018
    object_property_set_bool(OBJECT(dev), value, name, &error_abort);
1019 1020
}

J
Juan Quintela 已提交
1021 1022
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
{
1023
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
J
Juan Quintela 已提交
1024 1025
}

G
Gerd Hoffmann 已提交
1026 1027
void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
{
1028
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
G
Gerd Hoffmann 已提交
1029 1030 1031 1032
}

void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
{
1033
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
G
Gerd Hoffmann 已提交
1034 1035
}

1036 1037
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
{
1038
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
1039 1040
}

B
Blue Swirl 已提交
1041 1042
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
{
1043
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
B
Blue Swirl 已提交
1044 1045
}

1046
void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
1047
{
1048
    object_property_set_str(OBJECT(dev), value, name, &error_abort);
1049 1050
}

1051 1052
void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
                           const uint8_t *value)
G
Gerd Hoffmann 已提交
1053
{
P
Paolo Bonzini 已提交
1054 1055 1056 1057
    char str[2 * 6 + 5 + 1];
    snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
             value[0], value[1], value[2], value[3], value[4], value[5]);

1058
    object_property_set_str(OBJECT(dev), str, name, &error_abort);
G
Gerd Hoffmann 已提交
1059 1060
}

P
Paolo Bonzini 已提交
1061
void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
1062
{
P
Paolo Bonzini 已提交
1063 1064 1065 1066
    Property *prop;

    prop = qdev_prop_find(dev, name);
    object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1067
                            name, &error_abort);
1068 1069
}

G
Gerd Hoffmann 已提交
1070 1071
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
{
1072 1073 1074 1075 1076 1077 1078
    Property *prop;
    void **ptr;

    prop = qdev_prop_find(dev, name);
    assert(prop && prop->info == &qdev_prop_ptr);
    ptr = qdev_get_prop_ptr(dev, prop);
    *ptr = value;
G
Gerd Hoffmann 已提交
1079 1080
}

1081
static GList *global_props;
1082

1083
void qdev_prop_register_global(GlobalProperty *prop)
1084
{
1085
    global_props = g_list_append(global_props, prop);
1086 1087
}

1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
void register_compat_prop(const char *driver,
                          const char *property,
                          const char *value)
{
    GlobalProperty *p = g_new0(GlobalProperty, 1);

    /* Any compat_props must never cause error */
    p->errp = &error_abort;
    p->driver = driver;
    p->property = property;
    p->value = value;
    qdev_prop_register_global(p);
}

1102 1103 1104 1105 1106 1107 1108
void register_compat_props_array(GlobalProperty *prop)
{
    for (; prop && prop->driver; prop++) {
        register_compat_prop(prop->driver, prop->property, prop->value);
    }
}

1109
void qdev_prop_register_global_list(GlobalProperty *props)
1110
{
1111
    int i;
1112

1113 1114
    for (i = 0; props[i].driver != NULL; i++) {
        qdev_prop_register_global(props+i);
1115
    }
1116 1117
}

1118
int qdev_prop_check_globals(void)
1119
{
1120
    GList *l;
1121 1122
    int ret = 0;

1123 1124
    for (l = global_props; l; l = l->next) {
        GlobalProperty *prop = l->data;
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
        ObjectClass *oc;
        DeviceClass *dc;
        if (prop->used) {
            continue;
        }
        if (!prop->user_provided) {
            continue;
        }
        oc = object_class_by_name(prop->driver);
        oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
        if (!oc) {
1136 1137
            warn_report("global %s.%s has invalid class name",
                        prop->driver, prop->property);
1138 1139 1140 1141 1142
            ret = 1;
            continue;
        }
        dc = DEVICE_CLASS(oc);
        if (!dc->hotpluggable && !prop->used) {
1143 1144
            warn_report("global %s.%s=%s not used",
                        prop->driver, prop->property, prop->value);
1145
            ret = 1;
1146 1147 1148 1149 1150 1151
            continue;
        }
    }
    return ret;
}

1152
static void qdev_prop_set_globals_for_type(DeviceState *dev,
1153
                                           const char *typename)
1154
{
1155
    GList *l;
1156

1157 1158
    for (l = global_props; l; l = l->next) {
        GlobalProperty *prop = l->data;
1159 1160 1161 1162 1163
        Error *err = NULL;

        if (strcmp(typename, prop->driver) != 0) {
            continue;
        }
1164
        prop->used = true;
P
Paolo Bonzini 已提交
1165
        object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
1166
        if (err != NULL) {
1167 1168
            error_prepend(&err, "can't apply global %s.%s=%s: ",
                          prop->driver, prop->property, prop->value);
1169
            if (!dev->hotplugged && prop->errp) {
1170 1171 1172
                error_propagate(prop->errp, err);
            } else {
                assert(prop->user_provided);
1173
                warn_report_err(err);
1174
            }
1175 1176 1177 1178
        }
    }
}

1179
void qdev_prop_set_globals(DeviceState *dev)
1180
{
1181 1182 1183
    ObjectClass *class = object_get_class(OBJECT(dev));

    do {
1184
        qdev_prop_set_globals_for_type(dev, object_class_get_name(class));
1185 1186
        class = object_class_get_parent(class);
    } while (class);
1187
}
1188 1189 1190

/* --- 64bit unsigned int 'size' type --- */

1191 1192
static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
1193 1194 1195 1196 1197
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);

1198
    visit_type_size(v, name, ptr, errp);
1199 1200
}

1201 1202
static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
1203 1204 1205 1206 1207
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);

1208
    visit_type_size(v, name, ptr, errp);
1209 1210
}

1211
const PropertyInfo qdev_prop_size = {
1212 1213 1214
    .name  = "size",
    .get = get_size,
    .set = set_size,
1215
    .set_default_value = set_default_value_uint,
1216
};
F
Fam Zheng 已提交
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230

/* --- object link property --- */

static void create_link_property(Object *obj, Property *prop, Error **errp)
{
    Object **child = qdev_get_prop_ptr(DEVICE(obj), prop);

    object_property_add_link(obj, prop->name, prop->link_type,
                             child,
                             qdev_prop_allow_set_link_before_realize,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
                             errp);
}

1231
const PropertyInfo qdev_prop_link = {
F
Fam Zheng 已提交
1232 1233 1234
    .name = "link",
    .create = create_link_property,
};