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