2010-08-02 07:14:40

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 1/2] x86, setup: reorgize the early_console_setup


Seperate early_console_setup from tty.c
also make main.c to include printf.c/string.c/cmdline.c

will reuse early_serial_console.c/string.c/printf.c/cmdline.c in compressed/misc.c

Signed-off-by: Yinghai Lu <[email protected]>

---
arch/x86/boot/Makefile | 4
arch/x86/boot/boot.h | 16 ---
arch/x86/boot/cmdline.c | 8 -
arch/x86/boot/early_serial_console.c | 139 ++++++++++++++++++++++++++++++++++
arch/x86/boot/main.c | 14 +++
arch/x86/boot/printf.c | 6 -
arch/x86/boot/string.c | 16 +++
arch/x86/boot/tty.c | 141 -----------------------------------
8 files changed, 175 insertions(+), 169 deletions(-)

Index: linux-2.6/arch/x86/boot/tty.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/tty.c
+++ linux-2.6/arch/x86/boot/tty.c
@@ -15,27 +15,7 @@

#include "boot.h"

-#define DEFAULT_SERIAL_PORT 0x3f8 /* ttyS0 */
-
-static int early_serial_base;
-
-#define XMTRDY 0x20
-
-#define DLAB 0x80
-
-#define TXR 0 /* Transmit register (WRITE) */
-#define RXR 0 /* Receive register (READ) */
-#define IER 1 /* Interrupt Enable */
-#define IIR 2 /* Interrupt ID */
-#define FCR 2 /* FIFO control */
-#define LCR 3 /* Line control */
-#define MCR 4 /* Modem control */
-#define LSR 5 /* Line Status */
-#define MSR 6 /* Modem Status */
-#define DLL 0 /* Divisor Latch Low */
-#define DLH 1 /* Divisor latch High */
-
-#define DEFAULT_BAUD 9600
+#include "early_serial_console.c"

/*
* These functions are in .inittext so they can be used to signal
@@ -152,122 +132,3 @@ int getchar_timeout(void)
return 0; /* Timeout! */
}

-static void early_serial_init(int port, int baud)
-{
- unsigned char c;
- unsigned divisor;
-
- outb(0x3, port + LCR); /* 8n1 */
- outb(0, port + IER); /* no interrupt */
- outb(0, port + FCR); /* no fifo */
- outb(0x3, port + MCR); /* DTR + RTS */
-
- divisor = 115200 / baud;
- c = inb(port + LCR);
- outb(c | DLAB, port + LCR);
- outb(divisor & 0xff, port + DLL);
- outb((divisor >> 8) & 0xff, port + DLH);
- outb(c & ~DLAB, port + LCR);
-
- early_serial_base = port;
-
- printf("Early serial console at I/O port 0x%x baud: %d\n", port, baud);
-}
-
-static void parse_earlyprintk(void)
-{
- int baud = DEFAULT_BAUD;
- char arg[32];
- int pos = 0;
- int port = 0;
-
- if (cmdline_find_option("earlyprintk", arg, sizeof arg) > 0) {
- char *e;
-
- if (!strncmp(arg, "serial", 6)) {
- port = DEFAULT_SERIAL_PORT;
- pos += 6;
- }
-
- if (arg[pos] == ',')
- pos++;
-
- if (!strncmp(arg, "ttyS", 4)) {
- static const int bases[] = { 0x3f8, 0x2f8 };
- int idx = 0;
-
- if (!strncmp(arg + pos, "ttyS", 4))
- pos += 4;
-
- if (arg[pos++] == '1')
- idx = 1;
-
- port = bases[idx];
- }
-
- if (arg[pos] == ',')
- pos++;
-
- baud = simple_strtoull(arg + pos, &e, 0);
- if (baud == 0 || arg + pos == e)
- baud = DEFAULT_BAUD;
- }
-
- if (port)
- early_serial_init(port, baud);
-}
-
-#define BASE_BAUD (1843200/16)
-static unsigned int probe_baud(int port)
-{
- unsigned char lcr, dll, dlh;
- unsigned int quot;
-
- lcr = inb(port + LCR);
- outb(lcr | DLAB, port + LCR);
- dll = inb(port + DLL);
- dlh = inb(port + DLH);
- outb(lcr, port + LCR);
- quot = (dlh << 8) | dll;
-
- return BASE_BAUD / quot;
-}
-
-static void parse_console_uart8250(void)
-{
- char optstr[64], *options;
- int baud = DEFAULT_BAUD;
- int port = 0;
-
- /*
- * console=uart8250,io,0x3f8,115200n8
- * need to make sure it is last one console !
- */
- if (cmdline_find_option("console", optstr, sizeof optstr) <= 0)
- return;
-
- options = optstr;
-
- if (!strncmp(options, "uart8250,io,", 12))
- port = simple_strtoull(options + 12, &options, 0);
- else if (!strncmp(options, "uart,io,", 8))
- port = simple_strtoull(options + 8, &options, 0);
- else
- return;
-
- if (options && (options[0] == ','))
- baud = simple_strtoull(options + 1, &options, 0);
- else
- baud = probe_baud(port);
-
- if (port)
- early_serial_init(port, baud);
-}
-
-void console_init(void)
-{
- parse_earlyprintk();
-
- if (!early_serial_base)
- parse_console_uart8250();
-}
Index: linux-2.6/arch/x86/boot/early_serial_console.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/early_serial_console.c
@@ -0,0 +1,139 @@
+static int early_serial_base;
+
+#define DEFAULT_SERIAL_PORT 0x3f8 /* ttyS0 */
+
+#define XMTRDY 0x20
+
+#define DLAB 0x80
+
+#define TXR 0 /* Transmit register (WRITE) */
+#define RXR 0 /* Receive register (READ) */
+#define IER 1 /* Interrupt Enable */
+#define IIR 2 /* Interrupt ID */
+#define FCR 2 /* FIFO control */
+#define LCR 3 /* Line control */
+#define MCR 4 /* Modem control */
+#define LSR 5 /* Line Status */
+#define MSR 6 /* Modem Status */
+#define DLL 0 /* Divisor Latch Low */
+#define DLH 1 /* Divisor latch High */
+
+#define DEFAULT_BAUD 9600
+
+static void early_serial_init(int port, int baud)
+{
+ unsigned char c;
+ unsigned divisor;
+
+ outb(0x3, port + LCR); /* 8n1 */
+ outb(0, port + IER); /* no interrupt */
+ outb(0, port + FCR); /* no fifo */
+ outb(0x3, port + MCR); /* DTR + RTS */
+
+ divisor = 115200 / baud;
+ c = inb(port + LCR);
+ outb(c | DLAB, port + LCR);
+ outb(divisor & 0xff, port + DLL);
+ outb((divisor >> 8) & 0xff, port + DLH);
+ outb(c & ~DLAB, port + LCR);
+
+ early_serial_base = port;
+}
+
+static void parse_earlyprintk(void)
+{
+ int baud = DEFAULT_BAUD;
+ char arg[32];
+ int pos = 0;
+ int port = 0;
+
+ if (cmdline_find_option("earlyprintk", arg, sizeof arg) > 0) {
+ char *e;
+
+ if (!strncmp(arg, "serial", 6)) {
+ port = DEFAULT_SERIAL_PORT;
+ pos += 6;
+ }
+
+ if (arg[pos] == ',')
+ pos++;
+
+ if (!strncmp(arg, "ttyS", 4)) {
+ static const int bases[] = { 0x3f8, 0x2f8 };
+ int idx = 0;
+
+ if (!strncmp(arg + pos, "ttyS", 4))
+ pos += 4;
+
+ if (arg[pos++] == '1')
+ idx = 1;
+
+ port = bases[idx];
+ }
+
+ if (arg[pos] == ',')
+ pos++;
+
+ baud = simple_strtoull(arg + pos, &e, 0);
+ if (baud == 0 || arg + pos == e)
+ baud = DEFAULT_BAUD;
+ }
+
+ if (port)
+ early_serial_init(port, baud);
+}
+
+#define BASE_BAUD (1843200/16)
+static unsigned int probe_baud(int port)
+{
+ unsigned char lcr, dll, dlh;
+ unsigned int quot;
+
+ lcr = inb(port + LCR);
+ outb(lcr | DLAB, port + LCR);
+ dll = inb(port + DLL);
+ dlh = inb(port + DLH);
+ outb(lcr, port + LCR);
+ quot = (dlh << 8) | dll;
+
+ return BASE_BAUD / quot;
+}
+
+static void parse_console_uart8250(void)
+{
+ char optstr[64], *options;
+ int baud = DEFAULT_BAUD;
+ int port = 0;
+
+ /*
+ * console=uart8250,io,0x3f8,115200n8
+ * need to make sure it is last one console !
+ */
+ if (cmdline_find_option("console", optstr, sizeof optstr) <= 0)
+ return;
+
+ options = optstr;
+
+ if (!strncmp(options, "uart8250,io,", 12))
+ port = simple_strtoull(options + 12, &options, 0);
+ else if (!strncmp(options, "uart,io,", 8))
+ port = simple_strtoull(options + 8, &options, 0);
+ else
+ return;
+
+ if (options && (options[0] == ','))
+ baud = simple_strtoull(options + 1, &options, 0);
+ else
+ baud = probe_baud(port);
+
+ if (port)
+ early_serial_init(port, baud);
+}
+
+void console_init(void)
+{
+ parse_earlyprintk();
+
+ if (!early_serial_base)
+ parse_console_uart8250();
+}
Index: linux-2.6/arch/x86/boot/Makefile
===================================================================
--- linux-2.6.orig/arch/x86/boot/Makefile
+++ linux-2.6/arch/x86/boot/Makefile
@@ -26,9 +26,9 @@ targets := vmlinux.bin setup.bin setup.
targets += fdimage fdimage144 fdimage288 image.iso mtools.conf
subdir- := compressed

-setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o edd.o
+setup-y += a20.o bioscall.o copy.o cpu.o cpucheck.o edd.o
setup-y += header.o main.o mca.o memory.o pm.o pmjump.o
-setup-y += printf.o regs.o string.o tty.o video.o video-mode.o
+setup-y += regs.o tty.o video.o video-mode.o
setup-y += version.o
setup-$(CONFIG_X86_APM_BOOT) += apm.o

Index: linux-2.6/arch/x86/boot/printf.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/printf.c
+++ linux-2.6/arch/x86/boot/printf.c
@@ -15,8 +15,6 @@
*
*/

