Re: [PATCH] detour TTY driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, 15 May 2010 12:17:00 +0200 Samo Pogacnik wrote:
> Hi,
> 
> Here is the initial suggestion for a simple detour TTY driver, which
> provides the ability to write user messages through printk. This allows
> user output to be inlined with kernel output. Together with printk
> time-stamping enabled, a detailed boot sequence analyses is possible.
> Additionally, console logs could have been stored through the same
> mechanism as kernel messages and does not require the system logger to
> be started very/too soon.
> 
Hi again,

This version of patch provides the ability to initially redirect console
to "detour TTY" (on driver initialization), if "detour" boot command
line option is set. 

best regards, Samo

p.s.
Randy, Alan: Would you be so kind to comment on usability and
acceptability of this tty driver approach? Thanks.

---
Signed-off-by: Samo Pogacnik <samo_pogacnik@xxxxxxx>
diff --git a_linux/Documentation/devices.txt b_linux/Documentation/devices.txt
index 53d64d3..f889097 100644
--- a_linux/Documentation/devices.txt
+++ b_linux/Documentation/devices.txt
@@ -239,6 +239,7 @@ Your cooperation is appreciated.
 		  0 = /dev/tty		Current TTY device
 		  1 = /dev/console	System console
 		  2 = /dev/ptmx		PTY master multiplex
+		  3 = /dev/detour	Detour via printk TTY device
 		 64 = /dev/cua0		Callout device for ttyS0
 		    ...
 		255 = /dev/cua191	Callout device for ttyS191
diff --git a_linux/Documentation/kernel-parameters.txt b_linux/Documentation/kernel-parameters.txt
index 839b21b..1fd9f09 100644
--- a_linux/Documentation/kernel-parameters.txt
+++ b_linux/Documentation/kernel-parameters.txt
@@ -623,6 +623,8 @@ and is between 256 and 4096 characters. It is defined in the file
 			Defaults to the default architecture's huge page size
 			if not specified.
 
+	detour		[KNL] Initial console redirect via detour tty.
+
 	dhash_entries=	[KNL]
 			Set number of hash buckets for dentry cache.
 
diff --git a_linux/drivers/char/Kconfig b_linux/drivers/char/Kconfig
index 3141dd3..f81781d 100644
--- a_linux/drivers/char/Kconfig
+++ b_linux/drivers/char/Kconfig
@@ -485,6 +485,21 @@ config LEGACY_PTY_COUNT
 	  When not in use, each legacy PTY occupies 12 bytes on 32-bit
 	  architectures and 24 bytes on 64-bit architectures.
 
+config DETOUR_TTY
+	bool "TTY driver to detour user output via printk"
+	default n
+	---help---
+	  If you say Y here, the support for writing user messages (i.e.
+	  console messages) via printk is available.
+
+	  The feature is useful to inline user messages with kernel
+	  messages.
+	  In order to use this feature, you should output user messages
+	  to /dev/detour. By setting boot command line option "detour",
+	  the console is initially redirected to detour TTY.
+
+	  If unsure, say N.
+
 config BRIQ_PANEL
 	tristate 'Total Impact briQ front panel driver'
 	depends on PPC_CHRP
diff --git a_linux/drivers/char/Makefile b_linux/drivers/char/Makefile
index f957edf..b84db55 100644
--- a_linux/drivers/char/Makefile
+++ b_linux/drivers/char/Makefile
@@ -11,6 +11,7 @@ obj-y	 += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o t
 
 obj-$(CONFIG_LEGACY_PTYS)	+= pty.o
 obj-$(CONFIG_UNIX98_PTYS)	+= pty.o
+obj-$(CONFIG_DETOUR_TTY)	+= dty.o
 obj-y				+= misc.o
 obj-$(CONFIG_VT)		+= vt_ioctl.o vc_screen.o selection.o keyboard.o
 obj-$(CONFIG_BFIN_JTAG_COMM)	+= bfin_jtag_comm.o
