History

Merge tag 'efi-next-for-v6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi

Pull EFI updates from Ard Biesheuvel: - Decouple mixed mode startup code from the traditional x86 decompressor - Revert zero-length file hack in efivarfs - Prevent EFI zboot from using the CopyMem/SetMem boot services after ExitBootServices() - Update EFI zboot to use the ZLIB/ZSTD library interfaces directly * tag 'efi-next-for-v6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi: efi/libstub: Avoid legacy decompressor zlib/zstd wrappers efi/libstub: Avoid CopyMem/SetMem EFI services after ExitBootServices efi: efibc: change kmalloc(size * count, ...) to kmalloc_array() efivarfs: Revert "allow creation of zero length files" x86/efi/mixed: Move mixed mode startup code into libstub x86/efi/mixed: Simplify and document thunking logic x86/efi/mixed: Remove dependency on legacy startup_32 code x86/efi/mixed: Set up 1:1 mapping of lower 4GiB in the stub x86/efi/mixed: Factor out and clean up long mode entry x86/efi/mixed: Check CPU compatibility without relying on verify_cpu() x86/efistub: Merge PE and handover entrypoints

Linus Torvalds committed 1 year ago

Commit 1fa753c2 parents 3b9ea5b 0dc175414 files · +452 −436Browse files

Unified · Split

14 files
  1. arch/x86/boot/compressed/Makefile +0 −1
  2. arch/x86/boot/compressed/efi_mixed.S +0 −341
  3. arch/x86/boot/compressed/head_64.S +0 −7
  4. drivers/firmware/efi/efibc.c +1 −1
  5. drivers/firmware/efi/libstub/Makefile +9 −1
  6. drivers/firmware/efi/libstub/efistub.h +3 −0
  7. drivers/firmware/efi/libstub/intrinsics.c +26 −0
  8. drivers/firmware/efi/libstub/x86-mixed.S +253 −0
  9. drivers/firmware/efi/libstub/x86-stub.c +29 −23
  10. drivers/firmware/efi/libstub/zboot-decompress-gzip.c +68 −0
  11. drivers/firmware/efi/libstub/zboot-decompress-zstd.c +49 −0
  12. drivers/firmware/efi/libstub/zboot.c +9 −56
  13. drivers/firmware/efi/libstub/zboot.lds +1 −0
  14. fs/efivarfs/file.c +4 −6