-#include "boot.h"
-
static int skip_atoi(const char **s)
{
int i = 0;
@@ -34,7 +32,7 @@ static int skip_atoi(const char **s)
#define SMALL 32 /* Must be 32 == 0x20 */
#define SPECIAL 64 /* 0x */

-#define do_div(n,base) ({ \
+#define __do_div(n,base) ({ \
int __res; \
__res = ((unsigned long) n) % (unsigned) base; \
n = ((unsigned long) n) / (unsigned) base; \
@@ -83,7 +81,7 @@ static char *number(char *str, long num,
tmp[i++] = '0';
else
while (num != 0)
- tmp[i++] = (digits[do_div(num, base)] | locase);
+ tmp[i++] = (digits[__do_div(num, base)] | locase);
if (i > precision)
precision = i;
size -= precision;
Index: linux-2.6/arch/x86/boot/string.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/string.c
+++ linux-2.6/arch/x86/boot/string.c
@@ -12,7 +12,21 @@
* Very basic string functions
*/

-#include "boot.h"
+static inline int isdigit(int ch)
+{
+ return (ch >= '0') && (ch <= '9');
+}
+
+static inline int isxdigit(int ch)
+{
+ if (isdigit(ch))
+ return true;
+
+ if ((ch >= 'a') && (ch <= 'f'))
+ return true;
+
+ return (ch >= 'A') && (ch <= 'F');
+}

int strcmp(const char *str1, const char *str2)
{
Index: linux-2.6/arch/x86/boot/boot.h
===================================================================
--- linux-2.6.orig/arch/x86/boot/boot.h
+++ linux-2.6/arch/x86/boot/boot.h
@@ -200,22 +200,6 @@ static inline int memcmp_gs(const void *
return diff;
}

-static inline int isdigit(int ch)
-{
- return (ch >= '0') && (ch <= '9');
-}
-
-static inline int isxdigit(int ch)
-{
- if (isdigit(ch))
- return true;
-
- if ((ch >= 'a') && (ch <= 'f'))
- return true;
-
- return (ch >= 'A') && (ch <= 'F');
-}
-
/* Heap -- available for dynamic lists. */
extern char _end[];
extern char *HEAP;
Index: linux-2.6/arch/x86/boot/cmdline.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/cmdline.c
+++ linux-2.6/arch/x86/boot/cmdline.c
@@ -12,8 +12,6 @@
* Simple command-line parser for early boot.
*/

-#include "boot.h"
-
static inline int myisspace(u8 c)
{
return c <= ' '; /* Close enough approximation */
@@ -27,9 +25,8 @@ static inline int myisspace(u8 c)
* Returns the length of the argument (regardless of if it was
* truncated to fit in the buffer), or -1 on not found.
*/
-int cmdline_find_option(const char *option, char *buffer, int bufsize)
+static int __cmdline_find_option(u32 cmdline_ptr, const char *option, char *buffer, int bufsize)
{
- u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
addr_t cptr;
char c;
int len = -1;
@@ -100,9 +97,8 @@ int cmdline_find_option(const char *opti
* Returns the position of that option (starts counting with 1)
* or 0 on not found
*/
-int cmdline_find_option_bool(const char *option)
+static int __cmdline_find_option_bool(u32 cmdline_ptr, const char *option)
{
- u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
addr_t cptr;
char c;
int pos = 0, wstart = 0;
Index: linux-2.6/arch/x86/boot/main.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/main.c
+++ linux-2.6/arch/x86/boot/main.c
@@ -15,6 +15,20 @@

#include "boot.h"

+#include "string.c"
+#include "printf.c"
+
+#include "cmdline.c"
+int cmdline_find_option(const char *option, char *buffer, int bufsize)
+{
+ return __cmdline_find_option(boot_params.hdr.cmd_line_ptr, option, buffer, bufsize);
+}
+
+int cmdline_find_option_bool(const char *option)
+{
+ return __cmdline_find_option_bool(boot_params.hdr.cmd_line_ptr, option);
+}
+
struct boot_params boot_params __attribute__((aligned(16)));

char *HEAP = _end;


2010-08-02 07:17:24

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 2/2] x86: more early console output from compressed/misc.c


will get

|Decompressing Linux... Parsing ELF... done.
|Booting the kernel.

in serial console.

reuse code from arch/x86/boot/
and we can use printf if needed

Signed-off-by: Yinghai Lu <[email protected]>

---
arch/x86/boot/compressed/misc.c | 60 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 59 insertions(+), 1 deletion(-)

Index: linux-2.6/arch/x86/boot/compressed/misc.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/compressed/misc.c
+++ linux-2.6/arch/x86/boot/compressed/misc.c
@@ -125,12 +125,14 @@ static void error(char *m);
*/
static 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)
+#define puts(__x) __putstr(0, __x)

#ifdef CONFIG_X86_64
#define memptr long
@@ -145,6 +147,9 @@ static char *vidmem;
static int vidport;
static int lines, cols;

+#include "../string.c"
+#include "../printf.c"
+
#ifdef CONFIG_KERNEL_GZIP
#include "../../../../lib/decompress_inflate.c"
#endif
@@ -161,6 +166,27 @@ static int lines, cols;
#include "../../../../lib/decompress_unlzo.c"
#endif

+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);
+}
+#include "../early_serial_console.c"
+
static void scroll(void)
{
int i;
@@ -170,6 +196,16 @@ static void scroll(void)
vidmem[i] = ' ';
}

+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);
+}
+
static void __putstr(int error, const char *s)
{
int x, y, pos;
@@ -179,6 +215,14 @@ static void __putstr(int error, const ch
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 +349,12 @@ asmlinkage void decompress_kernel(void *
{
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;
+
+ console_init();

if (real_mode->screen_info.orig_video_mode == 7) {
vidmem = (char *) 0xb0000;
@@ -322,6 +370,16 @@ asmlinkage void decompress_kernel(void *
free_mem_ptr = heap; /* Heap */
free_mem_end_ptr = heap + BOOT_HEAP_SIZE;

+ if (debug) {
+ putstr("decompress_kernel:\n");
+ printf(" input: [0x%lx-0x%lx], output: 0x%lx, heap: [0x%lx-0x%lx]\n",
+ (unsigned long)input_data,
+ (unsigned long)input_data + input_len - 1,
+ (unsigned long)output,
+ (unsigned long)heap,
+ (unsigned long)heap + BOOT_HEAP_SIZE - 1);
+ }
+
if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1))
error("Destination address inappropriately aligned");
#ifdef CONFIG_X86_64

2010-08-02 07:17:57

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH 1/2] x86, setup: reorgize the early_console_setup

On 08/02/2010 12:13 AM, Yinghai Lu wrote:
> also make main.c to include printf.c/string.c/cmdline.c

No. We don't include .c files that way.

-hpa

--
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel. I don't speak on their behalf.

2010-08-02 07:19:47

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH 1/2] x86, setup: reorgize the early_console_setup

On 08/02/2010 12:13 AM, Yinghai Lu wrote:
>
> Seperate early_console_setup from tty.c
> also make main.c to include printf.c/string.c/cmdline.c
>
> will reuse early_serial_console.c/string.c/printf.c/cmdline.c in compressed/misc.c
>


The way to reuse files in boot/compressed/ would be just to create .c
files in boot/compressed/ with, for example:

/* string.c */
#include "../string.c"

-hpa

--
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel. I don't speak on their behalf.

2010-08-02 08:25:54

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH -v2 1/2] x86, setup: reorgize the early_console_setup


Seperate early_serial_console from tty.c

will reuse early_serial_console.c/string.c/printf.c/cmdline.c in compressed/misc.c

-v2: according to hpa, don't include string.c etc.

Signed-off-by: Yinghai Lu <[email protected]>

---
arch/x86/boot/Makefile | 8 -
arch/x86/boot/boot.h | 35 ++++----
arch/x86/boot/cmdline.c | 6 -
arch/x86/boot/early_serial_console.c | 141 +++++++++++++++++++++++++++++++++++
arch/x86/boot/isdigit.h | 21 +++++
arch/x86/boot/printf.c | 4
arch/x86/boot/tty.c | 136 ---------------------------------
7 files changed, 187 insertions(+), 164 deletions(-)

Index: linux-2.6/arch/x86/boot/tty.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/tty.c
+++ linux-2.6/arch/x86/boot/tty.c
@@ -15,27 +15,10 @@

#include "boot.h"

-#define DEFAULT_SERIAL_PORT 0x3f8 /* ttyS0 */
-
-static int early_serial_base;
-
#define XMTRDY 0x20

-#define DLAB 0x80
-
#define TXR 0 /* Transmit register (WRITE) */
-#define RXR 0 /* Receive register (READ) */
-#define IER 1 /* Interrupt Enable */
-#define IIR 2 /* Interrupt ID */
-#define FCR 2 /* FIFO control */
-#define LCR 3 /* Line control */
-#define MCR 4 /* Modem control */
#define LSR 5 /* Line Status */
-#define MSR 6 /* Modem Status */
-#define DLL 0 /* Divisor Latch Low */
-#define DLH 1 /* Divisor latch High */
-
-#define DEFAULT_BAUD 9600

/*
* These functions are in .inittext so they can be used to signal
@@ -152,122 +135,3 @@ int getchar_timeout(void)
return 0; /* Timeout! */
}

-static void early_serial_init(int port, int baud)
-{
- unsigned char c;
- unsigned divisor;
-
- outb(0x3, port + LCR); /* 8n1 */
- outb(0, port + IER); /* no interrupt */
- outb(0, port + FCR); /* no fifo */
- outb(0x3, port + MCR); /* DTR + RTS */
-
- divisor = 115200 / baud;
- c = inb(port + LCR);
- outb(c | DLAB, port + LCR);
- outb(divisor & 0xff, port + DLL);
- outb((divisor >> 8) & 0xff, port + DLH);
- outb(c & ~DLAB, port + LCR);
-
- early_serial_base = port;
-
- printf("Early serial console at I/O port 0x%x baud: %d\n", port, baud);
-}
-
-static void parse_earlyprintk(void)
-{
- int baud = DEFAULT_BAUD;
- char arg[32];
- int pos = 0;
- int port = 0;
-
- if (cmdline_find_option("earlyprintk", arg, sizeof arg) > 0) {
- char *e;
-
- if (!strncmp(arg, "serial", 6)) {
- port = DEFAULT_SERIAL_PORT;
- pos += 6;
- }
-
- if (arg[pos] == ',')
- pos++;
-
- if (!strncmp(arg, "ttyS", 4)) {
- static const int bases[] = { 0x3f8, 0x2f8 };
- int idx = 0;
-
- if (!strncmp(arg + pos, "ttyS", 4))
- pos += 4;
-
- if (arg[pos++] == '1')
- idx = 1;
-
- port = bases[idx];
- }
-
- if (arg[pos] == ',')
- pos++;
-
- baud = simple_strtoull(arg + pos, &e, 0);
- if (baud == 0 || arg + pos == e)
- baud = DEFAULT_BAUD;
- }
-
- if (port)
- early_serial_init(port, baud);
-}
-
-#define BASE_BAUD (1843200/16)
-static unsigned int probe_baud(int port)
-{
- unsigned char lcr, dll, dlh;
- unsigned int quot;
-
- lcr = inb(port + LCR);
- outb(lcr | DLAB, port + LCR);
- dll = inb(port + DLL);
- dlh = inb(port + DLH);
- outb(lcr, port + LCR);
- quot = (dlh << 8) | dll;
-
- return BASE_BAUD / quot;
-}
-
-static void parse_console_uart8250(void)
-{
- char optstr[64], *options;
- int baud = DEFAULT_BAUD;
- int port = 0;
-
- /*
- * console=uart8250,io,0x3f8,115200n8
- * need to make sure it is last one console !
- */
- if (cmdline_find_option("console", optstr, sizeof optstr) <= 0)
- return;
-
- options = optstr;
-
- if (!strncmp(options, "uart8250,io,", 12))
- port = simple_strtoull(options + 12, &options, 0);
- else if (!strncmp(options, "uart,io,", 8))
- port = simple_strtoull(options + 8, &options, 0);
- else
- return;
-
- if (options && (options[0] == ','))
- baud = simple_strtoull(options + 1, &options, 0);
- else
- baud = probe_baud(port);
-
- if (port)
- early_serial_init(port, baud);
-}
-
-void console_init(void)
-{
- parse_earlyprintk();
-
- if (!early_serial_base)
- parse_console_uart8250();
-}
Index: linux-2.6/arch/x86/boot/early_serial_console.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/early_serial_console.c
@@ -0,0 +1,141 @@
+#include "boot.h"
+
+int early_serial_base;
+
+#define DEFAULT_SERIAL_PORT 0x3f8 /* ttyS0 */
+
+#define XMTRDY 0x20
+
+#define DLAB 0x80
+
+#define TXR 0 /* Transmit register (WRITE) */
+#define RXR 0 /* Receive register (READ) */
+#define IER 1 /* Interrupt Enable */
+#define IIR 2 /* Interrupt ID */
+#define FCR 2 /* FIFO control */
+#define LCR 3 /* Line control */
+#define MCR 4 /* Modem control */
+#define LSR 5 /* Line Status */
+#define MSR 6 /* Modem Status */
+#define DLL 0 /* Divisor Latch Low */
+#define DLH 1 /* Divisor latch High */
+
+#define DEFAULT_BAUD 9600
+
+static void early_serial_init(int port, int baud)
+{
+ unsigned char c;
+ unsigned divisor;
+
+ outb(0x3, port + LCR); /* 8n1 */
+ outb(0, port + IER); /* no interrupt */
+ outb(0, port + FCR); /* no fifo */
+ outb(0x3, port + MCR); /* DTR + RTS */
+
+ divisor = 115200 / baud;
+ c = inb(port + LCR);
+ outb(c | DLAB, port + LCR);
+ outb(divisor & 0xff, port + DLL);
+ outb((divisor >> 8) & 0xff, port + DLH);
+ outb(c & ~DLAB, port + LCR);
+
+ early_serial_base = port;
+}
+
+static void parse_earlyprintk(void)
+{
+ int baud = DEFAULT_BAUD;
+ char arg[32];
+ int pos = 0;
+ int port = 0;
+
+ if (cmdline_find_option("earlyprintk", arg, sizeof arg) > 0) {
+ char *e;
+
+ if (!strncmp(arg, "serial", 6)) {
+ port = DEFAULT_SERIAL_PORT;
+ pos += 6;
+ }
+
+ if (arg[pos] == ',')
+ pos++;
+
+ if (!strncmp(arg, "ttyS", 4)) {
+ static const int bases[] = { 0x3f8, 0x2f8 };
+ int idx = 0;
+
+ if (!strncmp(arg + pos, "ttyS", 4))
+ pos += 4;
+
+ if (arg[pos++] == '1')
+ idx = 1;
+
+ port = bases[idx];
+ }
+
+ if (arg[pos] == ',')
+ pos++;
+
+ baud = simple_strtoull(arg + pos, &e, 0);
+ if (baud == 0 || arg + pos == e)
+ baud = DEFAULT_BAUD;
+ }
+
+ if (port)
+ early_serial_init(port, baud);
+}
+
+#define BASE_BAUD (1843200/16)
+static unsigned int probe_baud(int port)
+{
+ unsigned char lcr, dll, dlh;
+ unsigned int quot;
+
+ lcr = inb(port + LCR);
+ outb(lcr | DLAB, port + LCR);
+ dll = inb(port + DLL);
+ dlh = inb(port + DLH);
+ outb(lcr, port + LCR);
+ quot = (dlh << 8) | dll;
+
+ return BASE_BAUD / quot;
+}
+
+static void parse_console_uart8250(void)
+{
+ char optstr[64], *options;
+ int baud = DEFAULT_BAUD;
+ int port = 0;
+
+ /*
+ * console=uart8250,io,0x3f8,115200n8
+ * need to make sure it is last one console !
+ */
+ if (cmdline_find_option("console", optstr, sizeof optstr) <= 0)
+ return;
+
+ options = optstr;
+
+ if (!strncmp(options, "uart8250,io,", 12))
+ port = simple_strtoull(options + 12, &options, 0);
+ else if (!strncmp(options, "uart,io,", 8))
+ port = simple_strtoull(options + 8, &options, 0);
+ else
+ return;
+
+ if (options && (options[0] == ','))
+ baud = simple_strtoull(options + 1, &options, 0);
+ else
+ baud = probe_baud(port);
+
+ if (port)
+ early_serial_init(port, baud);
+}
+
+void console_init(void)
+{
+ parse_earlyprintk();
+
+ if (!early_serial_base)
+ parse_console_uart8250();
+}
Index: linux-2.6/arch/x86/boot/printf.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/printf.c
+++ linux-2.6/arch/x86/boot/printf.c
@@ -34,7 +34,7 @@ static int skip_atoi(const char **s)
#define SMALL 32 /* Must be 32 == 0x20 */
#define SPECIAL 64 /* 0x */

-#define do_div(n,base) ({ \
+#define __do_div(n, base) ({ \
int __res; \
__res = ((unsigned long) n) % (unsigned) base; \
n = ((unsigned long) n) / (unsigned) base; \
@@ -83,7 +83,7 @@ static char *number(char *str, long num,
tmp[i++] = '0';
else
while (num != 0)
- tmp[i++] = (digits[do_div(num, base)] | locase);
+ tmp[i++] = (digits[__do_div(num, base)] | locase);
if (i > precision)
precision = i;
size -= precision;
Index: linux-2.6/arch/x86/boot/cmdline.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/cmdline.c
+++ linux-2.6/arch/x86/boot/cmdline.c
@@ -27,9 +27,8 @@ static inline int myisspace(u8 c)
* Returns the length of the argument (regardless of if it was
* truncated to fit in the buffer), or -1 on not found.
*/
-int cmdline_find_option(const char *option, char *buffer, int bufsize)
+int __cmdline_find_option(u32 cmdline_ptr, const char *option, char *buffer, int bufsize)
{
- u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
addr_t cptr;
char c;
int len = -1;
@@ -100,9 +99,8 @@ int cmdline_find_option(const char *opti
* Returns the position of that option (starts counting with 1)
* or 0 on not found
*/
-int cmdline_find_option_bool(const char *option)
+int __cmdline_find_option_bool(u32 cmdline_ptr, const char *option)
{
- u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
addr_t cptr;
char c;
int pos = 0, wstart = 0;
Index: linux-2.6/arch/x86/boot/Makefile
===================================================================
--- linux-2.6.orig/arch/x86/boot/Makefile
+++ linux-2.6/arch/x86/boot/Makefile
@@ -26,10 +26,10 @@ targets := vmlinux.bin setup.bin setup.
targets += fdimage fdimage144 fdimage288 image.iso mtools.conf
subdir- := compressed

-setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o edd.o
-setup-y += header.o main.o mca.o memory.o pm.o pmjump.o
-setup-y += printf.o regs.o string.o tty.o video.o video-mode.o
-setup-y += version.o
+setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o
+setup-y += early_serial_console.o edd.o header.o main.o mca.o memory.o
+setup-y += pm.o pmjump.o printf.o regs.o string.o tty.o video.o
+setup-y += video-mode.o version.o
setup-$(CONFIG_X86_APM_BOOT) += apm.o

# The link order of the video-*.o modules can matter. In particular,
Index: linux-2.6/arch/x86/boot/boot.h
===================================================================
--- linux-2.6.orig/arch/x86/boot/boot.h
+++ linux-2.6/arch/x86/boot/boot.h
@@ -200,21 +200,7 @@ static inline int memcmp_gs(const void *
return diff;
}

-static inline int isdigit(int ch)
-{
- return (ch >= '0') && (ch <= '9');
-}
-
-static inline int isxdigit(int ch)
-{
- if (isdigit(ch))
- return true;
-
- if ((ch >= 'a') && (ch <= 'f'))
- return true;
-
- return (ch >= 'A') && (ch <= 'F');
-}
+#include "isdigit.h"

/* Heap -- available for dynamic lists. */
extern char _end[];
@@ -300,8 +286,18 @@ struct biosregs {
void intcall(u8 int_no, const struct biosregs *ireg, struct biosregs *oreg);

/* cmdline.c */
-int cmdline_find_option(const char *option, char *buffer, int bufsize);
-int cmdline_find_option_bool(const char *option);
+int __cmdline_find_option(u32 cmdline_ptr, const char *option, char *buffer, int bufsize);
+int __cmdline_find_option_bool(u32 cmdline_ptr, const char *option);
+static inline int cmdline_find_option(const char *option, char *buffer, int bufsize)
+{
+ return __cmdline_find_option(boot_params.hdr.cmd_line_ptr, option, buffer, bufsize);
+}
+
+static inline int cmdline_find_option_bool(const char *option)
+{
+ return __cmdline_find_option_bool(boot_params.hdr.cmd_line_ptr, option);
+}
+

/* cpu.c, cpucheck.c */
struct cpu_features {
@@ -313,6 +309,10 @@ extern struct cpu_features cpu;
int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
int validate_cpu(void);

+/* early_serial_console.c */
+extern int early_serial_base;
+void console_init(void);
+
/* edd.c */
void query_edd(void);

@@ -348,7 +348,6 @@ unsigned int atou(const char *s);
unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base);

/* tty.c */
-void console_init(void);
void puts(const char *);
void putchar(int);
int getchar(void);
Index: linux-2.6/arch/x86/boot/isdigit.h
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/isdigit.h
@@ -0,0 +1,21 @@
+#ifndef BOOT_ISDIGIT_H
+
+#define BOOT_ISDIGIT_H
+
+static inline int isdigit(int ch)
+{
+ return (ch >= '0') && (ch <= '9');
+}
+
+static inline int isxdigit(int ch)
+{
+ if (isdigit(ch))
+ return true;
+
+ if ((ch >= 'a') && (ch <= 'f'))
+ return true;
+
+ return (ch >= 'A') && (ch <= 'F');
+}
+
+#endif

2010-08-02 08:27:38

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH -v2 2/2] x86: more early console output from compressed/misc.c


will get

|Decompressing Linux... Parsing ELF... done.
|Booting the kernel.

in serial console.

reuse code from arch/x86/boot/
and we can use printf if needed

-v2: define BOOT_BOOT_H to avoid include boot.h

Signed-off-by: Yinghai Lu <[email protected]>

---
arch/x86/boot/compressed/misc.c | 62 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 61 insertions(+), 1 deletion(-)

Index: linux-2.6/arch/x86/boot/compressed/misc.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/compressed/misc.c
+++ linux-2.6/arch/x86/boot/compressed/misc.c
@@ -125,12 +125,14 @@ static void error(char *m);
*/
static 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)
+#define puts(__x) __putstr(0, __x)

#ifdef CONFIG_X86_64
#define memptr long
@@ -145,6 +147,11 @@ static char *vidmem;
static int vidport;
static int lines, cols;

+#define BOOT_BOOT_H
+#include "../isdigit.h"
+#include "../string.c"
+#include "../printf.c"
+
#ifdef CONFIG_KERNEL_GZIP
#include "../../../../lib/decompress_inflate.c"
#endif
@@ -161,6 +168,27 @@ static int lines, cols;
#include "../../../../lib/decompress_unlzo.c"
#endif

+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);
+}
+#include "../early_serial_console.c"
+
static void scroll(void)
{
int i;
@@ -170,6 +198,16 @@ static void scroll(void)
vidmem[i] = ' ';
}

+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);
+}
+
static void __putstr(int error, const char *s)
{
int x, y, pos;
@@ -179,6 +217,14 @@ static void __putstr(int error, const ch
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 +351,12 @@ asmlinkage void decompress_kernel(void *
{
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;
+
+ console_init();

if (real_mode->screen_info.orig_video_mode == 7) {
vidmem = (char *) 0xb0000;
@@ -322,6 +372,16 @@ asmlinkage void decompress_kernel(void *
free_mem_ptr = heap; /* Heap */
free_mem_end_ptr = heap + BOOT_HEAP_SIZE;

+ if (debug) {
+ putstr("decompress_kernel:\n");
+ printf(" input: [0x%lx-0x%lx], output: 0x%lx, heap: [0x%lx-0x%lx]\n",
+ (unsigned long)input_data,
+ (unsigned long)input_data + input_len - 1,
+ (unsigned long)output,
+ (unsigned long)heap,
+ (unsigned long)heap + BOOT_HEAP_SIZE - 1);
+ }
+
if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1))
error("Destination address inappropriately aligned");
#ifdef CONFIG_X86_64

2010-08-02 09:18:33

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH -v3 1/2] x86, setup: reorgize the early_console_setup



Seperate early_serial_console from tty.c

will reuse early_serial_console.c/string.c/printf.c/cmdline.c in compressed/misc.c

-v2: according to hpa, don't include string.c etc
-v3: compressed/misc.c must have early_serial_base as static, so move it back to tty.c
for setup code

Signed-off-by: Yinghai Lu <[email protected]>

---
arch/x86/boot/Makefile | 8 +-
arch/x86/boot/boot.h | 35 ++++----
arch/x86/boot/cmdline.c | 6 -
arch/x86/boot/early_serial_console.c | 139 +++++++++++++++++++++++++++++++++++
arch/x86/boot/isdigit.h | 21 +++++
arch/x86/boot/printf.c | 4 -
arch/x86/boot/tty.c | 136 ----------------------------------
7 files changed, 186 insertions(+), 163 deletions(-)

Index: linux-2.6/arch/x86/boot/tty.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/tty.c
+++ linux-2.6/arch/x86/boot/tty.c
@@ -15,27 +15,12 @@

#include "boot.h"

-#define DEFAULT_SERIAL_PORT 0x3f8 /* ttyS0 */
-
-static int early_serial_base;
+int early_serial_base;

#define XMTRDY 0x20

-#define DLAB 0x80
-
#define TXR 0 /* Transmit register (WRITE) */
-#define RXR 0 /* Receive register (READ) */
-#define IER 1 /* Interrupt Enable */
-#define IIR 2 /* Interrupt ID */
-#define FCR 2 /* FIFO control */
-#define LCR 3 /* Line control */
-#define MCR 4 /* Modem control */
#define LSR 5 /* Line Status */
-#define MSR 6 /* Modem Status */
-#define DLL 0 /* Divisor Latch Low */
-#define DLH 1 /* Divisor latch High */
-
-#define DEFAULT_BAUD 9600

/*
* These functions are in .inittext so they can be used to signal
@@ -152,122 +137,3 @@ int getchar_timeout(void)
return 0; /* Timeout! */
}

-static void early_serial_init(int port, int baud)
-{
- unsigned char c;
- unsigned divisor;
-
- outb(0x3, port + LCR); /* 8n1 */
- outb(0, port + IER); /* no interrupt */
- outb(0, port + FCR); /* no fifo */
- outb(0x3, port + MCR); /* DTR + RTS */
-
- divisor = 115200 / baud;
- c = inb(port + LCR);
- outb(c | DLAB, port + LCR);
- outb(divisor & 0xff, port + DLL);
- outb((divisor >> 8) & 0xff, port + DLH);
- outb(c & ~DLAB, port + LCR);
-
- early_serial_base = port;
-
- printf("Early serial console at I/O port 0x%x baud: %d\n", port, baud);
-}
-
-static void parse_earlyprintk(void)
-{
- int baud = DEFAULT_BAUD;
- char arg[32];
- int pos = 0;
- int port = 0;
-
- if (cmdline_find_option("earlyprintk", arg, sizeof arg) > 0) {
- char *e;
-
- if (!strncmp(arg, "serial", 6)) {
- port = DEFAULT_SERIAL_PORT;
- pos += 6;
- }
-
- if (arg[pos] == ',')
- pos++;
-
- if (!strncmp(arg, "ttyS", 4)) {
- static const int bases[] = { 0x3f8, 0x2f8 };
- int idx = 0;
-
- if (!strncmp(arg + pos, "ttyS", 4))
- pos += 4;
-
- if (arg[pos++] == '1')
- idx = 1;
-
- port = bases[idx];
- }
-
- if (arg[pos] == ',')
- pos++;
-
- baud = simple_strtoull(arg + pos, &e, 0);
- if (baud == 0 || arg + pos == e)
- baud = DEFAULT_BAUD;
- }
-
- if (port)
- early_serial_init(port, baud);
-}
-
-#define BASE_BAUD (1843200/16)
-static unsigned int probe_baud(int port)
-{
- unsigned char lcr, dll, dlh;
- unsigned int quot;
-
- lcr = inb(port + LCR);
- outb(lcr | DLAB, port + LCR);
- dll = inb(port + DLL);
- dlh = inb(port + DLH);
- outb(lcr, port + LCR);
- quot = (dlh << 8) | dll;
-
- return BASE_BAUD / quot;
-}
-
-static void parse_console_uart8250(void)
-{
- char optstr[64], *options;
- int baud = DEFAULT_BAUD;
- int port = 0;
-
- /*
- * console=uart8250,io,0x3f8,115200n8
- * need to make sure it is last one console !
- */
- if (cmdline_find_option("console", optstr, sizeof optstr) <= 0)
- return;
-
- options = optstr;
-
- if (!strncmp(options, "uart8250,io,", 12))
- port = simple_strtoull(options + 12, &options, 0);
- else if (!strncmp(options, "uart,io,", 8))
- port = simple_strtoull(options + 8, &options, 0);
- else
- return;
-
- if (options && (options[0] == ','))
- baud = simple_strtoull(options + 1, &options, 0);
- else
- baud = probe_baud(port);
-
- if (port)
- early_serial_init(port, baud);
-}
-
-void console_init(void)
-{
- parse_earlyprintk();
-
- if (!early_serial_base)
- parse_console_uart8250();
-}
Index: linux-2.6/arch/x86/boot/early_serial_console.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/early_serial_console.c
@@ -0,0 +1,139 @@
+#include "boot.h"
+
+#define DEFAULT_SERIAL_PORT 0x3f8 /* ttyS0 */
+
+#define XMTRDY 0x20
+
+#define DLAB 0x80
+
+#define TXR 0 /* Transmit register (WRITE) */
+#define RXR 0 /* Receive register (READ) */
+#define IER 1 /* Interrupt Enable */
+#define IIR 2 /* Interrupt ID */
+#define FCR 2 /* FIFO control */
+#define LCR 3 /* Line control */
+#define MCR 4 /* Modem control */
+#define LSR 5 /* Line Status */
+#define MSR 6 /* Modem Status */
+#define DLL 0 /* Divisor Latch Low */
+#define DLH 1 /* Divisor latch High */
+
+#define DEFAULT_BAUD 9600
+
+static void early_serial_init(int port, int baud)
+{
+ unsigned char c;
+ unsigned divisor;
+
+ outb(0x3, port + LCR); /* 8n1 */
+ outb(0, port + IER); /* no interrupt */
+ outb(0, port + FCR); /* no fifo */
+ outb(0x3, port + MCR); /* DTR + RTS */
+
+ divisor = 115200 / baud;
+ c = inb(port + LCR);
+ outb(c | DLAB, port + LCR);
+ outb(divisor & 0xff, port + DLL);
+ outb((divisor >> 8) & 0xff, port + DLH);
+ outb(c & ~DLAB, port + LCR);
+
+ early_serial_base = port;
+}
+
+static void parse_earlyprintk(void)
+{
+ int baud = DEFAULT_BAUD;
+ char arg[32];
+ int pos = 0;
+ int port = 0;
+
+ if (cmdline_find_option("earlyprintk", arg, sizeof arg) > 0) {
+ char *e;
+
+ if (!strncmp(arg, "serial", 6)) {
+ port = DEFAULT_SERIAL_PORT;
+ pos += 6;
+ }
+
+ if (arg[pos] == ',')
+ pos++;
+
+ if (!strncmp(arg, "ttyS", 4)) {
+ static const int bases[] = { 0x3f8, 0x2f8 };
+ int idx = 0;
+
+ if (!strncmp(arg + pos, "ttyS", 4))
+ pos += 4;
+
+ if (arg[pos++] == '1')
+ idx = 1;
+
+ port = bases[idx];
+ }
+
+ if (arg[pos] == ',')
+ pos++;
+
+ baud = simple_strtoull(arg + pos, &e, 0);
+ if (baud == 0 || arg + pos == e)
+ baud = DEFAULT_BAUD;
+ }
+
+ if (port)
+ early_serial_init(port, baud);
+}
+
+#define BASE_BAUD (1843200/16)
+static unsigned int probe_baud(int port)
+{
+ unsigned char lcr, dll, dlh;
+ unsigned int quot;
+
+ lcr = inb(port + LCR);
+ outb(lcr | DLAB, port + LCR);
+ dll = inb(port + DLL);
+ dlh = inb(port + DLH);
+ outb(lcr, port + LCR);
+ quot = (dlh << 8) | dll;
+
+ return BASE_BAUD / quot;
+}
+
+static void parse_console_uart8250(void)
+{
+ char optstr[64], *options;
+ int baud = DEFAULT_BAUD;
+ int port = 0;
+
+ /*
+ * console=uart8250,io,0x3f8,115200n8
+ * need to make sure it is last one console !
+ */
+ if (cmdline_find_option("console", optstr, sizeof optstr) <= 0)
+ return;
+
+ options = optstr;
+
+ if (!strncmp(options, "uart8250,io,", 12))
+ port = simple_strtoull(options + 12, &options, 0);
+ else if (!strncmp(options, "uart,io,", 8))
+ port = simple_strtoull(options + 8, &options, 0);
+ else
+ return;
+
+ if (options && (options[0] == ','))
+ baud = simple_strtoull(options + 1, &options, 0);
+ else
+ baud = probe_baud(port);
+
+ if (port)
+ early_serial_init(port, baud);
+}
+
+void console_init(void)
+{
+ parse_earlyprintk();
+
+ if (!early_serial_base)
+ parse_console_uart8250();
+}
Index: linux-2.6/arch/x86/boot/printf.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/printf.c
+++ linux-2.6/arch/x86/boot/printf.c
@@ -34,7 +34,7 @@ static int skip_atoi(const char **s)
#define SMALL 32 /* Must be 32 == 0x20 */
#define SPECIAL 64 /* 0x */

-#define do_div(n,base) ({ \
+#define __do_div(n, base) ({ \
int __res; \
__res = ((unsigned long) n) % (unsigned) base; \
n = ((unsigned long) n) / (unsigned) base; \
@@ -83,7 +83,7 @@ static char *number(char *str, long num,
tmp[i++] = '0';
else
while (num != 0)
- tmp[i++] = (digits[do_div(num, base)] | locase);
+ tmp[i++] = (digits[__do_div(num, base)] | locase);
if (i > precision)
precision = i;
size -= precision;
Index: linux-2.6/arch/x86/boot/cmdline.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/cmdline.c
+++ linux-2.6/arch/x86/boot/cmdline.c
@@ -27,9 +27,8 @@ static inline int myisspace(u8 c)
* Returns the length of the argument (regardless of if it was
* truncated to fit in the buffer), or -1 on not found.
*/
-int cmdline_find_option(const char *option, char *buffer, int bufsize)
+int __cmdline_find_option(u32 cmdline_ptr, const char *option, char *buffer, int bufsize)
{
- u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
addr_t cptr;
char c;
int len = -1;
@@ -100,9 +99,8 @@ int cmdline_find_option(const char *opti
* Returns the position of that option (starts counting with 1)
* or 0 on not found
*/
-int cmdline_find_option_bool(const char *option)
+int __cmdline_find_option_bool(u32 cmdline_ptr, const char *option)
{
- u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
addr_t cptr;
char c;
int pos = 0, wstart = 0;
Index: linux-2.6/arch/x86/boot/Makefile
===================================================================
--- linux-2.6.orig/arch/x86/boot/Makefile
+++ linux-2.6/arch/x86/boot/Makefile
@@ -26,10 +26,10 @@ targets := vmlinux.bin setup.bin setup.
targets += fdimage fdimage144 fdimage288 image.iso mtools.conf
subdir- := compressed

-setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o edd.o
-setup-y += header.o main.o mca.o memory.o pm.o pmjump.o
-setup-y += printf.o regs.o string.o tty.o video.o video-mode.o
-setup-y += version.o
+setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o
+setup-y += early_serial_console.o edd.o header.o main.o mca.o memory.o
+setup-y += pm.o pmjump.o printf.o regs.o string.o tty.o video.o
+setup-y += video-mode.o version.o
setup-$(CONFIG_X86_APM_BOOT) += apm.o

# The link order of the video-*.o modules can matter. In particular,
Index: linux-2.6/arch/x86/boot/boot.h
===================================================================
--- linux-2.6.orig/arch/x86/boot/boot.h
+++ linux-2.6/arch/x86/boot/boot.h
@@ -200,21 +200,7 @@ static inline int memcmp_gs(const void *
return diff;
}

-static inline int isdigit(int ch)
-{
- return (ch >= '0') && (ch <= '9');
-}
-
-static inline int isxdigit(int ch)
-{
- if (isdigit(ch))
- return true;
-
- if ((ch >= 'a') && (ch <= 'f'))
- return true;
-
- return (ch >= 'A') && (ch <= 'F');
-}
+#include "isdigit.h"

/* Heap -- available for dynamic lists. */
extern char _end[];
@@ -300,8 +286,18 @@ struct biosregs {
void intcall(u8 int_no, const struct biosregs *ireg, struct biosregs *oreg);

/* cmdline.c */
-int cmdline_find_option(const char *option, char *buffer, int bufsize);
-int cmdline_find_option_bool(const char *option);
+int __cmdline_find_option(u32 cmdline_ptr, const char *option, char *buffer, int bufsize);
+int __cmdline_find_option_bool(u32 cmdline_ptr, const char *option);
+static inline int cmdline_find_option(const char *option, char *buffer, int bufsize)
+{
+ return __cmdline_find_option(boot_params.hdr.cmd_line_ptr, option, buffer, bufsize);
+}
+
+static inline int cmdline_find_option_bool(const char *option)
+{
+ return __cmdline_find_option_bool(boot_params.hdr.cmd_line_ptr, option);
+}
+

/* cpu.c, cpucheck.c */
struct cpu_features {
@@ -313,6 +309,10 @@ extern struct cpu_features cpu;
int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
int validate_cpu(void);

+/* early_serial_console.c */
+extern int early_serial_base;
+void console_init(void);
+
/* edd.c */
void query_edd(void);

@@ -348,7 +348,6 @@ unsigned int atou(const char *s);
unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base);

/* tty.c */
-void console_init(void);
void puts(const char *);
void putchar(int);
int getchar(void);
Index: linux-2.6/arch/x86/boot/isdigit.h
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/isdigit.h
@@ -0,0 +1,21 @@
+#ifndef BOOT_ISDIGIT_H
+
+#define BOOT_ISDIGIT_H
+
+static inline int isdigit(int ch)
+{
+ return (ch >= '0') && (ch <= '9');
+}
+
+static inline int isxdigit(int ch)
+{
+ if (isdigit(ch))
+ return true;
+
+ if ((ch >= 'a') && (ch <= 'f'))
+ return true;
+
+ return (ch >= 'A') && (ch <= 'F');
+}
+
+#endif

2010-08-02 09:19:57

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c


will get

|Decompressing Linux... Parsing ELF... done.
|Booting the kernel.

in serial console.

reuse code from arch/x86/boot/
and we can use printf if needed

-v2: define BOOT_BOOT_H to avoid include boot.h
-v3: early_serial_base need to be static in misc.c ?

Signed-off-by: Yinghai Lu <[email protected]>

---
arch/x86/boot/compressed/misc.c | 65 +++++++++++++++++++++++++++++++++++++++-
arch/x86/boot/main.c | 6 +--
2 files changed, 66 insertions(+), 5 deletions(-)

Index: linux-2.6/arch/x86/boot/compressed/misc.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/compressed/misc.c
+++ linux-2.6/arch/x86/boot/compressed/misc.c
@@ -125,12 +125,14 @@ static void error(char *m);
*/
static 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)
+#define puts(__x) __putstr(0, __x)

#ifdef CONFIG_X86_64
#define memptr long
@@ -145,6 +147,11 @@ static char *vidmem;
static int vidport;
static int lines, cols;

+#define BOOT_BOOT_H
+#include "../isdigit.h"
+#include "../string.c"
+#include "../printf.c"
+
#ifdef CONFIG_KERNEL_GZIP
#include "../../../../lib/decompress_inflate.c"
#endif
@@ -161,6 +168,28 @@ static int lines, cols;
#include "../../../../lib/decompress_unlzo.c"
#endif

+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"
+static inline int cmdline_find_option(const char *option, char *buffer, int bufsize)
+{
+ return __cmdline_find_option(real_mode->hdr.cmd_line_ptr, option, buffer, bufsize);
+}
+static inline int cmdline_find_option_bool(const char *option)
+{
+ return __cmdline_find_option_bool(real_mode->hdr.cmd_line_ptr, option);
+}
+static int early_serial_base;
+#include "../early_serial_console.c"
+
static void scroll(void)
{
int i;
@@ -170,6 +199,16 @@ static void scroll(void)
vidmem[i] = ' ';
}

+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);
+}
+
static void __putstr(int error, const char *s)
{
int x, y, pos;
@@ -179,6 +218,14 @@ static void __putstr(int error, const ch
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 +352,10 @@ asmlinkage void decompress_kernel(void *
{
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,9 +368,23 @@ asmlinkage void decompress_kernel(void *
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;

+ if (debug) {
+ putstr("decompress_kernel:\n");
+ printf(" input: [0x%lx-0x%lx], output: 0x%lx, heap: [0x%lx-0x%lx]\n",
+ (unsigned long)input_data,
+ (unsigned long)input_data + input_len - 1,
+ (unsigned long)output,
+ (unsigned long)heap,
+ (unsigned long)heap + BOOT_HEAP_SIZE - 1);
+ }
+
if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1))
error("Destination address inappropriately aligned");
#ifdef CONFIG_X86_64
Index: linux-2.6/arch/x86/boot/main.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/main.c
+++ linux-2.6/arch/x86/boot/main.c
@@ -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();
}

2010-08-02 15:10:34

by Cyrill Gorcunov

[permalink] [raw]
Subject: Re: [PATCH 1/2] x86, setup: reorgize the early_console_setup

On Mon, Aug 02, 2010 at 12:13:31AM -0700, Yinghai Lu wrote:
>
> Seperate early_console_setup from tty.c
> also make main.c to include printf.c/string.c/cmdline.c
>
> will reuse early_serial_console.c/string.c/printf.c/cmdline.c in compressed/misc.c
>
> Signed-off-by: Yinghai Lu <[email protected]>
>
> ---

Hi Yinghai, I'll try to find some time for review though it looks somehow
too 'big' for me :)

Actually by reading your initial approach (which was much smaller in size) I
thought we end up in something like the patch below, though I'll review this
seris. So just to share (I've tested it under qemu). The idea is the same as
your was, so I pushed all constant parts into header and use it when needed
passing serial line base port via boot_params.

---
arch/x86/boot/boot.h | 2 -
arch/x86/boot/compressed/misc.c | 18 +++++++++++++
arch/x86/boot/main.c | 2 -
arch/x86/boot/tty.c | 51 ++++++++++-----------------------------
arch/x86/boot/tty.h | 45 ++++++++++++++++++++++++++++++++++
arch/x86/include/asm/bootparam.h | 2 -
arch/x86/kernel/early_printk.c | 36 +++------------------------
7 files changed, 85 insertions(+), 71 deletions(-)

Index: linux-2.6.git/arch/x86/boot/boot.h
=====================================================================
--- linux-2.6.git.orig/arch/x86/boot/boot.h
+++ linux-2.6.git/arch/x86/boot/boot.h
@@ -348,7 +348,7 @@ unsigned int atou(const char *s);
unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base);

/* tty.c */
-void console_init(void);
+void console_init(struct boot_params *boot_params);
void puts(const char *);
void putchar(int);
int getchar(void);
Index: linux-2.6.git/arch/x86/boot/compressed/misc.c
=====================================================================
--- linux-2.6.git.orig/arch/x86/boot/compressed/misc.c
+++ linux-2.6.git/arch/x86/boot/compressed/misc.c
@@ -27,6 +27,8 @@
#include <asm/boot.h>
#include <asm/bootparam.h>

+#include "../tty.h"
+
/* WARNING!!
* This code is compiled with -fPIC and it is relocated dynamically
* at run time, but no relocation processing is performed.
@@ -180,6 +182,21 @@ static void __putstr(int error, const ch
return;
#endif

+ /*
+ * write to early serial console first
+ * then we may write to video memory
+ */
+ if (real_mode->early_serial_base) {
+ int ch, base = real_mode->early_serial_base;
+ const char *str = s;
+ while ((ch = *str++)) {
+ /* \n -> \r\n */
+ if (ch == '\n')
+ __serial_putchar('\r', base);
+ __serial_putchar(ch, base);
+ }
+ }
+
if (real_mode->screen_info.orig_video_mode == 0 &&
lines == 0 && cols == 0)
return;
@@ -342,5 +359,6 @@ asmlinkage void decompress_kernel(void *
parse_elf(output);
if (!quiet)
putstr("done.\nBooting the kernel.\n");
+
return;
}
Index: linux-2.6.git/arch/x86/boot/main.c
=====================================================================
--- linux-2.6.git.orig/arch/x86/boot/main.c
+++ linux-2.6.git/arch/x86/boot/main.c
@@ -131,7 +131,7 @@ void main(void)
copy_boot_params();

/* Initialize the early-boot console */
- console_init();
+ console_init(&boot_params);

/* End of heap check */
init_heap();
Index: linux-2.6.git/arch/x86/boot/tty.c
=====================================================================
--- linux-2.6.git.orig/arch/x86/boot/tty.c
+++ linux-2.6.git/arch/x86/boot/tty.c
@@ -14,44 +14,15 @@
*/

#include "boot.h"
+#include "tty.h"

-#define DEFAULT_SERIAL_PORT 0x3f8 /* ttyS0 */
-
-static int early_serial_base;
-
-#define XMTRDY 0x20
-
-#define DLAB 0x80
-
-#define TXR 0 /* Transmit register (WRITE) */
-#define RXR 0 /* Receive register (READ) */
-#define IER 1 /* Interrupt Enable */
-#define IIR 2 /* Interrupt ID */
-#define FCR 2 /* FIFO control */
-#define LCR 3 /* Line control */
-#define MCR 4 /* Modem control */
-#define LSR 5 /* Line Status */
-#define MSR 6 /* Modem Status */
-#define DLL 0 /* Divisor Latch Low */
-#define DLH 1 /* Divisor latch High */
-
-#define DEFAULT_BAUD 9600
+static int early_serial_base;

/*
* These functions are in .inittext so they can be used to signal
* error during initialization.
*/

-static void __attribute__((section(".inittext"))) serial_putchar(int ch)
-{
- unsigned timeout = 0xffff;
-
- while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
- cpu_relax();
-
- outb(ch, early_serial_base + TXR);
-}
-
static void __attribute__((section(".inittext"))) bios_putchar(int ch)
{
struct biosregs ireg;
@@ -66,13 +37,14 @@ static void __attribute__((section(".ini

void __attribute__((section(".inittext"))) putchar(int ch)
{
+ /* \n -> \r\n */
if (ch == '\n')
- putchar('\r'); /* \n -> \r\n */
+ putchar('\r');

bios_putchar(ch);

- if (early_serial_base != 0)
- serial_putchar(ch);
+ if (early_serial_base)
+ __serial_putchar(ch, early_serial_base);
}

void __attribute__((section(".inittext"))) puts(const char *str)
@@ -193,7 +165,10 @@ static void parse_earlyprintk(void)
pos++;

if (!strncmp(arg, "ttyS", 4)) {
- static const int bases[] = { 0x3f8, 0x2f8 };
+ static const int bases[] = {
+ SERIAL_PORT_TTYS0,
+ SERIAL_PORT_TTYS1,
+ };
int idx = 0;

if (!strncmp(arg + pos, "ttyS", 4))
@@ -217,7 +192,6 @@ static void parse_earlyprintk(void)
early_serial_init(port, baud);
}

-#define BASE_BAUD (1843200/16)
static unsigned int probe_baud(int port)
{
unsigned char lcr, dll, dlh;
@@ -264,10 +238,13 @@ static void parse_console_uart8250(void)
early_serial_init(port, baud);
}

-void console_init(void)
+void console_init(struct boot_params *boot_params)
{
parse_earlyprintk();

if (!early_serial_base)
parse_console_uart8250();
+
+ if (early_serial_base)
+ boot_params->early_serial_base = early_serial_base;
}
Index: linux-2.6.git/arch/x86/boot/tty.h
=====================================================================
--- /dev/null
+++ linux-2.6.git/arch/x86/boot/tty.h
@@ -0,0 +1,45 @@
+#ifndef BOOT_TTY_H
+#define BOOT_TTY_H
+
+#include <linux/compiler.h>
+#include <asm/boot.h>
+
+#define SERIAL_PORT_TTYS0 0x3f8
+#define SERIAL_PORT_TTYS1 0x2f8
+
+#define DEFAULT_SERIAL_PORT SERIAL_PORT_TTYS0
+
+#define XMTRDY 0x20
+#define DLAB 0x80
+
+#define TXR 0 /* Transmit register (WRITE) */
+#define RXR 0 /* Receive register (READ) */
+#define IER 1 /* Interrupt Enable */
+#define IIR 2 /* Interrupt ID */
+#define FCR 2 /* FIFO control */
+#define LCR 3 /* Line control */
+#define MCR 4 /* Modem control */
+#define LSR 5 /* Line Status */
+#define MSR 6 /* Modem Status */
+#define DLL 0 /* Divisor Latch Low */
+#define DLH 1 /* Divisor latch High */
+
+#define DEFAULT_BAUD 9600
+#define BASE_BAUD (1843200 / 16)
+
+/*
+ * wait for serial line being ready to transmit data
+ * and write out a character then
+ */
+static __always_inline int __serial_putchar(int ch, int base)
+{
+ unsigned int timeout = 0xffff;
+
+ while ((inb(base + LSR) & XMTRDY) == 0 && --timeout)
+ cpu_relax();
+
+ outb(ch, base + TXR);
+ return timeout ? 0 : -1;
+}
+
+#endif /* BOOT_TTY_H */
Index: linux-2.6.git/arch/x86/include/asm/bootparam.h
=====================================================================
--- linux-2.6.git.orig/arch/x86/include/asm/bootparam.h
+++ linux-2.6.git/arch/x86/include/asm/bootparam.h
@@ -93,7 +93,7 @@ struct efi_info {
struct boot_params {
struct screen_info screen_info; /* 0x000 */
struct apm_bios_info apm_bios_info; /* 0x040 */
- __u8 _pad2[4]; /* 0x054 */
+ __u32 early_serial_base; /* 0x054 */
__u64 tboot_addr; /* 0x058 */
struct ist_info ist_info; /* 0x060 */
__u8 _pad3[16]; /* 0x070 */
Index: linux-2.6.git/arch/x86/kernel/early_printk.c
=====================================================================
--- linux-2.6.git.orig/arch/x86/kernel/early_printk.c
+++ linux-2.6.git/arch/x86/kernel/early_printk.c
@@ -17,6 +17,8 @@
#include <asm/pgtable.h>
#include <linux/usb/ehci_def.h>

+#include "../boot/tty.h"
+
/* Simple VGA output */
#define VGABASE (__ISA_IO_base + 0xb8000)

@@ -73,46 +75,18 @@ static struct console early_vga_console

/* Serial functions loosely based on a similar package from Klaus P. Gerlicher */

-static int early_serial_base = 0x3f8; /* ttyS0 */
-
-#define XMTRDY 0x20
-
-#define DLAB 0x80
-
-#define TXR 0 /* Transmit register (WRITE) */
-#define RXR 0 /* Receive register (READ) */
-#define IER 1 /* Interrupt Enable */
-#define IIR 2 /* Interrupt ID */
-#define FCR 2 /* FIFO control */
-#define LCR 3 /* Line control */
-#define MCR 4 /* Modem control */
-#define LSR 5 /* Line Status */
-#define MSR 6 /* Modem Status */
-#define DLL 0 /* Divisor Latch Low */
-#define DLH 1 /* Divisor latch High */
-
-static int early_serial_putc(unsigned char ch)
-{
- unsigned timeout = 0xffff;
-
- while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
- cpu_relax();
- outb(ch, early_serial_base + TXR);
- return timeout ? 0 : -1;
-}
+static int early_serial_base = DEFAULT_SERIAL_PORT;

static void early_serial_write(struct console *con, const char *s, unsigned n)
{
while (*s && n-- > 0) {
if (*s == '\n')
- early_serial_putc('\r');
- early_serial_putc(*s);
+ __serial_putchar('\r', early_serial_base);
+ __serial_putchar(*s, early_serial_base);
s++;
}
}

-#define DEFAULT_BAUD 9600
-
static __init void early_serial_init(char *s)
{
unsigned char c;

2010-08-02 17:43:40

by Cyrill Gorcunov

[permalink] [raw]
Subject: Re: [PATCH -v3 1/2] x86, setup: reorgize the early_console_setup

On Mon, Aug 02, 2010 at 02:17:31AM -0700, Yinghai Lu wrote:
...
> Index: linux-2.6/arch/x86/boot/printf.c
> ===================================================================
> --- linux-2.6.orig/arch/x86/boot/printf.c
> +++ linux-2.6/arch/x86/boot/printf.c
> @@ -34,7 +34,7 @@ static int skip_atoi(const char **s)
> #define SMALL 32 /* Must be 32 == 0x20 */
> #define SPECIAL 64 /* 0x */
>
> -#define do_div(n,base) ({ \
> +#define __do_div(n, base) ({ \
> int __res; \
> __res = ((unsigned long) n) % (unsigned) base; \
> n = ((unsigned long) n) / (unsigned) base; \
> @@ -83,7 +83,7 @@ static char *number(char *str, long num,
> tmp[i++] = '0';
> else
> while (num != 0)
> - tmp[i++] = (digits[do_div(num, base)] | locase);
> + tmp[i++] = (digits[__do_div(num, base)] | locase);

Yinghai, what was wrong with the origin do_div? After inclusion it as "printf.c"
in another *.c do_div gets clashed?

-- Cyrill

2010-08-02 17:49:22

by Cyrill Gorcunov

[permalink] [raw]
Subject: Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c

On Mon, Aug 02, 2010 at 02:18:39AM -0700, Yinghai Lu wrote:
>
> will get
>
> |Decompressing Linux... Parsing ELF... done.
> |Booting the kernel.
>
> in serial console.
>
> reuse code from arch/x86/boot/
> and we can use printf if needed
>
> -v2: define BOOT_BOOT_H to avoid include boot.h
> -v3: early_serial_base need to be static in misc.c ?
>
> Signed-off-by: Yinghai Lu <[email protected]>
>
> ---
> arch/x86/boot/compressed/misc.c | 65 +++++++++++++++++++++++++++++++++++++++-
> arch/x86/boot/main.c | 6 +--
> 2 files changed, 66 insertions(+), 5 deletions(-)
>

It seems eventually we just add ~80 lines of code in compare with what we had before,
just to print "Decompressing..." by serial line. Not sure Yinghai if it worth
it. Though having printf that early might be quite useful for those who debugging
or developing new compressors/decompressors. If it would be small non-intrusive
patch I would both hands for it but now I simply don't know (to be fair mine
proposal based on your initial patch not better either ;)

-- Cyrill

2010-08-02 17:56:54

by Thiago Farina

[permalink] [raw]
Subject: Re: [PATCH 1/2] x86, setup: reorgize the early_console_setup

On Mon, Aug 2, 2010 at 4:13 AM, Yinghai Lu <[email protected]> wrote:
> Index: linux-2.6/arch/x86/boot/string.c
> ===================================================================
> --- linux-2.6.orig/arch/x86/boot/string.c
> +++ linux-2.6/arch/x86/boot/string.c
> @@ -12,7 +12,21 @@
>  * Very basic string functions
>  */
>
> -#include "boot.h"
> +static inline int isdigit(int ch)
> +{
> +       return (ch >= '0') && (ch <= '9');
> +}
> +
> +static inline int isxdigit(int ch)
> +{
> +       if (isdigit(ch))
> +               return true;
> +
> +       if ((ch >= 'a') && (ch <= 'f'))
> +               return true;
> +
> +       return (ch >= 'A') && (ch <= 'F');
> +}
>

These to functions above can be fairly simplified by writting as:

static bool inline is_hex_digit(int c) {
return (c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'F') ||
(c >= 'a' && c <= 'f');
}

Thanks.

2010-08-02 18:00:15

by Thiago Farina

[permalink] [raw]
Subject: Re: [PATCH 1/2] x86, setup: reorgize the early_console_setup

On Mon, Aug 2, 2010 at 2:56 PM, Thiago Farina <[email protected]> wrote:
> On Mon, Aug 2, 2010 at 4:13 AM, Yinghai Lu <[email protected]> wrote:
>> Index: linux-2.6/arch/x86/boot/string.c
>> ===================================================================
>> --- linux-2.6.orig/arch/x86/boot/string.c
>> +++ linux-2.6/arch/x86/boot/string.c
>> @@ -12,7 +12,21 @@
>>  * Very basic string functions
>>  */
>>
>> -#include "boot.h"
>> +static inline int isdigit(int ch)
>> +{
>> +       return (ch >= '0') && (ch <= '9');
>> +}
>> +
>> +static inline int isxdigit(int ch)
>> +{
>> +       if (isdigit(ch))
>> +               return true;
>> +
>> +       if ((ch >= 'a') && (ch <= 'f'))
>> +               return true;
>> +
>> +       return (ch >= 'A') && (ch <= 'F');
>> +}
>>
>
> These to functions above can be fairly simplified by writting as:
>
> static bool inline is_hex_digit(int c) {
>  return (c >= '0' && c <= '9') ||
>            (c >= 'A' && c <= 'F') ||
>            (c >= 'a' && c <= 'f');
> }
>

Wow, sorry, this should be:

static inline bool is_hex_digit(int c) { ... }

2010-08-02 18:28:20

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH 1/2] x86, setup: reorgize the early_console_setup

On 08/02/2010 10:56 AM, Thiago Farina wrote:
>
> These to functions above can be fairly simplified by writting as:
>
> static bool inline is_hex_digit(int c) {
> return (c >= '0' && c <= '9') ||
> (c >= 'A' && c <= 'F') ||
> (c >= 'a' && c <= 'f');
> }
>

a) You lose the isdigit() functionality, which is useful on its own.
b) Does this enahance readability in any way?
c) Your proposed renaming is nonstandard.

As such, I don't think this is a good idea.

-hpa

2010-08-02 18:40:04

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c

On 08/02/2010 10:49 AM, Cyrill Gorcunov wrote:
> On Mon, Aug 02, 2010 at 02:18:39AM -0700, Yinghai Lu wrote:
>>
>> will get
>>
>> |Decompressing Linux... Parsing ELF... done.
>> |Booting the kernel.
>>
>> in serial console.
>>
>> reuse code from arch/x86/boot/
>> and we can use printf if needed
>>
>> -v2: define BOOT_BOOT_H to avoid include boot.h
>> -v3: early_serial_base need to be static in misc.c ?
>>
>> Signed-off-by: Yinghai Lu <[email protected]>
>>
>> ---
>> arch/x86/boot/compressed/misc.c | 65 +++++++++++++++++++++++++++++++++++++++-
>> arch/x86/boot/main.c | 6 +--
>> 2 files changed, 66 insertions(+), 5 deletions(-)
>>
>
> It seems eventually we just add ~80 lines of code in compare with what we had before,
> just to print "Decompressing..." by serial line. Not sure Yinghai if it worth
> it. Though having printf that early might be quite useful for those who debugging
> or developing new compressors/decompressors. If it would be small non-intrusive
> patch I would both hands for it but now I simply don't know (to be fair mine
> proposal based on your initial patch not better either ;)
>

Decompressing... is one thing, and if it was only that, I'd just suggest
killing off the console I/O in boot/compressed. Getting an error
message out when there is a decompression failure is another thing.

Processing the command line a novo is somewhat painful, but it does deal
better with bootloaders that use the 32-bit entry point by necessity
(kexec, EFI) or due to sheer stupidity (Grub2).

As such, I think it's a worthwhile addition, as long as the source code
can be cleanly shared with the boot/ directory.

-hpa

2010-08-02 18:54:22

by Cyrill Gorcunov

[permalink] [raw]
Subject: Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c

On Mon, Aug 02, 2010 at 11:38:57AM -0700, H. Peter Anvin wrote:
> On 08/02/2010 10:49 AM, Cyrill Gorcunov wrote:
> > On Mon, Aug 02, 2010 at 02:18:39AM -0700, Yinghai Lu wrote:
> >>
> >> will get
> >>
> >> |Decompressing Linux... Parsing ELF... done.
> >> |Booting the kernel.
> >>
> >> in serial console.
> >>
> >> reuse code from arch/x86/boot/
> >> and we can use printf if needed
> >>
...
> >
> > It seems eventually we just add ~80 lines of code in compare with what we had before,
> > just to print "Decompressing..." by serial line. Not sure Yinghai if it worth
> > it. Though having printf that early might be quite useful for those who debugging
> > or developing new compressors/decompressors. If it would be small non-intrusive
> > patch I would both hands for it but now I simply don't know (to be fair mine
> > proposal based on your initial patch not better either ;)
> >
>
> Decompressing... is one thing, and if it was only that, I'd just suggest
> killing off the console I/O in boot/compressed. Getting an error
> message out when there is a decompression failure is another thing.
>
> Processing the command line a novo is somewhat painful, but it does deal
> better with bootloaders that use the 32-bit entry point by necessity
> (kexec, EFI) or due to sheer stupidity (Grub2).
>
> As such, I think it's a worthwhile addition, as long as the source code
> can be cleanly shared with the boot/ directory.
>
> -hpa
>

ok, fair enough, I just don't like nesting *.c inclusion you know but seems
it would be the only more-less clean way here.

-- Cyrill

2010-08-02 18:59:10

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c

On 08/02/2010 11:54 AM, Cyrill Gorcunov wrote:
>
> ok, fair enough, I just don't like nesting *.c inclusion you know but seems
> it would be the only more-less clean way here.
>

I don't mind it *as long as* the including file contains nothing but a
single #include statement -- which is just another way to say "the same
thing as this other file". Don't combine files.

Look at most of the .c files in arch/x86/kernel/acpi/realmode/ for an
example.

-hpa

2010-08-02 19:09:34

by Thiago Farina

[permalink] [raw]
Subject: Re: [PATCH 1/2] x86, setup: reorgize the early_console_setup

On Mon, Aug 2, 2010 at 3:27 PM, H. Peter Anvin <[email protected]> wrote:
> On 08/02/2010 10:56 AM, Thiago Farina wrote:
>>
>> These to functions above can be fairly simplified by writting as:
>>
>> static bool inline is_hex_digit(int c) {
>>   return (c >= '0' && c <= '9') ||
>>             (c >= 'A' && c <= 'F') ||
>>             (c >= 'a' && c <= 'f');
>> }
>>
>
> a) You lose the isdigit() functionality, which is useful on its own.
> b) Does this enahance readability in any way?
> c) Your proposed renaming is nonstandard.
>

What about this instead?

static inline bool isxdigit(int ch) {
return (isdigit(ch) || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f');
}

> As such, I don't think this is a good idea.
>
>        -hpa
>

2010-08-02 19:17:19

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH -v3 1/2] x86, setup: reorgize the early_console_setup

On 08/02/2010 10:43 AM, Cyrill Gorcunov wrote:
> On Mon, Aug 02, 2010 at 02:17:31AM -0700, Yinghai Lu wrote:
> ...
>> Index: linux-2.6/arch/x86/boot/printf.c
>> ===================================================================
>> --- linux-2.6.orig/arch/x86/boot/printf.c
>> +++ linux-2.6/arch/x86/boot/printf.c
>> @@ -34,7 +34,7 @@ static int skip_atoi(const char **s)
>> #define SMALL 32 /* Must be 32 == 0x20 */
>> #define SPECIAL 64 /* 0x */
>>
>> -#define do_div(n,base) ({ \
>> +#define __do_div(n, base) ({ \
>> int __res; \
>> __res = ((unsigned long) n) % (unsigned) base; \
>> n = ((unsigned long) n) / (unsigned) base; \
>> @@ -83,7 +83,7 @@ static char *number(char *str, long num,
>> tmp[i++] = '0';
>> else
>> while (num != 0)
>> - tmp[i++] = (digits[do_div(num, base)] | locase);
>> + tmp[i++] = (digits[__do_div(num, base)] | locase);
>
> Yinghai, what was wrong with the origin do_div? After inclusion it as "printf.c"
> in another *.c do_div gets clashed?

yes. get clashed if include that printf.c in arch/x86/boot/compressed/misc.c

Yinghai

2010-08-02 19:24:12

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 1/2] x86, setup: reorgize the early_console_setup

On 08/02/2010 08:09 AM, Cyrill Gorcunov wrote:
> On Mon, Aug 02, 2010 at 12:13:31AM -0700, Yinghai Lu wrote:
>>
>> Seperate early_console_setup from tty.c
>> also make main.c to include printf.c/string.c/cmdline.c
>>
>> will reuse early_serial_console.c/string.c/printf.c/cmdline.c in compressed/misc.c
>>
>> Signed-off-by: Yinghai Lu <[email protected]>
>>
>> ---
>
> Hi Yinghai, I'll try to find some time for review though it looks somehow
> too 'big' for me :)
>
> Actually by reading your initial approach (which was much smaller in size) I
> thought we end up in something like the patch below, though I'll review this
> seris. So just to share (I've tested it under qemu). The idea is the same as
> your was, so I pushed all constant parts into header and use it when needed
> passing serial line base port via boot_params.

Eric doesn't like early_serial_console_base in zero page. and said that is fragile.

So try to include string.c/printf.c/cmdline.c/early_serial_console.c in arch/x86/boot/compressed/misc.c
and analyze that command line again.

then kexec path will get support too. that is from arch/x86/boot/compressed/head_32.S or head_64.S, startup_32.
and skip arch/x86/boot/main.c

later with following patch for 3, we get all covered in c code.
1. arch/x86/boot/main.c: setup code.
2. arch/x86/boot/compressed/misc.c: decompress_kernel code : the 2 -v3 patches that i sent last night.
3. arch/x86/kernel/head64.c: real kernel.

maybe we can make early_serial_console.c and early_printk.c to share some .h etc later.

Thanks

Yinghai

[PATCH -v2] x86: Setup early console as early as possible

Analyze "console=uart8250,io,0x3f8,115200n8" in i386_start_kernel/x86_64_start_kernel,
and call setup_early_serial8250_console() to init early serial console.

only can handle io port kind of 8250. because mmio need ioremap.

-v2: use boot_params.hdr.version instead of adding another variable, Suggested by hpa
update after using x86 memblock patchset

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/include/asm/setup.h | 2 ++
arch/x86/kernel/head.c | 27 +++++++++++++++++++++++++++
arch/x86/kernel/head32.c | 2 ++
arch/x86/kernel/head64.c | 13 +++++++++++--
kernel/printk.c | 4 ++++
5 files changed, 46 insertions(+), 2 deletions(-)

Index: linux-2.6/arch/x86/include/asm/setup.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/setup.h
+++ linux-2.6/arch/x86/include/asm/setup.h
@@ -42,6 +42,8 @@ static inline void visws_early_detect(vo
#endif

extern unsigned long saved_video_mode;
+int setup_early_serial8250_console(char *cmdline);
+void setup_early_console(void);

extern void reserve_standard_io_resources(void);
extern void i386_reserve_resources(void);
Index: linux-2.6/arch/x86/kernel/head.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/head.c
+++ linux-2.6/arch/x86/kernel/head.c
@@ -54,3 +54,30 @@ void __init reserve_ebda_region(void)
/* reserve all memory between lowmem and the 1MB mark */
memblock_x86_reserve_range(lowmem, 0x100000, "* BIOS reserved");
}
+
+
+void __init setup_early_console(void)
+{
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ char constr[64], *p, *q;
+
+ /* Can not handle mmio type 8250 uart yet, too early */
+ p = strstr(boot_command_line, "console=uart8250,io,");
+ if (!p)
+ p = strstr(boot_command_line, "console=uart,io,");
+ if (!p)
+ return;
+
+ p += 8; /* sizeof "console=" */
+ q = strchr(p, ' ');
+ if ((q - p) >= sizeof(constr))
+ return;
+
+ memset(constr, 0, sizeof(constr));
+ memcpy(constr, p, q - p);
+
+ lockdep_init();
+
+ setup_early_serial8250_console(constr);
+#endif
+}
Index: linux-2.6/arch/x86/kernel/head32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/head32.c
+++ linux-2.6/arch/x86/kernel/head32.c
@@ -31,6 +31,8 @@ static void __init i386_default_early_se

void __init i386_start_kernel(void)
{
+ setup_early_console();
+
memblock_init();

#ifdef CONFIG_X86_TRAMPOLINE
Index: linux-2.6/arch/x86/kernel/head64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/head64.c
+++ linux-2.6/arch/x86/kernel/head64.c
@@ -46,6 +46,10 @@ static void __init copy_bootdata(char *r
{
char * command_line;

+ /* make sure if it is copied already */
+ if (boot_params.hdr.version)
+ return;
+
memcpy(&boot_params, real_mode_data, sizeof boot_params);
if (boot_params.hdr.cmd_line_ptr) {
command_line = __va(boot_params.hdr.cmd_line_ptr);
@@ -74,6 +78,10 @@ void __init x86_64_start_kernel(char * r
/* clear bss before set_intr_gate with early_idt_handler */
clear_bss();

+ /* boot_params is in bss */
+ copy_bootdata(__va(real_mode_data));
+ setup_early_console();
+
/* Make NULL pointers segfault */
zap_identity_mappings();

@@ -97,9 +105,10 @@ void __init x86_64_start_kernel(char * r

void __init x86_64_start_reservations(char *real_mode_data)
{
- memblock_init();
-
copy_bootdata(__va(real_mode_data));
+ setup_early_console();
+
+ memblock_init();

memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");

Index: linux-2.6/kernel/printk.c
===================================================================
--- linux-2.6.orig/kernel/printk.c
+++ linux-2.6/kernel/printk.c
@@ -1204,6 +1204,10 @@ void register_console(struct console *ne
if (console_drivers && newcon->flags & CON_BOOT) {
/* find the last or real console */
for_each_console(bcon) {
+ /* not again */
+ if (bcon == newcon)
+ return;
+
if (!(bcon->flags & CON_BOOT)) {
printk(KERN_INFO "Too late to register bootconsole %s%d\n",
newcon->name, newcon->index);

2010-08-02 19:37:34

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c

On 08/02/2010 11:58 AM, H. Peter Anvin wrote:
> On 08/02/2010 11:54 AM, Cyrill Gorcunov wrote:
>>
>> ok, fair enough, I just don't like nesting *.c inclusion you know but seems
>> it would be the only more-less clean way here.
>>
>
> I don't mind it *as long as* the including file contains nothing but a
> single #include statement -- which is just another way to say "the same
> thing as this other file". Don't combine files.
>
> Look at most of the .c files in arch/x86/kernel/acpi/realmode/ for an
> example.

it seems I can not global variables in arch/x86/boot/compressed/misc.c

and misc.c already include some decompress .c like

#ifdef CONFIG_KERNEL_GZIP
#include "../../../../lib/decompress_inflate.c"
#endif

#ifdef CONFIG_KERNEL_BZIP2
#include "../../../../lib/decompress_bunzip2.c"
#endif

#ifdef CONFIG_KERNEL_LZMA
#include "../../../../lib/decompress_unlzma.c"
#endif

#ifdef CONFIG_KERNEL_LZO
#include "../../../../lib/decompress_unlzo.c"
#endif


this patch change to misc.c are following lines:

#define BOOT_BOOT_H
#include "../isdigit.h"
#include "../string.c"
#include "../printf.c"

...

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"
static inline int cmdline_find_option(const char *option, char *buffer, int bufsize)
{
return __cmdline_find_option(real_mode->hdr.cmd_line_ptr, option, buffer, bufsize);
}
static inline int cmdline_find_option_bool(const char *option)
{
return __cmdline_find_option_bool(real_mode->hdr.cmd_line_ptr, option);
}
static int early_serial_base;
#include "../early_serial_console.c"

or put them in another file?

Thanks

Yinghai

Yinghai

2010-08-02 20:18:04

by Cyrill Gorcunov

[permalink] [raw]
Subject: Re: [PATCH 1/2] x86, setup: reorgize the early_console_setup

On Mon, Aug 02, 2010 at 12:23:17PM -0700, Yinghai Lu wrote:
> On 08/02/2010 08:09 AM, Cyrill Gorcunov wrote:
> > On Mon, Aug 02, 2010 at 12:13:31AM -0700, Yinghai Lu wrote:
> >>
> >> Seperate early_console_setup from tty.c
> >> also make main.c to include printf.c/string.c/cmdline.c
> >>
> >> will reuse early_serial_console.c/string.c/printf.c/cmdline.c in compressed/misc.c
> >>
> >> Signed-off-by: Yinghai Lu <[email protected]>
> >>
> >> ---
> >
> > Hi Yinghai, I'll try to find some time for review though it looks somehow
> > too 'big' for me :)
> >
> > Actually by reading your initial approach (which was much smaller in size) I
> > thought we end up in something like the patch below, though I'll review this
> > seris. So just to share (I've tested it under qemu). The idea is the same as
> > your was, so I pushed all constant parts into header and use it when needed
> > passing serial line base port via boot_params.
>
> Eric doesn't like early_serial_console_base in zero page. and said that is fragile.
>

yeah, and Peter noted too as well, I missed Eric's mail in first place.

> So try to include string.c/printf.c/cmdline.c/early_serial_console.c in arch/x86/boot/compressed/misc.c
> and analyze that command line again.
>
> then kexec path will get support too. that is from arch/x86/boot/compressed/head_32.S or head_64.S, startup_32.
> and skip arch/x86/boot/main.c
>
> later with following patch for 3, we get all covered in c code.
> 1. arch/x86/boot/main.c: setup code.
> 2. arch/x86/boot/compressed/misc.c: decompress_kernel code : the 2 -v3 patches that i sent last night.
> 3. arch/x86/kernel/head64.c: real kernel.
>
> maybe we can make early_serial_console.c and early_printk.c to share some .h etc later.
>

yes, sounds tempting for me ;)

> Thanks
>
> Yinghai
>
> [PATCH -v2] x86: Setup early console as early as possible
>
> Analyze "console=uart8250,io,0x3f8,115200n8" in i386_start_kernel/x86_64_start_kernel,
> and call setup_early_serial8250_console() to init early serial console.
>
> only can handle io port kind of 8250. because mmio need ioremap.
>
> -v2: use boot_params.hdr.version instead of adding another variable, Suggested by hpa
> update after using x86 memblock patchset
>
> Signed-off-by: Yinghai Lu <[email protected]>
> ---
...
> +
> + p += 8; /* sizeof "console=" */
> + q = strchr(p, ' ');
> + if ((q - p) >= sizeof(constr))
> + return;
> +

I think the better would be to explicitly point q=0 here, ie if (!q || ...)
(yes, it'll trigger with former too but anyway this would be somewhat cleaner)

> + memset(constr, 0, sizeof(constr));
> + memcpy(constr, p, q - p);
> +
> + lockdep_init();
> +
> + setup_early_serial8250_console(constr);
> +#endif
> +}

...

> + /* make sure if it is copied already */
> + if (boot_params.hdr.version)
> + return;
> +

And Yinghai, lets be more verbose here a bit, since for those who will
be reading this code later might be non-obvious why we have checked for
'version' here. I guess something like "an easy way to check if boot_params
were already copied". Actually it's clean from commit message but I think
we first read code comments and commit messages after, agreed? ;-)

> memcpy(&boot_params, real_mode_data, sizeof boot_params);
> if (boot_params.hdr.cmd_line_ptr) {
> command_line = __va(boot_params.hdr.cmd_line_ptr);
> @@ -74,6 +78,10 @@ void __init x86_64_start_kernel(char * r
> /* clear bss before set_intr_gate with early_idt_handler */
> clear_bss();
>
...

Other then that looks good for me, thanks! My Reviewed-by if needed.

-- Cyrill

2010-08-02 20:31:48

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH 1/2] x86, setup: reorgize the early_console_setup

On 08/02/2010 01:17 PM, Cyrill Gorcunov wrote:
> On Mon, Aug 02, 2010 at 12:23:17PM -0700, Yinghai Lu wrote:
>> On 08/02/2010 08:09 AM, Cyrill Gorcunov wrote:
>>> On Mon, Aug 02, 2010 at 12:13:31AM -0700, Yinghai Lu wrote:
>> So try to include string.c/printf.c/cmdline.c/early_serial_console.c in arch/x86/boot/compressed/misc.c
>> and analyze that command line again.
>>
>> then kexec path will get support too. that is from arch/x86/boot/compressed/head_32.S or head_64.S, startup_32.
>> and skip arch/x86/boot/main.c
>>
>> later with following patch for 3, we get all covered in c code.
>> 1. arch/x86/boot/main.c: setup code.
>> 2. arch/x86/boot/compressed/misc.c: decompress_kernel code : the 2 -v3 patches that i sent last night.
>> 3. arch/x86/kernel/head64.c: real kernel.
>>
>>
>> [PATCH -v2] x86: Setup early console as early as possible
>>
>> Analyze "console=uart8250,io,0x3f8,115200n8" in i386_start_kernel/x86_64_start_kernel,
>> and call setup_early_serial8250_console() to init early serial console.
>>
>> only can handle io port kind of 8250. because mmio need ioremap.
>>
>> -v2: use boot_params.hdr.version instead of adding another variable, Suggested by hpa
>> update after using x86 memblock patchset
>>
>> Signed-off-by: Yinghai Lu <[email protected]>
>> ---

> ...
>
>> + /* make sure if it is copied already */
>> + if (boot_params.hdr.version)
>> + return;
>> +
>
> And Yinghai, lets be more verbose here a bit, since for those who will
> be reading this code later might be non-obvious why we have checked for
> 'version' here. I guess something like "an easy way to check if boot_params
> were already copied". Actually it's clean from commit message but I think
> we first read code comments and commit messages after, agreed? ;-)

will change to

/*
* hdr.version is always not 0, so check it to see
* if boot_params is copied or not.
*/

will resend this patch after memblock x86 changes.

YH

2010-08-02 20:34:49

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH 1/2] x86, setup: reorgize the early_console_setup

On 08/02/2010 12:09 PM, Thiago Farina wrote:
> On Mon, Aug 2, 2010 at 3:27 PM, H. Peter Anvin <[email protected]> wrote:
>> On 08/02/2010 10:56 AM, Thiago Farina wrote:
>>>
>>> These to functions above can be fairly simplified by writting as:
>>>
>>> static bool inline is_hex_digit(int c) {
>>> return (c >= '0' && c <= '9') ||
>>> (c >= 'A' && c <= 'F') ||
>>> (c >= 'a' && c <= 'f');
>>> }
>>>
>>
>> a) You lose the isdigit() functionality, which is useful on its own.
>> b) Does this enahance readability in any way?
>> c) Your proposed renaming is nonstandard.
>>
>
> What about this instead?
>
> static inline bool isxdigit(int ch) {
> return (isdigit(ch) || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f');
> }
>
>> As such, I don't think this is a good idea.
>>

Again, I don't think it adds any readability; the compiler will produce
the same code.

-hpa

2010-08-02 20:37:07

by Cyrill Gorcunov

[permalink] [raw]
Subject: Re: [PATCH 1/2] x86, setup: reorgize the early_console_setup

On Mon, Aug 02, 2010 at 01:30:17PM -0700, Yinghai Lu wrote:
...
> >> + /* make sure if it is copied already */
> >> + if (boot_params.hdr.version)
> >> + return;
> >> +
> >
> > And Yinghai, lets be more verbose here a bit, since for those who will
> > be reading this code later might be non-obvious why we have checked for
> > 'version' here. I guess something like "an easy way to check if boot_params
> > were already copied". Actually it's clean from commit message but I think
> > we first read code comments and commit messages after, agreed? ;-)
>
> will change to
>
> /*
> * hdr.version is always not 0, so check it to see
> * if boot_params is copied or not.
> */
>
> will resend this patch after memblock x86 changes.
>
> YH
>

ok, thanks!

-- Cyrill

2010-08-02 20:39:20

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c

On 08/02/2010 12:35 PM, Yinghai Lu wrote:
>
> it seems I can not global variables in arch/x86/boot/compressed/misc.c
>

Well, that should be fixed, then. If we can't use the linker for what
it's supposed to be used for it's just crap.

> and misc.c already include some decompress .c like
>
> #ifdef CONFIG_KERNEL_GZIP
> #include "../../../../lib/decompress_inflate.c"
> #endif
>
> #ifdef CONFIG_KERNEL_BZIP2
> #include "../../../../lib/decompress_bunzip2.c"
> #endif
>
> #ifdef CONFIG_KERNEL_LZMA
> #include "../../../../lib/decompress_unlzma.c"
> #endif
>
> #ifdef CONFIG_KERNEL_LZO
> #include "../../../../lib/decompress_unlzo.c"
> #endif
>

Yes, I know; that's crap in a lot of ways too... the whole decompression
stuff is its own issue which is slowly being addressed. It's not an
excuse to make the code crappier than it already is.

>
> this patch change to misc.c are following lines:
>
> #define BOOT_BOOT_H
> #include "../isdigit.h"
> #include "../string.c"
> #include "../printf.c"
>
> ...
>
> 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"
> static inline int cmdline_find_option(const char *option, char *buffer, int bufsize)
> {
> return __cmdline_find_option(real_mode->hdr.cmd_line_ptr, option, buffer, bufsize);
> }
> static inline int cmdline_find_option_bool(const char *option)
> {
> return __cmdline_find_option_bool(real_mode->hdr.cmd_line_ptr, option);
> }
> static int early_serial_base;
> #include "../early_serial_console.c"
>
> or put them in another file?
>

Hmf... games with set_fs() aren't a whole lot of fun at all. I think it
would be better to define some wrappers specific to cmdline.c which
allow it to be using a real pointer in 32-bit mode.

I'll see if I can muck with it, it shouldn't take long.

-hpa

2010-08-02 21:00:31

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c

On 08/02/2010 12:35 PM, Yinghai Lu wrote:
>
> it seems I can not global variables in arch/x86/boot/compressed/misc.c
>

I just looked at it, it's the fact that we don't relocate the GOT that
is causing problems. It's relatively easy to fix: here is a patch, but
in grand Linus tradition it is completely untested.

-hpa


Attachments:
diff (1.40 kB)

2010-08-02 21:09:28

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c

On 08/02/2010 01:59 PM, H. Peter Anvin wrote:
> On 08/02/2010 12:35 PM, Yinghai Lu wrote:
>>
>> it seems I can not global variables in arch/x86/boot/compressed/misc.c
>>
>
> I just looked at it, it's the fact that we don't relocate the GOT that
> is causing problems. It's relatively easy to fix: here is a patch, but
> in grand Linus tradition it is completely untested.
>

Untested indeed... here is one which doesn't clobber live registers.

-hpa


Attachments:
diff (1.40 kB)

2010-08-02 21:25:14

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c

On 08/02/2010 02:08 PM, H. Peter Anvin wrote:
> On 08/02/2010 01:59 PM, H. Peter Anvin wrote:
>> On 08/02/2010 12:35 PM, Yinghai Lu wrote:
>>>
>>> it seems I can not global variables in arch/x86/boot/compressed/misc.c
>>>
>>
>> I just looked at it, it's the fact that we don't relocate the GOT that
>> is causing problems. It's relatively easy to fix: here is a patch, but
>> in grand Linus tradition it is completely untested.
>>
>
> Untested indeed... here is one which doesn't clobber live registers.
>
> -hpa
>

still doesn't work.

with global early_serial_base got :

early console in setup code
[ 0.000000] bootconsole [uart0] enabled


with static early_serial_base got :

early console in setup code
early console in decompress_kernel
decompress_kernel:
input: [0x24a0269-0x2e8b234], output: 0x1000000, heap: [0x2e909c0-0x2e979bf]

Decompressing Linux... Parsing ELF... done.
Booting the kernel.
[ 0.000000] bootconsole [uart0] enabled


Thanks

Yinghai

2010-08-02 21:28:15

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c

On 08/02/2010 02:08 PM, H. Peter Anvin wrote:
> On 08/02/2010 01:59 PM, H. Peter Anvin wrote:
>> On 08/02/2010 12:35 PM, Yinghai Lu wrote:
>>>
>>> it seems I can not global variables in arch/x86/boot/compressed/misc.c
>>>
>>
>> I just looked at it, it's the fact that we don't relocate the GOT that
>> is causing problems. It's relatively easy to fix: here is a patch, but
>> in grand Linus tradition it is completely untested.
>>
>
> Untested indeed... here is one which doesn't clobber live registers.
>

And of course I got the test backwards... in AT&T syntax, number
compares you!

-hpa




Attachments:
diff (1.40 kB)

2010-08-02 21:37:57

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c

On 08/02/2010 02:27 PM, H. Peter Anvin wrote:
> On 08/02/2010 02:08 PM, H. Peter Anvin wrote:
>> On 08/02/2010 01:59 PM, H. Peter Anvin wrote:
>>> On 08/02/2010 12:35 PM, Yinghai Lu wrote:
>>>>
>>>> it seems I can not global variables in arch/x86/boot/compressed/misc.c
>>>>
>>>
>>> I just looked at it, it's the fact that we don't relocate the GOT that
>>> is causing problems. It's relatively easy to fix: here is a patch, but
>>> in grand Linus tradition it is completely untested.
>>>
>>
>> Untested indeed... here is one which doesn't clobber live registers.
>>
>
> And of course I got the test backwards... in AT&T syntax, number
> compares you!
>

great, this one works.

will have updated

[PATCH -v4 2/2] x86: more early console output from compressed/misc.c

Thanks

Yinghai

2010-08-02 22:32:12

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c

On 08/02/2010 02:27 PM, H. Peter Anvin wrote:
> On 08/02/2010 02:08 PM, H. Peter Anvin wrote:
>> On 08/02/2010 01:59 PM, H. Peter Anvin wrote:
>>> On 08/02/2010 12:35 PM, Yinghai Lu wrote:
>>>>
>>>> it seems I can not global variables in arch/x86/boot/compressed/misc.c
>>>>
>>>
>>> I just looked at it, it's the fact that we don't relocate the GOT that
>>> is causing problems. It's relatively easy to fix: here is a patch, but
>>> in grand Linus tradition it is completely untested.
>>>
>>
>> Untested indeed... here is one which doesn't clobber live registers.
>>
>
> And of course I got the test backwards... in AT&T syntax, number
> compares you!

updated version

Subject: [PATCH -v4 2/2] x86: more early console output from compressed/misc.c

will get

|Decompressing Linux... Parsing ELF... done.
|Booting the kernel.

in serial console.

reuse code from arch/x86/boot/
and we can use printf if needed

-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

Signed-off-by: Yinghai Lu <[email protected]>

---
arch/x86/boot/compressed/Makefile | 4 -
arch/x86/boot/compressed/cmdline.c | 21 +++++++
arch/x86/boot/compressed/early_serial_console.c | 4 +
arch/x86/boot/compressed/misc.c | 66 +++++++++++++++---------
arch/x86/boot/compressed/misc.h | 38 +++++++++++++
arch/x86/boot/compressed/printf.c | 4 +
arch/x86/boot/compressed/string.c | 4 +
arch/x86/boot/main.c | 6 --
8 files changed, 118 insertions(+), 29 deletions(-)

Index: linux-2.6/arch/x86/boot/compressed/misc.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/compressed/misc.c
+++ linux-2.6/arch/x86/boot/compressed/misc.c
@@ -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 ch
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 *
{
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,9 +325,23 @@ asmlinkage void decompress_kernel(void *
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;

+ if (debug) {
+ putstr("decompress_kernel:\n");
+ printf(" input: [0x%lx-0x%lx], output: 0x%lx, heap: [0x%lx-0x%lx]\n",
+ (unsigned long)input_data,
+ (unsigned long)input_data + input_len - 1,
+ (unsigned long)output,
+ (unsigned long)heap,
+ (unsigned long)heap + BOOT_HEAP_SIZE - 1);
+ }
+
if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1))
error("Destination address inappropriately aligned");
#ifdef CONFIG_X86_64
Index: linux-2.6/arch/x86/boot/main.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/main.c
+++ linux-2.6/arch/x86/boot/main.c
@@ -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();
}
Index: linux-2.6/arch/x86/boot/compressed/Makefile
===================================================================
--- linux-2.6.orig/arch/x86/boot/compressed/Makefile
+++ linux-2.6/arch/x86/boot/compressed/Makefile
@@ -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 printf.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)/printf.o $(obj)/cmdline.o $(obj)/early_serial_console.o $(obj)/piggy.o FORCE
$(call if_changed,ld)
@:

Index: linux-2.6/arch/x86/boot/compressed/cmdline.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/compressed/cmdline.c
@@ -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);
+}
Index: linux-2.6/arch/x86/boot/compressed/early_serial_console.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/compressed/early_serial_console.c
@@ -0,0 +1,4 @@
+#include "misc.h"
+
+int early_serial_base;
+#include "../early_serial_console.c"
Index: linux-2.6/arch/x86/boot/compressed/misc.h
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/compressed/misc.h
@@ -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
Index: linux-2.6/arch/x86/boot/compressed/printf.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/compressed/printf.c
@@ -0,0 +1,4 @@
+#include "misc.h"
+
+#include "../isdigit.h"
+#include "../printf.c"
Index: linux-2.6/arch/x86/boot/compressed/string.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/compressed/string.c
@@ -0,0 +1,4 @@
+#include "misc.h"
+
+#include "../isdigit.h"
+#include "../string.c"

2010-08-02 22:47:19

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c

First, I'm not quite sure which 1/2 patch you're expecting this to be
compiled against.

On 08/02/2010 03:30 PM, Yinghai Lu wrote:
>
> + if (debug) {
> + putstr("decompress_kernel:\n");
> + printf(" input: [0x%lx-0x%lx], output: 0x%lx, heap: [0x%lx-0x%lx]\n",
> + (unsigned long)input_data,
> + (unsigned long)input_data + input_len - 1,
> + (unsigned long)output,
> + (unsigned long)heap,
> + (unsigned long)heap + BOOT_HEAP_SIZE - 1);
> + }
> +

This seems to be the only user of printf() in the code. As such, I
really suspect it's not worth pulling in all of printf(). I'd be
willing to be convinced, but if so I need (a) a concrete usage case, and
(b) it should be a separate patch.

-hpa

2010-08-02 22:52:34

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c



On 08/02/2010 03:46 PM, H. Peter Anvin wrote:
> First, I'm not quite sure which 1/2 patch you're expecting this to be
> compiled against.

-v3

>
> On 08/02/2010 03:30 PM, Yinghai Lu wrote:
>>
>> + if (debug) {
>> + putstr("decompress_kernel:\n");
>> + printf(" input: [0x%lx-0x%lx], output: 0x%lx, heap: [0x%lx-0x%lx]\n",
>> + (unsigned long)input_data,
>> + (unsigned long)input_data + input_len - 1,
>> + (unsigned long)output,
>> + (unsigned long)heap,
>> + (unsigned long)heap + BOOT_HEAP_SIZE - 1);
>> + }
>> +
>
> This seems to be the only user of printf() in the code. As such, I
> really suspect it's not worth pulling in all of printf(). I'd be
> willing to be convinced, but if so I need (a) a concrete usage case, and
> (b) it should be a separate patch.

ok, will drop printf.

Yinghai

2010-08-02 23:22:22

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH -v3 2/2] x86: more early console output from compressed/misc.c

On 08/02/2010 03:51 PM, Yinghai Lu wrote:
>
>
> On 08/02/2010 03:46 PM, H. Peter Anvin wrote:
>> First, I'm not quite sure which 1/2 patch you're expecting this to be
>> compiled against.
>
> -v3
>
>>
>> On 08/02/2010 03:30 PM, Yinghai Lu wrote:
>>>
>>> + if (debug) {
>>> + putstr("decompress_kernel:\n");
>>> + printf(" input: [0x%lx-0x%lx], output: 0x%lx, heap: [0x%lx-0x%lx]\n",
>>> + (unsigned long)input_data,
>>> + (unsigned long)input_data + input_len - 1,
>>> + (unsigned long)output,
>>> + (unsigned long)heap,
>>> + (unsigned long)heap + BOOT_HEAP_SIZE - 1);
>>> + }
>>> +
>>
>> This seems to be the only user of printf() in the code. As such, I
>> really suspect it's not worth pulling in all of printf(). I'd be
>> willing to be convinced, but if so I need (a) a concrete usage case, and
>> (b) it should be a separate patch.
>
> ok, will drop printf.
>

please check..

Subject: [PATCH -v5 2/2] x86: more early console output from compressed/misc.c

will get

|Decompressing Linux... Parsing ELF... done.
|Booting the kernel.

in serial console.

reuse code from arch/x86/boot/
and we can use printf if needed

-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 <[email protected]>

---
arch/x86/boot/compressed/Makefile | 4 -
arch/x86/boot/compressed/cmdline.c | 21 +++++++++
arch/x86/boot/compressed/early_serial_console.c | 5 ++
arch/x86/boot/compressed/misc.c | 56 ++++++++++++++----------
arch/x86/boot/compressed/misc.h | 38 ++++++++++++++++
arch/x86/boot/compressed/string.c | 4 +
arch/x86/boot/main.c | 6 --
7 files changed, 105 insertions(+), 29 deletions(-)

Index: linux-2.6/arch/x86/boot/compressed/misc.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/compressed/misc.c
+++ linux-2.6/arch/x86/boot/compressed/misc.c
@@ -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 ch
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 *
{
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 *
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;

Index: linux-2.6/arch/x86/boot/main.c
===================================================================
--- linux-2.6.orig/arch/x86/boot/main.c
+++ linux-2.6/arch/x86/boot/main.c
@@ -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();
}
Index: linux-2.6/arch/x86/boot/compressed/Makefile
===================================================================
--- linux-2.6.orig/arch/x86/boot/compressed/Makefile
+++ linux-2.6/arch/x86/boot/compressed/Makefile
@@ -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)
@:

Index: linux-2.6/arch/x86/boot/compressed/cmdline.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/compressed/cmdline.c
@@ -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);
+}
Index: linux-2.6/arch/x86/boot/compressed/early_serial_console.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/compressed/early_serial_console.c
@@ -0,0 +1,5 @@
+#include "misc.h"
+
+int early_serial_base;
+
+#include "../early_serial_console.c"
Index: linux-2.6/arch/x86/boot/compressed/misc.h
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/compressed/misc.h
@@ -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
Index: linux-2.6/arch/x86/boot/compressed/string.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/x86/boot/compressed/string.c
@@ -0,0 +1,4 @@
+#include "misc.h"
+
+#include "../isdigit.h"
+#include "../string.c"

