Statistics
| Branch: | Revision:

root / qemu-config.c @ 73f5e313

History | View | Annotate | Download (19.6 kB)

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
            .name = "iops",
90
            .type = QEMU_OPT_NUMBER,
91
            .help = "limit total I/O operations per second",
92
        },{
93
            .name = "iops_rd",
94
            .type = QEMU_OPT_NUMBER,
95
            .help = "limit read operations per second",
96
        },{
97
            .name = "iops_wr",
98
            .type = QEMU_OPT_NUMBER,
99
            .help = "limit write operations per second",
100
        },{
101
            .name = "bps",
102
            .type = QEMU_OPT_NUMBER,
103
            .help = "limit total bytes per second",
104
        },{
105
            .name = "bps_rd",
106
            .type = QEMU_OPT_NUMBER,
107
            .help = "limit read bytes per second",
108
        },{
109
            .name = "bps_wr",
110
            .type = QEMU_OPT_NUMBER,
111
            .help = "limit write bytes per second",
112
        },{
113
            .name = "copy-on-read",
114
            .type = QEMU_OPT_BOOL,
115
            .help = "copy read data from backing file into image file",
116
        },
117
        { /* end of list */ }
118
    },
119
};
120

    
121
static QemuOptsList qemu_chardev_opts = {
122
    .name = "chardev",
123
    .implied_opt_name = "backend",
124
    .head = QTAILQ_HEAD_INITIALIZER(qemu_chardev_opts.head),
125
    .desc = {
126
        {
127
            .name = "backend",
128
            .type = QEMU_OPT_STRING,
129
        },{
130
            .name = "path",
131
            .type = QEMU_OPT_STRING,
132
        },{
133
            .name = "host",
134
            .type = QEMU_OPT_STRING,
135
        },{
136
            .name = "port",
137
            .type = QEMU_OPT_STRING,
138
        },{
139
            .name = "localaddr",
140
            .type = QEMU_OPT_STRING,
141
        },{
142
            .name = "localport",
143
            .type = QEMU_OPT_STRING,
144
        },{
145
            .name = "to",
146
            .type = QEMU_OPT_NUMBER,
147
        },{
148
            .name = "ipv4",
149
            .type = QEMU_OPT_BOOL,
150
        },{
151
            .name = "ipv6",
152
            .type = QEMU_OPT_BOOL,
153
        },{
154
            .name = "wait",
155
            .type = QEMU_OPT_BOOL,
156
        },{
157
            .name = "server",
158
            .type = QEMU_OPT_BOOL,
159
        },{
160
            .name = "delay",
161
            .type = QEMU_OPT_BOOL,
162
        },{
163
            .name = "telnet",
164
            .type = QEMU_OPT_BOOL,
165
        },{
166
            .name = "width",
167
            .type = QEMU_OPT_NUMBER,
168
        },{
169
            .name = "height",
170
            .type = QEMU_OPT_NUMBER,
171
        },{
172
            .name = "cols",
173
            .type = QEMU_OPT_NUMBER,
174
        },{
175
            .name = "rows",
176
            .type = QEMU_OPT_NUMBER,
177
        },{
178
            .name = "mux",
179
            .type = QEMU_OPT_BOOL,
180
        },{
181
            .name = "signal",
182
            .type = QEMU_OPT_BOOL,
183
        },{
184
            .name = "name",
185
            .type = QEMU_OPT_STRING,
186
        },{
187
            .name = "debug",
188
            .type = QEMU_OPT_NUMBER,
189
        },
190
        { /* end of list */ }
191
    },
192
};
193

    
194
QemuOptsList qemu_fsdev_opts = {
195
    .name = "fsdev",
196
    .implied_opt_name = "fsdriver",
197
    .head = QTAILQ_HEAD_INITIALIZER(qemu_fsdev_opts.head),
198
    .desc = {
199
        {
200
            .name = "fsdriver",
201
            .type = QEMU_OPT_STRING,
202
        }, {
203
            .name = "path",
204
            .type = QEMU_OPT_STRING,
205
        }, {
206
            .name = "security_model",
207
            .type = QEMU_OPT_STRING,
208
        }, {
209
            .name = "writeout",
210
            .type = QEMU_OPT_STRING,
211
        }, {
212
            .name = "readonly",
213
            .type = QEMU_OPT_BOOL,
214
        },
215

    
216
        { /*End of list */ }
217
    },
218
};
219

    
220
QemuOptsList qemu_virtfs_opts = {
221
    .name = "virtfs",
222
    .implied_opt_name = "fsdriver",
223
    .head = QTAILQ_HEAD_INITIALIZER(qemu_virtfs_opts.head),
224
    .desc = {
225
        {
226
            .name = "fsdriver",
227
            .type = QEMU_OPT_STRING,
228
        }, {
229
            .name = "path",
230
            .type = QEMU_OPT_STRING,
231
        }, {
232
            .name = "mount_tag",
233
            .type = QEMU_OPT_STRING,
234
        }, {
235
            .name = "security_model",
236
            .type = QEMU_OPT_STRING,
237
        }, {
238
            .name = "writeout",
239
            .type = QEMU_OPT_STRING,
240
        }, {
241
            .name = "readonly",
242
            .type = QEMU_OPT_BOOL,
243
        },
244

    
245
        { /*End of list */ }
246
    },
247
};
248

    
249
static QemuOptsList qemu_device_opts = {
250
    .name = "device",
251
    .implied_opt_name = "driver",
252
    .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
253
    .desc = {
254
        /*
255
         * no elements => accept any
256
         * sanity checking will happen later
257
         * when setting device properties
258
         */
259
        { /* end of list */ }
260
    },
261
};
262

    
263
static QemuOptsList qemu_netdev_opts = {
264
    .name = "netdev",
265
    .implied_opt_name = "type",
266
    .head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head),
