qemu-config.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  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/qerror.h"
  6. #include "qapi/qmp/qdict.h"
  7. #include "qapi/qmp/qlist.h"
  8. #include "qemu/error-report.h"
  9. #include "qemu/option.h"
  10. #include "qemu/config-file.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. /* restore machine options that are now machine's properties */
  125. static QemuOptsList machine_opts = {
  126. .merge_lists = true,
  127. .head = QTAILQ_HEAD_INITIALIZER(machine_opts.head),
  128. .desc = {
  129. {
  130. .name = "type",
  131. .type = QEMU_OPT_STRING,
  132. .help = "emulated machine"
  133. },{
  134. .name = "accel",
  135. .type = QEMU_OPT_STRING,
  136. .help = "accelerator list",
  137. },{
  138. .name = "kernel_irqchip",
  139. .type = QEMU_OPT_BOOL,
  140. .help = "use KVM in-kernel irqchip",
  141. },{
  142. .name = "kvm_shadow_mem",
  143. .type = QEMU_OPT_SIZE,
  144. .help = "KVM shadow MMU size",
  145. },{
  146. .name = "kernel",
  147. .type = QEMU_OPT_STRING,
  148. .help = "Linux kernel image file",
  149. },{
  150. .name = "initrd",
  151. .type = QEMU_OPT_STRING,
  152. .help = "Linux initial ramdisk file",
  153. },{
  154. .name = "append",
  155. .type = QEMU_OPT_STRING,
  156. .help = "Linux kernel command line",
  157. },{
  158. .name = "dtb",
  159. .type = QEMU_OPT_STRING,
  160. .help = "Linux kernel device tree file",
  161. },{
  162. .name = "dumpdtb",
  163. .type = QEMU_OPT_STRING,
  164. .help = "Dump current dtb to a file and quit",
  165. },{
  166. .name = "phandle_start",
  167. .type = QEMU_OPT_NUMBER,
  168. .help = "The first phandle ID we may generate dynamically",
  169. },{
  170. .name = "dt_compatible",
  171. .type = QEMU_OPT_STRING,
  172. .help = "Overrides the \"compatible\" property of the dt root node",
  173. },{
  174. .name = "dump-guest-core",
  175. .type = QEMU_OPT_BOOL,
  176. .help = "Include guest memory in a core dump",
  177. },{
  178. .name = "mem-merge",
  179. .type = QEMU_OPT_BOOL,
  180. .help = "enable/disable memory merge support",
  181. },{
  182. .name = "usb",
  183. .type = QEMU_OPT_BOOL,
  184. .help = "Set on/off to enable/disable usb",
  185. },{
  186. .name = "firmware",
  187. .type = QEMU_OPT_STRING,
  188. .help = "firmware image",
  189. },{
  190. .name = "iommu",
  191. .type = QEMU_OPT_BOOL,
  192. .help = "Set on/off to enable/disable Intel IOMMU (VT-d)",
  193. },{
  194. .name = "suppress-vmdesc",
  195. .type = QEMU_OPT_BOOL,
  196. .help = "Set on to disable self-describing migration",
  197. },{
  198. .name = "aes-key-wrap",
  199. .type = QEMU_OPT_BOOL,
  200. .help = "enable/disable AES key wrapping using the CPACF wrapping key",
  201. },{
  202. .name = "dea-key-wrap",
  203. .type = QEMU_OPT_BOOL,
  204. .help = "enable/disable DEA key wrapping using the CPACF wrapping key",
  205. },{
  206. .name = "loadparm",
  207. .type = QEMU_OPT_STRING,
  208. .help = "Up to 8 chars in set of [A-Za-z0-9. ](lower case chars"
  209. " converted to upper case) to pass to machine"
  210. " loader, boot manager, and guest kernel",
  211. },
  212. { /* End of list */ }
  213. }
  214. };
  215. CommandLineOptionInfoList *qmp_query_command_line_options(const char *option,
  216. Error **errp)
  217. {
  218. CommandLineOptionInfoList *conf_list = NULL;
  219. CommandLineOptionInfo *info;
  220. int i;
  221. for (i = 0; vm_config_groups[i] != NULL; i++) {
  222. if (!option || !strcmp(option, vm_config_groups[i]->name)) {
  223. info = g_malloc0(sizeof(*info));
  224. info->option = g_strdup(vm_config_groups[i]->name);
  225. if (!strcmp("drive", vm_config_groups[i]->name)) {
  226. info->parameters = get_drive_infolist();
  227. } else {
  228. info->parameters =
  229. query_option_descs(vm_config_groups[i]->desc);
  230. }
  231. QAPI_LIST_PREPEND(conf_list, info);
  232. }
  233. }
  234. if (!option || !strcmp(option, "machine")) {
  235. info = g_malloc0(sizeof(*info));
  236. info->option = g_strdup("machine");
  237. info->parameters = query_option_descs(machine_opts.desc);
  238. QAPI_LIST_PREPEND(conf_list, info);
  239. }
  240. if (conf_list == NULL) {
  241. error_setg(errp, "invalid option name: %s", option);
  242. }
  243. return conf_list;
  244. }
  245. QemuOptsList *qemu_find_opts_err(const char *group, Error **errp)
  246. {
  247. return find_list(vm_config_groups, group, errp);
  248. }
  249. void qemu_add_drive_opts(QemuOptsList *list)
  250. {
  251. int entries, i;
  252. entries = ARRAY_SIZE(drive_config_groups);
  253. entries--; /* keep list NULL terminated */
  254. for (i = 0; i < entries; i++) {
  255. if (drive_config_groups[i] == NULL) {
  256. drive_config_groups[i] = list;
  257. return;
  258. }
  259. }
  260. fprintf(stderr, "ran out of space in drive_config_groups");
  261. abort();
  262. }
  263. void qemu_add_opts(QemuOptsList *list)
  264. {
  265. int entries, i;
  266. entries = ARRAY_SIZE(vm_config_groups);
  267. entries--; /* keep list NULL terminated */
  268. for (i = 0; i < entries; i++) {
  269. if (vm_config_groups[i] == NULL) {
  270. vm_config_groups[i] = list;
  271. return;
  272. }
  273. }
  274. fprintf(stderr, "ran out of space in vm_config_groups");
  275. abort();
  276. }
  277. /* Returns number of config groups on success, -errno on error */
  278. static int qemu_config_foreach(FILE *fp, QEMUConfigCB *cb, void *opaque,
  279. const char *fname, Error **errp)
  280. {
  281. char line[1024], prev_group[64], group[64], arg[64], value[1024];
  282. Location loc;
  283. Error *local_err = NULL;
  284. QDict *qdict = NULL;
  285. int res = -EINVAL, lno = 0;
  286. int count = 0;
  287. loc_push_none(&loc);
  288. while (fgets(line, sizeof(line), fp) != NULL) {
  289. ++lno;
  290. if (line[0] == '\n') {
  291. /* skip empty lines */
  292. continue;
  293. }
  294. if (line[0] == '#') {
  295. /* comment */
  296. continue;
  297. }
  298. if (line[0] == '[') {
  299. QDict *prev = qdict;
  300. if (sscanf(line, "[%63s \"%63[^\"]\"]", group, value) == 2) {
  301. qdict = qdict_new();
  302. qdict_put_str(qdict, "id", value);
  303. count++;
  304. } else if (sscanf(line, "[%63[^]]]", group) == 1) {
  305. qdict = qdict_new();
  306. count++;
  307. }
  308. if (qdict != prev) {
  309. if (prev) {
  310. cb(prev_group, prev, opaque, &local_err);
  311. qobject_unref(prev);
  312. if (local_err) {
  313. error_propagate(errp, local_err);
  314. goto out;
  315. }
  316. }
  317. strcpy(prev_group, group);
  318. continue;
  319. }
  320. }
  321. loc_set_file(fname, lno);
  322. value[0] = '\0';
  323. if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2 ||
  324. sscanf(line, " %63s = \"\"", arg) == 1) {
  325. /* arg = value */
  326. if (qdict == NULL) {
  327. error_setg(errp, "no group defined");
  328. goto out;
  329. }
  330. qdict_put_str(qdict, arg, value);
  331. continue;
  332. }
  333. error_setg(errp, "parse error");
  334. goto out;
  335. }
  336. if (ferror(fp)) {
  337. loc_pop(&loc);
  338. error_setg_errno(errp, errno, "Cannot read config file");
  339. goto out_no_loc;
  340. }
  341. res = count;
  342. if (qdict) {
  343. cb(group, qdict, opaque, errp);
  344. }
  345. out:
  346. loc_pop(&loc);
  347. out_no_loc:
  348. qobject_unref(qdict);
  349. return res;
  350. }
  351. void qemu_config_do_parse(const char *group, QDict *qdict, void *opaque, Error **errp)
  352. {
  353. QemuOptsList **lists = opaque;
  354. QemuOptsList *list;
  355. list = find_list(lists, group, errp);
  356. if (!list) {
  357. return;
  358. }
  359. qemu_opts_from_qdict(list, qdict, errp);
  360. }
  361. int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp)
  362. {
  363. return qemu_config_foreach(fp, qemu_config_do_parse, lists, fname, errp);
  364. }
  365. int qemu_read_config_file(const char *filename, QEMUConfigCB *cb, Error **errp)
  366. {
  367. FILE *f = fopen(filename, "r");
  368. int ret;
  369. if (f == NULL) {
  370. error_setg_file_open(errp, errno, filename);
  371. return -errno;
  372. }
  373. ret = qemu_config_foreach(f, cb, vm_config_groups, filename, errp);
  374. fclose(f);
  375. return ret;
  376. }
  377. static void config_parse_qdict_section(QDict *options, QemuOptsList *opts,
  378. Error **errp)
  379. {
  380. QemuOpts *subopts;
  381. QDict *subqdict;
  382. QList *list = NULL;
  383. size_t orig_size, enum_size;
  384. char *prefix;
  385. prefix = g_strdup_printf("%s.", opts->name);
  386. qdict_extract_subqdict(options, &subqdict, prefix);
  387. g_free(prefix);
  388. orig_size = qdict_size(subqdict);
  389. if (!orig_size) {
  390. goto out;
  391. }
  392. subopts = qemu_opts_create(opts, NULL, 0, errp);
  393. if (!subopts) {
  394. goto out;
  395. }
  396. if (!qemu_opts_absorb_qdict(subopts, subqdict, errp)) {
  397. goto out;
  398. }
  399. enum_size = qdict_size(subqdict);
  400. if (enum_size < orig_size && enum_size) {
  401. error_setg(errp, "Unknown option '%s' for [%s]",
  402. qdict_first(subqdict)->key, opts->name);
  403. goto out;
  404. }
  405. if (enum_size) {
  406. /* Multiple, enumerated sections */
  407. QListEntry *list_entry;
  408. unsigned i = 0;
  409. /* Not required anymore */
  410. qemu_opts_del(subopts);
  411. qdict_array_split(subqdict, &list);
  412. if (qdict_size(subqdict)) {
  413. error_setg(errp, "Unused option '%s' for [%s]",
  414. qdict_first(subqdict)->key, opts->name);
  415. goto out;
  416. }
  417. QLIST_FOREACH_ENTRY(list, list_entry) {
  418. QDict *section = qobject_to(QDict, qlist_entry_obj(list_entry));
  419. char *opt_name;
  420. if (!section) {
  421. error_setg(errp, "[%s] section (index %u) does not consist of "
  422. "keys", opts->name, i);
  423. goto out;
  424. }
  425. opt_name = g_strdup_printf("%s.%u", opts->name, i++);
  426. subopts = qemu_opts_create(opts, opt_name, 1, errp);
  427. g_free(opt_name);
  428. if (!subopts) {
  429. goto out;
  430. }
  431. if (!qemu_opts_absorb_qdict(subopts, section, errp)) {
  432. qemu_opts_del(subopts);
  433. goto out;
  434. }
  435. if (qdict_size(section)) {
  436. error_setg(errp, "[%s] section doesn't support the option '%s'",
  437. opts->name, qdict_first(section)->key);
  438. qemu_opts_del(subopts);
  439. goto out;
  440. }
  441. }
  442. }
  443. out:
  444. qobject_unref(subqdict);
  445. qobject_unref(list);
  446. }
  447. void qemu_config_parse_qdict(QDict *options, QemuOptsList **lists,
  448. Error **errp)
  449. {
  450. int i;
  451. Error *local_err = NULL;
  452. for (i = 0; lists[i]; i++) {
  453. config_parse_qdict_section(options, lists[i], &local_err);
  454. if (local_err) {
  455. error_propagate(errp, local_err);
  456. return;
  457. }
  458. }
  459. }