Skip to content

Commit fc4c9f4

Browse files
committed
Merge tag 'efi-next-for-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi
Pull EFI updates from Ard Biesheuvel: "Another fairly sizable pull request, by EFI subsystem standards. Most of the work was done by me, some of it in collaboration with the distro and bootloader folks (GRUB, systemd-boot), where the main focus has been on removing pointless per-arch differences in the way EFI boots a Linux kernel. - Refactor the zboot code so that it incorporates all the EFI stub logic, rather than calling the decompressed kernel as a EFI app. - Add support for initrd= command line option to x86 mixed mode. - Allow initrd= to be used with arbitrary EFI accessible file systems instead of just the one the kernel itself was loaded from. - Move some x86-only handling and manipulation of the EFI memory map into arch/x86, as it is not used anywhere else. - More flexible handling of any random seeds provided by the boot environment (i.e., systemd-boot) so that it becomes available much earlier during the boot. - Allow improved arch-agnostic EFI support in loaders, by setting a uniform baseline of supported features, and adding a generic magic number to the DOS/PE header. This should allow loaders such as GRUB or systemd-boot to reduce the amount of arch-specific handling substantially. - (arm64) Run EFI runtime services from a dedicated stack, and use it to recover from synchronous exceptions that might occur in the firmware code. - (arm64) Ensure that we don't allocate memory outside of the 48-bit addressable physical range. - Make EFI pstore record size configurable - Add support for decoding CXL specific CPER records" * tag 'efi-next-for-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi: (43 commits) arm64: efi: Recover from synchronous exceptions occurring in firmware arm64: efi: Execute runtime services from a dedicated stack arm64: efi: Limit allocations to 48-bit addressable physical region efi: Put Linux specific magic number in the DOS header efi: libstub: Always enable initrd command line loader and bump version efi: stub: use random seed from EFI variable efi: vars: prohibit reading random seed variables efi: random: combine bootloader provided RNG seed with RNG protocol output efi/cper, cxl: Decode CXL Error Log efi/cper, cxl: Decode CXL Protocol Error Section efi: libstub: fix efi_load_initrd_dev_path() kernel-doc comment efi: x86: Move EFI runtime map sysfs code to arch/x86 efi: runtime-maps: Clarify purpose and enable by default for kexec efi: pstore: Add module parameter for setting the record size efi: xen: Set EFI_PARAVIRT for Xen dom0 boot on all architectures efi: memmap: Move manipulation routines into x86 arch tree efi: memmap: Move EFI fake memmap support into x86 arch tree efi: libstub: Undeprecate the command line initrd loader efi: libstub: Add mixed mode support to command line initrd loader efi: libstub: Permit mixed mode return types other than efi_status_t ...
2 parents 717e6eb + e8dfdf3 commit fc4c9f4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2138
-1492
lines changed

MAINTAINERS

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7839,7 +7839,6 @@ F: Documentation/admin-guide/efi-stub.rst
78397839
F: arch/*/include/asm/efi.h
78407840
F: arch/*/kernel/efi.c
78417841
F: arch/arm/boot/compressed/efi-header.S
7842-
F: arch/arm64/kernel/efi-entry.S
78437842
F: arch/x86/platform/efi/
78447843
F: drivers/firmware/efi/
78457844
F: include/linux/efi*.h

arch/arm/include/asm/efi.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ void efi_virtmap_unload(void);
4343

4444
/* arch specific definitions used by the stub code */
4545

