x86, setup: enable early console output from the decompressor
authorYinghai Lu <yinghai@kernel.org>
Mon, 2 Aug 2010 23:21:22 +0000 (16:21 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Tue, 3 Aug 2010 03:32:20 +0000 (20:32 -0700)
This enables the decompressor output to be seen on the serial console.
Most of the code is shared with the regular boot code.

We could add printf to the decompressor if needed, but currently there
is no sufficiently compelling user.

-v2: define BOOT_BOOT_H to avoid include boot.h
-v3: early_serial_base need to be static in misc.c ?
-v4: create seperate string.c printf.c cmdline.c early_serial_console.c
     after hpa's patch that allow global variables in compressed/misc stage
-v5: remove printf.c related

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
arch/x86/boot/compressed/Makefile
arch/x86/boot/compressed/cmdline.c [new file with mode: 0644]
arch/x86/boot/compressed/early_serial_console.c [new file with mode: 0644]
arch/x86/boot/compressed/misc.c
arch/x86/boot/compressed/misc.h [new file with mode: 0644]
arch/x86/boot/compressed/string.c [new file with mode: 0644]
arch/x86/boot/main.c

index fbb47da..0c22955 100644 (file)
@@ -4,7 +4,7 @@
 # create a compressed vmlinux image from the original vmlinux
 #
 
-targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.lzo head_$(BITS).o misc.o piggy.o
+targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.lzo head_$(BITS).o misc.o string.o cmdline.o early_serial_console.o piggy.o
 
 KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
 KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
@@ -23,7 +23,7 @@ LDFLAGS_vmlinux := -T
 
 hostprogs-y    := mkpiggy
 
-$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/piggy.o FORCE
+$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o $(obj)/piggy.o FORCE
        $(call if_changed,ld)
        @:
 
diff --git a/arch/x86/boot/compressed/cmdline.c b/arch/x86/boot/compressed/cmdline.c
new file mode 100644 (file)
index 0000000..cb62f78
--- /dev/null
@@ -0,0 +1,21 @@
+#include "misc.h"
+
+static unsigned long fs;
+static inline void set_fs(unsigned long seg)
+{
+       fs = seg << 4;  /* shift it back */
+}
+typedef unsigned long addr_t;
+static inline char rdfs8(addr_t addr)
+{
+       return *((char *)(fs + addr));
+}
+#include "../cmdline.c"
+int cmdline_find_option(const char *option, char *buffer, int bufsize)
+{
+       return __cmdline_find_option(real_mode->hdr.cmd_line_ptr, option, buffer, bufsize);
+}
+int cmdline_find_option_bool(const char *option)
+{
+       return __cmdline_find_option_bool(real_mode->hdr.cmd_line_ptr, option);
+}
diff --git a/arch/x86/boot/compressed/early_serial_console.c b/arch/x86/boot/compressed/early_serial_console.c
new file mode 100644 (file)
index 0000000..261e81f
--- /dev/null
@@ -0,0 +1,5 @@
+#include "misc.h"
+
+int early_serial_base;
+
+#include "../early_serial_console.c"
index 51e2407..8f7bef8 100644 (file)
@@ -9,23 +9,7 @@
  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  */
 
-/*
- * we have to be careful, because no indirections are allowed here, and
- * paravirt_ops is a kind of one. As it will only run in baremetal anyway,
- * we just keep it from happening
- */
-#undef CONFIG_PARAVIRT
-#ifdef CONFIG_X86_32
-#define _ASM_X86_DESC_H 1
-#endif
-
-#include <linux/linkage.h>
-#include <linux/screen_info.h>
-#include <linux/elf.h>
-#include <linux/io.h>
-#include <asm/page.h>
-#include <asm/boot.h>
-#include <asm/bootparam.h>
+#include "misc.h"
 
 /* WARNING!!
  * This code is compiled with -fPIC and it is relocated dynamically
@@ -123,15 +107,13 @@ static void error(char *m);
 /*
  * This is set up by the setup-routine at boot-time
  */
-static struct boot_params *real_mode;          /* Pointer to real-mode data */
+struct boot_params *real_mode;         /* Pointer to real-mode data */
 static int quiet;
+static int debug;
 
 void *memset(void *s, int c, size_t n);
 void *memcpy(void *dest, const void *src, size_t n);
 
-static void __putstr(int, const char *);
-#define putstr(__x)  __putstr(0, __x)
-
 #ifdef CONFIG_X86_64
 #define memptr long
 #else
@@ -170,7 +152,21 @@ static void scroll(void)
                vidmem[i] = ' ';
 }
 
