1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1991 The Regents of the University of California. 6 * Copyright (c) 1999 Michael Smith 7 * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> 8 * 9 * All rights reserved. 10 * 11 * This code is derived from software contributed to Berkeley by 12 * the Systems Programming Group of the University of Utah Computer 13 * Science Department. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 3. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * from: @(#)cons.c 7.2 (Berkeley) 5/9/91 40 */ 41 42 #include <sys/cdefs.h> 43 __FBSDID("$FreeBSD$"); 44 45 #include "opt_ddb.h" 46 #include "opt_syscons.h" 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/lock.h> 51 #include <sys/mutex.h> 52 #include <sys/conf.h> 53 #include <sys/cons.h> 54 #include <sys/fcntl.h> 55 #include <sys/kbio.h> 56 #include <sys/kdb.h> 57 #include <sys/kernel.h> 58 #include <sys/malloc.h> 59 #include <sys/msgbuf.h> 60 #include <sys/namei.h> 61 #include <sys/priv.h> 62 #include <sys/proc.h> 63 #include <sys/queue.h> 64 #include <sys/reboot.h> 65 #include <sys/sysctl.h> 66 #include <sys/sbuf.h> 67 #include <sys/tty.h> 68 #include <sys/uio.h> 69 #include <sys/vnode.h> 70 71 #include <ddb/ddb.h> 72 73 #include <dev/kbd/kbdreg.h> 74 75 #include <machine/cpu.h> 76 #include <machine/clock.h> 77 78 static MALLOC_DEFINE(M_TTYCONS, "tty console", "tty console handling"); 79 80 struct cn_device { 81 STAILQ_ENTRY(cn_device) cnd_next; 82 struct consdev *cnd_cn; 83 }; 84 85 #define CNDEVPATHMAX 32 86 #define CNDEVTAB_SIZE 4 87 static struct cn_device cn_devtab[CNDEVTAB_SIZE]; 88 static STAILQ_HEAD(, cn_device) cn_devlist = 89 STAILQ_HEAD_INITIALIZER(cn_devlist); 90 91 int cons_avail_mask = 0; /* Bit mask. Each registered low level console 92 * which is currently unavailable for inpit 93 * (i.e., if it is in graphics mode) will have 94 * this bit cleared. 95 */ 96 static int cn_mute; 97 static char *consbuf; /* buffer used by `consmsgbuf' */ 98 static struct callout conscallout; /* callout for outputting to constty */ 99 struct msgbuf consmsgbuf; /* message buffer for console tty */ 100 static u_char console_pausing; /* pause after each line during probe */ 101 static const char console_pausestr[] = 102 "<pause; press any key to proceed to next line or '.' to end pause mode>"; 103 struct tty *constty; /* pointer to console "window" tty */ 104 static struct mtx cnputs_mtx; /* Mutex for cnputs(). */ 105 static int use_cnputs_mtx = 0; /* != 0 if cnputs_mtx locking reqd. */ 106 107 static void constty_timeout(void *arg); 108 109 static struct consdev cons_consdev; 110 DATA_SET(cons_set, cons_consdev); 111 SET_DECLARE(cons_set, struct consdev); 112 113 /* 114 * Stub for configurations that don't actually have a keyboard driver. Inclusion 115 * of kbd.c is contingent on any number of keyboard/console drivers being 116 * present in the kernel; rather than trying to catch them all, we'll just 117 * maintain this weak kbdinit that will be overridden by the strong version in 118 * kbd.c if it's present. 119 */ 120 __weak_symbol void 121 kbdinit(void) 122 { 123 124 } 125 126 void 127 cninit(void) 128 { 129 struct consdev *best_cn, *cn, **list; 130 131 /* 132 * Check if we should mute the console (for security reasons perhaps) 133 * It can be changes dynamically using sysctl kern.consmute 134 * once we are up and going. 135 * 136 */ 137 cn_mute = ((boothowto & (RB_MUTE 138 |RB_SINGLE 139 |RB_VERBOSE 140 |RB_ASKNAME)) == RB_MUTE); 141 142 /* 143 * Bring up the kbd layer just in time for cnprobe. Console drivers 144 * have a dependency on kbd being ready, so this fits nicely between the 145 * machdep callers of cninit() and MI probing/initialization of consoles 146 * here. 147 */ 148 kbdinit(); 149 150 /* 151 * Find the first console with the highest priority. 152 */ 153 best_cn = NULL; 154 SET_FOREACH(list, cons_set) { 155 cn = *list; 156 cnremove(cn); 157 /* Skip cons_consdev. */ 158 if (cn->cn_ops == NULL) 159 continue; 160 cn->cn_ops->cn_probe(cn); 161 if (cn->cn_pri == CN_DEAD) 162 continue; 163 if (best_cn == NULL || cn->cn_pri > best_cn->cn_pri) 164 best_cn = cn; 165 if (boothowto & RB_MULTIPLE) { 166 /* 167 * Initialize console, and attach to it. 168 */ 169 cn->cn_ops->cn_init(cn); 170 cnadd(cn); 171 } 172 } 173 if (best_cn == NULL) 174 return; 175 if ((boothowto & RB_MULTIPLE) == 0) { 176 best_cn->cn_ops->cn_init(best_cn); 177 cnadd(best_cn); 178 } 179 if (boothowto & RB_PAUSE) 180 console_pausing = 1; 181 /* 182 * Make the best console the preferred console. 183 */ 184 cnselect(best_cn); 185 186 #ifdef EARLY_PRINTF 187 /* 188 * Release early console. 189 */ 190 early_putc = NULL; 191 #endif 192 } 193 194 void 195 cninit_finish() 196 { 197 console_pausing = 0; 198 } 199 200 /* add a new physical console to back the virtual console */ 201 int 202 cnadd(struct consdev *cn) 203 { 204 struct cn_device *cnd; 205 int i; 206 207 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) 208 if (cnd->cnd_cn == cn) 209 return (0); 210 for (i = 0; i < CNDEVTAB_SIZE; i++) { 211 cnd = &cn_devtab[i]; 212 if (cnd->cnd_cn == NULL) 213 break; 214 } 215 if (cnd->cnd_cn != NULL) 216 return (ENOMEM); 217 cnd->cnd_cn = cn; 218 if (cn->cn_name[0] == '\0') { 219 /* XXX: it is unclear if/where this print might output */ 220 printf("WARNING: console at %p has no name\n", cn); 221 } 222 STAILQ_INSERT_TAIL(&cn_devlist, cnd, cnd_next); 223 if (STAILQ_FIRST(&cn_devlist) == cnd) 224 ttyconsdev_select(cnd->cnd_cn->cn_name); 225 226 /* Add device to the active mask. */ 227 cnavailable(cn, (cn->cn_flags & CN_FLAG_NOAVAIL) == 0); 228 229 return (0); 230 } 231 232 void 233 cnremove(struct consdev *cn) 234 { 235 struct cn_device *cnd; 236 int i; 237 238 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 239 if (cnd->cnd_cn != cn) 240 continue; 241 if (STAILQ_FIRST(&cn_devlist) == cnd) 242 ttyconsdev_select(NULL); 243 STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next); 244 cnd->cnd_cn = NULL; 245 246 /* Remove this device from available mask. */ 247 for (i = 0; i < CNDEVTAB_SIZE; i++) 248 if (cnd == &cn_devtab[i]) { 249 cons_avail_mask &= ~(1 << i); 250 break; 251 } 252 #if 0 253 /* 254 * XXX 255 * syscons gets really confused if console resources are 256 * freed after the system has initialized. 257 */ 258 if (cn->cn_term != NULL) 259 cn->cn_ops->cn_term(cn); 260 #endif 261 return; 262 } 263 } 264 265 void 266 cnselect(struct consdev *cn) 267 { 268 struct cn_device *cnd; 269 270 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 271 if (cnd->cnd_cn != cn) 272 continue; 273 if (cnd == STAILQ_FIRST(&cn_devlist)) 274 return; 275 STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next); 276 STAILQ_INSERT_HEAD(&cn_devlist, cnd, cnd_next); 277 ttyconsdev_select(cnd->cnd_cn->cn_name); 278 return; 279 } 280 } 281 282 void 283 cnavailable(struct consdev *cn, int available) 284 { 285 int i; 286 287 for (i = 0; i < CNDEVTAB_SIZE; i++) { 288 if (cn_devtab[i].cnd_cn == cn) 289 break; 290 } 291 if (available) { 292 if (i < CNDEVTAB_SIZE) 293 cons_avail_mask |= (1 << i); 294 cn->cn_flags &= ~CN_FLAG_NOAVAIL; 295 } else { 296 if (i < CNDEVTAB_SIZE) 297 cons_avail_mask &= ~(1 << i); 298 cn->cn_flags |= CN_FLAG_NOAVAIL; 299 } 300 } 301 302 int 303 cnunavailable(void) 304 { 305 306 return (cons_avail_mask == 0); 307 } 308 309 /* 310 * sysctl_kern_console() provides output parseable in conscontrol(1). 311 */ 312 static int 313 sysctl_kern_console(SYSCTL_HANDLER_ARGS) 314 { 315 struct cn_device *cnd; 316 struct consdev *cp, **list; 317 char *p; 318 int delete, error; 319 struct sbuf *sb; 320 321 sb = sbuf_new(NULL, NULL, CNDEVPATHMAX * 2, SBUF_AUTOEXTEND | 322 SBUF_INCLUDENUL); 323 if (sb == NULL) 324 return (ENOMEM); 325 sbuf_clear(sb); 326 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) 327 sbuf_printf(sb, "%s,", cnd->cnd_cn->cn_name); 328 sbuf_printf(sb, "/"); 329 SET_FOREACH(list, cons_set) { 330 cp = *list; 331 if (cp->cn_name[0] != '\0') 332 sbuf_printf(sb, "%s,", cp->cn_name); 333 } 334 sbuf_finish(sb); 335 error = sysctl_handle_string(oidp, sbuf_data(sb), sbuf_len(sb), req); 336 if (error == 0 && req->newptr != NULL) { 337 p = sbuf_data(sb); 338 error = ENXIO; 339 delete = 0; 340 if (*p == '-') { 341 delete = 1; 342 p++; 343 } 344 SET_FOREACH(list, cons_set) { 345 cp = *list; 346 if (strcmp(p, cp->cn_name) != 0) 347 continue; 348 if (delete) { 349 cnremove(cp); 350 error = 0; 351 } else { 352 error = cnadd(cp); 353 if (error == 0) 354 cnselect(cp); 355 } 356 break; 357 } 358 } 359 sbuf_delete(sb); 360 return (error); 361 } 362 363 SYSCTL_PROC(_kern, OID_AUTO, console, 364 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 0, 0, 365 sysctl_kern_console, "A", 366 "Console device control"); 367 368 /* 369 * User has changed the state of the console muting. 370 * This may require us to open or close the device in question. 371 */ 372 static int 373 sysctl_kern_consmute(SYSCTL_HANDLER_ARGS) 374 { 375 int error; 376 377 error = sysctl_handle_int(oidp, &cn_mute, 0, req); 378 if (error != 0 || req->newptr == NULL) 379 return (error); 380 return (error); 381 } 382 383 SYSCTL_PROC(_kern, OID_AUTO, consmute, 384 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 0, sizeof(cn_mute), 385 sysctl_kern_consmute, "I", 386 "State of the console muting"); 387 388 void 389 cngrab() 390 { 391 struct cn_device *cnd; 392 struct consdev *cn; 393 394 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 395 cn = cnd->cnd_cn; 396 if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) 397 cn->cn_ops->cn_grab(cn); 398 } 399 } 400 401 void 402 cnungrab() 403 { 404 struct cn_device *cnd; 405 struct consdev *cn; 406 407 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 408 cn = cnd->cnd_cn; 409 if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) 410 cn->cn_ops->cn_ungrab(cn); 411 } 412 } 413 414 void 415 cnresume() 416 { 417 struct cn_device *cnd; 418 struct consdev *cn; 419 420 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 421 cn = cnd->cnd_cn; 422 if (cn->cn_ops->cn_resume != NULL) 423 cn->cn_ops->cn_resume(cn); 424 } 425 } 426 427 /* 428 * Low level console routines. 429 */ 430 int 431 cngetc(void) 432 { 433 int c; 434 435 if (cn_mute) 436 return (-1); 437 while ((c = cncheckc()) == -1) 438 cpu_spinwait(); 439 if (c == '\r') 440 c = '\n'; /* console input is always ICRNL */ 441 return (c); 442 } 443 444 int 445 cncheckc(void) 446 { 447 struct cn_device *cnd; 448 struct consdev *cn; 449 int c; 450 451 if (cn_mute) 452 return (-1); 453 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 454 cn = cnd->cnd_cn; 455 if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) { 456 c = cn->cn_ops->cn_getc(cn); 457 if (c != -1) 458 return (c); 459 } 460 } 461 return (-1); 462 } 463 464 void 465 cngets(char *cp, size_t size, int visible) 466 { 467 char *lp, *end; 468 int c; 469 470 cngrab(); 471 472 lp = cp; 473 end = cp + size - 1; 474 for (;;) { 475 c = cngetc() & 0177; 476 switch (c) { 477 case '\n': 478 case '\r': 479 cnputc(c); 480 *lp = '\0'; 481 cnungrab(); 482 return; 483 case '\b': 484 case '\177': 485 if (lp > cp) { 486 if (visible) 487 cnputs("\b \b"); 488 lp--; 489 } 490 continue; 491 case '\0': 492 continue; 493 default: 494 if (lp < end) { 495 switch (visible) { 496 case GETS_NOECHO: 497 break; 498 case GETS_ECHOPASS: 499 cnputc('*'); 500 break; 501 default: 502 cnputc(c); 503 break; 504 } 505 *lp++ = c; 506 } 507 } 508 } 509 } 510 511 void 512 cnputc(int c) 513 { 514 struct cn_device *cnd; 515 struct consdev *cn; 516 const char *cp; 517 518 #ifdef EARLY_PRINTF 519 if (early_putc != NULL) { 520 if (c == '\n') 521 early_putc('\r'); 522 early_putc(c); 523 return; 524 } 525 #endif 526 527 if (cn_mute || c == '\0') 528 return; 529 STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 530 cn = cnd->cnd_cn; 531 if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) { 532 if (c == '\n') 533 cn->cn_ops->cn_putc(cn, '\r'); 534 cn->cn_ops->cn_putc(cn, c); 535 } 536 } 537 if (console_pausing && c == '\n' && !kdb_active) { 538 for (cp = console_pausestr; *cp != '\0'; cp++) 539 cnputc(*cp); 540 cngrab(); 541 if (cngetc() == '.') 542 console_pausing = 0; 543 cnungrab(); 544 cnputc('\r'); 545 for (cp = console_pausestr; *cp != '\0'; cp++) 546 cnputc(' '); 547 cnputc('\r'); 548 } 549 } 550 551 void 552 cnputsn(const char *p, size_t n) 553 { 554 size_t i; 555 int unlock_reqd = 0; 556 557 if (use_cnputs_mtx) { 558 /* 559 * NOTE: Debug prints and/or witness printouts in 560 * console driver clients can cause the "cnputs_mtx" 561 * mutex to recurse. Simply return if that happens. 562 */ 563 if (mtx_owned(&cnputs_mtx)) 564 return; 565 mtx_lock_spin(&cnputs_mtx); 566 unlock_reqd = 1; 567 } 568 569 for (i = 0; i < n; i++) 570 cnputc(p[i]); 571 572 if (unlock_reqd) 573 mtx_unlock_spin(&cnputs_mtx); 574 } 575 576 void 577 cnputs(const char *p) 578 { 579 cnputsn(p, strlen(p)); 580 } 581 582 static int consmsgbuf_size = 8192; 583 SYSCTL_INT(_kern, OID_AUTO, consmsgbuf_size, CTLFLAG_RW, &consmsgbuf_size, 0, 584 "Console tty buffer size"); 585 586 /* 587 * Redirect console output to a tty. 588 */ 589 void 590 constty_set(struct tty *tp) 591 { 592 int size; 593 594 KASSERT(tp != NULL, ("constty_set: NULL tp")); 595 if (consbuf == NULL) { 596 size = consmsgbuf_size; 597 consbuf = malloc(size, M_TTYCONS, M_WAITOK); 598 msgbuf_init(&consmsgbuf, consbuf, size); 599 callout_init(&conscallout, 0); 600 } 601 constty = tp; 602 constty_timeout(NULL); 603 } 604 605 /* 606 * Disable console redirection to a tty. 607 */ 608 void 609 constty_clear(void) 610 { 611 int c; 612 613 constty = NULL; 614 if (consbuf == NULL) 615 return; 616 callout_stop(&conscallout); 617 while ((c = msgbuf_getchar(&consmsgbuf)) != -1) 618 cnputc(c); 619 free(consbuf, M_TTYCONS); 620 consbuf = NULL; 621 } 622 623 /* Times per second to check for pending console tty messages. */ 624 static int constty_wakeups_per_second = 5; 625 SYSCTL_INT(_kern, OID_AUTO, constty_wakeups_per_second, CTLFLAG_RW, 626 &constty_wakeups_per_second, 0, 627 "Times per second to check for pending console tty messages"); 628 629 static void 630 constty_timeout(void *arg) 631 { 632 int c; 633 634 if (constty != NULL) { 635 tty_lock(constty); 636 while ((c = msgbuf_getchar(&consmsgbuf)) != -1) { 637 if (tty_putchar(constty, c) < 0) { 638 tty_unlock(constty); 639 constty = NULL; 640 break; 641 } 642 } 643 644 if (constty != NULL) 645 tty_unlock(constty); 646 } 647 if (constty != NULL) { 648 callout_reset(&conscallout, hz / constty_wakeups_per_second, 649 constty_timeout, NULL); 650 } else { 651 /* Deallocate the constty buffer memory. */ 652 constty_clear(); 653 } 654 } 655 656 static void 657 cn_drvinit(void *unused) 658 { 659 660 mtx_init(&cnputs_mtx, "cnputs_mtx", NULL, MTX_SPIN | MTX_NOWITNESS); 661 use_cnputs_mtx = 1; 662 } 663 664 SYSINIT(cndev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, cn_drvinit, NULL); 665 666 /* 667 * Sysbeep(), if we have hardware for it 668 */ 669 670 #ifdef HAS_TIMER_SPKR 671 672 static int beeping; 673 static struct callout beeping_timer; 674 675 static void 676 sysbeepstop(void *chan) 677 { 678 679 timer_spkr_release(); 680 beeping = 0; 681 } 682 683 int 684 sysbeep(int pitch, int period) 685 { 686 687 if (timer_spkr_acquire()) { 688 if (!beeping) { 689 /* Something else owns it. */ 690 return (EBUSY); 691 } 692 } 693 timer_spkr_setfreq(pitch); 694 if (!beeping) { 695 beeping = period; 696 callout_reset(&beeping_timer, period, sysbeepstop, NULL); 697 } 698 return (0); 699 } 700 701 static void 702 sysbeep_init(void *unused) 703 { 704 705 callout_init(&beeping_timer, 1); 706 } 707 SYSINIT(sysbeep, SI_SUB_SOFTINTR, SI_ORDER_ANY, sysbeep_init, NULL); 708 #else 709 710 /* 711 * No hardware, no sound 712 */ 713 714 int 715 sysbeep(int pitch __unused, int period __unused) 716 { 717 718 return (ENODEV); 719 } 720 721 #endif 722 723 /* 724 * Temporary support for sc(4) to vt(4) transition. 725 */ 726 static unsigned vty_prefer; 727 static char vty_name[16]; 728 SYSCTL_STRING(_kern, OID_AUTO, vty, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, vty_name, 729 0, "Console vty driver"); 730 731 int 732 vty_enabled(unsigned vty) 733 { 734 static unsigned vty_selected = 0; 735 736 if (vty_selected == 0) { 737 TUNABLE_STR_FETCH("kern.vty", vty_name, sizeof(vty_name)); 738 do { 739 #if defined(DEV_SC) 740 if (strcmp(vty_name, "sc") == 0) { 741 vty_selected = VTY_SC; 742 break; 743 } 744 #endif 745 #if defined(DEV_VT) 746 if (strcmp(vty_name, "vt") == 0) { 747 vty_selected = VTY_VT; 748 break; 749 } 750 #endif 751 if (vty_prefer != 0) { 752 vty_selected = vty_prefer; 753 break; 754 } 755 #if defined(DEV_VT) 756 vty_selected = VTY_VT; 757 #elif defined(DEV_SC) 758 vty_selected = VTY_SC; 759 #endif 760 } while (0); 761 762 if (vty_selected == VTY_VT) 763 strcpy(vty_name, "vt"); 764 else if (vty_selected == VTY_SC) 765 strcpy(vty_name, "sc"); 766 } 767 return ((vty_selected & vty) != 0); 768 } 769 770 void 771 vty_set_preferred(unsigned vty) 772 { 773 774 vty_prefer = vty; 775 #if !defined(DEV_SC) 776 vty_prefer &= ~VTY_SC; 777 #endif 778 #if !defined(DEV_VT) 779 vty_prefer &= ~VTY_VT; 780 #endif 781 } 782 783