Skip to content

Commit bc53f67

Browse files
committed
Merge tag 'efi-urgent-2020-06-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI fixes from Ingo Molnar: - Fix build regression on v4.8 and older - Robustness fix for TPM log parsing code - kobject refcount fix for the ESRT parsing code - Two efivarfs fixes to make it behave more like an ordinary file system - Style fixup for zero length arrays - Fix a regression in path separator handling in the initrd loader - Fix a missing prototype warning - Add some kerneldoc headers for newly introduced stub routines - Allow support for SSDT overrides via EFI variables to be disabled - Report CPU mode and MMU state upon entry for 32-bit ARM - Use the correct stack pointer alignment when entering from mixed mode * tag 'efi-urgent-2020-06-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: efi/libstub: arm: Print CPU boot mode and MMU state at boot efi/libstub: arm: Omit arch specific config table matching array on arm64 efi/x86: Setup stack correctly for efi_pe_entry efi: Make it possible to disable efivar_ssdt entirely efi/libstub: Descriptions for stub helper functions efi/libstub: Fix path separator regression efi/libstub: Fix missing-prototype warning for skip_spaces() efi: Replace zero-length array and use struct_size() helper efivarfs: Don't return -EINTR when rate-limiting reads efivarfs: Update inode modification time for successful writes efi/esrt: Fix reference count leak in esre_create_sysfs_entry. efi/tpm: Verify event log header before parsing efi/x86: Fix build with gcc 4
2 parents 91a9a90 + 2a55280 commit bc53f67

File tree

16 files changed

+235
-37
lines changed

16 files changed

+235
-37
lines changed

arch/arm/include/asm/efi.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,11 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
8787
return dram_base + SZ_512M;
8888
}
8989

90+
struct efi_arm_entry_state {
91+
u32 cpsr_before_ebs;
92+
u32 sctlr_before_ebs;
93+
u32 cpsr_after_ebs;
94+
u32 sctlr_after_ebs;
95+
};
96+
9097
#endif /* _ASM_ARM_EFI_H */

arch/x86/boot/compressed/head_64.S

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,6 @@ SYM_FUNC_START(startup_32)
213213
* We place all of the values on our mini stack so lret can
214214
* used to perform that far jump.
215215
*/
216-
pushl $__KERNEL_CS
217216
leal startup_64(%ebp), %eax
218217
#ifdef CONFIG_EFI_MIXED
219218
movl efi32_boot_args(%ebp), %edi
@@ -224,11 +223,20 @@ SYM_FUNC_START(startup_32)
224223
movl efi32_boot_args+8(%ebp), %edx // saved bootparams pointer
225224
cmpl $0, %edx
226225
jnz 1f
226+
/*
227+
* efi_pe_entry uses MS calling convention, which requires 32 bytes of
228+
* shadow space on the stack even if all arguments are passed in
229+
* registers. We also need an additional 8 bytes for the space that
230+
* would be occupied by the return address, and this also results in
231+
* the correct stack alignment for entry.
232+
*/
233+
subl $40, %esp
227234
leal efi_pe_entry(%ebp), %eax
228235
movl %edi, %ecx // MS calling convention
229236
movl %esi, %edx
230237
1:
231238
#endif
239+
pushl $__KERNEL_CS
232240
pushl %eax
233241

234242
/* Enter paged protected Mode, activating Long Mode */
@@ -784,6 +792,7 @@ SYM_DATA_LOCAL(boot_heap, .fill BOOT_HEAP_SIZE, 1, 0)
784792

785793
SYM_DATA_START_LOCAL(boot_stack)
786794
.fill BOOT_STACK_SIZE, 1, 0
795+
.balign 16
787796
SYM_DATA_END_LABEL(boot_stack, SYM_L_LOCAL, boot_stack_end)
788797

789798
/*

drivers/firmware/efi/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,3 +278,14 @@ config EFI_EARLYCON
278278
depends on SERIAL_EARLYCON && !ARM && !IA64
279279
select FONT_SUPPORT
280280
select ARCH_USE_MEMREMAP_PROT
281+
282+
config EFI_CUSTOM_SSDT_OVERLAYS
283+
bool "Load custom ACPI SSDT overlay from an EFI variable"
284+
depends on EFI_VARS && ACPI
285+
default ACPI_TABLE_UPGRADE
286+
help
287+
Allow loading of an ACPI SSDT overlay from an EFI variable specified
288+
by a kernel command line option.
289+
290+
See Documentation/admin-guide/acpi/ssdt-overlays.rst for more
291+
information.

drivers/firmware/efi/arm-init.c

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,20 @@ static phys_addr_t __init efi_to_phys(unsigned long addr)
5252
}
5353

5454
static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR;
55+
static __initdata unsigned long cpu_state_table = EFI_INVALID_TABLE_ADDR;
5556

5657
static const efi_config_table_type_t arch_tables[] __initconst = {
5758
{LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, &screen_info_table},
59+
{LINUX_EFI_ARM_CPU_STATE_TABLE_GUID, &cpu_state_table},
5860
{}
5961
};
6062

6163
static void __init init_screen_info(void)
6264
{
6365
struct screen_info *si;
6466

65-
if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
67+
if (IS_ENABLED(CONFIG_ARM) &&
68+
screen_info_table != EFI_INVALID_TABLE_ADDR) {
6669
si = early_memremap_ro(screen_info_table, sizeof(*si));
6770
if (!si) {
6871
pr_err("Could not map screen_info config table\n");
@@ -116,7 +119,8 @@ static int __init uefi_init(u64 efi_system_table)
116119
goto out;
117120
}
118121
retval = efi_config_parse_tables(config_tables, systab->nr_tables,
119-
arch_tables);
122+
IS_ENABLED(CONFIG_ARM) ? arch_tables
123+
: NULL);
120124

121125
early_memunmap(config_tables, table_size);
122126
out:
@@ -238,9 +242,37 @@ void __init efi_init(void)
238242

239243
init_screen_info();
240244

245+
#ifdef CONFIG_ARM
241246
/* ARM does not permit early mappings to persist across paging_init() */
242-
if (IS_ENABLED(CONFIG_ARM))
243-
efi_memmap_unmap();
247+
efi_memmap_unmap();
248+
249+
if (cpu_state_table != EFI_INVALID_TABLE_ADDR) {
250+
struct efi_arm_entry_state *state;
251+
bool dump_state = true;
252+
253+
state = early_memremap_ro(cpu_state_table,
254+
sizeof(struct efi_arm_entry_state));
255+
if (state == NULL) {
256+
pr_warn("Unable to map CPU entry state table.\n");
257+
return;
258+
}
259+
260+
if ((state->sctlr_before_ebs & 1) == 0)
261+
pr_warn(FW_BUG "EFI stub was entered with MMU and Dcache disabled, please fix your firmware!\n");
262+
else if ((state->sctlr_after_ebs & 1) == 0)
263+
pr_warn(FW_BUG "ExitBootServices() returned with MMU and Dcache disabled, please fix your firmware!\n");
264+
else
265+
dump_state = false;
266+
267+
if (dump_state || efi_enabled(EFI_DBG)) {
268+
pr_info("CPSR at EFI stub entry : 0x%08x\n", state->cpsr_before_ebs);
269+
pr_info("SCTLR at EFI stub entry : 0x%08x\n", state->sctlr_before_ebs);
270+
pr_info("CPSR after ExitBootServices() : 0x%08x\n", state->cpsr_after_ebs);
271+
pr_info("SCTLR after ExitBootServices(): 0x%08x\n", state->sctlr_after_ebs);
272+
}
273+
early_memunmap(state, sizeof(struct efi_arm_entry_state));
274+
}
275+
#endif
244276
}
245277

246278
static bool efifb_overlaps_pci_range(const struct of_pci_range *range)

drivers/firmware/efi/efi.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ static void generic_ops_unregister(void)
189189
efivars_unregister(&generic_efivars);
190190
}
191191

192-
#if IS_ENABLED(CONFIG_ACPI)
192+
#ifdef CONFIG_EFI_CUSTOM_SSDT_OVERLAYS
193193
#define EFIVAR_SSDT_NAME_MAX 16
194194
static char efivar_ssdt[EFIVAR_SSDT_NAME_MAX] __initdata;
195195
static int __init efivar_ssdt_setup(char *str)
@@ -622,7 +622,8 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
622622
rsv = (void *)(p + prsv % PAGE_SIZE);
623623

