tty: Add NULL TTY driver

If no console driver is enabled (or if a non-present driver is selected
with something like console=null in an attempt to disable the console),
opening /dev/console errors out, and init scripts and other userspace
code that relies on the existence of a console will fail.  Symlinking
/dev/null to /dev/console does not solve the problem since /dev/null
does not behave like a real TTY.

To just provide a dummy console to userspace when no console driver is
available or desired, add a ttynull driver which simply discards all
writes.  It can be chosen on the command line in the standard way, i.e.
with console=ttynull.

Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Vincent Whitchurch 2019-04-03 13:33:27 +02:00 committed by Greg Kroah-Hartman
parent 89bb1e1ee5
commit 3117ff13f1
3 changed files with 124 additions and 0 deletions

View File

@ -374,6 +374,20 @@ config PPC_EARLY_DEBUG_EHV_BC_HANDLE
there simply will be no early console output. This is true also
if you don't boot under a hypervisor at all.
config NULL_TTY
tristate "NULL TTY driver"
help
Say Y here if you want a NULL TTY which simply discards messages.
This is useful to allow userspace applications which expect a console
device to work without modifications even when no console is
available or desired.
In order to use this driver, you should redirect the console to this
TTY, or boot the kernel with console=ttynull.
If unsure, say N.
config GOLDFISH_TTY
tristate "Goldfish TTY Driver"
depends on GOLDFISH

View File

@ -25,6 +25,7 @@ obj-$(CONFIG_ISI) += isicom.o
obj-$(CONFIG_MOXA_INTELLIO) += moxa.o
obj-$(CONFIG_MOXA_SMARTIO) += mxser.o
obj-$(CONFIG_NOZOMI) += nozomi.o
obj-$(CONFIG_NULL_TTY) += ttynull.o
obj-$(CONFIG_ROCKETPORT) += rocket.o
obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o
obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o

109
drivers/tty/ttynull.c Normal file
View File

@ -0,0 +1,109 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2019 Axis Communications AB
*
* Based on ttyprintk.c:
* Copyright (C) 2010 Samo Pogacnik
*/
#include <linux/console.h>
#include <linux/module.h>
#include <linux/tty.h>
static const struct tty_port_operations ttynull_port_ops;
static struct tty_driver *ttynull_driver;
static struct tty_port ttynull_port;
static int ttynull_open(struct tty_struct *tty, struct file *filp)
{
return tty_port_open(&ttynull_port, tty, filp);
}
static void ttynull_close(struct tty_struct *tty, struct file *filp)
{
tty_port_close(&ttynull_port, tty, filp);
}
static void ttynull_hangup(struct tty_struct *tty)
{
tty_port_hangup(&ttynull_port);
}
static int ttynull_write(struct tty_struct *tty, const unsigned char *buf,
int count)
{
return count;
}
static int ttynull_write_room(struct tty_struct *tty)
{
return 65536;
}
static const struct tty_operations ttynull_ops = {
.open = ttynull_open,
.close = ttynull_close,
.hangup = ttynull_hangup,
.write = ttynull_write,
.write_room = ttynull_write_room,
};
static struct tty_driver *ttynull_device(struct console *c, int *index)
{
*index = 0;
return ttynull_driver;
}
static struct console ttynull_console = {
.name = "ttynull",
.device = ttynull_device,
};
static int __init ttynull_init(void)
{
struct tty_driver *driver;
int ret;
driver = tty_alloc_driver(1,
TTY_DRIVER_RESET_TERMIOS |
TTY_DRIVER_REAL_RAW |
TTY_DRIVER_UNNUMBERED_NODE);
if (IS_ERR(driver))
return PTR_ERR(driver);
tty_port_init(&ttynull_port);
ttynull_port.ops = &ttynull_port_ops;
driver->driver_name = "ttynull";
driver->name = "ttynull";
driver->type = TTY_DRIVER_TYPE_CONSOLE;
driver->init_termios = tty_std_termios;
driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
tty_set_operations(driver, &ttynull_ops);
tty_port_link_device(&ttynull_port, driver, 0);
ret = tty_register_driver(driver);
if (ret < 0) {
put_tty_driver(driver);
tty_port_destroy(&ttynull_port);
return ret;
}
ttynull_driver = driver;
register_console(&ttynull_console);
return 0;
}
static void __exit ttynull_exit(void)
{
unregister_console(&ttynull_console);
tty_unregister_driver(ttynull_driver);
put_tty_driver(ttynull_driver);
tty_port_destroy(&ttynull_port);
}
module_init(ttynull_init);
module_exit(ttynull_exit);
MODULE_LICENSE("GPL v2");