qemu-config.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  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. static QemuOptsList *vm_config_groups[48];
  11. static QemuOptsList *drive_config_groups[5];
  12. static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
  13. Error **errp)
  14. {
  15. int i;
  16. for (i = 0; lists[i] != NULL; i++) {
  17. if (strcmp(lists[i]->name, group) == 0)
  18. break;
  19. }
  20. if (lists[i] == NULL) {
  21. error_setg(errp, "There is no option group '%s'", group);
  22. }
  23. return lists[i];
  24. }
  25. QemuOptsList *qemu_find_opts(const char *group)
  26. {
  27. QemuOptsList *ret;
  28. Error *local_err = NULL;
  29. ret = find_list(vm_config_groups, group, &local_err);
  30. if (local_err) {
  31. error_report_err(local_err);
  32. }
  33. return ret;
  34. }
  35. QemuOpts *qemu_find_opts_singleton(const char *group)
  36. {
  37. QemuOptsList *list;
  38. QemuOpts *opts;
  39. list = qemu_find_opts(group);
  40. assert(list);
  41. opts = qemu_opts_find(list, NULL);
  42. if (!opts) {
  43. opts = qemu_opts_create(list, NULL, 0, &error_abort);
  44. }
  45. return opts;
  46. }
  47. static CommandLineParameterInfoList *query_option_descs(const QemuOptDesc *desc)
  48. {
  49. CommandLineParameterInfoList *param_list = NULL, *entry;
  50. CommandLineParameterInfo *info;
  51. int i;
  52. for (i = 0; desc[i].name != NULL; i++) {
  53. info = g_malloc0(sizeof(*info));
  54. info->name = g_strdup(desc[i].name);
  55. switch (desc[i].type) {
  56. case QEMU_OPT_STRING:
  57. info->type = COMMAND_LINE_PARAMETER_TYPE_STRING;
  58. break;
  59. case QEMU_OPT_BOOL:
  60. info->type = COMMAND_LINE_PARAMETER_TYPE_BOOLEAN;
  61. break;
  62. case QEMU_OPT_NUMBER:
  63. info->type = COMMAND_LINE_PARAMETER_TYPE_NUMBER;
  64. break;
  65. case QEMU_OPT_SIZE:
  66. info->type = COMMAND_LINE_PARAMETER_TYPE_SIZE;
  67. break;
  68. }
  69. if (desc[i].help) {
  70. info->has_help = true;
  71. info->help = g_strdup(desc[i].help);
  72. }
  73. if (desc[i].def_value_str) {
  74. info->has_q_default = true;
  75. info->q_default = g_strdup(desc[i].def_value_str);
  76. }
  77. entry = g_malloc0(sizeof(*entry));
  78. entry->value = info;
  79. entry->next = param_list;
  80. param_list = entry;
  81. }
  82. return param_list;
  83. }
  84. /* remove repeated entry from the info list */
  85. static void cleanup_infolist(CommandLineParameterInfoList *head)
  86. {
  87. CommandLineParameterInfoList *pre_entry, *cur, *del_entry;
  88. cur = head;
  89. while (cur->next) {
  90. pre_entry = head;
  91. while (pre_entry != cur->next) {
  92. if (!strcmp(pre_entry->value->name, cur->next->value->name)) {
  93. del_entry = cur->next;
  94. cur->next = cur->next->next;
  95. del_entry->next = NULL;
  96. qapi_free_CommandLineParameterInfoList(del_entry);
  97. break;
  98. }
  99. pre_entry = pre_entry->next;
  100. }
  101. cur = cur->next;
  102. }
  103. }
  104. /* merge the description items of two parameter infolists */
  105. static void connect_infolist(CommandLineParameterInfoList *head,
  106. CommandLineParameterInfoList *new)
  107. {
  108. CommandLineParameterInfoList *cur;
  109. cur = head;
  110. while (cur->next) {
  111. cur = cur->next;
  112. }
  113. cur->next = new;
  114. }
  115. /* access all the local QemuOptsLists for drive option */
  116. static CommandLineParameterInfoList *get_drive_infolist(void)
  117. {
  118. CommandLineParameterInfoList *head = NULL, *cur;
  119. int i;
  120. for (i = 0; drive_config_groups[i] != NULL; i++) {
  121. if (!head) {
  122. head = query_option_descs(drive_config_groups[i]->desc);
  123. } else {
  124. cur = query_option_descs(drive_config_groups[i]->desc);
  125. connect_infolist(head, cur);
  126. }
  127. }
  128. cleanup_infolist(head);
  129. return head;
  130. }
  131. /* restore machine options that are now machine's properties */
  132. static QemuOptsList machine_opts = {
  133. .merge_lists = true,
  134. .head = QTAILQ_HEAD_INITIALIZER(machine_opts.head),
  135. .desc = {
  136. {
  137. .name = "type",
  138. .type = QEMU_OPT_STRING,
  139. .help = "emulated machine"
  140. },{
  141. .name = "accel",
  142. .type = QEMU_OPT_STRING,
  143. .help = "accelerator list",
  144. },{
  145. .name = "kernel_irqchip",
  146. .type = QEMU_OPT_BOOL,
  147. .help = "use KVM in-kernel irqchip",
  148. },{
  149. .name = "kvm_shadow_mem",
  150. .type = QEMU_OPT_SIZE,
  151. .help = "KVM shadow MMU size",
  152. },{
  153. .name = "kernel",
  154. .type = QEMU_OPT_STRING,
  155. .help = "Linux kernel image file",
  156. },{
  157. .name = "initrd",
  158. .type = QEMU_OPT_STRING,
  159. .help = "Linux initial ramdisk file",
  160. },{
  161. .name = "append",
  162. .type = QEMU_OPT_STRING,
  163. .help = "Linux kernel command line",
  164. },{
  165. .name = "dtb",
  166. .type = QEMU_OPT_STRING,
  167. .help = "Linux kernel device tree file",
  168. },{
  169. .name = "dumpdtb",
  170. .type = QEMU_OPT_STRING,
  171. .help = "Dump current dtb to a file and quit",
  172. },{
  173. .name = "phandle_start",
  174. .type = QEMU_OPT_NUMBER,
  175. .help = "The first phandle ID we may generate dynamically",
  176. },{
  177. .name = "dt_compatible",
  178. .type = QEMU_OPT_STRING,
  179. .help = "Overrides the \"compatible\" property of the dt root node",
  180. },{
  181. .name = "dump-guest-core",
  182. .type = QEMU_OPT_BOOL,
  183. .help = "Include guest memory in a core dump",
  184. },{
  185. .name = "mem-merge",
  186. .type = QEMU_OPT_BOOL,
  187. .help = "enable/disable memory merge support",
  188. },{
  189. .name = "usb",
  190. .type = QEMU_OPT_BOOL,
  191. .help = "Set on/off to enable/disable usb",
  192. },{
  193. .name = "firmware",
  194. .type = QEMU_OPT_STRING,
  195. .help = "firmware image",
  196. },{
  197. .name = "iommu",
  198. .type = QEMU_OPT_BOOL,
  199. .help = "Set on/off to enable/disable Intel IOMMU (VT-d)",
  200. },{
  201. .name = "suppress-vmdesc",
  202. .type = QEMU_OPT_BOOL,
  203. .help = "Set on to disable self-describing migration",
  204. },{
  205. .name = "aes-key-wrap",
  206. .type = QEMU_OPT_BOOL,
  207. .help = "enable/disable AES key wrapping using the CPACF wrapping key",
  208. },{
  209. .name = "dea-key-wrap",
  210. .type = QEMU_OPT_BOOL,
  211. .help = "enable/disable DEA key wrapping using the CPACF wrapping key",
  212. },{
  213. .name = "loadparm",
  214. .type = QEMU_OPT_STRING,
  215. .help = "Up to 8 chars in set of [A-Za-z0-9. ](lower case chars"
  216. " converted to upper case) to pass to machine"
  217. " loader, boot manager, and guest kernel",
  218. },
  219. { /* End of list */ }
  220. }
  221. };
  222. CommandLineOptionInfoList *qmp_query_command_line_options(bool has_option,
  223. const char *option,
  224. Error **errp)
  225. {
  226. CommandLineOptionInfoList *conf_list = NULL, *entry;
  227. CommandLineOptionInfo *info;
  228. int i;
  229. for (i = 0; vm_config_groups[i] != NULL; i++) {
  230. if (!has_option || !strcmp(option, vm_config_groups[i]->name)) {
  231. info = g_malloc0(sizeof(*info));
  232. info->option = g_strdup(vm_config_groups[i]->name);
  233. if (!strcmp("drive", vm_config_groups[i]->name)) {
  234. info->parameters = get_drive_infolist();
  235. } else if (!strcmp("machine", vm_config_groups[i]->name)) {
  236. info->parameters = query_option_descs(machine_opts.desc);
  237. } else {
  238. info->parameters =
  239. query_option_descs(vm_config_groups[i]->desc);
  240. }
  241. entry = g_malloc0(sizeof(*entry));
  242. entry->value = info;
  243. entry->next = conf_list;
  244. conf_list = entry;
  245. }
  246. }
  247. if (conf_list == NULL) {
  248. error_setg(errp, "invalid option name: %s", option);
  249. }
  250. return conf_list;
  251. }
  252. QemuOptsList *qemu_find_opts_err(const char *group, Error **errp)
  253. {
  254. return find_list(vm_config_groups, group, errp);
  255. }
  256. void qemu_add_drive_opts(QemuOptsList *list)
  257. {
  258. int entries, i;
  259. entries = ARRAY_SIZE(drive_config_groups);
  260. entries--; /* keep list NULL terminated */
  261. for (i = 0; i < entries; i++) {
  262. if (drive_config_groups[i] == NULL) {
  263. drive_config_groups[i] = list;
  264. return;
  265. }
  266. }
  267. fprintf(stderr, "ran out of space in drive_config_groups");
  268. abort();
  269. }
  270. void qemu_add_opts(QemuOptsList *list)
  271. {
  272. int entries, i;
  273. entries = ARRAY_SIZE(vm_config_groups);
  274. entries--; /* keep list NULL terminated */
  275. for (i = 0; i < entries; i++) {
  276. if (vm_config_groups[i] == NULL) {
  277. vm_config_groups[i] = list;
  278. return;
  279. }
  280. }
  281. fprintf(stderr, "ran out of space in vm_config_groups");
  282. abort();
  283. }
  284. int qemu_set_option(const char *str)
  285. {
  286. Error *local_err = NULL;
  287. char group[64], id[64], arg[64];
  288. QemuOptsList *list;
  289. QemuOpts *opts;
  290. int rc, offset;
  291. rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset);
  292. if (rc < 3 || str[offset] != '=') {
  293. error_report("can't parse: \"%s\"", str);
  294. return -1;
  295. }
  296. list = qemu_find_opts(group);
  297. if (list == NULL) {
  298. return -1;
  299. }
  300. opts = qemu_opts_find(list, id);
  301. if (!opts) {
  302. error_report("there is no %s \"%s\" defined",
  303. list->name, id);
  304. return -1;
  305. }
  306. qemu_opt_set(opts, arg, str + offset + 1, &local_err);
  307. if (local_err) {
  308. error_report_err(local_err);
  309. return -1;
  310. }
  311. return 0;
  312. }
  313. struct ConfigWriteData {
  314. QemuOptsList *list;
  315. FILE *fp;
  316. };
  317. static int config_write_opt(void *opaque, const char *name, const char *value,
  318. Error **errp)
  319. {
  320. struct ConfigWriteData *data = opaque;
  321. fprintf(data->fp, " %s = \"%s\"\n", name, value);
  322. return 0;
  323. }
  324. static int config_write_opts(void *opaque, QemuOpts *opts, Error **errp)
  325. {
  326. struct ConfigWriteData *data = opaque;
  327. const char *id = qemu_opts_id(opts);
  328. if (id) {
  329. fprintf(data->fp, "[%s \"%s\"]\n", data->list->name, id);
  330. } else {
  331. fprintf(data->fp, "[%s]\n", data->list->name);
  332. }
  333. qemu_opt_foreach(opts, config_write_opt, data, NULL);
  334. fprintf(data->fp, "\n");
  335. return 0;
  336. }
  337. void qemu_config_write(FILE *fp)
  338. {
  339. struct ConfigWriteData data = { .fp = fp };
  340. QemuOptsList **lists = vm_config_groups;
  341. int i;
  342. fprintf(fp, "# qemu config file\n\n");
  343. for (i = 0; lists[i] != NULL; i++) {
  344. data.list = lists[i];
  345. qemu_opts_foreach(data.list, config_write_opts, &data, NULL);
  346. }
  347. }
  348. /* Returns number of config groups on success, -errno on error */
  349. int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
  350. {
  351. char line[1024], group[64], id[64], arg[64], value[1024];
  352. Location loc;
  353. QemuOptsList *list = NULL;
  354. Error *local_err = NULL;
  355. QemuOpts *opts = NULL;
  356. int res = -EINVAL, lno = 0;
  357. int count = 0;
  358. loc_push_none(&loc);
  359. while (fgets(line, sizeof(line), fp) != NULL) {
  360. loc_set_file(fname, ++lno);
  361. if (line[0] == '\n') {
  362. /* skip empty lines */
  363. continue;
  364. }
  365. if (line[0] == '#') {
  366. /* comment */
  367. continue;
  368. }
  369. if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
  370. /* group with id */
  371. list = find_list(lists, group, &local_err);
  372. if (local_err) {
  373. error_report_err(local_err);
  374. goto out;
  375. }
  376. opts = qemu_opts_create(list, id, 1, NULL);
  377. count++;
  378. continue;
  379. }
  380. if (sscanf(line, "[%63[^]]]", group) == 1) {
  381. /* group without id */
  382. list = find_list(lists, group, &local_err);
  383. if (local_err) {
  384. error_report_err(local_err);
  385. goto out;
  386. }
  387. opts = qemu_opts_create(list, NULL, 0, &error_abort);
  388. count++;
  389. continue;
  390. }
  391. value[0] = '\0';
  392. if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2 ||
  393. sscanf(line, " %63s = \"\"", arg) == 1) {
  394. /* arg = value */
  395. if (opts == NULL) {
  396. error_report("no group defined");
  397. goto out;
  398. }
  399. qemu_opt_set(opts, arg, value, &local_err);
  400. if (local_err) {
  401. error_report_err(local_err);
  402. goto out;
  403. }
  404. continue;
  405. }
  406. error_report("parse error");
  407. goto out;
  408. }
  409. if (ferror(fp)) {
  410. error_report("error reading file");
  411. goto out;
  412. }
  413. res = count;
  414. out:
  415. loc_pop(&loc);
  416. return res;
  417. }
  418. int qemu_read_config_file(const char *filename)
  419. {
  420. FILE *f = fopen(filename, "r");
  421. int ret;
  422. if (f == NULL) {
  423. return -errno;
  424. }
  425. ret = qemu_config_parse(f, vm_config_groups, filename);
  426. fclose(f);
  427. return ret;
  428. }
  429. static void config_parse_qdict_section(QDict *options, QemuOptsList *opts,
  430. Error **errp)
  431. {
  432. QemuOpts *subopts;
  433. QDict *subqdict;
  434. QList *list = NULL;
  435. Error *local_err = NULL;
  436. size_t orig_size, enum_size;
  437. char *prefix;
  438. prefix = g_strdup_printf("%s.", opts->name);
  439. qdict_extract_subqdict(options, &subqdict, prefix);
  440. g_free(prefix);
  441. orig_size = qdict_size(subqdict);
  442. if (!orig_size) {
  443. goto out;
  444. }
  445. subopts = qemu_opts_create(opts, NULL, 0, &local_err);
  446. if (local_err) {
  447. error_propagate(errp, local_err);
  448. goto out;
  449. }
  450. qemu_opts_absorb_qdict(subopts, subqdict, &local_err);
  451. if (local_err) {
  452. error_propagate(errp, local_err);
  453. goto out;
  454. }
  455. enum_size = qdict_size(subqdict);
  456. if (enum_size < orig_size && enum_size) {
  457. error_setg(errp, "Unknown option '%s' for [%s]",
  458. qdict_first(subqdict)->key, opts->name);
  459. goto out;
  460. }
  461. if (enum_size) {
  462. /* Multiple, enumerated sections */
  463. QListEntry *list_entry;
  464. unsigned i = 0;
  465. /* Not required anymore */
  466. qemu_opts_del(subopts);
  467. qdict_array_split(subqdict, &list);
  468. if (qdict_size(subqdict)) {
  469. error_setg(errp, "Unused option '%s' for [%s]",
  470. qdict_first(subqdict)->key, opts->name);
  471. goto out;
  472. }
  473. QLIST_FOREACH_ENTRY(list, list_entry) {
  474. QDict *section = qobject_to(QDict, qlist_entry_obj(list_entry));
  475. char *opt_name;
  476. if (!section) {
  477. error_setg(errp, "[%s] section (index %u) does not consist of "
  478. "keys", opts->name, i);
  479. goto out;
  480. }
  481. opt_name = g_strdup_printf("%s.%u", opts->name, i++);
  482. subopts = qemu_opts_create(opts, opt_name, 1, &local_err);
  483. g_free(opt_name);
  484. if (local_err) {
  485. error_propagate(errp, local_err);
  486. goto out;
  487. }
  488. qemu_opts_absorb_qdict(subopts, section, &local_err);
  489. if (local_err) {
  490. error_propagate(errp, local_err);
  491. qemu_opts_del(subopts);
  492. goto out;
  493. }
  494. if (qdict_size(section)) {
  495. error_setg(errp, "[%s] section doesn't support the option '%s'",
  496. opts->name, qdict_first(section)->key);
  497. qemu_opts_del(subopts);
  498. goto out;
  499. }
  500. }
  501. }
  502. out:
  503. qobject_unref(subqdict);
  504. qobject_unref(list);
  505. }
  506. void qemu_config_parse_qdict(QDict *options, QemuOptsList **lists,
  507. Error **errp)
  508. {
  509. int i;
  510. Error *local_err = NULL;
  511. for (i = 0; lists[i]; i++) {
  512. config_parse_qdict_section(options, lists[i], &local_err);
  513. if (local_err) {
  514. error_propagate(errp, local_err);
  515. return;
  516. }
  517. }
  518. }