aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/boot
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/boot')
-rw-r--r--arch/x86/boot/Makefile10
-rw-r--r--arch/x86/boot/apm.c3
-rw-r--r--arch/x86/boot/boot.h17
-rw-r--r--arch/x86/boot/cmdline.c65
-rw-r--r--arch/x86/boot/compressed/Makefile62
-rw-r--r--arch/x86/boot/compressed/Makefile_3250
-rw-r--r--arch/x86/boot/compressed/Makefile_6430
-rw-r--r--arch/x86/boot/compressed/misc.c (renamed from arch/x86/boot/compressed/misc_32.c)77
-rw-r--r--arch/x86/boot/compressed/misc_64.c371
-rw-r--r--arch/x86/boot/compressed/relocs.c7
-rw-r--r--arch/x86/boot/compressed/vmlinux.scr (renamed from arch/x86/boot/compressed/vmlinux_64.scr)2
-rw-r--r--arch/x86/boot/compressed/vmlinux_32.lds10
-rw-r--r--arch/x86/boot/compressed/vmlinux_32.scr10
-rw-r--r--arch/x86/boot/compressed/vmlinux_64.lds12
-rw-r--r--arch/x86/boot/edd.c13
-rw-r--r--arch/x86/boot/header.S5
-rw-r--r--arch/x86/boot/main.c31
-rw-r--r--arch/x86/boot/pm.c6
-rw-r--r--arch/x86/boot/pmjump.S54
-rw-r--r--arch/x86/boot/video-bios.c3
-rw-r--r--arch/x86/boot/video-vesa.c26
-rw-r--r--arch/x86/boot/video-vga.c20
-rw-r--r--arch/x86/boot/video.c33
-rw-r--r--arch/x86/boot/video.h3
-rw-r--r--arch/x86/boot/voyager.c4
25 files changed, 355 insertions, 569 deletions
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 7a3116ccf387..349b81a39c40 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -28,9 +28,11 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
28targets := vmlinux.bin setup.bin setup.elf zImage bzImage 28targets := vmlinux.bin setup.bin setup.elf zImage bzImage
29subdir- := compressed 29subdir- := compressed
30 30
31setup-y += a20.o apm.o cmdline.o copy.o cpu.o cpucheck.o edd.o 31setup-y += a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o
32setup-y += header.o main.o mca.o memory.o pm.o pmjump.o 32setup-y += header.o main.o mca.o memory.o pm.o pmjump.o
33setup-y += printf.o string.o tty.o video.o version.o voyager.o 33setup-y += printf.o string.o tty.o video.o version.o
34setup-$(CONFIG_X86_APM_BOOT) += apm.o
35setup-$(CONFIG_X86_VOYAGER) += voyager.o
34 36
35# The link order of the video-*.o modules can matter. In particular, 37# The link order of the video-*.o modules can matter. In particular,
36# video-vga.o *must* be listed first, followed by video-vesa.o. 38# video-vga.o *must* be listed first, followed by video-vesa.o.
@@ -49,10 +51,7 @@ HOSTCFLAGS_build.o := $(LINUXINCLUDE)
49 51
50# How to compile the 16-bit code. Note we always compile for -march=i386, 52# How to compile the 16-bit code. Note we always compile for -march=i386,
51# that way we can complain to the user if the CPU is insufficient. 53# that way we can complain to the user if the CPU is insufficient.
52cflags-$(CONFIG_X86_32) :=
53cflags-$(CONFIG_X86_64) := -m32
54KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \ 54KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
55 $(cflags-y) \
56 -Wall -Wstrict-prototypes \ 55 -Wall -Wstrict-prototypes \
57 -march=i386 -mregparm=3 \ 56 -march=i386 -mregparm=3 \
58 -include $(srctree)/$(src)/code16gcc.h \ 57 -include $(srctree)/$(src)/code16gcc.h \
@@ -62,6 +61,7 @@ KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
62 $(call cc-option, -fno-unit-at-a-time)) \ 61 $(call cc-option, -fno-unit-at-a-time)) \
63 $(call cc-option, -fno-stack-protector) \ 62 $(call cc-option, -fno-stack-protector) \
64 $(call cc-option, -mpreferred-stack-boundary=2) 63 $(call cc-option, -mpreferred-stack-boundary=2)
64KBUILD_CFLAGS += $(call cc-option,-m32)
65KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ 65KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
66 66
67$(obj)/zImage: IMAGE_OFFSET := 0x1000 67$(obj)/zImage: IMAGE_OFFSET := 0x1000
diff --git a/arch/x86/boot/apm.c b/arch/x86/boot/apm.c
index eab50c55a3a5..c117c7fb859c 100644
--- a/arch/x86/boot/apm.c
+++ b/arch/x86/boot/apm.c
@@ -19,8 +19,6 @@
19 19
20#include "boot.h" 20#include "boot.h"
21 21
22#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
23
24int query_apm_bios(void) 22int query_apm_bios(void)
25{ 23{
26 u16 ax, bx, cx, dx, di; 24 u16 ax, bx, cx, dx, di;
@@ -95,4 +93,3 @@ int query_apm_bios(void)
95 return 0; 93 return 0;
96} 94}
97 95
98#endif
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index d2b5adf46512..7822a4983da2 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -109,7 +109,7 @@ typedef unsigned int addr_t;
109static inline u8 rdfs8(addr_t addr) 109static inline u8 rdfs8(addr_t addr)
110{ 110{
111 u8 v; 111 u8 v;
112 asm volatile("movb %%fs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); 112 asm volatile("movb %%fs:%1,%0" : "=q" (v) : "m" (*(u8 *)addr));
113 return v; 113 return v;
114} 114}
115static inline u16 rdfs16(addr_t addr) 115static inline u16 rdfs16(addr_t addr)
@@ -127,21 +127,21 @@ static inline u32 rdfs32(addr_t addr)
127 127
128static inline void wrfs8(u8 v, addr_t addr) 128static inline void wrfs8(u8 v, addr_t addr)
129{ 129{
130 asm volatile("movb %1,%%fs:%0" : "+m" (*(u8 *)addr) : "r" (v)); 130 asm volatile("movb %1,%%fs:%0" : "+m" (*(u8 *)addr) : "qi" (v));
131} 131}
132static inline void wrfs16(u16 v, addr_t addr) 132static inline void wrfs16(u16 v, addr_t addr)
133{ 133{
134 asm volatile("movw %1,%%fs:%0" : "+m" (*(u16 *)addr) : "r" (v)); 134 asm volatile("movw %1,%%fs:%0" : "+m" (*(u16 *)addr) : "ri" (v));
135} 135}
136static inline void wrfs32(u32 v, addr_t addr) 136static inline void wrfs32(u32 v, addr_t addr)
137{ 137{
138 asm volatile("movl %1,%%fs:%0" : "+m" (*(u32 *)addr) : "r" (v)); 138 asm volatile("movl %1,%%fs:%0" : "+m" (*(u32 *)addr) : "ri" (v));
139} 139}
140 140
141static inline u8 rdgs8(addr_t addr) 141static inline u8 rdgs8(addr_t addr)
142{ 142{
143 u8 v; 143 u8 v;
144 asm volatile("movb %%gs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); 144 asm volatile("movb %%gs:%1,%0" : "=q" (v) : "m" (*(u8 *)addr));
145 return v; 145 return v;
146} 146}
147static inline u16 rdgs16(addr_t addr) 147static inline u16 rdgs16(addr_t addr)
@@ -159,15 +159,15 @@ static inline u32 rdgs32(addr_t addr)
159 159
160static inline void wrgs8(u8 v, addr_t addr) 160static inline void wrgs8(u8 v, addr_t addr)
161{ 161{
162 asm volatile("movb %1,%%gs:%0" : "+m" (*(u8 *)addr) : "r" (v)); 162 asm volatile("movb %1,%%gs:%0" : "+m" (*(u8 *)addr) : "qi" (v));
163} 163}
164static inline void wrgs16(u16 v, addr_t addr) 164static inline void wrgs16(u16 v, addr_t addr)
165{ 165{
166 asm volatile("movw %1,%%gs:%0" : "+m" (*(u16 *)addr) : "r" (v)); 166 asm volatile("movw %1,%%gs:%0" : "+m" (*(u16 *)addr) : "ri" (v));
167} 167}
168static inline void wrgs32(u32 v, addr_t addr) 168static inline void wrgs32(u32 v, addr_t addr)
169{ 169{
170 asm volatile("movl %1,%%gs:%0" : "+m" (*(u32 *)addr) : "r" (v)); 170 asm volatile("movl %1,%%gs:%0" : "+m" (*(u32 *)addr) : "ri" (v));
171} 171}
172 172
173/* Note: these only return true/false, not a signed return value! */ 173/* Note: these only return true/false, not a signed return value! */
@@ -241,6 +241,7 @@ int query_apm_bios(void);
241 241
242/* cmdline.c */ 242/* cmdline.c */
243int cmdline_find_option(const char *option, char *buffer, int bufsize); 243int cmdline_find_option(const char *option, char *buffer, int bufsize);
244int cmdline_find_option_bool(const char *option);
244 245
245/* cpu.c, cpucheck.c */ 246/* cpu.c, cpucheck.c */
246int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr); 247int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
diff --git a/arch/x86/boot/cmdline.c b/arch/x86/boot/cmdline.c
index 34bb778c4357..680408a0f463 100644
--- a/arch/x86/boot/cmdline.c
+++ b/arch/x86/boot/cmdline.c
@@ -95,3 +95,68 @@ int cmdline_find_option(const char *option, char *buffer, int bufsize)
95 95
96 return len; 96 return len;
97} 97}
98
99/*
100 * Find a boolean option (like quiet,noapic,nosmp....)
101 *
102 * Returns the position of that option (starts counting with 1)
103 * or 0 on not found
104 */
105int cmdline_find_option_bool(const char *option)
106{
107 u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
108 addr_t cptr;
109 char c;
110 int pos = 0, wstart = 0;
111 const char *opptr = NULL;
112 enum {
113 st_wordstart, /* Start of word/after whitespace */
114 st_wordcmp, /* Comparing this word */
115 st_wordskip, /* Miscompare, skip */
116 } state = st_wordstart;
117
118 if (!cmdline_ptr || cmdline_ptr >= 0x100000)
119 return -1; /* No command line, or inaccessible */
120
121 cptr = cmdline_ptr & 0xf;
122 set_fs(cmdline_ptr >> 4);
123
124 while (cptr < 0x10000) {
125 c = rdfs8(cptr++);
126 pos++;
127
128 switch (state) {
129 case st_wordstart:
130 if (!c)
131 return 0;
132 else if (myisspace(c))
133 break;
134
135 state = st_wordcmp;
136 opptr = option;
137 wstart = pos;
138 /* fall through */
139
140 case st_wordcmp:
141 if (!*opptr)
142 if (!c || myisspace(c))
143 return wstart;
144 else
145 state = st_wordskip;
146 else if (!c)
147 return 0;
148 else if (c != *opptr++)
149 state = st_wordskip;
150 break;
151
152 case st_wordskip:
153 if (!c)
154 return 0;
155 else if (myisspace(c))
156 state = st_wordstart;
157 break;
158 }
159 }
160
161 return 0; /* Buffer overrun */
162}
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 52c1db854520..fe24ceabd909 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -1,5 +1,63 @@
1#
2# linux/arch/x86/boot/compressed/Makefile
3#
4# create a compressed vmlinux image from the original vmlinux
5#
6
7targets := vmlinux vmlinux.bin vmlinux.bin.gz head_$(BITS).o misc.o piggy.o
8
9KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
10KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
11cflags-$(CONFIG_X86_64) := -mcmodel=small
12KBUILD_CFLAGS += $(cflags-y)
13KBUILD_CFLAGS += $(call cc-option,-ffreestanding)
14KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector)
15
16KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
17
18LDFLAGS := -m elf_$(UTS_MACHINE)
19LDFLAGS_vmlinux := -T
20
21$(obj)/vmlinux: $(src)/vmlinux_$(BITS).lds $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/piggy.o FORCE
22 $(call if_changed,ld)
23 @:
24
25$(obj)/vmlinux.bin: vmlinux FORCE
26 $(call if_changed,objcopy)
27
28
1ifeq ($(CONFIG_X86_32),y) 29ifeq ($(CONFIG_X86_32),y)
2include ${srctree}/arch/x86/boot/compressed/Makefile_32 30targets += vmlinux.bin.all vmlinux.relocs
31hostprogs-y := relocs
32
33quiet_cmd_relocs = RELOCS $@
34 cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $<
35$(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE
36 $(call if_changed,relocs)
37
38vmlinux.bin.all-y := $(obj)/vmlinux.bin
39vmlinux.bin.all-$(CONFIG_RELOCATABLE) += $(obj)/vmlinux.relocs
40quiet_cmd_relocbin = BUILD $@
41 cmd_relocbin = cat $(filter-out FORCE,$^) > $@
42$(obj)/vmlinux.bin.all: $(vmlinux.bin.all-y) FORCE
43 $(call if_changed,relocbin)
44
45ifdef CONFIG_RELOCATABLE
46$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE
47 $(call if_changed,gzip)
3else 48else
4include ${srctree}/arch/x86/boot/compressed/Makefile_64 49$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
50 $(call if_changed,gzip)
5endif 51endif
52LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
53
54else
55$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
56 $(call if_changed,gzip)
57
58LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T
59endif
60
61
62$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
63 $(call if_changed,ld)
diff --git a/arch/x86/boot/compressed/Makefile_32 b/arch/x86/boot/compressed/Makefile_32
deleted file mode 100644
index e43ff7c56e6e..000000000000
--- a/arch/x86/boot/compressed/Makefile_32
+++ /dev/null
@@ -1,50 +0,0 @@
1#
2# linux/arch/x86/boot/compressed/Makefile
3#
4# create a compressed vmlinux image from the original vmlinux
5#
6
7targets := vmlinux vmlinux.bin vmlinux.bin.gz head_32.o misc_32.o piggy.o \
8 vmlinux.bin.all vmlinux.relocs
9EXTRA_AFLAGS := -traditional
10
11LDFLAGS_vmlinux := -T
12hostprogs-y := relocs
13
14KBUILD_CFLAGS := -m32 -D__KERNEL__ $(LINUX_INCLUDE) -O2 \
15 -fno-strict-aliasing -fPIC \
16 $(call cc-option,-ffreestanding) \
17 $(call cc-option,-fno-stack-protector)
18LDFLAGS := -m elf_i386
19
20$(obj)/vmlinux: $(src)/vmlinux_32.lds $(obj)/head_32.o $(obj)/misc_32.o $(obj)/piggy.o FORCE
21 $(call if_changed,ld)
22 @:
23
24$(obj)/vmlinux.bin: vmlinux FORCE
25 $(call if_changed,objcopy)
26
27quiet_cmd_relocs = RELOCS $@
28 cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $<
29$(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE
30 $(call if_changed,relocs)
31
32vmlinux.bin.all-y := $(obj)/vmlinux.bin
33vmlinux.bin.all-$(CONFIG_RELOCATABLE) += $(obj)/vmlinux.relocs
34quiet_cmd_relocbin = BUILD $@
35 cmd_relocbin = cat $(filter-out FORCE,$^) > $@
36$(obj)/vmlinux.bin.all: $(vmlinux.bin.all-y) FORCE
37 $(call if_changed,relocbin)
38
39ifdef CONFIG_RELOCATABLE
40$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE
41 $(call if_changed,gzip)
42else
43$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
44 $(call if_changed,gzip)
45endif
46
47LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
48
49$(obj)/piggy.o: $(src)/vmlinux_32.scr $(obj)/vmlinux.bin.gz FORCE
50 $(call if_changed,ld)
diff --git a/arch/x86/boot/compressed/Makefile_64 b/arch/x86/boot/compressed/Makefile_64
deleted file mode 100644
index 7801e8dd90b2..000000000000
--- a/arch/x86/boot/compressed/Makefile_64
+++ /dev/null
@@ -1,30 +0,0 @@
1#
2# linux/arch/x86/boot/compressed/Makefile
3#
4# create a compressed vmlinux image from the original vmlinux
5#
6
7targets := vmlinux vmlinux.bin vmlinux.bin.gz head_64.o misc_64.o piggy.o
8
9KBUILD_CFLAGS := -m64 -D__KERNEL__ $(LINUXINCLUDE) -O2 \
10 -fno-strict-aliasing -fPIC -mcmodel=small \
11 $(call cc-option, -ffreestanding) \
12 $(call cc-option, -fno-stack-protector)
13KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
14LDFLAGS := -m elf_x86_64
15
16LDFLAGS_vmlinux := -T
17$(obj)/vmlinux: $(src)/vmlinux_64.lds $(obj)/head_64.o $(obj)/misc_64.o $(obj)/piggy.o FORCE
18 $(call if_changed,ld)
19 @:
20
21$(obj)/vmlinux.bin: vmlinux FORCE
22 $(call if_changed,objcopy)
23
24$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
25 $(call if_changed,gzip)
26
27LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T
28
29$(obj)/piggy.o: $(obj)/vmlinux_64.scr $(obj)/vmlinux.bin.gz FORCE
30 $(call if_changed,ld)
diff --git a/arch/x86/boot/compressed/misc_32.c b/arch/x86/boot/compressed/misc.c
index b74d60d1b2fa..8182e32c1b42 100644
--- a/arch/x86/boot/compressed/misc_32.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * misc.c 2 * misc.c
3 * 3 *
4 * This is a collection of several routines from gzip-1.0.3 4 * This is a collection of several routines from gzip-1.0.3
5 * adapted for Linux. 5 * adapted for Linux.
6 * 6 *
7 * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 7 * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
@@ -9,9 +9,18 @@
9 * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 9 * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
10 */ 10 */
11 11
12/*
13 * we have to be careful, because no indirections are allowed here, and
14 * paravirt_ops is a kind of one. As it will only run in baremetal anyway,
15 * we just keep it from happening
16 */
12#undef CONFIG_PARAVIRT 17#undef CONFIG_PARAVIRT
18#ifdef CONFIG_X86_64
19#define _LINUX_STRING_H_ 1
20#define __LINUX_BITMAP_H 1
21#endif
22
13#include <linux/linkage.h> 23#include <linux/linkage.h>
14#include <linux/vmalloc.h>
15#include <linux/screen_info.h> 24#include <linux/screen_info.h>
16#include <asm/io.h> 25#include <asm/io.h>
17#include <asm/page.h> 26#include <asm/page.h>
@@ -186,10 +195,20 @@ static void *memcpy(void *dest, const void *src, unsigned n);
186 195
187static void putstr(const char *); 196static void putstr(const char *);
188 197
189static unsigned long free_mem_ptr; 198#ifdef CONFIG_X86_64
190static unsigned long free_mem_end_ptr; 199#define memptr long
200#else
201#define memptr unsigned
202#endif
203
204static memptr free_mem_ptr;
205static memptr free_mem_end_ptr;
191 206
207#ifdef CONFIG_X86_64
208#define HEAP_SIZE 0x7000
209#else
192#define HEAP_SIZE 0x4000 210#define HEAP_SIZE 0x4000
211#endif
193 212
194static char *vidmem = (char *)0xb8000; 213static char *vidmem = (char *)0xb8000;
195static int vidport; 214static int vidport;
@@ -230,7 +249,7 @@ static void gzip_mark(void **ptr)
230 249
231static void gzip_release(void **ptr) 250static void gzip_release(void **ptr)
232{ 251{
233 free_mem_ptr = (unsigned long) *ptr; 252 free_mem_ptr = (memptr) *ptr;
234} 253}
235 254
236static void scroll(void) 255static void scroll(void)
@@ -247,8 +266,10 @@ static void putstr(const char *s)
247 int x,y,pos; 266 int x,y,pos;
248 char c; 267 char c;
249 268
269#ifdef CONFIG_X86_32
250 if (RM_SCREEN_INFO.orig_video_mode == 0 && lines == 0 && cols == 0) 270 if (RM_SCREEN_INFO.orig_video_mode == 0 && lines == 0 && cols == 0)
251 return; 271 return;
272#endif
252 273
253 x = RM_SCREEN_INFO.orig_x; 274 x = RM_SCREEN_INFO.orig_x;
254 y = RM_SCREEN_INFO.orig_y; 275 y = RM_SCREEN_INFO.orig_y;
@@ -261,7 +282,7 @@ static void putstr(const char *s)
261 y--; 282 y--;
262 } 283 }
263 } else { 284 } else {
264 vidmem [ ( x + cols * y ) * 2 ] = c; 285 vidmem [(x + cols * y) * 2] = c;
265 if ( ++x >= cols ) { 286 if ( ++x >= cols ) {
266 x = 0; 287 x = 0;
267 if ( ++y >= lines ) { 288 if ( ++y >= lines ) {
@@ -276,16 +297,16 @@ static void putstr(const char *s)
276 RM_SCREEN_INFO.orig_y = y; 297 RM_SCREEN_INFO.orig_y = y;
277 298
278 pos = (x + cols * y) * 2; /* Update cursor position */ 299 pos = (x + cols * y) * 2; /* Update cursor position */
279 outb_p(14, vidport); 300 outb(14, vidport);
280 outb_p(0xff & (pos >> 9), vidport+1); 301 outb(0xff & (pos >> 9), vidport+1);
281 outb_p(15, vidport); 302 outb(15, vidport);
282 outb_p(0xff & (pos >> 1), vidport+1); 303 outb(0xff & (pos >> 1), vidport+1);
283} 304}
284 305
285static void* memset(void* s, int c, unsigned n) 306static void* memset(void* s, int c, unsigned n)
286{ 307{
287 int i; 308 int i;
288 char *ss = (char*)s; 309 char *ss = s;
289 310
290 for (i=0;i<n;i++) ss[i] = c; 311 for (i=0;i<n;i++) ss[i] = c;
291 return s; 312 return s;
@@ -294,7 +315,8 @@ static void* memset(void* s, int c, unsigned n)
294static void* memcpy(void* dest, const void* src, unsigned n) 315static void* memcpy(void* dest, const void* src, unsigned n)
295{ 316{
296 int i; 317 int i;
297 char *d = (char *)dest, *s = (char *)src; 318 const char *s = src;
319 char *d = dest;
298 320
299 for (i=0;i<n;i++) d[i] = s[i]; 321 for (i=0;i<n;i++) d[i] = s[i];
300 return dest; 322 return dest;
@@ -339,11 +361,13 @@ static void error(char *x)
339 putstr(x); 361 putstr(x);
340 putstr("\n\n -- System halted"); 362 putstr("\n\n -- System halted");
341 363
342 while(1); /* Halt */ 364 while (1)
365 asm("hlt");
343} 366}
344 367
345asmlinkage void decompress_kernel(void *rmode, unsigned long end, 368asmlinkage void decompress_kernel(void *rmode, memptr heap,
346 uch *input_data, unsigned long input_len, uch *output) 369 uch *input_data, unsigned long input_len,
370 uch *output)
347{ 371{
348 real_mode = rmode; 372 real_mode = rmode;
349 373
@@ -358,25 +382,32 @@ asmlinkage void decompress_kernel(void *rmode, unsigned long end,
358 lines = RM_SCREEN_INFO.orig_video_lines; 382 lines = RM_SCREEN_INFO.orig_video_lines;
359 cols = RM_SCREEN_INFO.orig_video_cols; 383 cols = RM_SCREEN_INFO.orig_video_cols;
360 384
361 window = output; /* Output buffer (Normally at 1M) */ 385 window = output; /* Output buffer (Normally at 1M) */
362 free_mem_ptr = end; /* Heap */ 386 free_mem_ptr = heap; /* Heap */
363 free_mem_end_ptr = end + HEAP_SIZE; 387 free_mem_end_ptr = heap + HEAP_SIZE;
364 inbuf = input_data; /* Input buffer */ 388 inbuf = input_data; /* Input buffer */
365 insize = input_len; 389 insize = input_len;
366 inptr = 0; 390 inptr = 0;
367 391
392#ifdef CONFIG_X86_64
393 if ((ulg)output & (__KERNEL_ALIGN - 1))
394 error("Destination address not 2M aligned");
395 if ((ulg)output >= 0xffffffffffUL)
396 error("Destination address too large");
397#else
368 if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1)) 398 if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
369 error("Destination address not CONFIG_PHYSICAL_ALIGN aligned"); 399 error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
370 if (end > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff)) 400 if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff))
371 error("Destination address too large"); 401 error("Destination address too large");
372#ifndef CONFIG_RELOCATABLE 402#ifndef CONFIG_RELOCATABLE
373 if ((u32)output != LOAD_PHYSICAL_ADDR) 403 if ((u32)output != LOAD_PHYSICAL_ADDR)
374 error("Wrong destination address"); 404 error("Wrong destination address");
375#endif 405#endif
406#endif
376 407
377 makecrc(); 408 makecrc();
378 putstr("Uncompressing Linux... "); 409 putstr("\nDecompressing Linux... ");
379 gunzip(); 410 gunzip();
380 putstr("Ok, booting the kernel.\n"); 411 putstr("done.\nBooting the kernel.\n");
381 return; 412 return;
382} 413}
diff --git a/arch/x86/boot/compressed/misc_64.c b/arch/x86/boot/compressed/misc_64.c
deleted file mode 100644
index 6ea015aa65e4..000000000000
--- a/arch/x86/boot/compressed/misc_64.c
+++ /dev/null
@@ -1,371 +0,0 @@
1/*
2 * misc.c
3 *
4 * This is a collection of several routines from gzip-1.0.3
5 * adapted for Linux.
6 *
7 * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
8 * puts by Nick Holloway 1993, better puts by Martin Mares 1995
9 * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
10 */
11
12#define _LINUX_STRING_H_ 1
13#define __LINUX_BITMAP_H 1
14
15#include <linux/linkage.h>
16#include <linux/screen_info.h>
17#include <asm/io.h>
18#include <asm/page.h>
19
20/* WARNING!!
21 * This code is compiled with -fPIC and it is relocated dynamically
22 * at run time, but no relocation processing is performed.
23 * This means that it is not safe to place pointers in static structures.
24 */
25
26/*
27 * Getting to provable safe in place decompression is hard.
28 * Worst case behaviours need to be analyzed.
29 * Background information:
30 *
31 * The file layout is:
32 * magic[2]
33 * method[1]
34 * flags[1]
35 * timestamp[4]
36 * extraflags[1]
37 * os[1]
38 * compressed data blocks[N]
39 * crc[4] orig_len[4]
40 *
41 * resulting in 18 bytes of non compressed data overhead.
42 *
43 * Files divided into blocks
44 * 1 bit (last block flag)
45 * 2 bits (block type)
46 *
47 * 1 block occurs every 32K -1 bytes or when there 50% compression has been achieved.
48 * The smallest block type encoding is always used.
49 *
50 * stored:
51 * 32 bits length in bytes.
52 *
53 * fixed:
54 * magic fixed tree.
55 * symbols.
56 *
57 * dynamic:
58 * dynamic tree encoding.
59 * symbols.
60 *
61 *
62 * The buffer for decompression in place is the length of the
63 * uncompressed data, plus a small amount extra to keep the algorithm safe.
64 * The compressed data is placed at the end of the buffer. The output
65 * pointer is placed at the start of the buffer and the input pointer
66 * is placed where the compressed data starts. Problems will occur
67 * when the output pointer overruns the input pointer.
68 *
69 * The output pointer can only overrun the input pointer if the input
70 * pointer is moving faster than the output pointer. A condition only
71 * triggered by data whose compressed form is larger than the uncompressed
72 * form.
73 *
74 * The worst case at the block level is a growth of the compressed data
75 * of 5 bytes per 32767 bytes.
76 *
77 * The worst case internal to a compressed block is very hard to figure.
78 * The worst case can at least be boundined by having one bit that represents
79 * 32764 bytes and then all of the rest of the bytes representing the very
80 * very last byte.
81 *
82 * All of which is enough to compute an amount of extra data that is required
83 * to be safe. To avoid problems at the block level allocating 5 extra bytes
84 * per 32767 bytes of data is sufficient. To avoind problems internal to a block
85 * adding an extra 32767 bytes (the worst case uncompressed block size) is
86 * sufficient, to ensure that in the worst case the decompressed data for
87 * block will stop the byte before the compressed data for a block begins.
88 * To avoid problems with the compressed data's meta information an extra 18
89 * bytes are needed. Leading to the formula:
90 *
91 * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size.
92 *
93 * Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
94 * Adding 32768 instead of 32767 just makes for round numbers.
95 * Adding the decompressor_size is necessary as it musht live after all
96 * of the data as well. Last I measured the decompressor is about 14K.
97 * 10K of actual data and 4K of bss.
98 *
99 */
100
101/*
102 * gzip declarations
103 */
104
105#define OF(args) args
106#define STATIC static
107
108#undef memset
109#undef memcpy
110#define memzero(s, n) memset ((s), 0, (n))
111
112typedef unsigned char uch;
113typedef unsigned short ush;
114typedef unsigned long ulg;
115
116#define WSIZE 0x80000000 /* Window size must be at least 32k,
117 * and a power of two
118 * We don't actually have a window just
119 * a huge output buffer so I report
120 * a 2G windows size, as that should
121 * always be larger than our output buffer.
122 */
123
124static uch *inbuf; /* input buffer */
125static uch *window; /* Sliding window buffer, (and final output buffer) */
126
127static unsigned insize; /* valid bytes in inbuf */
128static unsigned inptr; /* index of next byte to be processed in inbuf */
129static unsigned outcnt; /* bytes in output buffer */
130
131/* gzip flag byte */
132#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
133#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
134#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
135#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
136#define COMMENT 0x10 /* bit 4 set: file comment present */
137#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
138#define RESERVED 0xC0 /* bit 6,7: reserved */
139
140#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
141
142/* Diagnostic functions */
143#ifdef DEBUG
144# define Assert(cond,msg) {if(!(cond)) error(msg);}
145# define Trace(x) fprintf x
146# define Tracev(x) {if (verbose) fprintf x ;}
147# define Tracevv(x) {if (verbose>1) fprintf x ;}
148# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
149# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
150#else
151# define Assert(cond,msg)
152# define Trace(x)
153# define Tracev(x)
154# define Tracevv(x)
155# define Tracec(c,x)
156# define Tracecv(c,x)
157#endif
158
159static int fill_inbuf(void);
160static void flush_window(void);
161static void error(char *m);
162static void gzip_mark(void **);
163static void gzip_release(void **);
164
165/*
166 * This is set up by the setup-routine at boot-time
167 */
168static unsigned char *real_mode; /* Pointer to real-mode data */
169
170#define RM_EXT_MEM_K (*(unsigned short *)(real_mode + 0x2))
171#ifndef STANDARD_MEMORY_BIOS_CALL
172#define RM_ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0))
173#endif
174#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
175
176extern unsigned char input_data[];
177extern int input_len;
178
179static long bytes_out = 0;
180
181static void *malloc(int size);
182static void free(void *where);
183
184static void *memset(void *s, int c, unsigned n);
185static void *memcpy(void *dest, const void *src, unsigned n);
186
187static void putstr(const char *);
188
189static long free_mem_ptr;
190static long free_mem_end_ptr;
191
192#define HEAP_SIZE 0x7000
193
194static char *vidmem = (char *)0xb8000;
195static int vidport;
196static int lines, cols;
197
198#include "../../../../lib/inflate.c"
199
200static void *malloc(int size)
201{
202 void *p;
203
204 if (size <0) error("Malloc error");
205 if (free_mem_ptr <= 0) error("Memory error");
206
207 free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
208
209 p = (void *)free_mem_ptr;
210 free_mem_ptr += size;
211
212 if (free_mem_ptr >= free_mem_end_ptr)
213 error("Out of memory");
214
215 return p;
216}
217
218static void free(void *where)
219{ /* Don't care */
220}
221
222static void gzip_mark(void **ptr)
223{
224 *ptr = (void *) free_mem_ptr;
225}
226
227static void gzip_release(void **ptr)
228{
229 free_mem_ptr = (long) *ptr;
230}
231
232static void scroll(void)
233{
234 int i;
235
236 memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
237 for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
238 vidmem[i] = ' ';
239}
240
241static void putstr(const char *s)
242{
243 int x,y,pos;
244 char c;
245
246 x = RM_SCREEN_INFO.orig_x;
247 y = RM_SCREEN_INFO.orig_y;
248
249 while ( ( c = *s++ ) != '\0' ) {
250 if ( c == '\n' ) {
251 x = 0;
252 if ( ++y >= lines ) {
253 scroll();
254 y--;
255 }
256 } else {
257 vidmem [ ( x + cols * y ) * 2 ] = c;
258 if ( ++x >= cols ) {
259 x = 0;
260 if ( ++y >= lines ) {
261 scroll();
262 y--;
263 }
264 }
265 }
266 }
267
268 RM_SCREEN_INFO.orig_x = x;
269 RM_SCREEN_INFO.orig_y = y;
270
271 pos = (x + cols * y) * 2; /* Update cursor position */
272 outb_p(14, vidport);
273 outb_p(0xff & (pos >> 9), vidport+1);
274 outb_p(15, vidport);
275 outb_p(0xff & (pos >> 1), vidport+1);
276}
277
278static void* memset(void* s, int c, unsigned n)
279{
280 int i;
281 char *ss = (char*)s;
282
283 for (i=0;i<n;i++) ss[i] = c;
284 return s;
285}
286
287static void* memcpy(void* dest, const void* src, unsigned n)
288{
289 int i;
290 char *d = (char *)dest, *s = (char *)src;
291
292 for (i=0;i<n;i++) d[i] = s[i];
293 return dest;
294}
295
296/* ===========================================================================
297 * Fill the input buffer. This is called only when the buffer is empty
298 * and at least one byte is really needed.
299 */
300static int fill_inbuf(void)
301{
302 error("ran out of input data");
303 return 0;
304}
305
306/* ===========================================================================
307 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
308 * (Used for the decompressed data only.)
309 */
310static void flush_window(void)
311{
312 /* With my window equal to my output buffer
313 * I only need to compute the crc here.
314 */
315 ulg c = crc; /* temporary variable */
316 unsigned n;
317 uch *in, ch;
318
319 in = window;
320 for (n = 0; n < outcnt; n++) {
321 ch = *in++;
322 c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
323 }
324 crc = c;
325 bytes_out += (ulg)outcnt;
326 outcnt = 0;
327}
328
329static void error(char *x)
330{
331 putstr("\n\n");
332 putstr(x);
333 putstr("\n\n -- System halted");
334
335 while(1); /* Halt */
336}
337
338asmlinkage void decompress_kernel(void *rmode, unsigned long heap,
339 uch *input_data, unsigned long input_len, uch *output)
340{
341 real_mode = rmode;
342
343 if (RM_SCREEN_INFO.orig_video_mode == 7) {
344 vidmem = (char *) 0xb0000;
345 vidport = 0x3b4;
346 } else {
347 vidmem = (char *) 0xb8000;
348 vidport = 0x3d4;
349 }
350
351 lines = RM_SCREEN_INFO.orig_video_lines;
352 cols = RM_SCREEN_INFO.orig_video_cols;
353
354 window = output; /* Output buffer (Normally at 1M) */
355 free_mem_ptr = heap; /* Heap */
356 free_mem_end_ptr = heap + HEAP_SIZE;
357 inbuf = input_data; /* Input buffer */
358 insize = input_len;
359 inptr = 0;
360
361 if ((ulg)output & (__KERNEL_ALIGN - 1))
362 error("Destination address not 2M aligned");
363 if ((ulg)output >= 0xffffffffffUL)
364 error("Destination address too large");
365
366 makecrc();
367 putstr(".\nDecompressing Linux...");
368 gunzip();
369 putstr("done.\nBooting the kernel.\n");
370 return;
371}
diff --git a/arch/x86/boot/compressed/relocs.c b/arch/x86/boot/compressed/relocs.c
index 7a0d00b2cf28..d01ea42187e6 100644
--- a/arch/x86/boot/compressed/relocs.c
+++ b/arch/x86/boot/compressed/relocs.c
@@ -27,11 +27,6 @@ static unsigned long *relocs;
27 * absolute relocations present w.r.t these symbols. 27 * absolute relocations present w.r.t these symbols.
28 */ 28 */
29static const char* safe_abs_relocs[] = { 29static const char* safe_abs_relocs[] = {
30 "__kernel_vsyscall",
31 "__kernel_rt_sigreturn",
32 "__kernel_sigreturn",
33 "SYSENTER_RETURN",
34 "VDSO_NOTE_MASK",
35 "xen_irq_disable_direct_reloc", 30 "xen_irq_disable_direct_reloc",
36 "xen_save_fl_direct_reloc", 31 "xen_save_fl_direct_reloc",
37}; 32};
@@ -45,6 +40,8 @@ static int is_safe_abs_reloc(const char* sym_name)
45 /* Match found */ 40 /* Match found */
46 return 1; 41 return 1;
47 } 42 }
43 if (strncmp(sym_name, "VDSO", 4) == 0)
44 return 1;
48 if (strncmp(sym_name, "__crc_", 6) == 0) 45 if (strncmp(sym_name, "__crc_", 6) == 0)
49 return 1; 46 return 1;
50 return 0; 47 return 0;
diff --git a/arch/x86/boot/compressed/vmlinux_64.scr b/arch/x86/boot/compressed/vmlinux.scr
index bd1429ce193e..f02382ae5c48 100644
--- a/arch/x86/boot/compressed/vmlinux_64.scr
+++ b/arch/x86/boot/compressed/vmlinux.scr
@@ -1,6 +1,6 @@
1SECTIONS 1SECTIONS
2{ 2{
3 .text.compressed : { 3 .rodata.compressed : {
4 input_len = .; 4 input_len = .;
5 LONG(input_data_end - input_data) input_data = .; 5 LONG(input_data_end - input_data) input_data = .;
6 *(.data) 6 *(.data)
diff --git a/arch/x86/boot/compressed/vmlinux_32.lds b/arch/x86/boot/compressed/vmlinux_32.lds
index cc4854f6c6c1..bb3c48379c40 100644
--- a/arch/x86/boot/compressed/vmlinux_32.lds
+++ b/arch/x86/boot/compressed/vmlinux_32.lds
@@ -3,17 +3,17 @@ OUTPUT_ARCH(i386)
3ENTRY(startup_32) 3ENTRY(startup_32)
4SECTIONS 4SECTIONS
5{ 5{
6 /* Be careful parts of head.S assume startup_32 is at 6 /* Be careful parts of head_32.S assume startup_32 is at
7 * address 0. 7 * address 0.
8 */ 8 */
9 . = 0 ; 9 . = 0;
10 .text.head : { 10 .text.head : {
11 _head = . ; 11 _head = . ;
12 *(.text.head) 12 *(.text.head)
13 _ehead = . ; 13 _ehead = . ;
14 } 14 }
15 .data.compressed : { 15 .rodata.compressed : {
16 *(.data.compressed) 16 *(.rodata.compressed)
17 } 17 }
18 .text : { 18 .text : {
19 _text = .; /* Text */ 19 _text = .; /* Text */
diff --git a/arch/x86/boot/compressed/vmlinux_32.scr b/arch/x86/boot/compressed/vmlinux_32.scr
deleted file mode 100644
index 707a88f7f29e..000000000000
--- a/arch/x86/boot/compressed/vmlinux_32.scr
+++ /dev/null
@@ -1,10 +0,0 @@
1SECTIONS
2{
3 .data.compressed : {
4 input_len = .;
5 LONG(input_data_end - input_data) input_data = .;
6 *(.data)
7 output_len = . - 4;
8 input_data_end = .;
9 }
10}
diff --git a/arch/x86/boot/compressed/vmlinux_64.lds b/arch/x86/boot/compressed/vmlinux_64.lds
index 94c13e557fb4..f6e5b445f457 100644
--- a/arch/x86/boot/compressed/vmlinux_64.lds
+++ b/arch/x86/boot/compressed/vmlinux_64.lds
@@ -3,15 +3,19 @@ OUTPUT_ARCH(i386:x86-64)
3ENTRY(startup_64) 3ENTRY(startup_64)
4SECTIONS 4SECTIONS
5{ 5{
6 /* Be careful parts of head.S assume startup_32 is at 6 /* Be careful parts of head_64.S assume startup_64 is at
7 * address 0. 7 * address 0.
8 */ 8 */
9 . = 0; 9 . = 0;
10 .text : { 10 .text.head : {
11 _head = . ; 11 _head = . ;
12 *(.text.head) 12 *(.text.head)
13 _ehead = . ; 13 _ehead = . ;
14 *(.text.compressed) 14 }
15 .rodata.compressed : {
16 *(.rodata.compressed)
17 }
18 .text : {
15 _text = .; /* Text */ 19 _text = .; /* Text */
16 *(.text) 20 *(.text)
17 *(.text.*) 21 *(.text.*)
diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c
index bd138e442ec2..8721dc46a0b6 100644
--- a/arch/x86/boot/edd.c
+++ b/arch/x86/boot/edd.c
@@ -129,6 +129,7 @@ void query_edd(void)
129 char eddarg[8]; 129 char eddarg[8];
130 int do_mbr = 1; 130 int do_mbr = 1;
131 int do_edd = 1; 131 int do_edd = 1;
132 int be_quiet;
132 int devno; 133 int devno;
133 struct edd_info ei, *edp; 134 struct edd_info ei, *edp;
134 u32 *mbrptr; 135 u32 *mbrptr;
@@ -140,12 +141,21 @@ void query_edd(void)
140 do_edd = 0; 141 do_edd = 0;
141 } 142 }
142 143
144 be_quiet = cmdline_find_option_bool("quiet");
145
143 edp = boot_params.eddbuf; 146 edp = boot_params.eddbuf;
144 mbrptr = boot_params.edd_mbr_sig_buffer; 147 mbrptr = boot_params.edd_mbr_sig_buffer;
145 148
146 if (!do_edd) 149 if (!do_edd)
147 return; 150 return;
148 151
152 /* Bugs in OnBoard or AddOnCards Bios may hang the EDD probe,
153 * so give a hint if this happens.
154 */
155
156 if (!be_quiet)
157 printf("Probing EDD (edd=off to disable)... ");
158
149 for (devno = 0x80; devno < 0x80+EDD_MBR_SIG_MAX; devno++) { 159 for (devno = 0x80; devno < 0x80+EDD_MBR_SIG_MAX; devno++) {
150 /* 160 /*
151 * Scan the BIOS-supported hard disks and query EDD 161 * Scan the BIOS-supported hard disks and query EDD
@@ -162,6 +172,9 @@ void query_edd(void)
162 if (do_mbr && !read_mbr_sig(devno, &ei, mbrptr++)) 172 if (do_mbr && !read_mbr_sig(devno, &ei, mbrptr++))
163 boot_params.edd_mbr_sig_buf_entries = devno-0x80+1; 173 boot_params.edd_mbr_sig_buf_entries = devno-0x80+1;
164 } 174 }
175
176 if (!be_quiet)
177 printf("ok\n");
165} 178}
166 179
167#endif 180#endif
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 4cc5b0411db5..64ad9016585a 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -195,10 +195,13 @@ cmd_line_ptr: .long 0 # (Header version 0x0202 or later)
195 # can be located anywhere in 195 # can be located anywhere in
196 # low memory 0x10000 or higher. 196 # low memory 0x10000 or higher.
197 197
198ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff 198ramdisk_max: .long 0x7fffffff
199 # (Header version 0x0203 or later) 199 # (Header version 0x0203 or later)
200 # The highest safe address for 200 # The highest safe address for
201 # the contents of an initrd 201 # the contents of an initrd
202 # The current kernel allows up to 4 GB,
203 # but leave it at 2 GB to avoid
204 # possible bootloader bugs.
202 205
203kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment 206kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment
204 #required for protected mode 207 #required for protected mode
diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
index 1f95750ede28..7828da5cfd07 100644
--- a/arch/x86/boot/main.c
+++ b/arch/x86/boot/main.c
@@ -100,20 +100,32 @@ static void set_bios_mode(void)
100#endif 100#endif
101} 101}
102 102
103void main(void) 103static void init_heap(void)
104{ 104{
105 /* First, copy the boot header into the "zeropage" */ 105 char *stack_end;
106 copy_boot_params();
107 106
108 /* End of heap check */
109 if (boot_params.hdr.loadflags & CAN_USE_HEAP) { 107 if (boot_params.hdr.loadflags & CAN_USE_HEAP) {
110 heap_end = (char *)(boot_params.hdr.heap_end_ptr 108 asm("leal %P1(%%esp),%0"
111 +0x200-STACK_SIZE); 109 : "=r" (stack_end) : "i" (-STACK_SIZE));
110
111 heap_end = (char *)
112 ((size_t)boot_params.hdr.heap_end_ptr + 0x200);
113 if (heap_end > stack_end)
114 heap_end = stack_end;
112 } else { 115 } else {
113 /* Boot protocol 2.00 only, no heap available */ 116 /* Boot protocol 2.00 only, no heap available */
114 puts("WARNING: Ancient bootloader, some functionality " 117 puts("WARNING: Ancient bootloader, some functionality "
115 "may be limited!\n"); 118 "may be limited!\n");
116 } 119 }
120}
121
122void main(void)
123{
124 /* First, copy the boot header into the "zeropage" */
125 copy_boot_params();
126
127 /* End of heap check */
128 init_heap();
117 129
118 /* Make sure we have all the proper CPU support */ 130 /* Make sure we have all the proper CPU support */
119 if (validate_cpu()) { 131 if (validate_cpu()) {
@@ -131,9 +143,6 @@ void main(void)
131 /* Set keyboard repeat rate (why?) */ 143 /* Set keyboard repeat rate (why?) */
132 keyboard_set_repeat(); 144 keyboard_set_repeat();
133 145
134 /* Set the video mode */
135 set_video();
136
137 /* Query MCA information */ 146 /* Query MCA information */
138 query_mca(); 147 query_mca();
139 148
@@ -154,6 +163,10 @@ void main(void)
154#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) 163#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
155 query_edd(); 164 query_edd();
156#endif 165#endif
166
167 /* Set the video mode */
168 set_video();
169
157 /* Do the last things and invoke protected mode */ 170 /* Do the last things and invoke protected mode */
158 go_to_protected_mode(); 171 go_to_protected_mode();
159} 172}
diff --git a/arch/x86/boot/pm.c b/arch/x86/boot/pm.c
index 09fb342cc62e..1a0f936c160b 100644
--- a/arch/x86/boot/pm.c
+++ b/arch/x86/boot/pm.c
@@ -104,7 +104,7 @@ static void reset_coprocessor(void)
104 (((u64)(base & 0xff000000) << 32) | \ 104 (((u64)(base & 0xff000000) << 32) | \
105 ((u64)flags << 40) | \ 105 ((u64)flags << 40) | \
106 ((u64)(limit & 0x00ff0000) << 32) | \ 106 ((u64)(limit & 0x00ff0000) << 32) | \
107 ((u64)(base & 0x00ffff00) << 16) | \ 107 ((u64)(base & 0x00ffffff) << 16) | \
108 ((u64)(limit & 0x0000ffff))) 108 ((u64)(limit & 0x0000ffff)))
109 109
110struct gdt_ptr { 110struct gdt_ptr {
@@ -121,6 +121,10 @@ static void setup_gdt(void)
121 [GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff), 121 [GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
122 /* DS: data, read/write, 4 GB, base 0 */ 122 /* DS: data, read/write, 4 GB, base 0 */
123 [GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff), 123 [GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
124 /* TSS: 32-bit tss, 104 bytes, base 4096 */
125 /* We only have a TSS here to keep Intel VT happy;
126 we don't actually use it for anything. */
127 [GDT_ENTRY_BOOT_TSS] = GDT_ENTRY(0x0089, 4096, 103),
124 }; 128 };
125 /* Xen HVM incorrectly stores a pointer to the gdt_ptr, instead 129 /* Xen HVM incorrectly stores a pointer to the gdt_ptr, instead
126 of the gdt_ptr contents. Thus, make it static so it will 130 of the gdt_ptr contents. Thus, make it static so it will
diff --git a/arch/x86/boot/pmjump.S b/arch/x86/boot/pmjump.S
index fa6bed1fac14..f5402d51f7c3 100644
--- a/arch/x86/boot/pmjump.S
+++ b/arch/x86/boot/pmjump.S
@@ -15,6 +15,7 @@
15 */ 15 */
16 16
17#include <asm/boot.h> 17#include <asm/boot.h>
18#include <asm/processor-flags.h>
18#include <asm/segment.h> 19#include <asm/segment.h>
19 20
20 .text 21 .text
@@ -29,28 +30,55 @@
29 */ 30 */
30protected_mode_jump: 31protected_mode_jump:
31 movl %edx, %esi # Pointer to boot_params table 32 movl %edx, %esi # Pointer to boot_params table
32 movl %eax, 2f # Patch ljmpl instruction 33
34 xorl %ebx, %ebx
35 movw %cs, %bx
36 shll $4, %ebx
37 addl %ebx, 2f
33 38
34 movw $__BOOT_DS, %cx 39 movw $__BOOT_DS, %cx
35 xorl %ebx, %ebx # Per the 32-bit boot protocol 40 movw $__BOOT_TSS, %di
36 xorl %ebp, %ebp # Per the 32-bit boot protocol
37 xorl %edi, %edi # Per the 32-bit boot protocol
38 41
39 movl %cr0, %edx 42 movl %cr0, %edx
40 orb $1, %dl # Protected mode (PE) bit 43 orb $X86_CR0_PE, %dl # Protected mode
41 movl %edx, %cr0 44 movl %edx, %cr0
42 jmp 1f # Short jump to serialize on 386/486 45 jmp 1f # Short jump to serialize on 386/486
431: 461:
44 47
45 movw %cx, %ds 48 # Transition to 32-bit mode
46 movw %cx, %es
47 movw %cx, %fs
48 movw %cx, %gs
49 movw %cx, %ss
50
51 # Jump to the 32-bit entrypoint
52 .byte 0x66, 0xea # ljmpl opcode 49 .byte 0x66, 0xea # ljmpl opcode
532: .long 0 # offset 502: .long in_pm32 # offset
54 .word __BOOT_CS # segment 51 .word __BOOT_CS # segment
55 52
56 .size protected_mode_jump, .-protected_mode_jump 53 .size protected_mode_jump, .-protected_mode_jump
54
55 .code32
56 .type in_pm32, @function
57in_pm32:
58 # Set up data segments for flat 32-bit mode
59 movl %ecx, %ds
60 movl %ecx, %es
61 movl %ecx, %fs
62 movl %ecx, %gs
63 movl %ecx, %ss
64 # The 32-bit code sets up its own stack, but this way we do have
65 # a valid stack if some debugging hack wants to use it.
66 addl %ebx, %esp
67
68 # Set up TR to make Intel VT happy
69 ltr %di
70
71 # Clear registers to allow for future extensions to the
72 # 32-bit boot protocol
73 xorl %ecx, %ecx
74 xorl %edx, %edx
75 xorl %ebx, %ebx
76 xorl %ebp, %ebp
77 xorl %edi, %edi
78
79 # Set up LDTR to make Intel VT happy
80 lldt %cx
81
82 jmpl *%eax # Jump to the 32-bit entrypoint
83
84 .size in_pm32, .-in_pm32
diff --git a/arch/x86/boot/video-bios.c b/arch/x86/boot/video-bios.c
index ed0672a81870..ff664a117096 100644
--- a/arch/x86/boot/video-bios.c
+++ b/arch/x86/boot/video-bios.c
@@ -104,6 +104,7 @@ static int bios_probe(void)
104 104
105 mi = GET_HEAP(struct mode_info, 1); 105 mi = GET_HEAP(struct mode_info, 1);
106 mi->mode = VIDEO_FIRST_BIOS+mode; 106 mi->mode = VIDEO_FIRST_BIOS+mode;
107 mi->depth = 0; /* text */
107 mi->x = rdfs16(0x44a); 108 mi->x = rdfs16(0x44a);
108 mi->y = rdfs8(0x484)+1; 109 mi->y = rdfs8(0x484)+1;
109 nmodes++; 110 nmodes++;
@@ -116,7 +117,7 @@ static int bios_probe(void)
116 117
117__videocard video_bios = 118__videocard video_bios =
118{ 119{
119 .card_name = "BIOS (scanned)", 120 .card_name = "BIOS",
120 .probe = bios_probe, 121 .probe = bios_probe,
121 .set_mode = bios_set_mode, 122 .set_mode = bios_set_mode,
122 .unsafe = 1, 123 .unsafe = 1,
diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c
index 4716b9a96357..662dd2f13068 100644
--- a/arch/x86/boot/video-vesa.c
+++ b/arch/x86/boot/video-vesa.c
@@ -79,20 +79,28 @@ static int vesa_probe(void)
79 /* Text Mode, TTY BIOS supported, 79 /* Text Mode, TTY BIOS supported,
80 supported by hardware */ 80 supported by hardware */
81 mi = GET_HEAP(struct mode_info, 1); 81 mi = GET_HEAP(struct mode_info, 1);
82 mi->mode = mode + VIDEO_FIRST_VESA; 82 mi->mode = mode + VIDEO_FIRST_VESA;
83 mi->x = vminfo.h_res; 83 mi->depth = 0; /* text */
84 mi->y = vminfo.v_res; 84 mi->x = vminfo.h_res;
85 mi->y = vminfo.v_res;
85 nmodes++; 86 nmodes++;
86 } else if ((vminfo.mode_attr & 0x99) == 0x99) { 87 } else if ((vminfo.mode_attr & 0x99) == 0x99 &&
88 (vminfo.memory_layout == 4 ||
89 vminfo.memory_layout == 6) &&
90 vminfo.memory_planes == 1) {
87#ifdef CONFIG_FB 91#ifdef CONFIG_FB
88 /* Graphics mode, color, linear frame buffer 92 /* Graphics mode, color, linear frame buffer
89 supported -- register the mode but hide from 93 supported. Only register the mode if
90 the menu. Only do this if framebuffer is 94 if framebuffer is configured, however,
91 configured, however, otherwise the user will 95 otherwise the user will be left without a screen.
92 be left without a screen. */ 96 We don't require CONFIG_FB_VESA, however, since
97 some of the other framebuffer drivers can use
98 this mode-setting, too. */
93 mi = GET_HEAP(struct mode_info, 1); 99 mi = GET_HEAP(struct mode_info, 1);
94 mi->mode = mode + VIDEO_FIRST_VESA; 100 mi->mode = mode + VIDEO_FIRST_VESA;
95 mi->x = mi->y = 0; 101 mi->depth = vminfo.bpp;
102 mi->x = vminfo.h_res;
103 mi->y = vminfo.v_res;
96 nmodes++; 104 nmodes++;
97#endif 105#endif
98 } 106 }
diff --git a/arch/x86/boot/video-vga.c b/arch/x86/boot/video-vga.c
index aef02f9ec0c1..7259387b7d19 100644
--- a/arch/x86/boot/video-vga.c
+++ b/arch/x86/boot/video-vga.c
@@ -18,22 +18,22 @@
18#include "video.h" 18#include "video.h"
19 19
20static struct mode_info vga_modes[] = { 20static struct mode_info vga_modes[] = {
21 { VIDEO_80x25, 80, 25 }, 21 { VIDEO_80x25, 80, 25, 0 },
22 { VIDEO_8POINT, 80, 50 }, 22 { VIDEO_8POINT, 80, 50, 0 },
23 { VIDEO_80x43, 80, 43 }, 23 { VIDEO_80x43, 80, 43, 0 },
24 { VIDEO_80x28, 80, 28 }, 24 { VIDEO_80x28, 80, 28, 0 },
25 { VIDEO_80x30, 80, 30 }, 25 { VIDEO_80x30, 80, 30, 0 },
26 { VIDEO_80x34, 80, 34 }, 26 { VIDEO_80x34, 80, 34, 0 },
27 { VIDEO_80x60, 80, 60 }, 27 { VIDEO_80x60, 80, 60, 0 },
28}; 28};
29 29
30static struct mode_info ega_modes[] = { 30static struct mode_info ega_modes[] = {
31 { VIDEO_80x25, 80, 25 }, 31 { VIDEO_80x25, 80, 25, 0 },
32 { VIDEO_8POINT, 80, 43 }, 32 { VIDEO_8POINT, 80, 43, 0 },
33}; 33};
34 34
35static struct mode_info cga_modes[] = { 35static struct mode_info cga_modes[] = {
36 { VIDEO_80x25, 80, 25 }, 36 { VIDEO_80x25, 80, 25, 0 },
37}; 37};
38 38
39__videocard video_vga; 39__videocard video_vga;
diff --git a/arch/x86/boot/video.c b/arch/x86/boot/video.c
index ad9712f01739..696d08f3843c 100644
--- a/arch/x86/boot/video.c
+++ b/arch/x86/boot/video.c
@@ -293,13 +293,28 @@ static void display_menu(void)
293 struct mode_info *mi; 293 struct mode_info *mi;
294 char ch; 294 char ch;
295 int i; 295 int i;
296 int nmodes;
297 int modes_per_line;
298 int col;
296 299
297 puts("Mode: COLSxROWS:\n"); 300 nmodes = 0;
301 for (card = video_cards; card < video_cards_end; card++)
302 nmodes += card->nmodes;
298 303
304 modes_per_line = 1;
305 if (nmodes >= 20)
306 modes_per_line = 3;
307
308 for (col = 0; col < modes_per_line; col++)
309 puts("Mode: Resolution: Type: ");
310 putchar('\n');
311
312 col = 0;
299 ch = '0'; 313 ch = '0';
300 for (card = video_cards; card < video_cards_end; card++) { 314 for (card = video_cards; card < video_cards_end; card++) {
301 mi = card->modes; 315 mi = card->modes;
302 for (i = 0; i < card->nmodes; i++, mi++) { 316 for (i = 0; i < card->nmodes; i++, mi++) {
317 char resbuf[32];
303 int visible = mi->x && mi->y; 318 int visible = mi->x && mi->y;
304 u16 mode_id = mi->mode ? mi->mode : 319 u16 mode_id = mi->mode ? mi->mode :
305 (mi->y << 8)+mi->x; 320 (mi->y << 8)+mi->x;
@@ -307,8 +322,18 @@ static void display_menu(void)
307 if (!visible) 322 if (!visible)
308 continue; /* Hidden mode */ 323 continue; /* Hidden mode */
309 324
310 printf("%c %04X %3dx%-3d %s\n", 325 if (mi->depth)
311 ch, mode_id, mi->x, mi->y, card->card_name); 326 sprintf(resbuf, "%dx%d", mi->y, mi->depth);
327 else
328 sprintf(resbuf, "%d", mi->y);
329
330 printf("%c %03X %4dx%-7s %-6s",
331 ch, mode_id, mi->x, resbuf, card->card_name);
332 col++;
333 if (col >= modes_per_line) {
334 putchar('\n');
335 col = 0;
336 }
312 337
313 if (ch == '9') 338 if (ch == '9')
314 ch = 'a'; 339 ch = 'a';
@@ -318,6 +343,8 @@ static void display_menu(void)
318 ch++; 343 ch++;
319 } 344 }
320 } 345 }
346 if (col)
347 putchar('\n');
321} 348}
322 349
323#define H(x) ((x)-'a'+10) 350#define H(x) ((x)-'a'+10)
diff --git a/arch/x86/boot/video.h b/arch/x86/boot/video.h
index b92447d51213..d69347f79e8e 100644
--- a/arch/x86/boot/video.h
+++ b/arch/x86/boot/video.h
@@ -83,7 +83,8 @@ void store_screen(void);
83 83
84struct mode_info { 84struct mode_info {
85 u16 mode; /* Mode number (vga= style) */ 85 u16 mode; /* Mode number (vga= style) */
86 u8 x, y; /* Width, height */ 86 u16 x, y; /* Width, height */
87 u16 depth; /* Bits per pixel, 0 for text mode */
87}; 88};
88 89
89struct card_info { 90struct card_info {
diff --git a/arch/x86/boot/voyager.c b/arch/x86/boot/voyager.c
index 61c8fe0453be..6499e3239b41 100644
--- a/arch/x86/boot/voyager.c
+++ b/arch/x86/boot/voyager.c
@@ -16,8 +16,6 @@
16 16
17#include "boot.h" 17#include "boot.h"
18 18
19#ifdef CONFIG_X86_VOYAGER
20
21int query_voyager(void) 19int query_voyager(void)
22{ 20{
23 u8 err; 21 u8 err;
@@ -42,5 +40,3 @@ int query_voyager(void)
42 copy_from_fs(data_ptr, di, 7); /* Table is 7 bytes apparently */ 40 copy_from_fs(data_ptr, di, 7); /* Table is 7 bytes apparently */
43 return 0; 41 return 0;
44} 42}
45
46#endif /* CONFIG_X86_VOYAGER */