diff --git a_linux/drivers/char/dty.c b_linux/drivers/char/dty.c
new file mode 100644
index 0000000..4c9018f
--- /dev/null
+++ b_linux/drivers/char/dty.c
@@ -0,0 +1,183 @@
+/*
+ *  linux/drivers/char/detour.c
+ *
+ *  Copyright (C) 2010  Samo Pogacnik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+/*
+ * This pseudo device allows user to make printk messages. It is possible
+ * to store "console" messages inline with kernel messages for better analyses
+ * of the boot process, for example.
+ */
+
+#include <linux/security.h>
+#include <linux/device.h>
+#include <linux/tty.h>
+
+static int console_detour;
+static struct tty_driver *dty_driver;
+
+/*
+ * Set console_detour to 1.
+ */
+void set_console_detour(void)
+{
+	console_detour = 1;
+}
+EXPORT_SYMBOL(set_console_detour);
+
+/*
+ * Our simple preformatting:
+ * - every cr is replaced by '^'nl combination
+ * - every non cr or nl ended write is padded with '\'nl combination
+ * - adds a detour source tag in front of each line
+ *
+ * This is useful for logging purposes (kind of a logging ldisc?).
+ */
+static const char *detour_tag = "[D] ";
+#define DETOUR_STR_SIZE 508
+
+static void detour_printk(const unsigned char *buf, int count)
+{
+	static char tmp[DETOUR_STR_SIZE + 4];
+	static int curr;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		tmp[curr] = buf[i];
+		if (curr < DETOUR_STR_SIZE) {
+			switch (buf[i]) {
+			case '\r':
+				tmp[curr] = '^';
+				tmp[curr + 1] = '\n';
+				tmp[curr + 2] = '\0';
+				printk(KERN_INFO "%s%s", detour_tag, tmp);
+				curr = 0;
+				if (buf[i + 1] == '\n')
+					i++;
+				break;
+			case '\n':
+				tmp[curr + 1] = '\0';
+				printk(KERN_INFO "%s%s", detour_tag, tmp);
+				curr = 0;
+				break;
+			default:
+				curr++;
+			}
+		} else {
+			/* end of tmp buffer reached: cut the message in two */
+			tmp[curr + 1] = '\\';
+			tmp[curr + 2] = '\n';
+			tmp[curr + 3] = '\0';
+			printk(KERN_INFO "%s%s", detour_tag, tmp);
+			curr = 0;
+		}
+	}
+	if (curr > 0) {
+		/* non nl or cr terminated message */
+		tmp[curr + 0] = '\\';
+		tmp[curr + 1] = '\n';
+		tmp[curr + 2] = '\0';
+		printk(KERN_INFO "%s%s", detour_tag, tmp);
+		curr = 0;
+	}
+}
+
+/*
+ *	Dummy tty ops open for succesfull terminal device open.
+ */
+static int dty_open(struct tty_struct *tty, struct file *filp)
+{
+	return 0;
+}
+
+/*
+ *	File ops (not tty ops) write avoids ldisc inserting additional CRs.
+ *	We simply throw this to our preformatter, which calls printk.
+ */
+static ssize_t detour_write(struct file *file, const char __user *buf,
+	size_t count, loff_t *ppos)
+{
+	detour_printk(buf, count);
+	return count;
+}
+
+static const struct tty_operations dty_ops = {
+	.open = dty_open,
+};
+
+static struct file_operations detour_fops;
+static void initial_console_redirect(void);
+
+static int __init dty_init(void)
+{
+	dty_driver = alloc_tty_driver(1);
+	if (!dty_driver)
+		panic("Couldn't allocate pty driver");
+
+	dty_driver->owner = THIS_MODULE;
+	dty_driver->driver_name = "dty";
+	dty_driver->name = "detour";
+	dty_driver->major = TTYAUX_MAJOR;
+	dty_driver->minor_start = 3;
+	dty_driver->num = 1;
+	dty_driver->type = TTY_DRIVER_TYPE_CONSOLE;
+	dty_driver->init_termios = tty_std_termios;
+	dty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
+		TTY_DRIVER_DYNAMIC_DEV;
+	tty_set_operations(dty_driver, &dty_ops);
+
+	if (tty_register_driver(dty_driver))
+		panic("Couldn't register dty driver");
+
+	/* register our fops write function */
+	tty_default_fops(&detour_fops);
+	detour_fops.write = detour_write;
+
+	cdev_init(&dty_driver->cdev, &detour_fops);
+
+	/* create our unnumbered device */
+	device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 3), NULL,
+		dty_driver->name);
+
+	if (console_detour > 0)
+		initial_console_redirect();
+
+	return 0;
+}
+module_init(dty_init);
+
+/*
+ * Support for internal handling of console redirection via detour.
+ */
+static struct file detour_file;
+static struct inode detour_inode;
+static struct dentry detour_dentry;
+
+static void initial_console_redirect(void)
+{
+	long ret;
+
+	/* re-register our fops write function */
+	detour_fops.write = detour_write;
+
+	detour_file.f_dentry = &detour_dentry;
+	detour_file.f_dentry->d_inode = &detour_inode;
+	detour_file.f_op = &detour_fops;
+	detour_file.f_mode |= FMODE_WRITE;
+	security_file_alloc(&detour_file);
+	INIT_LIST_HEAD(&detour_file.f_u.fu_list);
+
+	detour_inode.i_rdev = MKDEV(TTYAUX_MAJOR, 3);
+	security_inode_alloc(&detour_inode);
+	INIT_LIST_HEAD(&detour_inode.inotify_watches);
+
+	ret = detour_fops.open(&detour_inode, &detour_file);
+	printk(KERN_INFO "detour_fops.open() returned %ld\n", ret);
+	ret = detour_fops.unlocked_ioctl(&detour_file, TIOCCONS, 0);
+	printk(KERN_INFO "detour_fops.ioctl() returned %ld\n", ret);
+}
diff --git a_linux/init/main.c b_linux/init/main.c
index 5c85402..be9dee9 100644
--- a_linux/init/main.c
+++ b_linux/init/main.c
@@ -263,6 +263,18 @@ static int __init loglevel(char *str)
 
 early_param("loglevel", loglevel);
 
+#ifdef CONFIG_DETOUR_TTY
+extern void set_console_detour(void);
+
+static int __init detour(char *str)
+{
+	set_console_detour();
+	return 0;
+}
+
+early_param("detour", detour);
+#endif
+
 /*
  * Unknown boot options get handed to init, unless they look like
  * unused parameters (modprobe will find them in /proc/cmdline).


--
To unsubscribe from this list: send the line "unsubscribe linux-embedded" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Gstreamer Embedded]     [Linux MMC Devel]     [U-Boot V2]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux ARM Kernel]     [Linux OMAP]     [Linux SCSI]

  Powered by Linux