qdev-properties.c 31.2 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 30 31 32 33 34 35 36 37 38 39
void qdev_prop_allow_set_link_before_realize(Object *obj, const char *name,
                                             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 已提交
40 41 42 43 44 45 46
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
{
    void *ptr = dev;
    ptr += prop->offset;
    return ptr;
}

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

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

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

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

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

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

78 79
/* Bit */

M
Michael S. Tsirkin 已提交
80 81
static uint32_t qdev_get_prop_mask(Property *prop)
{
82
    assert(prop->info == &qdev_prop_bit);
M
Michael S. Tsirkin 已提交
83 84 85 86 87 88 89
    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 已提交
90
    if (val) {
91
        *p |= mask;
E
Eduardo Habkost 已提交
92
    } else {
M
Michael S. Tsirkin 已提交
93
        *p &= ~mask;
E
Eduardo Habkost 已提交
94
    }
M
Michael S. Tsirkin 已提交
95 96
}

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

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

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

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

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

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

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

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

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

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;
    }
}

161 162
static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
                           void *opaque, Error **errp)
G
Gerd Hoffmann 已提交
163 164 165 166 167 168
{
    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;

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

172 173
static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
                           void *opaque, Error **errp)
G
Gerd Hoffmann 已提交
174 175 176 177 178 179 180 181 182 183 184
{
    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;
    }

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

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

201 202
/* --- bool --- */

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

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

213 214
static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
215 216 217 218 219 220 221 222 223 224
{
    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;
    }

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

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

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

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

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

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

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

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

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

J
Juan Quintela 已提交
267 268
PropertyInfo qdev_prop_uint8 = {
    .name  = "uint8",
269 270
    .get   = get_uint8,
    .set   = set_uint8,
271
    .set_default_value = set_default_value_int,
J
Juan Quintela 已提交
272 273
};

G
Gerd Hoffmann 已提交
274 275
/* --- 16bit integer --- */

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

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

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

293
    if (dev->realized) {
294
        qdev_prop_set_after_realize(dev, name, errp);
295 296 297
        return;
    }

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

G
Gerd Hoffmann 已提交
301 302
PropertyInfo qdev_prop_uint16 = {
    .name  = "uint16",
303 304
    .get   = get_uint16,
    .set   = set_uint16,
305
    .set_default_value = set_default_value_int,
G
Gerd Hoffmann 已提交
306 307 308 309
};

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

310 311
static void get_uint32(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
312 313 314
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
315
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
316

317
    visit_type_uint32(v, name, ptr, errp);
318 319
}

320 321
static void set_uint32(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
322 323 324
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
325
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
326

327
    if (dev->realized) {
328
        qdev_prop_set_after_realize(dev, name, errp);
329 330 331
        return;
    }

332
    visit_type_uint32(v, name, ptr, errp);
333 334
}

335 336
static void get_int32(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
337
{
338
    DeviceState *dev = DEVICE(obj);
339 340 341
    Property *prop = opaque;
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);

342
    visit_type_int32(v, name, ptr, errp);
343 344
}

345 346
static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
347
{
348
    DeviceState *dev = DEVICE(obj);
349
    Property *prop = opaque;
350
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
351

352
    if (dev->realized) {
353
        qdev_prop_set_after_realize(dev, name, errp);
354 355 356
        return;
    }

357
    visit_type_int32(v, name, ptr, errp);
358 359
}

G
Gerd Hoffmann 已提交
360 361
PropertyInfo qdev_prop_uint32 = {
    .name  = "uint32",
362 363
    .get   = get_uint32,
    .set   = set_uint32,
364
    .set_default_value = set_default_value_int,
G
Gerd Hoffmann 已提交
365 366
};

367 368
PropertyInfo qdev_prop_int32 = {
    .name  = "int32",
369 370
    .get   = get_int32,
    .set   = set_int32,
371
    .set_default_value = set_default_value_int,
372 373
};

B
Blue Swirl 已提交
374 375
/* --- 64bit integer --- */

