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