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 "qapi/error.h" 27 #include "qemu/module.h" 28 #include "qemu/option.h" 29 #include "qemu/bitops.h" 30 #include "chardev/char.h" 31 #include "sysemu/block-backend.h" 32 #include "qapi/qapi-commands-control.h" 33 #include "chardev-internal.h" 34 35 /* MUX driver for serial I/O splitting */ 36 37 /* 38 * Set to false by suspend_mux_open. Open events are delayed until 39 * resume_mux_open. Usually suspend_mux_open is called before 40 * command line processing and resume_mux_open afterwards. 41 */ 42 static bool muxes_opened = true; 43 44 /* Called with chr_write_lock held. */ 45 static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len) 46 { 47 MuxChardev *d = MUX_CHARDEV(chr); 48 int ret; 49 if (!d->timestamps) { 50 ret = qemu_chr_fe_write(&d->chr, buf, len); 51 } else { 52 int i; 53 54 ret = 0; 55 for (i = 0; i < len; i++) { 56 if (d->linestart) { 57 char buf1[64]; 58 int64_t ti; 59 int secs; 60 61 ti = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); 62 if (d->timestamps_start == -1) { 63 d->timestamps_start = ti; 64 } 65 ti -= d->timestamps_start; 66 secs = ti / 1000; 67 snprintf(buf1, sizeof(buf1), 68 "[%02d:%02d:%02d.%03d] ", 69 secs / 3600, 70 (secs / 60) % 60, 71 secs % 60, 72 (int)(ti % 1000)); 73 /* XXX this blocks entire thread. Rewrite to use 74 * qemu_chr_fe_write and background I/O callbacks */ 75 qemu_chr_fe_write_all(&d->chr, 76 (uint8_t *)buf1, strlen(buf1)); 77 d->linestart = false; 78 } 79 ret += qemu_chr_fe_write(&d->chr, buf + i, 1); 80 if (buf[i] == '\n') { 81 d->linestart = true; 82 } 83 } 84 } 85 return ret; 86 } 87 88 static const char * const mux_help[] = { 89 "% h print this help\n\r", 90 "% x exit emulator\n\r", 91 "% s save disk data back to file (if -snapshot)\n\r", 92 "% t toggle console timestamps\n\r", 93 "% b send break (magic sysrq)\n\r", 94 "% c switch between console and monitor\n\r", 95 "% % sends %\n\r", 96 NULL 97 }; 98 99 int term_escape_char = 0x01; /* ctrl-a is used for escape */ 100 static void mux_print_help(Chardev *chr) 101 { 102 int i, j; 103 char ebuf[15] = "Escape-Char"; 104 char cbuf[50] = "\n\r"; 105 106 if (term_escape_char > 0 && term_escape_char < 26) { 107 snprintf(cbuf, sizeof(cbuf), "\n\r"); 108 snprintf(ebuf, sizeof(ebuf), "C-%c", term_escape_char - 1 + 'a'); 109 } else { 110 snprintf(cbuf, sizeof(cbuf), 111 "\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r", 112 term_escape_char); 113 } 114 /* XXX this blocks entire thread. Rewrite to use 115 * qemu_chr_fe_write and background I/O callbacks */ 116 qemu_chr_write_all(chr, (uint8_t *)cbuf, strlen(cbuf)); 117 for (i = 0; mux_help[i] != NULL; i++) { 118 for (j = 0; mux_help[i][j] != '\0'; j++) { 119 if (mux_help[i][j] == '%') { 120 qemu_chr_write_all(chr, (uint8_t *)ebuf, strlen(ebuf)); 121 } else { 122 qemu_chr_write_all(chr, (uint8_t *)&mux_help[i][j], 1); 123 } 124 } 125 } 126 } 127 128 static void mux_chr_send_event(MuxChardev *d, unsigned int mux_nr, 129 QEMUChrEvent event) 130 { 131 CharBackend *be = d->backends[mux_nr]; 132 133 if (be && be->chr_event) { 134 be->chr_event(be->opaque, event); 135 } 136 } 137 138 static void mux_chr_be_event(Chardev *chr, QEMUChrEvent event) 139 { 140 MuxChardev *d = MUX_CHARDEV(chr); 141 142 if (d->focus != -1) { 143 mux_chr_send_event(d, d->focus, event); 144 } 145 } 146 147 static int mux_proc_byte(Chardev *chr, MuxChardev *d, int ch) 148 { 149 if (d->term_got_escape) { 150 d->term_got_escape = false; 151 if (ch == term_escape_char) { 152 goto send_char; 153 } 154 switch (ch) { 155 case '?': 156 case 'h': 157 mux_print_help(chr); 158 break; 159 case 'x': 160 { 161 const char *term = "QEMU: Terminated\n\r"; 162 qemu_chr_write_all(chr, (uint8_t *)term, strlen(term)); 163 qmp_quit(NULL); 164 break; 165 } 166 case 's': 167 blk_commit_all(); 168 break; 169 case 'b': 170 qemu_chr_be_event(chr, CHR_EVENT_BREAK); 171 break; 172 case 'c': { 173 unsigned int bit; 174 175 /* Handler registered with first fe */ 176 assert(d->mux_bitset != 0); 177 /* Switch to the next registered device */ 178 bit = find_next_bit(&d->mux_bitset, MAX_MUX, d->focus + 1); 179 if (bit >= MAX_MUX) { 180 bit = find_next_bit(&d->mux_bitset, MAX_MUX, 0); 181 } 182 mux_set_focus(chr, bit); 183 break; 184 } case 't': 185 d->timestamps = !d->timestamps; 186 d->timestamps_start = -1; 187 d->linestart = false; 188 break; 189 } 190 } else if (ch == term_escape_char) { 191 d->term_got_escape = true; 192 } else { 193 send_char: 194 return 1; 195 } 196 return 0; 197 } 198 199 static void mux_chr_accept_input(Chardev *chr) 200 { 201 MuxChardev *d = MUX_CHARDEV(chr); 202 int m = d->focus; 203 CharBackend *be = d->backends[m]; 204 205 while (be && d->prod[m] != d->cons[m] && 206 be->chr_can_read && be->chr_can_read(be->opaque)) { 207 be->chr_read(be->opaque, 208 &d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1); 209 } 210 } 211 212 static int mux_chr_can_read(void *opaque) 213 { 214 MuxChardev *d = MUX_CHARDEV(opaque); 215 int m = d->focus; 216 CharBackend *be = d->backends[m]; 217 218 if ((d->prod[m] - d->cons[m]) < MUX_BUFFER_SIZE) { 219 return 1; 220 } 221 222 if (be && be->chr_can_read) { 223 return be->chr_can_read(be->opaque); 224 } 225 226 return 0; 227 } 228 229 static void mux_chr_read(void *opaque, const uint8_t *buf, int size) 230 { 231 Chardev *chr = CHARDEV(opaque); 232 MuxChardev *d = MUX_CHARDEV(opaque); 233 int m = d->focus; 234 CharBackend *be = d->backends[m]; 235 int i; 236 237 mux_chr_accept_input(opaque); 238 239 for (i = 0; i < size; i++) 240 if (mux_proc_byte(chr, d, buf[i])) { 241 if (d->prod[m] == d->cons[m] && 242 be && be->chr_can_read && 243 be->chr_can_read(be->opaque)) { 244 be->chr_read(be->opaque, &buf[i], 1); 245 } else { 246 d->buffer[m][d->prod[m]++ & MUX_BUFFER_MASK] = buf[i]; 247 } 248 } 249 } 250 251 void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event) 252 { 253 MuxChardev *d = MUX_CHARDEV(chr); 254 int bit; 255 256 if (!muxes_opened) { 257 return; 258 } 259 260 /* Send the event to all registered listeners */ 261 bit = -1; 262 while ((bit = find_next_bit(&d->mux_bitset, MAX_MUX, bit + 1)) < MAX_MUX) { 263 mux_chr_send_event(d, bit, event); 264 } 265 } 266 267 static void mux_chr_event(void *opaque, QEMUChrEvent event) 268 { 269 mux_chr_send_all_event(CHARDEV(opaque), event); 270 } 271 272 static GSource *mux_chr_add_watch(Chardev *s, GIOCondition cond) 273 { 274 MuxChardev *d = MUX_CHARDEV(s); 275 Chardev *chr = qemu_chr_fe_get_driver(&d->chr); 276 ChardevClass *cc = CHARDEV_GET_CLASS(chr); 277 278 if (!cc->chr_add_watch) { 279 return NULL; 280 } 281 282 return cc->chr_add_watch(chr, cond); 283 } 284 285 static void char_mux_finalize(Object *obj) 286 { 287 MuxChardev *d = MUX_CHARDEV(obj); 288 int bit; 289 290 bit = -1; 291 while ((bit = find_next_bit(&d->mux_bitset, MAX_MUX, bit + 1)) < MAX_MUX) { 292 CharBackend *be = d->backends[bit]; 293 be->chr = NULL; 294 d->backends[bit] = NULL; 295 } 296 d->mux_bitset = 0; 297 qemu_chr_fe_deinit(&d->chr, false); 298 } 299 300 static void mux_chr_update_read_handlers(Chardev *chr) 301 { 302 MuxChardev *d = MUX_CHARDEV(chr); 303 304 /* Fix up the real driver with mux routines */ 305 qemu_chr_fe_set_handlers_full(&d->chr, 306 mux_chr_can_read, 307 mux_chr_read, 308 mux_chr_event, 309 NULL, 310 chr, 311 chr->gcontext, true, false); 312 } 313 314 bool mux_chr_attach_frontend(MuxChardev *d, CharBackend *b, 315 unsigned int *tag, Error **errp) 316 { 317 unsigned int bit; 318 319 bit = find_next_zero_bit(&d->mux_bitset, MAX_MUX, 0); 320 if (bit >= MAX_MUX) { 321 error_setg(errp, 322 "too many uses of multiplexed chardev '%s'" 323 " (maximum is " stringify(MAX_MUX) ")", 324 d->parent.label); 325 return false; 326 } 327 328 d->mux_bitset |= (1 << bit); 329 d->backends[bit] = b; 330 *tag = bit; 331 332 return true; 333 } 334 335 bool mux_chr_detach_frontend(MuxChardev *d, unsigned int tag) 336 { 337 unsigned int bit; 338 339 bit = find_next_bit(&d->mux_bitset, MAX_MUX, tag); 340 if (bit != tag) { 341 return false; 342 } 343 344 d->mux_bitset &= ~(1 << bit); 345 d->backends[bit] = NULL; 346 347 return true; 348 } 349 350 void mux_set_focus(Chardev *chr, unsigned int focus) 351 { 352 MuxChardev *d = MUX_CHARDEV(chr); 353 354 assert(find_next_bit(&d->mux_bitset, MAX_MUX, focus) == focus); 355 356 if (d->focus != -1) { 357 mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT); 358 } 359 360 d->focus = focus; 361 chr->be = d->backends[focus]; 362 mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN); 363 } 364 365 static void qemu_chr_open_mux(Chardev *chr, 366 ChardevBackend *backend, 367 bool *be_opened, 368 Error **errp) 369 { 370 ChardevMux *mux = backend->u.mux.data; 371 Chardev *drv; 372 MuxChardev *d = MUX_CHARDEV(chr); 373 374 drv = qemu_chr_find(mux->chardev); 375 if (drv == NULL) { 376 error_setg(errp, "mux: base chardev %s not found", mux->chardev); 377 return; 378 } 379 380 d->focus = -1; 381 /* only default to opened state if we've realized the initial 382 * set of muxes 383 */ 384 *be_opened = muxes_opened; 385 qemu_chr_fe_init(&d->chr, drv, errp); 386 } 387 388 static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend, 389 Error **errp) 390 { 391 const char *chardev = qemu_opt_get(opts, "chardev"); 392 ChardevMux *mux; 393 394 if (chardev == NULL) { 395 error_setg(errp, "chardev: mux: no chardev given"); 396 return; 397 } 398 backend->type = CHARDEV_BACKEND_KIND_MUX; 399 mux = backend->u.mux.data = g_new0(ChardevMux, 1); 400 qemu_chr_parse_common(opts, qapi_ChardevMux_base(mux)); 401 mux->chardev = g_strdup(chardev); 402 } 403 404 /** 405 * Called after processing of default and command-line-specified 406 * chardevs to deliver CHR_EVENT_OPENED events to any FEs attached 407 * to a mux chardev. This is done here to ensure that 408 * output/prompts/banners are only displayed for the FE that has 409 * focus when initial command-line processing/machine init is 410 * completed. 411 * 412 * After this point, any new FE attached to any new or existing 413 * mux will receive CHR_EVENT_OPENED notifications for the BE 414 * immediately. 415 */ 416 static void open_muxes(Chardev *chr) 417 { 418 /* send OPENED to all already-attached FEs */ 419 mux_chr_send_all_event(chr, CHR_EVENT_OPENED); 420 421 /* 422 * mark mux as OPENED so any new FEs will immediately receive 423 * OPENED event 424 */ 425 chr->be_open = 1; 426 } 427 428 void suspend_mux_open(void) 429 { 430 muxes_opened = false; 431 } 432 433 static int chardev_options_parsed_cb(Object *child, void *opaque) 434 { 435 Chardev *chr = (Chardev *)child; 436 437 if (!chr->be_open && CHARDEV_IS_MUX(chr)) { 438 open_muxes(chr); 439 } 440 441 return 0; 442 } 443 444 void resume_mux_open(void) 445 { 446 muxes_opened = true; 447 object_child_foreach(get_chardevs_root(), 448 chardev_options_parsed_cb, NULL); 449 } 450 451 static void char_mux_class_init(ObjectClass *oc, void *data) 452 { 453 ChardevClass *cc = CHARDEV_CLASS(oc); 454 455 cc->parse = qemu_chr_parse_mux; 456 cc->open = qemu_chr_open_mux; 457 cc->chr_write = mux_chr_write; 458 cc->chr_accept_input = mux_chr_accept_input; 459 cc->chr_add_watch = mux_chr_add_watch; 460 cc->chr_be_event = mux_chr_be_event; 461 cc->chr_update_read_handler = mux_chr_update_read_handlers; 462 } 463 464 static const TypeInfo char_mux_type_info = { 465 .name = TYPE_CHARDEV_MUX, 466 .parent = TYPE_CHARDEV, 467 .class_init = char_mux_class_init, 468 .instance_size = sizeof(MuxChardev), 469 .instance_finalize = char_mux_finalize, 470 }; 471 472 static void register_types(void) 473 { 474 type_register_static(&char_mux_type_info); 475 } 476 477 type_init(register_types); 478