x86/efi: Fixup GOT in all boot code paths
[cascardo/linux.git] / arch / x86 / boot / compressed / head_32.S
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
50 1:
51         cmpl    %ecx, %edx
52         jae     2f
53         addl    %ebx, (%edx)
54         addl    $4, %edx
55         jmp     1b
56 2:
57         movb    $1, got_fixed(%ebx)
58 .endm
59
60         __HEAD
61 ENTRY(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          */
69 ENTRY(efi_pe_entry)
70         add     $0x4, %esp
71
72         call    1f
73 1:      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
98 ENTRY(efi32_stub_entry)
99         add     $0x4, %esp
100         popl    %ecx
101         popl    %edx
102
103         call    1f
104 1:      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
118 2:
119         call    efi_main
120         cmpl    $0, %eax
121         movl    %eax, %esi
122         jne     2f
123 fail:
124         /* EFI init failed, so hang. */
125         hlt
126         jmp     fail
127 2:
128         movl    BP_code32_start(%esi), %eax
129         leal    preferred_addr(%eax), %eax
130         jmp     *%eax
131
132 preferred_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
149 1:
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
161 1:      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
181 1:
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
212 ENDPROC(startup_32)
213
214         .text
215 relocated:
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? */
252 got_fixed:
253         .byte 0
254
255 #ifdef CONFIG_EFI_STUB
256 efi32_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
268 boot_heap:
269         .fill BOOT_HEAP_SIZE, 1, 0
270 boot_stack:
271         .fill BOOT_STACK_SIZE, 1, 0
272 boot_stack_end: