Commit | Line | Data |
---|---|---|
1da177e4 LT |
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 |