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