Skip to content

Commit

Permalink
Merge tag 'efi-urgent-2020-06-28' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/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
  • Loading branch information
torvalds committed Jun 28, 2020
2 parents 91a9a90 + 2a55280 commit bc53f67
Show file tree
Hide file tree
Showing 16 changed files with 235 additions and 37 deletions.
7 changes: 7 additions & 0 deletions arch/arm/include/asm/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,11 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
return dram_base + SZ_512M;
}

struct efi_arm_entry_state {
u32 cpsr_before_ebs;
u32 sctlr_before_ebs;
u32 cpsr_after_ebs;
u32 sctlr_after_ebs;
};

#endif /* _ASM_ARM_EFI_H */
11 changes: 10 additions & 1 deletion arch/x86/boot/compressed/head_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,6 @@ SYM_FUNC_START(startup_32)
* We place all of the values on our mini stack so lret can
* used to perform that far jump.
*/
pushl $__KERNEL_CS
leal startup_64(%ebp), %eax
#ifdef CONFIG_EFI_MIXED
movl efi32_boot_args(%ebp), %edi
Expand All @@ -224,11 +223,20 @@ SYM_FUNC_START(startup_32)
movl efi32_boot_args+8(%ebp), %edx // saved bootparams pointer
cmpl $0, %edx
jnz 1f
/*
* efi_pe_entry uses MS calling convention, which requires 32 bytes of
* shadow space on the stack even if all arguments are passed in
* registers. We also need an additional 8 bytes for the space that
* would be occupied by the return address, and this also results in
* the correct stack alignment for entry.
*/
subl $40, %esp
leal efi_pe_entry(%ebp), %eax
movl %edi, %ecx // MS calling convention
movl %esi, %edx
1:
#endif
pushl $__KERNEL_CS
pushl %eax

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

SYM_DATA_START_LOCAL(boot_stack)
.fill BOOT_STACK_SIZE, 1, 0
.balign 16
SYM_DATA_END_LABEL(boot_stack, SYM_L_LOCAL, boot_stack_end)

/*
Expand Down
11 changes: 11 additions & 0 deletions drivers/firmware/efi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -278,3 +278,14 @@ config EFI_EARLYCON
depends on SERIAL_EARLYCON && !ARM && !IA64
select FONT_SUPPORT
select ARCH_USE_MEMREMAP_PROT

config EFI_CUSTOM_SSDT_OVERLAYS
bool "Load custom ACPI SSDT overlay from an EFI variable"
depends on EFI_VARS && ACPI
default ACPI_TABLE_UPGRADE
help
Allow loading of an ACPI SSDT overlay from an EFI variable specified
by a kernel command line option.

See Documentation/admin-guide/acpi/ssdt-overlays.rst for more
information.
40 changes: 36 additions & 4 deletions drivers/firmware/efi/arm-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,20 @@ static phys_addr_t __init efi_to_phys(unsigned long addr)
}

static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR;
static __initdata unsigned long cpu_state_table = EFI_INVALID_TABLE_ADDR;

static const efi_config_table_type_t arch_tables[] __initconst = {
{LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, &screen_info_table},
{LINUX_EFI_ARM_CPU_STATE_TABLE_GUID, &cpu_state_table},
{}
};

static void __init init_screen_info(void)
{
struct screen_info *si;

if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
if (IS_ENABLED(CONFIG_ARM) &&
screen_info_table != EFI_INVALID_TABLE_ADDR) {
si = early_memremap_ro(screen_info_table, sizeof(*si));
if (!si) {
pr_err("Could not map screen_info config table\n");
Expand Down Expand Up @@ -116,7 +119,8 @@ static int __init uefi_init(u64 efi_system_table)
goto out;
}
retval = efi_config_parse_tables(config_tables, systab->nr_tables,
arch_tables);
IS_ENABLED(CONFIG_ARM) ? arch_tables
: NULL);

early_memunmap(config_tables, table_size);
out:
Expand Down Expand Up @@ -238,9 +242,37 @@ void __init efi_init(void)

init_screen_info();

#ifdef CONFIG_ARM
/* ARM does not permit early mappings to persist across paging_init() */
if (IS_ENABLED(CONFIG_ARM))
efi_memmap_unmap();
efi_memmap_unmap();

