Signed-off-by: Samo Pogacnik <samo_pogacnik@t-2.net>
diff --git a_linux-2.6.33.3/Documentation/kernel-parameters.txt b_linux-2.6.33.3/Documentation/kernel-parameters.txt
index e2c7487..ab0072c 100644
--- a_linux-2.6.33.3/Documentation/kernel-parameters.txt
+++ b_linux-2.6.33.3/Documentation/kernel-parameters.txt
@@ -628,6 +628,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] Enable console logging detour via printk.
+
 	dhash_entries=	[KNL]
 			Set number of hash buckets for dentry cache.
 
diff --git a_linux-2.6.33.3/drivers/char/Kconfig b_linux-2.6.33.3/drivers/char/Kconfig
index e023682..43c552e 100644
--- a_linux-2.6.33.3/drivers/char/Kconfig
+++ b_linux-2.6.33.3/drivers/char/Kconfig
@@ -88,6 +88,22 @@ config VT_HW_CONSOLE_BINDING
 	 information. For framebuffer console users, please refer to
 	 <file:Documentation/fb/fbcon.txt>.
 
+config CONSOLE_DETOUR
+	bool "Support for console detour via printk"
+	default n
+	---help---
+	  If you say Y here, the support for writing console messages via
+	  printk is included into the console code.
+
+	  The feature is useful to catch all console log messages.
+	  In order to use this feature, you should specify kernel command line
+	  option "detour" or write a positive number into
+	  /proc/sys/kernel/console_detour. You can disable the feature on-line
+	  by writing zero into the proc file. By writing a negative value into
+	  the proc file, the feature is disabled permanently (until next boot).
+
+	  If unsure, say N.
+
 config DEVKMEM
 	bool "/dev/kmem virtual device support"
 	default y
diff --git a_linux-2.6.33.3/drivers/char/tty_io.c b_linux-2.6.33.3/drivers/char/tty_io.c
index 76253cf..f77de34 100644
--- a_linux-2.6.33.3/drivers/char/tty_io.c
+++ b_linux-2.6.33.3/drivers/char/tty_io.c
@@ -1087,6 +1087,13 @@ ssize_t redirected_tty_write(struct file *file, const char __user *buf,
 	}
 	spin_unlock(&redirect_lock);
 
+#ifdef CONFIG_CONSOLE_DETOUR
+	if (console_detour) {
+		console_printk_detour(buf, count);
+		if (!p)
+			return count;
+	}
+#endif
 	if (p) {
 		ssize_t res;
 		res = vfs_write(p, buf, count, &p->f_pos);
diff --git a_linux-2.6.33.3/include/linux/console.h b_linux-2.6.33.3/include/linux/console.h
index dcca533..354a7a8 100644
--- a_linux-2.6.33.3/include/linux/console.h
+++ b_linux-2.6.33.3/include/linux/console.h
@@ -108,6 +108,13 @@ struct console {
 	struct	 console *next;
 };
 
+extern int console_detour;
+extern void console_printk_detour(const unsigned char *buf, int count);
+
+struct ctl_table;
+int detour_sysctl_handler(struct ctl_table *table, int write,
+		void __user *buffer, size_t *length, loff_t *ppos);
+
 extern int console_set_on_cmdline;
 
 extern int add_preferred_console(char *name, int idx, char *options);
diff --git a_linux-2.6.33.3/init/main.c b_linux-2.6.33.3/init/main.c
index 512ba15..add9e95 100644
--- a_linux-2.6.33.3/init/main.c
+++ b_linux-2.6.33.3/init/main.c
@@ -25,6 +25,7 @@
 #include <linux/bootmem.h>
 #include <linux/acpi.h>
 #include <linux/tty.h>
+#include <linux/console.h>
 #include <linux/gfp.h>
 #include <linux/percpu.h>
 #include <linux/kmod.h>
@@ -249,6 +250,14 @@ static int __init loglevel(char *str)
 
 early_param("loglevel", loglevel);
 
+static int __init detour(char *str)
+{
+	console_detour = 1;
+	return 0;
+}
+
+early_param("detour", detour);
+
 /*
  * Unknown boot options get handed to init, unless they look like
  * unused parameters (modprobe will find them in /proc/cmdline).
diff --git a_linux-2.6.33.3/kernel/printk.c b_linux-2.6.33.3/kernel/printk.c
index 1751c45..953c6ea 100644
--- a_linux-2.6.33.3/kernel/printk.c
+++ b_linux-2.6.33.3/kernel/printk.c
@@ -1368,6 +1368,51 @@ static int __init disable_boot_consoles(void)
 }
 late_initcall(disable_boot_consoles);
 
+/*
+ * This option can be enabled with kernel command line option "detour" or
+ * through a proc file (/proc/sys/kernel/console_detour). It enables console
+ * logging through printk, if supported by enabled console.
+ */
+int console_detour;
+EXPORT_SYMBOL(console_detour);
+
+#define DETOUR_STR_SIZE 512
+void console_printk_detour(const unsigned char *buf, int count)
+{
+	char tmp[DETOUR_STR_SIZE + 1];
+
+	do {
+		if (count > DETOUR_STR_SIZE) {
+			memcpy(tmp, buf, DETOUR_STR_SIZE);
+			tmp[DETOUR_STR_SIZE] = '\0';
+		} else {
+			memcpy(tmp, buf, count);
+			tmp[count] = '\0';
+		}
+		count -= DETOUR_STR_SIZE;
+		printk(KERN_INFO "%s", tmp);
+	} while (count > 0);
+}
+EXPORT_SYMBOL(console_printk_detour);
+
+int detour_sysctl_handler(struct ctl_table *table, int write,
+	void __user *buffer, size_t *length, loff_t *ppos)
+{
+	static int disable_forever;
+
+	proc_dointvec(table, write, buffer, length, ppos);
+	if (write) {
+		if ((console_detour < 0) || (disable_forever != 0)) {
+			disable_forever = 1;
+			console_detour = 0;
+			return 0;
+		}
+		if (console_detour > 1)
+			console_detour = 1;
+	}
+	return 0;
+}
+
 #if defined CONFIG_PRINTK
 
 /*
diff --git a_linux-2.6.33.3/kernel/sysctl.c b_linux-2.6.33.3/kernel/sysctl.c
index 8a68b24..ab644cb 100644
--- a_linux-2.6.33.3/kernel/sysctl.c
+++ b_linux-2.6.33.3/kernel/sysctl.c
@@ -50,6 +50,7 @@
 #include <linux/ftrace.h>
 #include <linux/slow-work.h>
 #include <linux/perf_event.h>
+#include <linux/console.h>
 
 #include <asm/uaccess.h>
 #include <asm/processor.h>
@@ -936,6 +937,13 @@ static struct ctl_table kern_table[] = {
 		.proc_handler	= proc_dointvec,
 	},
 #endif
+	{
+		.procname	= "console_detour",
+		.data		= &console_detour,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &detour_sysctl_handler,
+	},
 /*
  * NOTE: do not add new entries to this table unless you have read
  * Documentation/sysctl/ctl_unnumbered.txt
