2
0

qemu-config.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. #include "qemu/osdep.h"
  2. #include "block/qdict.h" /* for qdict_extract_subqdict() */
  3. #include "qapi/error.h"
  4. #include "qapi/qapi-commands-misc.h"
  5. #include "qapi/qmp/qdict.h"
  6. #include "qapi/qmp/qlist.h"
  7. #include "qemu/error-report.h"
  8. #include "qemu/option.h"
  9. #include "qemu/config-file.h"
  10. #include "hw/boards.h"
  11. static QemuOptsList *vm_config_groups[48];
  12. static QemuOptsList *drive_config_groups[5];
  13. static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
  14. Error **errp)
  15. {
  16. int i;
  17. qemu_load_module_for_opts(group);
  18. for (i = 0; lists[i] != NULL; i++) {
  19. if (strcmp(lists[i]->name, group) == 0)
  20. break;
  21. }
  22. if (lists[i] == NULL) {
  23. error_setg(errp, "There is no option group '%s'", group);
  24. }
  25. return lists[i];
  26. }
  27. QemuOptsList *qemu_find_opts(const char *group)
  28. {
  29. QemuOptsList *ret;
  30. Error *local_err = NULL;
  31. ret = find_list(vm_config_groups, group, &local_err);
  32. if (local_err) {
  33. error_report_err(local_err);
  34. }
  35. return ret;
  36. }
  37. QemuOpts *qemu_find_opts_singleton(const char *group)
  38. {
  39. QemuOptsList *list;
  40. QemuOpts *opts;
  41. list = qemu_find_opts(group);
  42. assert(list);
  43. opts = qemu_opts_find(list, NULL);
  44. if (!opts) {
  45. opts = qemu_opts_create(list, NULL, 0, &error_abort);
  46. }
  47. return opts;
  48. }
  49. static CommandLineParameterInfoList *query_option_descs(const QemuOptDesc *desc)
  50. {
  51. CommandLineParameterInfoList *param_list = NULL;
  52. CommandLineParameterInfo *info;
  53. int i;
  54. for (i = 0; desc[i].name != NULL; i++) {
  55. info = g_malloc0(sizeof(*info));
  56. info->name = g_strdup(desc[i].name);
  57. switch (desc[i].type) {
  58. case QEMU_OPT_STRING:
  59. info->type = COMMAND_LINE_PARAMETER_TYPE_STRING;
  60. break;
  61. case QEMU_OPT_BOOL:
  62. info->type = COMMAND_LINE_PARAMETER_TYPE_BOOLEAN;
  63. break;
  64. case QEMU_OPT_NUMBER:
  65. info->type = COMMAND_LINE_PARAMETER_TYPE_NUMBER;
  66. break;
  67. case QEMU_OPT_SIZE:
  68. info->type = COMMAND_LINE_PARAMETER_TYPE_SIZE;
  69. break;
  70. }
  71. info->help = g_strdup(desc[i].help);
  72. info->q_default = g_strdup(desc[i].def_value_str);
  73. QAPI_LIST_PREPEND(param_list, info);
  74. }
  75. return param_list;
  76. }
  77. /* remove repeated entry from the info list */
  78. static void cleanup_infolist(CommandLineParameterInfoList *head)
  79. {
  80. CommandLineParameterInfoList *pre_entry, *cur, *del_entry;
  81. cur = head;
  82. while (cur->next) {
  83. pre_entry = head;
  84. while (pre_entry != cur->next) {
  85. if (!strcmp(pre_entry->value->name, cur->next->value->name)) {
  86. del_entry = cur->next;
  87. cur->next = cur->next->next;
  88. del_entry->next = NULL;
  89. qapi_free_CommandLineParameterInfoList(del_entry);
  90. break;
  91. }
  92. pre_entry = pre_entry->next;
  93. }
  94. cur = cur->next;
  95. }
  96. }
  97. /* merge the description items of two parameter infolists */
  98. static void connect_infolist(CommandLineParameterInfoList *head,
  99. CommandLineParameterInfoList *new)
  100. {
  101. CommandLineParameterInfoList *cur;
  102. cur = head;
  103. while (cur->next) {
  104. cur = cur->next;
  105. }
  106. cur->next = new;
  107. }
  108. /* access all the local QemuOptsLists for drive option */
  109. static CommandLineParameterInfoList *get_drive_infolist(void)
  110. {
  111. CommandLineParameterInfoList *head = NULL, *cur;
  112. int i;
  113. for (i = 0; drive_config_groups[i] != NULL; i++) {
  114. if (!head) {
  115. head = query_option_descs(drive_config_groups[i]->desc);
  116. } else {
  117. cur = query_option_descs(drive_config_groups[i]->desc);
  118. connect_infolist(head, cur);
  119. }
  120. }
  121. cleanup_infolist(head);
  122. return head;
  123. }
  124. static CommandLineParameterInfo *objprop_to_cmdline_prop(ObjectProperty *prop)
  125. {
  126. CommandLineParameterInfo *info;
  127. info = g_malloc0(sizeof(*info));
  128. info->name = g_strdup(prop->name);
  129. if (g_str_equal(prop->type, "bool") || g_str_equal(prop->type, "OnOffAuto")) {
  130. info->type = COMMAND_LINE_PARAMETER_TYPE_BOOLEAN;
  131. } else if (g_str_equal(prop->type, "int")) {
  132. info->type = COMMAND_LINE_PARAMETER_TYPE_NUMBER;
  133. } else if (g_str_equal(prop->type, "size")) {
  134. info->type = COMMAND_LINE_PARAMETER_TYPE_SIZE;
  135. } else {
  136. info->type = COMMAND_LINE_PARAMETER_TYPE_STRING;
  137. }
  138. if (prop->description) {
  139. info->help = g_strdup(prop->description);
  140. }
  141. return info;
  142. }
  143. static CommandLineParameterInfoList *query_all_machine_properties(void)
  144. {
  145. CommandLineParameterInfoList *params = NULL, *clpiter;
  146. CommandLineParameterInfo *info;
  147. GSList *machines, *curr_mach;
  148. ObjectPropertyIterator op_iter;
  149. ObjectProperty *prop;
  150. bool is_new;
  151. machines = object_class_get_list(TYPE_MACHINE, false);
  152. assert(machines);
  153. /* Loop over all machine classes */
  154. for (curr_mach = machines; curr_mach; curr_mach = curr_mach->next) {
  155. object_class_property_iter_init(&op_iter, curr_mach->data);
  156. /* ... and over the properties of each machine: */
  157. while ((prop = object_property_iter_next(&op_iter))) {
  158. if (!prop->set) {
  159. continue;
  160. }
  161. /*
  162. * Check whether the property has already been put into the list
  163. * (via another machine class)
  164. */
  165. is_new = true;
  166. for (clpiter = params; clpiter != NULL; clpiter = clpiter->next) {
  167. if (g_str_equal(clpiter->value->name, prop->name)) {
  168. is_new = false;
  169. break;
  170. }
  171. }
  172. /* If it hasn't been added before, add it now to the list */
  173. if (is_new) {
  174. info = objprop_to_cmdline_prop(prop);
  175. QAPI_LIST_PREPEND(params, info);
  176. }
  177. }
  178. }
  179. g_slist_free(machines);
  180. /* Add entry for the "type" parameter */
  181. info = g_malloc0(sizeof(*info));
  182. info->name = g_strdup("type");
  183. info->type = COMMAND_LINE_PARAMETER_TYPE_STRING;
  184. info->help = g_strdup("machine type");
  185. QAPI_LIST_PREPEND(params, info);
  186. return params;
  187. }
  188. CommandLineOptionInfoList *qmp_query_command_line_options(const char *option,
  189. Error **errp)
  190. {
  191. CommandLineOptionInfoList *conf_list = NULL;
  192. CommandLineOptionInfo *info;
  193. int i;
  194. for (i = 0; vm_config_groups[i] != NULL; i++) {
  195. if (!option || !strcmp(option, vm_config_groups[i]->name)) {
  196. info = g_malloc0(sizeof(*info));
  197. info->option = g_strdup(vm_config_groups[i]->name);
  198. if (!strcmp("drive", vm_config_groups[i]->name)) {
  199. info->parameters = get_drive_infolist();
  200. } else {
  201. info->parameters =
  202. query_option_descs(vm_config_groups[i]->desc);
  203. }
  204. QAPI_LIST_PREPEND(conf_list, info);
  205. }
  206. }
  207. if (!option || !strcmp(option, "machine")) {
  208. info = g_malloc0(sizeof(*info));
  209. info->option = g_strdup("machine");
  210. info->parameters = query_all_machine_properties();
  211. QAPI_LIST_PREPEND(conf_list, info);
  212. }
  213. if (conf_list == NULL) {
  214. error_setg(errp, "invalid option name: %s", option);
  215. }
  216. return conf_list;
  217. }
  218. QemuOptsList *qemu_find_opts_err(const char *group, Error **errp)
  219. {
  220. return find_list(vm_config_groups, group, errp);
  221. }
  222. void qemu_add_drive_opts(QemuOptsList *list)
  223. {
  224. int entries, i;
  225. entries = ARRAY_SIZE(drive_config_groups);
  226. entries--; /* keep list NULL terminated */
  227. for (i = 0; i < entries; i++) {
  228. if (drive_config_groups[i] == NULL) {
  229. drive_config_groups[i] = list;
  230. return;
  231. }
  232. }
  233. fprintf(stderr, "ran out of space in drive_config_groups");
  234. abort();
  235. }
  236. void qemu_add_opts(QemuOptsList *list)
  237. {
  238. int entries, i;
  239. entries = ARRAY_SIZE(vm_config_groups);
  240. entries--; /* keep list NULL terminated */
  241. for (i = 0; i < entries; i++) {
  242. if (vm_config_groups[i] == NULL) {
  243. vm_config_groups[i] = list;
  244. return;
  245. }
  246. }
  247. fprintf(stderr, "ran out of space in vm_config_groups");
  248. abort();
  249. }
  250. /* Returns number of config groups on success, -errno on error */
  251. static int qemu_config_foreach(FILE *fp, QEMUConfigCB *cb, void *opaque,
  252. const char *fname, Error **errp)
  253. {
  254. ERRP_GUARD();
  255. char line[1024], prev_group[64], group[64], arg[64], value[1024];
  256. Location loc;
  257. QDict *qdict = NULL;
  258. int res = -EINVAL, lno = 0;
  259. int count = 0;
  260. loc_push_none(&loc);
  261. while (fgets(line, sizeof(line), fp) != NULL) {
  262. ++lno;
  263. if (line[0] == '\n') {
  264. /* skip empty lines */
  265. continue;
  266. }
  267. if (line[0] == '#') {
  268. /* comment */
  269. continue;
  270. }
  271. if (line[0] == '[') {
  272. QDict *prev = qdict;
  273. if (sscanf(line, "[%63s \"%63[^\"]\"]", group, value) == 2) {
  274. qdict = qdict_new();
  275. qdict_put_str(qdict, "id", value);
  276. count++;
  277. } else if (sscanf(line, "[%63[^]]]", group) == 1) {
  278. qdict = qdict_new();
  279. count++;
  280. }
  281. if (qdict != prev) {
  282. if (prev) {
  283. cb(prev_group, prev, opaque, errp);
  284. qobject_unref(prev);
  285. if (*errp) {
  286. goto out;
  287. }
  288. }
  289. strcpy(prev_group, group);
  290. continue;
  291. }
  292. }
  293. loc_set_file(fname, lno);
  294. value[0] = '\0';
  295. if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2 ||
  296. sscanf(line, " %63s = \"\"", arg) == 1) {
  297. /* arg = value */
  298. if (qdict == NULL) {
  299. error_setg(errp, "no group defined");
  300. goto out;
  301. }
  302. qdict_put_str(qdict, arg, value);
  303. continue;
  304. }
  305. error_setg(errp, "parse error");
  306. goto out;
  307. }
  308. if (ferror(fp)) {
  309. loc_pop(&loc);
  310. error_setg_errno(errp, errno, "Cannot read config file");
  311. goto out_no_loc;
  312. }
  313. res = count;
  314. if (qdict) {
  315. cb(group, qdict, opaque, errp);
  316. }
  317. out:
  318. loc_pop(&loc);
  319. out_no_loc:
  320. qobject_unref(qdict);
  321. return res;
  322. }
  323. void qemu_config_do_parse(const char *group, QDict *qdict, void *opaque, Error **errp)
  324. {
  325. QemuOptsList **lists = opaque;
  326. QemuOptsList *list;
  327. list = find_list(lists, group, errp);
  328. if (!list) {
  329. return;
  330. }
  331. qemu_opts_from_qdict(list, qdict, errp);
  332. }
  333. int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp)
  334. {
  335. return qemu_config_foreach(fp, qemu_config_do_parse, lists, fname, errp);
  336. }
  337. int qemu_read_config_file(const char *filename, QEMUConfigCB *cb, Error **errp)
  338. {
  339. FILE *f = fopen(filename, "r");
  340. int ret;
  341. if (f == NULL) {
  342. error_setg_file_open(errp, errno, filename);
  343. return -errno;
  344. }
  345. ret = qemu_config_foreach(f, cb, vm_config_groups, filename, errp);
  346. fclose(f);
  347. return ret;
  348. }
  349. static bool config_parse_qdict_section(QDict *options, QemuOptsList *opts,
  350. Error **errp)
  351. {
  352. QemuOpts *subopts;
  353. g_autoptr(QDict) subqdict = NULL;
  354. g_autoptr(QList) list = NULL;
  355. size_t orig_size, enum_size;
  356. char *prefix;
  357. prefix = g_strdup_printf("%s.", opts->name);
  358. qdict_extract_subqdict(options, &subqdict, prefix);
  359. g_free(prefix);
  360. orig_size = qdict_size(subqdict);
  361. if (!orig_size) {
  362. return true;
  363. }
  364. subopts = qemu_opts_create(opts, NULL, 0, errp);
  365. if (!subopts) {
  366. return false;
  367. }
  368. if (!qemu_opts_absorb_qdict(subopts, subqdict, errp)) {
  369. return false;
  370. }
  371. enum_size = qdict_size(subqdict);
  372. if (enum_size < orig_size && enum_size) {
  373. error_setg(errp, "Unknown option '%s' for [%s]",
  374. qdict_first(subqdict)->key, opts->name);
  375. return false;
  376. }
  377. if (enum_size) {
  378. /* Multiple, enumerated sections */
  379. QListEntry *list_entry;
  380. unsigned i = 0;
  381. /* Not required anymore */
  382. qemu_opts_del(subopts);
  383. qdict_array_split(subqdict, &list);
  384. if (qdict_size(subqdict)) {
  385. error_setg(errp, "Unused option '%s' for [%s]",
  386. qdict_first(subqdict)->key, opts->name);
  387. return false;
  388. }
  389. QLIST_FOREACH_ENTRY(list, list_entry) {
  390. QDict *section = qobject_to(QDict, qlist_entry_obj(list_entry));
  391. char *opt_name;
  392. if (!section) {
  393. error_setg(errp, "[%s] section (index %u) does not consist of "
  394. "keys", opts->name, i);
  395. return false;
  396. }
  397. opt_name = g_strdup_printf("%s.%u", opts->name, i++);
  398. subopts = qemu_opts_create(opts, opt_name, 1, errp);
  399. g_free(opt_name);
  400. if (!subopts) {
  401. return false;
  402. }
  403. if (!qemu_opts_absorb_qdict(subopts, section, errp)) {
  404. qemu_opts_del(subopts);
  405. return false;
  406. }
  407. if (qdict_size(section)) {
  408. error_setg(errp, "[%s] section doesn't support the option '%s'",
  409. opts->name, qdict_first(section)->key);
  410. qemu_opts_del(subopts);
  411. return false;
  412. }
  413. }
  414. }
  415. return true;
  416. }
  417. bool qemu_config_parse_qdict(QDict *options, QemuOptsList **lists,
  418. Error **errp)
  419. {
  420. int i;
  421. for (i = 0; lists[i]; i++) {
  422. if (!config_parse_qdict_section(options, lists[i], errp)) {
  423. return false;
  424. }
  425. }
  426. return true;
  427. }