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