qdev-properties-system.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /*
  2. * qdev property parsing and global properties
  3. * (parts specific for qemu-system-*)
  4. *
  5. * This file is based on code from hw/qdev-properties.c from
  6. * commit 074a86fccd185616469dfcdc0e157f438aebba18,
  7. * Copyright (c) Gerd Hoffmann <kraxel@redhat.com> and other contributors.
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  10. * See the COPYING file in the top-level directory.
  11. */
  12. #include "net/net.h"
  13. #include "hw/qdev.h"
  14. #include "qapi/qmp/qerror.h"
  15. #include "sysemu/blockdev.h"
  16. #include "hw/block/block.h"
  17. #include "net/hub.h"
  18. #include "qapi/visitor.h"
  19. #include "char/char.h"
  20. static void get_pointer(Object *obj, Visitor *v, Property *prop,
  21. const char *(*print)(void *ptr),
  22. const char *name, Error **errp)
  23. {
  24. DeviceState *dev = DEVICE(obj);
  25. void **ptr = qdev_get_prop_ptr(dev, prop);
  26. char *p;
  27. p = (char *) (*ptr ? print(*ptr) : "");
  28. visit_type_str(v, &p, name, errp);
  29. }
  30. static void set_pointer(Object *obj, Visitor *v, Property *prop,
  31. int (*parse)(DeviceState *dev, const char *str,
  32. void **ptr),
  33. const char *name, Error **errp)
  34. {
  35. DeviceState *dev = DEVICE(obj);
  36. Error *local_err = NULL;
  37. void **ptr = qdev_get_prop_ptr(dev, prop);
  38. char *str;
  39. int ret;
  40. if (dev->realized) {
  41. qdev_prop_set_after_realize(dev, name, errp);
  42. return;
  43. }
  44. visit_type_str(v, &str, name, &local_err);
  45. if (local_err) {
  46. error_propagate(errp, local_err);
  47. return;
  48. }
  49. if (!*str) {
  50. g_free(str);
  51. *ptr = NULL;
  52. return;
  53. }
  54. ret = parse(dev, str, ptr);
  55. error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
  56. g_free(str);
  57. }
  58. /* --- drive --- */
  59. static int parse_drive(DeviceState *dev, const char *str, void **ptr)
  60. {
  61. BlockDriverState *bs;
  62. bs = bdrv_find(str);
  63. if (bs == NULL) {
  64. return -ENOENT;
  65. }
  66. if (bdrv_attach_dev(bs, dev) < 0) {
  67. return -EEXIST;
  68. }
  69. *ptr = bs;
  70. return 0;
  71. }
  72. static void release_drive(Object *obj, const char *name, void *opaque)
  73. {
  74. DeviceState *dev = DEVICE(obj);
  75. Property *prop = opaque;
  76. BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
  77. if (*ptr) {
  78. bdrv_detach_dev(*ptr, dev);
  79. blockdev_auto_del(*ptr);
  80. }
  81. }
  82. static const char *print_drive(void *ptr)
  83. {
  84. return bdrv_get_device_name(ptr);
  85. }
  86. static void get_drive(Object *obj, Visitor *v, void *opaque,
  87. const char *name, Error **errp)
  88. {
  89. get_pointer(obj, v, opaque, print_drive, name, errp);
  90. }
  91. static void set_drive(Object *obj, Visitor *v, void *opaque,
  92. const char *name, Error **errp)
  93. {
  94. set_pointer(obj, v, opaque, parse_drive, name, errp);
  95. }
  96. PropertyInfo qdev_prop_drive = {
  97. .name = "drive",
  98. .get = get_drive,
  99. .set = set_drive,
  100. .release = release_drive,
  101. };
  102. /* --- character device --- */
  103. static int parse_chr(DeviceState *dev, const char *str, void **ptr)
  104. {
  105. CharDriverState *chr = qemu_chr_find(str);
  106. if (chr == NULL) {
  107. return -ENOENT;
  108. }
  109. if (qemu_chr_fe_claim(chr) != 0) {
  110. return -EEXIST;
  111. }
  112. *ptr = chr;
  113. return 0;
  114. }
  115. static void release_chr(Object *obj, const char *name, void *opaque)
  116. {
  117. DeviceState *dev = DEVICE(obj);
  118. Property *prop = opaque;
  119. CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
  120. CharDriverState *chr = *ptr;
  121. if (chr) {
  122. qemu_chr_add_handlers(chr, NULL, NULL, NULL, NULL);
  123. qemu_chr_fe_release(chr);
  124. }
  125. }
  126. static const char *print_chr(void *ptr)
  127. {
  128. CharDriverState *chr = ptr;
  129. return chr->label ? chr->label : "";
  130. }
  131. static void get_chr(Object *obj, Visitor *v, void *opaque,
  132. const char *name, Error **errp)
  133. {
  134. get_pointer(obj, v, opaque, print_chr, name, errp);
  135. }
  136. static void set_chr(Object *obj, Visitor *v, void *opaque,
  137. const char *name, Error **errp)
  138. {
  139. set_pointer(obj, v, opaque, parse_chr, name, errp);
  140. }
  141. PropertyInfo qdev_prop_chr = {
  142. .name = "chr",
  143. .get = get_chr,
  144. .set = set_chr,
  145. .release = release_chr,
  146. };
  147. /* --- netdev device --- */
  148. static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
  149. {
  150. NICPeers *peers_ptr = (NICPeers *)ptr;
  151. NICConf *conf = container_of(peers_ptr, NICConf, peers);
  152. NetClientState **ncs = peers_ptr->ncs;
  153. NetClientState *peers[MAX_QUEUE_NUM];
  154. int queues, i = 0;
  155. int ret;
  156. queues = qemu_find_net_clients_except(str, peers,
  157. NET_CLIENT_OPTIONS_KIND_NIC,
  158. MAX_QUEUE_NUM);
  159. if (queues == 0) {
  160. ret = -ENOENT;
  161. goto err;
  162. }
  163. if (queues > MAX_QUEUE_NUM) {
  164. ret = -E2BIG;
  165. goto err;
  166. }
  167. for (i = 0; i < queues; i++) {
  168. if (peers[i] == NULL) {
  169. ret = -ENOENT;
  170. goto err;
  171. }
  172. if (peers[i]->peer) {
  173. ret = -EEXIST;
  174. goto err;
  175. }
  176. ncs[i] = peers[i];
  177. ncs[i]->queue_index = i;
  178. }
  179. conf->queues = queues;
  180. return 0;
  181. err:
  182. return ret;
  183. }
  184. static const char *print_netdev(void *ptr)
  185. {
  186. NetClientState *netdev = ptr;
  187. return netdev->name ? netdev->name : "";
  188. }
  189. static void get_netdev(Object *obj, Visitor *v, void *opaque,
  190. const char *name, Error **errp)
  191. {
  192. get_pointer(obj, v, opaque, print_netdev, name, errp);
  193. }
  194. static void set_netdev(Object *obj, Visitor *v, void *opaque,
  195. const char *name, Error **errp)
  196. {
  197. set_pointer(obj, v, opaque, parse_netdev, name, errp);
  198. }
  199. PropertyInfo qdev_prop_netdev = {
  200. .name = "netdev",
  201. .get = get_netdev,
  202. .set = set_netdev,
  203. };
  204. /* --- vlan --- */
  205. static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
  206. {
  207. NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
  208. if (*ptr) {
  209. int id;
  210. if (!net_hub_id_for_client(*ptr, &id)) {
  211. return snprintf(dest, len, "%d", id);
  212. }
  213. }
  214. return snprintf(dest, len, "<null>");
  215. }
  216. static void get_vlan(Object *obj, Visitor *v, void *opaque,
  217. const char *name, Error **errp)
  218. {
  219. DeviceState *dev = DEVICE(obj);
  220. Property *prop = opaque;
  221. NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
  222. int32_t id = -1;
  223. if (*ptr) {
  224. int hub_id;
  225. if (!net_hub_id_for_client(*ptr, &hub_id)) {
  226. id = hub_id;
  227. }
  228. }
  229. visit_type_int32(v, &id, name, errp);
  230. }
  231. static void set_vlan(Object *obj, Visitor *v, void *opaque,
  232. const char *name, Error **errp)
  233. {
  234. DeviceState *dev = DEVICE(obj);
  235. Property *prop = opaque;
  236. NICPeers *peers_ptr = qdev_get_prop_ptr(dev, prop);
  237. NetClientState **ptr = &peers_ptr->ncs[0];
  238. Error *local_err = NULL;
  239. int32_t id;
  240. NetClientState *hubport;
  241. if (dev->realized) {
  242. qdev_prop_set_after_realize(dev, name, errp);
  243. return;
  244. }
  245. visit_type_int32(v, &id, name, &local_err);
  246. if (local_err) {
  247. error_propagate(errp, local_err);
  248. return;
  249. }
  250. if (id == -1) {
  251. *ptr = NULL;
  252. return;
  253. }
  254. hubport = net_hub_port_find(id);
  255. if (!hubport) {
  256. error_set(errp, QERR_INVALID_PARAMETER_VALUE,
  257. name, prop->info->name);
  258. return;
  259. }
  260. *ptr = hubport;
  261. }
  262. PropertyInfo qdev_prop_vlan = {
  263. .name = "vlan",
  264. .print = print_vlan,
  265. .get = get_vlan,
  266. .set = set_vlan,
  267. };
  268. int qdev_prop_set_drive(DeviceState *dev, const char *name,
  269. BlockDriverState *value)
  270. {
  271. Error *errp = NULL;
  272. const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
  273. object_property_set_str(OBJECT(dev), bdrv_name,
  274. name, &errp);
  275. if (errp) {
  276. qerror_report_err(errp);
  277. error_free(errp);
  278. return -1;
  279. }
  280. return 0;
  281. }
  282. void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name,
  283. BlockDriverState *value)
  284. {
  285. if (qdev_prop_set_drive(dev, name, value) < 0) {
  286. exit(1);
  287. }
  288. }
  289. void qdev_prop_set_chr(DeviceState *dev, const char *name,
  290. CharDriverState *value)
  291. {
  292. Error *errp = NULL;
  293. assert(!value || value->label);
  294. object_property_set_str(OBJECT(dev),
  295. value ? value->label : "", name, &errp);
  296. assert_no_error(errp);
  297. }
  298. void qdev_prop_set_netdev(DeviceState *dev, const char *name,
  299. NetClientState *value)
  300. {
  301. Error *errp = NULL;
  302. assert(!value || value->name);
  303. object_property_set_str(OBJECT(dev),
  304. value ? value->name : "", name, &errp);
  305. assert_no_error(errp);
  306. }
  307. void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
  308. {
  309. qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
  310. if (nd->netdev) {
  311. qdev_prop_set_netdev(dev, "netdev", nd->netdev);
  312. }
  313. if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
  314. object_property_find(OBJECT(dev), "vectors", NULL)) {
  315. qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
  316. }
  317. nd->instantiated = 1;
  318. }
  319. static int qdev_add_one_global(QemuOpts *opts, void *opaque)
  320. {
  321. GlobalProperty *g;
  322. g = g_malloc0(sizeof(*g));
  323. g->driver = qemu_opt_get(opts, "driver");
  324. g->property = qemu_opt_get(opts, "property");
  325. g->value = qemu_opt_get(opts, "value");
  326. qdev_prop_register_global(g);
  327. return 0;
  328. }
  329. void qemu_add_globals(void)
  330. {
  331. qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
  332. }