2010-08-03 03:31:10

by H. Peter Anvin

[permalink] [raw]
Subject: [tip:x86/setup] x86, setup: Allow global variables and functions in the decompressor

Commit-ID: 22a57f5896df218356bae6203dfaf04bcfd6c88c
Gitweb: http://git.kernel.org/tip/22a57f5896df218356bae6203dfaf04bcfd6c88c
Author: H. Peter Anvin <[email protected]>
AuthorDate: Mon, 2 Aug 2010 15:34:44 -0700
Committer: H. Peter Anvin <[email protected]>
CommitDate: Mon, 2 Aug 2010 15:34:44 -0700

x86, setup: Allow global variables and functions in the decompressor

In order for global variables and functions to work in the
decompressor, we need to fix up the GOT in assembly code.

Signed-off-by: H. Peter Anvin <[email protected]>
LKML-Reference: <[email protected]>
---
arch/x86/boot/compressed/head_32.S | 13 +++++++++++++
arch/x86/boot/compressed/head_64.S | 13 +++++++++++++
arch/x86/boot/compressed/vmlinux.lds.S | 6 ++++++
3 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index f543b70..67a655a 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -124,6 +124,19 @@ relocated:
rep stosl

/*
+ * Adjust our own GOT
+ */
+ leal _got(%ebx), %edx
+ leal _egot(%ebx), %ecx
+1:
+ cmpl %ecx, %edx
+ jae 2f
+ addl %ebx, (%edx)
+ addl $4, %edx
+ jmp 1b
+2:
+
+/*
* Do the decompression, and jump to the new kernel..
*/
leal z_extract_offset_negative(%ebx), %ebp
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index faff0dc..52f85a1 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -280,6 +280,19 @@ relocated:
rep stosq

