public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "Eric W. Biederman" <ebiederm@xmission.com>
To: <fastboot@osdl.org>
Cc: <linux-kernel@vger.kernel.org>, Horms <horms@verge.net.au>,
	Jan Kratochvil <lace@jankratochvil.net>,
	"H. Peter Anvin" <hpa@zytor.com>,
	Magnus Damm <magnus.damm@gmail.com>,
	Vivek Goyal <vgoyal@in.ibm.com>, Linda Wang <lwang@redhat.com>,
	"Eric W. Biederman" <ebiederm@xmission.com>
Subject: [PATCH 9/33] i386 boot: Add serial output support to the decompressor
Date: Tue,  1 Aug 2006 05:03:24 -0600	[thread overview]
Message-ID: <115443023544-git-send-email-ebiederm@xmission.com> (raw)
In-Reply-To: <m1d5bk2046.fsf@ebiederm.dsl.xmission.com>

This patch does two very simple things.
It adds a serial output capability to the decompressor.
It adds a command line parser for the early_printk
option so we know which output method to use for the decompressor.

This makes debugging the decompressor a little easier, and
keeps us from assuming we always have a vga console on all
hardware.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 arch/i386/boot/compressed/misc.c |  258 +++++++++++++++++++++++++++++++++++---
 1 files changed, 241 insertions(+), 17 deletions(-)

diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c
index 905c37e..fcaa9f0 100644
--- a/arch/i386/boot/compressed/misc.c
+++ b/arch/i386/boot/compressed/misc.c
@@ -9,11 +9,14 @@
  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  */
 
+#define __init
 #include <linux/config.h>
 #include <linux/linkage.h>
 #include <linux/vmalloc.h>
+#include <linux/serial_reg.h>
 #include <linux/screen_info.h>
 #include <asm/io.h>
+#include <asm/setup.h>
 
 /*
  * gzip declarations
@@ -24,7 +27,9 @@ #define STATIC static
 
 #undef memset
 #undef memcpy
+#undef memcmp
 #define memzero(s, n)     memset ((s), 0, (n))
+char *strstr(const char *haystack, const char *needle);
 
 typedef unsigned char  uch;
 typedef unsigned short ush;
@@ -78,12 +83,17 @@ static void gzip_release(void **);
  * This is set up by the setup-routine at boot-time
  */
 static unsigned char *real_mode; /* Pointer to real-mode data */
+static char saved_command_line[COMMAND_LINE_SIZE];
 
 #define RM_EXT_MEM_K   (*(unsigned short *)(real_mode + 0x2))
 #ifndef STANDARD_MEMORY_BIOS_CALL
 #define RM_ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
 #endif
 #define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
+#define RM_NEW_CL_POINTER ((char *)(unsigned long)(*(unsigned *)(real_mode+0x228)))
+#define RM_OLD_CL_MAGIC (*(unsigned short *)(real_mode + 0x20))
+#define RM_OLD_CL_OFFSET (*(unsigned short *)(real_mode + 0x22))
+#define OLD_CL_MAGIC 0xA33F
 
 extern unsigned char input_data[];
 extern int input_len;
@@ -97,8 +107,10 @@ static void free(void *where);
 
 static void *memset(void *s, int c, unsigned n);
 static void *memcpy(void *dest, const void *src, unsigned n);
+static int memcmp(const void *s1, const void *s2, unsigned n);
 
 static void putstr(const char *);
+static unsigned simple_strtou(const char *cp,char **endp,unsigned base);
 
 extern int end;
 static long free_mem_ptr = (long)&end;
@@ -112,14 +124,25 @@ static unsigned int low_buffer_end, low_
 static int high_loaded =0;
 static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/;
 
-static char *vidmem = (char *)0xb8000;
+static char *vidmem;
 static int vidport;
 static int lines, cols;
 
 #ifdef CONFIG_X86_NUMAQ
-static void * xquad_portio = NULL;
+static void * xquad_portio;
 #endif
 
+/* The early serial console */
+
+#define DEFAULT_BAUD 9600
+#define DEFAULT_BASE 0x3f8 /* ttyS0 */
+static unsigned serial_base = DEFAULT_BASE;
+
+#define CONSOLE_NOOP   0
+#define CONSOLE_VID    1
+#define CONSOLE_SERIAL 2
+static int console = CONSOLE_NOOP;
+
 #include "../../../../lib/inflate.c"
 
 static void *malloc(int size)
