qdev-properties.c 19 KB

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