aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/boot/Makefile8
-rw-r--r--arch/x86/boot/boot.h35
-rw-r--r--arch/x86/boot/cmdline.c6
-rw-r--r--arch/x86/boot/early_serial_console.c139
-rw-r--r--arch/x86/boot/isdigit.h21
-rw-r--r--arch/x86/boot/printf.c4
-rw-r--r--arch/x86/boot/tty.c136
7 files changed, 186 insertions, 163 deletions
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index ec749c2bfdd7..f7cb086b4add 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -26,10 +26,10 @@ targets := vmlinux.bin setup.bin setup.elf bzImage
26targets += fdimage fdimage144 fdimage288 image.iso mtools.conf 26targets += fdimage fdimage144 fdimage288 image.iso mtools.conf
27subdir- := compressed 27subdir- := compressed
28 28
29setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o edd.o 29setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o
30setup-y += header.o main.o mca.o memory.o pm.o pmjump.o 30setup-y += early_serial_console.o edd.o header.o main.o mca.o memory.o
31setup-y += printf.o regs.o string.o tty.o video.o video-mode.o 31setup-y += pm.o pmjump.o printf.o regs.o string.o tty.o video.o
32setup-y += version.o 32setup-y += video-mode.o version.o
33setup-$(CONFIG_X86_APM_BOOT) += apm.o 33setup-$(CONFIG_X86_APM_BOOT) += apm.o
34 34
35# The link order of the video-*.o modules can matter. In particular, 35# 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 46c4c5c71af7..00cf51cfc2e6 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)
200 return diff; 200 return diff;
201} 201}
202 202
203static inline int isdigit(int ch) 203#include "isdigit.h"
204{
205 return (ch >= '0') && (ch <= '9');
206}
207
208static inline int isxdigit(int ch)
209{
210 if (isdigit(ch))
211 return true;
212
213 if ((ch >= 'a') && (ch <= 'f'))
214 return true;
215
216 return (ch >= 'A') && (ch <= 'F');
217}
218 204
219/* Heap -- available for dynamic lists. */ 205/* Heap -- available for dynamic lists. */
220extern char _end[]; 206extern char _end[];
@@ -300,8 +286,18 @@ struct biosregs {
300void intcall(u8 int_no, const struct biosregs *ireg, struct biosregs *oreg); 286void intcall(u8 int_no, const struct biosregs *ireg, struct biosregs *oreg);
301 287
302/* cmdline.c */ 288/* cmdline.c */
303int cmdline_find_option(const char *option, char *buffer, int bufsize); 289int __cmdline_find_option(u32 cmdline_ptr, const char *option, char *buffer, int bufsize);
304int cmdline_find_option_bool(const char *option); 290int __cmdline_find_option_bool(u32 cmdline_ptr, const char *option);
291static inline int cmdline_find_option(const char *option, char *buffer, int bufsize)
292{
293 return __cmdline_find_option(boot_params.hdr.cmd_line_ptr, option, buffer, bufsize);
294}
295
296static inline int cmdline_find_option_bool(const char *option)
297{
298 return __cmdline_find_option_bool(boot_params.hdr.cmd_line_ptr, option);
299}
300
305 301
306/* cpu.c, cpucheck.c */ 302/* cpu.c, cpucheck.c */
307struct cpu_features { 303struct cpu_features {
@@ -313,6 +309,10 @@ extern struct cpu_features cpu;
313int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr); 309int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
314int validate_cpu(void); 310int validate_cpu(void);
315 311
312/* early_serial_console.c */
313extern int early_serial_base;
314void console_init(void);
315
316/* edd.c */ 316/* edd.c */
317void query_edd(void); 317void query_edd(void);
318 318
@@ -348,7 +348,6 @@ unsigned int atou(const char *s);
348unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base); 348unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base);
349 349
350/* tty.c */ 350/* tty.c */
351void console_init(void);
352void puts(const char *); 351void puts(const char *);
353void putchar(int); 352void putchar(int);
354int getchar(void); 353int getchar(void);
diff --git a/arch/x86/boot/cmdline.c b/arch/x86/boot/cmdline.c
index a1d35634bce0..6b3b6f708c04 100644
--- a/arch/x86/boot/cmdline.c
+++ b/arch/x86/boot/cmdline.c
@@ -27,9 +27,8 @@ static inline int myisspace(u8 c)
27 * Returns the length of the argument (regardless of if it was 27 * Returns the length of the argument (regardless of if it was
28 * truncated to fit in the buffer), or -1 on not found. 28 * truncated to fit in the buffer), or -1 on not found.
29 */ 29 */
30int cmdline_find_option(const char *option, char *buffer, int bufsize) 30int __cmdline_find_option(u32 cmdline_ptr, const char *option, char *buffer, int bufsize)
31{ 31{
32 u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
33 addr_t cptr; 32 addr_t cptr;
34 char c; 33 char c;
35 int len = -1; 34 int len = -1;
@@ -100,9 +99,8 @@ int cmdline_find_option(const char *option, char *buffer, int bufsize)
100 * Returns the position of that option (starts counting with 1) 99 * Returns the position of that option (starts counting with 1)
101 * or 0 on not found 100 * or 0 on not found
102 */ 101 */
103int cmdline_find_option_bool(const char *option) 102int __cmdline_find_option_bool(u32 cmdline_ptr, const char *option)
104{ 103{
105 u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
106 addr_t cptr; 104 addr_t cptr;
107 char c; 105 char c;
108 int pos = 0, wstart = 0; 106 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 000000000000..030f4b93e255
--- /dev/null
+++ b/arch/x86/boot/early_serial_console.c
@@ -0,0 +1,139 @@
1#include "boot.h"
2
3#define DEFAULT_SERIAL_PORT 0x3f8 /* ttyS0 */
4
5#define XMTRDY 0x20
6
7#define DLAB 0x80
8
9#define TXR 0 /* Transmit register (WRITE) */
10#define RXR 0 /* Receive register (READ) */
11#define IER 1 /* Interrupt Enable */
12#define IIR 2 /* Interrupt ID */
13#define FCR 2 /* FIFO control */
14#define LCR 3 /* Line control */
15#define MCR 4 /* Modem control */
16#define LSR 5 /* Line Status */
17#define MSR 6 /* Modem Status */
18#define DLL 0 /* Divisor Latch Low */
19#define DLH 1 /* Divisor latch High */
20
21#define DEFAULT_BAUD 9600
22
23static void early_serial_init(int port, int baud)
24{
25 unsigned char c;
26 unsigned divisor;
27
28 outb(0x3, port + LCR); /* 8n1 */
29 outb(0, port + IER); /* no interrupt */
30 outb(0, port + FCR); /* no fifo */
31 outb(0x3, port + MCR); /* DTR + RTS */
32
33 divisor = 115200 / baud;
34 c = inb(port + LCR);
35 outb(c | DLAB, port + LCR);
36 outb(divisor & 0xff, port + DLL);
37 outb((divisor >> 8) & 0xff, port + DLH);
38 outb(c & ~DLAB, port + LCR);
39
40 early_serial_base = port;
41}
42
43static void parse_earlyprintk(void)
44{
45 int baud = DEFAULT_BAUD;
46 char arg[32];
47 int pos = 0;
48 int port = 0;
49
50 if (cmdline_find_option("earlyprintk", arg, sizeof arg) > 0) {
51 char *e;
52
53 if (!strncmp(arg, "serial", 6)) {
54 port = DEFAULT_SERIAL_PORT;
55 pos += 6;
56 }
57
58 if (arg[pos] == ',')
59 pos++;
60
61 if (!strncmp(arg, "ttyS", 4)) {
62 static const int bases[] = { 0x3f8, 0x2f8 };
63 int idx = 0;
64
65 if (!strncmp(arg + pos, "ttyS", 4))
66 pos += 4;
67
68 if (arg[pos++] == '1')
69 idx = 1;
70
71 port = bases[idx];
72 }
73
74 if (arg[pos] == ',')
75 pos++;
76
77 baud = simple_strtoull(arg + pos, &e, 0);
78 if (baud == 0 || arg + pos == e)
79 baud = DEFAULT_BAUD;
80 }
81
82 if (port)
83 early_serial_init(port, baud);
84}
85
86#define BASE_BAUD (1843200/16)
87static unsigned int probe_baud(int port)
88{
89 unsigned char lcr, dll, dlh;
90 unsigned int quot;
91
92 lcr = inb(port + LCR);
93 outb(lcr | DLAB, port + LCR);
94 dll = inb(port + DLL);
95 dlh = inb(port + DLH);
96 outb(lcr, port + LCR);
97 quot = (dlh << 8) | dll;
98
99 return BASE_BAUD / quot;
100}
101
102static void parse_console_uart8250(void)
103{
104 char optstr[64], *options;
105 int baud = DEFAULT_BAUD;
106 int port = 0;
107
108 /*
109 * console=uart8250,io,0x3f8,115200n8
110 * need to make sure it is last one console !
111 */
112 if (cmdline_find_option("console", optstr, sizeof optstr) <= 0)
113 return;
114
115 options = optstr;
116
117 if (!strncmp(options, "uart8250,io,", 12))
118 port = simple_strtoull(options + 12, &options, 0);
119 else if (!strncmp(options, "uart,io,", 8))
120 port = simple_strtoull(options + 8, &options, 0);
121 else
122 return;
123
124 if (options && (options[0] == ','))
125 baud = simple_strtoull(options + 1, &options, 0);
126 else
127 baud = probe_baud(port);
128
129 if (port)
130 early_serial_init(port, baud);
131}
132
133void console_init(void)
134{
135 parse_earlyprintk();
136
137 if (!early_serial_base)
138 parse_console_uart8250();
139}
diff --git a/arch/x86/boot/isdigit.h b/arch/x86/boot/isdigit.h
new file mode 100644
index 000000000000..25e13403193c
--- /dev/null
+++ b/arch/x86/boot/isdigit.h
@@ -0,0 +1,21 @@
1#ifndef BOOT_ISDIGIT_H
2
3#define BOOT_ISDIGIT_H
4
5static inline int isdigit(int ch)
6{
7 return (ch >= '0') && (ch <= '9');
8}
9
10static inline int isxdigit(int ch)
11{
12 if (isdigit(ch))
13 return true;
14
15 if ((ch >= 'a') && (ch <= 'f'))
16 return true;
17
18 return (ch >= 'A') && (ch <= 'F');
19}
20
21#endif
diff --git a/arch/x86/boot/printf.c b/arch/x86/boot/printf.c
index 50e47cdbdddd..cdac91ca55d3 100644
--- a/arch/x86/boot/printf.c
+++ b/arch/x86/boot/printf.c
@@ -34,7 +34,7 @@ static int skip_atoi(const char **s)
34#define SMALL 32 /* Must be 32 == 0x20 */ 34#define SMALL 32 /* Must be 32 == 0x20 */
35#define SPECIAL 64 /* 0x */ 35#define SPECIAL 64 /* 0x */
36 36
37#define do_div(n,base) ({ \ 37#define __do_div(n, base) ({ \
38int __res; \ 38int __res; \
39__res = ((unsigned long) n) % (unsigned) base; \ 39__res = ((unsigned long) n) % (unsigned) base; \
40n = ((unsigned long) n) / (unsigned) base; \ 40n = ((unsigned long) n) / (unsigned) base; \
@@ -83,7 +83,7 @@ static char *number(char *str, long num, int base, int size, int precision,
83 tmp[i++] = '0'; 83 tmp[i++] = '0';
84 else 84 else
85 while (num != 0) 85 while (num != 0)
86 tmp[i++] = (digits[do_div(num, base)] | locase); 86 tmp[i++] = (digits[__do_div(num, base)] | locase);
87 if (i > precision) 87 if (i > precision)
88 precision = i; 88 precision = i;
89 size -= precision; 89 size -= precision;
diff --git a/arch/x86/boot/tty.c b/arch/x86/boot/tty.c
index ff4b27a0fc5e..def2451f46ae 100644
--- a/arch/x86/boot/tty.c
+++ b/arch/x86/boot/tty.c
@@ -15,27 +15,12 @@
15 15
16#include "boot.h" 16#include "boot.h"
17 17
18#define DEFAULT_SERIAL_PORT 0x3f8 /* ttyS0 */ 18int early_serial_base;
19
20static int early_serial_base;
21 19
22#define XMTRDY 0x20 20#define XMTRDY 0x20
23 21
24#define DLAB 0x80
25
26#define TXR 0 /* Transmit register (WRITE) */ 22#define TXR 0 /* Transmit register (WRITE) */
27#define RXR 0 /* Receive register (READ) */
28#define IER 1 /* Interrupt Enable */
29#define IIR 2 /* Interrupt ID */
30#define FCR 2 /* FIFO control */
31#define LCR 3 /* Line control */
32#define MCR 4 /* Modem control */
33#define LSR 5 /* Line Status */ 23#define LSR 5 /* Line Status */
34#define MSR 6 /* Modem Status */
35#define DLL 0 /* Divisor Latch Low */
36#define DLH 1 /* Divisor latch High */
37
38#define DEFAULT_BAUD 9600
39 24
40/* 25/*
41 * These functions are in .inittext so they can be used to signal 26 * These functions are in .inittext so they can be used to signal
@@ -152,122 +137,3 @@ int getchar_timeout(void)
152 return 0; /* Timeout! */ 137 return 0; /* Timeout! */
153} 138}
154 139
155static void early_serial_init(int port, int baud)
156{
157 unsigned char c;
158 unsigned divisor;
159
160 outb(0x3, port + LCR); /* 8n1 */
161 outb(0, port + IER); /* no interrupt */
162 outb(0, port + FCR); /* no fifo */
163 outb(0x3, port + MCR); /* DTR + RTS */
164
165 divisor = 115200 / baud;
166 c = inb(port + LCR);
167 outb(c | DLAB, port + LCR);
168 outb(divisor & 0xff, port + DLL);
169 outb((divisor >> 8) & 0xff, port + DLH);
170 outb(c & ~DLAB, port + LCR);
171
172 early_serial_base = port;
173
174 printf("Early serial console at I/O port 0x%x baud: %d\n", port, baud);
175}
176
177static void parse_earlyprintk(void)
178{
179 int baud = DEFAULT_BAUD;
180 char arg[32];
181 int pos = 0;
182 int port = 0;
183
184 if (cmdline_find_option("earlyprintk", arg, sizeof arg) > 0) {
185 char *e;
186
187 if (!strncmp(arg, "serial", 6)) {
188 port = DEFAULT_SERIAL_PORT;
189 pos += 6;
190 }
191
192 if (arg[pos] == ',')
193 pos++;
194
195 if (!strncmp(arg, "ttyS", 4)) {
196 static const int bases[] = { 0x3f8, 0x2f8 };
197 int idx = 0;
198
199 if (!strncmp(arg + pos, "ttyS", 4))
200 pos += 4;
201
202 if (arg[pos++] == '1')
203 idx = 1;
204
205 port = bases[idx];
206 }
207
208 if (arg[pos] == ',')
209 pos++;
210
211 baud = simple_strtoull(arg + pos, &e, 0);
212 if (baud == 0 || arg + pos == e)
213 baud = DEFAULT_BAUD;
214 }
215
216 if (port)
217 early_serial_init(port, baud);
218}
219
220#define BASE_BAUD (1843200/16)
221static unsigned int probe_baud(int port)
222{
223 unsigned char lcr, dll, dlh;
224 unsigned int quot;
225
226 lcr = inb(port + LCR);
227 outb(lcr | DLAB, port + LCR);
228 dll = inb(port + DLL);
229 dlh = inb(port + DLH);
230 outb(lcr, port + LCR);
231 quot = (dlh << 8) | dll;
232
233 return BASE_BAUD / quot;
234}
235
236static void parse_console_uart8250(void)
237{
238 char optstr[64], *options;
239 int baud = DEFAULT_BAUD;
240 int port = 0;
241
242 /*
243 * console=uart8250,io,0x3f8,115200n8
244 * need to make sure it is last one console !
245 */
246 if (cmdline_find_option("console", optstr, sizeof optstr) <= 0)
247 return;
248
249 options = optstr;
250
251 if (!strncmp(options, "uart8250,io,", 12))
252 port = simple_strtoull(options + 12, &options, 0);
253 else if (!strncmp(options, "uart,io,", 8))
254 port = simple_strtoull(options + 8, &options, 0);
255 else
256 return;
257
258 if (options && (options[0] == ','))
259 baud = simple_strtoull(options + 1, &options, 0);
260 else
261 baud = probe_baud(port);
262
263 if (port)
264 early_serial_init(port, baud);
265}
266
267void console_init(void)
268{
269 parse_earlyprintk();
270
271 if (!early_serial_base)
272 parse_console_uart8250();
273}