/*
+ * Adjust our own GOT
+ */
+ leaq _got(%rip), %rdx
+ leaq _egot(%rip), %rcx
+1:
+ cmpq %rcx, %rdx
+ jae 2f
+ addq %rbx, (%rdx)
+ addq $8, %rdx
+ jmp 1b
+2:
+
+/*
* Do the decompression, and jump to the new kernel..
*/
pushq %rsi /* Save the real mode argument */
diff --git a/arch/x86/boot/compressed/vmlinux.lds.S b/arch/x86/boot/compressed/vmlinux.lds.S
index 5ddabce..34d047c 100644
--- a/arch/x86/boot/compressed/vmlinux.lds.S
+++ b/arch/x86/boot/compressed/vmlinux.lds.S
@@ -41,6 +41,12 @@ SECTIONS
*(.rodata.*)
_erodata = . ;
}
+ .got : {
+ _got = .;
+ KEEP(*(.got.plt))
+ KEEP(*(.got))
+ _egot = .;
+ }
.data : {
_data = . ;
*(.data)

2010-08-03 03:31:31

by Yinghai Lu

[permalink] [raw]
Subject: [tip:x86/setup] x86, setup: reorganize the early console setup

Commit-ID: f4ed2877b16e8146427306aea8819adac5c88374
Gitweb: http://git.kernel.org/tip/f4ed2877b16e8146427306aea8819adac5c88374
Author: Yinghai Lu <[email protected]>
AuthorDate: Mon, 2 Aug 2010 02:17:31 -0700
Committer: H. Peter Anvin <[email protected]>
CommitDate: Mon, 2 Aug 2010 15:51:56 -0700

x86, setup: reorganize the early console setup

Separate early_serial_console from tty.c

This allows for reuse of
early_serial_console.c/string.c/printf.c/cmdline.c in boot/compressed/.

-v2: according to hpa, don't include string.c etc
-v3: compressed/misc.c must have early_serial_base as static, so move it back to tty.c
for setup code

Signed-off-by: Yinghai Lu <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: H. Peter Anvin <[email protected]>
---
arch/x86/boot/Makefile | 8 +-
arch/x86/boot/boot.h | 35 ++++-----
arch/x86/boot/cmdline.c | 6 +-
arch/x86/boot/early_serial_console.c | 139 ++++++++++++++++++++++++++++++++++
arch/x86/boot/isdigit.h | 21 +++++
arch/x86/boot/printf.c | 4 +-
arch/x86/boot/tty.c | 136 +---------------------------------
7 files changed, 186 insertions(+), 163 deletions(-)

diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index ec749c2..f7cb086 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -26,10 +26,10 @@ targets := vmlinux.bin setup.bin setup.elf bzImage
targets += fdimage fdimage144 fdimage288 image.iso mtools.conf
subdir- := compressed

-setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o edd.o
-setup-y += header.o main.o mca.o memory.o pm.o pmjump.o
-setup-y += printf.o regs.o string.o tty.o video.o video-mode.o
-setup-y += version.o
+setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o
+setup-y += early_serial_console.o edd.o header.o main.o mca.o memory.o
+setup-y += pm.o pmjump.o printf.o regs.o string.o tty.o video.o
+setup-y += video-mode.o version.o
setup-$(CONFIG_X86_APM_BOOT) += apm.o

# The link order of the video-*.o modules can matter. In particular,
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index 46c4c5c..00cf51c 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -200,21 +200,7 @@ static inline int memcmp_gs(const void *s1, addr_t s2, size_t len)
return diff;
}

