1 /* 2 * QEMU System Emulator 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "qemu/osdep.h" 26 #include "qemu/cutils.h" 27 #include "monitor/monitor.h" 28 #include "sysemu/sysemu.h" 29 #include "qemu/config-file.h" 30 #include "qemu/error-report.h" 31 #include "qemu/qemu-print.h" 32 #include "chardev/char.h" 33 #include "qapi/error.h" 34 #include "qapi/qapi-commands-char.h" 35 #include "qapi/qmp/qerror.h" 36 #include "sysemu/replay.h" 37 #include "qemu/help_option.h" 38 #include "qemu/module.h" 39 #include "qemu/option.h" 40 41 #include "chardev/char-mux.h" 42 43 /***********************************************************/ 44 /* character device */ 45 46 static Object *get_chardevs_root(void) 47 { 48 return container_get(object_get_root(), "/chardevs"); 49 } 50 51 static void chr_be_event(Chardev *s, QEMUChrEvent event) 52 { 53 CharBackend *be = s->be; 54 55 if (!be || !be->chr_event) { 56 return; 57 } 58 59 be->chr_event(be->opaque, event); 60 } 61 62 void qemu_chr_be_event(Chardev *s, QEMUChrEvent event) 63 { 64 /* Keep track if the char device is open */ 65 switch (event) { 66 case CHR_EVENT_OPENED: 67 s->be_open = 1; 68 break; 69 case CHR_EVENT_CLOSED: 70 s->be_open = 0; 71 break; 72 case CHR_EVENT_BREAK: 73 case CHR_EVENT_MUX_IN: 74 case CHR_EVENT_MUX_OUT: 75 /* Ignore */ 76 break; 77 } 78 79 CHARDEV_GET_CLASS(s)->chr_be_event(s, event); 80 } 81 82 /* Not reporting errors from writing to logfile, as logs are 83 * defined to be "best effort" only */ 84 static void qemu_chr_write_log(Chardev *s, const uint8_t *buf, size_t len) 85 { 86 size_t done = 0; 87 ssize_t ret; 88 89 if (s->logfd < 0) { 90 return; 91 } 92 93 while (done < len) { 94 retry: 95 ret = write(s->logfd, buf + done, len - done); 96 if (ret == -1 && errno == EAGAIN) { 97 g_usleep(100); 98 goto retry; 99 } 100 101 if (ret <= 0) { 102 return; 103 } 104 done += ret; 105 } 106 } 107 108 static int qemu_chr_write_buffer(Chardev *s, 109 const uint8_t *buf, int len, 110 int *offset, bool write_all) 111 { 112 ChardevClass *cc = CHARDEV_GET_CLASS(s); 113 int res = 0; 114 *offset = 0; 115 116 qemu_mutex_lock(&s->chr_write_lock); 117 while (*offset < len) { 118 retry: 119 res = cc->chr_write(s, buf + *offset, len - *offset); 120 if (res < 0 && errno == EAGAIN && write_all) { 121 g_usleep(100); 122 goto retry; 123 } 124 125 if (res <= 0) { 126 break; 127 } 128 129 *offset += res; 130 if (!write_all) { 131 break; 132 } 133 } 134 if (*offset > 0) { 135 qemu_chr_write_log(s, buf, *offset); 136 } 137 qemu_mutex_unlock(&s->chr_write_lock); 138 139 return res; 140 } 141 142 int qemu_chr_write(Chardev *s, const uint8_t *buf, int len, bool write_all) 143 { 144 int offset = 0; 145 int res; 146 147 if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_PLAY) { 148 replay_char_write_event_load(&res, &offset); 149 assert(offset <= len); 150 qemu_chr_write_buffer(s, buf, offset, &offset, true); 151 return res; 152 } 153 154 res = qemu_chr_write_buffer(s, buf, len, &offset, write_all); 155 156 if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_RECORD) { 157 replay_char_write_event_save(res, offset); 158 } 159 160 if (res < 0) { 161 return res; 162 } 163 return offset; 164 } 165 166 int qemu_chr_be_can_write(Chardev *s) 167 { 168 CharBackend *be = s->be; 169 170 if (!be || !be->chr_can_read) { 171 return 0; 172 } 173 174 return be->chr_can_read(be->opaque); 175 } 176 177 void qemu_chr_be_write_impl(Chardev *s, uint8_t *buf, int len) 178 { 179 CharBackend *be = s->be; 180 181 if (be && be->chr_read) { 182 be->chr_read(be->opaque, buf, len); 183 } 184 } 185 186 void qemu_chr_be_write(Chardev *s, uint8_t *buf, int len) 187 { 188 if (qemu_chr_replay(s)) { 189 if (replay_mode == REPLAY_MODE_PLAY) { 190 return; 191 } 192 replay_chr_be_write(s, buf, len); 193 } else { 194 qemu_chr_be_write_impl(s, buf, len); 195 } 196 } 197 198 void qemu_chr_be_update_read_handlers(Chardev *s, 199 GMainContext *context) 200 { 201 ChardevClass *cc = CHARDEV_GET_CLASS(s); 202 203 assert(qemu_chr_has_feature(s, QEMU_CHAR_FEATURE_GCONTEXT) 204 || !context); 205 s->gcontext = context; 206 if (cc->chr_update_read_handler) { 207 cc->chr_update_read_handler(s); 208 } 209 } 210 211 int qemu_chr_add_client(Chardev *s, int fd) 212 { 213 return CHARDEV_GET_CLASS(s)->chr_add_client ? 214 CHARDEV_GET_CLASS(s)->chr_add_client(s, fd) : -1; 215 } 216 217 static void qemu_char_open(Chardev *chr, ChardevBackend *backend, 218 bool *be_opened, Error **errp) 219 { 220 ChardevClass *cc = CHARDEV_GET_CLASS(chr); 221 /* Any ChardevCommon member would work */ 222 ChardevCommon *common = backend ? backend->u.null.data : NULL; 223 224 if (common && common->has_logfile) { 225 int flags = O_WRONLY | O_CREAT; 226 if (common->has_logappend && 227 common->logappend) { 228 flags |= O_APPEND; 229 } else { 230 flags |= O_TRUNC; 231 } 232 chr->logfd = qemu_open(common->logfile, flags, 0666); 233 if (chr->logfd < 0) { 234 error_setg_errno(errp, errno, 235 "Unable to open logfile %s", 236 common->logfile); 237 return; 238 } 239 } 240 241 if (cc->open) { 242 cc->open(chr, backend, be_opened, errp); 243 } 244 } 245 246 static void char_init(Object *obj) 247 { 248 Chardev *chr = CHARDEV(obj); 249 250 chr->logfd = -1; 251 qemu_mutex_init(&chr->chr_write_lock); 252 253 /* 254 * Assume if chr_update_read_handler is implemented it will 255 * take the updated gcontext into account. 256 */ 257 if (CHARDEV_GET_CLASS(chr)->chr_update_read_handler) { 258 qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_GCONTEXT); 259 } 260 261 } 262 263 static int null_chr_write(Chardev *chr, const uint8_t *buf, int len) 264 { 265 return len; 266 } 267 268 static void char_class_init(ObjectClass *oc, void *data) 269 { 270 ChardevClass *cc = CHARDEV_CLASS(oc); 271 272 cc->chr_write = null_chr_write; 273 cc->chr_be_event = chr_be_event; 274 } 275 276 static void char_finalize(Object *obj) 277 { 278 Chardev *chr = CHARDEV(obj); 279 280 if (chr->be) { 281 chr->be->chr = NULL; 282 } 283 g_free(chr->filename); 284 g_free(chr->label); 285 if (chr->logfd != -1) { 286 close(chr->logfd); 287 } 288 qemu_mutex_destroy(&chr->chr_write_lock); 289 } 290 291 static const TypeInfo char_type_info = { 292 .name = TYPE_CHARDEV, 293 .parent = TYPE_OBJECT, 294 .instance_size = sizeof(Chardev), 295 .instance_init = char_init, 296 .instance_finalize = char_finalize, 297 .abstract = true, 298 .class_size = sizeof(ChardevClass), 299 .class_init = char_class_init, 300 }; 301 302 static int chardev_machine_done_notify_one(Object *child, void *opaque) 303 { 304 Chardev *chr = (Chardev *)child; 305 ChardevClass *class = CHARDEV_GET_CLASS(chr); 306 307 if (class->chr_machine_done) { 308 return class->chr_machine_done(chr); 309 } 310 311 return 0; 312 } 313 314 static void chardev_machine_done_hook(Notifier *notifier, void *unused) 315 { 316 int ret = object_child_foreach(get_chardevs_root(), 317 chardev_machine_done_notify_one, NULL); 318 319 if (ret) { 320 error_report("Failed to call chardev machine_done hooks"); 321 exit(1); 322 } 323 } 324 325 static Notifier chardev_machine_done_notify = { 326 .notify = chardev_machine_done_hook, 327 }; 328 329 static bool qemu_chr_is_busy(Chardev *s) 330 { 331 if (CHARDEV_IS_MUX(s)) { 332 MuxChardev *d = MUX_CHARDEV(s); 333 return d->mux_cnt >= 0; 334 } else { 335 return s->be != NULL; 336 } 337 } 338 339 int qemu_chr_wait_connected(Chardev *chr, Error **errp) 340 { 341 ChardevClass *cc = CHARDEV_GET_CLASS(chr); 342 343 if (cc->chr_wait_connected) { 344 return cc->chr_wait_connected(chr, errp); 345 } 346 347 return 0; 348 } 349 350 QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename, 351 bool permit_mux_mon) 352 { 353 char host[65], port[33], width[8], height[8]; 354 int pos; 355 const char *p; 356 QemuOpts *opts; 357 Error *local_err = NULL; 358 359 opts = qemu_opts_create(qemu_find_opts("chardev"), label, 1, &local_err); 360 if (local_err) { 361 error_report_err(local_err); 362 return NULL; 363 } 364 365 if (strstart(filename, "mon:", &p)) { 366 if (!permit_mux_mon) { 367 error_report("mon: isn't supported in this context"); 368 return NULL; 369 } 370 filename = p; 371 qemu_opt_set(opts, "mux", "on", &error_abort); 372 if (strcmp(filename, "stdio") == 0) { 373 /* Monitor is muxed to stdio: do not exit on Ctrl+C by default 374 * but pass it to the guest. Handle this only for compat syntax, 375 * for -chardev syntax we have special option for this. 376 * This is what -nographic did, redirecting+muxing serial+monitor 377 * to stdio causing Ctrl+C to be passed to guest. */ 378 qemu_opt_set(opts, "signal", "off", &error_abort); 379 } 380 } 381 382 if (strcmp(filename, "null") == 0 || 383 strcmp(filename, "pty") == 0 || 384 strcmp(filename, "msmouse") == 0 || 385 strcmp(filename, "wctablet") == 0 || 386 strcmp(filename, "braille") == 0 || 387 strcmp(filename, "testdev") == 0 || 388 strcmp(filename, "stdio") == 0) { 389 qemu_opt_set(opts, "backend", filename, &error_abort); 390 return opts; 391 } 392 if (strstart(filename, "vc", &p)) { 393 qemu_opt_set(opts, "backend", "vc", &error_abort); 394 if (*p == ':') { 395 if (sscanf(p+1, "%7[0-9]x%7[0-9]", width, height) == 2) { 396 /* pixels */ 397 qemu_opt_set(opts, "width", width, &error_abort); 398 qemu_opt_set(opts, "height", height, &error_abort); 399 } else if (sscanf(p+1, "%7[0-9]Cx%7[0-9]C", width, height) == 2) { 400 /* chars */ 401 qemu_opt_set(opts, "cols", width, &error_abort); 402 qemu_opt_set(opts, "rows", height, &error_abort); 403 } else { 404 goto fail; 405 } 406 } 407 return opts; 408 } 409 if (strcmp(filename, "con:") == 0) { 410 qemu_opt_set(opts, "backend", "console", &error_abort); 411 return opts; 412 } 413 if (strstart(filename, "COM", NULL)) { 414 qemu_opt_set(opts, "backend", "serial", &error_abort); 415 qemu_opt_set(opts, "path", filename, &error_abort); 416 return opts; 417 } 418 if (strstart(filename, "file:", &p)) { 419 qemu_opt_set(opts, "backend", "file", &error_abort); 420 qemu_opt_set(opts, "path", p, &error_abort); 421 return opts; 422 } 423 if (strstart(filename, "pipe:", &p)) { 424 qemu_opt_set(opts, "backend", "pipe", &error_abort); 425 qemu_opt_set(opts, "path", p, &error_abort); 426 return opts; 427 } 428 if (strstart(filename, "tcp:", &p) || 429 strstart(filename, "telnet:", &p) || 430 strstart(filename, "tn3270:", &p) || 431 strstart(filename, "websocket:", &p)) { 432 if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) { 433 host[0] = 0; 434 if (sscanf(p, ":%32[^,]%n", port, &pos) < 1) 435 goto fail; 436 } 437 qemu_opt_set(opts, "backend", "socket", &error_abort); 438 qemu_opt_set(opts, "host", host, &error_abort); 439 qemu_opt_set(opts, "port", port, &error_abort); 440 if (p[pos] == ',') { 441 qemu_opts_do_parse(opts, p+pos+1, NULL, &local_err); 442 if (local_err) { 443 error_report_err(local_err); 444 goto fail; 445 } 446 } 447 if (strstart(filename, "telnet:", &p)) { 448 qemu_opt_set(opts, "telnet", "on", &error_abort); 449 } else if (strstart(filename, "tn3270:", &p)) { 450 qemu_opt_set(opts, "tn3270", "on", &error_abort); 451 } else if (strstart(filename, "websocket:", &p)) { 452 qemu_opt_set(opts, "websocket", "on", &error_abort); 453 } 454 return opts; 455 } 456 if (strstart(filename, "udp:", &p)) { 457 qemu_opt_set(opts, "backend", "udp", &error_abort); 458 if (sscanf(p, "%64[^:]:%32[^@,]%n", host, port, &pos) < 2) { 459 host[0] = 0; 460 if (sscanf(p, ":%32[^@,]%n", port, &pos) < 1) { 461 goto fail; 462 } 463 } 464 qemu_opt_set(opts, "host", host, &error_abort); 465 qemu_opt_set(opts, "port", port, &error_abort); 466 if (p[pos] == '@') { 467 p += pos + 1; 468 if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) { 469 host[0] = 0; 470 if (sscanf(p, ":%32[^,]%n", port, &pos) < 1) { 471 goto fail; 472 } 473 } 474 qemu_opt_set(opts, "localaddr", host, &error_abort); 475 qemu_opt_set(opts, "localport", port, &error_abort); 476 } 477 return opts; 478 } 479 if (strstart(filename, "unix:", &p)) { 480 qemu_opt_set(opts, "backend", "socket", &error_abort); 481 qemu_opts_do_parse(opts, p, "path", &local_err); 482 if (local_err) { 483 error_report_err(local_err); 484 goto fail; 485 } 486 return opts; 487 } 488 if (strstart(filename, "/dev/parport", NULL) || 489 strstart(filename, "/dev/ppi", NULL)) { 490 qemu_opt_set(opts, "backend", "parallel", &error_abort); 491 qemu_opt_set(opts, "path", filename, &error_abort); 492 return opts; 493 } 494 if (strstart(filename, "/dev/", NULL)) { 495 qemu_opt_set(opts, "backend", "serial", &error_abort); 496 qemu_opt_set(opts, "path", filename, &error_abort); 497 return opts; 498 } 499 500 error_report("'%s' is not a valid char driver", filename); 501 502 fail: 503 qemu_opts_del(opts); 504 return NULL; 505 } 506 507 void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend) 508 { 509 const char *logfile = qemu_opt_get(opts, "logfile"); 510 511 backend->has_logfile = logfile != NULL; 512 backend->logfile = g_strdup(logfile); 513 514 backend->has_logappend = true; 515 backend->logappend = qemu_opt_get_bool(opts, "logappend", false); 516 } 517 518 static const ChardevClass *char_get_class(const char *driver, Error **errp) 519 { 520 ObjectClass *oc; 521 const ChardevClass *cc; 522 char *typename = g_strdup_printf("chardev-%s", driver); 523 524 oc = object_class_by_name(typename); 525 g_free(typename); 526 527 if (!object_class_dynamic_cast(oc, TYPE_CHARDEV)) { 528 error_setg(errp, "'%s' is not a valid char driver name", driver); 529 return NULL; 530 } 531 532 if (object_class_is_abstract(oc)) { 533 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver", 534 "abstract device type"); 535 return NULL; 536 } 537 538 cc = CHARDEV_CLASS(oc); 539 if (cc->internal) { 540 error_setg(errp, "'%s' is not a valid char driver name", driver); 541 return NULL; 542 } 543 544 return cc; 545 } 546 547 static const struct ChardevAlias { 548 const char *typename; 549 const char *alias; 550 } chardev_alias_table[] = { 551 #ifdef HAVE_CHARDEV_PARPORT 552 { "parallel", "parport" }, 553 #endif 554 #ifdef HAVE_CHARDEV_SERIAL 555 { "serial", "tty" }, 556 #endif 557 }; 558 559 typedef struct ChadevClassFE { 560 void (*fn)(const char *name, void *opaque); 561 void *opaque; 562 } ChadevClassFE; 563 564 static void 565 chardev_class_foreach(ObjectClass *klass, void *opaque) 566 { 567 ChadevClassFE *fe = opaque; 568 569 assert(g_str_has_prefix(object_class_get_name(klass), "chardev-")); 570 if (CHARDEV_CLASS(klass)->internal) { 571 return; 572 } 573 574 fe->fn(object_class_get_name(klass) + 8, fe->opaque); 575 } 576 577 static void 578 chardev_name_foreach(void (*fn)(const char *name, void *opaque), void *opaque) 579 { 580 ChadevClassFE fe = { .fn = fn, .opaque = opaque }; 581 int i; 582 583 object_class_foreach(chardev_class_foreach, TYPE_CHARDEV, false, &fe); 584 585 for (i = 0; i < (int)ARRAY_SIZE(chardev_alias_table); i++) { 586 fn(chardev_alias_table[i].alias, opaque); 587 } 588 } 589 590 static void 591 help_string_append(const char *name, void *opaque) 592 { 593 GString *str = opaque; 594 595 g_string_append_printf(str, "\n %s", name); 596 } 597 598 static const char *chardev_alias_translate(const char *name) 599 { 600 int i; 601 for (i = 0; i < (int)ARRAY_SIZE(chardev_alias_table); i++) { 602 if (g_strcmp0(chardev_alias_table[i].alias, name) == 0) { 603 return chardev_alias_table[i].typename; 604 } 605 } 606 return name; 607 } 608 609 ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts, Error **errp) 610 { 611 Error *local_err = NULL; 612 const ChardevClass *cc; 613 ChardevBackend *backend = NULL; 614 const char *name = chardev_alias_translate(qemu_opt_get(opts, "backend")); 615 616 if (name == NULL) { 617 error_setg(errp, "chardev: \"%s\" missing backend", 618 qemu_opts_id(opts)); 619 return NULL; 620 } 621 622 cc = char_get_class(name, errp); 623 if (cc == NULL) { 624 return NULL; 625 } 626 627 backend = g_new0(ChardevBackend, 1); 628 backend->type = CHARDEV_BACKEND_KIND_NULL; 629 630 if (cc->parse) { 631 cc->parse(opts, backend, &local_err); 632 if (local_err) { 633 error_propagate(errp, local_err); 634 qapi_free_ChardevBackend(backend); 635 return NULL; 636 } 637 } else { 638 ChardevCommon *ccom = g_new0(ChardevCommon, 1); 639 qemu_chr_parse_common(opts, ccom); 640 backend->u.null.data = ccom; /* Any ChardevCommon member would work */ 641 } 642 643 return backend; 644 } 645 646 Chardev *qemu_chr_new_from_opts(QemuOpts *opts, GMainContext *context, 647 Error **errp) 648 { 649 const ChardevClass *cc; 650 Chardev *chr = NULL; 651 ChardevBackend *backend = NULL; 652 const char *name = chardev_alias_translate(qemu_opt_get(opts, "backend")); 653 const char *id = qemu_opts_id(opts); 654 char *bid = NULL; 655 656 if (name && is_help_option(name)) { 657 GString *str = g_string_new(""); 658 659 chardev_name_foreach(help_string_append, str); 660 661 qemu_printf("Available chardev backend types: %s\n", str->str); 662 g_string_free(str, true); 663 return NULL; 664 } 665 666 if (id == NULL) { 667 error_setg(errp, "chardev: no id specified"); 668 return NULL; 669 } 670 671 backend = qemu_chr_parse_opts(opts, errp); 672 if (backend == NULL) { 673 return NULL; 674 } 675 676 cc = char_get_class(name, errp); 677 if (cc == NULL) { 678 goto out; 679 } 680 681 if (qemu_opt_get_bool(opts, "mux", 0)) { 682 bid = g_strdup_printf("%s-base", id); 683 } 684 685 chr = qemu_chardev_new(bid ? bid : id, 686 object_class_get_name(OBJECT_CLASS(cc)), 687 backend, context, errp); 688 689 if (chr == NULL) { 690 goto out; 691 } 692 693 if (bid) { 694 Chardev *mux; 695 qapi_free_ChardevBackend(backend); 696 backend = g_new0(ChardevBackend, 1); 697 backend->type = CHARDEV_BACKEND_KIND_MUX; 698 backend->u.mux.data = g_new0(ChardevMux, 1); 699 backend->u.mux.data->chardev = g_strdup(bid); 700 mux = qemu_chardev_new(id, TYPE_CHARDEV_MUX, backend, context, errp); 701 if (mux == NULL) { 702 object_unparent(OBJECT(chr)); 703 chr = NULL; 704 goto out; 705 } 706 chr = mux; 707 } 708 709 out: 710 qapi_free_ChardevBackend(backend); 711 g_free(bid); 712 return chr; 713 } 714 715 Chardev *qemu_chr_new_noreplay(const char *label, const char *filename, 716 bool permit_mux_mon, GMainContext *context) 717 { 718 const char *p; 719 Chardev *chr; 720 QemuOpts *opts; 721 Error *err = NULL; 722 723 if (strstart(filename, "chardev:", &p)) { 724 return qemu_chr_find(p); 725 } 726 727 opts = qemu_chr_parse_compat(label, filename, permit_mux_mon); 728 if (!opts) 729 return NULL; 730 731 chr = qemu_chr_new_from_opts(opts, context, &err); 732 if (!chr) { 733 error_report_err(err); 734 goto out; 735 } 736 737 if (qemu_opt_get_bool(opts, "mux", 0)) { 738 assert(permit_mux_mon); 739 monitor_init_hmp(chr, true); 740 } 741 742 out: 743 qemu_opts_del(opts); 744 return chr; 745 } 746 747 static Chardev *qemu_chr_new_permit_mux_mon(const char *label, 748 const char *filename, 749 bool permit_mux_mon, 750 GMainContext *context) 751 { 752 Chardev *chr; 753 chr = qemu_chr_new_noreplay(label, filename, permit_mux_mon, context); 754 if (chr) { 755 if (replay_mode != REPLAY_MODE_NONE) { 756 qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_REPLAY); 757 } 758 if (qemu_chr_replay(chr) && CHARDEV_GET_CLASS(chr)->chr_ioctl) { 759 error_report("Replay: ioctl is not supported " 760 "for serial devices yet"); 761 } 762 replay_register_char_driver(chr); 763 } 764 return chr; 765 } 766 767 Chardev *qemu_chr_new(const char *label, const char *filename, 768 GMainContext *context) 769 { 770 return qemu_chr_new_permit_mux_mon(label, filename, false, context); 771 } 772 773 Chardev *qemu_chr_new_mux_mon(const char *label, const char *filename, 774 GMainContext *context) 775 { 776 return qemu_chr_new_permit_mux_mon(label, filename, true, context); 777 } 778 779 static int qmp_query_chardev_foreach(Object *obj, void *data) 780 { 781 Chardev *chr = CHARDEV(obj); 782 ChardevInfoList **list = data; 783 ChardevInfoList *info = g_malloc0(sizeof(*info)); 784 785 info->value = g_malloc0(sizeof(*info->value)); 786 info->value->label = g_strdup(chr->label); 787 info->value->filename = g_strdup(chr->filename); 788 info->value->frontend_open = chr->be && chr->be->fe_open; 789 790 info->next = *list; 791 *list = info; 792 793 return 0; 794 } 795 796 ChardevInfoList *qmp_query_chardev(Error **errp) 797 { 798 ChardevInfoList *chr_list = NULL; 799 800 object_child_foreach(get_chardevs_root(), 801 qmp_query_chardev_foreach, &chr_list); 802 803 return chr_list; 804 } 805 806 static void 807 qmp_prepend_backend(const char *name, void *opaque) 808 { 809 ChardevBackendInfoList **list = opaque; 810 ChardevBackendInfoList *info = g_malloc0(sizeof(*info)); 811 812 info->value = g_malloc0(sizeof(*info->value)); 813 info->value->name = g_strdup(name); 814 info->next = *list; 815 *list = info; 816 } 817 818 ChardevBackendInfoList *qmp_query_chardev_backends(Error **errp) 819 { 820 ChardevBackendInfoList *backend_list = NULL; 821 822 chardev_name_foreach(qmp_prepend_backend, &backend_list); 823 824 return backend_list; 825 } 826 827 Chardev *qemu_chr_find(const char *name) 828 { 829 Object *obj = object_resolve_path_component(get_chardevs_root(), name); 830 831 return obj ? CHARDEV(obj) : NULL; 832 } 833 834 QemuOptsList qemu_chardev_opts = { 835 .name = "chardev", 836 .implied_opt_name = "backend", 837 .head = QTAILQ_HEAD_INITIALIZER(qemu_chardev_opts.head), 838 .desc = { 839 { 840 .name = "backend", 841 .type = QEMU_OPT_STRING, 842 },{ 843 .name = "path", 844 .type = QEMU_OPT_STRING, 845 },{ 846 .name = "host", 847 .type = QEMU_OPT_STRING, 848 },{ 849 .name = "port", 850 .type = QEMU_OPT_STRING, 851 },{ 852 .name = "fd", 853 .type = QEMU_OPT_STRING, 854 },{ 855 .name = "localaddr", 856 .type = QEMU_OPT_STRING, 857 },{ 858 .name = "localport", 859 .type = QEMU_OPT_STRING, 860 },{ 861 .name = "to", 862 .type = QEMU_OPT_NUMBER, 863 },{ 864 .name = "ipv4", 865 .type = QEMU_OPT_BOOL, 866 },{ 867 .name = "ipv6", 868 .type = QEMU_OPT_BOOL, 869 },{ 870 .name = "wait", 871 .type = QEMU_OPT_BOOL, 872 },{ 873 .name = "server", 874 .type = QEMU_OPT_BOOL, 875 },{ 876 .name = "delay", 877 .type = QEMU_OPT_BOOL, 878 },{ 879 .name = "reconnect", 880 .type = QEMU_OPT_NUMBER, 881 },{ 882 .name = "telnet", 883 .type = QEMU_OPT_BOOL, 884 },{ 885 .name = "tn3270", 886 .type = QEMU_OPT_BOOL, 887 },{ 888 .name = "tls-creds", 889 .type = QEMU_OPT_STRING, 890 },{ 891 .name = "tls-authz", 892 .type = QEMU_OPT_STRING, 893 },{ 894 .name = "websocket", 895 .type = QEMU_OPT_BOOL, 896 },{ 897 .name = "width", 898 .type = QEMU_OPT_NUMBER, 899 },{ 900 .name = "height", 901 .type = QEMU_OPT_NUMBER, 902 },{ 903 .name = "cols", 904 .type = QEMU_OPT_NUMBER, 905 },{ 906 .name = "rows", 907 .type = QEMU_OPT_NUMBER, 908 },{ 909 .name = "mux", 910 .type = QEMU_OPT_BOOL, 911 },{ 912 .name = "signal", 913 .type = QEMU_OPT_BOOL, 914 },{ 915 .name = "name", 916 .type = QEMU_OPT_STRING, 917 },{ 918 .name = "debug", 919 .type = QEMU_OPT_NUMBER, 920 },{ 921 .name = "size", 922 .type = QEMU_OPT_SIZE, 923 },{ 924 .name = "chardev", 925 .type = QEMU_OPT_STRING, 926 },{ 927 .name = "append", 928 .type = QEMU_OPT_BOOL, 929 },{ 930 .name = "logfile", 931 .type = QEMU_OPT_STRING, 932 },{ 933 .name = "logappend", 934 .type = QEMU_OPT_BOOL, 935 }, 936 { /* end of list */ } 937 }, 938 }; 939 940 bool qemu_chr_has_feature(Chardev *chr, 941 ChardevFeature feature) 942 { 943 return test_bit(feature, chr->features); 944 } 945 946 void qemu_chr_set_feature(Chardev *chr, 947 ChardevFeature feature) 948 { 949 return set_bit(feature, chr->features); 950 } 951 952 Chardev *qemu_chardev_new(const char *id, const char *typename, 953 ChardevBackend *backend, 954 GMainContext *gcontext, 955 Error **errp) 956 { 957 Object *obj; 958 Chardev *chr = NULL; 959 Error *local_err = NULL; 960 bool be_opened = true; 961 962 assert(g_str_has_prefix(typename, "chardev-")); 963 964 obj = object_new(typename); 965 chr = CHARDEV(obj); 966 chr->label = g_strdup(id); 967 chr->gcontext = gcontext; 968 969 qemu_char_open(chr, backend, &be_opened, &local_err); 970 if (local_err) { 971 goto end; 972 } 973 974 if (!chr->filename) { 975 chr->filename = g_strdup(typename + 8); 976 } 977 if (be_opened) { 978 qemu_chr_be_event(chr, CHR_EVENT_OPENED); 979 } 980 981 if (id) { 982 object_property_add_child(get_chardevs_root(), id, obj, &local_err); 983 if (local_err) { 984 goto end; 985 } 986 object_unref(obj); 987 } 988 989 end: 990 if (local_err) { 991 error_propagate(errp, local_err); 992 object_unref(obj); 993 return NULL; 994 } 995 996 return chr; 997 } 998 999 ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend, 1000 Error **errp) 1001 { 1002 const ChardevClass *cc; 1003 ChardevReturn *ret; 1004 Chardev *chr; 1005 1006 cc = char_get_class(ChardevBackendKind_str(backend->type), errp); 1007 if (!cc) { 1008 return NULL; 1009 } 1010 1011 chr = qemu_chardev_new(id, object_class_get_name(OBJECT_CLASS(cc)), 1012 backend, NULL, errp); 1013 if (!chr) { 1014 return NULL; 1015 } 1016 1017 ret = g_new0(ChardevReturn, 1); 1018 if (CHARDEV_IS_PTY(chr)) { 1019 ret->pty = g_strdup(chr->filename + 4); 1020 ret->has_pty = true; 1021 } 1022 1023 return ret; 1024 } 1025 1026 ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend, 1027 Error **errp) 1028 { 1029 CharBackend *be; 1030 const ChardevClass *cc; 1031 Chardev *chr, *chr_new; 1032 bool closed_sent = false; 1033 ChardevReturn *ret; 1034 1035 chr = qemu_chr_find(id); 1036 if (!chr) { 1037 error_setg(errp, "Chardev '%s' does not exist", id); 1038 return NULL; 1039 } 1040 1041 if (CHARDEV_IS_MUX(chr)) { 1042 error_setg(errp, "Mux device hotswap not supported yet"); 1043 return NULL; 1044 } 1045 1046 if (qemu_chr_replay(chr)) { 1047 error_setg(errp, 1048 "Chardev '%s' cannot be changed in record/replay mode", id); 1049 return NULL; 1050 } 1051 1052 be = chr->be; 1053 if (!be) { 1054 /* easy case */ 1055 object_unparent(OBJECT(chr)); 1056 return qmp_chardev_add(id, backend, errp); 1057 } 1058 1059 if (!be->chr_be_change) { 1060 error_setg(errp, "Chardev user does not support chardev hotswap"); 1061 return NULL; 1062 } 1063 1064 cc = char_get_class(ChardevBackendKind_str(backend->type), errp); 1065 if (!cc) { 1066 return NULL; 1067 } 1068 1069 chr_new = qemu_chardev_new(NULL, object_class_get_name(OBJECT_CLASS(cc)), 1070 backend, chr->gcontext, errp); 1071 if (!chr_new) { 1072 return NULL; 1073 } 1074 chr_new->label = g_strdup(id); 1075 1076 if (chr->be_open && !chr_new->be_open) { 1077 qemu_chr_be_event(chr, CHR_EVENT_CLOSED); 1078 closed_sent = true; 1079 } 1080 1081 chr->be = NULL; 1082 qemu_chr_fe_init(be, chr_new, &error_abort); 1083 1084 if (be->chr_be_change(be->opaque) < 0) { 1085 error_setg(errp, "Chardev '%s' change failed", chr_new->label); 1086 chr_new->be = NULL; 1087 qemu_chr_fe_init(be, chr, &error_abort); 1088 if (closed_sent) { 1089 qemu_chr_be_event(chr, CHR_EVENT_OPENED); 1090 } 1091 object_unref(OBJECT(chr_new)); 1092 return NULL; 1093 } 1094 1095 object_unparent(OBJECT(chr)); 1096 object_property_add_child(get_chardevs_root(), chr_new->label, 1097 OBJECT(chr_new), &error_abort); 1098 object_unref(OBJECT(chr_new)); 1099 1100 ret = g_new0(ChardevReturn, 1); 1101 if (CHARDEV_IS_PTY(chr_new)) { 1102 ret->pty = g_strdup(chr_new->filename + 4); 1103 ret->has_pty = true; 1104 } 1105 1106 return ret; 1107 } 1108 1109 void qmp_chardev_remove(const char *id, Error **errp) 1110 { 1111 Chardev *chr; 1112 1113 chr = qemu_chr_find(id); 1114 if (chr == NULL) { 1115 error_setg(errp, "Chardev '%s' not found", id); 1116 return; 1117 } 1118 if (qemu_chr_is_busy(chr)) { 1119 error_setg(errp, "Chardev '%s' is busy", id); 1120 return; 1121 } 1122 if (qemu_chr_replay(chr)) { 1123 error_setg(errp, 1124 "Chardev '%s' cannot be unplugged in record/replay mode", id); 1125 return; 1126 } 1127 object_unparent(OBJECT(chr)); 1128 } 1129 1130 void qmp_chardev_send_break(const char *id, Error **errp) 1131 { 1132 Chardev *chr; 1133 1134 chr = qemu_chr_find(id); 1135 if (chr == NULL) { 1136 error_setg(errp, "Chardev '%s' not found", id); 1137 return; 1138 } 1139 qemu_chr_be_event(chr, CHR_EVENT_BREAK); 1140 } 1141 1142 /* 1143 * Add a timeout callback for the chardev (in milliseconds), return 1144 * the GSource object created. Please use this to add timeout hook for 1145 * chardev instead of g_timeout_add() and g_timeout_add_seconds(), to 1146 * make sure the gcontext that the task bound to is correct. 1147 */ 1148 GSource *qemu_chr_timeout_add_ms(Chardev *chr, guint ms, 1149 GSourceFunc func, void *private) 1150 { 1151 GSource *source = g_timeout_source_new(ms); 1152 1153 assert(func); 1154 g_source_set_callback(source, func, private, NULL); 1155 g_source_attach(source, chr->gcontext); 1156 1157 return source; 1158 } 1159 1160 void qemu_chr_cleanup(void) 1161 { 1162 object_unparent(get_chardevs_root()); 1163 } 1164 1165 static void register_types(void) 1166 { 1167 type_register_static(&char_type_info); 1168 1169 /* this must be done after machine init, since we register FEs with muxes 1170 * as part of realize functions like serial_isa_realizefn when -nographic 1171 * is specified 1172 */ 1173 qemu_add_machine_init_done_notifier(&chardev_machine_done_notify); 1174 } 1175 1176 type_init(register_types); 1177