qdev-properties-system.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  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 "qdev.h"
  14. #include "qapi/qmp/qerror.h"
  15. #include "sysemu/blockdev.h"
  16. #include "hw/block-common.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. error_set(errp, QERR_PERMISSION_DENIED);
  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 (chr->avail_connections < 1) {
  110. return -EEXIST;
  111. }
  112. *ptr = chr;
  113. --chr->avail_connections;
  114. return 0;
  115. }
  116. static void release_chr(Object *obj, const char *name, void *opaque)
  117. {
  118. DeviceState *dev = DEVICE(obj);
  119. Property *prop = opaque;
  120. CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
  121. if (*ptr) {
  122. qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
  123. }
  124. }
  125. static const char *print_chr(void *ptr)
  126. {
  127. CharDriverState *chr = ptr;
  128. return chr->label ? chr->label : "";
  129. }
  130. static void get_chr(Object *obj, Visitor *v, void *opaque,
  131. const char *name, Error **errp)
  132. {
  133. get_pointer(obj, v, opaque, print_chr, name, errp);
  134. }
  135. static void set_chr(Object *obj, Visitor *v, void *opaque,
  136. const char *name, Error **errp)
  137. {
  138. set_pointer(obj, v, opaque, parse_chr, name, errp);
  139. }
  140. PropertyInfo qdev_prop_chr = {
  141. .name = "chr",
  142. .get = get_chr,
  143. .set = set_chr,
  144. .release = release_chr,
  145. };
  146. /* --- netdev device --- */
  147. static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
  148. {
  149. NICPeers *peers_ptr = (NICPeers *)ptr;
  150. NICConf *conf = container_of(peers_ptr, NICConf, peers);
  151. NetClientState **ncs = peers_ptr->ncs;
  152. NetClientState *peers[MAX_QUEUE_NUM];
  153. int queues, i = 0;
  154. int ret;
  155. queues = qemu_find_net_clients_except(str, peers,
  156. NET_CLIENT_OPTIONS_KIND_NIC,
  157. MAX_QUEUE_NUM);
  158. if (queues == 0) {
  159. ret = -ENOENT;
  160. goto err;
  161. }
  162. if (queues > MAX_QUEUE_NUM) {
  163. ret = -E2BIG;
  164. goto err;
  165. }
  166. for (i = 0; i < queues; i++) {
  167. if (peers[i] == NULL) {
  168. ret = -ENOENT;
  169. goto err;
  170. }
  171. if (peers[i]->peer) {
  172. ret = -EEXIST;
  173. goto err;
  174. }
  175. ncs[i] = peers[i];
  176. ncs[i]->queue_index = i;
  177. }
  178. conf->queues = queues;
  179. return 0;
  180. err:
  181. return ret;
  182. }
  183. static const char *print_netdev(void *ptr)
  184. {
  185. NetClientState *netdev = ptr;
  186. return netdev->name ? netdev->name : "";
  187. }
  188. static void get_netdev(Object *obj, Visitor *v, void *opaque,
  189. const char *name, Error **errp)
  190. {
  191. get_pointer(obj, v, opaque, print_netdev, name, errp);
  192. }
  193. static void set_netdev(Object *obj, Visitor *v, void *opaque,
  194. const char *name, Error **errp)
  195. {
  196. set_pointer(obj, v, opaque, parse_netdev, name, errp);
  197. }
  198. PropertyInfo qdev_prop_netdev = {
  199. .name = "netdev",
  200. .get = get_netdev,
  201. .set = set_netdev,
  202. };
  203. /* --- vlan --- */
  204. static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
  205. {
  206. NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
  207. if (*ptr) {
  208. int id;
  209. if (!net_hub_id_for_client(*ptr, &id)) {
  210. return snprintf(dest, len, "%d", id);
  211. }
  212. }
  213. return snprintf(dest, len, "<null>");
  214. }
  215. static void get_vlan(Object *obj, Visitor *v, void *opaque,
  216. const char *name, Error **errp)
  217. {
  218. DeviceState *dev = DEVICE(obj);
  219. Property *prop = opaque;
  220. NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
  221. int32_t id = -1;
  222. if (*ptr) {
  223. int hub_id;
  224. if (!net_hub_id_for_client(*ptr, &hub_id)) {
  225. id = hub_id;
  226. }
  227. }
  228. visit_type_int32(v, &id, name, errp);
  229. }
  230. static void set_vlan(Object *obj, Visitor *v, void *opaque,
  231. const char *name, Error **errp)
  232. {
  233. DeviceState *dev = DEVICE(obj);
  234. Property *prop = opaque;
  235. NICPeers *peers_ptr = qdev_get_prop_ptr(dev, prop);
  236. NetClientState **ptr = &peers_ptr->ncs[0];
  237. Error *local_err = NULL;
  238. int32_t id;
  239. NetClientState *hubport;
  240. if (dev->realized) {
  241. error_set(errp, QERR_PERMISSION_DENIED);
  242. return;
  243. }
  244. visit_type_int32(v, &id, name, &local_err);
  245. if (local_err) {
  246. error_propagate(errp, local_err);
  247. return;
  248. }
  249. if (id == -1) {
  250. *ptr = NULL;
  251. return;
  252. }
  253. hubport = net_hub_port_find(id);
  254. if (!hubport) {
  255. error_set(errp, QERR_INVALID_PARAMETER_VALUE,
  256. name, prop->info->name);
  257. return;
  258. }
  259. *ptr = hubport;
  260. }
  261. PropertyInfo qdev_prop_vlan = {
  262. .name = "vlan",
  263. .print = print_vlan,
  264. .get = get_vlan,
  265. .set = set_vlan,
  266. };
  267. int qdev_prop_set_drive(DeviceState *dev, const char *name,
  268. BlockDriverState *value)
  269. {
  270. Error *errp = NULL;
  271. const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
  272. object_property_set_str(OBJECT(dev), bdrv_name,
  273. name, &errp);
  274. if (errp) {
  275. qerror_report_err(errp);
  276. error_free(errp);
  277. return -1;
  278. }
  279. return 0;
  280. }
  281. void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name,
  282. BlockDriverState *value)
  283. {
  284. if (qdev_prop_set_drive(dev, name, value) < 0) {
  285. exit(1);
  286. }
  287. }
  288. void qdev_prop_set_chr(DeviceState *dev, const char *name,
  289. CharDriverState *value)
  290. {
  291. Error *errp = NULL;
  292. assert(!value || value->label);
  293. object_property_set_str(OBJECT(dev),
  294. value ? value->label : "", name, &errp);
  295. assert_no_error(errp);
  296. }
  297. void qdev_prop_set_netdev(DeviceState *dev, const char *name,
  298. NetClientState *value)
  299. {
  300. Error *errp = NULL;
  301. assert(!value || value->name);
  302. object_property_set_str(OBJECT(dev),
  303. value ? value->name : "", name, &errp);
  304. assert_no_error(errp);
  305. }
  306. void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
  307. {
  308. qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
  309. if (nd->netdev) {
  310. qdev_prop_set_netdev(dev, "netdev", nd->netdev);
  311. }
  312. if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
  313. object_property_find(OBJECT(dev), "vectors", NULL)) {
  314. qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
  315. }
  316. nd->instantiated = 1;
  317. }
  318. static int qdev_add_one_global(QemuOpts *opts, void *opaque)
  319. {
  320. GlobalProperty *g;
  321. g = g_malloc0(sizeof(*g));
  322. g->driver = qemu_opt_get(opts, "driver");
  323. g->property = qemu_opt_get(opts, "property");
  324. g->value = qemu_opt_get(opts, "value");
  325. qdev_prop_register_global(g);
  326. return 0;
  327. }
  328. void qemu_add_globals(void)
  329. {
  330. qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
  331. }