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