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
106vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY) += $(obj)/mem.o106vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY) += $(obj)/mem.o
107 107
108vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o108vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
109vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
110vmlinux-libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a109vmlinux-libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
111 110
112$(obj)/vmlinux: $(vmlinux-objs-y) $(vmlinux-libs-y) FORCE111$(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 */
50SYM_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
75SYM_FUNC_END(startup_64_mixed_mode)
76
77SYM_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
1301: 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
147SYM_FUNC_END(__efi64_thunk)
148
149 .code32
150#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
151SYM_FUNC_START(efi32_stub_entry)
152 call 1f
1531: 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
171SYM_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 */
179SYM_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
239SYM_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 */
252SYM_FUNC_START_LOCAL(efi32_entry)
253 call 1f
2541: 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
289SYM_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 */
295SYM_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
3112: popl %edi // restore callee-save registers
312 popl %ebx
313 leave
314 RET
315SYM_FUNC_END(efi32_pe_entry)
316
317#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
318 .org efi32_stub_entry + 0x200
319 .code64
320SYM_FUNC_START_NOALIGN(efi64_stub_entry)
321 jmp efi_handover_entry
322SYM_FUNC_END(efi64_stub_entry)
323#endif
324
325 .data
326 .balign 8
327SYM_DATA_START_LOCAL(efi32_boot_gdt)
328 .word 0
329 .quad 0
330SYM_DATA_END(efi32_boot_gdt)
331
332SYM_DATA_START_LOCAL(efi32_boot_idt)
333 .word 0
334 .quad 0
335SYM_DATA_END(efi32_boot_idt)
336
337SYM_DATA_LOCAL(efi32_boot_cs, .word 0)
338SYM_DATA_LOCAL(efi32_boot_ds, .word 0)
339SYM_DATA_LOCAL(efi32_boot_sp, .long 0)
340SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0)
341SYM_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
263 * used to perform that far jump.263 * used to perform that far jump.
264 */264 */
265 leal rva(startup_64)(%ebp), %eax265 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
2701:
271#endif
272
273 pushl $__KERNEL_CS266 pushl $__KERNEL_CS
274 pushl %eax267 pushl %eax
275 268
drivers/firmware/efi/efibc.c+1−1
@@ -47,7 +47,7 @@ static int efibc_reboot_notifier_call(struct notifier_block *notifier, · 46 unmodified lines
47 if (ret || !data)47 if (ret || !data)
48 return NOTIFY_DONE;48 return NOTIFY_DONE;
49 49
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);
51 if (!wdata)51 if (!wdata)
52 return NOTIFY_DONE;52 return NOTIFY_DONE;
53 53
drivers/firmware/efi/libstub/Makefile+9−1
@@ -62,6 +62,8 @@ KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO), $(KBUILD_CFLAGS)) · 61 unmodified lines
62# `-fdata-sections` flag from KBUILD_CFLAGS_KERNEL62# `-fdata-sections` flag from KBUILD_CFLAGS_KERNEL
63KBUILD_CFLAGS_KERNEL := $(filter-out -fdata-sections, $(KBUILD_CFLAGS_KERNEL))63KBUILD_CFLAGS_KERNEL := $(filter-out -fdata-sections, $(KBUILD_CFLAGS_KERNEL))
64 64
65KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
66
65lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \67lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \
66 file.o mem.o random.o randomalloc.o pci.o \68 file.o mem.o random.o randomalloc.o pci.o \
67 skip_spaces.o lib-cmdline.o lib-ctype.o \69 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
83lib-$(CONFIG_ARM) += arm32-stub.o85lib-$(CONFIG_ARM) += arm32-stub.o
84lib-$(CONFIG_ARM64) += kaslr.o arm64.o arm64-stub.o smbios.o86lib-$(CONFIG_ARM64) += kaslr.o arm64.o arm64-stub.o smbios.o
85lib-$(CONFIG_X86) += x86-stub.o smbios.o87lib-$(CONFIG_X86) += x86-stub.o smbios.o
88lib-$(CONFIG_EFI_MIXED) += x86-mixed.o
86lib-$(CONFIG_X86_64) += x86-5lvl.o89lib-$(CONFIG_X86_64) += x86-5lvl.o
87lib-$(CONFIG_RISCV) += kaslr.o riscv.o riscv-stub.o90lib-$(CONFIG_RISCV) += kaslr.o riscv.o riscv-stub.o
88lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o91lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o
89 92
90CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)93CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
91 94
92zboot-obj-$(CONFIG_RISCV) := lib-clz_ctz.o lib-ashldi3.o95zboot-obj-y := zboot-decompress-gzip.o
96CFLAGS_zboot-decompress-gzip.o += -I$(srctree)/lib/zlib_inflate
97zboot-obj-$(CONFIG_KERNEL_ZSTD) := zboot-decompress-zstd.o lib-xxhash.o
98CFLAGS_zboot-decompress-zstd.o += -I$(srctree)/lib/zstd
99
100zboot-obj-$(CONFIG_RISCV) += lib-clz_ctz.o lib-ashldi3.o
93lib-$(CONFIG_EFI_ZBOOT) += zboot.o $(zboot-obj-y)101lib-$(CONFIG_EFI_ZBOOT) += zboot.o $(zboot-obj-y)
94 102
95lib-$(CONFIG_UNACCEPTED_MEMORY) += unaccepted_memory.o bitmap.o find.o103lib-$(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
1234void accept_memory(phys_addr_t start, unsigned long size);1234void accept_memory(phys_addr_t start, unsigned long size);
1235void arch_accept_memory(phys_addr_t start, phys_addr_t end);1235void arch_accept_memory(phys_addr_t start, phys_addr_t end);
1236 1236
1237efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size);
1238efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen);
1239
1237#endif1240#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
15void *__memset(void *s, int c, size_t count) __alias(memset);15void *__memset(void *s, int c, size_t count) __alias(memset);
16#endif16#endif
17 17
18static 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
30static 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
18void *memcpy(void *dst, const void *src, size_t len)38void *memcpy(void *dst, const void *src, size_t len)
19{39{
40 if (efi_table_attr(efi_system_table, boottime) == NULL)
41 return efistub_memmove(dst, src, len);
42
20 efi_bs_call(copy_mem, dst, src, len);43 efi_bs_call(copy_mem, dst, src, len);
21 return dst;44 return dst;
22}45}
@@ -25,6 +48,9 @@ extern void *memmove(void *dst, const void *src, size_t len) __alias(memcpy); · 2 unmodified lines
25 48
26void *memset(void *dst, int c, size_t len)49void *memset(void *dst, int c, size_t len)
27{50{
51 if (efi_table_attr(efi_system_table, boottime) == NULL)
52 return efistub_memset(dst, c, len);
53
28 efi_bs_call(set_mem, dst, len, c & U8_MAX);54 efi_bs_call(set_mem, dst, len, c & U8_MAX);
29 return dst;55 return dst;
30}56}
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
28SYM_FUNC_START(efi32_stub_entry)
29 call 1f
301: 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
44SYM_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 */
55SYM_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
89SYM_FUNC_END(efi_enter32)
90
91 .code64
92SYM_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
106SYM_FUNC_END(__efi64_thunk)
107
108 .code32
109SYM_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
127SYM_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 */
143SYM_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
1701: 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
1892: 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)
213SYM_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 */
219SYM_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
2301: movl $0x80000003, %eax // EFI_UNSUPPORTED
231 popl %ebx
232 RET
233SYM_FUNC_END(efi32_pe_entry)
234
235#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
236 .org efi32_stub_entry + 0x200
237 .code64
238SYM_FUNC_START_NOALIGN(efi64_stub_entry)
239 jmp efi_handover_entry
240SYM_FUNC_END(efi64_stub_entry)
241#endif
242
243 .data
244 .balign 8
245SYM_DATA_START_LOCAL(efi32_call)
246 .long efi_enter32 - .
247 .word 0x0
248SYM_DATA_END(efi32_call)
249SYM_DATA(efi_is64, .byte 1)
250
251 .bss
252 .balign PAGE_SIZE
253SYM_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
397 asm("hlt");397 asm("hlt");
398}398}
399 399
400void __noreturn efi_stub_entry(efi_handle_t handle,
401 efi_system_table_t *sys_table_arg,
402 struct boot_params *boot_params);
403
404/*400/*
405 * Because the x86 boot code expects to be passed a boot_params we401 * Because the x86 boot code expects to be passed a boot_params we
406 * need to create one ourselves (usually the bootloader would create402 * need to create one ourselves (usually the bootloader would create
407 * one for us).403 * one for us).
408 */404 */
409efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,405static efi_status_t efi_allocate_bootparams(efi_handle_t handle,
410 efi_system_table_t *sys_table_arg)406 struct boot_params **bp)
411{407{
412 efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;408 efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
413 struct boot_params *boot_params;409 struct boot_params *boot_params;
@@ -416,21 +412,15 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, · 2 unmodified lines
416 unsigned long alloc;412 unsigned long alloc;
417 char *cmdline_ptr;413 char *cmdline_ptr;
418 414
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
425 status = efi_bs_call(handle_protocol, handle, &proto, (void **)&image);415 status = efi_bs_call(handle_protocol, handle, &proto, (void **)&image);
426 if (status != EFI_SUCCESS) {416 if (status != EFI_SUCCESS) {
427 efi_err("Failed to get handle for LOADED_IMAGE_PROTOCOL\n");417 efi_err("Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
428 efi_exit(handle, status);418 return status;
429 }419 }
430 420
431 status = efi_allocate_pages(PARAM_SIZE, &alloc, ULONG_MAX);421 status = efi_allocate_pages(PARAM_SIZE, &alloc, ULONG_MAX);
432 if (status != EFI_SUCCESS)422 if (status != EFI_SUCCESS)
433 efi_exit(handle, status);423 return status;
434 424
435 boot_params = memset((void *)alloc, 0x0, PARAM_SIZE);425 boot_params = memset((void *)alloc, 0x0, PARAM_SIZE);
436 hdr = &boot_params->hdr;426 hdr = &boot_params->hdr;
@@ -446,14 +436,14 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, · 9 unmodified lines
446 cmdline_ptr = efi_convert_cmdline(image);436 cmdline_ptr = efi_convert_cmdline(image);
447 if (!cmdline_ptr) {437 if (!cmdline_ptr) {
448 efi_free(PARAM_SIZE, alloc);438 efi_free(PARAM_SIZE, alloc);
449 efi_exit(handle, EFI_OUT_OF_RESOURCES);439 return EFI_OUT_OF_RESOURCES;
450 }440 }
451 441
452 efi_set_u64_split((unsigned long)cmdline_ptr, &hdr->cmd_line_ptr,442 efi_set_u64_split((unsigned long)cmdline_ptr, &hdr->cmd_line_ptr,
453 &boot_params->ext_cmd_line_ptr);443 &boot_params->ext_cmd_line_ptr);
454 444
455 efi_stub_entry(handle, sys_table_arg, boot_params);445 *bp = boot_params;
456 /* not reached */446 return EFI_SUCCESS;
457}447}
458 448
459static void add_e820ext(struct boot_params *params,449static void add_e820ext(struct boot_params *params,
@@ -740,13 +730,16 @@ static efi_status_t parse_options(const char *cmdline) · 280 unmodified lines
740 return efi_parse_options(cmdline);730 return efi_parse_options(cmdline);
741}731}
742 732
743static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)733static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry,
734 struct boot_params *boot_params)
744{735{
745 unsigned long virt_addr = LOAD_PHYSICAL_ADDR;736 unsigned long virt_addr = LOAD_PHYSICAL_ADDR;
746 unsigned long addr, alloc_size, entry;737 unsigned long addr, alloc_size, entry;
747 efi_status_t status;738 efi_status_t status;
748 u32 seed[2] = {};739 u32 seed[2] = {};
749 740
741 boot_params_ptr = boot_params;
742
750 /* determine the required size of the allocation */743 /* determine the required size of the allocation */
751 alloc_size = ALIGN(max_t(unsigned long, output_len, kernel_total_size),744 alloc_size = ALIGN(max_t(unsigned long, output_len, kernel_total_size),
752 MIN_KERNEL_ALIGN);745 MIN_KERNEL_ALIGN);
@@ -777,7 +770,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry) · 24 unmodified lines
777 seed[0] = 0;770 seed[0] = 0;
778 }771 }
779 772
780 boot_params_ptr->hdr.loadflags |= KASLR_FLAG;773 boot_params->hdr.loadflags |= KASLR_FLAG;
781 }774 }
782 775
783 status = efi_random_alloc(alloc_size, CONFIG_PHYSICAL_ALIGN, &addr,776 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
815void __noreturn efi_stub_entry(efi_handle_t handle,808void __noreturn efi_stub_entry(efi_handle_t handle,
816 efi_system_table_t *sys_table_arg,809 efi_system_table_t *sys_table_arg,
817 struct boot_params *boot_params)810 struct boot_params *boot_params)
811
818{812{
819 efi_guid_t guid = EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID;813 efi_guid_t guid = EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID;
820 struct setup_header *hdr = &boot_params->hdr;
821 const struct linux_efi_initrd *initrd = NULL;814 const struct linux_efi_initrd *initrd = NULL;
822 unsigned long kernel_entry;815 unsigned long kernel_entry;
816 struct setup_header *hdr;
823 efi_status_t status;817 efi_status_t status;
824 818
825 boot_params_ptr = boot_params;
826
827 efi_system_table = sys_table_arg;819 efi_system_table = sys_table_arg;
828 /* Check if we were booted by the EFI firmware */820 /* Check if we were booted by the EFI firmware */
829 if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)821 if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
830 efi_exit(handle, EFI_INVALID_PARAMETER);822 efi_exit(handle, EFI_INVALID_PARAMETER);
831 823
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
832 if (have_unsupported_snp_features())832 if (have_unsupported_snp_features())
833 efi_exit(handle, EFI_UNSUPPORTED);833 efi_exit(handle, EFI_UNSUPPORTED);
834 834
@@ -870,7 +870,7 @@ void __noreturn efi_stub_entry(efi_handle_t handle, · 35 unmodified lines
870 if (efi_mem_encrypt > 0)870 if (efi_mem_encrypt > 0)
871 hdr->xloadflags |= XLF_MEM_ENCRYPTION;871 hdr->xloadflags |= XLF_MEM_ENCRYPTION;
872 872
873 status = efi_decompress_kernel(&kernel_entry);873 status = efi_decompress_kernel(&kernel_entry, boot_params);
874 if (status != EFI_SUCCESS) {874 if (status != EFI_SUCCESS) {
875 efi_err("Failed to decompress kernel\n");875 efi_err("Failed to decompress kernel\n");
876 goto fail;876 goto fail;
@@ -940,6 +940,12 @@ fail: · 63 unmodified lines
940 efi_exit(handle, status);940 efi_exit(handle, status);
941}941}
942 942
943efi_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
943#ifdef CONFIG_EFI_HANDOVER_PROTOCOL949#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
944void efi_handover_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg,950void efi_handover_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg,
945 struct boot_params *boot_params)951 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
14extern unsigned char _gzdata_start[], _gzdata_end[];
15extern u32 __aligned(1) payload_size;
16
17static struct z_stream_s stream;
18
19efi_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;
43out:
44 efi_free(zlib_inflate_workspacesize(), (unsigned long)stream.workspace);
45 return status;
46}
47
48efi_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
11extern unsigned char _gzdata_start[], _gzdata_end[];
12extern u32 __aligned(1) payload_size;
13
14static size_t wksp_size;
15static void *wksp;
16
17efi_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
30efi_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
7 7
8#include "efistub.h"8#include "efistub.h"
9 9
10static unsigned char zboot_heap[SZ_256K] __aligned(64);
11static 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
32extern char efi_zboot_header[];
33extern char _gzdata_start[], _gzdata_end[];
34
35static void error(char *x)
36{
37 efi_err("EFI decompressor: %s\n", x);
38}
39
40static unsigned long alloc_preferred_address(unsigned long alloc_size)10static unsigned long alloc_preferred_address(unsigned long alloc_size)
41{11{
42#ifdef EFI_KIMG_PREFERRED_ADDRESS12#ifdef EFI_KIMG_PREFERRED_ADDRESS
@@ -64,22 +34,17 @@ struct screen_info *alloc_screen_info(void) · 21 unmodified lines
64asmlinkage efi_status_t __efiapi34asmlinkage efi_status_t __efiapi
65efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)35efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
66{36{
67 unsigned long compressed_size = _gzdata_end - _gzdata_start;37 char *cmdline_ptr __free(efi_pool) = NULL;
68 unsigned long image_base, alloc_size;38 unsigned long image_base, alloc_size;
69 efi_loaded_image_t *image;39 efi_loaded_image_t *image;
70 efi_status_t status;40 efi_status_t status;
71 char *cmdline_ptr;
72 int ret;
73 41
74 WRITE_ONCE(efi_system_table, systab);42 WRITE_ONCE(efi_system_table, systab);
75 43
76 free_mem_ptr = (unsigned long)&zboot_heap;
77 free_mem_end_ptr = free_mem_ptr + sizeof(zboot_heap);
78
79 status = efi_bs_call(handle_protocol, handle,44 status = efi_bs_call(handle_protocol, handle,
80 &LOADED_IMAGE_PROTOCOL_GUID, (void **)&image);45 &LOADED_IMAGE_PROTOCOL_GUID, (void **)&image);
81 if (status != EFI_SUCCESS) {46 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");
83 return status;48 return status;
84 }49 }
85 50
@@ -89,9 +54,9 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab) · 3 unmodified lines
89 54
90 efi_info("Decompressing Linux Kernel...\n");55 efi_info("Decompressing Linux Kernel...\n");
91 56
92 // SizeOfImage from the compressee's PE/COFF header57 status = efi_zboot_decompress_init(&alloc_size);
93 alloc_size = round_up(get_unaligned_le32(_gzdata_end - 4),58 if (status != EFI_SUCCESS)
94 EFI_ALLOC_ALIGN);59 return status;
95 60
96 // If the architecture has a preferred address for the image,61 // If the architecture has a preferred address for the image,
97 // try that first.62 // try that first.
@@ -122,26 +87,14 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab) · 24 unmodified lines
122 seed, EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT);87 seed, EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT);
123 if (status != EFI_SUCCESS) {88 if (status != EFI_SUCCESS) {
124 efi_err("Failed to allocate memory\n");89 efi_err("Failed to allocate memory\n");
125 goto free_cmdline;90 return status;
126 }91 }
127 }92 }
128 93
129 // Decompress the payload into the newly allocated buffer.94 // Decompress the payload into the newly allocated buffer
130 ret = __decompress(_gzdata_start, compressed_size, NULL, NULL,95 status = efi_zboot_decompress((void *)image_base, alloc_size) ?:
131 (void *)image_base, alloc_size, NULL, error);96 efi_stub_common(handle, image, image_base, cmdline_ptr);
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);
141 97
142free_image:
143 efi_free(alloc_size, image_base);98 efi_free(alloc_size, image_base);
144free_cmdline:
145 efi_bs_call(free_pool, cmdline_ptr);
146 return status;99 return status;
147}100}
drivers/firmware/efi/libstub/zboot.lds+1−0
@@ -17,6 +17,7 @@ SECTIONS · 16 unmodified lines
17 .rodata : ALIGN(8) {17 .rodata : ALIGN(8) {
18 __efistub__gzdata_start = .;18 __efistub__gzdata_start = .;
19 *(.gzdata)19 *(.gzdata)
20 __efistub_payload_size = . - 4;
20 __efistub__gzdata_end = .;21 __efistub__gzdata_end = .;
21 *(.rodata* .init.rodata* .srodata*)22 *(.rodata* .init.rodata* .srodata*)
22 23
fs/efivarfs/file.c+4−6
@@ -57,11 +57,10 @@ static ssize_t efivarfs_file_write(struct file *file, · 56 unmodified lines
57 57
58 if (bytes == -ENOENT) {58 if (bytes == -ENOENT) {
59 /*59 /*
60 * FIXME: temporary workaround for fwupdate, signal60 * zero size signals to release that the write deleted
61 * failed write with a 1 to keep created but not61 * the variable
62 * written files
63 */62 */
64 i_size_write(inode, 1);63 i_size_write(inode, 0);
65 } else {64 } else {
66 i_size_write(inode, datasize + sizeof(attributes));65 i_size_write(inode, datasize + sizeof(attributes));
67 inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));66 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
125 struct efivar_entry *var = inode->i_private;124 struct efivar_entry *var = inode->i_private;
126 125
127 inode_lock(inode);126 inode_lock(inode);
128 /* FIXME: temporary work around for fwupdate */127 var->removed = (--var->open_count == 0 && i_size_read(inode) == 0);
129 var->removed = (--var->open_count == 0 && i_size_read(inode) == 1);
130 inode_unlock(inode);128 inode_unlock(inode);
131 129
132 if (var->removed)130 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