]> Git Repo - qemu.git/blob - qemu-config.c
Merge remote-tracking branch 'stefanha/trivial-patches' into staging
[qemu.git] / qemu-config.c
1 #include "qemu-common.h"
2 #include "qemu-error.h"
3 #include "qemu-option.h"
4 #include "qemu-config.h"
5 #include "hw/qdev.h"
6
7 static QemuOptsList qemu_drive_opts = {
8     .name = "drive",
9     .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head),
10     .desc = {
11         {
12             .name = "bus",
13             .type = QEMU_OPT_NUMBER,
14             .help = "bus number",
15         },{
16             .name = "unit",
17             .type = QEMU_OPT_NUMBER,
18             .help = "unit number (i.e. lun for scsi)",
19         },{
20             .name = "if",
21             .type = QEMU_OPT_STRING,
22             .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
23         },{
24             .name = "index",
25             .type = QEMU_OPT_NUMBER,
26             .help = "index number",
27         },{
28             .name = "cyls",
29             .type = QEMU_OPT_NUMBER,
30             .help = "number of cylinders (ide disk geometry)",
31         },{
32             .name = "heads",
33             .type = QEMU_OPT_NUMBER,
34             .help = "number of heads (ide disk geometry)",
35         },{
36             .name = "secs",
37             .type = QEMU_OPT_NUMBER,
38             .help = "number of sectors (ide disk geometry)",
39         },{
40             .name = "trans",
41             .type = QEMU_OPT_STRING,
42             .help = "chs translation (auto, lba. none)",
43         },{
44             .name = "media",
45             .type = QEMU_OPT_STRING,
46             .help = "media type (disk, cdrom)",
47         },{
48             .name = "snapshot",
49             .type = QEMU_OPT_BOOL,
50             .help = "enable/disable snapshot mode",
51         },{
52             .name = "file",
53             .type = QEMU_OPT_STRING,
54             .help = "disk image",
55         },{
56             .name = "cache",
57             .type = QEMU_OPT_STRING,
58             .help = "host cache usage (none, writeback, writethrough, "
59                     "directsync, unsafe)",
60         },{
61             .name = "aio",
62             .type = QEMU_OPT_STRING,
63             .help = "host AIO implementation (threads, native)",
64         },{
65             .name = "format",
66             .type = QEMU_OPT_STRING,
67             .help = "disk format (raw, qcow2, ...)",
68         },{
69             .name = "serial",
70             .type = QEMU_OPT_STRING,
71             .help = "disk serial number",
72         },{
73             .name = "rerror",
74             .type = QEMU_OPT_STRING,
75             .help = "read error action",
76         },{
77             .name = "werror",
78             .type = QEMU_OPT_STRING,
79             .help = "write error action",
80         },{
81             .name = "addr",
82             .type = QEMU_OPT_STRING,
83             .help = "pci address (virtio only)",
84         },{
85             .name = "readonly",
86             .type = QEMU_OPT_BOOL,
87             .help = "open drive file as read-only",
88         },
89         { /* end of list */ }
90     },
91 };
92
93 static QemuOptsList qemu_chardev_opts = {
94     .name = "chardev",
95     .implied_opt_name = "backend",
96     .head = QTAILQ_HEAD_INITIALIZER(qemu_chardev_opts.head),
97     .desc = {
98         {
99             .name = "backend",
100             .type = QEMU_OPT_STRING,
101         },{
102             .name = "path",
103             .type = QEMU_OPT_STRING,
104         },{
105             .name = "host",
106             .type = QEMU_OPT_STRING,
107         },{
108             .name = "port",
109             .type = QEMU_OPT_STRING,
110         },{
111             .name = "localaddr",
112             .type = QEMU_OPT_STRING,
113         },{
114             .name = "localport",
115             .type = QEMU_OPT_STRING,
116         },{
117             .name = "to",
118             .type = QEMU_OPT_NUMBER,
119         },{
120             .name = "ipv4",
121             .type = QEMU_OPT_BOOL,
122         },{
123             .name = "ipv6",
124             .type = QEMU_OPT_BOOL,
125         },{
126             .name = "wait",
127             .type = QEMU_OPT_BOOL,
128         },{
129             .name = "server",
130             .type = QEMU_OPT_BOOL,
131         },{
132             .name = "delay",
133             .type = QEMU_OPT_BOOL,
134         },{
135             .name = "telnet",
136             .type = QEMU_OPT_BOOL,
137         },{
138             .name = "width",
139             .type = QEMU_OPT_NUMBER,
140         },{
141             .name = "height",
142             .type = QEMU_OPT_NUMBER,
143         },{
144             .name = "cols",
145             .type = QEMU_OPT_NUMBER,
146         },{
147             .name = "rows",
148             .type = QEMU_OPT_NUMBER,
149         },{
150             .name = "mux",
151             .type = QEMU_OPT_BOOL,
152         },{
153             .name = "signal",
154             .type = QEMU_OPT_BOOL,
155         },{
156             .name = "name",
157             .type = QEMU_OPT_STRING,
158         },{
159             .name = "debug",
160             .type = QEMU_OPT_NUMBER,
161         },
162         { /* end of list */ }
163     },
164 };
165
166 QemuOptsList qemu_fsdev_opts = {
167     .name = "fsdev",
168     .implied_opt_name = "fsdriver",
169     .head = QTAILQ_HEAD_INITIALIZER(qemu_fsdev_opts.head),
170     .desc = {
171         {
172             .name = "fsdriver",
173             .type = QEMU_OPT_STRING,
174         }, {
175             .name = "path",
176             .type = QEMU_OPT_STRING,
177         }, {
178             .name = "security_model",
179             .type = QEMU_OPT_STRING,
180         }, {
181             .name = "writeout",
182             .type = QEMU_OPT_STRING,
183         }, {
184             .name = "readonly",
185             .type = QEMU_OPT_BOOL,
186         },
187
188         { /*End of list */ }
189     },
190 };
191
192 QemuOptsList qemu_virtfs_opts = {
193     .name = "virtfs",
194     .implied_opt_name = "fsdriver",
195     .head = QTAILQ_HEAD_INITIALIZER(qemu_virtfs_opts.head),
196     .desc = {
197         {
198             .name = "fsdriver",
199             .type = QEMU_OPT_STRING,
200         }, {
201             .name = "path",
202             .type = QEMU_OPT_STRING,
203         }, {
204             .name = "mount_tag",
205             .type = QEMU_OPT_STRING,
206         }, {
207             .name = "security_model",
208             .type = QEMU_OPT_STRING,
209         }, {
210             .name = "writeout",
211             .type = QEMU_OPT_STRING,
212         }, {
213             .name = "readonly",
214             .type = QEMU_OPT_BOOL,
215         },
216
217         { /*End of list */ }
218     },
219 };
220
221 static QemuOptsList qemu_device_opts = {
222     .name = "device",
223     .implied_opt_name = "driver",
224     .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
225     .desc = {
226         /*
227          * no elements => accept any
228          * sanity checking will happen later
229          * when setting device properties
230          */
231         { /* end of list */ }
232     },
233 };
234
235 static QemuOptsList qemu_netdev_opts = {
236     .name = "netdev",
237     .implied_opt_name = "type",
238     .head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head),
239     .desc = {
240         /*
241          * no elements => accept any params
242          * validation will happen later
243          */
244         { /* end of list */ }
245     },
246 };
247
248 static QemuOptsList qemu_net_opts = {
249     .name = "net",
250     .implied_opt_name = "type",
251     .head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head),
252     .desc = {
253         /*
254          * no elements => accept any params
255          * validation will happen later
256          */
257         { /* end of list */ }
258     },
259 };
260
261 static QemuOptsList qemu_rtc_opts = {
262     .name = "rtc",
263     .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head),
264     .desc = {
265         {
266             .name = "base",
267             .type = QEMU_OPT_STRING,
268         },{
269             .name = "clock",
270             .type = QEMU_OPT_STRING,
271         },{
272             .name = "driftfix",
273             .type = QEMU_OPT_STRING,
274         },
275         { /* end of list */ }
276     },
277 };
278
279 static QemuOptsList qemu_global_opts = {
280     .name = "global",
281     .head = QTAILQ_HEAD_INITIALIZER(qemu_global_opts.head),
282     .desc = {
283         {
284             .name = "driver",
285             .type = QEMU_OPT_STRING,
286         },{
287             .name = "property",
288             .type = QEMU_OPT_STRING,
289         },{
290             .name = "value",
291             .type = QEMU_OPT_STRING,
292         },
293         { /* end of list */ }
294     },
295 };
296
297 static QemuOptsList qemu_mon_opts = {
298     .name = "mon",
299     .implied_opt_name = "chardev",
300     .head = QTAILQ_HEAD_INITIALIZER(qemu_mon_opts.head),
301     .desc = {
302         {
303             .name = "mode",
304             .type = QEMU_OPT_STRING,
305         },{
306             .name = "chardev",
307             .type = QEMU_OPT_STRING,
308         },{
309             .name = "default",
310             .type = QEMU_OPT_BOOL,
311         },{
312             .name = "pretty",
313             .type = QEMU_OPT_BOOL,
314         },
315         { /* end of list */ }
316     },
317 };
318
319 static QemuOptsList qemu_trace_opts = {
320     .name = "trace",
321     .implied_opt_name = "trace",
322     .head = QTAILQ_HEAD_INITIALIZER(qemu_trace_opts.head),
323     .desc = {
324         {
325             .name = "events",
326             .type = QEMU_OPT_STRING,
327         },{
328             .name = "file",
329             .type = QEMU_OPT_STRING,
330         },
331         { /* end of list */ }
332     },
333 };
334
335 static QemuOptsList qemu_cpudef_opts = {
336     .name = "cpudef",
337     .head = QTAILQ_HEAD_INITIALIZER(qemu_cpudef_opts.head),
338     .desc = {
339         {
340             .name = "name",
341             .type = QEMU_OPT_STRING,
342         },{
343             .name = "level",
344             .type = QEMU_OPT_NUMBER,
345         },{
346             .name = "vendor",
347             .type = QEMU_OPT_STRING,
348         },{
349             .name = "family",
350             .type = QEMU_OPT_NUMBER,
351         },{
352             .name = "model",
353             .type = QEMU_OPT_NUMBER,
354         },{
355             .name = "stepping",
356             .type = QEMU_OPT_NUMBER,
357         },{
358             .name = "feature_edx",      /* cpuid 0000_0001.edx */
359             .type = QEMU_OPT_STRING,
360         },{
361             .name = "feature_ecx",      /* cpuid 0000_0001.ecx */
362             .type = QEMU_OPT_STRING,
363         },{
364             .name = "extfeature_edx",   /* cpuid 8000_0001.edx */
365             .type = QEMU_OPT_STRING,
366         },{
367             .name = "extfeature_ecx",   /* cpuid 8000_0001.ecx */
368             .type = QEMU_OPT_STRING,
369         },{
370             .name = "xlevel",
371             .type = QEMU_OPT_NUMBER,
372         },{
373             .name = "model_id",
374             .type = QEMU_OPT_STRING,
375         },{
376             .name = "vendor_override",
377             .type = QEMU_OPT_NUMBER,
378         },
379         { /* end of list */ }
380     },
381 };
382
383 QemuOptsList qemu_spice_opts = {
384     .name = "spice",
385     .head = QTAILQ_HEAD_INITIALIZER(qemu_spice_opts.head),
386     .desc = {
387         {
388             .name = "port",
389             .type = QEMU_OPT_NUMBER,
390         },{
391             .name = "tls-port",
392             .type = QEMU_OPT_NUMBER,
393         },{
394             .name = "addr",
395             .type = QEMU_OPT_STRING,
396         },{
397             .name = "ipv4",
398             .type = QEMU_OPT_BOOL,
399         },{
400             .name = "ipv6",
401             .type = QEMU_OPT_BOOL,
402         },{
403             .name = "password",
404             .type = QEMU_OPT_STRING,
405         },{
406             .name = "disable-ticketing",
407             .type = QEMU_OPT_BOOL,
408         },{
409             .name = "disable-copy-paste",
410             .type = QEMU_OPT_BOOL,
411         },{
412             .name = "sasl",
413             .type = QEMU_OPT_BOOL,
414         },{
415             .name = "x509-dir",
416             .type = QEMU_OPT_STRING,
417         },{
418             .name = "x509-key-file",
419             .type = QEMU_OPT_STRING,
420         },{
421             .name = "x509-key-password",
422             .type = QEMU_OPT_STRING,
423         },{
424             .name = "x509-cert-file",
425             .type = QEMU_OPT_STRING,
426         },{
427             .name = "x509-cacert-file",
428             .type = QEMU_OPT_STRING,
429         },{
430             .name = "x509-dh-key-file",
431             .type = QEMU_OPT_STRING,
432         },{
433             .name = "tls-ciphers",
434             .type = QEMU_OPT_STRING,
435         },{
436             .name = "tls-channel",
437             .type = QEMU_OPT_STRING,
438         },{
439             .name = "plaintext-channel",
440             .type = QEMU_OPT_STRING,
441         },{
442             .name = "image-compression",
443             .type = QEMU_OPT_STRING,
444         },{
445             .name = "jpeg-wan-compression",
446             .type = QEMU_OPT_STRING,
447         },{
448             .name = "zlib-glz-wan-compression",
449             .type = QEMU_OPT_STRING,
450         },{
451             .name = "streaming-video",
452             .type = QEMU_OPT_STRING,
453         },{
454             .name = "agent-mouse",
455             .type = QEMU_OPT_BOOL,
456         },{
457             .name = "playback-compression",
458             .type = QEMU_OPT_BOOL,
459         },
460         { /* end of list */ }
461     },
462 };
463
464 QemuOptsList qemu_option_rom_opts = {
465     .name = "option-rom",
466     .implied_opt_name = "romfile",
467     .head = QTAILQ_HEAD_INITIALIZER(qemu_option_rom_opts.head),
468     .desc = {
469         {
470             .name = "bootindex",
471             .type = QEMU_OPT_NUMBER,
472         }, {
473             .name = "romfile",
474             .type = QEMU_OPT_STRING,
475         },
476         { /* end of list */ }
477     },
478 };
479
480 static QemuOptsList qemu_machine_opts = {
481     .name = "machine",
482     .implied_opt_name = "type",
483     .head = QTAILQ_HEAD_INITIALIZER(qemu_machine_opts.head),
484     .desc = {
485         {
486             .name = "type",
487             .type = QEMU_OPT_STRING,
488             .help = "emulated machine"
489         }, {
490             .name = "accel",
491             .type = QEMU_OPT_STRING,
492             .help = "accelerator list",
493         },
494         { /* End of list */ }
495     },
496 };
497
498 QemuOptsList qemu_boot_opts = {
499     .name = "boot-opts",
500     .head = QTAILQ_HEAD_INITIALIZER(qemu_boot_opts.head),
501     .desc = {
502         /* the three names below are not used now */
503         {
504             .name = "order",
505             .type = QEMU_OPT_STRING,
506         }, {
507             .name = "once",
508             .type = QEMU_OPT_STRING,
509         }, {
510             .name = "menu",
511             .type = QEMU_OPT_STRING,
512         /* following are really used */
513         }, {
514             .name = "splash",
515             .type = QEMU_OPT_STRING,
516         }, {
517             .name = "splash-time",
518             .type = QEMU_OPT_STRING,
519         },
520         { /*End of list */ }
521     },
522 };
523
524 static QemuOptsList *vm_config_groups[32] = {
525     &qemu_drive_opts,
526     &qemu_chardev_opts,
527     &qemu_device_opts,
528     &qemu_netdev_opts,
529     &qemu_net_opts,
530     &qemu_rtc_opts,
531     &qemu_global_opts,
532     &qemu_mon_opts,
533     &qemu_cpudef_opts,
534     &qemu_trace_opts,
535     &qemu_option_rom_opts,
536     &qemu_machine_opts,
537     &qemu_boot_opts,
538     NULL,
539 };
540
541 static QemuOptsList *find_list(QemuOptsList **lists, const char *group)
542 {
543     int i;
544
545     for (i = 0; lists[i] != NULL; i++) {
546         if (strcmp(lists[i]->name, group) == 0)
547             break;
548     }
549     if (lists[i] == NULL) {
550         error_report("there is no option group \"%s\"", group);
551     }
552     return lists[i];
553 }
554
555 QemuOptsList *qemu_find_opts(const char *group)
556 {
557     return find_list(vm_config_groups, group);
558 }
559
560 void qemu_add_opts(QemuOptsList *list)
561 {
562     int entries, i;
563
564     entries = ARRAY_SIZE(vm_config_groups);
565     entries--; /* keep list NULL terminated */
566     for (i = 0; i < entries; i++) {
567         if (vm_config_groups[i] == NULL) {
568             vm_config_groups[i] = list;
569             return;
570         }
571     }
572     fprintf(stderr, "ran out of space in vm_config_groups");
573     abort();
574 }
575
576 int qemu_set_option(const char *str)
577 {
578     char group[64], id[64], arg[64];
579     QemuOptsList *list;
580     QemuOpts *opts;
581     int rc, offset;
582
583     rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset);
584     if (rc < 3 || str[offset] != '=') {
585         error_report("can't parse: \"%s\"", str);
586         return -1;
587     }
588
589     list = qemu_find_opts(group);
590     if (list == NULL) {
591         return -1;
592     }
593
594     opts = qemu_opts_find(list, id);
595     if (!opts) {
596         error_report("there is no %s \"%s\" defined",
597                      list->name, id);
598         return -1;
599     }
600
601     if (qemu_opt_set(opts, arg, str+offset+1) == -1) {
602         return -1;
603     }
604     return 0;
605 }
606
607 int qemu_global_option(const char *str)
608 {
609     char driver[64], property[64];
610     QemuOpts *opts;
611     int rc, offset;
612
613     rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
614     if (rc < 2 || str[offset] != '=') {
615         error_report("can't parse: \"%s\"", str);
616         return -1;
617     }
618
619     opts = qemu_opts_create(&qemu_global_opts, NULL, 0);
620     qemu_opt_set(opts, "driver", driver);
621     qemu_opt_set(opts, "property", property);
622     qemu_opt_set(opts, "value", str+offset+1);
623     return 0;
624 }
625
626 struct ConfigWriteData {
627     QemuOptsList *list;
628     FILE *fp;
629 };
630
631 static int config_write_opt(const char *name, const char *value, void *opaque)
632 {
633     struct ConfigWriteData *data = opaque;
634
635     fprintf(data->fp, "  %s = \"%s\"\n", name, value);
636     return 0;
637 }
638
639 static int config_write_opts(QemuOpts *opts, void *opaque)
640 {
641     struct ConfigWriteData *data = opaque;
642     const char *id = qemu_opts_id(opts);
643
644     if (id) {
645         fprintf(data->fp, "[%s \"%s\"]\n", data->list->name, id);
646     } else {
647         fprintf(data->fp, "[%s]\n", data->list->name);
648     }
649     qemu_opt_foreach(opts, config_write_opt, data, 0);
650     fprintf(data->fp, "\n");
651     return 0;
652 }
653
654 void qemu_config_write(FILE *fp)
655 {
656     struct ConfigWriteData data = { .fp = fp };
657     QemuOptsList **lists = vm_config_groups;
658     int i;
659
660     fprintf(fp, "# qemu config file\n\n");
661     for (i = 0; lists[i] != NULL; i++) {
662         data.list = lists[i];
663         qemu_opts_foreach(data.list, config_write_opts, &data, 0);
664     }
665 }
666
667 int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
668 {
669     char line[1024], group[64], id[64], arg[64], value[1024];
670     Location loc;
671     QemuOptsList *list = NULL;
672     QemuOpts *opts = NULL;
673     int res = -1, lno = 0;
674
675     loc_push_none(&loc);
676     while (fgets(line, sizeof(line), fp) != NULL) {
677         loc_set_file(fname, ++lno);
678         if (line[0] == '\n') {
679             /* skip empty lines */
680             continue;
681         }
682         if (line[0] == '#') {
683             /* comment */
684             continue;
685         }
686         if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
687             /* group with id */
688             list = find_list(lists, group);
689             if (list == NULL)
690                 goto out;
691             opts = qemu_opts_create(list, id, 1);
692             continue;
693         }
694         if (sscanf(line, "[%63[^]]]", group) == 1) {
695             /* group without id */
696             list = find_list(lists, group);
697             if (list == NULL)
698                 goto out;
699             opts = qemu_opts_create(list, NULL, 0);
700             continue;
701         }
702         if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
703             /* arg = value */
704             if (opts == NULL) {
705                 error_report("no group defined");
706                 goto out;
707             }
708             if (qemu_opt_set(opts, arg, value) != 0) {
709                 goto out;
710             }
711             continue;
712         }
713         error_report("parse error");
714         goto out;
715     }
716     if (ferror(fp)) {
717         error_report("error reading file");
718         goto out;
719     }
720     res = 0;
721 out:
722     loc_pop(&loc);
723     return res;
724 }
725
726 int qemu_read_config_file(const char *filename)
727 {
728     FILE *f = fopen(filename, "r");
729     int ret;
730
731     if (f == NULL) {
732         return -errno;
733     }
734
735     ret = qemu_config_parse(f, vm_config_groups, filename);
736     fclose(f);
737
738     if (ret == 0) {
739         return 0;
740     } else {
741         return -EINVAL;
742     }
743 }
This page took 0.066964 seconds and 4 git commands to generate.