Skip to content

Commit bd9e99f

Browse files
committed
Merge tag 'x86_boot_for_v6.6_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 boot updates from Borislav Petkov: "Avoid the baremetal decompressor code when booting on an EFI machine. This is mandated by the current tightening of EFI executables requirements when used in a secure boot scenario. More specifically, an EFI executable cannot have a single section with RWX permissions, which conflicts with the in-place kernel decompression that is done today. Instead, the things required by the booting kernel image are done in the EFI stub now. Work by Ard Biesheuvel" * tag 'x86_boot_for_v6.6_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (23 commits) x86/efistub: Avoid legacy decompressor when doing EFI boot x86/efistub: Perform SNP feature test while running in the firmware efi/libstub: Add limit argument to efi_random_alloc() x86/decompressor: Factor out kernel decompression and relocation x86/decompressor: Move global symbol references to C code decompress: Use 8 byte alignment x86/efistub: Prefer EFI memory attributes protocol over DXE services x86/efistub: Perform 4/5 level paging switch from the stub x86/decompressor: Merge trampoline cleanup with switching code x86/decompressor: Pass pgtable address to trampoline directly x86/decompressor: Only call the trampoline when changing paging levels x86/decompressor: Call trampoline directly from C code x86/decompressor: Avoid the need for a stack in the 32-bit trampoline x86/decompressor: Use standard calling convention for trampoline x86/decompressor: Call trampoline as a normal function x86/decompressor: Assign paging related global variables earlier x86/decompressor: Store boot_params pointer in callee save register x86/efistub: Clear BSS in EFI handover protocol entrypoint x86/decompressor: Avoid magic offsets for EFI handover entrypoint x86/efistub: Simplify and clean up handover entry code ...
2 parents 6f49693 + a1b87d5 commit bd9e99f

File tree

24 files changed

+587
-562
lines changed

24 files changed

+587
-562
lines changed

Documentation/arch/x86/boot.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1417,7 +1417,7 @@ execution context provided by the EFI firmware.
14171417

14181418
The function prototype for the handover entry point looks like this::
14191419

1420-
efi_main(void *handle, efi_system_table_t *table, struct boot_params *bp)
1420+
efi_stub_entry(void *handle, efi_system_table_t *table, struct boot_params *bp)
14211421
14221422
'handle' is the EFI image handle passed to the boot loader by the EFI
14231423
firmware, 'table' is the EFI system table - these are the first two

arch/x86/boot/compressed/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ LDFLAGS_vmlinux += -z noexecstack
7474
ifeq ($(CONFIG_LD_IS_BFD),y)
7575
LDFLAGS_vmlinux += $(call ld-option,--no-warn-rwx-segments)
7676
endif
77+
ifeq ($(CONFIG_EFI_STUB),y)
78+
# ensure that the static EFI stub library will be pulled in, even if it is
79+
# never referenced explicitly from the startup code
80+
LDFLAGS_vmlinux += -u efi_pe_entry
81+
endif
7782
LDFLAGS_vmlinux += -T
7883

7984
hostprogs := mkpiggy

arch/x86/boot/compressed/efi_mixed.S

Lines changed: 42 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
* When booting in 64-bit mode on 32-bit EFI firmware, startup_64_mixed_mode()
2727
* is the first thing that runs after switching to long mode. Depending on
2828
* whether the EFI handover protocol or the compat entry point was used to
29-
* enter the kernel, it will either branch to the 64-bit EFI handover
30-
* entrypoint at offset 0x390 in the image, or to the 64-bit EFI PE/COFF
29+
* enter the kernel, it will either branch to the common 64-bit EFI stub
30+
* entrypoint efi_stub_entry() directly, or via the 64-bit EFI PE/COFF
3131
* entrypoint efi_pe_entry(). In the former case, the bootloader must provide a
3232
* struct bootparams pointer as the third argument, so the presence of such a
3333
* pointer is used to disambiguate.
@@ -37,21 +37,23 @@
3737
* | efi32_pe_entry |---->| | | +-----------+--+
3838
* +------------------+ | | +------+----------------+ |
3939
* | startup_32 |---->| startup_64_mixed_mode | |
40-
* +------------------+ | | +------+----------------+ V
41-
* | efi32_stub_entry |---->| | | +------------------+
42-
* +------------------+ +------------+ +---->| efi64_stub_entry |
43-
* +-------------+----+
44-
* +------------+ +----------+ |
45-
* | startup_64 |<----| efi_main |<--------------+
46-
* +------------+ +----------+
40+
* +------------------+ | | +------+----------------+ |
41+
* | efi32_stub_entry |---->| | | |
42+
* +------------------+ +------------+ | |
43+
* V |
44+
* +------------+ +----------------+ |
45+
* | startup_64 |<----| efi_stub_entry |<--------+
46+
* +------------+ +----------------+
4747
*/
4848
SYM_FUNC_START(startup_64_mixed_mode)
4949
lea efi32_boot_args(%rip), %rdx
5050
mov 0(%rdx), %edi
5151
mov 4(%rdx), %esi
52+
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
5253
mov 8(%rdx), %edx // saved bootparams pointer
5354
test %edx, %edx
54-
jnz efi64_stub_entry
55+
jnz efi_stub_entry
56+
#endif
5557
/*
5658
* efi_pe_entry uses MS calling convention, which requires 32 bytes of
5759
* shadow space on the stack even if all arguments are passed in
@@ -138,6 +140,28 @@ SYM_FUNC_START(__efi64_thunk)
138140
SYM_FUNC_END(__efi64_thunk)
139141

140142
.code32
143+
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
144+
SYM_FUNC_START(efi32_stub_entry)
145+
call 1f
146+
1: popl %ecx
147+
148+
/* Clear BSS */
149+
xorl %eax, %eax
150+
leal (_bss - 1b)(%ecx), %edi
151+
leal (_ebss - 1b)(%ecx), %ecx
152+
subl %edi, %ecx
153+
shrl $2, %ecx
154+
cld
155+
rep stosl
156+
157+
add $0x4, %esp /* Discard return address */
158+
popl %ecx
159+
popl %edx
160+
popl %esi
161+
jmp efi32_entry
162+
SYM_FUNC_END(efi32_stub_entry)
163+
#endif
164+
141165
/*
142166
* EFI service pointer must be in %edi.
143167
*
@@ -218,7 +242,7 @@ SYM_FUNC_END(efi_enter32)
218242
* stub may still exit and return to the firmware using the Exit() EFI boot
219243
* service.]
220244
*/
221-
SYM_FUNC_START(efi32_entry)
245+
SYM_FUNC_START_LOCAL(efi32_entry)
222246
call 1f
223247
1: pop %ebx
224248

@@ -245,19 +269,13 @@ SYM_FUNC_START(efi32_entry)
245269
jmp startup_32
246270
SYM_FUNC_END(efi32_entry)
247271

248-
#define ST32_boottime 60 // offsetof(efi_system_table_32_t, boottime)
249-
#define BS32_handle_protocol 88 // offsetof(efi_boot_services_32_t, handle_protocol)
250-
#define LI32_image_base 32 // offsetof(efi_loaded_image_32_t, image_base)
251-
252272
/*
253273
* efi_status_t efi32_pe_entry(efi_handle_t image_handle,
254274
* efi_system_table_32_t *sys_table)
255275
*/
256276
SYM_FUNC_START(efi32_pe_entry)
257277
pushl %ebp
258278
movl %esp, %ebp
259-
pushl %eax // dummy push to allocate loaded_image
260-
261279
pushl %ebx // save callee-save registers
262280
pushl %edi
263281

@@ -266,48 +284,8 @@ SYM_FUNC_START(efi32_pe_entry)
266284
movl $0x80000003, %eax // EFI_UNSUPPORTED
267285
jnz 2f
268286

