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 * In SMP mode we keep this page safe. Really we ought to shuffle things and 16 * put the trampoline here. - AC. An SMP trampoline enters with %cx holding 17 * the stack base. 18 * 19 * Page 0 is deliberately kept safe, since System Management Mode code in 20 * laptops may need to access the BIOS data stored there. This is also 21 * useful for future device drivers that either access the BIOS via VM86 22 * mode. 23 */ 24
25 /* 26 * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 27 */ 28 .text
29
30 #define__ASSEMBLY__ 31 #include <linux/config.h>
32 #include <linux/linkage.h>
33 #include <asm/segment.h>
34
35 .globl startup_32
36
37 startup_32:
38 cld
39 cli
40 movl $(KERNEL_DS),%eax
41 mov %ax,%ds
42 mov %ax,%es
43 mov %ax,%fs
44 mov %ax,%gs
45 #ifdef__SMP__ 46 orw %bx,%bx # What state are we in BX=1 for SMP
47 # 0 for boot
48 jz 2f # Initial boot
49
50 /* 51 * We are trampolining an SMP processor 52 */ 53 mov %ax,%ss
54 xorl %eax,%eax # Back to 0
55 mov %cx,%ax # SP low 16 bits
56 movl %eax,%esp
57 pushl 0 # Clear NT
58 popfl
59 ljmp $(KERNEL_CS), $0x100000 # Into C and sanity
60
61 2:
62 #endif 63 lss SYMBOL_NAME(stack_start),%esp
64 xorl %eax,%eax
65 1: incl %eax # check that A20 really IS enabled
66 movl %eax,0x000000 # loop forever if it isn't
67 cmpl %eax,0x100000
68 je 1b
69 /* 70 * Initialize eflags. Some BIOS's leave bits like NT set. This would 71 * confuse the debugger if this code is traced. 72 * XXX - best to initialize before switching to protected mode. 73 */ 74 pushl $0
75 popfl
76 /* 77 * Clear BSS 78 */ 79 xorl %eax,%eax
80 movl $ SYMBOL_NAME(_edata),%edi
81 movl $ SYMBOL_NAME(_end),%ecx
82 subl %edi,%ecx
83 cld
84 rep
85 stosb
86 /* 87 * Do the decompression, and jump to the new kernel.. 88 */ 89 subl $16,%esp # place for structure on the stack
90 pushl %esp # address of structure as first arg
91 call SYMBOL_NAME(decompress_kernel)
92 orl %eax,%eax
93 jnz 3f
94 xorl %ebx,%ebx
95 ljmp $(KERNEL_CS), $0x100000
96
97 /* 98 * We come here, if we were loaded high. 99 * We need to move the move-in-place routine down to 0x1000 100 * and then start it with the buffer addresses in registers, 101 * which we got from the stack. 102 */ 103 3:
104 movl $move_routine_start,%esi
105 movl $0x1000,%edi
106 movl $move_routine_end,%ecx
107 subl %esi,%ecx
108 cld
109 rep
110 movsb
111
112 popl %esi # discard the address
113 popl %esi # low_buffer_start
114 popl %ecx # lcount
115 popl %edx # high_buffer_start
116 popl %eax # hcount
117 movl $0x100000,%edi
118 cli # make sure we don't get interrupted
119 ljmp $(KERNEL_CS), $0x1000 # and jump to the move routine
120
121 /* 122 * Routine (template) for moving the decompressed kernel in place, 123 * if we were high loaded. This _must_ PIC-code ! 124 */ 125 move_routine_start:
126 rep
127 movsb
128 movl %edx,%esi
129 movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0
130 rep
131 movsb
132 xorl %ebx,%ebx
133 /* 134 * Well, the kernel relies on %esp pointing into low mem, 135 * with the decompressor loaded high this is no longer true, 136 * so we set esp here. 137 */ 138 mov $0x90000,%esp
139 ljmp $(KERNEL_CS), $0x100000
140 move_routine_end: