blob: c5e80b69e7d41d8ae580ae734553d2b9584b9760 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
31startup_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
421: 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 */
853:
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 */
110move_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
128move_routine_end: