]> git.ipfire.org Git - thirdparty/kernel/stable.git/blob - arch/x86_64/boot/compressed/head.S
Linux-2.6.12-rc2
[thirdparty/kernel/stable.git] / arch / x86_64 / boot / compressed / head.S
1 /*
2 * linux/boot/head.S
3 *
4 * Copyright (C) 1991, 1992, 1993 Linus Torvalds
5 *
6 * $Id: head.S,v 1.3 2001/04/20 00:59:28 ak Exp $
7 */
8
9 /*
10 * head.S contains the 32-bit startup code.
11 *
12 * NOTE!!! Startup happens at absolute address 0x00001000, which is also where
13 * the page directory will exist. The startup code will be overwritten by
14 * the page directory. [According to comments etc elsewhere on a compressed
15 * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC]
16 *
17 * Page 0 is deliberately kept safe, since System Management Mode code in
18 * laptops may need to access the BIOS data stored there. This is also
19 * useful for future device drivers that either access the BIOS via VM86
20 * mode.
21 */
22
23 /*
24 * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
25 */
26 .code32
27 .text
28
29 #include <linux/linkage.h>
30 #include <asm/segment.h>
31
32 .code32
33 .globl startup_32
34
35 startup_32:
36 cld
37 cli
38 movl $(__KERNEL_DS),%eax
39 movl %eax,%ds
40 movl %eax,%es
41 movl %eax,%fs
42 movl %eax,%gs
43
44 lss stack_start,%esp
45 xorl %eax,%eax
46 1: incl %eax # check that A20 really IS enabled
47 movl %eax,0x000000 # loop forever if it isn't
48 cmpl %eax,0x100000
49 je 1b
50
51 /*
52 * Initialize eflags. Some BIOS's leave bits like NT set. This would
53 * confuse the debugger if this code is traced.
54 * XXX - best to initialize before switching to protected mode.
55 */
56 pushl $0
57 popfl
58 /*
59 * Clear BSS
60 */
61 xorl %eax,%eax
62 movl $_edata,%edi
63 movl $_end,%ecx
64 subl %edi,%ecx
65 cld
66 rep
67 stosb
68 /*
69 * Do the decompression, and jump to the new kernel..
70 */
71 subl $16,%esp # place for structure on the stack
72 movl %esp,%eax
73 pushl %esi # real mode pointer as second arg
74 pushl %eax # address of structure as first arg
75 call decompress_kernel
76 orl %eax,%eax
77 jnz 3f
78 addl $8,%esp
79 xorl %ebx,%ebx
80 ljmp $(__KERNEL_CS), $0x100000
81
82 /*
83 * We come here, if we were loaded high.
84 * We need to move the move-in-place routine down to 0x1000
85 * and then start it with the buffer addresses in registers,
86 * which we got from the stack.
87 */
88 3:
89 movl %esi,%ebx
90 movl $move_routine_start,%esi
91 movl $0x1000,%edi
92 movl $move_routine_end,%ecx
93 subl %esi,%ecx
94 addl $3,%ecx
95 shrl $2,%ecx
96 cld
97 rep
98 movsl
99
100 popl %esi # discard the address
101 addl $4,%esp # real mode pointer
102 popl %esi # low_buffer_start
103 popl %ecx # lcount
104 popl %edx # high_buffer_start
105 popl %eax # hcount
106 movl $0x100000,%edi
107 cli # make sure we don't get interrupted
108 ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine
109
110 /*
111 * Routine (template) for moving the decompressed kernel in place,
112 * if we were high loaded. This _must_ PIC-code !
113 */
114 move_routine_start:
115 movl %ecx,%ebp
116 shrl $2,%ecx
117 rep
118 movsl
119 movl %ebp,%ecx
120 andl $3,%ecx
121 rep
122 movsb
123 movl %edx,%esi
124 movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0
125 addl $3,%ecx
126 shrl $2,%ecx
127 rep
128 movsl
129 movl %ebx,%esi # Restore setup pointer
130 xorl %ebx,%ebx
131 ljmp $(__KERNEL_CS), $0x100000
132 move_routine_end:
133
134
135 /* Stack for uncompression */
136 .align 32
137 user_stack:
138 .fill 4096,4,0
139 stack_start:
140 .long user_stack+4096
141 .word __KERNEL_DS
142