if (cpu_state_table != EFI_INVALID_TABLE_ADDR) {
struct efi_arm_entry_state *state;
bool dump_state = true;

state = early_memremap_ro(cpu_state_table,
sizeof(struct efi_arm_entry_state));
if (state == NULL) {
pr_warn("Unable to map CPU entry state table.\n");
return;
}

if ((state->sctlr_before_ebs & 1) == 0)
pr_warn(FW_BUG "EFI stub was entered with MMU and Dcache disabled, please fix your firmware!\n");
else if ((state->sctlr_after_ebs & 1) == 0)
pr_warn(FW_BUG "ExitBootServices() returned with MMU and Dcache disabled, please fix your firmware!\n");
else
dump_state = false;

if (dump_state || efi_enabled(EFI_DBG)) {
pr_info("CPSR at EFI stub entry : 0x%08x\n", state->cpsr_before_ebs);
pr_info("SCTLR at EFI stub entry : 0x%08x\n", state->sctlr_before_ebs);
pr_info("CPSR after ExitBootServices() : 0x%08x\n", state->cpsr_after_ebs);
pr_info("SCTLR after ExitBootServices(): 0x%08x\n", state->sctlr_after_ebs);
}
early_memunmap(state, sizeof(struct efi_arm_entry_state));
}
#endif
}

static bool efifb_overlaps_pci_range(const struct of_pci_range *range)
Expand Down
5 changes: 3 additions & 2 deletions drivers/firmware/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ static void generic_ops_unregister(void)
efivars_unregister(&generic_efivars);
}

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

/* reserve the entry itself */
memblock_reserve(prsv, EFI_MEMRESERVE_SIZE(rsv->size));
memblock_reserve(prsv,
struct_size(rsv, entry, rsv->size));

for (i = 0; i < atomic_read(&rsv->count); i++) {
memblock_reserve(rsv->entry[i].base,
Expand Down
2 changes: 1 addition & 1 deletion drivers/firmware/efi/esrt.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ static int esre_create_sysfs_entry(void *esre, int entry_num)
rc = kobject_init_and_add(&entry->kobj, &esre1_ktype, NULL,
"entry%d", entry_num);
if (rc) {
kfree(entry);
kobject_put(&entry->kobj);
return rc;
}
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/firmware/efi/libstub/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
# enabled, even if doing so doesn't break the build.
#
cflags-$(CONFIG_X86_32) := -march=i386
cflags-$(CONFIG_X86_64) := -mcmodel=small
cflags-$(CONFIG_X86_64) := -mcmodel=small \
$(call cc-option,-maccumulate-outgoing-args)
cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \
-fPIC -fno-strict-aliasing -mno-red-zone \
-mno-mmx -mno-sse -fshort-wchar \
Expand Down
54 changes: 53 additions & 1 deletion drivers/firmware/efi/libstub/arm32-stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,49 @@

#include "efistub.h"

static efi_guid_t cpu_state_guid = LINUX_EFI_ARM_CPU_STATE_TABLE_GUID;

struct efi_arm_entry_state *efi_entry_state;

static void get_cpu_state(u32 *cpsr, u32 *sctlr)
{
asm("mrs %0, cpsr" : "=r"(*cpsr));
if ((*cpsr & MODE_MASK) == HYP_MODE)
asm("mrc p15, 4, %0, c1, c0, 0" : "=r"(*sctlr));
else
asm("mrc p15, 0, %0, c1, c0, 0" : "=r"(*sctlr));
}

efi_status_t check_platform_features(void)
{
efi_status_t status;
u32 cpsr, sctlr;
int block;

get_cpu_state(&cpsr, &sctlr);

efi_info("Entering in %s mode with MMU %sabled\n",
((cpsr & MODE_MASK) == HYP_MODE) ? "HYP" : "SVC",
(sctlr & 1) ? "en" : "dis");

status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
sizeof(*efi_entry_state),
(void **)&efi_entry_state);
if (status != EFI_SUCCESS) {
efi_err("allocate_pool() failed\n");
return status;
}

efi_entry_state->cpsr_before_ebs = cpsr;
efi_entry_state->sctlr_before_ebs = sctlr;

status = efi_bs_call(install_configuration_table, &cpu_state_guid,
efi_entry_state);
if (status != EFI_SUCCESS) {
efi_err("install_configuration_table() failed\n");
goto free_state;
}

/* non-LPAE kernels can run anywhere */
if (!IS_ENABLED(CONFIG_ARM_LPAE))
return EFI_SUCCESS;
Expand All @@ -19,9 +58,22 @@ efi_status_t check_platform_features(void)
block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0);
if (block < 5) {
efi_err("This LPAE kernel is not supported by your CPU\n");
return EFI_UNSUPPORTED;
status = EFI_UNSUPPORTED;
goto drop_table;
}
return EFI_SUCCESS;

drop_table:
efi_bs_call(install_configuration_table, &cpu_state_guid, NULL);
free_state:
efi_bs_call(free_pool, efi_entry_state);
return status;
}

void efi_handle_post_ebs_state(void)
{
get_cpu_state(&efi_entry_state->cpsr_after_ebs,
&efi_entry_state->sctlr_after_ebs);
}

static efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID;
Expand Down
Loading

0 comments on commit bc53f67

Please sign in to comment.