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