qdev-properties.c 29.9 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 "sysemu/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
}

/* Bit */

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

91 92
static void prop_get_bit(Object *obj, Visitor *v, const char *name,
                         void *opaque, Error **errp)
93
{
94
    DeviceState *dev = DEVICE(obj);
95 96 97 98
    Property *prop = opaque;
    uint32_t *p = qdev_get_prop_ptr(dev, prop);
    bool value = (*p & qdev_get_prop_mask(prop)) != 0;

99
    visit_type_bool(v, name, &value, errp);
100 101
}

102 103
static void prop_set_bit(Object *obj, Visitor *v, const char *name,
                         void *opaque, Error **errp)
104
{
105
    DeviceState *dev = DEVICE(obj);
106 107 108 109
    Property *prop = opaque;
    Error *local_err = NULL;
    bool value;

110
    if (dev->realized) {
111
        qdev_prop_set_after_realize(dev, name, errp);
112 113 114
        return;
    }

115
    visit_type_bool(v, name, &value, &local_err);
116 117 118 119 120 121 122
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
    bit_prop_set(dev, prop, value);
}

M
Michael S. Tsirkin 已提交
123
PropertyInfo qdev_prop_bit = {
124
    .name  = "bool",
125
    .description = "on/off",
126 127
    .get   = prop_get_bit,
    .set   = prop_set_bit,
M
Michael S. Tsirkin 已提交
128 129
};

G
Gerd Hoffmann 已提交
130 131 132 133
/* Bit64 */

static uint64_t qdev_get_prop_mask64(Property *prop)
{
C
Cornelia Huck 已提交
134
    assert(prop->info == &qdev_prop_bit64);
G
Gonglei 已提交
135
    return 0x1ull << prop->bitnr;
G
Gerd Hoffmann 已提交
136 137 138 139 140 141 142 143 144 145 146 147 148
}

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

149 150
static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
                           void *opaque, Error **errp)
G
Gerd Hoffmann 已提交
151 152 153 154 155 156
{
    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;

157
    visit_type_bool(v, name, &value, errp);
G
Gerd Hoffmann 已提交
158 159
}

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

173
    visit_type_bool(v, name, &value, &local_err);
G
Gerd Hoffmann 已提交
174 175 176 177 178 179 180 181 182 183 184 185 186 187
    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,
};

188 189
/* --- bool --- */

190 191
static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
192 193 194 195 196
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    bool *ptr = qdev_get_prop_ptr(dev, prop);

197
    visit_type_bool(v, name, ptr, errp);
198 199
}

200 201
static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
202 203 204 205 206 207 208 209 210 211
{
    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;
    }

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

PropertyInfo qdev_prop_bool = {
216
    .name  = "bool",
217 218 219 220
    .get   = get_bool,
    .set   = set_bool,
};

J
Juan Quintela 已提交
221 222
/* --- 8bit integer --- */

223 224
static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
225
{
226
    DeviceState *dev = DEVICE(obj);
227
    Property *prop = opaque;
228
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
229

230
    visit_type_uint8(v, name, ptr, errp);
231 232
}

233 234
static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
235
{
236
    DeviceState *dev = DEVICE(obj);
237
    Property *prop = opaque;
238
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
239

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

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

J
Juan Quintela 已提交
248 249
PropertyInfo qdev_prop_uint8 = {
    .name  = "uint8",
250 251
    .get   = get_uint8,
    .set   = set_uint8,
J
Juan Quintela 已提交
252 253
};

G
Gerd Hoffmann 已提交
254 255
/* --- 16bit integer --- */

256 257
static void get_uint16(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
258
{
259
    DeviceState *dev = DEVICE(obj);
260
    Property *prop = opaque;
261
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
262

263
    visit_type_uint16(v, name, ptr, errp);
264 265
}

266 267
static void set_uint16(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
268
{
269
    DeviceState *dev = DEVICE(obj);
270
    Property *prop = opaque;
271
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
272

273
    if (dev->realized) {
274
        qdev_prop_set_after_realize(dev, name, errp);
275 276 277
        return;
    }

278
    visit_type_uint16(v, name, ptr, errp);
279 280
}

G
Gerd Hoffmann 已提交
281 282
PropertyInfo qdev_prop_uint16 = {
    .name  = "uint16",
283 284
    .get   = get_uint16,
    .set   = set_uint16,
G
Gerd Hoffmann 已提交
285 286 287 288
};

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

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

296
    visit_type_uint32(v, name, ptr, errp);
297 298
}

299 300
static void set_uint32(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
301 302 303
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
304
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
305

306
    if (dev->realized) {
307
        qdev_prop_set_after_realize(dev, name, errp);
308 309 310
        return;
    }

311
    visit_type_uint32(v, name, ptr, errp);
312 313
}

314 315
static void get_int32(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
316
{
317
    DeviceState *dev = DEVICE(obj);
318 319 320
    Property *prop = opaque;
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);

321
    visit_type_int32(v, name, ptr, errp);
322 323
}

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

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

336
    visit_type_int32(v, name, ptr, errp);
337 338
}

G
Gerd Hoffmann 已提交
339 340
PropertyInfo qdev_prop_uint32 = {
    .name  = "uint32",
341 342
    .get   = get_uint32,
    .set   = set_uint32,
G
Gerd Hoffmann 已提交
343 344
};

345 346
PropertyInfo qdev_prop_int32 = {
    .name  = "int32",
347 348
    .get   = get_int32,
    .set   = set_int32,
349 350
};

B
Blue Swirl 已提交
351 352
/* --- 64bit integer --- */

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

360
    visit_type_uint64(v, name, ptr, errp);
361 362
}

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

