1 #include "qemu-common.h"
2 #include "qemu-error.h"
3 #include "qemu-option.h"
4 #include "qemu-config.h"
7 static QemuOptsList qemu_drive_opts
= {
9 .head
= QTAILQ_HEAD_INITIALIZER(qemu_drive_opts
.head
),
13 .type
= QEMU_OPT_NUMBER
,
17 .type
= QEMU_OPT_NUMBER
,
18 .help
= "unit number (i.e. lun for scsi)",
21 .type
= QEMU_OPT_STRING
,
22 .help
= "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
25 .type
= QEMU_OPT_NUMBER
,
26 .help
= "index number",
29 .type
= QEMU_OPT_NUMBER
,
30 .help
= "number of cylinders (ide disk geometry)",
33 .type
= QEMU_OPT_NUMBER
,
34 .help
= "number of heads (ide disk geometry)",
37 .type
= QEMU_OPT_NUMBER
,
38 .help
= "number of sectors (ide disk geometry)",
41 .type
= QEMU_OPT_STRING
,
42 .help
= "chs translation (auto, lba. none)",
45 .type
= QEMU_OPT_STRING
,
46 .help
= "media type (disk, cdrom)",
49 .type
= QEMU_OPT_BOOL
,
50 .help
= "enable/disable snapshot mode",
53 .type
= QEMU_OPT_STRING
,
57 .type
= QEMU_OPT_STRING
,
58 .help
= "host cache usage (none, writeback, writethrough, "
59 "directsync, unsafe)",
62 .type
= QEMU_OPT_STRING
,
63 .help
= "host AIO implementation (threads, native)",
66 .type
= QEMU_OPT_STRING
,
67 .help
= "disk format (raw, qcow2, ...)",
70 .type
= QEMU_OPT_STRING
,
71 .help
= "disk serial number",
74 .type
= QEMU_OPT_STRING
,
75 .help
= "read error action",
78 .type
= QEMU_OPT_STRING
,
79 .help
= "write error action",
82 .type
= QEMU_OPT_STRING
,
83 .help
= "pci address (virtio only)",
86 .type
= QEMU_OPT_BOOL
,
87 .help
= "open drive file as read-only",
90 .type
= QEMU_OPT_BOOL
,
91 .help
= "make this a boot drive",
97 static QemuOptsList qemu_chardev_opts
= {
99 .implied_opt_name
= "backend",
100 .head
= QTAILQ_HEAD_INITIALIZER(qemu_chardev_opts
.head
),
104 .type
= QEMU_OPT_STRING
,
107 .type
= QEMU_OPT_STRING
,
110 .type
= QEMU_OPT_STRING
,
113 .type
= QEMU_OPT_STRING
,
116 .type
= QEMU_OPT_STRING
,
119 .type
= QEMU_OPT_STRING
,
122 .type
= QEMU_OPT_NUMBER
,
125 .type
= QEMU_OPT_BOOL
,
128 .type
= QEMU_OPT_BOOL
,
131 .type
= QEMU_OPT_BOOL
,
134 .type
= QEMU_OPT_BOOL
,
137 .type
= QEMU_OPT_BOOL
,
140 .type
= QEMU_OPT_BOOL
,
143 .type
= QEMU_OPT_NUMBER
,
146 .type
= QEMU_OPT_NUMBER
,
149 .type
= QEMU_OPT_NUMBER
,
152 .type
= QEMU_OPT_NUMBER
,
155 .type
= QEMU_OPT_BOOL
,
158 .type
= QEMU_OPT_BOOL
,
161 .type
= QEMU_OPT_STRING
,
164 .type
= QEMU_OPT_NUMBER
,
166 { /* end of list */ }
170 QemuOptsList qemu_fsdev_opts
= {
172 .implied_opt_name
= "fstype",
173 .head
= QTAILQ_HEAD_INITIALIZER(qemu_fsdev_opts
.head
),
177 .type
= QEMU_OPT_STRING
,
180 .type
= QEMU_OPT_STRING
,
182 .name
= "security_model",
183 .type
= QEMU_OPT_STRING
,
189 QemuOptsList qemu_virtfs_opts
= {
191 .implied_opt_name
= "fstype",
192 .head
= QTAILQ_HEAD_INITIALIZER(qemu_virtfs_opts
.head
),
196 .type
= QEMU_OPT_STRING
,
199 .type
= QEMU_OPT_STRING
,
202 .type
= QEMU_OPT_STRING
,
204 .name
= "security_model",
205 .type
= QEMU_OPT_STRING
,
212 static QemuOptsList qemu_device_opts
= {
214 .implied_opt_name
= "driver",
215 .head
= QTAILQ_HEAD_INITIALIZER(qemu_device_opts
.head
),
218 * no elements => accept any
219 * sanity checking will happen later
220 * when setting device properties
222 { /* end of list */ }
226 static QemuOptsList qemu_netdev_opts
= {
228 .implied_opt_name
= "type",
229 .head
= QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts
.head
),
232 * no elements => accept any params
233 * validation will happen later
235 { /* end of list */ }
239 static QemuOptsList qemu_net_opts
= {
241 .implied_opt_name
= "type",
242 .head
= QTAILQ_HEAD_INITIALIZER(qemu_net_opts
.head
),
245 * no elements => accept any params
246 * validation will happen later
248 { /* end of list */ }
252 static QemuOptsList qemu_rtc_opts
= {
254 .head
= QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts
.head
),
258 .type
= QEMU_OPT_STRING
,
261 .type
= QEMU_OPT_STRING
,
264 .type
= QEMU_OPT_STRING
,
266 { /* end of list */ }
270 static QemuOptsList qemu_global_opts
= {
272 .head
= QTAILQ_HEAD_INITIALIZER(qemu_global_opts
.head
),
276 .type
= QEMU_OPT_STRING
,
279 .type
= QEMU_OPT_STRING
,
282 .type
= QEMU_OPT_STRING
,
284 { /* end of list */ }
288 static QemuOptsList qemu_mon_opts
= {
290 .implied_opt_name
= "chardev",
291 .head
= QTAILQ_HEAD_INITIALIZER(qemu_mon_opts
.head
),
295 .type
= QEMU_OPT_STRING
,
298 .type
= QEMU_OPT_STRING
,
301 .type
= QEMU_OPT_BOOL
,
304 .type
= QEMU_OPT_BOOL
,
306 { /* end of list */ }
310 static QemuOptsList qemu_trace_opts
= {
312 .implied_opt_name
= "trace",
313 .head
= QTAILQ_HEAD_INITIALIZER(qemu_trace_opts
.head
),
317 .type
= QEMU_OPT_STRING
,
320 .type
= QEMU_OPT_STRING
,
322 { /* end of list */ }
326 static QemuOptsList qemu_cpudef_opts
= {
328 .head
= QTAILQ_HEAD_INITIALIZER(qemu_cpudef_opts
.head
),
332 .type
= QEMU_OPT_STRING
,
335 .type
= QEMU_OPT_NUMBER
,
338 .type
= QEMU_OPT_STRING
,
341 .type
= QEMU_OPT_NUMBER
,
344 .type
= QEMU_OPT_NUMBER
,
347 .type
= QEMU_OPT_NUMBER
,
349 .name
= "feature_edx", /* cpuid 0000_0001.edx */
350 .type
= QEMU_OPT_STRING
,
352 .name
= "feature_ecx", /* cpuid 0000_0001.ecx */
353 .type
= QEMU_OPT_STRING
,
355 .name
= "extfeature_edx", /* cpuid 8000_0001.edx */
356 .type
= QEMU_OPT_STRING
,
358 .name
= "extfeature_ecx", /* cpuid 8000_0001.ecx */
359 .type
= QEMU_OPT_STRING
,
362 .type
= QEMU_OPT_NUMBER
,
365 .type
= QEMU_OPT_STRING
,
367 .name
= "vendor_override",
368 .type
= QEMU_OPT_NUMBER
,
370 { /* end of list */ }
374 QemuOptsList qemu_spice_opts
= {
376 .head
= QTAILQ_HEAD_INITIALIZER(qemu_spice_opts
.head
),
380 .type
= QEMU_OPT_NUMBER
,
383 .type
= QEMU_OPT_NUMBER
,
386 .type
= QEMU_OPT_STRING
,
389 .type
= QEMU_OPT_BOOL
,
392 .type
= QEMU_OPT_BOOL
,
395 .type
= QEMU_OPT_STRING
,
397 .name
= "disable-ticketing",
398 .type
= QEMU_OPT_BOOL
,
400 .name
= "disable-copy-paste",
401 .type
= QEMU_OPT_BOOL
,
404 .type
= QEMU_OPT_BOOL
,
407 .type
= QEMU_OPT_STRING
,
409 .name
= "x509-key-file",
410 .type
= QEMU_OPT_STRING
,
412 .name
= "x509-key-password",
413 .type
= QEMU_OPT_STRING
,
415 .name
= "x509-cert-file",
416 .type
= QEMU_OPT_STRING
,
418 .name
= "x509-cacert-file",
419 .type
= QEMU_OPT_STRING
,
421 .name
= "x509-dh-key-file",
422 .type
= QEMU_OPT_STRING
,
424 .name
= "tls-ciphers",
425 .type
= QEMU_OPT_STRING
,
427 .name
= "tls-channel",
428 .type
= QEMU_OPT_STRING
,
430 .name
= "plaintext-channel",
431 .type
= QEMU_OPT_STRING
,
433 .name
= "image-compression",
434 .type
= QEMU_OPT_STRING
,
436 .name
= "jpeg-wan-compression",
437 .type
= QEMU_OPT_STRING
,
439 .name
= "zlib-glz-wan-compression",
440 .type
= QEMU_OPT_STRING
,
442 .name
= "streaming-video",
443 .type
= QEMU_OPT_STRING
,
445 .name
= "agent-mouse",
446 .type
= QEMU_OPT_BOOL
,
448 .name
= "playback-compression",
449 .type
= QEMU_OPT_BOOL
,
451 { /* end of list */ }
455 QemuOptsList qemu_option_rom_opts
= {
456 .name
= "option-rom",
457 .implied_opt_name
= "romfile",
458 .head
= QTAILQ_HEAD_INITIALIZER(qemu_option_rom_opts
.head
),
462 .type
= QEMU_OPT_NUMBER
,
465 .type
= QEMU_OPT_STRING
,
467 { /* end of list */ }
471 static QemuOptsList qemu_machine_opts
= {
473 .implied_opt_name
= "type",
474 .head
= QTAILQ_HEAD_INITIALIZER(qemu_machine_opts
.head
),
478 .type
= QEMU_OPT_STRING
,
479 .help
= "emulated machine"
482 .type
= QEMU_OPT_STRING
,
483 .help
= "accelerator list",
485 { /* End of list */ }
489 QemuOptsList qemu_boot_opts
= {
491 .head
= QTAILQ_HEAD_INITIALIZER(qemu_boot_opts
.head
),
493 /* the three names below are not used now */
496 .type
= QEMU_OPT_STRING
,
499 .type
= QEMU_OPT_STRING
,
502 .type
= QEMU_OPT_STRING
,
503 /* following are really used */
506 .type
= QEMU_OPT_STRING
,
508 .name
= "splash-time",
509 .type
= QEMU_OPT_STRING
,
515 static QemuOptsList
*vm_config_groups
[32] = {
526 &qemu_option_rom_opts
,
532 static QemuOptsList
*find_list(QemuOptsList
**lists
, const char *group
)
536 for (i
= 0; lists
[i
] != NULL
; i
++) {
537 if (strcmp(lists
[i
]->name
, group
) == 0)
540 if (lists
[i
] == NULL
) {
541 error_report("there is no option group \"%s\"", group
);
546 QemuOptsList
*qemu_find_opts(const char *group
)
548 return find_list(vm_config_groups
, group
);
551 void qemu_add_opts(QemuOptsList
*list
)
555 entries
= ARRAY_SIZE(vm_config_groups
);
556 entries
--; /* keep list NULL terminated */
557 for (i
= 0; i
< entries
; i
++) {
558 if (vm_config_groups
[i
] == NULL
) {
559 vm_config_groups
[i
] = list
;
563 fprintf(stderr
, "ran out of space in vm_config_groups");
567 int qemu_set_option(const char *str
)
569 char group
[64], id
[64], arg
[64];
574 rc
= sscanf(str
, "%63[^.].%63[^.].%63[^=]%n", group
, id
, arg
, &offset
);
575 if (rc
< 3 || str
[offset
] != '=') {
576 error_report("can't parse: \"%s\"", str
);
580 list
= qemu_find_opts(group
);
585 opts
= qemu_opts_find(list
, id
);
587 error_report("there is no %s \"%s\" defined",
592 if (qemu_opt_set(opts
, arg
, str
+offset
+1) == -1) {
598 int qemu_global_option(const char *str
)
600 char driver
[64], property
[64];
604 rc
= sscanf(str
, "%63[^.].%63[^=]%n", driver
, property
, &offset
);
605 if (rc
< 2 || str
[offset
] != '=') {
606 error_report("can't parse: \"%s\"", str
);
610 opts
= qemu_opts_create(&qemu_global_opts
, NULL
, 0);
611 qemu_opt_set(opts
, "driver", driver
);
612 qemu_opt_set(opts
, "property", property
);
613 qemu_opt_set(opts
, "value", str
+offset
+1);
617 struct ConfigWriteData
{
622 static int config_write_opt(const char *name
, const char *value
, void *opaque
)
624 struct ConfigWriteData
*data
= opaque
;
626 fprintf(data
->fp
, " %s = \"%s\"\n", name
, value
);
630 static int config_write_opts(QemuOpts
*opts
, void *opaque
)
632 struct ConfigWriteData
*data
= opaque
;
633 const char *id
= qemu_opts_id(opts
);
636 fprintf(data
->fp
, "[%s \"%s\"]\n", data
->list
->name
, id
);
638 fprintf(data
->fp
, "[%s]\n", data
->list
->name
);
640 qemu_opt_foreach(opts
, config_write_opt
, data
, 0);
641 fprintf(data
->fp
, "\n");
645 void qemu_config_write(FILE *fp
)
647 struct ConfigWriteData data
= { .fp
= fp
};
648 QemuOptsList
**lists
= vm_config_groups
;
651 fprintf(fp
, "# qemu config file\n\n");
652 for (i
= 0; lists
[i
] != NULL
; i
++) {
653 data
.list
= lists
[i
];
654 qemu_opts_foreach(data
.list
, config_write_opts
, &data
, 0);
658 int qemu_config_parse(FILE *fp
, QemuOptsList
**lists
, const char *fname
)
660 char line
[1024], group
[64], id
[64], arg
[64], value
[1024];
662 QemuOptsList
*list
= NULL
;
663 QemuOpts
*opts
= NULL
;
664 int res
= -1, lno
= 0;
667 while (fgets(line
, sizeof(line
), fp
) != NULL
) {
668 loc_set_file(fname
, ++lno
);
669 if (line
[0] == '\n') {
670 /* skip empty lines */
673 if (line
[0] == '#') {
677 if (sscanf(line
, "[%63s \"%63[^\"]\"]", group
, id
) == 2) {
679 list
= find_list(lists
, group
);
682 opts
= qemu_opts_create(list
, id
, 1);
685 if (sscanf(line
, "[%63[^]]]", group
) == 1) {
686 /* group without id */
687 list
= find_list(lists
, group
);
690 opts
= qemu_opts_create(list
, NULL
, 0);
693 if (sscanf(line
, " %63s = \"%1023[^\"]\"", arg
, value
) == 2) {
696 error_report("no group defined");
699 if (qemu_opt_set(opts
, arg
, value
) != 0) {
704 error_report("parse error");
708 error_report("error reading file");
717 int qemu_read_config_file(const char *filename
)
719 FILE *f
= fopen(filename
, "r");
726 ret
= qemu_config_parse(f
, vm_config_groups
, filename
);