xref: /openbmc/linux/arch/x86/boot/compressed/head_32.S (revision 7051924f771722c6dd235e693742cda6488ac700)
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/init.h>
27#include <linux/linkage.h>
28#include <asm/segment.h>
29#include <asm/page_types.h>
30#include <asm/boot.h>
31#include <asm/asm-offsets.h>
32
33/*
34 * Adjust our own GOT
35 *
36 * The relocation base must be in %ebx
37 *
38 * It is safe to call this macro more than once, because in some of the
39 * code paths multiple invocations are inevitable, e.g. via the efi*
40 * entry points.
41 *
42 * Relocation is only performed the first time.
43 */
44.macro FIXUP_GOT
45	cmpb	$1, got_fixed(%ebx)
46	je	2f
47
48	leal	_got(%ebx), %edx
49	leal	_egot(%ebx), %ecx
501:
51	cmpl	%ecx, %edx
52	jae	2f
53	addl	%ebx, (%edx)
54	addl	$4, %edx
55	jmp	1b
562:
57	movb	$1, got_fixed(%ebx)
58.endm
59
60	__HEAD
61ENTRY(startup_32)
62#ifdef CONFIG_EFI_STUB
63	jmp	preferred_addr
64
65	/*
66	 * We don't need the return address, so set up the stack so
67	 * efi_main() can find its arguments.
68	 */
69ENTRY(efi_pe_entry)
70	add	$0x4, %esp
71
72	call	1f
731:	popl	%esi
74	subl	$1b, %esi
75
76	popl	%ecx
77	movl	%ecx, efi32_config(%esi)	/* Handle */
78	popl	%ecx
79	movl	%ecx, efi32_config+8(%esi)	/* EFI System table pointer */
80
81	/* Relocate efi_config->call() */
82	leal	efi32_config(%esi), %eax
83	add	%esi, 88(%eax)
84	pushl	%eax
85
86	movl	%esi, %ebx
87	FIXUP_GOT
88
89	call	make_boot_params
90	cmpl	$0, %eax
91	je	fail
92	movl	%esi, BP_code32_start(%eax)
93	popl	%ecx
94	pushl	%eax
95	pushl	%ecx
96	jmp	2f		/* Skip efi_config initialization */
97
98ENTRY(efi32_stub_entry)
99	add	$0x4, %esp
100	popl	%ecx
101	popl	%edx
102
103	call	1f
1041:	popl	%esi
105	subl	$1b, %esi
106
107	movl	%ecx, efi32_config(%esi)	/* Handle */
108	movl	%edx, efi32_config+8(%esi)	/* EFI System table pointer */
109
110	/* Relocate efi_config->call() */
111	leal	efi32_config(%esi), %eax
112	add	%esi, 88(%eax)
113	pushl	%eax
114
115	movl	%esi, %ebx
116	FIXUP_GOT
117
1182:
119	call	efi_main
120	cmpl	$0, %eax
121	movl	%eax, %esi
122	jne	2f
123fail:
124	/* EFI init failed, so hang. */
125	hlt
126	jmp	fail
1272:
128	movl	BP_code32_start(%esi), %eax
129	leal	preferred_addr(%eax), %eax
130	jmp	*%eax
131
132preferred_addr:
133#endif
134	cld
135	/*
136	 * Test KEEP_SEGMENTS flag to see if the bootloader is asking
137	 * us to not reload segments
138	 */
139	testb	$(1<<6), BP_loadflags(%esi)
140	jnz	1f
141
142	cli
143	movl	$__BOOT_DS, %eax
144	movl	%eax, %ds
145	movl	%eax, %es
146	movl	%eax, %fs
147	movl	%eax, %gs
148	movl	%eax, %ss
1491:
150
151/*
152 * Calculate the delta between where we were compiled to run
153 * at and where we were actually loaded at.  This can only be done
154 * with a short local call on x86.  Nothing  else will tell us what
155 * address we are running at.  The reserved chunk of the real-mode
156 * data at 0x1e4 (defined as a scratch field) are used as the stack
157 * for this calculation. Only 4 bytes are needed.
158 */
159	leal	(BP_scratch+4)(%esi), %esp
160	call	1f
1611:	popl	%ebp
162	subl	$1b, %ebp
163
164/*
165 * %ebp contains the address we are loaded at by the boot loader and %ebx
166 * contains the address where we should move the kernel image temporarily
167 * for safe in-place decompression.
168 */
169
170#ifdef CONFIG_RELOCATABLE
171	movl	%ebp, %ebx
172	movl	BP_kernel_alignment(%esi), %eax
173	decl	%eax
174	addl    %eax, %ebx
175	notl	%eax
176	andl    %eax, %ebx
177	cmpl	$LOAD_PHYSICAL_ADDR, %ebx
178	jge	1f
179#endif
180	movl	$LOAD_PHYSICAL_ADDR, %ebx
1811:
182
183	/* Target address to relocate to for decompression */
184	addl	$z_extract_offset, %ebx
185
186	/* Set up the stack */
187	leal	boot_stack_end(%ebx), %esp
188
189	/* Zero EFLAGS */
190	pushl	$0
191	popfl
192
193/*
194 * Copy the compressed kernel to the end of our buffer
195 * where decompression in place becomes safe.
196 */
197	pushl	%esi
198	leal	(_bss-4)(%ebp), %esi
199	leal	(_bss-4)(%ebx), %edi
200	movl	$(_bss - startup_32), %ecx
201	shrl	$2, %ecx
202	std
203	rep	movsl
204	cld
205	popl	%esi
206
207/*
208 * Jump to the relocated address.
209 */
210	leal	relocated(%ebx), %eax
211	jmp	*%eax
212ENDPROC(startup_32)
213
214	.text
215relocated:
216
217/*
218 * Clear BSS (stack is currently empty)
219 */
220	xorl	%eax, %eax
221	leal	_bss(%ebx), %edi
222	leal	_ebss(%ebx), %ecx
223	subl	%edi, %ecx
224	shrl	$2, %ecx
225	rep	stosl
226
227	FIXUP_GOT
228/*
229 * Do the decompression, and jump to the new kernel..
230 */
231				/* push arguments for decompress_kernel: */
232	pushl	$z_output_len	/* decompressed length */
233	leal	z_extract_offset_negative(%ebx), %ebp
234	pushl	%ebp		/* output address */
235	pushl	$z_input_len	/* input_len */
236	leal	input_data(%ebx), %eax
237	pushl	%eax		/* input_data */
238	leal	boot_heap(%ebx), %eax
239	pushl	%eax		/* heap area */
240	pushl	%esi		/* real mode pointer */
241	call	decompress_kernel /* returns kernel location in %eax */
242	addl	$24, %esp
243
244/*
245 * Jump to the decompressed kernel.
246 */
247	xorl	%ebx, %ebx
248	jmp	*%eax
249
250	.data
251/* Have we relocated the GOT? */
252got_fixed:
253	.byte 0
254
255#ifdef CONFIG_EFI_STUB
256efi32_config:
257	.fill 11,8,0
258	.long efi_call_phys
259	.long 0
260	.byte 0
261#endif
262
263/*
264 * Stack and heap for uncompression
265 */
266	.bss
267	.balign 4
268boot_heap:
269	.fill BOOT_HEAP_SIZE, 1, 0
270boot_stack:
271	.fill BOOT_STACK_SIZE, 1, 0
272boot_stack_end:
273