Merge tag 'efi_updates_for_v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / arch / x86 / boot / compressed / head_32.S
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  *  linux/boot/head.S
4  *
5  *  Copyright (C) 1991, 1992, 1993  Linus Torvalds
6  */
7
8 /*
9  *  head.S contains the 32-bit startup code.
10  *
11  * NOTE!!! Startup happens at absolute address 0x00001000, which is also where
12  * the page directory will exist. The startup code will be overwritten by
13  * the page directory. [According to comments etc elsewhere on a compressed
14  * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC]
15  *
16  * Page 0 is deliberately kept safe, since System Management Mode code in
17  * laptops may need to access the BIOS data stored there.  This is also
18  * useful for future device drivers that either access the BIOS via VM86
19  * mode.
20  */
21
22 /*
23  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
24  */
25         .text
26
27 #include <linux/init.h>
28 #include <linux/linkage.h>
29 #include <asm/segment.h>
30 #include <asm/page_types.h>
31 #include <asm/boot.h>
32 #include <asm/asm-offsets.h>
33 #include <asm/bootparam.h>
34
35 /*
36  * These symbols needed to be marked as .hidden to prevent the BFD linker from
37  * generating R_386_32 (rather than R_386_RELATIVE) relocations for them when
38  * the 32-bit compressed kernel is linked as PIE. This is no longer necessary,
39  * but it doesn't hurt to keep them .hidden.
40  */
41         .hidden _bss
42         .hidden _ebss
43         .hidden _end
44
45         __HEAD
46 SYM_FUNC_START(startup_32)
47         cld
48         cli
49
50 /*
51  * Calculate the delta between where we were compiled to run
52  * at and where we were actually loaded at.  This can only be done
53  * with a short local call on x86.  Nothing  else will tell us what
54  * address we are running at.  The reserved chunk of the real-mode
55  * data at 0x1e4 (defined as a scratch field) are used as the stack
56  * for this calculation. Only 4 bytes are needed.
57  */
58         leal    (BP_scratch+4)(%esi), %esp
59         call    1f
60 1:      popl    %edx
61         addl    $_GLOBAL_OFFSET_TABLE_+(.-1b), %edx
62
63         /* Load new GDT */
64         leal    gdt@GOTOFF(%edx), %eax
65         movl    %eax, 2(%eax)
66         lgdt    (%eax)
67
68         /* Load segment registers with our descriptors */
69         movl    $__BOOT_DS, %eax
70         movl    %eax, %ds
71         movl    %eax, %es
72         movl    %eax, %fs
73         movl    %eax, %gs
74         movl    %eax, %ss
75
76 /*
77  * %edx contains the address we are loaded at by the boot loader (plus the
78  * offset to the GOT).  The below code calculates %ebx to be the address where
79  * we should move the kernel image temporarily for safe in-place decompression
80  * (again, plus the offset to the GOT).
81  *
82  * %ebp is calculated to be the address that the kernel will be decompressed to.
83  */
84
85 #ifdef CONFIG_RELOCATABLE
86         leal    startup_32@GOTOFF(%edx), %ebx
87
88 #ifdef CONFIG_EFI_STUB
89 /*
90  * If we were loaded via the EFI LoadImage service, startup_32() will be at an
91  * offset to the start of the space allocated for the image. efi_pe_entry() will
92  * set up image_offset to tell us where the image actually starts, so that we
93  * can use the full available buffer.
94  *      image_offset = startup_32 - image_base
95  * Otherwise image_offset will be zero and has no effect on the calculations.
96  */
97         subl    image_offset@GOTOFF(%edx), %ebx
98 #endif
99
100         movl    BP_kernel_alignment(%esi), %eax
101         decl    %eax
102         addl    %eax, %ebx
103         notl    %eax
104         andl    %eax, %ebx
105         cmpl    $LOAD_PHYSICAL_ADDR, %ebx
106         jae     1f
107 #endif
108         movl    $LOAD_PHYSICAL_ADDR, %ebx
109 1:
110
111         movl    %ebx, %ebp      // Save the output address for later
112         /* Target address to relocate to for decompression */
113         addl    BP_init_size(%esi), %ebx
114         subl    $_end@GOTOFF, %ebx
115
116         /* Set up the stack */
117         leal    boot_stack_end@GOTOFF(%ebx), %esp
118
119         /* Zero EFLAGS */
120         pushl   $0
121         popfl
122
123 /*
124  * Copy the compressed kernel to the end of our buffer
125  * where decompression in place becomes safe.
126  */
127         pushl   %esi
128         leal    (_bss@GOTOFF-4)(%edx), %esi
129         leal    (_bss@GOTOFF-4)(%ebx), %edi
130         movl    $(_bss - startup_32), %ecx
131         shrl    $2, %ecx
132         std
133         rep     movsl
134         cld
135         popl    %esi
136
137         /*
138          * The GDT may get overwritten either during the copy we just did or
139          * during extract_kernel below. To avoid any issues, repoint the GDTR
140          * to the new copy of the GDT.
141          */
142         leal    gdt@GOTOFF(%ebx), %eax
143         movl    %eax, 2(%eax)
144         lgdt    (%eax)
145
146 /*
147  * Jump to the relocated address.
148  */
149         leal    .Lrelocated@GOTOFF(%ebx), %eax
150         jmp     *%eax
151 SYM_FUNC_END(startup_32)
152
153 #ifdef CONFIG_EFI_STUB
154 SYM_FUNC_START(efi32_stub_entry)
155 SYM_FUNC_START_ALIAS(efi_stub_entry)
156         add     $0x4, %esp
157         movl    8(%esp), %esi   /* save boot_params pointer */
158         call    efi_main
159         /* efi_main returns the possibly relocated address of startup_32 */
160         jmp     *%eax
161 SYM_FUNC_END(efi32_stub_entry)
162 SYM_FUNC_END_ALIAS(efi_stub_entry)
163 #endif
164
165         .text
166 SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
167
168 /*
169  * Clear BSS (stack is currently empty)
170  */
171         xorl    %eax, %eax
172         leal    _bss@GOTOFF(%ebx), %edi
173         leal    _ebss@GOTOFF(%ebx), %ecx
174         subl    %edi, %ecx
175         shrl    $2, %ecx
176         rep     stosl
177
178 /*
179  * Do the extraction, and jump to the new kernel..
180  */
181         /* push arguments for extract_kernel: */
182
183         pushl   output_len@GOTOFF(%ebx) /* decompressed length, end of relocs */
184         pushl   %ebp                    /* output address */
185         pushl   input_len@GOTOFF(%ebx)  /* input_len */
186         leal    input_data@GOTOFF(%ebx), %eax
187         pushl   %eax                    /* input_data */
188         leal    boot_heap@GOTOFF(%ebx), %eax
189         pushl   %eax                    /* heap area */
190         pushl   %esi                    /* real mode pointer */
191         call    extract_kernel          /* returns kernel location in %eax */
192         addl    $24, %esp
193
194 /*
195  * Jump to the extracted kernel.
196  */
197         xorl    %ebx, %ebx
198         jmp     *%eax
199 SYM_FUNC_END(.Lrelocated)
200
201         .data
202         .balign 8
203 SYM_DATA_START_LOCAL(gdt)
204         .word   gdt_end - gdt - 1
205         .long   0
206         .word   0
207         .quad   0x0000000000000000      /* Reserved */
208         .quad   0x00cf9a000000ffff      /* __KERNEL_CS */
209         .quad   0x00cf92000000ffff      /* __KERNEL_DS */
210 SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end)
211
212 #ifdef CONFIG_EFI_STUB
213 SYM_DATA(image_offset, .long 0)
214 #endif
215
216 /*
217  * Stack and heap for uncompression
218  */
219         .bss
220         .balign 4
221 boot_heap:
222         .fill BOOT_HEAP_SIZE, 1, 0
223 boot_stack:
224         .fill BOOT_STACK_SIZE, 1, 0
225 boot_stack_end: