ARM: Add an earlyprintk debug console
Catalin Marinas [Wed, 9 Dec 2009 10:02:18 +0000 (10:02 +0000)]
This patch allows an earlyprintk console if CONFIG_DEBUG_LL is enabled,
using the printch asm function.

The patch is based on the original work by Sascha Hauer.

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Acked-by: Uwe Kleine-K├Ânig <u.kleine-koenig@pengutronix.de>
Acked-by: Pavel Machek <pavel@ucw.cz>

arch/arm/Kconfig.debug
arch/arm/kernel/Makefile
arch/arm/kernel/early_printk.c [new file with mode: 0644]

index 1a6f70e..feb7b11 100644 (file)
@@ -71,6 +71,14 @@ config DEBUG_LL
          in the kernel.  This is helpful if you are debugging code that
          executes before the console is initialized.
 
+config EARLY_PRINTK
+       bool "Early printk"
+       depends on DEBUG_LL
+       help
+         Say Y here if you want to have an early console using the
+         kernel low-level debugging functions. Add earlyprintk to your
+         kernel parameters to enable this console.
+
 config DEBUG_ICEDCC
        bool "Kernel low-level debugging via EmbeddedICE DCC channel"
        depends on DEBUG_LL
index 79087dd..d0e40b7 100644 (file)
@@ -52,5 +52,6 @@ endif
 
 head-y                 := head$(MMUEXT).o
 obj-$(CONFIG_DEBUG_LL) += debug.o
+obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 
 extra-y := $(head-y) init_task.o vmlinux.lds
diff --git a/arch/arm/kernel/early_printk.c b/arch/arm/kernel/early_printk.c
new file mode 100644 (file)
index 0000000..85aa2b2
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  linux/arch/arm/kernel/early_printk.c
+ *
+ *  Copyright (C) 2009 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/init.h>
+
+extern void printch(int);
+
+static void early_write(const char *s, unsigned n)
+{
+       while (n-- > 0) {
+               if (*s == '\n')
+                       printch('\r');
+               printch(*s);
+               s++;
+       }
+}
+
+static void early_console_write(struct console *con, const char *s, unsigned n)
+{
+       early_write(s, n);
+}
+
+static struct console early_console = {
+       .name =         "earlycon",
+       .write =        early_console_write,
+       .flags =        CON_PRINTBUFFER | CON_BOOT,
+       .index =        -1,
+};
+
+asmlinkage void early_printk(const char *fmt, ...)
+{
+       char buf[512];
+       int n;
+       va_list ap;
+
+       va_start(ap, fmt);
+       n = vscnprintf(buf, sizeof(buf), fmt, ap);
+       early_write(buf, n);
+       va_end(ap);
+}
+
+static int __init setup_early_printk(char *buf)
+{
+       register_console(&early_console);
+       return 0;
+}
+
+early_param("earlyprintk", setup_early_printk);