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