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