370
    if (dev->realized) {
371
        qdev_prop_set_after_realize(dev, name, errp);
372 373 374
        return;
    }

375
    visit_type_uint64(v, name, ptr, errp);
376 377
}

B
Blue Swirl 已提交
378 379
PropertyInfo qdev_prop_uint64 = {
    .name  = "uint64",
380 381
    .get   = get_uint64,
    .set   = set_uint64,
B
Blue Swirl 已提交
382 383
};

G
Gerd Hoffmann 已提交
384 385
/* --- string --- */

P
Paolo Bonzini 已提交
386
static void release_string(Object *obj, const char *name, void *opaque)
387
{
P
Paolo Bonzini 已提交
388 389
    Property *prop = opaque;
    g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
390 391
}

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

    if (!*ptr) {
        char *str = (char *)"";
401
        visit_type_str(v, name, &str, errp);
402
    } else {
403
        visit_type_str(v, name, ptr, errp);
404 405 406
    }
}

407 408
static void set_string(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
409
{
410
    DeviceState *dev = DEVICE(obj);
411 412 413 414 415
    Property *prop = opaque;
    char **ptr = qdev_get_prop_ptr(dev, prop);
    Error *local_err = NULL;
    char *str;

416
    if (dev->realized) {
417
        qdev_prop_set_after_realize(dev, name, errp);
418 419 420
        return;
    }

421
    visit_type_str(v, name, &str, &local_err);
422 423 424 425
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
426
    g_free(*ptr);
427 428 429
    *ptr = str;
}

G
Gerd Hoffmann 已提交
430
PropertyInfo qdev_prop_string = {
431
    .name  = "str",
P
Paolo Bonzini 已提交
432
    .release = release_string,
433 434
    .get   = get_string,
    .set   = set_string,
G
Gerd Hoffmann 已提交
435 436
};

G
Gerd Hoffmann 已提交
437 438
/* --- pointer --- */

439
/* Not a proper property, just for dirty hacks.  TODO Remove it!  */
G
Gerd Hoffmann 已提交
440 441 442 443 444 445 446 447 448 449 450
PropertyInfo qdev_prop_ptr = {
    .name  = "ptr",
};

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

/*
 * accepted syntax versions:
 *   01:02:03:04:05:06
 *   01-02-03-04-05-06
 */
451 452
static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
                    Error **errp)
G
Gerd Hoffmann 已提交
453
{
454 455
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
G
Gerd Hoffmann 已提交
456
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
457 458 459 460 461 462 463
    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]);

464
    visit_type_str(v, name, &p, errp);
465 466
}

467 468
static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
                    Error **errp)
469 470 471 472 473
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
    Error *local_err = NULL;
G
Gerd Hoffmann 已提交
474
    int i, pos;
475 476
    char *str, *p;

477
    if (dev->realized) {
478
        qdev_prop_set_after_realize(dev, name, errp);
479 480 481
        return;
    }

482
    visit_type_str(v, name, &str, &local_err);
483 484 485 486
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
G
Gerd Hoffmann 已提交
487 488

    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
E
Eduardo Habkost 已提交
489
        if (!qemu_isxdigit(str[pos])) {
490
            goto inval;
E
Eduardo Habkost 已提交
491 492
        }
        if (!qemu_isxdigit(str[pos+1])) {
493
            goto inval;
E
Eduardo Habkost 已提交
494
        }
