From: Dave Hansen Most architectures have some way of doing printk()'s before console_init(). x86 doesn't. x86_64 has a self-contained serial and vga driver that do the trick. This could easily be a multiple architecture thing, but I didn't want to clutter up generic code with things that no one else is ever going to use. The ugly part here is the de-static'ing of the console init functions, and trying to keep the serial init function from running twice. The other part that I don't like is getting the console= part at config time. But, getting arguments parsed this early requires some invasive surgery in early boot. Although it _is_ ugly, it's also pretty small. Martin Bligh has promised to add vga support too. 25-akpm/arch/i386/Kconfig | 31 +++++++++++++++++++++++++++++++ 25-akpm/arch/i386/kernel/setup.c | 23 +++++++++++++++++++++++ 25-akpm/drivers/serial/8250.c | 7 ++++++- 25-akpm/include/linux/kernel.h | 6 ++++++ 25-akpm/init/main.c | 1 + 25-akpm/kernel/printk.c | 2 +- 6 files changed, 68 insertions(+), 2 deletions(-) diff -puN arch/i386/Kconfig~early-printk-x86 arch/i386/Kconfig --- 25/arch/i386/Kconfig~early-printk-x86 Tue Jun 10 15:54:47 2003 +++ 25-akpm/arch/i386/Kconfig Tue Jun 10 15:54:47 2003 @@ -1761,6 +1761,37 @@ config FRAME_POINTER and slower, but it will give very useful debugging information. If you don't debug the kernel, you can say N, but we may not be able to solve problems without frame pointers. +choice + prompt "Early printk support" + default DEBUG_EARLY_PRINTK_OFF + depends on DEBUG_KERNEL + +config DEBUG_EARLY_PRINTK_OFF + bool "off" + +config DEBUG_EP_SERIAL + bool "serial" + depends on SERIAL_8250_CONSOLE && SERIAL_CORE_CONSOLE + +config DEBUG_EP_VGA + bool "vga" + +endchoice + +config DEBUG_EARLY_PRINTK + bool + depends on !DEBUG_EARLY_PRINTK_OFF + default y + +config DEBUG_SERIAL_OPTIONS + string "serial port options" + default "ttyS0,57600" + depends on DEBUG_EP_SERIAL + help + This should be the same thing that you would put on the kernel + command line for the serial console, minus the 'console=' part. + This will override whatever you put on the command line, so + be sure to get it right. config MAGIC_SYSRQ bool diff -puN arch/i386/kernel/setup.c~early-printk-x86 arch/i386/kernel/setup.c --- 25/arch/i386/kernel/setup.c~early-printk-x86 Tue Jun 10 15:54:47 2003 +++ 25-akpm/arch/i386/kernel/setup.c Tue Jun 10 15:54:47 2003 @@ -905,6 +905,29 @@ static int __init noreplacement_setup(ch __setup("noreplacement", noreplacement_setup); +#ifdef CONFIG_DEBUG_EARLY_PRINTK +extern int __init console_setup(char *); +extern int __init serial8250_console_init(void); +void setup_early_printk(void) +{ + /* + * printk currently checks cpu_online_map to make sure that + * we don't try to printk from a CPU which hasn't had resources + * allocated for it yet. Make sure that whatever consoles you + * enable here don't require per-cpu resources. + */ + set_bit(smp_processor_id(), &cpu_online_map); +#ifdef CONFIG_DEBUG_EP_SERIAL + console_setup(CONFIG_DEBUG_SERIAL_OPTIONS); + serial8250_console_init(); + printk("early serial console support registered\n"); +#endif +#ifdef DEBUG_EARLY_PRINTK_VGA + // blah blah +#endif +} +#endif + void __init setup_arch(char **cmdline_p) { unsigned long max_low_pfn; diff -puN drivers/serial/8250.c~early-printk-x86 drivers/serial/8250.c --- 25/drivers/serial/8250.c~early-printk-x86 Tue Jun 10 15:54:47 2003 +++ 25-akpm/drivers/serial/8250.c Tue Jun 10 15:54:47 2003 @@ -1995,10 +1995,15 @@ static struct console serial8250_console .data = &serial8250_reg, }; -static int __init serial8250_console_init(void) +int __init serial8250_console_init(void) { + static int initialized = 0; + if (initialized) + return 0; + serial8250_isa_init_ports(); register_console(&serial8250_console); + initialized = 1; return 0; } console_initcall(serial8250_console_init); diff -puN include/linux/kernel.h~early-printk-x86 include/linux/kernel.h --- 25/include/linux/kernel.h~early-printk-x86 Tue Jun 10 15:54:47 2003 +++ 25-akpm/include/linux/kernel.h Tue Jun 10 15:54:47 2003 @@ -47,6 +47,12 @@ extern int console_printk[]; #define minimum_console_loglevel (console_printk[2]) #define default_console_loglevel (console_printk[3]) +#ifdef CONFIG_DEBUG_EARLY_PRINTK +extern void setup_early_printk(void); +#else +#define setup_early_printk() do {} while (0) +#endif + struct completion; #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP diff -puN init/main.c~early-printk-x86 init/main.c --- 25/init/main.c~early-printk-x86 Tue Jun 10 15:54:47 2003 +++ 25-akpm/init/main.c Tue Jun 10 15:54:47 2003 @@ -389,6 +389,7 @@ asmlinkage void __init start_kernel(void * enable them */ lock_kernel(); + setup_early_printk(); printk(linux_banner); setup_arch(&command_line); setup_per_zone_pages_min(); diff -puN kernel/printk.c~early-printk-x86 kernel/printk.c --- 25/kernel/printk.c~early-printk-x86 Tue Jun 10 15:54:47 2003 +++ 25-akpm/kernel/printk.c Tue Jun 10 15:54:47 2003 @@ -89,7 +89,7 @@ static int console_may_schedule; /* * Setup a list of consoles. Called from init/main.c */ -static int __init console_setup(char *str) +int __init console_setup(char *str) { struct console_cmdline *c; char name[sizeof(c->name)]; _