-static void __putstr(int error, const char *s)
+#define XMTRDY          0x20
+
+#define TXR             0       /*  Transmit register (WRITE) */
+#define LSR             5       /*  Line Status               */
+static void serial_putchar(int ch)
+{
+       unsigned timeout = 0xffff;
+
+       while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
+               cpu_relax();
+
+       outb(ch, early_serial_base + TXR);
+}
+
+void __putstr(int error, const char *s)
 {
        int x, y, pos;
        char c;
@@ -179,6 +175,14 @@ static void __putstr(int error, const char *s)
        if (!error)
                return;
 #endif
+       if (early_serial_base) {
+               const char *str = s;
+               while (*str) {
+                       if (*str == '\n')
+                               serial_putchar('\r');
+                       serial_putchar(*str++);
+               }
+       }
 
        if (real_mode->screen_info.orig_video_mode == 0 &&
            lines == 0 && cols == 0)
@@ -305,8 +309,10 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
 {
        real_mode = rmode;
 
-       if (real_mode->hdr.loadflags & QUIET_FLAG)
+       if (cmdline_find_option_bool("quiet"))
                quiet = 1;
+       if (cmdline_find_option_bool("debug"))
+               debug = 1;
 
        if (real_mode->screen_info.orig_video_mode == 7) {
                vidmem = (char *) 0xb0000;
@@ -319,6 +325,10 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
        lines = real_mode->screen_info.orig_video_lines;
        cols = real_mode->screen_info.orig_video_cols;
 
+       console_init();
+       if (debug)
+               putstr("early console in decompress_kernel\n");
+
        free_mem_ptr     = heap;        /* Heap */
        free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
 
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
new file mode 100644 (file)
index 0000000..a267849
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef BOOT_COMPRESSED_MISC_H
+#define BOOT_COMPRESSED_MISC_H
+
+/*
+ * we have to be careful, because no indirections are allowed here, and
+ * paravirt_ops is a kind of one. As it will only run in baremetal anyway,
+ * we just keep it from happening
+ */
+#undef CONFIG_PARAVIRT
+#ifdef CONFIG_X86_32
+#define _ASM_X86_DESC_H 1
+#endif
+
+#include <linux/linkage.h>
+#include <linux/screen_info.h>
+#include <linux/elf.h>
+#include <linux/io.h>
+#include <asm/page.h>
+#include <asm/boot.h>
+#include <asm/bootparam.h>
+
+#define BOOT_BOOT_H
+
+/* misc.c */
+extern struct boot_params *real_mode;          /* Pointer to real-mode data */
+void __putstr(int error, const char *s);
+#define putstr(__x)  __putstr(0, __x)
+#define puts(__x)  __putstr(0, __x)
+
+/* cmdline.c */
+int cmdline_find_option(const char *option, char *buffer, int bufsize);
+int cmdline_find_option_bool(const char *option);
+
+/* early_serial_console.c */
+extern int early_serial_base;
+void console_init(void);
+
+#endif
diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c
new file mode 100644 (file)
index 0000000..7995c6a
--- /dev/null
@@ -0,0 +1,4 @@
+#include "misc.h"
+
+#include "../isdigit.h"
+#include "../string.c"
index 4ef1a33..40358c8 100644 (file)
@@ -132,6 +132,8 @@ void main(void)
 
        /* Initialize the early-boot console */
        console_init();
+       if (cmdline_find_option_bool("debug"))
+               puts("early console in setup code\n");
 
        /* End of heap check */
        init_heap();
@@ -171,10 +173,6 @@ void main(void)
        /* Set the video mode */
        set_video();
 
-       /* Parse command line for 'quiet' and pass it to decompressor. */
-       if (cmdline_find_option_bool("quiet"))
-               boot_params.hdr.loadflags |= QUIET_FLAG;
-
        /* Do the last things and invoke protected mode */
        go_to_protected_mode();
 }