xref: /openbmc/linux/arch/x86/boot/compressed/head_32.S (revision 6aa7de05)
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#include <asm/bootparam.h>
33
34/*
35 * The 32-bit x86 assembler in binutils 2.26 will generate R_386_GOT32X
36 * relocation to get the symbol address in PIC.  When the compressed x86
37 * kernel isn't built as PIC, the linker optimizes R_386_GOT32X
38 * relocations to their fixed symbol addresses.  However, when the
39 * compressed x86 kernel is loaded at a different address, it leads
40 * to the following load failure:
41 *
42 *   Failed to allocate space for phdrs
43 *
44 * during the decompression stage.
45 *
46 * If the compressed x86 kernel is relocatable at run-time, it should be
47 * compiled with -fPIE, instead of -fPIC, if possible and should be built as
48 * Position Independent Executable (PIE) so that linker won't optimize
49 * R_386_GOT32X relocation to its fixed symbol address.  Older
50 * linkers generate R_386_32 relocations against locally defined symbols,
51 * _bss, _ebss, _got and _egot, in PIE.  It isn't wrong, just less
52 * optimal than R_386_RELATIVE.  But the x86 kernel fails to properly handle
53 * R_386_32 relocations when relocating the kernel.  To generate
54 * R_386_RELATIVE relocations, we mark _bss, _ebss, _got and _egot as
55 * hidden:
56 */
57	.hidden _bss
58	.hidden _ebss
59	.hidden _got
60	.hidden _egot
61
62	__HEAD
63ENTRY(startup_32)
64	cld
65	/*
66	 * Test KEEP_SEGMENTS flag to see if the bootloader is asking
67	 * us to not reload segments
68	 */
69	testb	$KEEP_SEGMENTS, BP_loadflags(%esi)
70	jnz	1f
71
72	cli
73	movl	$__BOOT_DS, %eax
74	movl	%eax, %ds
75	movl	%eax, %es
76	movl	%eax, %fs
77	movl	%eax, %gs
78	movl	%eax, %ss
791:
80
81/*
82 * Calculate the delta between where we were compiled to run
83 * at and where we were actually loaded at.  This can only be done
84 * with a short local call on x86.  Nothing  else will tell us what
85 * address we are running at.  The reserved chunk of the real-mode
86 * data at 0x1e4 (defined as a scratch field) are used as the stack
87 * for this calculation. Only 4 bytes are needed.
88 */
89	leal	(BP_scratch+4)(%esi), %esp
90	call	1f
911:	popl	%ebp
92	subl	$1b, %ebp
93
94/*
95 * %ebp contains the address we are loaded at by the boot loader and %ebx
96 * contains the address where we should move the kernel image temporarily
97 * for safe in-place decompression.
98 */
99
100#ifdef CONFIG_RELOCATABLE
101	movl	%ebp, %ebx
102	movl	BP_kernel_alignment(%esi), %eax
103	decl	%eax
104	addl    %eax, %ebx
105	notl	%eax
106	andl    %eax, %ebx
107	cmpl	$LOAD_PHYSICAL_ADDR, %ebx
108	jge	1f
109#endif
110	movl	$LOAD_PHYSICAL_ADDR, %ebx
1111:
112
113	/* Target address to relocate to for decompression */
114	movl    BP_init_size(%esi), %eax
115	subl    $_end, %eax
116	addl    %eax, %ebx
117
118	/* Set up the stack */
119	leal	boot_stack_end(%ebx), %esp
120
121	/* Zero EFLAGS */
122	pushl	$0
123	popfl
124
125/*
126 * Copy the compressed kernel to the end of our buffer
127 * where decompression in place becomes safe.
128 */
129	pushl	%esi
130	leal	(_bss-4)(%ebp), %esi
131	leal	(_bss-4)(%ebx), %edi
132	movl	$(_bss - startup_32), %ecx
133	shrl	$2, %ecx
134	std
135	rep	movsl
136	cld
137	popl	%esi
138
139/*
140 * Jump to the relocated address.
141 */
142	leal	relocated(%ebx), %eax
143	jmp	*%eax
144ENDPROC(startup_32)
145
146#ifdef CONFIG_EFI_STUB
147/*
148 * We don't need the return address, so set up the stack so efi_main() can find
149 * its arguments.
150 */
151ENTRY(efi_pe_entry)
152	add	$0x4, %esp
153
154	call	1f
1551:	popl	%esi
156	subl	$1b, %esi
157
158	popl	%ecx
159	movl	%ecx, efi32_config(%esi)	/* Handle */
160	popl	%ecx
161	movl	%ecx, efi32_config+8(%esi)	/* EFI System table pointer */
162
163	/* Relocate efi_config->call() */
164	leal	efi32_config(%esi), %eax
165	add	%esi, 40(%eax)
166	pushl	%eax
167
168	call	make_boot_params
169	cmpl	$0, %eax
170	je	fail
171	movl	%esi, BP_code32_start(%eax)
172	popl	%ecx
173	pushl	%eax
174	pushl	%ecx
175	jmp	2f		/* Skip efi_config initialization */
176ENDPROC(efi_pe_entry)
177
178ENTRY(efi32_stub_entry)
179	add	$0x4, %esp
180	popl	%ecx
181	popl	%edx
182
183	call	1f
1841:	popl	%esi
185	subl	$1b, %esi
186
187	movl	%ecx, efi32_config(%esi)	/* Handle */
188	movl	%edx, efi32_config+8(%esi)	/* EFI System table pointer */
189
190	/* Relocate efi_config->call() */
191	leal	efi32_config(%esi), %eax
192	add	%esi, 40(%eax)
193	pushl	%eax
1942:
195	call	efi_main
196	cmpl	$0, %eax
197	movl	%eax, %esi
198	jne	2f
199fail:
200	/* EFI init failed, so hang. */
201	hlt
202	jmp	fail
2032:
204	movl	BP_code32_start(%esi), %eax
205	leal	startup_32(%eax), %eax
206	jmp	*%eax
207ENDPROC(efi32_stub_entry)
208#endif
209
210	.text
211relocated:
212
213/*
214 * Clear BSS (stack is currently empty)
215 */
216	xorl	%eax, %eax
217	leal	_bss(%ebx), %edi
218	leal	_ebss(%ebx), %ecx
219	subl	%edi, %ecx
220	shrl	$2, %ecx
221	rep	stosl
222
223/*
224 * Adjust our own GOT
225 */
226	leal	_got(%ebx), %edx
227	leal	_egot(%ebx), %ecx
2281:
229	cmpl	%ecx, %edx
230	jae	2f
231	addl	%ebx, (%edx)
232	addl	$4, %edx
233	jmp	1b
2342:
235
236/*
237 * Do the extraction, and jump to the new kernel..
238 */
239				/* push arguments for extract_kernel: */
240	pushl	$z_output_len	/* decompressed length, end of relocs */
241
242	movl    BP_init_size(%esi), %eax
243	subl    $_end, %eax
244	movl    %ebx, %ebp
245	subl    %eax, %ebp
246	pushl	%ebp		/* output address */
247
248	pushl	$z_input_len	/* input_len */
249	leal	input_data(%ebx), %eax
250	pushl	%eax		/* input_data */
251	leal	boot_heap(%ebx), %eax
252	pushl	%eax		/* heap area */
253	pushl	%esi		/* real mode pointer */
254	call	extract_kernel	/* returns kernel location in %eax */
255	addl	$24, %esp
256
257/*
258 * Jump to the extracted kernel.
259 */
260	xorl	%ebx, %ebx
261	jmp	*%eax
262
263#ifdef CONFIG_EFI_STUB
264	.data
265efi32_config:
266	.fill 5,8,0
267	.long efi_call_phys
268	.long 0
269	.byte 0
270#endif
271
272/*
273 * Stack and heap for uncompression
274 */
275	.bss
276	.balign 4
277boot_heap:
278	.fill BOOT_HEAP_SIZE, 1, 0
279boot_stack:
280	.fill BOOT_STACK_SIZE, 1, 0
281boot_stack_end:
282