All of lore.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.