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