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