G
Gerd Hoffmann 已提交
495
        if (i == 5) {
E
Eduardo Habkost 已提交
496
            if (str[pos+2] != '\0') {
497
                goto inval;
E
Eduardo Habkost 已提交
498
            }
G
Gerd Hoffmann 已提交
499
        } else {
E
Eduardo Habkost 已提交
500
            if (str[pos+2] != ':' && str[pos+2] != '-') {
501
                goto inval;
E
Eduardo Habkost 已提交
502
            }
G
Gerd Hoffmann 已提交
503 504
        }
        mac->a[i] = strtol(str+pos, &p, 16);
G
Gerd Hoffmann 已提交
505
    }
D
dunrong huang 已提交
506
    g_free(str);
507
    return;
G
Gerd Hoffmann 已提交
508

509 510
inval:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
D
dunrong huang 已提交
511
    g_free(str);
G
Gerd Hoffmann 已提交
512 513 514
}

PropertyInfo qdev_prop_macaddr = {
515
    .name  = "str",
516
    .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
517 518
    .get   = get_mac,
    .set   = set_mac,
G
Gerd Hoffmann 已提交
519 520
};

521 522 523 524 525 526 527 528 529 530
/* --- 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,
};

531 532
/* --- lost tick policy --- */

533 534
QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));

535
PropertyInfo qdev_prop_losttickpolicy = {
536
    .name  = "LostTickPolicy",
537
    .enum_table  = LostTickPolicy_lookup,
538 539
    .get   = get_enum,
    .set   = set_enum,
540 541
};

542 543 544 545 546 547 548 549 550 551 552 553 554
/* --- 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,
};

555 556
/* --- BIOS CHS translation */

557
QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
558 559

PropertyInfo qdev_prop_bios_chs_trans = {
560
    .name = "BiosAtaTranslation",
561 562
    .description = "Logical CHS translation algorithm, "
                   "auto/none/lba/large/rechs",
563
    .enum_table = BiosAtaTranslation_lookup,
564 565 566 567
    .get = get_enum,
    .set = set_enum,
};

J
John Snow 已提交
568 569 570 571 572 573 574 575 576 577 578
/* --- 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,
    .set = set_enum
};

579 580 581 582 583
/* --- pci address --- */

/*
 * bus-local address, i.e. "$slot" or "$slot.$fn"
 */
584 585
static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
                          void *opaque, Error **errp)
586
{
587 588
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
589
    int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
590
    unsigned int slot, fn, n;
591
    Error *local_err = NULL;
D
dunrong huang 已提交
592
    char *str;
593

594
    if (dev->realized) {
595
        qdev_prop_set_after_realize(dev, name, errp);
596 597 598
        return;
    }

599
    visit_type_str(v, name, &str, &local_err);
600
    if (local_err) {
601
        error_free(local_err);
602
        local_err = NULL;
603
        visit_type_int32(v, name, &value, &local_err);
604 605 606
        if (local_err) {
            error_propagate(errp, local_err);
        } else if (value < -1 || value > 255) {
607 608
            error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
                       name ? name : "null", "pci_devfn");
609 610 611 612
        } else {
            *ptr = value;
        }
        return;
613
    }
614 615 616 617

    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
        fn = 0;
        if (sscanf(str, "%x%n", &slot, &n) != 1) {
618
            goto invalid;
619 620
        }
    }
621 622 623
    if (str[n] != '\0' || fn > 7 || slot > 31) {
        goto invalid;
    }
624
    *ptr = slot << 3 | fn;
D
dunrong huang 已提交
625
    g_free(str);
626 627 628 629
    return;

invalid:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
D
dunrong huang 已提交
630
    g_free(str);
631 632
}

E
Eduardo Habkost 已提交
633 634
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
                           size_t len)
635
{
636
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
637

B
Blue Swirl 已提交
638
    if (*ptr == -1) {
639 640 641 642 643 644 645
        return snprintf(dest, len, "<unset>");
    } else {
        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
    }
}

PropertyInfo qdev_prop_pci_devfn = {
646
    .name  = "int32",
647
    .description = "Slot and optional function number, example: 06.0 or 06",
648
    .print = print_pci_devfn,
649
    .get   = get_int32,
650
    .set   = set_pci_devfn,
651 652
};

653 654
/* --- blocksize --- */

655 656
static void set_blocksize(Object *obj, Visitor *v, const char *name,
                          void *opaque, Error **errp)
657 658 659
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
660
    uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
661
    Error *local_err = NULL;