arch/x86/boot/compressed/Makefile+0−1
@@ -106,7 +106,6 @@ vmlinux-objs-$(CONFIG_INTEL_TDX_GUEST) += $(obj)/tdx.o $(obj)/tdcall.o $(obj)/td · 105 unmodified lines
106106 vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY) += $(obj)/mem.o
107107
108108 vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
109−vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
110109 vmlinux-libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
111110
112111 $(obj)/vmlinux: $(vmlinux-objs-y) $(vmlinux-libs-y) FORCE
arch/x86/boot/compressed/efi_mixed.S+0−341
@@ -1,341 +0,0 @@
1−/* SPDX-License-Identifier: GPL-2.0 */
2−/*
3− * Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming
4− *
5− * Early support for invoking 32-bit EFI services from a 64-bit kernel.
6− *
7− * Because this thunking occurs before ExitBootServices() we have to
8− * restore the firmware's 32-bit GDT and IDT before we make EFI service
9− * calls.
10− *
11− * On the plus side, we don't have to worry about mangling 64-bit
12− * addresses into 32-bits because we're executing with an identity
13− * mapped pagetable and haven't transitioned to 64-bit virtual addresses
14− * yet.
15− */
16−
17−#include <linux/linkage.h>
18−#include <asm/asm-offsets.h>
19−#include <asm/msr.h>
20−#include <asm/page_types.h>
21−#include <asm/processor-flags.h>
22−#include <asm/segment.h>
23−#include <asm/setup.h>
24−
25− .code64
26− .text
27−/*
28− * When booting in 64-bit mode on 32-bit EFI firmware, startup_64_mixed_mode()
29− * is the first thing that runs after switching to long mode. Depending on
30− * whether the EFI handover protocol or the compat entry point was used to
31− * enter the kernel, it will either branch to the common 64-bit EFI stub
32− * entrypoint efi_stub_entry() directly, or via the 64-bit EFI PE/COFF
33− * entrypoint efi_pe_entry(). In the former case, the bootloader must provide a
34− * struct bootparams pointer as the third argument, so the presence of such a
35− * pointer is used to disambiguate.
36− *
37− * +--------------+
38− * +------------------+ +------------+ +------>| efi_pe_entry |
39− * | efi32_pe_entry |---->| | | +-----------+--+
40− * +------------------+ | | +------+----------------+ |
41− * | startup_32 |---->| startup_64_mixed_mode | |
42− * +------------------+ | | +------+----------------+ |
43− * | efi32_stub_entry |---->| | | |
44− * +------------------+ +------------+ | |
45− * V |
46− * +------------+ +----------------+ |
47− * | startup_64 |<----| efi_stub_entry |<--------+
48− * +------------+ +----------------+
49− */
50−SYM_FUNC_START(startup_64_mixed_mode)
51− lea efi32_boot_args(%rip), %rdx
52− mov 0(%rdx), %edi
53− mov 4(%rdx), %esi
54−
55− /* Switch to the firmware's stack */
56− movl efi32_boot_sp(%rip), %esp
57− andl $~7, %esp
58−
59−#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
60− mov 8(%rdx), %edx // saved bootparams pointer
61− test %edx, %edx
62− jnz efi_stub_entry
63−#endif
64− /*
65− * efi_pe_entry uses MS calling convention, which requires 32 bytes of
66− * shadow space on the stack even if all arguments are passed in
67− * registers. We also need an additional 8 bytes for the space that
68− * would be occupied by the return address, and this also results in
69− * the correct stack alignment for entry.
70− */
71− sub $40, %rsp
72− mov %rdi, %rcx // MS calling convention
73− mov %rsi, %rdx
74− jmp efi_pe_entry
75−SYM_FUNC_END(startup_64_mixed_mode)
76−
77−SYM_FUNC_START(__efi64_thunk)
78− push %rbp
79− push %rbx
80−
81− movl %ds, %eax
82− push %rax
83− movl %es, %eax
84− push %rax
85− movl %ss, %eax
86− push %rax
87−
88− /* Copy args passed on stack */
89− movq 0x30(%rsp), %rbp
90− movq 0x38(%rsp), %rbx
91− movq 0x40(%rsp), %rax
92−
93− /*
94− * Convert x86-64 ABI params to i386 ABI
95− */
96− subq $64, %rsp
97− movl %esi, 0x0(%rsp)
98− movl %edx, 0x4(%rsp)
99− movl %ecx, 0x8(%rsp)
100− movl %r8d, 0xc(%rsp)
101− movl %r9d, 0x10(%rsp)
102− movl %ebp, 0x14(%rsp)
103− movl %ebx, 0x18(%rsp)
104− movl %eax, 0x1c(%rsp)
105−
106− leaq 0x20(%rsp), %rbx
107− sgdt (%rbx)
108− sidt 16(%rbx)
109−
110− leaq 1f(%rip), %rbp
111−
112− /*
113− * Switch to IDT and GDT with 32-bit segments. These are the firmware
114− * GDT and IDT that were installed when the kernel started executing.
115− * The pointers were saved by the efi32_entry() routine below.
116− *
117− * Pass the saved DS selector to the 32-bit code, and use far return to
118− * restore the saved CS selector.
119− */
120− lidt efi32_boot_idt(%rip)
121− lgdt efi32_boot_gdt(%rip)
122−
123− movzwl efi32_boot_ds(%rip), %edx
124− movzwq efi32_boot_cs(%rip), %rax
125− pushq %rax
126− leaq efi_enter32(%rip), %rax
127− pushq %rax
128− lretq
129−
130−1: addq $64, %rsp
131− movq %rdi, %rax
132−
133− pop %rbx
134− movl %ebx, %ss
135− pop %rbx
136− movl %ebx, %es
137− pop %rbx
138− movl %ebx, %ds
139− /* Clear out 32-bit selector from FS and GS */
140− xorl %ebx, %ebx
141− movl %ebx, %fs
142− movl %ebx, %gs
143−
144− pop %rbx
145− pop %rbp
146− RET
147−SYM_FUNC_END(__efi64_thunk)
148−
149− .code32
150−#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
151−SYM_FUNC_START(efi32_stub_entry)
152− call 1f
153−1: popl %ecx
154− leal (efi32_boot_args - 1b)(%ecx), %ebx
155−
156− /* Clear BSS */
157− xorl %eax, %eax
158− leal (_bss - 1b)(%ecx), %edi
159− leal (_ebss - 1b)(%ecx), %ecx
160− subl %edi, %ecx
161− shrl $2, %ecx
162− cld
163− rep stosl
164−
165− add $0x4, %esp /* Discard return address */
166− popl %ecx
167− popl %edx
168− popl %esi
169− movl %esi, 8(%ebx)
170− jmp efi32_entry
171−SYM_FUNC_END(efi32_stub_entry)
172−#endif
173−
174−/*
175− * EFI service pointer must be in %edi.
176− *
177− * The stack should represent the 32-bit calling convention.
178− */
179−SYM_FUNC_START_LOCAL(efi_enter32)
180− /* Load firmware selector into data and stack segment registers */
181− movl %edx, %ds
182− movl %edx, %es
183− movl %edx, %fs
184− movl %edx, %gs
185− movl %edx, %ss
186−
187− /* Reload pgtables */
188− movl %cr3, %eax
189− movl %eax, %cr3
190−
191− /* Disable paging */
192− movl %cr0, %eax
193− btrl $X86_CR0_PG_BIT, %eax
194− movl %eax, %cr0
195−
196− /* Disable long mode via EFER */
197− movl $MSR_EFER, %ecx
198− rdmsr
199− btrl $_EFER_LME, %eax
200− wrmsr
201−
202− call *%edi
203−
204− /* We must preserve return value */
205− movl %eax, %edi
206−
207− /*
208− * Some firmware will return with interrupts enabled. Be sure to
209− * disable them before we switch GDTs and IDTs.
210− */
211− cli
212−
213− lidtl 16(%ebx)
214− lgdtl (%ebx)
215−
216− movl %cr4, %eax
217− btsl $(X86_CR4_PAE_BIT), %eax
218− movl %eax, %cr4
219−
220− movl %cr3, %eax
221− movl %eax, %cr3
222−
223− movl $MSR_EFER, %ecx
224− rdmsr
225− btsl $_EFER_LME, %eax
226− wrmsr
227−
228− xorl %eax, %eax
229− lldt %ax
230−
231− pushl $__KERNEL_CS
232− pushl %ebp
233−
234− /* Enable paging */
235− movl %cr0, %eax
236− btsl $X86_CR0_PG_BIT, %eax
237− movl %eax, %cr0
238− lret
239−SYM_FUNC_END(efi_enter32)
240−
241−/*
242− * This is the common EFI stub entry point for mixed mode.
243− *
244− * Arguments: %ecx image handle
245− * %edx EFI system table pointer
246− *
247− * Since this is the point of no return for ordinary execution, no registers
248− * are considered live except for the function parameters. [Note that the EFI
249− * stub may still exit and return to the firmware using the Exit() EFI boot
250− * service.]
251− */
252−SYM_FUNC_START_LOCAL(efi32_entry)
253− call 1f
254−1: pop %ebx
255−
256− /* Save firmware GDTR and code/data selectors */
257− sgdtl (efi32_boot_gdt - 1b)(%ebx)
258− movw %cs, (efi32_boot_cs - 1b)(%ebx)
259− movw %ds, (efi32_boot_ds - 1b)(%ebx)
260−
261− /* Store firmware IDT descriptor */
262− sidtl (efi32_boot_idt - 1b)(%ebx)
263−
264− /* Store firmware stack pointer */
265− movl %esp, (efi32_boot_sp - 1b)(%ebx)
266−
267− /* Store boot arguments */
268− leal (efi32_boot_args - 1b)(%ebx), %ebx
269− movl %ecx, 0(%ebx)
270− movl %edx, 4(%ebx)
271− movb $0x0, 12(%ebx) // efi_is64
272−
273− /*
274− * Allocate some memory for a temporary struct boot_params, which only
275− * needs the minimal pieces that startup_32() relies on.
276− */
277− subl $PARAM_SIZE, %esp
278− movl %esp, %esi
279− movl $PAGE_SIZE, BP_kernel_alignment(%esi)
280− movl $_end - 1b, BP_init_size(%esi)
281− subl $startup_32 - 1b, BP_init_size(%esi)
282−
283− /* Disable paging */
284− movl %cr0, %eax
285− btrl $X86_CR0_PG_BIT, %eax
286− movl %eax, %cr0
287−
288− jmp startup_32
289−SYM_FUNC_END(efi32_entry)
290−
291−/*
292− * efi_status_t efi32_pe_entry(efi_handle_t image_handle,
293− * efi_system_table_32_t *sys_table)
294− */
295−SYM_FUNC_START(efi32_pe_entry)
296− pushl %ebp
297− movl %esp, %ebp
298− pushl %ebx // save callee-save registers
299− pushl %edi
300−
301− call verify_cpu // check for long mode support
302− testl %eax, %eax
303− movl $0x80000003, %eax // EFI_UNSUPPORTED
304− jnz 2f
305−
306− movl 8(%ebp), %ecx // image_handle
307− movl 12(%ebp), %edx // sys_table
308− jmp efi32_entry // pass %ecx, %edx
309− // no other registers remain live
310−
311−2: popl %edi // restore callee-save registers
312− popl %ebx
313− leave
314− RET
315−SYM_FUNC_END(efi32_pe_entry)
316−
317−#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
318− .org efi32_stub_entry + 0x200
319− .code64
320−SYM_FUNC_START_NOALIGN(efi64_stub_entry)
321− jmp efi_handover_entry
322−SYM_FUNC_END(efi64_stub_entry)
323−#endif
324−
325− .data
326− .balign 8
327−SYM_DATA_START_LOCAL(efi32_boot_gdt)
328− .word 0
329− .quad 0
330−SYM_DATA_END(efi32_boot_gdt)
331−
332−SYM_DATA_START_LOCAL(efi32_boot_idt)
333− .word 0
334− .quad 0
335−SYM_DATA_END(efi32_boot_idt)
336−
337−SYM_DATA_LOCAL(efi32_boot_cs, .word 0)
338−SYM_DATA_LOCAL(efi32_boot_ds, .word 0)
339−SYM_DATA_LOCAL(efi32_boot_sp, .long 0)
340−SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0)
341−SYM_DATA(efi_is64, .byte 1)
arch/x86/boot/compressed/head_64.S+0−7
@@ -263,13 +263,6 @@ SYM_FUNC_START(startup_32) · 262 unmodified lines
263263 * used to perform that far jump.
264264 */
265265 leal rva(startup_64)(%ebp), %eax
266−#ifdef CONFIG_EFI_MIXED
267− cmpb $1, rva(efi_is64)(%ebp)
268− je 1f
269− leal rva(startup_64_mixed_mode)(%ebp), %eax
270−1:
271−#endif
272−
273266 pushl $__KERNEL_CS
274267 pushl %eax
275268
drivers/firmware/efi/efibc.c+1−1
@@ -47,7 +47,7 @@ static int efibc_reboot_notifier_call(struct notifier_block *notifier, · 46 unmodified lines
4747 if (ret || !data)
4848 return NOTIFY_DONE;
4949
50− wdata = kmalloc(MAX_DATA_LEN * sizeof(efi_char16_t), GFP_KERNEL);
50+ wdata = kmalloc_array(MAX_DATA_LEN, sizeof(efi_char16_t), GFP_KERNEL);
5151 if (!wdata)
5252 return NOTIFY_DONE;
5353
drivers/firmware/efi/libstub/Makefile+9−1
@@ -62,6 +62,8 @@ KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO), $(KBUILD_CFLAGS)) · 61 unmodified lines
6262 # `-fdata-sections` flag from KBUILD_CFLAGS_KERNEL
6363 KBUILD_CFLAGS_KERNEL := $(filter-out -fdata-sections, $(KBUILD_CFLAGS_KERNEL))
6464
65+KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
66+
6567 lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \
6668 file.o mem.o random.o randomalloc.o pci.o \
6769 skip_spaces.o lib-cmdline.o lib-ctype.o \
@@ -83,13 +85,19 @@ lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \ · 15 unmodified lines
8385 lib-$(CONFIG_ARM) += arm32-stub.o
8486 lib-$(CONFIG_ARM64) += kaslr.o arm64.o arm64-stub.o smbios.o
8587 lib-$(CONFIG_X86) += x86-stub.o smbios.o
88+lib-$(CONFIG_EFI_MIXED) += x86-mixed.o
8689 lib-$(CONFIG_X86_64) += x86-5lvl.o
8790 lib-$(CONFIG_RISCV) += kaslr.o riscv.o riscv-stub.o
8891 lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o
8992
9093 CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
9194
92−zboot-obj-$(CONFIG_RISCV) := lib-clz_ctz.o lib-ashldi3.o
95+zboot-obj-y := zboot-decompress-gzip.o
96+CFLAGS_zboot-decompress-gzip.o += -I$(srctree)/lib/zlib_inflate
97+zboot-obj-$(CONFIG_KERNEL_ZSTD) := zboot-decompress-zstd.o lib-xxhash.o
98+CFLAGS_zboot-decompress-zstd.o += -I$(srctree)/lib/zstd
99+
100+zboot-obj-$(CONFIG_RISCV) += lib-clz_ctz.o lib-ashldi3.o
93101 lib-$(CONFIG_EFI_ZBOOT) += zboot.o $(zboot-obj-y)
94102
95103 lib-$(CONFIG_UNACCEPTED_MEMORY) += unaccepted_memory.o bitmap.o find.o
drivers/firmware/efi/libstub/efistub.h+3−0
@@ -1234,4 +1234,7 @@ void process_unaccepted_memory(u64 start, u64 end); · 1233 unmodified lines
12341234 void accept_memory(phys_addr_t start, unsigned long size);
12351235 void arch_accept_memory(phys_addr_t start, phys_addr_t end);
12361236
1237+efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size);
1238+efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen);
1239+
12371240 #endif
drivers/firmware/efi/libstub/intrinsics.c+26−0
@@ -15,8 +15,31 @@ void *__memmove(void *__dest, const void *__src, size_t count) __alias(memmove); · 14 unmodified lines
1515 void *__memset(void *s, int c, size_t count) __alias(memset);
1616 #endif
1717
18+static void *efistub_memmove(u8 *dst, const u8 *src, size_t len)
19+{
20+ if (src > dst || dst >= (src + len))
21+ for (size_t i = 0; i < len; i++)
22+ dst[i] = src[i];
23+ else
24+ for (ssize_t i = len - 1; i >= 0; i--)
25+ dst[i] = src[i];
26+
27+ return dst;
28+}
29+
30+static void *efistub_memset(void *dst, int c, size_t len)
31+{
32+ for (u8 *d = dst; len--; d++)
33+ *d = c;
34+
35+ return dst;
36+}
37+
1838 void *memcpy(void *dst, const void *src, size_t len)
1939 {
40+ if (efi_table_attr(efi_system_table, boottime) == NULL)
41+ return efistub_memmove(dst, src, len);
42+
2043 efi_bs_call(copy_mem, dst, src, len);
2144 return dst;
2245 }
@@ -25,6 +48,9 @@ extern void *memmove(void *dst, const void *src, size_t len) __alias(memcpy); · 2 unmodified lines
2548
2649 void *memset(void *dst, int c, size_t len)
2750 {
51+ if (efi_table_attr(efi_system_table, boottime) == NULL)
52+ return efistub_memset(dst, c, len);
53+
2854 efi_bs_call(set_mem, dst, len, c & U8_MAX);
2955 return dst;
3056 }
drivers/firmware/efi/libstub/x86-mixed.S+253−0
@@ -0,0 +1,253 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
2+/*
3+ * Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming
4+ *
5+ * Early support for invoking 32-bit EFI services from a 64-bit kernel.
6+ *
7+ * Because this thunking occurs before ExitBootServices() we have to
8+ * restore the firmware's 32-bit GDT and IDT before we make EFI service
9+ * calls.
10+ *
11+ * On the plus side, we don't have to worry about mangling 64-bit
12+ * addresses into 32-bits because we're executing with an identity
13+ * mapped pagetable and haven't transitioned to 64-bit virtual addresses
14+ * yet.
15+ */
16+
17+#include <linux/linkage.h>
18+#include <asm/desc_defs.h>
19+#include <asm/msr.h>
20+#include <asm/page_types.h>
21+#include <asm/pgtable_types.h>
22+#include <asm/processor-flags.h>
23+#include <asm/segment.h>
24+
25+ .text
26+ .code32
27+#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
28+SYM_FUNC_START(efi32_stub_entry)
29+ call 1f
30+1: popl %ecx
31+
32+ /* Clear BSS */
33+ xorl %eax, %eax
34+ leal (_bss - 1b)(%ecx), %edi
35+ leal (_ebss - 1b)(%ecx), %ecx
36+ subl %edi, %ecx
37+ shrl $2, %ecx
38+ cld
39+ rep stosl
40+
41+ add $0x4, %esp /* Discard return address */
42+ movl 8(%esp), %ebx /* struct boot_params pointer */
43+ jmp efi32_startup
44+SYM_FUNC_END(efi32_stub_entry)
45+#endif
46+
47+/*
48+ * Called using a far call from __efi64_thunk() below, using the x86_64 SysV
49+ * ABI (except for R8/R9 which are inaccessible to 32-bit code - EAX/EBX are
50+ * used instead). EBP+16 points to the arguments passed via the stack.
51+ *
52+ * The first argument (EDI) is a pointer to the boot service or protocol, to
53+ * which the remaining arguments are passed, each truncated to 32 bits.
54+ */
55+SYM_FUNC_START_LOCAL(efi_enter32)
56+ /*
57+ * Convert x86-64 SysV ABI params to i386 ABI
58+ */
59+ pushl 32(%ebp) /* Up to 3 args passed via the stack */
60+ pushl 24(%ebp)
61+ pushl 16(%ebp)
62+ pushl %ebx /* R9 */
63+ pushl %eax /* R8 */
64+ pushl %ecx
65+ pushl %edx
66+ pushl %esi
67+
68+ /* Disable paging */
69+ movl %cr0, %eax
70+ btrl $X86_CR0_PG_BIT, %eax
71+ movl %eax, %cr0
72+
73+ /* Disable long mode via EFER */
74+ movl $MSR_EFER, %ecx
75+ rdmsr
76+ btrl $_EFER_LME, %eax
77+ wrmsr
78+
79+ call *%edi
80+
81+ /* We must preserve return value */
82+ movl %eax, %edi
83+
84+ call efi32_enable_long_mode
85+
86+ addl $32, %esp
87+ movl %edi, %eax
88+ lret
89+SYM_FUNC_END(efi_enter32)
90+
91+ .code64
92+SYM_FUNC_START(__efi64_thunk)
93+ push %rbp
94+ movl %esp, %ebp
95+ push %rbx
96+
97+ /* Move args #5 and #6 into 32-bit accessible registers */
98+ movl %r8d, %eax
99+ movl %r9d, %ebx
100+
101+ lcalll *efi32_call(%rip)
102+
103+ pop %rbx
104+ pop %rbp
105+ RET
106+SYM_FUNC_END(__efi64_thunk)
107+
108+ .code32
109+SYM_FUNC_START_LOCAL(efi32_enable_long_mode)
110+ movl %cr4, %eax
111+ btsl $(X86_CR4_PAE_BIT), %eax
112+ movl %eax, %cr4
113+
114+ movl $MSR_EFER, %ecx
115+ rdmsr
116+ btsl $_EFER_LME, %eax
117+ wrmsr
118+
119+ /* Disable interrupts - the firmware's IDT does not work in long mode */
120+ cli
121+
122+ /* Enable paging */
123+ movl %cr0, %eax
124+ btsl $X86_CR0_PG_BIT, %eax
125+ movl %eax, %cr0
126+ ret
127+SYM_FUNC_END(efi32_enable_long_mode)
128+
129+/*
130+ * This is the common EFI stub entry point for mixed mode. It sets up the GDT
131+ * and page tables needed for 64-bit execution, after which it calls the
132+ * common 64-bit EFI entrypoint efi_stub_entry().
133+ *
134+ * Arguments: 0(%esp) image handle
135+ * 4(%esp) EFI system table pointer
136+ * %ebx struct boot_params pointer (or NULL)
137+ *
138+ * Since this is the point of no return for ordinary execution, no registers
139+ * are considered live except for the function parameters. [Note that the EFI
140+ * stub may still exit and return to the firmware using the Exit() EFI boot
141+ * service.]
142+ */
143+SYM_FUNC_START_LOCAL(efi32_startup)
144+ movl %esp, %ebp
145+
146+ subl $8, %esp
147+ sgdtl (%esp) /* Save GDT descriptor to the stack */
148+ movl 2(%esp), %esi /* Existing GDT pointer */
149+ movzwl (%esp), %ecx /* Existing GDT limit */
150+ inc %ecx /* Existing GDT size */
151+ andl $~7, %ecx /* Ensure size is multiple of 8 */
152+
153+ subl %ecx, %esp /* Allocate new GDT */
154+ andl $~15, %esp /* Realign the stack */
155+ movl %esp, %edi /* New GDT address */
156+ leal 7(%ecx), %eax /* New GDT limit */
157+ pushw %cx /* Push 64-bit CS (for LJMP below) */
158+ pushl %edi /* Push new GDT address */
159+ pushw %ax /* Push new GDT limit */
160+
161+ /* Copy GDT to the stack and add a 64-bit code segment at the end */
162+ movl $GDT_ENTRY(DESC_CODE64, 0, 0xfffff) & 0xffffffff, (%edi,%ecx)
163+ movl $GDT_ENTRY(DESC_CODE64, 0, 0xfffff) >> 32, 4(%edi,%ecx)
164+ shrl $2, %ecx
165+ cld
166+ rep movsl /* Copy the firmware GDT */
167+ lgdtl (%esp) /* Switch to the new GDT */
168+
169+ call 1f
170+1: pop %edi
171+
172+ /* Record mixed mode entry */
173+ movb $0x0, (efi_is64 - 1b)(%edi)
174+
175+ /* Set up indirect far call to re-enter 32-bit mode */
176+ leal (efi32_call - 1b)(%edi), %eax
177+ addl %eax, (%eax)
178+ movw %cs, 4(%eax)
179+
180+ /* Disable paging */
181+ movl %cr0, %eax
182+ btrl $X86_CR0_PG_BIT, %eax
183+ movl %eax, %cr0
184+
185+ /* Set up 1:1 mapping */
186+ leal (pte - 1b)(%edi), %eax
187+ movl $_PAGE_PRESENT | _PAGE_RW | _PAGE_PSE, %ecx
188+ leal (_PAGE_PRESENT | _PAGE_RW)(%eax), %edx
189+2: movl %ecx, (%eax)
190+ addl $8, %eax
191+ addl $PMD_SIZE, %ecx
192+ jnc 2b
193+
194+ movl $PAGE_SIZE, %ecx
195+ .irpc l, 0123
196+ movl %edx, \l * 8(%eax)
197+ addl %ecx, %edx
198+ .endr
199+ addl %ecx, %eax
200+ movl %edx, (%eax)
201+ movl %eax, %cr3
202+
203+ call efi32_enable_long_mode
204+
205+ /* Set up far jump to 64-bit mode (CS is already on the stack) */
206+ leal (efi_stub_entry - 1b)(%edi), %eax
207+ movl %eax, 2(%esp)
208+
209+ movl 0(%ebp), %edi
210+ movl 4(%ebp), %esi
211+ movl %ebx, %edx
212+ ljmpl *2(%esp)
213+SYM_FUNC_END(efi32_startup)
214+
215+/*
216+ * efi_status_t efi32_pe_entry(efi_handle_t image_handle,
217+ * efi_system_table_32_t *sys_table)
218+ */
219+SYM_FUNC_START(efi32_pe_entry)
220+ pushl %ebx // save callee-save registers
221+
222+ /* Check whether the CPU supports long mode */
223+ movl $0x80000001, %eax // assume extended info support
224+ cpuid
225+ btl $29, %edx // check long mode bit
226+ jnc 1f
227+ leal 8(%esp), %esp // preserve stack alignment
228+ xor %ebx, %ebx // no struct boot_params pointer
229+ jmp efi32_startup // only ESP and EBX remain live
230+1: movl $0x80000003, %eax // EFI_UNSUPPORTED
231+ popl %ebx
232+ RET
233+SYM_FUNC_END(efi32_pe_entry)
234+
235+#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
236+ .org efi32_stub_entry + 0x200
237+ .code64
238+SYM_FUNC_START_NOALIGN(efi64_stub_entry)
239+ jmp efi_handover_entry
240+SYM_FUNC_END(efi64_stub_entry)
241+#endif
242+
243+ .data
244+ .balign 8
245+SYM_DATA_START_LOCAL(efi32_call)
246+ .long efi_enter32 - .
247+ .word 0x0
248+SYM_DATA_END(efi32_call)
249+SYM_DATA(efi_is64, .byte 1)
250+
251+ .bss
252+ .balign PAGE_SIZE
253+SYM_DATA_LOCAL(pte, .fill 6 * PAGE_SIZE, 1, 0)
drivers/firmware/efi/libstub/x86-stub.c+29−23
@@ -397,17 +397,13 @@ static void __noreturn efi_exit(efi_handle_t handle, efi_status_t status) · 396 unmodified lines
397397 asm("hlt");
398398 }
399399
400−void __noreturn efi_stub_entry(efi_handle_t handle,
401− efi_system_table_t *sys_table_arg,
402− struct boot_params *boot_params);
403−
404400 /*
405401 * Because the x86 boot code expects to be passed a boot_params we
406402 * need to create one ourselves (usually the bootloader would create
407403 * one for us).
408404 */
409−efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
410− efi_system_table_t *sys_table_arg)
405+static efi_status_t efi_allocate_bootparams(efi_handle_t handle,
406+ struct boot_params **bp)
411407 {
412408 efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
413409 struct boot_params *boot_params;
@@ -416,21 +412,15 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, · 2 unmodified lines
416412 unsigned long alloc;
417413 char *cmdline_ptr;
418414
419− efi_system_table = sys_table_arg;
420−
421− /* Check if we were booted by the EFI firmware */
422− if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
423− efi_exit(handle, EFI_INVALID_PARAMETER);
424−
425415 status = efi_bs_call(handle_protocol, handle, &proto, (void **)&image);
426416 if (status != EFI_SUCCESS) {
427417 efi_err("Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
428− efi_exit(handle, status);
418+ return status;
429419 }
430420
431421 status = efi_allocate_pages(PARAM_SIZE, &alloc, ULONG_MAX);
432422 if (status != EFI_SUCCESS)
433− efi_exit(handle, status);
423+ return status;
434424
435425 boot_params = memset((void *)alloc, 0x0, PARAM_SIZE);
436426 hdr = &boot_params->hdr;
@@ -446,14 +436,14 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, · 9 unmodified lines
446436 cmdline_ptr = efi_convert_cmdline(image);
447437 if (!cmdline_ptr) {
448438 efi_free(PARAM_SIZE, alloc);
449− efi_exit(handle, EFI_OUT_OF_RESOURCES);
439+ return EFI_OUT_OF_RESOURCES;
450440 }
451441
452442 efi_set_u64_split((unsigned long)cmdline_ptr, &hdr->cmd_line_ptr,
453443 &boot_params->ext_cmd_line_ptr);
454444
455− efi_stub_entry(handle, sys_table_arg, boot_params);
456− /* not reached */
445+ *bp = boot_params;
446+ return EFI_SUCCESS;
457447 }
458448
459449 static void add_e820ext(struct boot_params *params,
@@ -740,13 +730,16 @@ static efi_status_t parse_options(const char *cmdline) · 280 unmodified lines
740730 return efi_parse_options(cmdline);
741731 }
742732
743−static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
733+static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry,
734+ struct boot_params *boot_params)
744735 {
745736 unsigned long virt_addr = LOAD_PHYSICAL_ADDR;
746737 unsigned long addr, alloc_size, entry;
747738 efi_status_t status;
748739 u32 seed[2] = {};
749740
741+ boot_params_ptr = boot_params;
742+
750743 /* determine the required size of the allocation */
751744 alloc_size = ALIGN(max_t(unsigned long, output_len, kernel_total_size),
752745 MIN_KERNEL_ALIGN);
@@ -777,7 +770,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry) · 24 unmodified lines
777770 seed[0] = 0;
778771 }
779772
780− boot_params_ptr->hdr.loadflags |= KASLR_FLAG;
773+ boot_params->hdr.loadflags |= KASLR_FLAG;
781774 }
782775
783776 status = efi_random_alloc(alloc_size, CONFIG_PHYSICAL_ALIGN, &addr,
@@ -815,20 +808,27 @@ static void __noreturn enter_kernel(unsigned long kernel_addr, · 31 unmodified lines
815808 void __noreturn efi_stub_entry(efi_handle_t handle,
816809 efi_system_table_t *sys_table_arg,
817810 struct boot_params *boot_params)
811+
818812 {
819813 efi_guid_t guid = EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID;
820− struct setup_header *hdr = &boot_params->hdr;
821814 const struct linux_efi_initrd *initrd = NULL;
822815 unsigned long kernel_entry;
816+ struct setup_header *hdr;
823817 efi_status_t status;
824818
825− boot_params_ptr = boot_params;
826−
827819 efi_system_table = sys_table_arg;
828820 /* Check if we were booted by the EFI firmware */
829821 if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
830822 efi_exit(handle, EFI_INVALID_PARAMETER);
831823
824+ if (!IS_ENABLED(CONFIG_EFI_HANDOVER_PROTOCOL) || !boot_params) {
825+ status = efi_allocate_bootparams(handle, &boot_params);
826+ if (status != EFI_SUCCESS)
827+ efi_exit(handle, status);
828+ }
829+
830+ hdr = &boot_params->hdr;
831+
832832 if (have_unsupported_snp_features())
833833 efi_exit(handle, EFI_UNSUPPORTED);
834834
@@ -870,7 +870,7 @@ void __noreturn efi_stub_entry(efi_handle_t handle, · 35 unmodified lines
870870 if (efi_mem_encrypt > 0)
871871 hdr->xloadflags |= XLF_MEM_ENCRYPTION;
872872
873− status = efi_decompress_kernel(&kernel_entry);
873+ status = efi_decompress_kernel(&kernel_entry, boot_params);
874874 if (status != EFI_SUCCESS) {
875875 efi_err("Failed to decompress kernel\n");
876876 goto fail;
@@ -940,6 +940,12 @@ fail: · 63 unmodified lines
940940 efi_exit(handle, status);
941941 }
942942
943+efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
944+ efi_system_table_t *sys_table_arg)
945+{
946+ efi_stub_entry(handle, sys_table_arg, NULL);
947+}
948+
943949 #ifdef CONFIG_EFI_HANDOVER_PROTOCOL
944950 void efi_handover_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg,
945951 struct boot_params *boot_params)
drivers/firmware/efi/libstub/zboot-decompress-gzip.c+68−0
@@ -0,0 +1,68 @@
1+// SPDX-License-Identifier: GPL-2.0
2+
3+#include <linux/efi.h>
4+#include <linux/zlib.h>
5+
6+#include <asm/efi.h>
7+
8+#include "efistub.h"
9+
10+#include "inftrees.c"
11+#include "inffast.c"
12+#include "inflate.c"
13+
14+extern unsigned char _gzdata_start[], _gzdata_end[];
15+extern u32 __aligned(1) payload_size;
16+
17+static struct z_stream_s stream;
18+
19+efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size)
20+{
21+ efi_status_t status;
22+ int rc;
23+
24+ /* skip the 10 byte header, assume no recorded filename */
25+ stream.next_in = _gzdata_start + 10;
26+ stream.avail_in = _gzdata_end - stream.next_in;
27+
28+ status = efi_allocate_pages(zlib_inflate_workspacesize(),
29+ (unsigned long *)&stream.workspace,
30+ ULONG_MAX);
31+ if (status != EFI_SUCCESS)
32+ return status;
33+
34+ rc = zlib_inflateInit2(&stream, -MAX_WBITS);
35+ if (rc != Z_OK) {
36+ efi_err("failed to initialize GZIP decompressor: %d\n", rc);
37+ status = EFI_LOAD_ERROR;
38+ goto out;
39+ }
40+
41+ *alloc_size = payload_size;
42+ return EFI_SUCCESS;
43+out:
44+ efi_free(zlib_inflate_workspacesize(), (unsigned long)stream.workspace);
45+ return status;
46+}
47+
48+efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen)
49+{
50+ int rc;
51+
52+ stream.next_out = out;
53+ stream.avail_out = outlen;
54+
55+ rc = zlib_inflate(&stream, 0);
56+ zlib_inflateEnd(&stream);
57+
58+ efi_free(zlib_inflate_workspacesize(), (unsigned long)stream.workspace);
59+
60+ if (rc != Z_STREAM_END) {
61+ efi_err("GZIP decompression failed with status %d\n", rc);
62+ return EFI_LOAD_ERROR;
63+ }
64+
65+ efi_cache_sync_image((unsigned long)out, outlen);
66+
67+ return EFI_SUCCESS;
68+}
drivers/firmware/efi/libstub/zboot-decompress-zstd.c+49−0
@@ -0,0 +1,49 @@
1+// SPDX-License-Identifier: GPL-2.0
2+
3+#include <linux/efi.h>
4+#include <linux/zstd.h>
5+
6+#include <asm/efi.h>
7+
8+#include "decompress_sources.h"
9+#include "efistub.h"
10+
11+extern unsigned char _gzdata_start[], _gzdata_end[];
12+extern u32 __aligned(1) payload_size;
13+
14+static size_t wksp_size;
15+static void *wksp;
16+
17+efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size)
18+{
19+ efi_status_t status;
20+
21+ wksp_size = zstd_dctx_workspace_bound();
22+ status = efi_allocate_pages(wksp_size, (unsigned long *)&wksp, ULONG_MAX);
23+ if (status != EFI_SUCCESS)
24+ return status;
25+
26+ *alloc_size = payload_size;
27+ return EFI_SUCCESS;
28+}
29+
30+efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen)
31+{
32+ zstd_dctx *dctx = zstd_init_dctx(wksp, wksp_size);
33+ size_t ret;
34+ int retval;
35+
36+ ret = zstd_decompress_dctx(dctx, out, outlen, _gzdata_start,
37+ _gzdata_end - _gzdata_start - 4);
38+ efi_free(wksp_size, (unsigned long)wksp);
39+
40+ retval = zstd_get_error_code(ret);
41+ if (retval) {
42+ efi_err("ZSTD-decompression failed with status %d\n", retval);
43+ return EFI_LOAD_ERROR;
44+ }
45+
46+ efi_cache_sync_image((unsigned long)out, outlen);
47+
48+ return EFI_SUCCESS;
49+}
drivers/firmware/efi/libstub/zboot.c+9−56
@@ -7,36 +7,6 @@ · 6 unmodified lines
77
88 #include "efistub.h"
99
10−static unsigned char zboot_heap[SZ_256K] __aligned(64);
11−static unsigned long free_mem_ptr, free_mem_end_ptr;
12−
13−#define STATIC static
14−#if defined(CONFIG_KERNEL_GZIP)
15−#include "../../../../lib/decompress_inflate.c"
16−#elif defined(CONFIG_KERNEL_LZ4)
17−#include "../../../../lib/decompress_unlz4.c"
18−#elif defined(CONFIG_KERNEL_LZMA)
19−#include "../../../../lib/decompress_unlzma.c"
20−#elif defined(CONFIG_KERNEL_LZO)
21−#include "../../../../lib/decompress_unlzo.c"
22−#elif defined(CONFIG_KERNEL_XZ)
23−#undef memcpy
24−#define memcpy memcpy
25−#undef memmove
26−#define memmove memmove
27−#include "../../../../lib/decompress_unxz.c"
28−#elif defined(CONFIG_KERNEL_ZSTD)
29−#include "../../../../lib/decompress_unzstd.c"
30−#endif
31−
32−extern char efi_zboot_header[];
33−extern char _gzdata_start[], _gzdata_end[];
34−
35−static void error(char *x)
36−{
37− efi_err("EFI decompressor: %s\n", x);
38−}
39−
4010 static unsigned long alloc_preferred_address(unsigned long alloc_size)
4111 {
4212 #ifdef EFI_KIMG_PREFERRED_ADDRESS
@@ -64,22 +34,17 @@ struct screen_info *alloc_screen_info(void) · 21 unmodified lines
6434 asmlinkage efi_status_t __efiapi
6535 efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
6636 {
67− unsigned long compressed_size = _gzdata_end - _gzdata_start;
37+ char *cmdline_ptr __free(efi_pool) = NULL;
6838 unsigned long image_base, alloc_size;
6939 efi_loaded_image_t *image;
7040 efi_status_t status;
71− char *cmdline_ptr;
72− int ret;
7341
7442 WRITE_ONCE(efi_system_table, systab);
7543
76− free_mem_ptr = (unsigned long)&zboot_heap;
77− free_mem_end_ptr = free_mem_ptr + sizeof(zboot_heap);
78−
7944 status = efi_bs_call(handle_protocol, handle,
8045 &LOADED_IMAGE_PROTOCOL_GUID, (void **)&image);
8146 if (status != EFI_SUCCESS) {
82− error("Failed to locate parent's loaded image protocol");
47+ efi_err("Failed to locate parent's loaded image protocol\n");
8348 return status;
8449 }
8550
@@ -89,9 +54,9 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab) · 3 unmodified lines
8954
9055 efi_info("Decompressing Linux Kernel...\n");
9156
92− // SizeOfImage from the compressee's PE/COFF header
93− alloc_size = round_up(get_unaligned_le32(_gzdata_end - 4),
94− EFI_ALLOC_ALIGN);
57+ status = efi_zboot_decompress_init(&alloc_size);
58+ if (status != EFI_SUCCESS)
59+ return status;
9560
9661 // If the architecture has a preferred address for the image,
9762 // try that first.
@@ -122,26 +87,14 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab) · 24 unmodified lines
12287 seed, EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT);
12388 if (status != EFI_SUCCESS) {
12489 efi_err("Failed to allocate memory\n");
125− goto free_cmdline;
90+ return status;
12691 }
12792 }
12893
129− // Decompress the payload into the newly allocated buffer.
130− ret = __decompress(_gzdata_start, compressed_size, NULL, NULL,
131− (void *)image_base, alloc_size, NULL, error);
132− if (ret < 0) {
133− error("Decompression failed");
134− status = EFI_DEVICE_ERROR;
135− goto free_image;
136− }
137−
138− efi_cache_sync_image(image_base, alloc_size);
139−
140− status = efi_stub_common(handle, image, image_base, cmdline_ptr);
94+ // Decompress the payload into the newly allocated buffer
95+ status = efi_zboot_decompress((void *)image_base, alloc_size) ?:
96+ efi_stub_common(handle, image, image_base, cmdline_ptr);
14197
142−free_image:
14398 efi_free(alloc_size, image_base);
144−free_cmdline:
145− efi_bs_call(free_pool, cmdline_ptr);
14699 return status;
147100 }
drivers/firmware/efi/libstub/zboot.lds+1−0
@@ -17,6 +17,7 @@ SECTIONS · 16 unmodified lines
1717 .rodata : ALIGN(8) {
1818 __efistub__gzdata_start = .;
1919 *(.gzdata)
20+ __efistub_payload_size = . - 4;
2021 __efistub__gzdata_end = .;
2122 *(.rodata* .init.rodata* .srodata*)
2223
fs/efivarfs/file.c+4−6
@@ -57,11 +57,10 @@ static ssize_t efivarfs_file_write(struct file *file, · 56 unmodified lines
5757
5858 if (bytes == -ENOENT) {
5959 /*
60− * FIXME: temporary workaround for fwupdate, signal
61− * failed write with a 1 to keep created but not
62− * written files
60+ * zero size signals to release that the write deleted
61+ * the variable
6362 */
64− i_size_write(inode, 1);
63+ i_size_write(inode, 0);
6564 } else {
6665 i_size_write(inode, datasize + sizeof(attributes));
6766 inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
@@ -125,8 +124,7 @@ static int efivarfs_file_release(struct inode *inode, struct file *file) · 57 unmodified lines
125124 struct efivar_entry *var = inode->i_private;
126125
127126 inode_lock(inode);
128− /* FIXME: temporary work around for fwupdate */
129− var->removed = (--var->open_count == 0 && i_size_read(inode) == 1);
127+ var->removed = (--var->open_count == 0 && i_size_read(inode) == 0);
130128 inode_unlock(inode);
131129
132130 if (var->removed)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t