-static inline int isdigit(int ch)
-{
- return (ch >= '0') && (ch <= '9');
-}
-
-static inline int isxdigit(int ch)
-{
- if (isdigit(ch))
- return true;
-
- if ((ch >= 'a') && (ch <= 'f'))
- return true;
-
- return (ch >= 'A') && (ch <= 'F');
-}
+#include "isdigit.h"

/* Heap -- available for dynamic lists. */
extern char _end[];
@@ -300,8 +286,18 @@ struct biosregs {
void intcall(u8 int_no, const struct biosregs *ireg, struct biosregs *oreg);

/* cmdline.c */
-int cmdline_find_option(const char *option, char *buffer, int bufsize);
-int cmdline_find_option_bool(const char *option);
+int __cmdline_find_option(u32 cmdline_ptr, const char *option, char *buffer, int bufsize);
+int __cmdline_find_option_bool(u32 cmdline_ptr, const char *option);
+static inline int cmdline_find_option(const char *option, char *buffer, int bufsize)
+{
+ return __cmdline_find_option(boot_params.hdr.cmd_line_ptr, option, buffer, bufsize);
+}
+
+static inline int cmdline_find_option_bool(const char *option)
+{
+ return __cmdline_find_option_bool(boot_params.hdr.cmd_line_ptr, option);
+}
+

/* cpu.c, cpucheck.c */
struct cpu_features {
@@ -313,6 +309,10 @@ extern struct cpu_features cpu;
int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
int validate_cpu(void);

+/* early_serial_console.c */
+extern int early_serial_base;
+void console_init(void);
+
/* edd.c */
void query_edd(void);

@@ -348,7 +348,6 @@ unsigned int atou(const char *s);
unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base);

/* tty.c */
-void console_init(void);
void puts(const char *);
void putchar(int);
int getchar(void);
diff --git a/arch/x86/boot/cmdline.c b/arch/x86/boot/cmdline.c
index a1d3563..6b3b6f7 100644
--- a/arch/x86/boot/cmdline.c
+++ b/arch/x86/boot/cmdline.c
@@ -27,9 +27,8 @@ static inline int myisspace(u8 c)
* Returns the length of the argument (regardless of if it was
* truncated to fit in the buffer), or -1 on not found.
*/
-int cmdline_find_option(const char *option, char *buffer, int bufsize)
+int __cmdline_find_option(u32 cmdline_ptr, const char *option, char *buffer, int bufsize)
{
- u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
addr_t cptr;
char c;
int len = -1;
@@ -100,9 +99,8 @@ int cmdline_find_option(const char *option, char *buffer, int bufsize)
* Returns the position of that option (starts counting with 1)
* or 0 on not found
*/
-int cmdline_find_option_bool(const char *option)
+int __cmdline_find_option_bool(u32 cmdline_ptr, const char *option)
{
- u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
addr_t cptr;
char c;
int pos = 0, wstart = 0;
diff --git a/arch/x86/boot/early_serial_console.c b/arch/x86/boot/early_serial_console.c
new file mode 100644
index 0000000..030f4b9
--- /dev/null
+++ b/arch/x86/boot/early_serial_console.c
@@ -0,0 +1,139 @@
+#include "boot.h"
+
+#define DEFAULT_SERIAL_PORT 0x3f8 /* ttyS0 */
+
+#define XMTRDY 0x20
+
+#define DLAB 0x80
+
+#define TXR 0 /* Transmit register (WRITE) */
+#define RXR 0 /* Receive register (READ) */
+#define IER 1 /* Interrupt Enable */
+#define IIR 2 /* Interrupt ID */
+#define FCR 2 /* FIFO control */
+#define LCR 3 /* Line control */
+#define MCR 4 /* Modem control */
+#define LSR 5 /* Line Status */
+#define MSR 6 /* Modem Status */
+#define DLL 0 /* Divisor Latch Low */
+#define DLH 1 /* Divisor latch High */
+
+#define DEFAULT_BAUD 9600
+
+static void early_serial_init(int port, int baud)
+{
+ unsigned char c;
+ unsigned divisor;
+
+ outb(0x3, port + LCR); /* 8n1 */
+ outb(0, port + IER); /* no interrupt */
+ outb(0, port + FCR); /* no fifo */
+ outb(0x3, port + MCR); /* DTR + RTS */
+
+ divisor = 115200 / baud;
+ c = inb(port + LCR);
+ outb(c | DLAB, port + LCR);
+ outb(divisor & 0xff, port + DLL);
+ outb((divisor >> 8) & 0xff, port + DLH);
+ outb(c & ~DLAB, port + LCR);
+
+ early_serial_base = port;
+}
+
+static void parse_earlyprintk(void)
+{
+ int baud = DEFAULT_BAUD;
+ char arg[32];
+ int pos = 0;
+ int port = 0;
+
+ if (cmdline_find_option("earlyprintk", arg, sizeof arg) > 0) {
+ char *e;
+
+ if (!strncmp(arg, "serial", 6)) {
+ port = DEFAULT_SERIAL_PORT;
+ pos += 6;
+ }
+
+ if (arg[pos] == ',')
+ pos++;
+
+ if (!strncmp(arg, "ttyS", 4)) {
+ static const int bases[] = { 0x3f8, 0x2f8 };
+ int idx = 0;
+
+ if (!strncmp(arg + pos, "ttyS", 4))
+ pos += 4;
+
+ if (arg[pos++] == '1')
+ idx = 1;
+
+ port = bases[idx];
+ }
+
+ if (arg[pos] == ',')
+ pos++;
+
+ baud = simple_strtoull(arg + pos, &e, 0);
+ if (baud == 0 || arg + pos == e)
+ baud = DEFAULT_BAUD;
+ }
+
+ if (port)
+ early_serial_init(port, baud);
+}
+
+#define BASE_BAUD (1843200/16)
+static unsigned int probe_baud(int port)
+{
+ unsigned char lcr, dll, dlh;
+ unsigned int quot;
+
+ lcr = inb(port + LCR);
+ outb(lcr | DLAB, port + LCR);
+ dll = inb(port + DLL);
+ dlh = inb(port + DLH);
+ outb(lcr, port + LCR);
+ quot = (dlh << 8) | dll;
+
+ return BASE_BAUD / quot;
+}
+
+static void parse_console_uart8250(void)
+{
+ char optstr[64], *options;
+ int baud = DEFAULT_BAUD;
+ int port = 0;
+
+ /*
+ * console=uart8250,io,0x3f8,115200n8
+ * need to make sure it is last one console !
+ */
+ if (cmdline_find_option("console", optstr, sizeof optstr) <= 0)
+ return;
+
+ options = optstr;
+
+ if (!strncmp(options, "uart8250,io,", 12))
+ port = simple_strtoull(options + 12, &options, 0);
+ else if (!strncmp(options, "uart,io,", 8))
+ port = simple_strtoull(options + 8, &options, 0);
+ else
+ return;
+
+ if (options && (options[0] == ','))
+ baud = simple_strtoull(options + 1, &options, 0);
+ else
+ baud = probe_baud(port);
+
+ if (port)
+ early_serial_init(port, baud);
+}
+
+void console_init(void)
+{
+ parse_earlyprintk();
+
+ if (!early_serial_base)
+ parse_console_uart8250();
+}
diff --git a/arch/x86/boot/isdigit.h b/arch/x86/boot/isdigit.h
new file mode 100644
index 0000000..25e1340
--- /dev/null
+++ b/arch/x86/boot/isdigit.h
@@ -0,0 +1,21 @@
+#ifndef BOOT_ISDIGIT_H
+
+#define BOOT_ISDIGIT_H
+
+static inline int isdigit(int ch)
+{
+ return (ch >= '0') && (ch <= '9');
+}
+
+static inline int isxdigit(int ch)
+{
+ if (isdigit(ch))
+ return true;
+
+ if ((ch >= 'a') && (ch <= 'f'))
+ return true;
+
+ return (ch >= 'A') && (ch <= 'F');
+}
+
+#endif
diff --git a/arch/x86/boot/printf.c b/arch/x86/boot/printf.c
index 50e47cd..cdac91c 100644
--- a/arch/x86/boot/printf.c
+++ b/arch/x86/boot/printf.c
@@ -34,7 +34,7 @@ static int skip_atoi(const char **s)
#define SMALL 32 /* Must be 32 == 0x20 */
#define SPECIAL 64 /* 0x */

-#define do_div(n,base) ({ \
+#define __do_div(n, base) ({ \
int __res; \
__res = ((unsigned long) n) % (unsigned) base; \
n = ((unsigned long) n) / (unsigned) base; \
@@ -83,7 +83,7 @@ static char *number(char *str, long num, int base, int size, int precision,
tmp[i++] = '0';
else
while (num != 0)
- tmp[i++] = (digits[do_div(num, base)] | locase);
+ tmp[i++] = (digits[__do_div(num, base)] | locase);
if (i > precision)
precision = i;
size -= precision;
diff --git a/arch/x86/boot/tty.c b/arch/x86/boot/tty.c
index ff4b27a..def2451 100644
--- a/arch/x86/boot/tty.c
+++ b/arch/x86/boot/tty.c
@@ -15,27 +15,12 @@

#include "boot.h"

-#define DEFAULT_SERIAL_PORT 0x3f8 /* ttyS0 */
-
-static int early_serial_base;
+int early_serial_base;

#define XMTRDY 0x20

-#define DLAB 0x80
-
#define TXR 0 /* Transmit register (WRITE) */
-#define RXR 0 /* Receive register (READ) */
-#define IER 1 /* Interrupt Enable */
-#define IIR 2 /* Interrupt ID */
-#define FCR 2 /* FIFO control */
-#define LCR 3 /* Line control */
-#define MCR 4 /* Modem control */
#define LSR 5 /* Line Status */
-#define MSR 6 /* Modem Status */
-#define DLL 0 /* Divisor Latch Low */
-#define DLH 1 /* Divisor latch High */
-
-#define DEFAULT_BAUD 9600

/*
* These functions are in .inittext so they can be used to signal
@@ -152,122 +137,3 @@ int getchar_timeout(void)
return 0; /* Timeout! */
}

-static void early_serial_init(int port, int baud)
-{
- unsigned char c;
- unsigned divisor;
-
- outb(0x3, port + LCR); /* 8n1 */
- outb(0, port + IER); /* no interrupt */
- outb(0, port + FCR); /* no fifo */
- outb(0x3, port + MCR); /* DTR + RTS */
-
- divisor = 115200 / baud;
- c = inb(port + LCR);
- outb(c | DLAB, port + LCR);
- outb(divisor & 0xff, port + DLL);
- outb((divisor >> 8) & 0xff, port + DLH);
- outb(c & ~DLAB, port + LCR);
-
- early_serial_base = port;
-
- printf("Early serial console at I/O port 0x%x baud: %d\n", port, baud);
-}
-
-static void parse_earlyprintk(void)
-{
- int baud = DEFAULT_BAUD;
- char arg[32];
- int pos = 0;
- int port = 0;
-
- if (cmdline_find_option("earlyprintk", arg, sizeof arg) > 0) {
- char *e;
-
- if (!strncmp(arg, "serial", 6)) {
- port = DEFAULT_SERIAL_PORT;
- pos += 6;
- }
-
- if (arg[pos] == ',')
- pos++;
-
- if (!strncmp(arg, "ttyS", 4)) {
- static const int bases[] = { 0x3f8, 0x2f8 };
- int idx = 0;
-
- if (!strncmp(arg + pos, "ttyS", 4))
- pos += 4;
-
- if (arg[pos++] == '1')
- idx = 1;
-
- port = bases[idx];
- }
-
- if (arg[pos] == ',')
- pos++;
-
- baud = simple_strtoull(arg + pos, &e, 0);
- if (baud == 0 || arg + pos == e)
- baud = DEFAULT_BAUD;
- }
-
- if (port)
- early_serial_init(port, baud);
-}
-
-#define BASE_BAUD (1843200/16)
-static unsigned int probe_baud(int port)
-{
- unsigned char lcr, dll, dlh;
- unsigned int quot;
-
- lcr = inb(port + LCR);
- outb(lcr | DLAB, port + LCR);
- dll = inb(port + DLL);
- dlh = inb(port + DLH);
- outb(lcr, port + LCR);
- quot = (dlh << 8) | dll;
-
- return BASE_BAUD / quot;
-}
-
-static void parse_console_uart8250(void)
-{
- char optstr[64], *options;
- int baud = DEFAULT_BAUD;
- int port = 0;
-
- /*
- * console=uart8250,io,0x3f8,115200n8
- * need to make sure it is last one console !
- */
- if (cmdline_find_option("console", optstr, sizeof optstr) <= 0)
- return;
-
- options = optstr;
-
- if (!strncmp(options, "uart8250,io,", 12))
- port = simple_strtoull(options + 12, &options, 0);
- else if (!strncmp(options, "uart,io,", 8))
- port = simple_strtoull(options + 8, &options, 0);
- else
- return;
-
- if (options && (options[0] == ','))
- baud = simple_strtoull(options + 1, &options, 0);
- else
- baud = probe_baud(port);
-
- if (port)
- early_serial_init(port, baud);
-}
-
-void console_init(void)
-{
- parse_earlyprintk();
-
- if (!early_serial_base)
- parse_console_uart8250();
-}

2010-08-03 04:10:25

by H. Peter Anvin

[permalink] [raw]
Subject: [tip:x86/setup] x86, setup: move isdigit.h to ctype.h, header files on top.

Commit-ID: 6238b47b58480cd9c092600c05338dbe261b71ce
Gitweb: http://git.kernel.org/tip/6238b47b58480cd9c092600c05338dbe261b71ce
Author: H. Peter Anvin <[email protected]>
AuthorDate: Mon, 2 Aug 2010 21:03:46 -0700
Committer: H. Peter Anvin <[email protected]>
CommitDate: Mon, 2 Aug 2010 21:07:20 -0700

x86, setup: move isdigit.h to ctype.h, header files on top.

It is a subset of <ctype.h> functionality, so name it ctype.h. Also,
reorganize header files so #include statements are clustered near the
top as they should be.

Signed-off-by: H. Peter Anvin <[email protected]>
LKML-Reference: <[email protected]>
---
arch/x86/boot/boot.h | 3 +--
arch/x86/boot/compressed/misc.h | 1 +
arch/x86/boot/compressed/string.c | 2 --
arch/x86/boot/{isdigit.h => ctype.h} | 0
4 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index 00cf51c..c7093bd 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -28,6 +28,7 @@
#include "bitops.h"
#include <asm/cpufeature.h>
#include <asm/processor-flags.h>
+#include "ctype.h"

/* Useful macros */
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
@@ -200,8 +201,6 @@ static inline int memcmp_gs(const void *s1, addr_t s2, size_t len)
return diff;
}

-#include "isdigit.h"
-
/* Heap -- available for dynamic lists. */
extern char _end[];
extern char *HEAP;
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index a267849..3f19c81 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -20,6 +20,7 @@
#include <asm/bootparam.h>

#define BOOT_BOOT_H
+#include "../ctype.h"

/* misc.c */
extern struct boot_params *real_mode; /* Pointer to real-mode data */
diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c
index 7995c6a..19b3e69 100644
--- a/arch/x86/boot/compressed/string.c
+++ b/arch/x86/boot/compressed/string.c
@@ -1,4 +1,2 @@
#include "misc.h"
-
-#include "../isdigit.h"
#include "../string.c"
diff --git a/arch/x86/boot/isdigit.h b/arch/x86/boot/ctype.h
similarity index 100%
rename from arch/x86/boot/isdigit.h
rename to arch/x86/boot/ctype.h

2010-08-03 07:17:17

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH -v3] x86: Setup early console as early as possible


Analyze "console=uart8250,io,0x3f8,115200n8" in i386_start_kernel/x86_64_start_kernel,
and call setup_early_serial8250_console() to init early serial console.

only can handle io port kind of 8250. because mmio need ioremap.

-v2: use boot_params.hdr.version instead of adding another variable, Suggested by hpa
update after using x86 memblock patchset
-v3: x86 memblock can not make into with 2.6.36 now
so update this patch to be applied before x86 memblock patchset again.

Signed-off-by: Yinghai Lu <[email protected]>
---
arch/x86/include/asm/setup.h | 2 ++
arch/x86/kernel/head.c | 26 ++++++++++++++++++++++++++
arch/x86/kernel/head32.c | 2 ++
arch/x86/kernel/head64.c | 13 ++++++++++++-
kernel/printk.c | 4 ++++
5 files changed, 46 insertions(+), 1 deletion(-)

Index: linux-2.6/arch/x86/include/asm/setup.h
===================================================================
--- linux-2.6.orig/arch/x86/include/asm/setup.h
+++ linux-2.6/arch/x86/include/asm/setup.h
@@ -42,6 +42,8 @@ static inline void visws_early_detect(vo
#endif

extern unsigned long saved_video_mode;
+int setup_early_serial8250_console(char *cmdline);
+void setup_early_console(void);

extern void reserve_standard_io_resources(void);
extern void i386_reserve_resources(void);
Index: linux-2.6/arch/x86/kernel/head.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/head.c
+++ linux-2.6/arch/x86/kernel/head.c
@@ -53,3 +53,29 @@ void __init reserve_ebda_region(void)
/* reserve all memory between lowmem and the 1MB mark */
reserve_early_overlap_ok(lowmem, 0x100000, "BIOS reserved");
}
+
+void __init setup_early_console(void)
+{
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ char constr[64], *p, *q;
+
+ /* Can not handle mmio type 8250 uart yet, too early */
+ p = strstr(boot_command_line, "console=uart8250,io,");
+ if (!p)
+ p = strstr(boot_command_line, "console=uart,io,");
+ if (!p)
+ return;
+
+ p += 8; /* sizeof "console=" */
+ q = strchr(p, ' ');
+ if ((q - p) >= sizeof(constr))
+ return;
+
+ memset(constr, 0, sizeof(constr));
+ memcpy(constr, p, q - p);
+
+ lockdep_init();
+
+ setup_early_serial8250_console(constr);
+#endif
+}
Index: linux-2.6/arch/x86/kernel/head32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/head32.c
+++ linux-2.6/arch/x86/kernel/head32.c
@@ -30,6 +30,8 @@ static void __init i386_default_early_se

void __init i386_start_kernel(void)
{
+ setup_early_console();
+
#ifdef CONFIG_X86_TRAMPOLINE
/*
* But first pinch a few for the stack/trampoline stuff
Index: linux-2.6/arch/x86/kernel/head64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/head64.c
+++ linux-2.6/arch/x86/kernel/head64.c
@@ -73,6 +73,10 @@ void __init x86_64_start_kernel(char * r
/* clear bss before set_intr_gate with early_idt_handler */
clear_bss();

+ /* boot_params is in bss */
+ copy_bootdata(__va(real_mode_data));
+ setup_early_console();
+
/* Make NULL pointers segfault */
zap_identity_mappings();

@@ -96,7 +100,14 @@ void __init x86_64_start_kernel(char * r

void __init x86_64_start_reservations(char *real_mode_data)
{
- copy_bootdata(__va(real_mode_data));
+ /*
+ * hdr.version is always not 0, so check it to see
+ * if boot_params is copied or not.
+ */
+ if (!boot_params.hdr.version) {
+ copy_bootdata(__va(real_mode_data));
+ setup_early_console();
+ }

reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");

Index: linux-2.6/kernel/printk.c
===================================================================
--- linux-2.6.orig/kernel/printk.c
+++ linux-2.6/kernel/printk.c
@@ -1203,6 +1203,10 @@ void register_console(struct console *ne
if (console_drivers && newcon->flags & CON_BOOT) {
/* find the last or real console */
for_each_console(bcon) {
+ /* not again */
+ if (bcon == newcon)
+ return;
+
if (!(bcon->flags & CON_BOOT)) {
printk(KERN_INFO "Too late to register bootconsole %s%d\n",
newcon->name, newcon->index);

2010-08-03 09:06:22

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH -v3] x86: Setup early console as early as possible

On Tue, 03 Aug 2010 00:14:38 -0700 Yinghai Lu <[email protected]> wrote:

>
> Analyze "console=uart8250,io,0x3f8,115200n8" in i386_start_kernel/x86_64_start_kernel,
> and call setup_early_serial8250_console() to init early serial console.
>
> only can handle io port kind of 8250. because mmio need ioremap.
>
> -v2: use boot_params.hdr.version instead of adding another variable, Suggested by hpa
> update after using x86 memblock patchset
> -v3: x86 memblock can not make into with 2.6.36 now
> so update this patch to be applied before x86 memblock patchset again.
>
> ...
>
> --- linux-2.6.orig/kernel/printk.c
> +++ linux-2.6/kernel/printk.c
> @@ -1203,6 +1203,10 @@ void register_console(struct console *ne
> if (console_drivers && newcon->flags & CON_BOOT) {
> /* find the last or real console */
> for_each_console(bcon) {
> + /* not again */
> + if (bcon == newcon)
> + return;
> +
> if (!(bcon->flags & CON_BOOT)) {
> printk(KERN_INFO "Too late to register bootconsole %s%d\n",

Why this change?

2010-08-03 09:10:36

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH -v3] x86: Setup early console as early as possible

On 08/03/2010 02:06 AM, Andrew Morton wrote:
> On Tue, 03 Aug 2010 00:14:38 -0700 Yinghai Lu <[email protected]> wrote:
>
>>
>> Analyze "console=uart8250,io,0x3f8,115200n8" in i386_start_kernel/x86_64_start_kernel,
>> and call setup_early_serial8250_console() to init early serial console.
>>
>> only can handle io port kind of 8250. because mmio need ioremap.
>>
>> -v2: use boot_params.hdr.version instead of adding another variable, Suggested by hpa
>> update after using x86 memblock patchset
>> -v3: x86 memblock can not make into with 2.6.36 now
>> so update this patch to be applied before x86 memblock patchset again.
>>
>> ...
>>
>> --- linux-2.6.orig/kernel/printk.c
>> +++ linux-2.6/kernel/printk.c
>> @@ -1203,6 +1203,10 @@ void register_console(struct console *ne
>> if (console_drivers && newcon->flags & CON_BOOT) {
>> /* find the last or real console */
>> for_each_console(bcon) {
>> + /* not again */
>> + if (bcon == newcon)
>> + return;
>> +
>> if (!(bcon->flags & CON_BOOT)) {
>> printk(KERN_INFO "Too late to register bootconsole %s%d\n",
>
> Why this change?

it seems register the same console as early console will dead loop.

let me double check that again to see if can remove that change.

Yinghai

2010-08-03 10:16:08

by Yinghai Lu

[permalink] [raw]
Subject: Re: [PATCH -v3] x86: Setup early console as early as possible

On 08/03/2010 02:06 AM, Andrew Morton wrote:
> On Tue, 03 Aug 2010 00:14:38 -0700 Yinghai Lu <[email protected]> wrote:
>
>>
>> Analyze "console=uart8250,io,0x3f8,115200n8" in i386_start_kernel/x86_64_start_kernel,
>> and call setup_early_serial8250_console() to init early serial console.
>>
>> only can handle io port kind of 8250. because mmio need ioremap.
>>
>> -v2: use boot_params.hdr.version instead of adding another variable, Suggested by hpa
>> update after using x86 memblock patchset
>> -v3: x86 memblock can not make into with 2.6.36 now
>> so update this patch to be applied before x86 memblock patchset again.
>>
>> ...
>>
>> --- linux-2.6.orig/kernel/printk.c
>> +++ linux-2.6/kernel/printk.c
>> @@ -1203,6 +1203,10 @@ void register_console(struct console *ne
>> if (console_drivers && newcon->flags & CON_BOOT) {
>> /* find the last or real console */
>> for_each_console(bcon) {
>> + /* not again */
>> + if (bcon == newcon)
>> + return;
>> +
>> if (!(bcon->flags & CON_BOOT)) {
>> printk(KERN_INFO "Too late to register bootconsole %s%d\n",
>
> Why this change?

without that will get

early console in setup code
early console in decompress_kernel
decompress_kernel:
input: [0x24a0269-0x2e8b642], output: 0x1000000, heap: [0x2e90e40-0x2e97e3f]

Decompressing Linux... Parsing ELF... done.
Booting the kernel.
[ 0.000000] bootconsole [uart0] enabled
[ 0.000000] Kernel Layout:
[ 0.000000] .text: [0x01000000-0x01cb210d]
[ 0.000000] .rodata: [0x01cb8000-0x02419fff]
[ 0.000000] .data: [0x0241a000-0x025b583f]
[ 0.000000] .init: [0x025b7000-0x02875fff]
[ 0.000000] .bss: [0x02880000-0x0348bb6f]
[ 0.000000] .brk: [0x0348c000-0x034abfff]
[ 0.000000] memblock_x86_reserve_range: [0x01000000-0x0348bb6f] TEXT DATA BSS
[ 0.000000] memblock_x86_reserve_range: [0x2c6b0000-0x2ffcefff] RAMDISK
[ 0.000000] memblock_x86_reserve_range: [0x0009fc00-0x000fffff] * BIOS reserved
[ 0.000000] Initializing cgroup subsys cpuset
[ 0.000000] Initializing cgroup subsys cpu
[ 0.000000] Linux version 2.6.35-tip-yh-01758-g649ef4b-dirty (yhlu@linux-siqj) (gcc version 4.4.1 [gcc-4_4-branch revision 150839] (SUSE Linux) ) #148 SMP Tue Aug 3 03:09:06 PDT 2010
[ 0.000000] Command line: BOOT_IMAGE=linux debug apic=debug ramdisk_size=262144 root=/dev/ram0 rw ip=dhcp console=uart8250,io,0x3f8,115200 initrd=initrd.img
[ 0.000000] KERNEL supported cpus:
[ 0.000000] Intel GenuineIntel
[ 0.000000] AMD AuthenticAMD
[ 0.000000] Centaur CentaurHauls
[ 0.000000] BIOS-provided physical RAM map:
[ 0.000000] BIOS-e820: [0x00000000000000-0x0000000009efff] (usable)
[ 0.000000] BIOS-e820: [0x0000000009f000-0x0000000009ffff] (reserved)
[ 0.000000] BIOS-e820: [0x000000000e8000-0x000000000fffff] (reserved)
[ 0.000000] BIOS-e820: [0x00000000100000-0x0000002ffeffff] (usable)
[ 0.000000] BIOS-e820: [0x0000002fff0000-0x0000002fffffff] (ACPI data)
[ 0.000000] BIOS-e820: [0x000000fffbc000-0x000000ffffffff] (reserved)
[ 0.000000] Early serial console at I/O port 0x3f8 (options '115200')
[ 0.000000] Early serial console at I/O port 0x3f8 (options '115200')
[ 0.000000] Early serial console at I/O port 0x3f8 (options '115200')
[ 0.000000] Early serial console at I/O port 0x3f8 (options '115200')
....

2010-08-03 15:07:56

by Cyrill Gorcunov

[permalink] [raw]
Subject: Re: [PATCH -v3] x86: Setup early console as early as possible

On Tue, Aug 03, 2010 at 12:14:38AM -0700, Yinghai Lu wrote:
>
> Analyze "console=uart8250,io,0x3f8,115200n8" in i386_start_kernel/x86_64_start_kernel,
> and call setup_early_serial8250_console() to init early serial console.
>
> only can handle io port kind of 8250. because mmio need ioremap.
>
> -v2: use boot_params.hdr.version instead of adding another variable, Suggested by hpa
> update after using x86 memblock patchset
> -v3: x86 memblock can not make into with 2.6.36 now
> so update this patch to be applied before x86 memblock patchset again.
>
> Signed-off-by: Yinghai Lu <[email protected]>
> ---

Looks good to me, thanks Yinghai!

-- Cyrill