269-
call 1f
270-
1: pop %ebx
271-
272-
/* Get the loaded image protocol pointer from the image handle */
273-
leal -4(%ebp), %eax
274-
pushl %eax // &loaded_image
275-
leal (loaded_image_proto - 1b)(%ebx), %eax
276-
pushl %eax // pass the GUID address
277-
pushl 8(%ebp) // pass the image handle
278-
279-
/*
280-
* Note the alignment of the stack frame.
281-
* sys_table
282-
* handle <-- 16-byte aligned on entry by ABI
283-
* return address
284-
* frame pointer
285-
* loaded_image <-- local variable
286-
* saved %ebx <-- 16-byte aligned here
287-
* saved %edi
288-
* &loaded_image
289-
* &loaded_image_proto
290-
* handle <-- 16-byte aligned for call to handle_protocol
291-
*/
292-
293-
movl 12(%ebp), %eax // sys_table
294-
movl ST32_boottime(%eax), %eax // sys_table->boottime
295-
call *BS32_handle_protocol(%eax) // sys_table->boottime->handle_protocol
296-
addl $12, %esp // restore argument space
297-
testl %eax, %eax
298-
jnz 2f
299-
300287
movl 8(%ebp), %ecx // image_handle
301288
movl 12(%ebp), %edx // sys_table
302-
movl -4(%ebp), %esi // loaded_image
303-
movl LI32_image_base(%esi), %esi // loaded_image->image_base
304-
leal (startup_32 - 1b)(%ebx), %ebp // runtime address of startup_32
305-
/*
306-
* We need to set the image_offset variable here since startup_32() will
307-
* use it before we get to the 64-bit efi_pe_entry() in C code.
308-
*/
309-
subl %esi, %ebp // calculate image_offset
310-
movl %ebp, (image_offset - 1b)(%ebx) // save image_offset
311289
xorl %esi, %esi
312290
jmp efi32_entry // pass %ecx, %edx, %esi
313291
// no other registers remain live
@@ -318,14 +296,13 @@ SYM_FUNC_START(efi32_pe_entry)
318296
RET
319297
SYM_FUNC_END(efi32_pe_entry)
320298

321-
.section ".rodata"
322-
/* EFI loaded image protocol GUID */
323-
.balign 4
324-
SYM_DATA_START_LOCAL(loaded_image_proto)
325-
.long 0x5b1b31a1
326-
.word 0x9562, 0x11d2
327-
.byte 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b
328-
SYM_DATA_END(loaded_image_proto)
299+
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
300+
.org efi32_stub_entry + 0x200
301+
.code64
302+
SYM_FUNC_START_NOALIGN(efi64_stub_entry)
303+
jmp efi_handover_entry
304+
SYM_FUNC_END(efi64_stub_entry)
305+
#endif
329306

330307
.data
331308
.balign 8

arch/x86/boot/compressed/head_32.S

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,6 @@ SYM_FUNC_START(startup_32)
8484

8585
#ifdef CONFIG_RELOCATABLE
8686
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-
10087
movl BP_kernel_alignment(%esi), %eax
10188
decl %eax
10289
addl %eax, %ebx
@@ -150,17 +137,6 @@ SYM_FUNC_START(startup_32)
150137
jmp *%eax
151138
SYM_FUNC_END(startup_32)
152139

153-
#ifdef CONFIG_EFI_STUB
154-
SYM_FUNC_START(efi32_stub_entry)
155-
add $0x4, %esp
156-
movl 8(%esp), %esi /* save boot_params pointer */
157-
call efi_main
158-
/* efi_main returns the possibly relocated address of startup_32 */
159-
jmp *%eax
160-
SYM_FUNC_END(efi32_stub_entry)
161-
SYM_FUNC_ALIAS(efi_stub_entry, efi32_stub_entry)
162-
#endif
163-
164140
.text
165141
SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
166142

@@ -179,13 +155,7 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
179155
*/
180156
/* push arguments for extract_kernel: */
181157

182-
pushl output_len@GOTOFF(%ebx) /* decompressed length, end of relocs */
183158
pushl %ebp /* output address */
184-
pushl input_len@GOTOFF(%ebx) /* input_len */
185-
leal input_data@GOTOFF(%ebx), %eax
186-
pushl %eax /* input_data */
187-
leal boot_heap@GOTOFF(%ebx), %eax
188-
pushl %eax /* heap area */
189159
pushl %esi /* real mode pointer */
190160
call extract_kernel /* returns kernel entry point in %eax */
191161
addl $24, %esp
@@ -213,8 +183,6 @@ SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end)
213183
*/
214184
.bss
215185
.balign 4
216-
boot_heap:
217-
.fill BOOT_HEAP_SIZE, 1, 0
218186
boot_stack:
219187
.fill BOOT_STACK_SIZE, 1, 0
220188
boot_stack_end:

0 commit comments

Comments
 (0)