662 663
    const int64_t min = 512;
    const int64_t max = 32768;
664

665
    if (dev->realized) {
666
        qdev_prop_set_after_realize(dev, name, errp);
667 668 669
        return;
    }

670
    visit_type_uint16(v, name, &value, &local_err);
671 672 673 674
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
675 676
    /* value of 0 means "unset" */
    if (value && (value < min || value > max)) {
677 678
        error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
                   dev->id ? : "", name, (int64_t)value, min, max);
679 680 681 682 683
        return;
    }

    /* We rely on power-of-2 blocksizes for bitmasks */
    if ((value & (value - 1)) != 0) {
684 685 686
        error_setg(errp,
                  "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2",
                  dev->id ?: "", name, (int64_t)value);
687 688 689 690 691 692 693
        return;
    }

    *ptr = value;
}

PropertyInfo qdev_prop_blocksize = {
694
    .name  = "uint16",
695
    .description = "A power of two between 512 and 32768",
696
    .get   = get_uint16,
697 698 699
    .set   = set_blocksize,
};

700 701
/* --- pci host address --- */

702 703
static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
                                 void *opaque, Error **errp)
704 705 706 707
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
708
    char buffer[] = "ffff:ff:ff.f";
709 710 711
    char *p = buffer;
    int rc = 0;

712 713 714 715 716 717 718 719 720
    /*
     * Catch "invalid" device reference from vfio-pci and allow the
     * default buffer representing the non-existant device to be used.
     */
    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);
    }
721

722
    visit_type_str(v, name, &p, errp);
723 724 725 726 727 728
}

/*
 * Parse [<domain>:]<bus>:<slot>.<func>
 *   if <domain> is not supplied, it's assumed to be 0.
 */
729 730
static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
                                 void *opaque, Error **errp)
731 732 733 734 735 736 737 738 739 740 741
{
    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;

742
    if (dev->realized) {
743
        qdev_prop_set_after_realize(dev, name, errp);
744 745 746
        return;
    }

747
    visit_type_str(v, name, &str, &local_err);
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 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
    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 = {
808
    .name = "str",
809 810
    .description = "Address (bus/device/function) of "
                   "the host device, example: 04:10.0",
811 812 813 814
    .get = get_pci_host_devaddr,
    .set = set_pci_host_devaddr,
};

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
/* --- 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);
}

843 844
static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
                              void *opaque, Error **errp)
845 846 847 848 849 850 851 852 853 854
{
    /* 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;
855
    Error *local_err = NULL;
856 857 858 859 860
    void *eltptr;
    const char *arrayname;
    int i;

    if (dev->realized) {
861
        qdev_prop_set_after_realize(dev, name, errp);
862 863 864 865 866 867 868
        return;
    }
    if (*alenptr) {
        error_setg(errp, "array size property %s may not be set more than once",
                   name);
        return;
    }
869
    visit_type_uint32(v, name, alenptr, &local_err);
870 871
    if (local_err) {
        error_propagate(errp, local_err);
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907
        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,
908 909 910
                            arrayprop, &local_err);
        if (local_err) {
            error_propagate(errp, local_err);
911 912 913 914 915 916 917 918 919 920 921
            return;
        }
    }
}

PropertyInfo qdev_prop_arraylen = {
    .name = "uint32",
    .get = get_uint32,
    .set = set_prop_arraylen,
};

G
Gerd Hoffmann 已提交
922 923 924 925
/* --- public helpers --- */

static Property *qdev_prop_walk(Property *props, const char *name)
{
E
Eduardo Habkost 已提交
926
    if (!props) {
G
Gerd Hoffmann 已提交
927
        return NULL;
E
Eduardo Habkost 已提交
928
    }
G
Gerd Hoffmann 已提交
929
    while (props->name) {
E
Eduardo Habkost 已提交
930
        if (strcmp(props->name, name) == 0) {
G
Gerd Hoffmann 已提交
931
            return props;
E
Eduardo Habkost 已提交
932
        }
G
Gerd Hoffmann 已提交
933 934 935 936 937 938 939
        props++;
    }
    return NULL;
}

static Property *qdev_prop_find(DeviceState *dev, const char *name)
{
940
    ObjectClass *class;
G
Gerd Hoffmann 已提交
941 942 943
    Property *prop;

    /* device properties */
944 945 946 947 948 949 950 951
    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 已提交
952 953 954 955

    return NULL;
}

956 957 958 959 960
void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
                                    Property *prop, const char *value)
{
    switch (ret) {
    case -EEXIST:
961
        error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
962
                  object_get_typename(OBJECT(dev)), prop->name, value);
963 964 965
        break;
    default:
    case -EINVAL:
966 967
        error_setg(errp, QERR_PROPERTY_VALUE_BAD,
                   object_get_typename(OBJECT(dev)), prop->name, value);
968 969
        break;
    case -ENOENT:
970
        error_setg(errp, "Property '%s.%s' can't find value '%s'",
971
                  object_get_typename(OBJECT(dev)), prop->name, value);
972 973 974 975 976 977
        break;
    case 0:
        break;
    }
}

