diff options
Diffstat (limited to 'arch/x86/boot')
-rw-r--r-- | arch/x86/boot/Makefile | 5 | ||||
-rw-r--r-- | arch/x86/boot/bioscall.S | 82 | ||||
-rw-r--r-- | arch/x86/boot/boot.h | 48 | ||||
-rw-r--r-- | arch/x86/boot/header.S | 2 | ||||
-rw-r--r-- | arch/x86/boot/regs.c | 29 | ||||
-rw-r--r-- | arch/x86/boot/setup.ld | 6 |
6 files changed, 169 insertions, 3 deletions
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index 6633b6e7505a..658bc525cac7 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile | |||
@@ -26,9 +26,10 @@ targets := vmlinux.bin setup.bin setup.elf bzImage | |||
26 | targets += fdimage fdimage144 fdimage288 image.iso mtools.conf | 26 | targets += fdimage fdimage144 fdimage288 image.iso mtools.conf |
27 | subdir- := compressed | 27 | subdir- := compressed |
28 | 28 | ||
29 | setup-y += a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o | 29 | setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o edd.o |
30 | setup-y += header.o main.o mca.o memory.o pm.o pmjump.o | 30 | setup-y += header.o main.o mca.o memory.o pm.o pmjump.o |
31 | setup-y += printf.o string.o tty.o video.o video-mode.o version.o | 31 | setup-y += printf.o regs.o string.o tty.o video.o video-mode.o |
32 | setup-y += version.o | ||
32 | setup-$(CONFIG_X86_APM_BOOT) += apm.o | 33 | setup-$(CONFIG_X86_APM_BOOT) += apm.o |
33 | 34 | ||
34 | # 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/bioscall.S b/arch/x86/boot/bioscall.S new file mode 100644 index 000000000000..22b4b3efb9f9 --- /dev/null +++ b/arch/x86/boot/bioscall.S | |||
@@ -0,0 +1,82 @@ | |||
1 | /* ----------------------------------------------------------------------- | ||
2 | * | ||
3 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
4 | * | ||
5 | * This file is part of the Linux kernel, and is made available under | ||
6 | * the terms of the GNU General Public License version 2 or (at your | ||
7 | * option) any later version; incorporated herein by reference. | ||
8 | * | ||
9 | * ----------------------------------------------------------------------- */ | ||
10 | |||
11 | /* | ||
12 | * "Glove box" for BIOS calls. Avoids the constant problems with BIOSes | ||
13 | * touching memory they shouldn't be. | ||
14 | */ | ||
15 | |||
16 | .code16 | ||
17 | .text | ||
18 | .globl intcall | ||
19 | .type intcall, @function | ||
20 | intcall: | ||
21 | /* Self-modify the INT instruction. Ugly, but works. */ | ||
22 | cmpb %al, 3f | ||
23 | je 1f | ||
24 | movb %al, 3f | ||
25 | jmp 1f /* Synchronize pipeline */ | ||
26 | 1: | ||
27 | /* Save state */ | ||
28 | pushfl | ||
29 | pushw %fs | ||
30 | pushw %gs | ||
31 | pushal | ||
32 | |||
33 | /* Copy input state to stack frame */ | ||
34 | subw $44, %sp | ||
35 | movw %dx, %si | ||
36 | movw %sp, %di | ||
37 | movw $11, %cx | ||
38 | rep; movsd | ||
39 | |||
40 | /* Pop full state from the stack */ | ||
41 | popal | ||
42 | popw %gs | ||
43 | popw %fs | ||
44 | popw %es | ||
45 | popw %ds | ||
46 | popfl | ||
47 | |||
48 | /* Actual INT */ | ||
49 | .byte 0xcd /* INT opcode */ | ||
50 | 3: .byte 0 | ||
51 | |||
52 | /* Push full state to the stack */ | ||
53 | pushfl | ||
54 | pushw %ds | ||
55 | pushw %es | ||
56 | pushw %fs | ||
57 | pushw %gs | ||
58 | pushal | ||
59 | |||
60 | /* Re-establish C environment invariants */ | ||
61 | cld | ||
62 | movzwl %sp, %esp | ||
63 | movw %cs, %ax | ||
64 | movw %ax, %ds | ||
65 | movw %ax, %es | ||
66 | |||
67 | /* Copy output state from stack frame */ | ||
68 | movw 68(%esp), %di /* Original %cx == 3rd argument */ | ||
69 | andw %di, %di | ||
70 | jz 4f | ||
71 | movw %sp, %si | ||
72 | movw $11, %cx | ||
73 | rep; movsd | ||
74 | 4: addw $44, %sp | ||
75 | |||
76 | /* Restore state and return */ | ||
77 | popal | ||
78 | popw %gs | ||
79 | popw %fs | ||
80 | popfl | ||
81 | retl | ||
82 | .size intcall, .-intcall | ||
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h index 7b2692e897e5..98239d2658f2 100644 --- a/arch/x86/boot/boot.h +++ b/arch/x86/boot/boot.h | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | 3 | * Copyright (C) 1991, 1992 Linus Torvalds |
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | 4 | * Copyright 2007 rPath, Inc. - All Rights Reserved |
5 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
5 | * | 6 | * |
6 | * This file is part of the Linux kernel, and is made available under | 7 | * This file is part of the Linux kernel, and is made available under |
7 | * the terms of the GNU General Public License version 2. | 8 | * the terms of the GNU General Public License version 2. |
@@ -26,6 +27,7 @@ | |||
26 | #include <asm/setup.h> | 27 | #include <asm/setup.h> |
27 | #include "bitops.h" | 28 | #include "bitops.h" |
28 | #include <asm/cpufeature.h> | 29 | #include <asm/cpufeature.h> |
30 | #include <asm/processor-flags.h> | ||
29 | 31 | ||
30 | /* Useful macros */ | 32 | /* Useful macros */ |
31 | #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) | 33 | #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) |
@@ -241,6 +243,49 @@ int enable_a20(void); | |||
241 | /* apm.c */ | 243 | /* apm.c */ |
242 | int query_apm_bios(void); | 244 | int query_apm_bios(void); |
243 | 245 | ||
246 | /* bioscall.c */ | ||
247 | struct biosregs { | ||
248 | union { | ||
249 | struct { | ||
250 | u32 edi; | ||
251 | u32 esi; | ||
252 | u32 ebp; | ||
253 | u32 _esp; | ||
254 | u32 ebx; | ||
255 | u32 edx; | ||
256 | u32 ecx; | ||
257 | u32 eax; | ||
258 | u32 _fsgs; | ||
259 | u32 _dses; | ||
260 | u32 eflags; | ||
261 | }; | ||
262 | struct { | ||
263 | u16 di, hdi; | ||
264 | u16 si, hsi; | ||
265 | u16 bp, hbp; | ||
266 | u16 _sp, _hsp; | ||
267 | u16 bx, hbx; | ||
268 | u16 dx, hdx; | ||
269 | u16 cx, hcx; | ||
270 | u16 ax, hax; | ||
271 | u16 gs, fs; | ||
272 | u16 es, ds; | ||
273 | u16 flags, hflags; | ||
274 | }; | ||
275 | struct { | ||
276 | u8 dil, dih, edi2, edi3; | ||
277 | u8 sil, sih, esi2, esi3; | ||
278 | u8 bpl, bph, ebp2, ebp3; | ||
279 | u8 _spl, _sph, _esp2, _esp3; | ||
280 | u8 bl, bh, ebx2, ebx3; | ||
281 | u8 dl, dh, edx2, edx3; | ||
282 | u8 cl, ch, ecx2, ecx3; | ||
283 | u8 al, ah, eax2, eax3; | ||
284 | }; | ||
285 | }; | ||
286 | }; | ||
287 | void intcall(u8 int_no, const struct biosregs *ireg, struct biosregs *oreg); | ||
288 | |||
244 | /* cmdline.c */ | 289 | /* cmdline.c */ |
245 | int cmdline_find_option(const char *option, char *buffer, int bufsize); | 290 | int cmdline_find_option(const char *option, char *buffer, int bufsize); |
246 | int cmdline_find_option_bool(const char *option); | 291 | int cmdline_find_option_bool(const char *option); |
@@ -279,6 +324,9 @@ int sprintf(char *buf, const char *fmt, ...); | |||
279 | int vsprintf(char *buf, const char *fmt, va_list args); | 324 | int vsprintf(char *buf, const char *fmt, va_list args); |
280 | int printf(const char *fmt, ...); | 325 | int printf(const char *fmt, ...); |
281 | 326 | ||
327 | /* regs.c */ | ||
328 | void initregs(struct biosregs *regs); | ||
329 | |||
282 | /* string.c */ | 330 | /* string.c */ |
283 | int strcmp(const char *str1, const char *str2); | 331 | int strcmp(const char *str1, const char *str2); |
284 | size_t strnlen(const char *s, size_t maxlen); | 332 | size_t strnlen(const char *s, size_t maxlen); |
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 5d84d1c74e4c..486d97fa7f4d 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S | |||
@@ -221,7 +221,7 @@ setup_data: .quad 0 # 64-bit physical pointer to | |||
221 | 221 | ||
222 | # End of setup header ##################################################### | 222 | # End of setup header ##################################################### |
223 | 223 | ||
224 | .section ".inittext", "ax" | 224 | .section ".entrytext", "ax" |
225 | start_of_setup: | 225 | start_of_setup: |
226 | #ifdef SAFE_RESET_DISK_CONTROLLER | 226 | #ifdef SAFE_RESET_DISK_CONTROLLER |
227 | # Reset the disk controller. | 227 | # Reset the disk controller. |
diff --git a/arch/x86/boot/regs.c b/arch/x86/boot/regs.c new file mode 100644 index 000000000000..958019b1cfa5 --- /dev/null +++ b/arch/x86/boot/regs.c | |||
@@ -0,0 +1,29 @@ | |||
1 | /* ----------------------------------------------------------------------- | ||
2 | * | ||
3 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
4 | * | ||
5 | * This file is part of the Linux kernel, and is made available under | ||
6 | * the terms of the GNU General Public License version 2 or (at your | ||
7 | * option) any later version; incorporated herein by reference. | ||
8 | * | ||
9 | * ----------------------------------------------------------------------- */ | ||
10 | |||
11 | /* | ||
12 | * Simple helper function for initializing a register set. | ||
13 | * | ||
14 | * Note that this sets EFLAGS_CF in the input register set; this | ||
15 | * makes it easier to catch functions which do nothing but don't | ||
16 | * explicitly set CF. | ||
17 | */ | ||
18 | |||
19 | #include "boot.h" | ||
20 | |||
21 | void initregs(struct biosregs *reg) | ||
22 | { | ||
23 | memset(reg, 0, sizeof *reg); | ||
24 | reg->eflags |= X86_EFLAGS_CF; | ||
25 | reg->ds = ds(); | ||
26 | reg->es = ds(); | ||
27 | reg->fs = fs(); | ||
28 | reg->gs = gs(); | ||
29 | } | ||
diff --git a/arch/x86/boot/setup.ld b/arch/x86/boot/setup.ld index bb8dc2de7969..0f6ec455a2b1 100644 --- a/arch/x86/boot/setup.ld +++ b/arch/x86/boot/setup.ld | |||
@@ -15,8 +15,11 @@ SECTIONS | |||
15 | 15 | ||
16 | . = 497; | 16 | . = 497; |
17 | .header : { *(.header) } | 17 | .header : { *(.header) } |
18 | .entrytext : { *(.entrytext) } | ||
18 | .inittext : { *(.inittext) } | 19 | .inittext : { *(.inittext) } |
19 | .initdata : { *(.initdata) } | 20 | .initdata : { *(.initdata) } |
21 | __end_init = .; | ||
22 | |||
20 | .text : { *(.text) } | 23 | .text : { *(.text) } |
21 | .text32 : { *(.text32) } | 24 | .text32 : { *(.text32) } |
22 | 25 | ||
@@ -52,4 +55,7 @@ SECTIONS | |||
52 | 55 | ||
53 | . = ASSERT(_end <= 0x8000, "Setup too big!"); | 56 | . = ASSERT(_end <= 0x8000, "Setup too big!"); |
54 | . = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!"); | 57 | . = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!"); |
58 | /* Necessary for the very-old-loader check to work... */ | ||
59 | . = ASSERT(__end_init <= 5*512, "init sections too big!"); | ||
60 | |||
55 | } | 61 | } |