46-
struct screen_info *alloc_screen_info(void);
47-
void free_screen_info(struct screen_info *si);
48-
4946
/*
5047
* A reasonable upper bound for the uncompressed kernel size is 32 MBytes,
5148
* so we will reserve that amount of memory. We have no easy way to tell what

arch/arm/kernel/efi.c

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -75,38 +75,13 @@ int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
7575
return 0;
7676
}
7777

78-
static unsigned long __initdata screen_info_table = EFI_INVALID_TABLE_ADDR;
7978
static unsigned long __initdata cpu_state_table = EFI_INVALID_TABLE_ADDR;
8079

8180
const efi_config_table_type_t efi_arch_tables[] __initconst = {
82-
{LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, &screen_info_table},
8381
{LINUX_EFI_ARM_CPU_STATE_TABLE_GUID, &cpu_state_table},
8482
{}
8583
};
8684

87-
static void __init load_screen_info_table(void)
88-
{
89-
struct screen_info *si;
90-
91-
if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
92-
si = early_memremap_ro(screen_info_table, sizeof(*si));
93-
if (!si) {
94-
pr_err("Could not map screen_info config table\n");
95-
return;
96-
}
97-
screen_info = *si;
98-
early_memunmap(si, sizeof(*si));
99-
100-
/* dummycon on ARM needs non-zero values for columns/lines */
101-
screen_info.orig_video_cols = 80;
102-
screen_info.orig_video_lines = 25;
103-
104-
if (memblock_is_map_memory(screen_info.lfb_base))
105-
memblock_mark_nomap(screen_info.lfb_base,
106-
screen_info.lfb_size);
107-
}
108-
}
109-
11085
static void __init load_cpu_state_table(void)
11186
{
11287
if (cpu_state_table != EFI_INVALID_TABLE_ADDR) {
@@ -145,7 +120,11 @@ void __init arm_efi_init(void)
145120
{
146121
efi_init();
147122

148-
load_screen_info_table();
123+
if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI) {
124+
/* dummycon on ARM needs non-zero values for columns/lines */
125+
screen_info.orig_video_cols = 80;
126+
screen_info.orig_video_lines = 25;
127+
}
149128

150129
/* ARM does not permit early mappings to persist across paging_init() */
151130
efi_memmap_unmap();

arch/arm64/include/asm/efi.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,16 @@
1414

1515
#ifdef CONFIG_EFI
1616
extern void efi_init(void);
17+
18+
bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg);
1719
#else
1820
#define efi_init()
21+
22+
static inline
23+
bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg)
24+
{
25+
return false;
26+
}
1927
#endif
2028

2129
int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
@@ -25,6 +33,7 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
2533
({ \
2634
efi_virtmap_load(); \
2735
__efi_fpsimd_begin(); \
36+
spin_lock(&efi_rt_lock); \
2837
})
2938

3039
#undef arch_efi_call_virt
@@ -33,10 +42,12 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
3342

3443
#define arch_efi_call_virt_teardown() \
3544
({ \
45+
spin_unlock(&efi_rt_lock); \
3646
__efi_fpsimd_end(); \
3747
efi_virtmap_unload(); \
3848
})
3949

50+
extern spinlock_t efi_rt_lock;
4051
efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...);
4152

4253
#define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)
@@ -76,13 +87,23 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
7687
return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS_MIN - 1));
7788
}
7889

79-
#define alloc_screen_info(x...) &screen_info
80-
81-
static inline void free_screen_info(struct screen_info *si)
90+
static inline unsigned long efi_get_kimg_min_align(void)
8291
{
92+
extern bool efi_nokaslr;
93+
94+
/*
95+
* Although relocatable kernels can fix up the misalignment with
96+
* respect to MIN_KIMG_ALIGN, the resulting virtual text addresses are
97+
* subtly out of sync with those recorded in the vmlinux when kaslr is
98+
* disabled but the image required relocation anyway. Therefore retain
99+
* 2M alignment if KASLR was explicitly disabled, even if it was not
100+
* going to be activated to begin with.
101+
*/
102+
return efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
83103
}
84104

85105
#define EFI_ALLOC_ALIGN SZ_64K
106+
#define EFI_ALLOC_LIMIT ((1UL << 48) - 1)
86107

87108
/*
88109
* On ARM systems, virtually remapped UEFI runtime services are set up in two

arch/arm64/kernel/Makefile

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,6 @@ obj-y := debug-monitors.o entry.o irq.o fpsimd.o \
3636
syscall.o proton-pack.o idreg-override.o idle.o \
3737
patching.o
3838

39-
targets += efi-entry.o
40-
41-
OBJCOPYFLAGS := --prefix-symbols=__efistub_
42-
$(obj)/%.stub.o: $(obj)/%.o FORCE
43-
$(call if_changed,objcopy)
44-
4539
obj-$(CONFIG_COMPAT) += sys32.o signal32.o \
4640
sys_compat.o
4741
obj-$(CONFIG_COMPAT) += sigreturn32.o
@@ -57,8 +51,7 @@ obj-$(CONFIG_CPU_PM) += sleep.o suspend.o
5751
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
5852
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
5953
obj-$(CONFIG_KGDB) += kgdb.o
60-
obj-$(CONFIG_EFI) += efi.o efi-entry.stub.o \
61-
efi-rt-wrapper.o
54+
obj-$(CONFIG_EFI) += efi.o efi-rt-wrapper.o
6255
obj-$(CONFIG_PCI) += pci.o
6356
obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o
6457
obj-$(CONFIG_ACPI) += acpi.o

arch/arm64/kernel/efi-entry.S

Lines changed: 0 additions & 69 deletions
This file was deleted.

arch/arm64/kernel/efi-rt-wrapper.S

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include <linux/linkage.h>
77

88
SYM_FUNC_START(__efi_rt_asm_wrapper)
9-
stp x29, x30, [sp, #-32]!
9+
stp x29, x30, [sp, #-112]!
1010
mov x29, sp
1111

1212
/*
@@ -16,6 +16,22 @@ SYM_FUNC_START(__efi_rt_asm_wrapper)
1616
*/
1717
stp x1, x18, [sp, #16]
1818

19+
/*
20+
* Preserve all callee saved registers and preserve the stack pointer
21+
* value at the base of the EFI runtime stack so we can recover from
22+
* synchronous exceptions occurring while executing the firmware
23+
* routines.
24+
*/
25+
stp x19, x20, [sp, #32]
26+
stp x21, x22, [sp, #48]
27+
stp x23, x24, [sp, #64]
28+
stp x25, x26, [sp, #80]
29+
stp x27, x28, [sp, #96]
30+
31+
ldr_l x16, efi_rt_stack_top
32+
mov sp, x16
33+
stp x18, x29, [sp, #-16]!
34+
1935
/*
2036
* We are lucky enough that no EFI runtime services take more than
2137
* 5 arguments, so all are passed in registers rather than via the
@@ -29,9 +45,10 @@ SYM_FUNC_START(__efi_rt_asm_wrapper)
2945
mov x4, x6
3046
blr x8
3147

48+
mov sp, x29
3249
ldp x1, x2, [sp, #16]
3350
cmp x2, x18
34-
ldp x29, x30, [sp], #32
51+
ldp x29, x30, [sp], #112
3552
b.ne 0f
3653
ret
3754
0:
@@ -42,6 +59,22 @@ SYM_FUNC_START(__efi_rt_asm_wrapper)
4259
* called with preemption disabled and a separate shadow stack is used
4360
* for interrupts.
4461
*/
45-
mov x18, x2
62+
#ifdef CONFIG_SHADOW_CALL_STACK
63+
ldr_l x18, efi_rt_stack_top
64+
ldr x18, [x18, #-16]
65+
#endif
66+
4667
b efi_handle_corrupted_x18 // tail call
4768
SYM_FUNC_END(__efi_rt_asm_wrapper)
69+
70+
SYM_CODE_START(__efi_rt_asm_recover)
71+
mov sp, x30
72+
73+
ldp x19, x20, [sp, #32]
74+
ldp x21, x22, [sp, #48]
75+
ldp x23, x24, [sp, #64]
76+
ldp x25, x26, [sp, #80]
77+
ldp x27, x28, [sp, #96]
78+
ldp x29, x30, [sp], #112
79+
ret
80+
SYM_CODE_END(__efi_rt_asm_recover)

arch/arm64/kernel/efi.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,52 @@ asmlinkage efi_status_t efi_handle_corrupted_x18(efi_status_t s, const char *f)
144144
pr_err_ratelimited(FW_BUG "register x18 corrupted by EFI %s\n", f);
145145
return s;
146146
}
147+
148+
DEFINE_SPINLOCK(efi_rt_lock);
149+
150+
asmlinkage u64 *efi_rt_stack_top __ro_after_init;
151+
152+
asmlinkage efi_status_t __efi_rt_asm_recover(void);
153+
154+
bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg)
155+
{
156+
/* Check whether the exception occurred while running the firmware */
157+
if (current_work() != &efi_rts_work.work || regs->pc >= TASK_SIZE_64)
158+
return false;
159+
160+
pr_err(FW_BUG "Unable to handle %s in EFI runtime service\n", msg);
161+
add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
162+
clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
163+
164+
regs->regs[0] = EFI_ABORTED;
165+
regs->regs[30] = efi_rt_stack_top[-1];
166+
regs->pc = (u64)__efi_rt_asm_recover;
167+
168+
if (IS_ENABLED(CONFIG_SHADOW_CALL_STACK))
169+
regs->regs[18] = efi_rt_stack_top[-2];
170+
171+
return true;
172+
}
173+
174+
/* EFI requires 8 KiB of stack space for runtime services */
175+
static_assert(THREAD_SIZE >= SZ_8K);
176+
177+
static int __init arm64_efi_rt_init(void)
178+
{
179+
void *p;
180+
181+
if (!efi_enabled(EFI_RUNTIME_SERVICES))
182+
return 0;
183+
184+
p = __vmalloc_node(THREAD_SIZE, THREAD_ALIGN, GFP_KERNEL,
185+
NUMA_NO_NODE, &&l);
186+
l: if (!p) {
187+
pr_warn("Failed to allocate EFI runtime stack\n");
188+
clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
189+
return -ENOMEM;
190+
}
191+
192+
efi_rt_stack_top = p + THREAD_SIZE;
193+
return 0;
194+
}
195+
core_initcall(arm64_efi_rt_init);

arch/arm64/kernel/image-vars.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#error This file should only be included in vmlinux.lds.S
1111
#endif
1212

13-
PROVIDE(__efistub_kernel_size = _edata - _text);
1413
PROVIDE(__efistub_primary_entry_offset = primary_entry - _text);
1514

1615
/*
@@ -22,13 +21,6 @@ PROVIDE(__efistub_primary_entry_offset = primary_entry - _text);
2221
* linked at. The routines below are all implemented in assembler in a
2322
* position independent manner
2423
*/
25-
PROVIDE(__efistub_memcmp = __pi_memcmp);
26-
PROVIDE(__efistub_memchr = __pi_memchr);
27-
PROVIDE(__efistub_strlen = __pi_strlen);
28-
PROVIDE(__efistub_strnlen = __pi_strnlen);
29-
PROVIDE(__efistub_strcmp = __pi_strcmp);
30-
PROVIDE(__efistub_strncmp = __pi_strncmp);
31-
PROVIDE(__efistub_strrchr = __pi_strrchr);
3224
PROVIDE(__efistub_dcache_clean_poc = __pi_dcache_clean_poc);
3325

3426
PROVIDE(__efistub__text = _text);

arch/arm64/mm/fault.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <asm/bug.h>
3131
#include <asm/cmpxchg.h>
3232
#include <asm/cpufeature.h>
33+
#include <asm/efi.h>
3334
#include <asm/exception.h>
3435
#include <asm/daifflags.h>
3536
#include <asm/debug-monitors.h>
@@ -397,6 +398,9 @@ static void __do_kernel_fault(unsigned long addr, unsigned long esr,
397398
msg = "paging request";
398399
}
399400

401+
if (efi_runtime_fixup_exception(regs, msg))
402+
return;
403+
400404
die_kernel_fault(msg, addr, esr, regs);
401405
}
402406

0 commit comments

Comments
 (0)