|
|
1.1.1.2 ! root 1: #include "sysemu.h" ! 2: #include "net.h" 1.1 root 3: #include "qdev.h" 4: 5: void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) 6: { 7: void *ptr = dev; 8: ptr += prop->offset; 9: return ptr; 10: } 11: 1.1.1.2 ! root 12: /* --- 8bit integer --- */ ! 13: ! 14: static int parse_uint8(DeviceState *dev, Property *prop, const char *str) ! 15: { ! 16: uint8_t *ptr = qdev_get_prop_ptr(dev, prop); ! 17: const char *fmt; ! 18: ! 19: /* accept both hex and decimal */ ! 20: fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx8 : "%" PRIu8; ! 21: if (sscanf(str, fmt, ptr) != 1) ! 22: return -1; ! 23: return 0; ! 24: } ! 25: ! 26: static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len) ! 27: { ! 28: uint8_t *ptr = qdev_get_prop_ptr(dev, prop); ! 29: return snprintf(dest, len, "%" PRIu8, *ptr); ! 30: } ! 31: ! 32: PropertyInfo qdev_prop_uint8 = { ! 33: .name = "uint8", ! 34: .type = PROP_TYPE_UINT8, ! 35: .size = sizeof(uint8_t), ! 36: .parse = parse_uint8, ! 37: .print = print_uint8, ! 38: }; ! 39: 1.1 root 40: /* --- 16bit integer --- */ 41: 42: static int parse_uint16(DeviceState *dev, Property *prop, const char *str) 43: { 44: uint16_t *ptr = qdev_get_prop_ptr(dev, prop); 45: const char *fmt; 46: 47: /* accept both hex and decimal */ 48: fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx16 : "%" PRIu16; 49: if (sscanf(str, fmt, ptr) != 1) 50: return -1; 51: return 0; 52: } 53: 54: static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len) 55: { 56: uint16_t *ptr = qdev_get_prop_ptr(dev, prop); 57: return snprintf(dest, len, "%" PRIu16, *ptr); 58: } 59: 60: PropertyInfo qdev_prop_uint16 = { 61: .name = "uint16", 62: .type = PROP_TYPE_UINT16, 63: .size = sizeof(uint16_t), 64: .parse = parse_uint16, 65: .print = print_uint16, 66: }; 67: 68: /* --- 32bit integer --- */ 69: 70: static int parse_uint32(DeviceState *dev, Property *prop, const char *str) 71: { 72: uint32_t *ptr = qdev_get_prop_ptr(dev, prop); 73: const char *fmt; 74: 75: /* accept both hex and decimal */ 76: fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx32 : "%" PRIu32; 77: if (sscanf(str, fmt, ptr) != 1) 78: return -1; 79: return 0; 80: } 81: 82: static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len) 83: { 84: uint32_t *ptr = qdev_get_prop_ptr(dev, prop); 85: return snprintf(dest, len, "%" PRIu32, *ptr); 86: } 87: 88: PropertyInfo qdev_prop_uint32 = { 89: .name = "uint32", 90: .type = PROP_TYPE_UINT32, 91: .size = sizeof(uint32_t), 92: .parse = parse_uint32, 93: .print = print_uint32, 94: }; 95: 1.1.1.2 ! root 96: static int parse_int32(DeviceState *dev, Property *prop, const char *str) ! 97: { ! 98: int32_t *ptr = qdev_get_prop_ptr(dev, prop); ! 99: ! 100: if (sscanf(str, "%" PRId32, ptr) != 1) ! 101: return -1; ! 102: return 0; ! 103: } ! 104: ! 105: static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len) ! 106: { ! 107: int32_t *ptr = qdev_get_prop_ptr(dev, prop); ! 108: return snprintf(dest, len, "%" PRId32, *ptr); ! 109: } ! 110: ! 111: PropertyInfo qdev_prop_int32 = { ! 112: .name = "int32", ! 113: .type = PROP_TYPE_INT32, ! 114: .size = sizeof(int32_t), ! 115: .parse = parse_int32, ! 116: .print = print_int32, ! 117: }; ! 118: 1.1 root 119: /* --- 32bit hex value --- */ 120: 121: static int parse_hex32(DeviceState *dev, Property *prop, const char *str) 122: { 123: uint32_t *ptr = qdev_get_prop_ptr(dev, prop); 124: 125: if (sscanf(str, "%" PRIx32, ptr) != 1) 126: return -1; 127: return 0; 128: } 129: 130: static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len) 131: { 132: uint32_t *ptr = qdev_get_prop_ptr(dev, prop); 133: return snprintf(dest, len, "0x%" PRIx32, *ptr); 134: } 135: 136: PropertyInfo qdev_prop_hex32 = { 137: .name = "hex32", 138: .type = PROP_TYPE_UINT32, 139: .size = sizeof(uint32_t), 140: .parse = parse_hex32, 141: .print = print_hex32, 142: }; 143: 1.1.1.2 ! root 144: /* --- 64bit integer --- */ ! 145: ! 146: static int parse_uint64(DeviceState *dev, Property *prop, const char *str) ! 147: { ! 148: uint64_t *ptr = qdev_get_prop_ptr(dev, prop); ! 149: const char *fmt; ! 150: ! 151: /* accept both hex and decimal */ ! 152: fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx64 : "%" PRIu64; ! 153: if (sscanf(str, fmt, ptr) != 1) ! 154: return -1; ! 155: return 0; ! 156: } ! 157: ! 158: static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len) ! 159: { ! 160: uint64_t *ptr = qdev_get_prop_ptr(dev, prop); ! 161: return snprintf(dest, len, "%" PRIu64, *ptr); ! 162: } ! 163: ! 164: PropertyInfo qdev_prop_uint64 = { ! 165: .name = "uint64", ! 166: .type = PROP_TYPE_UINT64, ! 167: .size = sizeof(uint64_t), ! 168: .parse = parse_uint64, ! 169: .print = print_uint64, ! 170: }; ! 171: ! 172: /* --- 64bit hex value --- */ ! 173: ! 174: static int parse_hex64(DeviceState *dev, Property *prop, const char *str) ! 175: { ! 176: uint64_t *ptr = qdev_get_prop_ptr(dev, prop); ! 177: ! 178: if (sscanf(str, "%" PRIx64, ptr) != 1) ! 179: return -1; ! 180: return 0; ! 181: } ! 182: ! 183: static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len) ! 184: { ! 185: uint64_t *ptr = qdev_get_prop_ptr(dev, prop); ! 186: return snprintf(dest, len, "0x%" PRIx64, *ptr); ! 187: } ! 188: ! 189: PropertyInfo qdev_prop_hex64 = { ! 190: .name = "hex64", ! 191: .type = PROP_TYPE_UINT64, ! 192: .size = sizeof(uint64_t), ! 193: .parse = parse_hex64, ! 194: .print = print_hex64, ! 195: }; ! 196: ! 197: /* --- string --- */ ! 198: ! 199: static int parse_string(DeviceState *dev, Property *prop, const char *str) ! 200: { ! 201: char **ptr = qdev_get_prop_ptr(dev, prop); ! 202: ! 203: if (*ptr) ! 204: qemu_free(*ptr); ! 205: *ptr = qemu_strdup(str); ! 206: return 0; ! 207: } ! 208: ! 209: static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len) ! 210: { ! 211: char **ptr = qdev_get_prop_ptr(dev, prop); ! 212: if (!*ptr) ! 213: return snprintf(dest, len, "<null>"); ! 214: return snprintf(dest, len, "\"%s\"", *ptr); ! 215: } ! 216: ! 217: PropertyInfo qdev_prop_string = { ! 218: .name = "string", ! 219: .type = PROP_TYPE_STRING, ! 220: .size = sizeof(char*), ! 221: .parse = parse_string, ! 222: .print = print_string, ! 223: }; ! 224: ! 225: /* --- drive --- */ ! 226: ! 227: static int parse_drive(DeviceState *dev, Property *prop, const char *str) ! 228: { ! 229: DriveInfo **ptr = qdev_get_prop_ptr(dev, prop); ! 230: ! 231: *ptr = drive_get_by_id(str); ! 232: if (*ptr == NULL) ! 233: return -1; ! 234: return 0; ! 235: } ! 236: ! 237: static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len) ! 238: { ! 239: DriveInfo **ptr = qdev_get_prop_ptr(dev, prop); ! 240: return snprintf(dest, len, "%s", (*ptr) ? (*ptr)->id : "<null>"); ! 241: } ! 242: ! 243: PropertyInfo qdev_prop_drive = { ! 244: .name = "drive", ! 245: .type = PROP_TYPE_DRIVE, ! 246: .size = sizeof(DriveInfo*), ! 247: .parse = parse_drive, ! 248: .print = print_drive, ! 249: }; ! 250: ! 251: /* --- character device --- */ ! 252: ! 253: static int parse_chr(DeviceState *dev, Property *prop, const char *str) ! 254: { ! 255: CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); ! 256: ! 257: *ptr = qemu_chr_find(str); ! 258: if (*ptr == NULL) ! 259: return -1; ! 260: return 0; ! 261: } ! 262: ! 263: static int print_chr(DeviceState *dev, Property *prop, char *dest, size_t len) ! 264: { ! 265: CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); ! 266: ! 267: if (*ptr && (*ptr)->label) { ! 268: return snprintf(dest, len, "%s", (*ptr)->label); ! 269: } else { ! 270: return snprintf(dest, len, "<null>"); ! 271: } ! 272: } ! 273: ! 274: PropertyInfo qdev_prop_chr = { ! 275: .name = "chr", ! 276: .type = PROP_TYPE_CHR, ! 277: .size = sizeof(CharDriverState*), ! 278: .parse = parse_chr, ! 279: .print = print_chr, ! 280: }; ! 281: ! 282: /* --- netdev device --- */ ! 283: ! 284: static int parse_netdev(DeviceState *dev, Property *prop, const char *str) ! 285: { ! 286: VLANClientState **ptr = qdev_get_prop_ptr(dev, prop); ! 287: ! 288: *ptr = qemu_find_netdev(str); ! 289: if (*ptr == NULL) ! 290: return -1; ! 291: return 0; ! 292: } ! 293: ! 294: static int print_netdev(DeviceState *dev, Property *prop, char *dest, size_t len) ! 295: { ! 296: VLANClientState **ptr = qdev_get_prop_ptr(dev, prop); ! 297: ! 298: if (*ptr && (*ptr)->name) { ! 299: return snprintf(dest, len, "%s", (*ptr)->name); ! 300: } else { ! 301: return snprintf(dest, len, "<null>"); ! 302: } ! 303: } ! 304: ! 305: PropertyInfo qdev_prop_netdev = { ! 306: .name = "netdev", ! 307: .type = PROP_TYPE_NETDEV, ! 308: .size = sizeof(VLANClientState*), ! 309: .parse = parse_netdev, ! 310: .print = print_netdev, ! 311: }; ! 312: ! 313: /* --- vlan --- */ ! 314: ! 315: static int parse_vlan(DeviceState *dev, Property *prop, const char *str) ! 316: { ! 317: VLANState **ptr = qdev_get_prop_ptr(dev, prop); ! 318: int id; ! 319: ! 320: if (sscanf(str, "%d", &id) != 1) ! 321: return -1; ! 322: *ptr = qemu_find_vlan(id, 1); ! 323: if (*ptr == NULL) ! 324: return -1; ! 325: return 0; ! 326: } ! 327: ! 328: static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len) ! 329: { ! 330: VLANState **ptr = qdev_get_prop_ptr(dev, prop); ! 331: ! 332: if (*ptr) { ! 333: return snprintf(dest, len, "%d", (*ptr)->id); ! 334: } else { ! 335: return snprintf(dest, len, "<null>"); ! 336: } ! 337: } ! 338: ! 339: PropertyInfo qdev_prop_vlan = { ! 340: .name = "vlan", ! 341: .type = PROP_TYPE_VLAN, ! 342: .size = sizeof(VLANClientState*), ! 343: .parse = parse_vlan, ! 344: .print = print_vlan, ! 345: }; ! 346: 1.1 root 347: /* --- pointer --- */ 348: 349: static int print_ptr(DeviceState *dev, Property *prop, char *dest, size_t len) 350: { 351: void **ptr = qdev_get_prop_ptr(dev, prop); 352: return snprintf(dest, len, "<%p>", *ptr); 353: } 354: 355: PropertyInfo qdev_prop_ptr = { 356: .name = "ptr", 357: .type = PROP_TYPE_PTR, 358: .size = sizeof(void*), 359: .print = print_ptr, 360: }; 361: 362: /* --- mac address --- */ 363: 364: /* 365: * accepted syntax versions: 366: * 01:02:03:04:05:06 367: * 01-02-03-04-05-06 368: */ 369: static int parse_mac(DeviceState *dev, Property *prop, const char *str) 370: { 1.1.1.2 ! root 371: MACAddr *mac = qdev_get_prop_ptr(dev, prop); 1.1 root 372: int i, pos; 373: char *p; 374: 375: for (i = 0, pos = 0; i < 6; i++, pos += 3) { 376: if (!qemu_isxdigit(str[pos])) 377: return -1; 378: if (!qemu_isxdigit(str[pos+1])) 379: return -1; 1.1.1.2 ! root 380: if (i == 5) { ! 381: if (str[pos+2] != '\0') ! 382: return -1; ! 383: } else { ! 384: if (str[pos+2] != ':' && str[pos+2] != '-') ! 385: return -1; ! 386: } ! 387: mac->a[i] = strtol(str+pos, &p, 16); 1.1 root 388: } 389: return 0; 390: } 391: 392: static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len) 393: { 1.1.1.2 ! root 394: MACAddr *mac = qdev_get_prop_ptr(dev, prop); ! 395: 1.1 root 396: return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x", 1.1.1.2 ! root 397: mac->a[0], mac->a[1], mac->a[2], ! 398: mac->a[3], mac->a[4], mac->a[5]); 1.1 root 399: } 400: 401: PropertyInfo qdev_prop_macaddr = { 1.1.1.2 ! root 402: .name = "macaddr", 1.1 root 403: .type = PROP_TYPE_MACADDR, 1.1.1.2 ! root 404: .size = sizeof(MACAddr), 1.1 root 405: .parse = parse_mac, 406: .print = print_mac, 407: }; 408: 1.1.1.2 ! root 409: /* --- pci address --- */ ! 410: ! 411: /* ! 412: * bus-local address, i.e. "$slot" or "$slot.$fn" ! 413: */ ! 414: static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str) ! 415: { ! 416: uint32_t *ptr = qdev_get_prop_ptr(dev, prop); ! 417: unsigned int slot, fn, n; ! 418: ! 419: if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) { ! 420: fn = 0; ! 421: if (sscanf(str, "%x%n", &slot, &n) != 1) { ! 422: return -1; ! 423: } ! 424: } ! 425: if (str[n] != '\0') ! 426: return -1; ! 427: if (fn > 7) ! 428: return -1; ! 429: *ptr = slot << 3 | fn; ! 430: return 0; ! 431: } ! 432: ! 433: static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len) ! 434: { ! 435: uint32_t *ptr = qdev_get_prop_ptr(dev, prop); ! 436: ! 437: if (*ptr == -1) { ! 438: return snprintf(dest, len, "<unset>"); ! 439: } else { ! 440: return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7); ! 441: } ! 442: } ! 443: ! 444: PropertyInfo qdev_prop_pci_devfn = { ! 445: .name = "pci-devfn", ! 446: .type = PROP_TYPE_UINT32, ! 447: .size = sizeof(uint32_t), ! 448: .parse = parse_pci_devfn, ! 449: .print = print_pci_devfn, ! 450: }; ! 451: 1.1 root 452: /* --- public helpers --- */ 453: 454: static Property *qdev_prop_walk(Property *props, const char *name) 455: { 456: if (!props) 457: return NULL; 458: while (props->name) { 459: if (strcmp(props->name, name) == 0) 460: return props; 461: props++; 462: } 463: return NULL; 464: } 465: 466: static Property *qdev_prop_find(DeviceState *dev, const char *name) 467: { 468: Property *prop; 469: 470: /* device properties */ 471: prop = qdev_prop_walk(dev->info->props, name); 472: if (prop) 473: return prop; 474: 475: /* bus properties */ 476: prop = qdev_prop_walk(dev->parent_bus->info->props, name); 477: if (prop) 478: return prop; 479: 480: return NULL; 481: } 482: 1.1.1.2 ! root 483: int qdev_prop_exists(DeviceState *dev, const char *name) ! 484: { ! 485: return qdev_prop_find(dev, name) ? true : false; ! 486: } ! 487: 1.1 root 488: int qdev_prop_parse(DeviceState *dev, const char *name, const char *value) 489: { 490: Property *prop; 491: 492: prop = qdev_prop_find(dev, name); 493: if (!prop) { 494: fprintf(stderr, "property \"%s.%s\" not found\n", 495: dev->info->name, name); 496: return -1; 497: } 498: if (!prop->info->parse) { 499: fprintf(stderr, "property \"%s.%s\" has no parser\n", 500: dev->info->name, name); 501: return -1; 502: } 1.1.1.2 ! root 503: if (prop->info->parse(dev, prop, value) != 0) { ! 504: fprintf(stderr, "property \"%s.%s\": failed to parse \"%s\"\n", ! 505: dev->info->name, name, value); ! 506: return -1; ! 507: } ! 508: return 0; 1.1 root 509: } 510: 511: void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type) 512: { 513: Property *prop; 514: void *dst; 515: 516: prop = qdev_prop_find(dev, name); 517: if (!prop) { 518: fprintf(stderr, "%s: property \"%s.%s\" not found\n", 519: __FUNCTION__, dev->info->name, name); 520: abort(); 521: } 522: if (prop->info->type != type) { 523: fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n", 524: __FUNCTION__, dev->info->name, name); 525: abort(); 526: } 527: dst = qdev_get_prop_ptr(dev, prop); 528: memcpy(dst, src, prop->info->size); 529: } 530: 1.1.1.2 ! root 531: void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value) ! 532: { ! 533: qdev_prop_set(dev, name, &value, PROP_TYPE_UINT8); ! 534: } ! 535: 1.1 root 536: void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value) 537: { 538: qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16); 539: } 540: 541: void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value) 542: { 543: qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32); 544: } 545: 1.1.1.2 ! root 546: void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value) ! 547: { ! 548: qdev_prop_set(dev, name, &value, PROP_TYPE_INT32); ! 549: } ! 550: ! 551: void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value) ! 552: { ! 553: qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64); ! 554: } ! 555: ! 556: void qdev_prop_set_drive(DeviceState *dev, const char *name, DriveInfo *value) ! 557: { ! 558: qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE); ! 559: } ! 560: ! 561: void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value) ! 562: { ! 563: qdev_prop_set(dev, name, &value, PROP_TYPE_CHR); ! 564: } ! 565: ! 566: void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value) ! 567: { ! 568: qdev_prop_set(dev, name, &value, PROP_TYPE_NETDEV); ! 569: } ! 570: ! 571: void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value) ! 572: { ! 573: qdev_prop_set(dev, name, &value, PROP_TYPE_VLAN); ! 574: } ! 575: ! 576: void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value) ! 577: { ! 578: qdev_prop_set(dev, name, value, PROP_TYPE_MACADDR); ! 579: } ! 580: 1.1 root 581: void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value) 582: { 583: qdev_prop_set(dev, name, &value, PROP_TYPE_PTR); 584: } 585: 586: void qdev_prop_set_defaults(DeviceState *dev, Property *props) 587: { 588: char *dst; 589: 590: if (!props) 591: return; 592: while (props->name) { 593: if (props->defval) { 594: dst = qdev_get_prop_ptr(dev, props); 595: memcpy(dst, props->defval, props->info->size); 596: } 597: props++; 598: } 599: } 600: 1.1.1.2 ! root 601: static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props); 1.1 root 602: 1.1.1.2 ! root 603: void qdev_prop_register_global(GlobalProperty *prop) 1.1 root 604: { 1.1.1.2 ! root 605: QTAILQ_INSERT_TAIL(&global_props, prop, next); 1.1 root 606: } 607: 1.1.1.2 ! root 608: void qdev_prop_register_global_list(GlobalProperty *props) 1.1 root 609: { 1.1.1.2 ! root 610: int i; 1.1 root 611: 1.1.1.2 ! root 612: for (i = 0; props[i].driver != NULL; i++) { ! 613: qdev_prop_register_global(props+i); 1.1 root 614: } 1.1.1.2 ! root 615: } ! 616: ! 617: void qdev_prop_set_globals(DeviceState *dev) ! 618: { ! 619: GlobalProperty *prop; ! 620: ! 621: QTAILQ_FOREACH(prop, &global_props, next) { ! 622: if (strcmp(dev->info->name, prop->driver) != 0 && ! 623: strcmp(dev->info->bus_info->name, prop->driver) != 0) { 1.1 root 624: continue; 625: } 626: if (qdev_prop_parse(dev, prop->property, prop->value) != 0) { 1.1.1.2 ! root 627: exit(1); 1.1 root 628: } 629: } 630: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.