624624
/* reserve the entry itself */
625-
memblock_reserve(prsv, EFI_MEMRESERVE_SIZE(rsv->size));
625+
memblock_reserve(prsv,
626+
struct_size(rsv, entry, rsv->size));
626627

627628
for (i = 0; i < atomic_read(&rsv->count); i++) {
628629
memblock_reserve(rsv->entry[i].base,

drivers/firmware/efi/esrt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ static int esre_create_sysfs_entry(void *esre, int entry_num)
181181
rc = kobject_init_and_add(&entry->kobj, &esre1_ktype, NULL,
182182
"entry%d", entry_num);
183183
if (rc) {
184-
kfree(entry);
184+
kobject_put(&entry->kobj);
185185
return rc;
186186
}
187187
}

drivers/firmware/efi/libstub/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
# enabled, even if doing so doesn't break the build.
77
#
88
cflags-$(CONFIG_X86_32) := -march=i386
9-
cflags-$(CONFIG_X86_64) := -mcmodel=small
9+
cflags-$(CONFIG_X86_64) := -mcmodel=small \
10+
$(call cc-option,-maccumulate-outgoing-args)
1011
cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \
1112
-fPIC -fno-strict-aliasing -mno-red-zone \
1213
-mno-mmx -mno-sse -fshort-wchar \

drivers/firmware/efi/libstub/arm32-stub.c

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,49 @@
77

88
#include "efistub.h"
99

10+
static efi_guid_t cpu_state_guid = LINUX_EFI_ARM_CPU_STATE_TABLE_GUID;
11+
12+
struct efi_arm_entry_state *efi_entry_state;
13+
14+
static void get_cpu_state(u32 *cpsr, u32 *sctlr)
15+
{
16+
asm("mrs %0, cpsr" : "=r"(*cpsr));
17+
if ((*cpsr & MODE_MASK) == HYP_MODE)
18+
asm("mrc p15, 4, %0, c1, c0, 0" : "=r"(*sctlr));
19+
else
20+
asm("mrc p15, 0, %0, c1, c0, 0" : "=r"(*sctlr));
21+
}
22+
1023
efi_status_t check_platform_features(void)
1124
{
25+
efi_status_t status;
26+
u32 cpsr, sctlr;
1227
int block;
1328

29+
get_cpu_state(&cpsr, &sctlr);
30+
31+
efi_info("Entering in %s mode with MMU %sabled\n",
32+
((cpsr & MODE_MASK) == HYP_MODE) ? "HYP" : "SVC",
33+
(sctlr & 1) ? "en" : "dis");
34+
35+
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
36+
sizeof(*efi_entry_state),
37+
(void **)&efi_entry_state);
38+
if (status != EFI_SUCCESS) {
39+
efi_err("allocate_pool() failed\n");
40+
return status;
41+
}
42+
43+
efi_entry_state->cpsr_before_ebs = cpsr;
44+
efi_entry_state->sctlr_before_ebs = sctlr;
45+
46+
status = efi_bs_call(install_configuration_table, &cpu_state_guid,
47+
efi_entry_state);
48+
if (status != EFI_SUCCESS) {
49+
efi_err("install_configuration_table() failed\n");
50+
goto free_state;
51+
}
52+
1453
/* non-LPAE kernels can run anywhere */
1554
if (!IS_ENABLED(CONFIG_ARM_LPAE))
1655
return EFI_SUCCESS;
@@ -19,9 +58,22 @@ efi_status_t check_platform_features(void)
1958
block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0);
2059
if (block < 5) {
2160
efi_err("This LPAE kernel is not supported by your CPU\n");
22-
return EFI_UNSUPPORTED;
61+
status = EFI_UNSUPPORTED;
62+
goto drop_table;
2363
}
2464
return EFI_SUCCESS;
65+
66+
drop_table:
67+
efi_bs_call(install_configuration_table, &cpu_state_guid, NULL);
68+
free_state:
69+
efi_bs_call(free_pool, efi_entry_state);
70+
return status;
71+
}
72+
73+
void efi_handle_post_ebs_state(void)
74+
{
75+
get_cpu_state(&efi_entry_state->cpsr_after_ebs,
76+
&efi_entry_state->sctlr_after_ebs);
2577
}
2678

2779
static efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID;

0 commit comments

Comments
 (0)