267
    .desc = {
268
        /*
269
         * no elements => accept any params
270
         * validation will happen later
271
         */
272
        { /* end of list */ }
273
    },
274
};
275

    
276
static QemuOptsList qemu_net_opts = {
277
    .name = "net",
278
    .implied_opt_name = "type",
279
    .head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head),
280
    .desc = {
281
        /*
282
         * no elements => accept any params
283
         * validation will happen later
284
         */
285
        { /* end of list */ }
286
    },
287
};
288

    
289
static QemuOptsList qemu_rtc_opts = {
290
    .name = "rtc",
291
    .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head),
292
    .desc = {
293
        {
294
            .name = "base",
295
            .type = QEMU_OPT_STRING,
296
        },{
297
            .name = "clock",
298
            .type = QEMU_OPT_STRING,
299
        },{
300
            .name = "driftfix",
301
            .type = QEMU_OPT_STRING,
302
        },
303
        { /* end of list */ }
304
    },
305
};
306

    
307
static QemuOptsList qemu_global_opts = {
308
    .name = "global",
309
    .head = QTAILQ_HEAD_INITIALIZER(qemu_global_opts.head),
310
    .desc = {
311
        {
312
            .name = "driver",
313
            .type = QEMU_OPT_STRING,
314
        },{
315
            .name = "property",
316
            .type = QEMU_OPT_STRING,
317
        },{
318
            .name = "value",
319
            .type = QEMU_OPT_STRING,
320
        },
321
        { /* end of list */ }
322
    },
323
};
324

    
325
static QemuOptsList qemu_mon_opts = {
326
    .name = "mon",
327
    .implied_opt_name = "chardev",
328
    .head = QTAILQ_HEAD_INITIALIZER(qemu_mon_opts.head),
329
    .desc = {
330
        {
331
            .name = "mode",
332
            .type = QEMU_OPT_STRING,
333
        },{
334
            .name = "chardev",
335
            .type = QEMU_OPT_STRING,
336
        },{
337
            .name = "default",
338
            .type = QEMU_OPT_BOOL,
339
        },{
340
            .name = "pretty",
341
            .type = QEMU_OPT_BOOL,
342
        },
343
        { /* end of list */ }
344
    },
345
};
346

    
347
static QemuOptsList qemu_trace_opts = {
348
    .name = "trace",
349
    .implied_opt_name = "trace",
350
    .head = QTAILQ_HEAD_INITIALIZER(qemu_trace_opts.head),
351
    .desc = {
352
        {
353
            .name = "events",
354
            .type = QEMU_OPT_STRING,
355
        },{
356
            .name = "file",
357
            .type = QEMU_OPT_STRING,
358
        },
359
        { /* end of list */ }
360
    },
361
};
362

    
363
static QemuOptsList qemu_cpudef_opts = {
364
    .name = "cpudef",
365
    .head = QTAILQ_HEAD_INITIALIZER(qemu_cpudef_opts.head),
366
    .desc = {
367
        {
368
            .name = "name",
369
            .type = QEMU_OPT_STRING,
370
        },{
371
            .name = "level",
372
            .type = QEMU_OPT_NUMBER,
373
        },{
374
            .name = "vendor",
375
            .type = QEMU_OPT_STRING,
376
        },{
377
            .name = "family",
378
            .type = QEMU_OPT_NUMBER,
379
        },{
380
            .name = "model",
381
            .type = QEMU_OPT_NUMBER,
382
        },{
383
            .name = "stepping",
384
            .type = QEMU_OPT_NUMBER,
385
        },{
386
            .name = "feature_edx",      /* cpuid 0000_0001.edx */
387
            .type = QEMU_OPT_STRING,
388
        },{
389
            .name = "feature_ecx",      /* cpuid 0000_0001.ecx */
390
            .type = QEMU_OPT_STRING,
391
        },{
392
            .name = "extfeature_edx",   /* cpuid 8000_0001.edx */
393
            .type = QEMU_OPT_STRING,
394
        },{
395
            .name = "extfeature_ecx",   /* cpuid 8000_0001.ecx */
396
            .type = QEMU_OPT_STRING,
397
        },{
398
            .name = "xlevel",
399
            .type = QEMU_OPT_NUMBER,
400
        },{
401
            .name = "model_id",
402
            .type = QEMU_OPT_STRING,
403
        },{
404
            .name = "vendor_override",
405
            .type = QEMU_OPT_NUMBER,
406
        },
407
        { /* end of list */ }
408
    },
409
};
410

    
411
QemuOptsList qemu_spice_opts = {
412
    .name = "spice",
413
    .head = QTAILQ_HEAD_INITIALIZER(qemu_spice_opts.head),
414
    .desc = {
415
        {
416
            .name = "port",
417
            .type = QEMU_OPT_NUMBER,
418
        },{
419
            .name = "tls-port",
420
            .type = QEMU_OPT_NUMBER,
421
        },{
422
            .name = "addr",
423
            .type = QEMU_OPT_STRING,
424
        },{
425
            .name = "ipv4",
426
            .type = QEMU_OPT_BOOL,
427
        },{
428
            .name = "ipv6",
429
            .type = QEMU_OPT_BOOL,
430
        },{
431
            .name = "password",
432
            .type = QEMU_OPT_STRING,
433
        },{
434
            .name = "disable-ticketing",
435
            .type = QEMU_OPT_BOOL,
436
        },{
437
            .name = "disable-copy-paste",
438
            .type = QEMU_OPT_BOOL,
439
        },{
440
            .name = "sasl",
441
            .type = QEMU_OPT_BOOL,
442
        },{
443
            .name = "x509-dir",
444
            .type = QEMU_OPT_STRING,
445
        },{
446
            .name = "x509-key-file",
447
            .type = QEMU_OPT_STRING,
448
        },{
449
            .name = "x509-key-password",
450
            .type = QEMU_OPT_STRING,
451
        },{
452
            .name = "x509-cert-file",
453
            .type = QEMU_OPT_STRING,
454
        },{
455
            .name = "x509-cacert-file",
456
            .type = QEMU_OPT_STRING,
457
        },{
458
            .name = "x509-dh-key-file",
459
            .type = QEMU_OPT_STRING,
460
        },{
461
            .name = "tls-ciphers",
462
            .type = QEMU_OPT_STRING,
463
        },{
464
            .name = "tls-channel",
465
            .type = QEMU_OPT_STRING,
466
        },{
467
            .name = "plaintext-channel",
468
            .type = QEMU_OPT_STRING,
469
        },{
470
            .name = "image-compression",
471
            .type = QEMU_OPT_STRING,
472
        },{
473
            .name = "jpeg-wan-compression",
474
            .type = QEMU_OPT_STRING,
475
        },{
476
            .name = "zlib-glz-wan-compression",
477
            .type = QEMU_OPT_STRING,
478
        },{
479
            .name = "streaming-video",
480
            .type = QEMU_OPT_STRING,
481
        },{
482
            .name = "agent-mouse",
483
            .type = QEMU_OPT_BOOL,
484
        },{
485
            .name = "playback-compression",
486
            .type = QEMU_OPT_BOOL,
487
        },
488
        { /* end of list */ }
489
    },
490
};
491

    
492
QemuOptsList qemu_option_rom_opts = {
493
    .name = "option-rom",
494
    .implied_opt_name = "romfile",
495
    .head = QTAILQ_HEAD_INITIALIZER(qemu_option_rom_opts.head),
496
    .desc = {
497
        {
498
            .name = "bootindex",
499
            .type = QEMU_OPT_NUMBER,
500
        }, {
501
            .name = "romfile",
502
            .type = QEMU_OPT_STRING,
503
        },
504
        { /* end of list */ }
505
    },
506
};
507

    
508
static QemuOptsList qemu_machine_opts = {
509
    .name = "machine",
510
    .implied_opt_name = "type",
511
    .head = QTAILQ_HEAD_INITIALIZER(qemu_machine_opts.head),
512
    .desc = {
513
        {
514
            .name = "type",
515
            .type = QEMU_OPT_STRING,
516
            .help = "emulated machine"
517
        }, {
518
            .name = "accel",
519
            .type = QEMU_OPT_STRING,
520
            .help = "accelerator list",
521
        },
522
        { /* End of list */ }
523
    },
524
};
525

    
526
QemuOptsList qemu_boot_opts = {
527
    .name = "boot-opts",
528
    .head = QTAILQ_HEAD_INITIALIZER(qemu_boot_opts.head),
529
    .desc = {
530
        /* the three names below are not used now */
531
        {
532
            .name = "order",
533
            .type = QEMU_OPT_STRING,
534
        }, {
535
            .name = "once",
536
            .type = QEMU_OPT_STRING,
537
        }, {
538
            .name = "menu",
539
            .type = QEMU_OPT_STRING,
540
        /* following are really used */
541
        }, {
542
            .name = "splash",
543
            .type = QEMU_OPT_STRING,
544
        }, {
545
            .name = "splash-time",
546
            .type = QEMU_OPT_STRING,
547
        },
548
        { /*End of list */ }
549
    },
550
};
551

    
552
static QemuOptsList *vm_config_groups[32] = {
553
    &qemu_drive_opts,
554
    &qemu_chardev_opts,
555
    &qemu_device_opts,
556
    &qemu_netdev_opts,
557
    &qemu_net_opts,
558
    &qemu_rtc_opts,
559
    &qemu_global_opts,
560
    &qemu_mon_opts,
561
    &qemu_cpudef_opts,
562
    &qemu_trace_opts,
563
    &qemu_option_rom_opts,
564
    &qemu_machine_opts,
565
    &qemu_boot_opts,
566
    NULL,
567
};
568

    
569
static QemuOptsList *find_list(QemuOptsList **lists, const char *group)
570
{
571
    int i;
572

    
573
    for (i = 0; lists[i] != NULL; i++) {
574
        if (strcmp(lists[i]->name, group) == 0)
575
            break;
576
    }
577
    if (lists[i] == NULL) {
578
        error_report("there is no option group \"%s\"", group);
579
    }
580
    return lists[i];
581
}
582

    
583
QemuOptsList *qemu_find_opts(const char *group)
584
{
585
    return find_list(vm_config_groups, group);
586
}
587

    
588
void qemu_add_opts(QemuOptsList *list)
589
{
590
    int entries, i;
591

    
592
    entries = ARRAY_SIZE(vm_config_groups);
593
    entries--; /* keep list NULL terminated */
594
    for (i = 0; i < entries; i++) {
595
        if (vm_config_groups[i] == NULL) {
596
            vm_config_groups[i] = list;
597
            return;
598
        }
599
    }
600
    fprintf(stderr, "ran out of space in vm_config_groups");
601
    abort();
602
}
603

    
604
int qemu_set_option(const char *str)
605
{
606
    char group[64], id[64], arg[64];
607
    QemuOptsList *list;
608
    QemuOpts *opts;
609
    int rc, offset;
610

    
611
    rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset);