978 979
void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
{
980
    object_property_set_bool(OBJECT(dev), value, name, &error_abort);
981 982
}

J
Juan Quintela 已提交
983 984
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
{
985
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
J
Juan Quintela 已提交
986 987
}

G
Gerd Hoffmann 已提交
988 989
void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
{
990
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
G
Gerd Hoffmann 已提交
991 992 993 994
}

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

998 999
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
{
1000
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
1001 1002
}

B
Blue Swirl 已提交
1003 1004
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
{
1005
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
B
Blue Swirl 已提交
1006 1007
}

1008
void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
1009
{
1010
    object_property_set_str(OBJECT(dev), value, name, &error_abort);
1011 1012
}

G
Gerd Hoffmann 已提交
1013 1014
void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
{
P
Paolo Bonzini 已提交
1015 1016 1017 1018
    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]);

1019
    object_property_set_str(OBJECT(dev), str, name, &error_abort);
G
Gerd Hoffmann 已提交
1020 1021
}

P
Paolo Bonzini 已提交
1022
void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
1023
{
P
Paolo Bonzini 已提交
1024 1025 1026 1027
    Property *prop;

    prop = qdev_prop_find(dev, name);
    object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1028
                            name, &error_abort);
1029 1030
}

G
Gerd Hoffmann 已提交
1031 1032
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
{
1033 1034 1035 1036 1037 1038 1039
    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 已提交
1040 1041
}

1042
static GList *global_props;
1043

1044
void qdev_prop_register_global(GlobalProperty *prop)
1045
{
1046
    global_props = g_list_append(global_props, prop);
1047 1048
}

1049
void qdev_prop_register_global_list(GlobalProperty *props)
1050
{
1051
    int i;
1052

1053 1054
    for (i = 0; props[i].driver != NULL; i++) {
        qdev_prop_register_global(props+i);
1055
    }
1056 1057
}

1058
int qdev_prop_check_globals(void)
1059
{
1060
    GList *l;
1061 1062
    int ret = 0;

1063 1064
    for (l = global_props; l; l = l->next) {
        GlobalProperty *prop = l->data;
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
        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;
1086 1087 1088 1089 1090 1091
            continue;
        }
    }
    return ret;
}

1092
static void qdev_prop_set_globals_for_type(DeviceState *dev,
1093
                                           const char *typename)
1094
{
1095
    GList *l;
1096

1097 1098
    for (l = global_props; l; l = l->next) {
        GlobalProperty *prop = l->data;
1099 1100 1101 1102 1103
        Error *err = NULL;

        if (strcmp(typename, prop->driver) != 0) {
            continue;
        }
1104
        prop->used = true;
P
Paolo Bonzini 已提交
1105
        object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
1106
        if (err != NULL) {
1107 1108
            error_prepend(&err, "can't apply global %s.%s=%s: ",
                          prop->driver, prop->property, prop->value);
1109
            if (!dev->hotplugged && prop->errp) {
1110 1111 1112 1113 1114
                error_propagate(prop->errp, err);
            } else {
                assert(prop->user_provided);
                error_reportf_err(err, "Warning: ");
            }
1115 1116 1117 1118
        }
    }
}

1119
void qdev_prop_set_globals(DeviceState *dev)
1120
{
1121 1122 1123
    ObjectClass *class = object_get_class(OBJECT(dev));

    do {
1124
        qdev_prop_set_globals_for_type(dev, object_class_get_name(class));
1125 1126
        class = object_class_get_parent(class);
    } while (class);
1127
}
1128 1129 1130

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

1131 1132
static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
1133 1134 1135 1136 1137
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);

1138
    visit_type_size(v, name, ptr, errp);
1139 1140
}

1141 1142
static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
1143 1144 1145 1146 1147
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);

1148
    visit_type_size(v, name, ptr, errp);
1149 1150 1151 1152 1153 1154 1155
}

PropertyInfo qdev_prop_size = {
    .name  = "size",
    .get = get_size,
    .set = set_size,
};