summaryrefslogtreecommitdiffstats
path: root/arch/i386/boot/compressed/head.S
blob: 6f68a92d4a377adc7ed59bab24a8f8d08747e38d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 *  linux/boot/head.S
 *
 *  Copyright (C) 1991, 1992, 1993  Linus Torvalds
 */

/*
 *  head.S contains the 32-bit startup code.
 *
 * NOTE!!! Startup happens at absolute address 0x00001000, which is also where
 * the page directory will exist. The startup code will be overwritten by
 * the page directory. [According to comments etc elsewhere on a compressed
 * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC]
 *
 * In SMP mode we keep this page safe. Really we ought to shuffle things and
 * put the trampoline here. - AC. An SMP trampoline enters with %cx holding
 * the stack base.
 *
 * Page 0 is deliberately kept safe, since System Management Mode code in 
 * laptops may need to access the BIOS data stored there.  This is also
 * useful for future device drivers that either access the BIOS via VM86 
 * mode.
 */

/*
 * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
 */
.text

#define __ASSEMBLY__
#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/segment.h>

	.globl startup_32
	
startup_32:
	cld
	cli
	movl $(KERNEL_DS),%eax
	mov %ax,%ds
	mov %ax,%es
	mov %ax,%fs
	mov %ax,%gs
#ifdef __SMP__
	orw %bx,%bx			# What state are we in BX=1 for SMP
					# 0 for boot
	jz  2f				# Initial boot

/*
 *	We are trampolining an SMP processor
 */
	mov %ax,%ss
	xorl %eax,%eax			# Back to 0
	mov  %cx,%ax			# SP low 16 bits
	movl %eax,%esp
	pushl 0				# Clear NT
	popfl
	ljmp $(KERNEL_CS), $0x100000    # Into C and sanity

2:
#endif
	lss SYMBOL_NAME(stack_start),%esp
	xorl %eax,%eax
1:	incl %eax		# check that A20 really IS enabled
	movl %eax,0x000000	# loop forever if it isn't
	cmpl %eax,0x100000
	je 1b
/*
 * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
 * confuse the debugger if this code is traced.
 * XXX - best to initialize before switching to protected mode.
 */
	pushl $0
	popfl
/*
 * Clear BSS
 */
	xorl %eax,%eax
	movl $ SYMBOL_NAME(_edata),%edi
	movl $ SYMBOL_NAME(_end),%ecx
	subl %edi,%ecx
	cld
	rep
	stosb
/*
 * Do the decompression, and jump to the new kernel..
 */
	subl $16,%esp	# place for structure on the stack
	pushl %esp	# address of structure as first arg
	call SYMBOL_NAME(decompress_kernel)
	orl  %eax,%eax 
	jnz  3f
	xorl %ebx,%ebx
	ljmp $(KERNEL_CS), $0x100000

/*
 * We come here, if we were loaded high.
 * We need to move the move-in-place routine down to 0x1000
 * and then start it with the buffer addresses in registers,
 * which we got from the stack.
 */
3:
	movl $move_routine_start,%esi
	movl $0x1000,%edi
	movl $move_routine_end,%ecx
	subl %esi,%ecx
	cld
	rep
	movsb

	popl %esi	# discard the address
	popl %esi	# low_buffer_start
	popl %ecx	# lcount
	popl %edx	# high_buffer_start
	popl %eax	# hcount
	movl $0x100000,%edi
	cli		# make sure we don't get interrupted
	ljmp $(KERNEL_CS), $0x1000 # and jump to the move routine

/*
 * Routine (template) for moving the decompressed kernel in place,
 * if we were high loaded. This _must_ PIC-code !
 */
move_routine_start:
	rep
	movsb
	movl %edx,%esi
	movl %eax,%ecx	# NOTE: rep movsb won't move if %ecx == 0
	rep
	movsb
	xorl %ebx,%ebx
/*
 * Well, the kernel relies on %esp pointing into low mem,
 * with the decompressor loaded high this is no longer true,
 * so we set esp here.
 */
	mov  $0x90000,%esp
	ljmp $(KERNEL_CS), $0x100000
move_routine_end: