1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1991 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Systems Programming Group of the University of Utah Computer 8 * Science Department. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * from: @(#)cons.c 7.2 (Berkeley) 5/9/91 39 * $FreeBSD: src/sys/kern/tty_cons.c,v 1.81.2.4 2001/12/17 18:44:41 guido Exp $ 40 * $DragonFly: src/sys/kern/tty_cons.c,v 1.14 2004/09/13 16:22:36 dillon Exp $ 41 */ 42 43 #include "opt_ddb.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/conf.h> 48 #include <sys/cons.h> 49 #include <sys/kernel.h> 50 #include <sys/proc.h> 51 #include <sys/reboot.h> 52 #include <sys/sysctl.h> 53 #include <sys/tty.h> 54 #include <sys/uio.h> 55 #include <sys/msgport.h> 56 #include <sys/msgport2.h> 57 #include <sys/device.h> 58 59 #include <ddb/ddb.h> 60 61 #include <machine/cpu.h> 62 63 static int cnopen(struct cdevmsg_open *msg); 64 static int cnclose(struct cdevmsg_close *msg); 65 static int cnread(struct cdevmsg_read *msg); 66 static int cnwrite(struct cdevmsg_write *msg); 67 static int cnioctl(struct cdevmsg_ioctl *msg); 68 static int cnpoll(struct cdevmsg_poll *msg); 69 static int cnkqfilter(struct cdevmsg_kqfilter *msg); 70 71 static int console_putport(lwkt_port_t port, lwkt_msg_t lmsg); 72 static int console_interceptport(lwkt_port_t port, lwkt_msg_t lmsg); 73 74 static struct lwkt_port cn_port; /* console device port */ 75 static struct lwkt_port cn_iport; /* intercept port */ 76 77 #define CDEV_MAJOR 0 78 static struct cdevsw cn_cdevsw = { 79 /* name */ "console", 80 /* maj */ CDEV_MAJOR, 81 /* flags */ D_TTY | D_KQFILTER, 82 /* port */ &cn_port, 83 /* clone */ NULL 84 }; 85 86 static dev_t cn_dev_t; 87 static udev_t cn_udev_t; 88 SYSCTL_OPAQUE(_machdep, CPU_CONSDEV, consdev, CTLFLAG_RD, 89 &cn_udev_t, sizeof cn_udev_t, "T,dev_t", ""); 90 91 static int cn_mute; 92 93 int cons_unavail = 0; /* XXX: 94 * physical console not available for 95 * input (i.e., it is in graphics mode) 96 */ 97 98 static u_char cn_is_open; /* nonzero if logical console is open */ 99 static int openmode, openflag; /* how /dev/console was openned */ 100 static dev_t cn_devfsdev; /* represents the device private info */ 101 static u_char cn_phys_is_open; /* nonzero if physical device is open */ 102 struct consdev *cn_tab; /* physical console device info */ 103 static u_char console_pausing; /* pause after each line during probe */ 104 static char *console_pausestr= 105 "<pause; press any key to proceed to next line or '.' to end pause mode>"; 106 107 static lwkt_port_t cn_fwd_port; 108 109 CONS_DRIVER(cons, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 110 SET_DECLARE(cons_set, struct consdev); 111 112 void 113 cninit() 114 { 115 struct consdev *best_cp, *cp, **list; 116 117 /* 118 * Our port intercept 119 */ 120 lwkt_initport(&cn_port, NULL); 121 cn_port.mp_putport = console_putport; 122 lwkt_initport(&cn_iport, NULL); 123 cn_iport.mp_putport = console_interceptport; 124 125 /* 126 * Find the first console with the highest priority. 127 */ 128 best_cp = NULL; 129 SET_FOREACH(list, cons_set) { 130 cp = *list; 131 if (cp->cn_probe == NULL) 132 continue; 133 (*cp->cn_probe)(cp); 134 if (cp->cn_pri > CN_DEAD && 135 (best_cp == NULL || cp->cn_pri > best_cp->cn_pri)) 136 best_cp = cp; 137 } 138 139 /* 140 * Check if we should mute the console (for security reasons perhaps) 141 * It can be changes dynamically using sysctl kern.consmute 142 * once we are up and going. 143 * 144 */ 145 cn_mute = ((boothowto & (RB_MUTE 146 |RB_SINGLE 147 |RB_VERBOSE 148 |RB_ASKNAME 149 |RB_CONFIG)) == RB_MUTE); 150 151 /* 152 * If no console, give up. 153 */ 154 if (best_cp == NULL) { 155 if (cn_tab != NULL && cn_tab->cn_term != NULL) 156 (*cn_tab->cn_term)(cn_tab); 157 cn_tab = best_cp; 158 return; 159 } 160 161 /* 162 * Initialize console, then attach to it. This ordering allows 163 * debugging using the previous console, if any. 164 */ 165 (*best_cp->cn_init)(best_cp); 166 if (cn_tab != NULL && cn_tab != best_cp) { 167 /* Turn off the previous console. */ 168 if (cn_tab->cn_term != NULL) 169 (*cn_tab->cn_term)(cn_tab); 170 } 171 if (boothowto & RB_PAUSE) 172 console_pausing = 1; 173 cn_tab = best_cp; 174 } 175 176 /* 177 * Hook the open and close functions on the selected device. 178 */ 179 void 180 cninit_finish() 181 { 182 if ((cn_tab == NULL) || cn_mute) 183 return; 184 185 /* 186 * Hook the open and close functions. XXX bad hack. 187 */ 188 if (dev_is_good(cn_tab->cn_dev)) 189 cn_fwd_port = cdevsw_dev_override(cn_tab->cn_dev, &cn_iport); 190 cn_dev_t = cn_tab->cn_dev; 191 cn_udev_t = dev2udev(cn_dev_t); 192 console_pausing = 0; 193 } 194 195 static void 196 cnuninit(void) 197 { 198 if (cn_tab == NULL) 199 return; 200 201 /* 202 * Unhook the open and close functions. XXX bad hack 203 */ 204 if (cn_fwd_port) 205 cdevsw_dev_override(cn_tab->cn_dev, cn_fwd_port); 206 cn_fwd_port = NULL; 207 cn_dev_t = NODEV; 208 cn_udev_t = NOUDEV; 209 } 210 211 /* 212 * User has changed the state of the console muting. 213 * This may require us to open or close the device in question. 214 */ 215 static int 216 sysctl_kern_consmute(SYSCTL_HANDLER_ARGS) 217 { 218 int error; 219 int ocn_mute; 220 221 ocn_mute = cn_mute; 222 error = sysctl_handle_int(oidp, &cn_mute, 0, req); 223 if((error == 0) && (cn_tab != NULL) && (req->newptr != NULL)) { 224 if(ocn_mute && !cn_mute) { 225 /* 226 * going from muted to unmuted.. open the physical dev 227 * if the console has been openned 228 */ 229 cninit_finish(); 230 if (cn_is_open) { 231 /* XXX curproc is not what we want really */ 232 error = dev_dopen(cn_dev_t, openflag, 233 openmode, curthread); 234 } 235 /* if it failed, back it out */ 236 if ( error != 0) cnuninit(); 237 } else if (!ocn_mute && cn_mute) { 238 /* 239 * going from unmuted to muted.. close the physical dev 240 * if it's only open via /dev/console 241 */ 242 if (cn_is_open) { 243 error = dev_dclose(cn_dev_t, openflag, 244 openmode, curthread); 245 } 246 if (error == 0) 247 cnuninit(); 248 } 249 if (error != 0) { 250 /* 251 * back out the change if there was an error 252 */ 253 cn_mute = ocn_mute; 254 } 255 } 256 return (error); 257 } 258 259 SYSCTL_PROC(_kern, OID_AUTO, consmute, CTLTYPE_INT|CTLFLAG_RW, 260 0, sizeof cn_mute, sysctl_kern_consmute, "I", ""); 261 262 /* 263 * We intercept the OPEN and CLOSE calls on the original device, and 264 * forward the rest through. 265 */ 266 static int 267 console_interceptport(lwkt_port_t port, lwkt_msg_t lmsg) 268 { 269 cdevallmsg_t msg = (cdevallmsg_t)lmsg; 270 int error; 271 272 switch(msg->am_lmsg.ms_cmd.cm_op) { 273 case CDEV_CMD_OPEN: 274 error = cnopen(&msg->am_open); 275 break; 276 case CDEV_CMD_CLOSE: 277 error = cnclose(&msg->am_close); 278 break; 279 default: 280 error = lwkt_forwardmsg(cn_fwd_port, &msg->am_lmsg); 281 break; 282 } 283 return(error); 284 } 285 286 /* 287 * This is the port handler for /dev/console. These functions will basically 288 * past the request through to the actual physical device representing the 289 * console. 290 * 291 * Note, however, that cnopen() and cnclose() are also called from the mute 292 * code and the intercept code. 293 */ 294 static int 295 console_putport(lwkt_port_t port, lwkt_msg_t lmsg) 296 { 297 cdevallmsg_t msg = (cdevallmsg_t)lmsg; 298 int error; 299 300 switch(msg->am_lmsg.ms_cmd.cm_op) { 301 case CDEV_CMD_OPEN: 302 error = cnopen(&msg->am_open); 303 break; 304 case CDEV_CMD_CLOSE: 305 error = cnclose(&msg->am_close); 306 break; 307 case CDEV_CMD_STRATEGY: 308 nostrategy(msg->am_strategy.bp); 309 error = 0; 310 break; 311 case CDEV_CMD_IOCTL: 312 error = cnioctl(&msg->am_ioctl); 313 break; 314 case CDEV_CMD_DUMP: 315 error = nodump(msg->am_dump.msg.dev, 0, 0, 0); 316 break; 317 case CDEV_CMD_PSIZE: 318 error = nopsize(msg->am_psize.msg.dev); 319 break; 320 case CDEV_CMD_READ: 321 error = cnread(&msg->am_read); 322 break; 323 case CDEV_CMD_WRITE: 324 error = cnwrite(&msg->am_write); 325 break; 326 case CDEV_CMD_POLL: 327 error = cnpoll(&msg->am_poll); 328 break; 329 case CDEV_CMD_KQFILTER: 330 error = cnkqfilter(&msg->am_kqfilter); 331 break; 332 case CDEV_CMD_MMAP: 333 error = nommap(msg->am_mmap.msg.dev, 334 msg->am_mmap.offset, 335 msg->am_mmap.nprot); 336 break; 337 default: 338 error = ENODEV; 339 break; 340 } 341 return(error); 342 } 343 344 /* 345 * cnopen() is called as a port intercept function (dev will be that of the 346 * actual physical device representing our console), and also called from 347 * the muting code and from the /dev/console switch (dev will have the 348 * console's cdevsw). 349 */ 350 static int 351 cnopen(struct cdevmsg_open *msg) 352 { 353 dev_t dev = msg->msg.dev; 354 int flag = msg->oflags; 355 int mode = msg->devtype; 356 dev_t cndev, physdev; 357 int retval = 0; 358 359 if (cn_tab == NULL || cn_fwd_port == NULL) 360 return (0); 361 cndev = cn_tab->cn_dev; 362 physdev = (major(dev) == major(cndev) ? dev : cndev); 363 364 /* 365 * If mute is active, then non console opens don't get here 366 * so we don't need to check for that. They bypass this and go 367 * straight to the device. 368 * 369 * XXX at the moment we assume that the port forwarding function 370 * is synchronous for open. 371 */ 372 if (!cn_mute) { 373 msg->msg.dev = physdev; 374 retval = lwkt_forwardmsg(cn_fwd_port, &msg->msg.msg); 375 } 376 if (retval == 0) { 377 /* 378 * check if we openned it via /dev/console or 379 * via the physical entry (e.g. /dev/sio0). 380 */ 381 if (dev == cndev) 382 cn_phys_is_open = 1; 383 else if (physdev == cndev) { 384 openmode = mode; 385 openflag = flag; 386 cn_is_open = 1; 387 } 388 dev->si_tty = physdev->si_tty; 389 } 390 return (retval); 391 } 392 393 /* 394 * cnclose() is called as a port intercept function (dev will be that of the 395 * actual physical device representing our console), and also called from 396 * the muting code and from the /dev/console switch (dev will have the 397 * console's cdevsw). 398 */ 399 static int 400 cnclose(struct cdevmsg_close *msg) 401 { 402 dev_t dev = msg->msg.dev; 403 dev_t cndev; 404 struct tty *cn_tp; 405 406 if (cn_tab == NULL || cn_fwd_port == NULL) 407 return (0); 408 cndev = cn_tab->cn_dev; 409 cn_tp = cndev->si_tty; 410 /* 411 * act appropriatly depending on whether it's /dev/console 412 * or the pysical device (e.g. /dev/sio) that's being closed. 413 * in either case, don't actually close the device unless 414 * both are closed. 415 */ 416 if (dev == cndev) { 417 /* the physical device is about to be closed */ 418 cn_phys_is_open = 0; 419 if (cn_is_open) { 420 if (cn_tp) { 421 /* perform a ttyhalfclose() */ 422 /* reset session and proc group */ 423 ttyclearsession(cn_tp); 424 } 425 return (0); 426 } 427 } else if (major(dev) != major(cndev)) { 428 /* the logical console is about to be closed */ 429 cn_is_open = 0; 430 if (cn_phys_is_open) 431 return (0); 432 dev = cndev; 433 } 434 if (cn_fwd_port) { 435 msg->msg.dev = dev; 436 return(lwkt_forwardmsg(cn_fwd_port, &msg->msg.msg)); 437 } 438 return (0); 439 } 440 441 /* 442 * The following functions are dispatched solely from the /dev/console 443 * port switch. Their job is primarily to forward the request through. 444 * If the console is not attached to anything then write()'s are sunk 445 * to null and reads return 0 (mostly). 446 */ 447 static int 448 cnread(struct cdevmsg_read *msg) 449 { 450 if (cn_tab == NULL || cn_fwd_port == NULL) 451 return (0); 452 msg->msg.dev = cn_tab->cn_dev; 453 return(lwkt_forwardmsg(cn_fwd_port, &msg->msg.msg)); 454 } 455 456 static int 457 cnwrite(struct cdevmsg_write *msg) 458 { 459 struct uio *uio = msg->uio; 460 dev_t dev; 461 462 if (cn_tab == NULL || cn_fwd_port == NULL) { 463 uio->uio_resid = 0; /* dump the data */ 464 return (0); 465 } 466 if (constty) 467 dev = constty->t_dev; 468 else 469 dev = cn_tab->cn_dev; 470 log_console(uio); 471 msg->msg.dev = dev; 472 return(lwkt_forwardmsg(cn_fwd_port, &msg->msg.msg)); 473 } 474 475 static int 476 cnioctl(struct cdevmsg_ioctl *msg) 477 { 478 u_long cmd = msg->cmd; 479 int error; 480 481 if (cn_tab == NULL || cn_fwd_port == NULL) 482 return (0); 483 KKASSERT(msg->td->td_proc != NULL); 484 /* 485 * Superuser can always use this to wrest control of console 486 * output from the "virtual" console. 487 */ 488 if (cmd == TIOCCONS && constty) { 489 error = suser(msg->td); 490 if (error) 491 return (error); 492 constty = NULL; 493 return (0); 494 } 495 msg->msg.dev = cn_tab->cn_dev; 496 return(lwkt_forwardmsg(cn_fwd_port, &msg->msg.msg)); 497 } 498 499 static int 500 cnpoll(struct cdevmsg_poll *msg) 501 { 502 if ((cn_tab == NULL) || cn_mute || cn_fwd_port == NULL) 503 return (1); 504 msg->msg.dev = cn_tab->cn_dev; 505 return(lwkt_forwardmsg(cn_fwd_port, &msg->msg.msg)); 506 } 507 508 static int 509 cnkqfilter(struct cdevmsg_kqfilter *msg) 510 { 511 if ((cn_tab == NULL) || cn_mute || cn_fwd_port == NULL) 512 return (1); 513 msg->msg.dev = cn_tab->cn_dev; 514 return(lwkt_forwardmsg(cn_fwd_port, &msg->msg.msg)); 515 } 516 517 /* 518 * These synchronous functions are primarily used the kernel needs to 519 * access the keyboard (e.g. when running the debugger), or output data 520 * directly to the console. 521 */ 522 int 523 cngetc(void) 524 { 525 int c; 526 if ((cn_tab == NULL) || cn_mute) 527 return (-1); 528 c = (*cn_tab->cn_getc)(cn_tab->cn_dev); 529 if (c == '\r') c = '\n'; /* console input is always ICRNL */ 530 return (c); 531 } 532 533 int 534 cncheckc(void) 535 { 536 if ((cn_tab == NULL) || cn_mute) 537 return (-1); 538 return ((*cn_tab->cn_checkc)(cn_tab->cn_dev)); 539 } 540 541 void 542 cnputc(int c) 543 { 544 char *cp; 545 546 if ((cn_tab == NULL) || cn_mute) 547 return; 548 if (c) { 549 if (c == '\n') 550 (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r'); 551 (*cn_tab->cn_putc)(cn_tab->cn_dev, c); 552 #ifdef DDB 553 if (console_pausing && !db_active && (c == '\n')) { 554 #else 555 if (console_pausing && (c == '\n')) { 556 #endif 557 for(cp=console_pausestr; *cp != '\0'; cp++) 558 (*cn_tab->cn_putc)(cn_tab->cn_dev, *cp); 559 if (cngetc() == '.') 560 console_pausing = 0; 561 (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r'); 562 for(cp=console_pausestr; *cp != '\0'; cp++) 563 (*cn_tab->cn_putc)(cn_tab->cn_dev, ' '); 564 (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r'); 565 } 566 } 567 } 568 569 void 570 cndbctl(int on) 571 { 572 static int refcount; 573 574 if (cn_tab == NULL) 575 return; 576 if (!on) 577 refcount--; 578 if (refcount == 0 && cn_tab->cn_dbctl != NULL) 579 (*cn_tab->cn_dbctl)(cn_tab->cn_dev, on); 580 if (on) 581 refcount++; 582 } 583 584 static void 585 cn_drvinit(void *unused) 586 { 587 cdevsw_add(&cn_cdevsw, 0, 0); 588 cn_devfsdev = make_dev(&cn_cdevsw, 0, UID_ROOT, GID_WHEEL, 589 0600, "console"); 590 } 591 592 SYSINIT(cndev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,cn_drvinit,NULL) 593