612
    if (rc < 3 || str[offset] != '=') {
613
        error_report("can't parse: \"%s\"", str);
614
        return -1;
615
    }
616

    
617
    list = qemu_find_opts(group);
618
    if (list == NULL) {
619
        return -1;
620
    }
621

    
622
    opts = qemu_opts_find(list, id);
623
    if (!opts) {
624
        error_report("there is no %s \"%s\" defined",
625
                     list->name, id);
626
        return -1;
627
    }
628

    
629
    if (qemu_opt_set(opts, arg, str+offset+1) == -1) {
630
        return -1;
631
    }
632
    return 0;
633
}
634

    
635
int qemu_global_option(const char *str)
636
{
637
    char driver[64], property[64];
638
    QemuOpts *opts;
639
    int rc, offset;
640

    
641
    rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
642
    if (rc < 2 || str[offset] != '=') {
643
        error_report("can't parse: \"%s\"", str);
644
        return -1;
645
    }
646

    
647
    opts = qemu_opts_create(&qemu_global_opts, NULL, 0);
648
    qemu_opt_set(opts, "driver", driver);
649
    qemu_opt_set(opts, "property", property);
650
    qemu_opt_set(opts, "value", str+offset+1);
651
    return 0;
652
}
653

    
654
struct ConfigWriteData {
655
    QemuOptsList *list;
656
    FILE *fp;
657
};
658

    
659
static int config_write_opt(const char *name, const char *value, void *opaque)
660
{
661
    struct ConfigWriteData *data = opaque;
662

    
663
    fprintf(data->fp, "  %s = \"%s\"\n", name, value);
664
    return 0;
665
}
666

    
667
static int config_write_opts(QemuOpts *opts, void *opaque)
668
{
669
    struct ConfigWriteData *data = opaque;
670
    const char *id = qemu_opts_id(opts);
671

    
672
    if (id) {
673
        fprintf(data->fp, "[%s \"%s\"]\n", data->list->name, id);
674
    } else {
675
        fprintf(data->fp, "[%s]\n", data->list->name);
676
    }
677
    qemu_opt_foreach(opts, config_write_opt, data, 0);
678
    fprintf(data->fp, "\n");
679
    return 0;
680
}
681

    
682
void qemu_config_write(FILE *fp)
683
{
684
    struct ConfigWriteData data = { .fp = fp };
685
    QemuOptsList **lists = vm_config_groups;
686
    int i;
687

    
688
    fprintf(fp, "# qemu config file\n\n");
689
    for (i = 0; lists[i] != NULL; i++) {
690
        data.list = lists[i];
691
        qemu_opts_foreach(data.list, config_write_opts, &data, 0);
692
    }
693
}
694

    
695
int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
696
{
697
    char line[1024], group[64], id[64], arg[64], value[1024];
698
    Location loc;
699
    QemuOptsList *list = NULL;
700
    QemuOpts *opts = NULL;
701
    int res = -1, lno = 0;
702

    
703
    loc_push_none(&loc);
704
    while (fgets(line, sizeof(line), fp) != NULL) {
705
        loc_set_file(fname, ++lno);
706
        if (line[0] == '\n') {
707
            /* skip empty lines */
708
            continue;
709
        }
710
        if (line[0] == '#') {
711
            /* comment */
712
            continue;
713
        }
714
        if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
715
            /* group with id */
716
            list = find_list(lists, group);
717
            if (list == NULL)
718
                goto out;
719
            opts = qemu_opts_create(list, id, 1);
720
            continue;
721
        }
722
        if (sscanf(line, "[%63[^]]]", group) == 1) {
723
            /* group without id */
724
            list = find_list(lists, group);
725
            if (list == NULL)
726
                goto out;
727
            opts = qemu_opts_create(list, NULL, 0);
728
            continue;
729
        }
730
        if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
731
            /* arg = value */
732
            if (opts == NULL) {
733
                error_report("no group defined");
734
                goto out;
735
            }
736
            if (qemu_opt_set(opts, arg, value) != 0) {
737
                goto out;
738
            }
739
            continue;
740
        }
741
        error_report("parse error");
742
        goto out;
743
    }
744
    if (ferror(fp)) {
745
        error_report("error reading file");
746
        goto out;
747
    }
748
    res = 0;
749
out:
750
    loc_pop(&loc);
751
    return res;
752
}
753

    
754
int qemu_read_config_file(const char *filename)
755
{
756
    FILE *f = fopen(filename, "r");
757
    int ret;
758

    
759
    if (f == NULL) {
760
        return -errno;
761
    }
762

    
763
    ret = qemu_config_parse(f, vm_config_groups, filename);
764
    fclose(f);
765

    
766
    if (ret == 0) {
767
        return 0;
768
    } else {
769
        return -EINVAL;
770
    }
771
}