@@ -154,7 +177,8 @@ static void gzip_release(void **ptr)
 	free_mem_ptr = (long) *ptr;
 }
  
-static void scroll(void)
+/* The early video console */
+static void vid_scroll(void)
 {
 	int i;
 
@@ -163,7 +187,7 @@ static void scroll(void)
 		vidmem[i] = ' ';
 }
 
-static void putstr(const char *s)
+static void vid_putstr(const char *s)
 {
 	int x,y,pos;
 	char c;
@@ -175,7 +199,7 @@ static void putstr(const char *s)
 		if ( c == '\n' ) {
 			x = 0;
 			if ( ++y >= lines ) {
-				scroll();
+				vid_scroll();
 				y--;
 			}
 		} else {
@@ -183,7 +207,7 @@ static void putstr(const char *s)
 			if ( ++x >= cols ) {
 				x = 0;
 				if ( ++y >= lines ) {
-					scroll();
+					vid_scroll();
 					y--;
 				}
 			}
@@ -200,6 +224,178 @@ static void putstr(const char *s)
 	outb_p(0xff & (pos >> 1), vidport+1);
 }
 
+static void vid_console_init(void)
+{
+	if (RM_SCREEN_INFO.orig_video_mode == 7) {
+		vidmem = (char *) 0xb0000;
+		vidport = 0x3b4;
+	} else {
+		vidmem = (char *) 0xb8000;
+		vidport = 0x3d4;
+	}
+
+	lines = RM_SCREEN_INFO.orig_video_lines;
+	cols = RM_SCREEN_INFO.orig_video_cols;
+}
+
+/* The early serial console */
+static void serial_putc(int ch)
+{
+	if (ch == '\n') {
+		serial_putc('\r');
+	}
+	/* Wait until I can send a byte */
+	while ((inb(serial_base + UART_LSR) & UART_LSR_THRE) == 0)
+		;
+
+	/* Send the byte */
+	outb(ch, serial_base + UART_TX);
+
+	/* Wait until the byte is transmitted */
+	while (!(inb(serial_base + UART_LSR) & UART_LSR_TEMT))
+		;
+}
+
+static void serial_putstr(const char *str)
+{
+	int ch;
+	while((ch = *str++) != '\0') {
+		if (ch == '\n') {
+			serial_putc('\r');
+		}
+		serial_putc(ch);
+	}
+}
+
+static void serial_console_init(char *s)
+{
+	unsigned base = DEFAULT_BASE;
+	unsigned baud = DEFAULT_BAUD;
+	unsigned divisor;
+	char *e;
+
+	if (*s == ',')
+		++s;
+	if (*s && (*s != ' ')) {
+		if (memcmp(s, "0x", 2) == 0) {
+			base = simple_strtou(s, &e, 16);
+		} else {
+			static const unsigned bases[] = { 0x3f8, 0x2f8 };
+			unsigned port;
+
+			if (memcmp(s, "ttyS", 4) == 0)
+				s += 4;
+			port = simple_strtou(s, &e, 10);
+			if ((port > 1) || (s == e))
+				port = 0;
+			base = bases[port];
+		}
+		s = e;
+		if (*s == ',')
+			++s;
+	}
+	if (*s && (*s != ' ')) {
+		baud = simple_strtou(s, &e, 0);
+		if ((baud == 0) || (s == e))
+			baud = DEFAULT_BAUD;
+	}
+	divisor = 115200 / baud;
+	serial_base = base;
+
+	outb(0x00, serial_base + UART_IER); /* no interrupt */
+	outb(0x00, serial_base + UART_FCR); /* no fifo */
+	outb(0x03, serial_base + UART_MCR); /* DTR + RTS */
+
+	/* Set Baud Rate divisor  */
+	outb(0x83, serial_base + UART_LCR);
+	outb(divisor & 0xff, serial_base + UART_DLL);
+	outb(divisor >> 8, serial_base + UART_DLM);
+	outb(0x03, serial_base + UART_LCR); /* 8n1 */
+
+}
+
+static void putstr(const char *str)
+{
+	if (console == CONSOLE_VID) {
+		vid_putstr(str);
+	} else if (console == CONSOLE_SERIAL) {
+		serial_putstr(str);
+	}
+}
+
+static void console_init(char *cmdline)
+{
+	cmdline = strstr(cmdline, "earlyprintk=");
+	if (!cmdline)
+		return;
+	cmdline += 12;
+	if (memcmp(cmdline, "vga", 3) == 0) {
+		vid_console_init();
+		console = CONSOLE_VID;
+	} else if (memcmp(cmdline, "serial", 6) == 0) {
+		serial_console_init(cmdline + 6);
+		console = CONSOLE_SERIAL;
+	} else if (memcmp(cmdline, "ttyS", 4) == 0) {
+		serial_console_init(cmdline);
+		console = CONSOLE_SERIAL;
+	}
+}
+
+static inline int tolower(int ch)
+{
+	return ch | 0x20;
+}
+
+static inline int isdigit(int ch)
+{
+	return (ch >= '0') && (ch <= '9');
+}
+
+static inline int isxdigit(int ch)
+{
+	ch = tolower(ch);
+	return isdigit(ch) || ((ch >= 'a') && (ch <= 'f'));
+}
+
+
+static inline int digval(int ch)
+{
+	return isdigit(ch)? (ch - '0') : tolower(ch) - 'a' + 10;
+}
+
+/**
+ * simple_strtou - convert a string to an unsigned
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+static unsigned simple_strtou(const char *cp, char **endp, unsigned base)
+{
+	unsigned result = 0,value;
+
+	if (!base) {
+		base = 10;
+		if (*cp == '0') {
+			base = 8;
+			cp++;
+			if ((tolower(*cp) == 'x') && isxdigit(cp[1])) {
+				cp++;
+				base = 16;
+			}
+		}
+	} else if (base == 16) {
+		if (cp[0] == '0' && tolower(cp[1]) == 'x')
+			cp += 2;
+	}
+	while (isxdigit(*cp) && ((value = digval(*cp)) < base)) {
+		result = result*base + value;
+		cp++;
+	}
+	if (endp)
+		*endp = (char *)cp;
+	return result;
+}
+
 static void* memset(void* s, int c, unsigned n)
 {
 	int i;
@@ -218,6 +414,29 @@ static void* memcpy(void* dest, const vo
 	return dest;
 }
 
+static int memcmp(const void *s1, const void *s2, unsigned n)
+{
+	const unsigned char *str1 = s1, *str2 = s2;
+	size_t i;
+	int result = 0;
+	for(i = 0; (result == 0) && (i < n); i++) {
+		result = *str1++ - *str2++;
+		}
+	return result;
+}
+
+char *strstr(const char *haystack, const char *needle)
+{
+	size_t len;
+	len = strlen(needle);
+	while(*haystack) {
+		if (memcmp(haystack, needle, len) == 0)
+			return (char *)haystack;
+		haystack++;
+	}
+	return NULL;
+}
+
 /* ===========================================================================
  * Fill the input buffer. This is called only when the buffer is empty
  * and at least one byte is really needed.
@@ -346,20 +565,25 @@ static void close_output_buffer_if_we_ru
 	}
 }
 
-asmlinkage int decompress_kernel(struct moveparams *mv, void *rmode)
+static void save_command_line(void)
 {
-	real_mode = rmode;
-
-	if (RM_SCREEN_INFO.orig_video_mode == 7) {
-		vidmem = (char *) 0xb0000;
-		vidport = 0x3b4;
-	} else {
-		vidmem = (char *) 0xb8000;
-		vidport = 0x3d4;
+	/* Find the command line */
+	char *cmdline;
+	cmdline = saved_command_line;
+	if (RM_NEW_CL_POINTER) {
+		cmdline = RM_NEW_CL_POINTER;
+	} else if (OLD_CL_MAGIC == RM_OLD_CL_MAGIC) {
+		cmdline = real_mode + RM_OLD_CL_OFFSET;
 	}
+	memcpy(saved_command_line, cmdline, COMMAND_LINE_SIZE);
+	saved_command_line[COMMAND_LINE_SIZE - 1] = '\0';
+}
 
