qdev-properties.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088
  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. .get = get_bool,
  211. .set = set_bool,
  212. .set_default_value = set_default_value_bool,
  213. };
  214. /* --- 8bit integer --- */
  215. static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
  216. Error **errp)
  217. {
  218. const Property *prop = opaque;
  219. uint8_t *ptr = object_field_prop_ptr(obj, prop);
  220. visit_type_uint8(v, name, ptr, errp);
  221. }
  222. static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
  223. Error **errp)
  224. {
  225. const Property *prop = opaque;
  226. uint8_t *ptr = object_field_prop_ptr(obj, prop);
  227. visit_type_uint8(v, name, ptr, errp);
  228. }
  229. void qdev_propinfo_set_default_value_int(ObjectProperty *op,
  230. const Property *prop)
  231. {
  232. object_property_set_default_int(op, prop->defval.i);
  233. }
  234. void qdev_propinfo_set_default_value_uint(ObjectProperty *op,
  235. const Property *prop)
  236. {
  237. object_property_set_default_uint(op, prop->defval.u);
  238. }
  239. const PropertyInfo qdev_prop_uint8 = {
  240. .type = "uint8",
  241. .get = get_uint8,
  242. .set = set_uint8,
  243. .set_default_value = qdev_propinfo_set_default_value_uint,
  244. };
  245. /* --- 16bit integer --- */
  246. static void get_uint16(Object *obj, Visitor *v, const char *name,
  247. void *opaque, Error **errp)
  248. {
  249. const Property *prop = opaque;
  250. uint16_t *ptr = object_field_prop_ptr(obj, prop);
  251. visit_type_uint16(v, name, ptr, errp);
  252. }
  253. static void set_uint16(Object *obj, Visitor *v, const char *name,
  254. void *opaque, Error **errp)
  255. {
  256. const Property *prop = opaque;
  257. uint16_t *ptr = object_field_prop_ptr(obj, prop);
  258. visit_type_uint16(v, name, ptr, errp);
  259. }
  260. const PropertyInfo qdev_prop_uint16 = {
  261. .type = "uint16",
  262. .get = get_uint16,
  263. .set = set_uint16,
  264. .set_default_value = qdev_propinfo_set_default_value_uint,
  265. };
  266. /* --- 32bit integer --- */
  267. static void get_uint32(Object *obj, Visitor *v, const char *name,
  268. void *opaque, Error **errp)
  269. {
  270. const Property *prop = opaque;
  271. uint32_t *ptr = object_field_prop_ptr(obj, prop);
  272. visit_type_uint32(v, name, ptr, errp);
  273. }
  274. static void set_uint32(Object *obj, Visitor *v, const char *name,
  275. void *opaque, Error **errp)
  276. {
  277. const Property *prop = opaque;
  278. uint32_t *ptr = object_field_prop_ptr(obj, prop);
  279. visit_type_uint32(v, name, ptr, errp);
  280. }
  281. void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name,
  282. void *opaque, Error **errp)
  283. {
  284. const Property *prop = opaque;
  285. int32_t *ptr = object_field_prop_ptr(obj, prop);
  286. visit_type_int32(v, name, ptr, errp);
  287. }
  288. static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
  289. Error **errp)
  290. {
  291. const Property *prop = opaque;
  292. int32_t *ptr = object_field_prop_ptr(obj, prop);
  293. visit_type_int32(v, name, ptr, errp);
  294. }
  295. const PropertyInfo qdev_prop_uint32 = {
  296. .type = "uint32",
  297. .get = get_uint32,
  298. .set = set_uint32,
  299. .set_default_value = qdev_propinfo_set_default_value_uint,
  300. };
  301. const PropertyInfo qdev_prop_int32 = {
  302. .type = "int32",
  303. .get = qdev_propinfo_get_int32,
  304. .set = set_int32,
  305. .set_default_value = qdev_propinfo_set_default_value_int,
  306. };
  307. /* --- 64bit integer --- */
  308. static void get_uint64(Object *obj, Visitor *v, const char *name,
  309. void *opaque, Error **errp)
  310. {
  311. const Property *prop = opaque;
  312. uint64_t *ptr = object_field_prop_ptr(obj, prop);
  313. visit_type_uint64(v, name, ptr, errp);
  314. }
  315. static void set_uint64(Object *obj, Visitor *v, const char *name,
  316. void *opaque, Error **errp)
  317. {
  318. const Property *prop = opaque;
  319. uint64_t *ptr = object_field_prop_ptr(obj, prop);
  320. visit_type_uint64(v, name, ptr, errp);
  321. }
  322. static void get_int64(Object *obj, Visitor *v, const char *name,
  323. void *opaque, Error **errp)
  324. {
  325. const Property *prop = opaque;
  326. int64_t *ptr = object_field_prop_ptr(obj, prop);
  327. visit_type_int64(v, name, ptr, errp);
  328. }
  329. static void set_int64(Object *obj, Visitor *v, const char *name,
  330. void *opaque, Error **errp)
  331. {
  332. const Property *prop = opaque;
  333. int64_t *ptr = object_field_prop_ptr(obj, prop);
  334. visit_type_int64(v, name, ptr, errp);
  335. }
  336. const PropertyInfo qdev_prop_uint64 = {
  337. .type = "uint64",
  338. .get = get_uint64,
  339. .set = set_uint64,
  340. .set_default_value = qdev_propinfo_set_default_value_uint,
  341. };
  342. const PropertyInfo qdev_prop_int64 = {
  343. .type = "int64",
  344. .get = get_int64,
  345. .set = set_int64,
  346. .set_default_value = qdev_propinfo_set_default_value_int,
  347. };
  348. static void set_uint64_checkmask(Object *obj, Visitor *v, const char *name,
  349. void *opaque, Error **errp)
  350. {
  351. const Property *prop = opaque;
  352. uint64_t *ptr = object_field_prop_ptr(obj, prop);
  353. visit_type_uint64(v, name, ptr, errp);
  354. if (*ptr & ~prop->bitmask) {
  355. error_setg(errp, "Property value for '%s' has bits outside mask '0x%" PRIx64 "'",
  356. name, prop->bitmask);
  357. }
  358. }
  359. const PropertyInfo qdev_prop_uint64_checkmask = {
  360. .type = "uint64",
  361. .get = get_uint64,
  362. .set = set_uint64_checkmask,
  363. };
  364. /* --- string --- */
  365. static void release_string(Object *obj, const char *name, void *opaque)
  366. {
  367. const Property *prop = opaque;
  368. g_free(*(char **)object_field_prop_ptr(obj, prop));
  369. }
  370. static void get_string(Object *obj, Visitor *v, const char *name,
  371. void *opaque, Error **errp)
  372. {
  373. const Property *prop = opaque;
  374. char **ptr = object_field_prop_ptr(obj, prop);
  375. if (!*ptr) {
  376. char *str = (char *)"";
  377. visit_type_str(v, name, &str, errp);
  378. } else {
  379. visit_type_str(v, name, ptr, errp);
  380. }
  381. }
  382. static void set_string(Object *obj, Visitor *v, const char *name,
  383. void *opaque, Error **errp)
  384. {
  385. const Property *prop = opaque;
  386. char **ptr = object_field_prop_ptr(obj, prop);
  387. char *str;
  388. if (!visit_type_str(v, name, &str, errp)) {
  389. return;
  390. }
  391. g_free(*ptr);
  392. *ptr = str;
  393. }
  394. const PropertyInfo qdev_prop_string = {
  395. .type = "str",
  396. .release = release_string,
  397. .get = get_string,
  398. .set = set_string,
  399. };
  400. /* --- on/off/auto --- */
  401. const PropertyInfo qdev_prop_on_off_auto = {
  402. .type = "OnOffAuto",
  403. .description = "on/off/auto",
  404. .enum_table = &OnOffAuto_lookup,
  405. .get = qdev_propinfo_get_enum,
  406. .set = qdev_propinfo_set_enum,
  407. .set_default_value = qdev_propinfo_set_default_value_enum,
  408. };
  409. /* --- 32bit unsigned int 'size' type --- */
  410. void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name,
  411. void *opaque, Error **errp)
  412. {
  413. const Property *prop = opaque;
  414. uint32_t *ptr = object_field_prop_ptr(obj, prop);
  415. uint64_t value = *ptr;
  416. visit_type_size(v, name, &value, errp);
  417. }
  418. static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,
  419. Error **errp)
  420. {
  421. const Property *prop = opaque;
  422. uint32_t *ptr = object_field_prop_ptr(obj, prop);
  423. uint64_t value;
  424. if (!visit_type_size(v, name, &value, errp)) {
  425. return;
  426. }
  427. if (value > UINT32_MAX) {
  428. error_setg(errp,
  429. "Property %s.%s doesn't take value %" PRIu64
  430. " (maximum: %u)",
  431. object_get_typename(obj), name, value, UINT32_MAX);
  432. return;
  433. }
  434. *ptr = value;
  435. }
  436. const PropertyInfo qdev_prop_size32 = {
  437. .type = "size",
  438. .get = qdev_propinfo_get_size32,
  439. .set = set_size32,
  440. .set_default_value = qdev_propinfo_set_default_value_uint,
  441. };
  442. /* --- support for array properties --- */
  443. typedef struct ArrayElementList ArrayElementList;
  444. struct ArrayElementList {
  445. ArrayElementList *next;
  446. void *value;
  447. };
  448. /*
  449. * Given an array property @parent_prop in @obj, return a Property for a
  450. * specific element of the array. Arrays are backed by an uint32_t length field
  451. * and an element array. @elem points at an element in this element array.
  452. */
  453. static Property array_elem_prop(Object *obj, const Property *parent_prop,
  454. const char *name, char *elem)
  455. {
  456. return (Property) {
  457. .info = parent_prop->arrayinfo,
  458. .name = name,
  459. /*
  460. * This ugly piece of pointer arithmetic sets up the offset so
  461. * that when the underlying release hook calls qdev_get_prop_ptr
  462. * they get the right answer despite the array element not actually
  463. * being inside the device struct.
  464. */
  465. .offset = (uintptr_t)elem - (uintptr_t)obj,
  466. };
  467. }
  468. /*
  469. * Object property release callback for array properties: We call the
  470. * underlying element's property release hook for each element.
  471. *
  472. * Note that it is the responsibility of the individual device's deinit
  473. * to free the array proper.
  474. */
  475. static void release_prop_array(Object *obj, const char *name, void *opaque)
  476. {
  477. const Property *prop = opaque;
  478. uint32_t *alenptr = object_field_prop_ptr(obj, prop);
  479. void **arrayptr = (void *)obj + prop->arrayoffset;
  480. char *elem = *arrayptr;
  481. int i;
  482. if (!prop->arrayinfo->release) {
  483. return;
  484. }
  485. for (i = 0; i < *alenptr; i++) {
  486. Property elem_prop = array_elem_prop(obj, prop, name, elem);
  487. prop->arrayinfo->release(obj, NULL, &elem_prop);
  488. elem += prop->arrayfieldsize;
  489. }
  490. }
  491. /*
  492. * Setter for an array property. This sets both the array length (which
  493. * is technically the property field in the object) and the array itself
  494. * (a pointer to which is stored in the additional field described by
  495. * prop->arrayoffset).
  496. */
  497. static void set_prop_array(Object *obj, Visitor *v, const char *name,
  498. void *opaque, Error **errp)
  499. {
  500. ERRP_GUARD();
  501. const Property *prop = opaque;
  502. uint32_t *alenptr = object_field_prop_ptr(obj, prop);
  503. void **arrayptr = (void *)obj + prop->arrayoffset;
  504. ArrayElementList *list, *elem, *next;
  505. const size_t size = sizeof(*list);
  506. char *elemptr;
  507. bool ok = true;
  508. if (*alenptr) {
  509. error_setg(errp, "array size property %s may not be set more than once",
  510. name);
  511. return;
  512. }
  513. if (!visit_start_list(v, name, (GenericList **) &list, size, errp)) {
  514. return;
  515. }
  516. /* Read the whole input into a temporary list */
  517. elem = list;
  518. while (elem) {
  519. Property elem_prop;
  520. elem->value = g_malloc0(prop->arrayfieldsize);
  521. elem_prop = array_elem_prop(obj, prop, name, elem->value);
  522. prop->arrayinfo->set(obj, v, NULL, &elem_prop, errp);
  523. if (*errp) {
  524. ok = false;
  525. goto out_obj;
  526. }
  527. if (*alenptr == INT_MAX) {
  528. error_setg(errp, "array is too big");
  529. return;
  530. }
  531. (*alenptr)++;
  532. elem = (ArrayElementList *) visit_next_list(v, (GenericList*) elem,
  533. size);
  534. }
  535. ok = visit_check_list(v, errp);
  536. out_obj:
  537. visit_end_list(v, (void**) &list);
  538. if (!ok) {
  539. for (elem = list; elem; elem = next) {
  540. Property elem_prop = array_elem_prop(obj, prop, name,
  541. elem->value);
  542. if (prop->arrayinfo->release) {
  543. prop->arrayinfo->release(obj, NULL, &elem_prop);
  544. }
  545. next = elem->next;
  546. g_free(elem->value);
  547. g_free(elem);
  548. }
  549. return;
  550. }
  551. /*
  552. * Now that we know how big the array has to be, move the data over to a
  553. * linear array and free the temporary list.
  554. */
  555. *arrayptr = g_malloc_n(*alenptr, prop->arrayfieldsize);
  556. elemptr = *arrayptr;
  557. for (elem = list; elem; elem = next) {
  558. memcpy(elemptr, elem->value, prop->arrayfieldsize);
  559. elemptr += prop->arrayfieldsize;
  560. next = elem->next;
  561. g_free(elem->value);
  562. g_free(elem);
  563. }
  564. }
  565. static void get_prop_array(Object *obj, Visitor *v, const char *name,
  566. void *opaque, Error **errp)
  567. {
  568. ERRP_GUARD();
  569. const Property *prop = opaque;
  570. uint32_t *alenptr = object_field_prop_ptr(obj, prop);
  571. void **arrayptr = (void *)obj + prop->arrayoffset;
  572. char *elemptr = *arrayptr;
  573. ArrayElementList *list = NULL, *elem;
  574. ArrayElementList **tail = &list;
  575. const size_t size = sizeof(*list);
  576. int i;
  577. bool ok;
  578. /* At least the string output visitor needs a real list */
  579. for (i = 0; i < *alenptr; i++) {
  580. elem = g_new0(ArrayElementList, 1);
  581. elem->value = elemptr;
  582. elemptr += prop->arrayfieldsize;
  583. *tail = elem;
  584. tail = &elem->next;
  585. }
  586. if (!visit_start_list(v, name, (GenericList **) &list, size, errp)) {
  587. return;
  588. }
  589. elem = list;
  590. while (elem) {
  591. Property elem_prop = array_elem_prop(obj, prop, name, elem->value);
  592. prop->arrayinfo->get(obj, v, NULL, &elem_prop, errp);
  593. if (*errp) {
  594. goto out_obj;
  595. }
  596. elem = (ArrayElementList *) visit_next_list(v, (GenericList*) elem,
  597. size);
  598. }
  599. /* visit_check_list() can only fail for input visitors */
  600. ok = visit_check_list(v, errp);
  601. assert(ok);
  602. out_obj:
  603. visit_end_list(v, (void**) &list);
  604. while (list) {
  605. elem = list;
  606. list = elem->next;
  607. g_free(elem);
  608. }
  609. }
  610. static void default_prop_array(ObjectProperty *op, const Property *prop)
  611. {
  612. object_property_set_default_list(op);
  613. }
  614. const PropertyInfo qdev_prop_array = {
  615. .type = "list",
  616. .get = get_prop_array,
  617. .set = set_prop_array,
  618. .release = release_prop_array,
  619. .set_default_value = default_prop_array,
  620. };
  621. /* --- public helpers --- */
  622. static const Property *qdev_prop_walk(DeviceClass *cls, const char *name)
  623. {
  624. for (int i = 0, n = cls->props_count_; i < n; ++i) {
  625. const Property *prop = &cls->props_[i];
  626. if (strcmp(prop->name, name) == 0) {
  627. return prop;
  628. }
  629. }
  630. return NULL;
  631. }
  632. static const Property *qdev_prop_find(DeviceState *dev, const char *name)
  633. {
  634. ObjectClass *class;
  635. const Property *prop;
  636. /* device properties */
  637. class = object_get_class(OBJECT(dev));
  638. do {
  639. prop = qdev_prop_walk(DEVICE_CLASS(class), name);
  640. if (prop) {
  641. return prop;
  642. }
  643. class = object_class_get_parent(class);
  644. } while (class != object_class_by_name(TYPE_DEVICE));
  645. return NULL;
  646. }
  647. void error_set_from_qdev_prop_error(Error **errp, int ret, Object *obj,
  648. const char *name, const char *value)
  649. {
  650. switch (ret) {
  651. case -EEXIST:
  652. error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
  653. object_get_typename(obj), name, value);
  654. break;
  655. default:
  656. case -EINVAL:
  657. error_setg(errp, "Property '%s.%s' doesn't take value '%s'",
  658. object_get_typename(obj), name, value);
  659. break;
  660. case -ENOENT:
  661. error_setg(errp, "Property '%s.%s' can't find value '%s'",
  662. object_get_typename(obj), name, value);
  663. break;
  664. case 0:
  665. break;
  666. }
  667. }
  668. void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
  669. {
  670. object_property_set_bool(OBJECT(dev), name, value, &error_abort);
  671. }
  672. void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
  673. {
  674. object_property_set_int(OBJECT(dev), name, value, &error_abort);
  675. }
  676. void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
  677. {
  678. object_property_set_int(OBJECT(dev), name, value, &error_abort);
  679. }
  680. void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
  681. {
  682. object_property_set_int(OBJECT(dev), name, value, &error_abort);
  683. }
  684. void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
  685. {
  686. object_property_set_int(OBJECT(dev), name, value, &error_abort);
  687. }
  688. void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
  689. {
  690. object_property_set_int(OBJECT(dev), name, value, &error_abort);
  691. }
  692. void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
  693. {
  694. object_property_set_str(OBJECT(dev), name, value, &error_abort);
  695. }
  696. void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
  697. {
  698. const Property *prop;
  699. prop = qdev_prop_find(dev, name);
  700. object_property_set_str(OBJECT(dev), name,
  701. qapi_enum_lookup(prop->info->enum_table, value),
  702. &error_abort);
  703. }
  704. void qdev_prop_set_array(DeviceState *dev, const char *name, QList *values)
  705. {
  706. object_property_set_qobject(OBJECT(dev), name, QOBJECT(values),
  707. &error_abort);
  708. qobject_unref(values);
  709. }
  710. static GPtrArray *global_props(void)
  711. {
  712. static GPtrArray *gp;
  713. if (!gp) {
  714. gp = g_ptr_array_new();
  715. }
  716. return gp;
  717. }
  718. void qdev_prop_register_global(GlobalProperty *prop)
  719. {
  720. g_ptr_array_add(global_props(), prop);
  721. }
  722. const GlobalProperty *qdev_find_global_prop(Object *obj,
  723. const char *name)
  724. {
  725. GPtrArray *props = global_props();
  726. const GlobalProperty *p;
  727. int i;
  728. for (i = 0; i < props->len; i++) {
  729. p = g_ptr_array_index(props, i);
  730. if (object_dynamic_cast(obj, p->driver)
  731. && !strcmp(p->property, name)) {
  732. return p;
  733. }
  734. }
  735. return NULL;
  736. }
  737. int qdev_prop_check_globals(void)
  738. {
  739. int i, ret = 0;
  740. for (i = 0; i < global_props()->len; i++) {
  741. GlobalProperty *prop;
  742. ObjectClass *oc;
  743. DeviceClass *dc;
  744. prop = g_ptr_array_index(global_props(), i);
  745. if (prop->used) {
  746. continue;
  747. }
  748. oc = object_class_by_name(prop->driver);
  749. oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
  750. if (!oc) {
  751. warn_report("global %s.%s has invalid class name",
  752. prop->driver, prop->property);
  753. ret = 1;
  754. continue;
  755. }
  756. dc = DEVICE_CLASS(oc);
  757. if (!dc->hotpluggable && !prop->used) {
  758. warn_report("global %s.%s=%s not used",
  759. prop->driver, prop->property, prop->value);
  760. ret = 1;
  761. continue;
  762. }
  763. }
  764. return ret;
  765. }
  766. void qdev_prop_set_globals(DeviceState *dev)
  767. {
  768. object_apply_global_props(OBJECT(dev), global_props(),
  769. dev->hotplugged ? NULL : &error_fatal);
  770. }
  771. /* --- 64bit unsigned int 'size' type --- */
  772. static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
  773. Error **errp)
  774. {
  775. const Property *prop = opaque;
  776. uint64_t *ptr = object_field_prop_ptr(obj, prop);
  777. visit_type_size(v, name, ptr, errp);
  778. }
  779. static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
  780. Error **errp)
  781. {
  782. const Property *prop = opaque;
  783. uint64_t *ptr = object_field_prop_ptr(obj, prop);
  784. visit_type_size(v, name, ptr, errp);
  785. }
  786. const PropertyInfo qdev_prop_size = {
  787. .type = "size",
  788. .get = get_size,
  789. .set = set_size,
  790. .set_default_value = qdev_propinfo_set_default_value_uint,
  791. };
  792. /* --- object link property --- */
  793. static ObjectProperty *create_link_property(ObjectClass *oc, const char *name,
  794. const Property *prop)
  795. {
  796. return object_class_property_add_link(oc, name, prop->link_type,
  797. prop->offset,
  798. qdev_prop_allow_set_link_before_realize,
  799. OBJ_PROP_LINK_STRONG);
  800. }
  801. const PropertyInfo qdev_prop_link = {
  802. .type = "link",
  803. .create = create_link_property,
  804. };
  805. void qdev_property_add_static(DeviceState *dev, const Property *prop)
  806. {
  807. Object *obj = OBJECT(dev);
  808. ObjectProperty *op;
  809. assert(!prop->info->create);
  810. op = object_property_add(obj, prop->name, prop->info->type,
  811. field_prop_getter(prop->info),
  812. field_prop_setter(prop->info),
  813. prop->info->release,
  814. (Property *)prop);
  815. object_property_set_description(obj, prop->name,
  816. prop->info->description);
  817. if (prop->set_default) {
  818. prop->info->set_default_value(op, prop);
  819. if (op->init) {
  820. op->init(obj, op);
  821. }
  822. }
  823. }
  824. static void qdev_class_add_property(DeviceClass *klass, const char *name,
  825. const Property *prop)
  826. {
  827. ObjectClass *oc = OBJECT_CLASS(klass);
  828. ObjectProperty *op;
  829. if (prop->info->create) {
  830. op = prop->info->create(oc, name, prop);
  831. } else {
  832. op = object_class_property_add(oc,
  833. name, prop->info->type,
  834. field_prop_getter(prop->info),
  835. field_prop_setter(prop->info),
  836. prop->info->release,
  837. (Property *)prop);
  838. }
  839. if (prop->set_default) {
  840. prop->info->set_default_value(op, prop);
  841. }
  842. object_class_property_set_description(oc, name, prop->info->description);
  843. }
  844. /**
  845. * Legacy property handling
  846. */
  847. static void qdev_get_legacy_property(Object *obj, Visitor *v,
  848. const char *name, void *opaque,
  849. Error **errp)
  850. {
  851. const Property *prop = opaque;
  852. char buffer[1024];
  853. char *ptr = buffer;
  854. prop->info->print(obj, prop, buffer, sizeof(buffer));
  855. visit_type_str(v, name, &ptr, errp);
  856. }
  857. /**
  858. * qdev_class_add_legacy_property:
  859. * @dev: Device to add the property to.
  860. * @prop: The qdev property definition.
  861. *
  862. * Add a legacy QOM property to @dev for qdev property @prop.
  863. *
  864. * Legacy properties are string versions of QOM properties. The format of
  865. * the string depends on the property type. Legacy properties are only
  866. * needed for "info qtree".
  867. *
  868. * Do not use this in new code! QOM Properties added through this interface
  869. * will be given names in the "legacy" namespace.
  870. */
  871. static void qdev_class_add_legacy_property(DeviceClass *dc, const Property *prop)
  872. {
  873. g_autofree char *name = NULL;
  874. /* Register pointer properties as legacy properties */
  875. if (!prop->info->print && prop->info->get) {
  876. return;
  877. }
  878. name = g_strdup_printf("legacy-%s", prop->name);
  879. object_class_property_add(OBJECT_CLASS(dc), name, "str",
  880. prop->info->print ? qdev_get_legacy_property : prop->info->get,
  881. NULL, NULL, (Property *)prop);
  882. }
  883. void device_class_set_props_n(DeviceClass *dc, const Property *props, size_t n)
  884. {
  885. /* We used a hole in DeviceClass because that's still a lot. */
  886. assert(n <= UINT16_MAX);
  887. assert(n != 0);
  888. dc->props_ = props;
  889. dc->props_count_ = n;
  890. for (size_t i = 0; i < n; ++i) {
  891. const Property *prop = &props[i];
  892. assert(prop->name);
  893. qdev_class_add_legacy_property(dc, prop);
  894. qdev_class_add_property(dc, prop->name, prop);
  895. }
  896. }
  897. void qdev_alias_all_properties(DeviceState *target, Object *source)
  898. {
  899. ObjectClass *class;
  900. ObjectPropertyIterator iter;
  901. ObjectProperty *prop;
  902. class = object_get_class(OBJECT(target));
  903. object_class_property_iter_init(&iter, class);
  904. while ((prop = object_property_iter_next(&iter))) {
  905. if (object_property_find(source, prop->name)) {
  906. continue; /* skip duplicate properties */
  907. }
  908. object_property_add_alias(source, prop->name,
  909. OBJECT(target), prop->name);
  910. }
  911. }