376 377
static void get_uint64(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
378
{
379
    DeviceState *dev = DEVICE(obj);
380
    Property *prop = opaque;
381
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
382

383
    visit_type_uint64(v, name, ptr, errp);
384 385
}

386 387
static void set_uint64(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
388
{
389
    DeviceState *dev = DEVICE(obj);
390
    Property *prop = opaque;
391
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
392

393
    if (dev->realized) {
394
        qdev_prop_set_after_realize(dev, name, errp);
395 396 397
        return;
    }

398
    visit_type_uint64(v, name, ptr, errp);
399 400
}

B
Blue Swirl 已提交
401 402
PropertyInfo qdev_prop_uint64 = {
    .name  = "uint64",
403 404
    .get   = get_uint64,
    .set   = set_uint64,
405
    .set_default_value = set_default_value_int,
B
Blue Swirl 已提交
406 407
};

G
Gerd Hoffmann 已提交
408 409
/* --- string --- */

P
Paolo Bonzini 已提交
410
static void release_string(Object *obj, const char *name, void *opaque)
411
{
P
Paolo Bonzini 已提交
412 413
    Property *prop = opaque;
    g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
414 415
}

416 417
static void get_string(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
418
{
419
    DeviceState *dev = DEVICE(obj);
420 421 422 423 424
    Property *prop = opaque;
    char **ptr = qdev_get_prop_ptr(dev, prop);

    if (!*ptr) {
        char *str = (char *)"";
425
        visit_type_str(v, name, &str, errp);
426
    } else {
427
        visit_type_str(v, name, ptr, errp);
428 429 430
    }
}

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

440
    if (dev->realized) {
441
        qdev_prop_set_after_realize(dev, name, errp);
442 443 444
        return;
    }

445
    visit_type_str(v, name, &str, &local_err);
446 447 448 449
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
450
    g_free(*ptr);
451 452 453
    *ptr = str;
}

G
Gerd Hoffmann 已提交
454
PropertyInfo qdev_prop_string = {
455
    .name  = "str",
P
Paolo Bonzini 已提交
456
    .release = release_string,
457 458
    .get   = get_string,
    .set   = set_string,
G
Gerd Hoffmann 已提交
459 460
};

G
Gerd Hoffmann 已提交
461 462
/* --- pointer --- */

463
/* Not a proper property, just for dirty hacks.  TODO Remove it!  */
G
Gerd Hoffmann 已提交
464 465 466 467 468 469 470 471 472 473 474
PropertyInfo qdev_prop_ptr = {
    .name  = "ptr",
};

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

/*
 * accepted syntax versions:
 *   01:02:03:04:05:06
 *   01-02-03-04-05-06
 */
475 476
static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
                    Error **errp)
G
Gerd Hoffmann 已提交
477
{
478 479
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
G
Gerd Hoffmann 已提交
480
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
481 482 483 484 485 486 487
    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]);

488
    visit_type_str(v, name, &p, errp);
489 490
}

491 492
static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
                    Error **errp)
493 494 495 496 497
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
    Error *local_err = NULL;
G
Gerd Hoffmann 已提交
498
    int i, pos;
499 500
    char *str, *p;

501
    if (dev->realized) {
502
        qdev_prop_set_after_realize(dev, name, errp);
503 504 505
        return;
    }

506
    visit_type_str(v, name, &str, &local_err);
507 508 509 510
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
G
Gerd Hoffmann 已提交
511 512

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

533 534
inval:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
D
dunrong huang 已提交
535
    g_free(str);
G
Gerd Hoffmann 已提交
536 537 538
}

PropertyInfo qdev_prop_macaddr = {
539
    .name  = "str",
540
    .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
541 542
    .get   = get_mac,
    .set   = set_mac,
G
Gerd Hoffmann 已提交
543 544
};

545 546 547 548 549 550 551 552
/* --- on/off/auto --- */

PropertyInfo qdev_prop_on_off_auto = {
    .name = "OnOffAuto",
    .description = "on/off/auto",
    .enum_table = OnOffAuto_lookup,
    .get = get_enum,
    .set = set_enum,
553
    .set_default_value = set_default_value_enum,
554 555
};

556 557
/* --- lost tick policy --- */

558 559
QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));

560
PropertyInfo qdev_prop_losttickpolicy = {
561
    .name  = "LostTickPolicy",
562
    .enum_table  = LostTickPolicy_lookup,
563 564
    .get   = get_enum,
    .set   = set_enum,
565
    .set_default_value = set_default_value_enum,
566 567
};

568 569 570 571 572 573 574 575 576 577 578
/* --- Block device error handling policy --- */

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

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

582 583
/* --- BIOS CHS translation */

584
QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
585 586

PropertyInfo qdev_prop_bios_chs_trans = {
587
    .name = "BiosAtaTranslation",
588 589
    .description = "Logical CHS translation algorithm, "
                   "auto/none/lba/large/rechs",
590
    .enum_table = BiosAtaTranslation_lookup,
591 592
    .get = get_enum,
    .set = set_enum,
593
    .set_default_value = set_default_value_enum,
594 595
};

J
John Snow 已提交
596 597 598 599 600 601 602 603
/* --- FDC default drive types */

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

608 609 610 611 612
/* --- pci address --- */

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

623
    if (dev->realized) {
624
        qdev_prop_set_after_realize(dev, name, errp);
625 626 627
        return;
    }

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

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

invalid:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
D
dunrong huang 已提交
659
    g_free(str);
660 661
}

E
Eduardo Habkost 已提交
662 663
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
                           size_t len)
