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 8 static QemuOptsList *vm_config_groups[48]; 9 static QemuOptsList *drive_config_groups[5]; 10 11 static 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 26 QemuOptsList *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 39 QemuOpts *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 53 static 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 */ 97 static 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 del_entry->next = NULL; 109 qapi_free_CommandLineParameterInfoList(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 .name = "aes-key-wrap", 225 .type = QEMU_OPT_BOOL, 226 .help = "enable/disable AES key wrapping using the CPACF wrapping key", 227 },{ 228 .name = "dea-key-wrap", 229 .type = QEMU_OPT_BOOL, 230 .help = "enable/disable DEA key wrapping using the CPACF wrapping key", 231 },{ 232 .name = "loadparm", 233 .type = QEMU_OPT_STRING, 234 .help = "Up to 8 chars in set of [A-Za-z0-9. ](lower case chars" 235 " converted to upper case) to pass to machine" 236 " loader, boot manager, and guest kernel", 237 }, 238 { /* End of list */ } 239 } 240 }; 241 242 CommandLineOptionInfoList *qmp_query_command_line_options(bool has_option, 243 const char *option, 244 Error **errp) 245 { 246 CommandLineOptionInfoList *conf_list = NULL, *entry; 247 CommandLineOptionInfo *info; 248 int i; 249 250 for (i = 0; vm_config_groups[i] != NULL; i++) { 251 if (!has_option || !strcmp(option, vm_config_groups[i]->name)) { 252 info = g_malloc0(sizeof(*info)); 253 info->option = g_strdup(vm_config_groups[i]->name); 254 if (!strcmp("drive", vm_config_groups[i]->name)) { 255 info->parameters = get_drive_infolist(); 256 } else if (!strcmp("machine", vm_config_groups[i]->name)) { 257 info->parameters = query_option_descs(machine_opts.desc); 258 } else { 259 info->parameters = 260 query_option_descs(vm_config_groups[i]->desc); 261 } 262 entry = g_malloc0(sizeof(*entry)); 263 entry->value = info; 264 entry->next = conf_list; 265 conf_list = entry; 266 } 267 } 268 269 if (conf_list == NULL) { 270 error_setg(errp, "invalid option name: %s", option); 271 } 272 273 return conf_list; 274 } 275 276 QemuOptsList *qemu_find_opts_err(const char *group, Error **errp) 277 { 278 return find_list(vm_config_groups, group, errp); 279 } 280 281 void qemu_add_drive_opts(QemuOptsList *list) 282 { 283 int entries, i; 284 285 entries = ARRAY_SIZE(drive_config_groups); 286 entries--; /* keep list NULL terminated */ 287 for (i = 0; i < entries; i++) { 288 if (drive_config_groups[i] == NULL) { 289 drive_config_groups[i] = list; 290 return; 291 } 292 } 293 fprintf(stderr, "ran out of space in drive_config_groups"); 294 abort(); 295 } 296 297 void qemu_add_opts(QemuOptsList *list) 298 { 299 int entries, i; 300 301 entries = ARRAY_SIZE(vm_config_groups); 302 entries--; /* keep list NULL terminated */ 303 for (i = 0; i < entries; i++) { 304 if (vm_config_groups[i] == NULL) { 305 vm_config_groups[i] = list; 306 return; 307 } 308 } 309 fprintf(stderr, "ran out of space in vm_config_groups"); 310 abort(); 311 } 312 313 int qemu_set_option(const char *str) 314 { 315 Error *local_err = NULL; 316 char group[64], id[64], arg[64]; 317 QemuOptsList *list; 318 QemuOpts *opts; 319 int rc, offset; 320 321 rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset); 322 if (rc < 3 || str[offset] != '=') { 323 error_report("can't parse: \"%s\"", str); 324 return -1; 325 } 326 327 list = qemu_find_opts(group); 328 if (list == NULL) { 329 return -1; 330 } 331 332 opts = qemu_opts_find(list, id); 333 if (!opts) { 334 error_report("there is no %s \"%s\" defined", 335 list->name, id); 336 return -1; 337 } 338 339 qemu_opt_set(opts, arg, str + offset + 1, &local_err); 340 if (local_err) { 341 error_report_err(local_err); 342 return -1; 343 } 344 return 0; 345 } 346 347 struct ConfigWriteData { 348 QemuOptsList *list; 349 FILE *fp; 350 }; 351 352 static int config_write_opt(void *opaque, const char *name, const char *value, 353 Error **errp) 354 { 355 struct ConfigWriteData *data = opaque; 356 357 fprintf(data->fp, " %s = \"%s\"\n", name, value); 358 return 0; 359 } 360 361 static int config_write_opts(void *opaque, QemuOpts *opts, Error **errp) 362 { 363 struct ConfigWriteData *data = opaque; 364 const char *id = qemu_opts_id(opts); 365 366 if (id) { 367 fprintf(data->fp, "[%s \"%s\"]\n", data->list->name, id); 368 } else { 369 fprintf(data->fp, "[%s]\n", data->list->name); 370 } 371 qemu_opt_foreach(opts, config_write_opt, data, NULL); 372 fprintf(data->fp, "\n"); 373 return 0; 374 } 375 376 void qemu_config_write(FILE *fp) 377 { 378 struct ConfigWriteData data = { .fp = fp }; 379 QemuOptsList **lists = vm_config_groups; 380 int i; 381 382 fprintf(fp, "# qemu config file\n\n"); 383 for (i = 0; lists[i] != NULL; i++) { 384 data.list = lists[i]; 385 qemu_opts_foreach(data.list, config_write_opts, &data, NULL); 386 } 387 } 388 389 /* Returns number of config groups on success, -errno on error */ 390 int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname) 391 { 392 char line[1024], group[64], id[64], arg[64], value[1024]; 393 Location loc; 394 QemuOptsList *list = NULL; 395 Error *local_err = NULL; 396 QemuOpts *opts = NULL; 397 int res = -EINVAL, lno = 0; 398 int count = 0; 399 400 loc_push_none(&loc); 401 while (fgets(line, sizeof(line), fp) != NULL) { 402 loc_set_file(fname, ++lno); 403 if (line[0] == '\n') { 404 /* skip empty lines */ 405 continue; 406 } 407 if (line[0] == '#') { 408 /* comment */ 409 continue; 410 } 411 if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) { 412 /* group with id */ 413 list = find_list(lists, group, &local_err); 414 if (local_err) { 415 error_report_err(local_err); 416 goto out; 417 } 418 opts = qemu_opts_create(list, id, 1, NULL); 419 count++; 420 continue; 421 } 422 if (sscanf(line, "[%63[^]]]", group) == 1) { 423 /* group without id */ 424 list = find_list(lists, group, &local_err); 425 if (local_err) { 426 error_report_err(local_err); 427 goto out; 428 } 429 opts = qemu_opts_create(list, NULL, 0, &error_abort); 430 count++; 431 continue; 432 } 433 value[0] = '\0'; 434 if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2 || 435 sscanf(line, " %63s = \"\"", arg) == 1) { 436 /* arg = value */ 437 if (opts == NULL) { 438 error_report("no group defined"); 439 goto out; 440 } 441 qemu_opt_set(opts, arg, value, &local_err); 442 if (local_err) { 443 error_report_err(local_err); 444 goto out; 445 } 446 continue; 447 } 448 error_report("parse error"); 449 goto out; 450 } 451 if (ferror(fp)) { 452 error_report("error reading file"); 453 goto out; 454 } 455 res = count; 456 out: 457 loc_pop(&loc); 458 return res; 459 } 460 461 int qemu_read_config_file(const char *filename) 462 { 463 FILE *f = fopen(filename, "r"); 464 int ret; 465 466 if (f == NULL) { 467 return -errno; 468 } 469 470 ret = qemu_config_parse(f, vm_config_groups, filename); 471 fclose(f); 472 return ret; 473 } 474 475 static void config_parse_qdict_section(QDict *options, QemuOptsList *opts, 476 Error **errp) 477 { 478 QemuOpts *subopts; 479 QDict *subqdict; 480 QList *list = NULL; 481 Error *local_err = NULL; 482 size_t orig_size, enum_size; 483 char *prefix; 484 485 prefix = g_strdup_printf("%s.", opts->name); 486 qdict_extract_subqdict(options, &subqdict, prefix); 487 g_free(prefix); 488 orig_size = qdict_size(subqdict); 489 if (!orig_size) { 490 goto out; 491 } 492 493 subopts = qemu_opts_create(opts, NULL, 0, &local_err); 494 if (local_err) { 495 error_propagate(errp, local_err); 496 goto out; 497 } 498 499 qemu_opts_absorb_qdict(subopts, subqdict, &local_err); 500 if (local_err) { 501 error_propagate(errp, local_err); 502 goto out; 503 } 504 505 enum_size = qdict_size(subqdict); 506 if (enum_size < orig_size && enum_size) { 507 error_setg(errp, "Unknown option '%s' for [%s]", 508 qdict_first(subqdict)->key, opts->name); 509 goto out; 510 } 511 512 if (enum_size) { 513 /* Multiple, enumerated sections */ 514 QListEntry *list_entry; 515 unsigned i = 0; 516 517 /* Not required anymore */ 518 qemu_opts_del(subopts); 519 520 qdict_array_split(subqdict, &list); 521 if (qdict_size(subqdict)) { 522 error_setg(errp, "Unused option '%s' for [%s]", 523 qdict_first(subqdict)->key, opts->name); 524 goto out; 525 } 526 527 QLIST_FOREACH_ENTRY(list, list_entry) { 528 QDict *section = qobject_to_qdict(qlist_entry_obj(list_entry)); 529 char *opt_name; 530 531 if (!section) { 532 error_setg(errp, "[%s] section (index %u) does not consist of " 533 "keys", opts->name, i); 534 goto out; 535 } 536 537 opt_name = g_strdup_printf("%s.%u", opts->name, i++); 538 subopts = qemu_opts_create(opts, opt_name, 1, &local_err); 539 g_free(opt_name); 540 if (local_err) { 541 error_propagate(errp, local_err); 542 goto out; 543 } 544 545 qemu_opts_absorb_qdict(subopts, section, &local_err); 546 if (local_err) { 547 error_propagate(errp, local_err); 548 qemu_opts_del(subopts); 549 goto out; 550 } 551 552 if (qdict_size(section)) { 553 error_setg(errp, "[%s] section doesn't support the option '%s'", 554 opts->name, qdict_first(section)->key); 555 qemu_opts_del(subopts); 556 goto out; 557 } 558 } 559 } 560 561 out: 562 QDECREF(subqdict); 563 QDECREF(list); 564 } 565 566 void qemu_config_parse_qdict(QDict *options, QemuOptsList **lists, 567 Error **errp) 568 { 569 int i; 570 Error *local_err = NULL; 571 572 for (i = 0; lists[i]; i++) { 573 config_parse_qdict_section(options, lists[i], &local_err); 574 if (local_err) { 575 error_propagate(errp, local_err); 576 return; 577 } 578 } 579 } 580