hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/arch/x86/boot/compressed/head_32.S
....@@ -33,52 +33,19 @@
3333 #include <asm/bootparam.h>
3434
3535 /*
36
- * The 32-bit x86 assembler in binutils 2.26 will generate R_386_GOT32X
37
- * relocation to get the symbol address in PIC. When the compressed x86
38
- * kernel isn't built as PIC, the linker optimizes R_386_GOT32X
39
- * relocations to their fixed symbol addresses. However, when the
40
- * compressed x86 kernel is loaded at a different address, it leads
41
- * to the following load failure:
42
- *
43
- * Failed to allocate space for phdrs
44
- *
45
- * during the decompression stage.
46
- *
47
- * If the compressed x86 kernel is relocatable at run-time, it should be
48
- * compiled with -fPIE, instead of -fPIC, if possible and should be built as
49
- * Position Independent Executable (PIE) so that linker won't optimize
50
- * R_386_GOT32X relocation to its fixed symbol address. Older
51
- * linkers generate R_386_32 relocations against locally defined symbols,
52
- * _bss, _ebss, _got, _egot and _end, in PIE. It isn't wrong, just less
53
- * optimal than R_386_RELATIVE. But the x86 kernel fails to properly handle
54
- * R_386_32 relocations when relocating the kernel. To generate
55
- * R_386_RELATIVE relocations, we mark _bss, _ebss, _got, _egot and _end as
56
- * hidden:
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.
5740 */
5841 .hidden _bss
5942 .hidden _ebss
60
- .hidden _got
61
- .hidden _egot
6243 .hidden _end
6344
6445 __HEAD
65
-ENTRY(startup_32)
46
+SYM_FUNC_START(startup_32)
6647 cld
67
- /*
68
- * Test KEEP_SEGMENTS flag to see if the bootloader is asking
69
- * us to not reload segments
70
- */
71
- testb $KEEP_SEGMENTS, BP_loadflags(%esi)
72
- jnz 1f
73
-
7448 cli
75
- movl $__BOOT_DS, %eax
76
- movl %eax, %ds
77
- movl %eax, %es
78
- movl %eax, %fs
79
- movl %eax, %gs
80
- movl %eax, %ss
81
-1:
8249
8350 /*
8451 * Calculate the delta between where we were compiled to run
....@@ -90,17 +57,46 @@
9057 */
9158 leal (BP_scratch+4)(%esi), %esp
9259 call 1f
93
-1: popl %ebp
94
- subl $1b, %ebp
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
9575
9676 /*
97
- * %ebp contains the address we are loaded at by the boot loader and %ebx
98
- * contains the address where we should move the kernel image temporarily
99
- * for safe in-place decompression.
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.
10083 */
10184
10285 #ifdef CONFIG_RELOCATABLE
103
- movl %ebp, %ebx
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
+
104100 movl BP_kernel_alignment(%esi), %eax
105101 decl %eax
106102 addl %eax, %ebx
....@@ -112,13 +108,13 @@
112108 movl $LOAD_PHYSICAL_ADDR, %ebx
113109 1:
114110
111
+ movl %ebx, %ebp // Save the output address for later
115112 /* Target address to relocate to for decompression */
116
- movl BP_init_size(%esi), %eax
117
- subl $_end, %eax
118
- addl %eax, %ebx
113
+ addl BP_init_size(%esi), %ebx
114
+ subl $_end@GOTOFF, %ebx
119115
120116 /* Set up the stack */
121
- leal boot_stack_end(%ebx), %esp
117
+ leal boot_stack_end@GOTOFF(%ebx), %esp
122118
123119 /* Zero EFLAGS */
124120 pushl $0
....@@ -129,8 +125,8 @@
129125 * where decompression in place becomes safe.
130126 */
131127 pushl %esi
132
- leal (_bss-4)(%ebp), %esi
133
- leal (_bss-4)(%ebx), %edi
128
+ leal (_bss@GOTOFF-4)(%edx), %esi
129
+ leal (_bss@GOTOFF-4)(%ebx), %edi
134130 movl $(_bss - startup_32), %ecx
135131 shrl $2, %ecx
136132 std
....@@ -138,122 +134,61 @@
138134 cld
139135 popl %esi
140136
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
+
141146 /*
142147 * Jump to the relocated address.
143148 */
144
- leal relocated(%ebx), %eax
149
+ leal .Lrelocated@GOTOFF(%ebx), %eax
145150 jmp *%eax
146
-ENDPROC(startup_32)
151
+SYM_FUNC_END(startup_32)
147152
148153 #ifdef CONFIG_EFI_STUB
149
-/*
150
- * We don't need the return address, so set up the stack so efi_main() can find
151
- * its arguments.
152
- */
153
-ENTRY(efi_pe_entry)
154
+SYM_FUNC_START(efi32_stub_entry)
155
+SYM_FUNC_START_ALIAS(efi_stub_entry)
154156 add $0x4, %esp
155
-
156
- call 1f
157
-1: popl %esi
158
- subl $1b, %esi
159
-
160
- popl %ecx
161
- movl %ecx, efi32_config(%esi) /* Handle */
162
- popl %ecx
163
- movl %ecx, efi32_config+8(%esi) /* EFI System table pointer */
164
-
165
- /* Relocate efi_config->call() */
166
- leal efi32_config(%esi), %eax
167
- add %esi, 40(%eax)
168
- pushl %eax
169
-
170
- call make_boot_params
171
- cmpl $0, %eax
172
- je fail
173
- movl %esi, BP_code32_start(%eax)
174
- popl %ecx
175
- pushl %eax
176
- pushl %ecx
177
- jmp 2f /* Skip efi_config initialization */
178
-ENDPROC(efi_pe_entry)
179
-
180
-ENTRY(efi32_stub_entry)
181
- add $0x4, %esp
182
- popl %ecx
183
- popl %edx
184
-
185
- call 1f
186
-1: popl %esi
187
- subl $1b, %esi
188
-
189
- movl %ecx, efi32_config(%esi) /* Handle */
190
- movl %edx, efi32_config+8(%esi) /* EFI System table pointer */
191
-
192
- /* Relocate efi_config->call() */
193
- leal efi32_config(%esi), %eax
194
- add %esi, 40(%eax)
195
- pushl %eax
196
-2:
157
+ movl 8(%esp), %esi /* save boot_params pointer */
197158 call efi_main
198
- cmpl $0, %eax
199
- movl %eax, %esi
200
- jne 2f
201
-fail:
202
- /* EFI init failed, so hang. */
203
- hlt
204
- jmp fail
205
-2:
206
- movl BP_code32_start(%esi), %eax
207
- leal startup_32(%eax), %eax
159
+ /* efi_main returns the possibly relocated address of startup_32 */
208160 jmp *%eax
209
-ENDPROC(efi32_stub_entry)
161
+SYM_FUNC_END(efi32_stub_entry)
162
+SYM_FUNC_END_ALIAS(efi_stub_entry)
210163 #endif
211164
212165 .text
213
-relocated:
166
+SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
214167
215168 /*
216169 * Clear BSS (stack is currently empty)
217170 */
218171 xorl %eax, %eax
219
- leal _bss(%ebx), %edi
220
- leal _ebss(%ebx), %ecx
172
+ leal _bss@GOTOFF(%ebx), %edi
173
+ leal _ebss@GOTOFF(%ebx), %ecx
221174 subl %edi, %ecx
222175 shrl $2, %ecx
223176 rep stosl
224177
225178 /*
226
- * Adjust our own GOT
227
- */
228
- leal _got(%ebx), %edx
229
- leal _egot(%ebx), %ecx
230
-1:
231
- cmpl %ecx, %edx
232
- jae 2f
233
- addl %ebx, (%edx)
234
- addl $4, %edx
235
- jmp 1b
236
-2:
237
-
238
-/*
239179 * Do the extraction, and jump to the new kernel..
240180 */
241
- /* push arguments for extract_kernel: */
242
- pushl $z_output_len /* decompressed length, end of relocs */
181
+ /* push arguments for extract_kernel: */
243182
244
- movl BP_init_size(%esi), %eax
245
- subl $_end, %eax
246
- movl %ebx, %ebp
247
- subl %eax, %ebp
248
- pushl %ebp /* output address */
249
-
250
- pushl $z_input_len /* input_len */
251
- leal input_data(%ebx), %eax
252
- pushl %eax /* input_data */
253
- leal boot_heap(%ebx), %eax
254
- pushl %eax /* heap area */
255
- pushl %esi /* real mode pointer */
256
- call extract_kernel /* returns kernel location in %eax */
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 */
257192 addl $24, %esp
258193
259194 /*
....@@ -261,14 +196,21 @@
261196 */
262197 xorl %ebx, %ebx
263198 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)
264211
265212 #ifdef CONFIG_EFI_STUB
266
- .data
267
-efi32_config:
268
- .fill 5,8,0
269
- .long efi_call_phys
270
- .long 0
271
- .byte 0
213
+SYM_DATA(image_offset, .long 0)
272214 #endif
273215
274216 /*