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