-	lines = RM_SCREEN_INFO.orig_video_lines;
-	cols = RM_SCREEN_INFO.orig_video_cols;
+asmlinkage int decompress_kernel(struct moveparams *mv, void *rmode)
+{
+	real_mode = rmode;
+	save_command_line();
+	console_init(saved_command_line);
 
 	if (free_mem_ptr < 0x100000) setup_normal_output_buffer();
 	else setup_output_buffer_if_we_run_high(mv);
-- 
1.4.2.rc2.g5209e


  parent reply	other threads:[~2006-08-01 11:09 UTC|newest]

Thread overview: 105+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-08-01 10:58 [RFC] ELF Relocatable x86 and x86_64 bzImages Eric W. Biederman
2006-08-01 11:03 ` [PATCH 1/33] i386: vmlinux.lds.S Distinguish absolute symbols Eric W. Biederman
2006-08-01 19:06   ` Sam Ravnborg
2006-08-01 11:03 ` [PATCH 2/33] i386: define __pa_symbol Eric W. Biederman
2006-08-01 19:06   ` Andi Kleen
2006-08-02  2:19     ` Eric W. Biederman
2006-08-02  3:04       ` Andi Kleen
2006-08-01 11:03 ` [PATCH 3/33] i386 setup.c: Reserve kernel memory starting from _text Eric W. Biederman
2006-08-01 11:03 ` [PATCH 4/33] i386: CONFIG_PHYSICAL_START cleanup Eric W. Biederman
2006-08-01 19:08   ` Sam Ravnborg
2006-08-02  2:23     ` Eric W. Biederman
2006-08-02 16:14     ` Eric W. Biederman
2006-08-03 14:05       ` Sam Ravnborg
2006-08-01 11:03 ` [PATCH 5/33] i386 Kconfig: Add a range definition to config PHYSICAL_START Eric W. Biederman
2006-08-01 11:03 ` [PATCH 6/33] Make linux/elf.h safe to be included in assembly files Eric W. Biederman
2006-08-01 11:03 ` [PATCH 7/33] elf: Add ELFOSABI_STANDALONE to elf.h Eric W. Biederman
2006-08-01 11:03 ` [PATCH 8/33] kallsyms.c: Generate relocatable symbols Eric W. Biederman
2006-08-01 11:36   ` Paulo Marques
2006-08-01 11:52     ` Eric W. Biederman
2006-08-01 11:03 ` Eric W. Biederman [this message]
2006-08-01 19:19   ` [PATCH 9/33] i386 boot: Add serial output support to the decompressor Andi Kleen
2006-08-02  2:30     ` Eric W. Biederman
2006-08-02  3:07       ` Andi Kleen
2006-08-02  4:57         ` Eric W. Biederman
2006-08-02  5:21           ` Andi Kleen
2006-08-02  6:44             ` Eric W. Biederman
2006-08-02  3:06     ` Eric W. Biederman
2006-08-02  3:10       ` Andi Kleen
2006-08-02  5:27         ` Eric W. Biederman
2006-08-02  5:44           ` Andi Kleen
2006-08-02  7:14             ` Eric W. Biederman
2006-08-01 11:03 ` [PATCH 10/33] i386: Relocatable kernel support Eric W. Biederman
2006-08-01 13:34   ` Mika Penttilä
2006-08-01 18:07     ` Eric W. Biederman
2006-08-01 18:11       ` Sam Ravnborg
2006-08-01 18:16       ` Mika Penttilä
2006-08-01 11:03 ` [PATCH 11/33] i386 boot: Add an ELF header to bzImage Eric W. Biederman
2006-08-01 22:10   ` Jeremy Fitzhardinge
2006-08-02  2:38     ` Eric W. Biederman
2006-08-01 11:03 ` [PATCH 12/33] x86_64: fixup indentation in e820.c Eric W. Biederman
2006-08-01 11:03 ` [PATCH 13/33] x86_64: Remove assumptions about the kernel start address from e820/bad_addr() Eric W. Biederman
2006-08-01 11:03 ` [PATCH 14/33] x86_64: Properly report in /proc/iomem the kernel address Eric W. Biederman
2006-08-01 11:03 ` [PATCH 15/33] x86_64: Fix kernel direct mapping size check Eric W. Biederman
2006-08-01 11:03 ` [PATCH 16/33] x86_64: Assembly safe page.h and pgtable.h Eric W. Biederman
2006-08-01 11:03 ` [PATCH 17/33] x86_64: Separate normal memory map initialization from the hotplug case Eric W. Biederman
2006-08-01 11:03 ` [PATCH 18/33] x86_64: Kill temp_boot_pmds Eric W. Biederman
2006-08-01 19:02   ` Andi Kleen
2006-08-02  2:08     ` Eric W. Biederman
2006-08-01 19:04   ` [PATCH 18/33] x86_64: Kill temp_boot_pmds II Andi Kleen
2006-08-02  2:11     ` Eric W. Biederman
2006-08-02  3:07       ` Andi Kleen
2006-08-02  5:35         ` Eric W. Biederman
2006-08-01 11:03 ` [PATCH 19/33] x86_64: Cleanup the early boot page table Eric W. Biederman
2006-08-01 11:03 ` [PATCH 20/33] x86_64: fix early_printk to use the standard ISA mapping Eric W. Biederman
2006-08-01 11:03 ` [PATCH 21/33] x86_64: modify copy_bootdata to use virtual addresses Eric W. Biederman
2006-08-01 11:03 ` [PATCH 22/33] x86_64: Fix gdt table size in trampoline.S Eric W. Biederman
2006-08-01 18:59   ` Andi Kleen
2006-08-01 11:03 ` [PATCH 23/33] x86_64: cleanup segments Eric W. Biederman
2006-08-01 11:03 ` [PATCH 24/33] x86_64: Add EFER to the set registers saved by save_processor_state Eric W. Biederman
2006-08-01 11:03 ` [PATCH 25/33] x86_64: 64bit PIC SMP trampoline Eric W. Biederman
2006-08-01 19:13   ` Andi Kleen
2006-08-01 11:03 ` [PATCH 26/33] x86_64: 64bit PIC ACPI wakeup Eric W. Biederman
2006-08-01 19:10   ` Andi Kleen
2006-08-01 11:03 ` [PATCH 27/33] x86_64: Modify discover_ebda to use virtual addresses Eric W. Biederman
2006-08-01 11:03 ` [PATCH 28/33] x86_64: Remove the identity mapping as early as possible Eric W. Biederman
2006-08-01 19:15   ` Andi Kleen
2006-08-01 11:03 ` [PATCH 29/33] x86_64: __pa and __pa_symbol address space separation Eric W. Biederman
2006-08-01 11:03 ` [PATCH 30/33] x86_64: Remove CONFIG_PHYSICAL_START Eric W. Biederman
2006-08-01 11:03 ` [PATCH 31/33] x86_64 boot: Add serial output support to the decompressor Eric W. Biederman
2006-08-01 11:03 ` [PATCH 32/33] x86_64: Relocatable kernel support Eric W. Biederman
2006-08-01 19:11   ` Andi Kleen
2006-08-02  2:25     ` Eric W. Biederman
2006-11-05  6:02       ` Yinghai Lu
2006-11-05  6:52         ` Eric W. Biederman
2006-11-05  7:15           ` Yinghai Lu
2006-08-01 11:03 ` [PATCH 33/33] x86_64: Make bzImage a valid 64bit elf executable Eric W. Biederman
2006-08-01 19:26 ` [RFC] ELF Relocatable x86 and x86_64 bzImages Vivek Goyal
2006-08-01 20:13   ` Jan Kratochvil
2006-08-01 20:25   ` H. Peter Anvin
2006-08-02  2:02     ` Eric W. Biederman
2006-08-01 20:40 ` Vivek Goyal
2006-08-02  2:40   ` Eric W. Biederman
2006-08-02  6:34 ` Magnus Damm
2006-08-02  7:09   ` Eric W. Biederman
2006-08-02  8:34     ` Magnus Damm
2006-08-02  9:59       ` Eric W. Biederman
2006-08-02 18:37 ` [Fastboot] " Don Zickus
2006-08-03  1:00   ` Eric W. Biederman
2006-08-03  4:53     ` H. Peter Anvin
2006-08-04 22:56 ` Vivek Goyal
2006-08-04 23:14   ` Eric W. Biederman
2006-08-04 23:38     ` Dave Jones
2006-08-04 23:47       ` H. Peter Anvin
2006-08-05  8:01         ` Eric W. Biederman
2006-08-08  3:34     ` Horms
2006-08-08  4:32       ` H. Peter Anvin
2006-08-08  4:57         ` Magnus Damm
2006-08-08  5:04         ` Eric W. Biederman
2006-08-08  6:09         ` Horms
2006-08-08  7:23           ` Eric W. Biederman
2006-08-08  7:58             ` Horms
2006-08-09 14:56               ` D. Hazelton
2006-08-17 18:44             ` Vivek Goyal
2006-08-11 13:11   ` [Fastboot] " Rachita Kothiyal
2006-08-11 13:36     ` Vivek Goyal

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=115443023544-git-send-email-ebiederm@xmission.com \
    --to=ebiederm@xmission.com \
    --cc=fastboot@osdl.org \
    --cc=horms@verge.net.au \
    --cc=hpa@zytor.com \
    --cc=lace@jankratochvil.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lwang@redhat.com \
    --cc=magnus.damm@gmail.com \
    --cc=vgoyal@in.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox