xref: /dragonfly/sys/kern/tty_cons.c (revision 27f48495)
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