qdev-properties.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  1. #include "qemu/osdep.h"
  2. #include "hw/qdev-properties.h"
  3. #include "qapi/error.h"
  4. #include "qapi/qapi-types-misc.h"
  5. #include "qobject/qlist.h"
  6. #include "qemu/ctype.h"
  7. #include "qemu/error-report.h"
  8. #include "qapi/visitor.h"
  9. #include "qemu/units.h"
  10. #include "qemu/cutils.h"
  11. #include "qdev-prop-internal.h"
  12. #include "qom/qom-qobject.h"
  13. void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
  14. Error **errp)
  15. {
  16. if (dev->id) {
  17. error_setg(errp, "Attempt to set property '%s' on device '%s' "
  18. "(type '%s') after it was realized", name, dev->id,
  19. object_get_typename(OBJECT(dev)));
  20. } else {
  21. error_setg(errp, "Attempt to set property '%s' on anonymous device "
  22. "(type '%s') after it was realized", name,
  23. object_get_typename(OBJECT(dev)));
  24. }
  25. }
  26. /* returns: true if property is allowed to be set, false otherwise */
  27. static bool qdev_prop_allow_set(Object *obj, const char *name,
  28. const PropertyInfo *info, Error **errp)
  29. {
  30. DeviceState *dev = DEVICE(obj);
  31. if (dev->realized && !info->realized_set_allowed) {
  32. qdev_prop_set_after_realize(dev, name, errp);
  33. return false;
  34. }
  35. return true;
  36. }
  37. void qdev_prop_allow_set_link_before_realize(const Object *obj,
  38. const char *name,
  39. Object *val, Error **errp)
  40. {
  41. DeviceState *dev = DEVICE(obj);
  42. if (dev->realized) {
  43. error_setg(errp, "Attempt to set link property '%s' on device '%s' "
  44. "(type '%s') after it was realized",
  45. name, dev->id, object_get_typename(obj));
  46. }
  47. }
  48. void *object_field_prop_ptr(Object *obj, const Property *prop)
  49. {
  50. void *ptr = obj;
  51. ptr += prop->offset;
  52. return ptr;
  53. }
  54. static void field_prop_get(Object *obj, Visitor *v, const char *name,
  55. void *opaque, Error **errp)
  56. {
  57. const Property *prop = opaque;
  58. return prop->info->get(obj, v, name, opaque, errp);
  59. }
  60. /**
  61. * field_prop_getter: Return getter function to be used for property
  62. *
  63. * Return value can be NULL if @info has no getter function.
  64. */
  65. static ObjectPropertyAccessor *field_prop_getter(const PropertyInfo *info)
  66. {
  67. return info->get ? field_prop_get : NULL;
  68. }
  69. static void field_prop_set(Object *obj, Visitor *v, const char *name,
  70. void *opaque, Error **errp)
  71. {
  72. const Property *prop = opaque;
  73. if (!qdev_prop_allow_set(obj, name, prop->info, errp)) {
  74. return;
  75. }
  76. return prop->info->set(obj, v, name, opaque, errp);
  77. }
  78. /**
  79. * field_prop_setter: Return setter function to be used for property
  80. *
  81. * Return value can be NULL if @info has not setter function.
  82. */
  83. static ObjectPropertyAccessor *field_prop_setter(const PropertyInfo *info)
  84. {
  85. return info->set ? field_prop_set : NULL;
  86. }
  87. void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name,
  88. void *opaque, Error **errp)
  89. {
  90. const Property *prop = opaque;
  91. int *ptr = object_field_prop_ptr(obj, prop);
  92. visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
  93. }
  94. void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name,
  95. void *opaque, Error **errp)
  96. {
  97. const Property *prop = opaque;
  98. int *ptr = object_field_prop_ptr(obj, prop);
  99. visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
  100. }
  101. void qdev_propinfo_set_default_value_enum(ObjectProperty *op,
  102. const Property *prop)
  103. {
  104. object_property_set_default_str(op,
  105. qapi_enum_lookup(prop->info->enum_table, prop->defval.i));
  106. }
  107. /* Bit */
  108. static uint32_t qdev_get_prop_mask(const Property *prop)
  109. {
  110. assert(prop->info == &qdev_prop_bit);
  111. return 0x1 << prop->bitnr;
  112. }
  113. static void bit_prop_set(Object *obj, const Property *props, bool val)
  114. {
  115. uint32_t *p = object_field_prop_ptr(obj, props);
  116. uint32_t mask = qdev_get_prop_mask(props);
  117. if (val) {
  118. *p |= mask;
  119. } else {
  120. *p &= ~mask;
  121. }
  122. }
  123. static void prop_get_bit(Object *obj, Visitor *v, const char *name,
  124. void *opaque, Error **errp)
  125. {
  126. const Property *prop = opaque;
  127. uint32_t *p = object_field_prop_ptr(obj, prop);
  128. bool value = (*p & qdev_get_prop_mask(prop)) != 0;
  129. visit_type_bool(v, name, &value, errp);
  130. }
  131. static void prop_set_bit(Object *obj, Visitor *v, const char *name,
  132. void *opaque, Error **errp)
  133. {
  134. const Property *prop = opaque;
  135. bool value;
  136. if (!visit_type_bool(v, name, &value, errp)) {
  137. return;
  138. }
  139. bit_prop_set(obj, prop, value);
  140. }
  141. static void set_default_value_bool(ObjectProperty *op, const Property *prop)
  142. {
  143. object_property_set_default_bool(op, prop->defval.u);
  144. }
  145. const PropertyInfo qdev_prop_bit = {
  146. .type = "bool",
  147. .description = "on/off",
  148. .get = prop_get_bit,
  149. .set = prop_set_bit,
  150. .set_default_value = set_default_value_bool,
  151. };
  152. /* Bit64 */
  153. static uint64_t qdev_get_prop_mask64(const Property *prop)
  154. {
  155. assert(prop->info == &qdev_prop_bit64);
  156. return 0x1ull << prop->bitnr;
  157. }
  158. static void bit64_prop_set(Object *obj, const Property *props, bool val)
  159. {
  160. uint64_t *p = object_field_prop_ptr(obj, props);
  161. uint64_t mask = qdev_get_prop_mask64(props);
  162. if (val) {
  163. *p |= mask;
  164. } else {
  165. *p &= ~mask;
  166. }
  167. }
  168. static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
  169. void *opaque, Error **errp)
  170. {
  171. const Property *prop = opaque;
  172. uint64_t *p = object_field_prop_ptr(obj, prop);
  173. bool value = (*p & qdev_get_prop_mask64(prop)) != 0;
  174. visit_type_bool(v, name, &value, errp);
  175. }
  176. static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
  177. void *opaque, Error **errp)
  178. {
  179. const Property *prop = opaque;
  180. bool value;
  181. if (!visit_type_bool(v, name, &value, errp)) {
  182. return;
  183. }
  184. bit64_prop_set(obj, prop, value);
  185. }
  186. const PropertyInfo qdev_prop_bit64 = {
  187. .type = "bool",
  188. .description = "on/off",
  189. .get = prop_get_bit64,
  190. .set = prop_set_bit64,
  191. .set_default_value = set_default_value_bool,
  192. };
  193. /* --- bool --- */
  194. static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,
  195. Error **errp)
  196. {
  197. const Property *prop = opaque;
  198. bool *ptr = object_field_prop_ptr(obj, prop);
  199. visit_type_bool(v, name, ptr, errp);
  200. }
  201. static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
  202. Error **errp)
  203. {
  204. const Property *prop = opaque;
  205. bool *ptr = object_field_prop_ptr(obj, prop);
  206. visit_type_bool(v, name, ptr, errp);
  207. }
  208. const PropertyInfo qdev_prop_bool = {
  209. .type = "bool",
  210. .description = "on/off",
  211. .get = get_bool,
  212. .set = set_bool,
  213. .set_default_value = set_default_value_bool,
  214. };
  215. /* --- 8bit integer --- */
  216. static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
  217. Error **errp)
  218. {
  219. const Property *prop = opaque;
  220. uint8_t *ptr = object_field_prop_ptr(obj, prop);
  221. visit_type_uint8(v, name, ptr, errp);
  222. }
  223. static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
  224. Error **errp)
  225. {
  226. const Property *prop = opaque;
  227. uint8_t *ptr = object_field_prop_ptr(obj, prop);
  228. visit_type_uint8(v, name, ptr, errp);
  229. }
  230. void qdev_propinfo_set_default_value_int(ObjectProperty *op,
  231. const Property *prop)
  232. {
  233. object_property_set_default_int(op, prop->defval.i);
  234. }
  235. void qdev_propinfo_set_default_value_uint(ObjectProperty *op,
  236. const Property *prop)
  237. {
  238. object_property_set_default_uint(op, prop->defval.u);
  239. }
  240. const PropertyInfo qdev_prop_uint8 = {
  241. .type = "uint8",
  242. .get = get_uint8,
  243. .set = set_uint8,
  244. .set_default_value = qdev_propinfo_set_default_value_uint,
  245. };
  246. /* --- 16bit integer --- */
  247. static void get_uint16(Object *obj, Visitor *v, const char *name,
  248. void *opaque, Error **errp)
  249. {
  250. const Property *prop = opaque;
  251. uint16_t *ptr = object_field_prop_ptr(obj, prop);
  252. visit_type_uint16(v, name, ptr, errp);
  253. }
  254. static void set_uint16(Object *obj, Visitor *v, const char *name,
  255. void *opaque, Error **errp)
  256. {
  257. const Property *prop = opaque;
  258. uint16_t *ptr = object_field_prop_ptr(obj, prop);
  259. visit_type_uint16(v, name, ptr, errp);
  260. }
  261. const PropertyInfo qdev_prop_uint16 = {
  262. .type = "uint16",
  263. .get = get_uint16,
  264. .set = set_uint16,
  265. .set_default_value = qdev_propinfo_set_default_value_uint,
  266. };
  267. /* --- 32bit integer --- */
  268. static void get_uint32(Object *obj, Visitor *v, const char *name,
  269. void *opaque, Error **errp)
  270. {
  271. const Property *prop = opaque;
  272. uint32_t *ptr = object_field_prop_ptr(obj, prop);
  273. visit_type_uint32(v, name, ptr, errp);
  274. }
  275. static void set_uint32(Object *obj, Visitor *v, const char *name,
  276. void *opaque, Error **errp)
  277. {
  278. const Property *prop = opaque;
  279. uint32_t *ptr = object_field_prop_ptr(obj, prop);
  280. visit_type_uint32(v, name, ptr, errp);
  281. }
  282. void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name,
  283. void *opaque, Error **errp)
  284. {
  285. const Property *prop = opaque;
  286. int32_t *ptr = object_field_prop_ptr(obj, prop);
  287. visit_type_int32(v, name, ptr, errp);
  288. }
  289. static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
  290. Error **errp)
  291. {
  292. const Property *prop = opaque;
  293. int32_t *ptr = object_field_prop_ptr(obj, prop);
  294. visit_type_int32(v, name, ptr, errp);
  295. }
  296. const PropertyInfo qdev_prop_uint32 = {
  297. .type = "uint32",
  298. .get = get_uint32,
  299. .set = set_uint32,
  300. .set_default_value = qdev_propinfo_set_default_value_uint,
  301. };
  302. const PropertyInfo qdev_prop_int32 = {
  303. .type = "int32",
  304. .get = qdev_propinfo_get_int32,
  305. .set = set_int32,
  306. .set_default_value = qdev_propinfo_set_default_value_int,
  307. };
  308. /* --- 64bit integer --- */
  309. static void get_uint64(Object *obj, Visitor *v, const char *name,
  310. void *opaque, Error **errp)
  311. {
  312. const Property *prop = opaque;
  313. uint64_t *ptr = object_field_prop_ptr(obj, prop);
  314. visit_type_uint64(v, name, ptr, errp);
  315. }
  316. static void set_uint64(Object *obj, Visitor *v, const char *name,
  317. void *opaque, Error **errp)
  318. {
  319. const Property *prop = opaque;
  320. uint64_t *ptr = object_field_prop_ptr(obj, prop);
  321. visit_type_uint64(v, name, ptr, errp);
  322. }
  323. static void get_int64(Object *obj, Visitor *v, const char *name,
  324. void *opaque, Error **errp)
  325. {
  326. const Property *prop = opaque;
  327. int64_t *ptr = object_field_prop_ptr(obj, prop);
  328. visit_type_int64(v, name, ptr, errp);
  329. }
  330. static void set_int64(Object *obj, Visitor *v, const char *name,
  331. void *opaque, Error **errp)
  332. {
  333. const Property *prop = opaque;
  334. int64_t *ptr = object_field_prop_ptr(obj, prop);
  335. visit_type_int64(v, name, ptr, errp);
  336. }
  337. const PropertyInfo qdev_prop_uint64 = {
  338. .type = "uint64",
  339. .get = get_uint64,
  340. .set = set_uint64,
  341. .set_default_value = qdev_propinfo_set_default_value_uint,
  342. };
  343. const PropertyInfo qdev_prop_int64 = {
  344. .type = "int64",
  345. .get = get_int64,
  346. .set = set_int64,
  347. .set_default_value = qdev_propinfo_set_default_value_int,
  348. };
  349. static void set_uint64_checkmask(Object *obj, Visitor *v, const char *name,
  350. void *opaque, Error **errp)
  351. {
  352. const Property *prop = opaque;
  353. uint64_t *ptr = object_field_prop_ptr(obj, prop);
  354. visit_type_uint64(v, name, ptr, errp);
  355. if (*ptr & ~prop->bitmask) {
  356. error_setg(errp, "Property value for '%s' has bits outside mask '0x%" PRIx64 "'",
  357. name, prop->bitmask);
  358. }
  359. }
  360. const PropertyInfo qdev_prop_uint64_checkmask = {
  361. .type = "uint64",
  362. .get = get_uint64,
  363. .set = set_uint64_checkmask,
  364. };
  365. /* --- pointer-size integer --- */
  366. static void get_usize(Object *obj, Visitor *v, const char *name, void *opaque,
  367. Error **errp)
  368. {
  369. const Property *prop = opaque;
  370. #if HOST_LONG_BITS == 32
  371. uint32_t *ptr = object_field_prop_ptr(obj, prop);
  372. visit_type_uint32(v, name, ptr, errp);
  373. #else
  374. uint64_t *ptr = object_field_prop_ptr(obj, prop);
  375. visit_type_uint64(v, name, ptr, errp);
  376. #endif
  377. }
  378. static void set_usize(Object *obj, Visitor *v, const char *name, void *opaque,
  379. Error **errp)
  380. {
  381. const Property *prop = opaque;
  382. #if HOST_LONG_BITS == 32
  383. uint32_t *ptr = object_field_prop_ptr(obj, prop);
  384. visit_type_uint32(v, name, ptr, errp);
  385. #else
  386. uint64_t *ptr = object_field_prop_ptr(obj, prop);
  387. visit_type_uint64(v, name, ptr, errp);
  388. #endif
  389. }
  390. const PropertyInfo qdev_prop_usize = {
  391. .type = "usize",
  392. .get = get_usize,
  393. .set = set_usize,
  394. .set_default_value = qdev_propinfo_set_default_value_uint,
  395. };
  396. /* --- string --- */
  397. static void release_string(Object *obj, const char *name, void *opaque)
  398. {
  399. const Property *prop = opaque;
  400. g_free(*(char **)object_field_prop_ptr(obj, prop));
  401. }
  402. static void get_string(Object *obj, Visitor *v, const char *name,
  403. void *opaque, Error **errp)
  404. {
  405. const Property *prop = opaque;
  406. char **ptr = object_field_prop_ptr(obj, prop);
  407. if (!*ptr) {
  408. char *str = (char *)"";
  409. visit_type_str(v, name, &str, errp);
  410. } else {
  411. visit_type_str(v, name, ptr, errp);
  412. }
  413. }
  414. static void set_string(Object *obj, Visitor *v, const char *name,
  415. void *opaque, Error **errp)
  416. {
  417. const Property *prop = opaque;
  418. char **ptr = object_field_prop_ptr(obj, prop);
  419. char *str;
  420. if (!visit_type_str(v, name, &str, errp)) {
  421. return;
  422. }
  423. g_free(*ptr);
  424. *ptr = str;
  425. }
  426. const PropertyInfo qdev_prop_string = {
  427. .type = "str",
  428. .release = release_string,
  429. .get = get_string,
  430. .set = set_string,
  431. };
  432. /* --- on/off/auto --- */
  433. const PropertyInfo qdev_prop_on_off_auto = {
  434. .type = "OnOffAuto",
  435. .description = "on/off/auto",
  436. .enum_table = &OnOffAuto_lookup,
  437. .get = qdev_propinfo_get_enum,
  438. .set = qdev_propinfo_set_enum,
  439. .set_default_value = qdev_propinfo_set_default_value_enum,
  440. };
  441. /* --- 32bit unsigned int 'size' type --- */
  442. void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name,
  443. void *opaque, Error **errp)
  444. {
  445. const Property *prop = opaque;
  446. uint32_t *ptr = object_field_prop_ptr(obj, prop);
  447. uint64_t value = *ptr;
  448. visit_type_size(v, name, &value, errp);
  449. }
  450. static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,
  451. Error **errp)
  452. {
  453. const Property *prop = opaque;
  454. uint32_t *ptr = object_field_prop_ptr(obj, prop);
  455. uint64_t value;
  456. if (!visit_type_size(v, name, &value, errp)) {
  457. return;
  458. }
  459. if (value > UINT32_MAX) {
  460. error_setg(errp,
  461. "Property %s.%s doesn't take value %" PRIu64
  462. " (maximum: %u)",
  463. object_get_typename(obj), name, value, UINT32_MAX);
  464. return;
  465. }
  466. *ptr = value;
  467. }
  468. const PropertyInfo qdev_prop_size32 = {
  469. .type = "size",
  470. .get = qdev_propinfo_get_size32,
  471. .set = set_size32,
  472. .set_default_value = qdev_propinfo_set_default_value_uint,
  473. };
  474. /* --- support for array properties --- */
  475. typedef struct ArrayElementList ArrayElementList;
  476. struct ArrayElementList {
  477. ArrayElementList *next;
  478. void *value;
  479. };
  480. /*
  481. * Given an array property @parent_prop in @obj, return a Property for a
  482. * specific element of the array. Arrays are backed by an uint32_t length field
  483. * and an element array. @elem points at an element in this element array.
  484. */
  485. static Property array_elem_prop(Object *obj, const Property *parent_prop,
  486. const char *name, char *elem)
  487. {
  488. return (Property) {
  489. .info = parent_prop->arrayinfo,
  490. .name = name,
  491. /*
  492. * This ugly piece of pointer arithmetic sets up the offset so
  493. * that when the underlying release hook calls qdev_get_prop_ptr
  494. * they get the right answer despite the array element not actually
  495. * being inside the device struct.
  496. */
  497. .offset = (uintptr_t)elem - (uintptr_t)obj,
  498. };
  499. }
  500. /*
  501. * Object property release callback for array properties: We call the
  502. * underlying element's property release hook for each element.
  503. *
  504. * Note that it is the responsibility of the individual device's deinit
  505. * to free the array proper.
  506. */
  507. static void release_prop_array(Object *obj, const char *name, void *opaque)
  508. {
  509. const Property *prop = opaque;
  510. uint32_t *alenptr = object_field_prop_ptr(obj, prop);
  511. void **arrayptr = (void *)obj + prop->arrayoffset;
  512. char *elem = *arrayptr;
  513. int i;
  514. if (!prop->arrayinfo->release) {
  515. return;
  516. }
  517. for (i = 0; i < *alenptr; i++) {
  518. Property elem_prop = array_elem_prop(obj, prop, name, elem);
  519. prop->arrayinfo->release(obj, NULL, &elem_prop);
  520. elem += prop->arrayfieldsize;
  521. }
  522. }
  523. /*
  524. * Setter for an array property. This sets both the array length (which
  525. * is technically the property field in the object) and the array itself
  526. * (a pointer to which is stored in the additional field described by
  527. * prop->arrayoffset).
  528. */
  529. static void set_prop_array(Object *obj, Visitor *v, const char *name,
  530. void *opaque, Error **errp)
  531. {
  532. ERRP_GUARD();
  533. const Property *prop = opaque;
  534. uint32_t *alenptr = object_field_prop_ptr(obj, prop);
  535. void **arrayptr = (void *)obj + prop->arrayoffset;
  536. ArrayElementList *list, *elem, *next;
  537. const size_t size = sizeof(*list);
  538. char *elemptr;
  539. bool ok = true;
  540. if (*alenptr) {
  541. error_setg(errp, "array size property %s may not be set more than once",
  542. name);
  543. return;
  544. }
  545. if (!visit_start_list(v, name, (GenericList **) &list, size, errp)) {
  546. return;
  547. }
  548. /* Read the whole input into a temporary list */
  549. elem = list;
  550. while (elem) {
  551. Property elem_prop;
  552. elem->value = g_malloc0(prop->arrayfieldsize);
  553. elem_prop = array_elem_prop(obj, prop, name, elem->value);
  554. prop->arrayinfo->set(obj, v, NULL, &elem_prop, errp);
  555. if (*errp) {
  556. ok = false;
  557. goto out_obj;
  558. }
  559. if (*alenptr == INT_MAX) {
  560. error_setg(errp, "array is too big");
  561. return;
  562. }
  563. (*alenptr)++;
  564. elem = (ArrayElementList *) visit_next_list(v, (GenericList*) elem,
  565. size);
  566. }
  567. ok = visit_check_list(v, errp);
  568. out_obj:
  569. visit_end_list(v, (void**) &list);
  570. if (!ok) {
  571. for (elem = list; elem; elem = next) {
  572. Property elem_prop = array_elem_prop(obj, prop, name,
  573. elem->value);
  574. if (prop->arrayinfo->release) {
  575. prop->arrayinfo->release(obj, NULL, &elem_prop);
  576. }
  577. next = elem->next;
  578. g_free(elem->value);
  579. g_free(elem);
  580. }
  581. return;
  582. }
  583. /*
  584. * Now that we know how big the array has to be, move the data over to a
  585. * linear array and free the temporary list.
  586. */
  587. *arrayptr = g_malloc_n(*alenptr, prop->arrayfieldsize);
  588. elemptr = *arrayptr;
  589. for (elem = list; elem; elem = next) {
  590. memcpy(elemptr, elem->value, prop->arrayfieldsize);
  591. elemptr += prop->arrayfieldsize;
  592. next = elem->next;
  593. g_free(elem->value);
  594. g_free(elem);
  595. }
  596. }
  597. static void get_prop_array(Object *obj, Visitor *v, const char *name,
  598. void *opaque, Error **errp)
  599. {
  600. ERRP_GUARD();
  601. const Property *prop = opaque;
  602. uint32_t *alenptr = object_field_prop_ptr(obj, prop);
  603. void **arrayptr = (void *)obj + prop->arrayoffset;
  604. char *elemptr = *arrayptr;
  605. ArrayElementList *list = NULL, *elem;
  606. ArrayElementList **tail = &list;
  607. const size_t size = sizeof(*list);
  608. int i;
  609. bool ok;
  610. /* At least the string output visitor needs a real list */
  611. for (i = 0; i < *alenptr; i++) {
  612. elem = g_new0(ArrayElementList, 1);
  613. elem->value = elemptr;
  614. elemptr += prop->arrayfieldsize;
  615. *tail = elem;
  616. tail = &elem->next;
  617. }
  618. if (!visit_start_list(v, name, (GenericList **) &list, size, errp)) {
  619. return;
  620. }
  621. elem = list;
  622. while (elem) {
  623. Property elem_prop = array_elem_prop(obj, prop, name, elem->value);
  624. prop->arrayinfo->get(obj, v, NULL, &elem_prop, errp);
  625. if (*errp) {
  626. goto out_obj;
  627. }
  628. elem = (ArrayElementList *) visit_next_list(v, (GenericList*) elem,
  629. size);
  630. }
  631. /* visit_check_list() can only fail for input visitors */
  632. ok = visit_check_list(v, errp);
  633. assert(ok);
  634. out_obj:
  635. visit_end_list(v, (void**) &list);
  636. while (list) {
  637. elem = list;
  638. list = elem->next;
  639. g_free(elem);
  640. }
  641. }
  642. static void default_prop_array(ObjectProperty *op, const Property *prop)
  643. {
  644. object_property_set_default_list(op);
  645. }
  646. const PropertyInfo qdev_prop_array = {
  647. .type = "list",
  648. .get = get_prop_array,
  649. .set = set_prop_array,
  650. .release = release_prop_array,
  651. .set_default_value = default_prop_array,
  652. };
  653. /* --- public helpers --- */
  654. static const Property *qdev_prop_walk(DeviceClass *cls, const char *name)
  655. {
  656. for (int i = 0, n = cls->props_count_; i < n; ++i) {
  657. const Property *prop = &cls->props_[i];
  658. if (strcmp(prop->name, name) == 0) {
  659. return prop;
  660. }
  661. }
  662. return NULL;
  663. }
  664. static const Property *qdev_prop_find(DeviceState *dev, const char *name)
  665. {
  666. ObjectClass *class;
  667. const Property *prop;
  668. /* device properties */
  669. class = object_get_class(OBJECT(dev));
  670. do {
  671. prop = qdev_prop_walk(DEVICE_CLASS(class), name);
  672. if (prop) {
  673. return prop;
  674. }
  675. class = object_class_get_parent(class);
  676. } while (class != object_class_by_name(TYPE_DEVICE));
  677. return NULL;
  678. }
  679. void error_set_from_qdev_prop_error(Error **errp, int ret, Object *obj,
  680. const char *name, const char *value)
  681. {
  682. switch (ret) {
  683. case -EEXIST:
  684. error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
  685. object_get_typename(obj), name, value);
  686. break;
  687. default:
  688. case -EINVAL:
  689. error_setg(errp, "Property '%s.%s' doesn't take value '%s'",
  690. object_get_typename(obj), name, value);
  691. break;
  692. case -ENOENT:
  693. error_setg(errp, "Property '%s.%s' can't find value '%s'",
  694. object_get_typename(obj), name, value);
  695. break;
  696. case 0:
  697. break;
  698. }
  699. }
  700. void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
  701. {
  702. object_property_set_bool(OBJECT(dev), name, value, &error_abort);
  703. }
  704. void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
  705. {
  706. object_property_set_int(OBJECT(dev), name, value, &error_abort);
  707. }
  708. void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
  709. {
  710. object_property_set_int(OBJECT(dev), name, value, &error_abort);
  711. }
  712. void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
  713. {
  714. object_property_set_int(OBJECT(dev), name, value, &error_abort);
  715. }
  716. void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
  717. {
  718. object_property_set_int(OBJECT(dev), name, value, &error_abort);
  719. }
  720. void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
  721. {
  722. object_property_set_int(OBJECT(dev), name, value, &error_abort);
  723. }
  724. void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
  725. {
  726. object_property_set_str(OBJECT(dev), name, value, &error_abort);
  727. }
  728. void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
  729. {
  730. const Property *prop;
  731. prop = qdev_prop_find(dev, name);
  732. object_property_set_str(OBJECT(dev), name,
  733. qapi_enum_lookup(prop->info->enum_table, value),
  734. &error_abort);
  735. }
  736. void qdev_prop_set_array(DeviceState *dev, const char *name, QList *values)
  737. {
  738. object_property_set_qobject(OBJECT(dev), name, QOBJECT(values),
  739. &error_abort);
  740. qobject_unref(values);
  741. }
  742. static GPtrArray *global_props(void)
  743. {
  744. static GPtrArray *gp;
  745. if (!gp) {
  746. gp = g_ptr_array_new();
  747. }
  748. return gp;
  749. }
  750. void qdev_prop_register_global(GlobalProperty *prop)
  751. {
  752. g_ptr_array_add(global_props(), prop);
  753. }
  754. const GlobalProperty *qdev_find_global_prop(Object *obj,
  755. const char *name)
  756. {
  757. GPtrArray *props = global_props();
  758. const GlobalProperty *p;
  759. int i;
  760. for (i = 0; i < props->len; i++) {
  761. p = g_ptr_array_index(props, i);
  762. if (object_dynamic_cast(obj, p->driver)
  763. && !strcmp(p->property, name)) {
  764. return p;
  765. }
  766. }
  767. return NULL;
  768. }
  769. int qdev_prop_check_globals(void)
  770. {
  771. int i, ret = 0;
  772. for (i = 0; i < global_props()->len; i++) {
  773. GlobalProperty *prop;
  774. ObjectClass *oc;
  775. DeviceClass *dc;
  776. prop = g_ptr_array_index(global_props(), i);
  777. if (prop->used) {
  778. continue;
  779. }
  780. oc = object_class_by_name(prop->driver);
  781. oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
  782. if (!oc) {
  783. warn_report("global %s.%s has invalid class name",
  784. prop->driver, prop->property);
  785. ret = 1;
  786. continue;
  787. }
  788. dc = DEVICE_CLASS(oc);
  789. if (!dc->hotpluggable && !prop->used) {
  790. warn_report("global %s.%s=%s not used",
  791. prop->driver, prop->property, prop->value);
  792. ret = 1;
  793. continue;
  794. }
  795. }
  796. return ret;
  797. }
  798. void qdev_prop_set_globals(DeviceState *dev)
  799. {
  800. object_apply_global_props(OBJECT(dev), global_props(),
  801. dev->hotplugged ? NULL : &error_fatal);
  802. }
  803. /* --- 64bit unsigned int 'size' type --- */
  804. static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
  805. Error **errp)
  806. {
  807. const Property *prop = opaque;
  808. uint64_t *ptr = object_field_prop_ptr(obj, prop);
  809. visit_type_size(v, name, ptr, errp);
  810. }
  811. static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
  812. Error **errp)
  813. {
  814. const Property *prop = opaque;
  815. uint64_t *ptr = object_field_prop_ptr(obj, prop);
  816. visit_type_size(v, name, ptr, errp);
  817. }
  818. const PropertyInfo qdev_prop_size = {
  819. .type = "size",
  820. .get = get_size,
  821. .set = set_size,
  822. .set_default_value = qdev_propinfo_set_default_value_uint,
  823. };
  824. /* --- object link property --- */
  825. static ObjectProperty *create_link_property(ObjectClass *oc, const char *name,
  826. const Property *prop)
  827. {
  828. return object_class_property_add_link(oc, name, prop->link_type,
  829. prop->offset,
  830. qdev_prop_allow_set_link_before_realize,
  831. OBJ_PROP_LINK_STRONG);
  832. }
  833. const PropertyInfo qdev_prop_link = {
  834. .type = "link",
  835. .create = create_link_property,
  836. };
  837. void qdev_property_add_static(DeviceState *dev, const Property *prop)
  838. {
  839. Object *obj = OBJECT(dev);
  840. ObjectProperty *op;
  841. assert(!prop->info->create);
  842. op = object_property_add(obj, prop->name, prop->info->type,
  843. field_prop_getter(prop->info),
  844. field_prop_setter(prop->info),
  845. prop->info->release,
  846. (Property *)prop);
  847. object_property_set_description(obj, prop->name,
  848. prop->info->description);
  849. if (prop->set_default) {
  850. prop->info->set_default_value(op, prop);
  851. if (op->init) {
  852. op->init(obj, op);
  853. }
  854. }
  855. }
  856. static void qdev_class_add_property(DeviceClass *klass, const char *name,
  857. const Property *prop)
  858. {
  859. ObjectClass *oc = OBJECT_CLASS(klass);
  860. ObjectProperty *op;
  861. if (prop->info->create) {
  862. op = prop->info->create(oc, name, prop);
  863. } else {
  864. op = object_class_property_add(oc,
  865. name, prop->info->type,
  866. field_prop_getter(prop->info),
  867. field_prop_setter(prop->info),
  868. prop->info->release,
  869. (Property *)prop);
  870. }
  871. if (prop->set_default) {
  872. prop->info->set_default_value(op, prop);
  873. }
  874. object_class_property_set_description(oc, name, prop->info->description);
  875. }
  876. /**
  877. * Legacy property handling
  878. */
  879. static void qdev_get_legacy_property(Object *obj, Visitor *v,
  880. const char *name, void *opaque,
  881. Error **errp)
  882. {
  883. const Property *prop = opaque;
  884. char buffer[1024];
  885. char *ptr = buffer;
  886. prop->info->print(obj, prop, buffer, sizeof(buffer));
  887. visit_type_str(v, name, &ptr, errp);
  888. }
  889. /**
  890. * qdev_class_add_legacy_property:
  891. * @dev: Device to add the property to.
  892. * @prop: The qdev property definition.
  893. *
  894. * Add a legacy QOM property to @dev for qdev property @prop.
  895. *
  896. * Legacy properties are string versions of QOM properties. The format of
  897. * the string depends on the property type. Legacy properties are only
  898. * needed for "info qtree".
  899. *
  900. * Do not use this in new code! QOM Properties added through this interface
  901. * will be given names in the "legacy" namespace.
  902. */
  903. static void qdev_class_add_legacy_property(DeviceClass *dc, const Property *prop)
  904. {
  905. g_autofree char *name = NULL;
  906. /* Register pointer properties as legacy properties */
  907. if (!prop->info->print && prop->info->get) {
  908. return;
  909. }
  910. name = g_strdup_printf("legacy-%s", prop->name);
  911. object_class_property_add(OBJECT_CLASS(dc), name, "str",
  912. prop->info->print ? qdev_get_legacy_property : prop->info->get,
  913. NULL, NULL, (Property *)prop);
  914. }
  915. void device_class_set_props_n(DeviceClass *dc, const Property *props, size_t n)
  916. {
  917. /* We used a hole in DeviceClass because that's still a lot. */
  918. assert(n <= UINT16_MAX);
  919. assert(n != 0);
  920. dc->props_ = props;
  921. dc->props_count_ = n;
  922. for (size_t i = 0; i < n; ++i) {
  923. const Property *prop = &props[i];
  924. assert(prop->name);
  925. qdev_class_add_legacy_property(dc, prop);
  926. qdev_class_add_property(dc, prop->name, prop);
  927. }
  928. }
  929. void qdev_alias_all_properties(DeviceState *target, Object *source)
  930. {
  931. ObjectClass *class;
  932. ObjectPropertyIterator iter;
  933. ObjectProperty *prop;
  934. class = object_get_class(OBJECT(target));
  935. object_class_property_iter_init(&iter, class);
  936. while ((prop = object_property_iter_next(&iter))) {
  937. if (object_property_find(source, prop->name)) {
  938. continue; /* skip duplicate properties */
  939. }
  940. object_property_add_alias(source, prop->name,
  941. OBJECT(target), prop->name);
  942. }
  943. }