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