664
{
665
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
666

B
Blue Swirl 已提交
667
    if (*ptr == -1) {
668 669 670 671 672 673 674
        return snprintf(dest, len, "<unset>");
    } else {
        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
    }
}

PropertyInfo qdev_prop_pci_devfn = {
675
    .name  = "int32",
676
    .description = "Slot and optional function number, example: 06.0 or 06",
677
    .print = print_pci_devfn,
678
    .get   = get_int32,
679
    .set   = set_pci_devfn,
680
    .set_default_value = set_default_value_int,
681 682
};

683 684
/* --- blocksize --- */

685 686
static void set_blocksize(Object *obj, Visitor *v, const char *name,
                          void *opaque, Error **errp)
687 688 689
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
690
    uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
691
    Error *local_err = NULL;
692 693
    const int64_t min = 512;
    const int64_t max = 32768;
694

695
    if (dev->realized) {
696
        qdev_prop_set_after_realize(dev, name, errp);
697 698 699
        return;
    }

700
    visit_type_uint16(v, name, &value, &local_err);
701 702 703 704
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
705 706
    /* value of 0 means "unset" */
    if (value && (value < min || value > max)) {
707 708
        error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
                   dev->id ? : "", name, (int64_t)value, min, max);
709 710 711 712 713
        return;
    }

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

    *ptr = value;
}

PropertyInfo qdev_prop_blocksize = {
724
    .name  = "uint16",
725
    .description = "A power of two between 512 and 32768",
726
    .get   = get_uint16,
727
    .set   = set_blocksize,
728
    .set_default_value = set_default_value_int,
729 730
};

731 732
/* --- pci host address --- */

733 734
static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
                                 void *opaque, Error **errp)
735 736 737 738
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
739
    char buffer[] = "ffff:ff:ff.f";
740 741 742
    char *p = buffer;
    int rc = 0;

743 744
    /*
     * Catch "invalid" device reference from vfio-pci and allow the
S
Stefan Weil 已提交
745
     * default buffer representing the non-existent device to be used.
746 747 748 749 750 751
     */
    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);
    }
752

753
    visit_type_str(v, name, &p, errp);
754 755 756 757 758 759
}

/*
 * Parse [<domain>:]<bus>:<slot>.<func>
 *   if <domain> is not supplied, it's assumed to be 0.
 */
760 761
static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
                                 void *opaque, Error **errp)
762 763 764 765 766 767 768 769 770 771 772
{
    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;

773
    if (dev->realized) {
774
        qdev_prop_set_after_realize(dev, name, errp);
775 776 777
        return;
    }

778
    visit_type_str(v, name, &str, &local_err);
779 780 781 782 783 784 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
    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);
}

PropertyInfo qdev_prop_pci_host_devaddr = {
839
    .name = "str",
840 841
    .description = "Address (bus/device/function) of "
                   "the host device, example: 04:10.0",
842 843 844 845
    .get = get_pci_host_devaddr,
    .set = set_pci_host_devaddr,
};

846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873
/* --- 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);
}

874 875
static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
                              void *opaque, Error **errp)
876 877 878 879 880 881 882 883 884 885
{
    /* 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;
886
    Error *local_err = NULL;
887 888 889 890 891
    void *eltptr;
    const char *arrayname;
    int i;

    if (dev->realized) {
892
        qdev_prop_set_after_realize(dev, name, errp);
893 894 895 896 897 898 899
        return;
    }
    if (*alenptr) {
        error_setg(errp, "array size property %s may not be set more than once",
                   name);
        return;
    }
900
    visit_type_uint32(v, name, alenptr, &local_err);
901 902
    if (local_err) {
        error_propagate(errp, local_err);
903 904 905 906 907 908 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
        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,
939 940 941
                            arrayprop, &local_err);
        if (local_err) {
            error_propagate(errp, local_err);
942 943 944 945 946 947 948 949 950
            return;
        }
    }
}

PropertyInfo qdev_prop_arraylen = {
    .name = "uint32",
    .get = get_uint32,
    .set = set_prop_arraylen,
951
    .set_default_value = set_default_value_int,
952 953
};

G
Gerd Hoffmann 已提交
954 955 956 957
/* --- public helpers --- */

static Property *qdev_prop_walk(Property *props, const char *name)
{
E
Eduardo Habkost 已提交
958
    if (!props) {
G
Gerd Hoffmann 已提交
959
        return NULL;
E
Eduardo Habkost 已提交
960
    }
G
Gerd Hoffmann 已提交
961
    while (props->name) {
E
Eduardo Habkost 已提交
962
        if (strcmp(props->name, name) == 0) {
G
Gerd Hoffmann 已提交
963
            return props;
E
Eduardo Habkost 已提交
964
        }
G
Gerd Hoffmann 已提交
965 966 967 968 969 970 971
        props++;
    }
    return NULL;
}

static Property *qdev_prop_find(DeviceState *dev, const char *name)
{
972
    ObjectClass *class;
G
Gerd Hoffmann 已提交
973 974 975
    Property *prop;

    /* device properties */
976 977 978 979 980 981 982 983
    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 已提交
984 985 986 987

    return NULL;
}

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

1010 1011
void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
{
1012
    object_property_set_bool(OBJECT(dev), value, name, &error_abort);
1013 1014
}

J
Juan Quintela 已提交
1015 1016
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
{
1017
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
J
Juan Quintela 已提交
1018 1019
}

G
Gerd Hoffmann 已提交
1020 1021
void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
{
1022
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
G
Gerd Hoffmann 已提交
1023 1024 1025 1026
}

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

1030 1031
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
{
1032
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
1033 1034
}

B
Blue Swirl 已提交
1035 1036
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
{
1037
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
B
Blue Swirl 已提交
1038 1039
}

1040
void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
1041
{
1042
    object_property_set_str(OBJECT(dev), value, name, &error_abort);
1043 1044
}

1045 1046
void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
                           const uint8_t *value)
G
Gerd Hoffmann 已提交
1047
{
P
Paolo Bonzini 已提交
1048 1049 1050 1051
    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]);

1052
    object_property_set_str(OBJECT(dev), str, name, &error_abort);
G
Gerd Hoffmann 已提交
1053 1054
}

P
Paolo Bonzini 已提交
1055
void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
1056
{
P
Paolo Bonzini 已提交
1057 1058 1059 1060
    Property *prop;

    prop = qdev_prop_find(dev, name);
    object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1061
                            name, &error_abort);
1062 1063
}

G
Gerd Hoffmann 已提交
1064 1065
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
{
1066 1067 1068 1069 1070 1071 1072
    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 已提交
1073 1074
}

1075
static GList *global_props;
1076

1077
void qdev_prop_register_global(GlobalProperty *prop)
1078
{
1079
    global_props = g_list_append(global_props, prop);
1080 1081
}

1082
void qdev_prop_register_global_list(GlobalProperty *props)
1083
{
1084
    int i;
1085

1086 1087
    for (i = 0; props[i].driver != NULL; i++) {
        qdev_prop_register_global(props+i);
1088
    }
1089 1090
}

1091
int qdev_prop_check_globals(void)
1092
{
1093
    GList *l;
1094 1095
    int ret = 0;

1096 1097
    for (l = global_props; l; l = l->next) {
        GlobalProperty *prop = l->data;
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118
        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) {
            error_report("Warning: global %s.%s has invalid class name",
                       prop->driver, prop->property);
            ret = 1;
            continue;
        }
        dc = DEVICE_CLASS(oc);
        if (!dc->hotpluggable && !prop->used) {
            error_report("Warning: global %s.%s=%s not used",
                       prop->driver, prop->property, prop->value);
            ret = 1;
1119 1120 1121 1122 1123 1124
            continue;
        }
    }
    return ret;
}

1125
static void qdev_prop_set_globals_for_type(DeviceState *dev,
1126
                                           const char *typename)
1127
{
1128
    GList *l;
1129

1130 1131
    for (l = global_props; l; l = l->next) {
        GlobalProperty *prop = l->data;
1132 1133 1134 1135 1136
        Error *err = NULL;

        if (strcmp(typename, prop->driver) != 0) {
            continue;
        }
1137
        prop->used = true;
P
Paolo Bonzini 已提交
1138
        object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
1139
        if (err != NULL) {
1140 1141
            error_prepend(&err, "can't apply global %s.%s=%s: ",
                          prop->driver, prop->property, prop->value);
1142
            if (!dev->hotplugged && prop->errp) {
1143 1144 1145 1146 1147
                error_propagate(prop->errp, err);
            } else {
                assert(prop->user_provided);
                error_reportf_err(err, "Warning: ");
            }
1148 1149 1150 1151
        }
    }
}

1152
void qdev_prop_set_globals(DeviceState *dev)
1153
{
1154 1155 1156
    ObjectClass *class = object_get_class(OBJECT(dev));

    do {
1157
        qdev_prop_set_globals_for_type(dev, object_class_get_name(class));
1158 1159
        class = object_class_get_parent(class);
    } while (class);
1160
}
1161 1162 1163

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

1164 1165
static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
1166 1167 1168 1169 1170
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);

1171
    visit_type_size(v, name, ptr, errp);
1172 1173
}

1174 1175
static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
1176 1177 1178 1179 1180
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);

1181
    visit_type_size(v, name, ptr, errp);
1182 1183 1184 1185 1186 1187
}

PropertyInfo qdev_prop_size = {
    .name  = "size",
    .get = get_size,
    .set = set_size,
1188
    .set_default_value = set_default_value_int,
1189
};