aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorArd Biesheuvel2022-09-16 10:04:57 +0200
committerArd Biesheuvel2022-09-27 13:26:16 +0200
commit69e377b289376147c84cfd09bab1ad0328a0ecc6 (patch)
tree6b11f9f5eba435c03490ae4f7e04970c6b3e371d /arch/arm/kernel
parent71c7adc9fffd4e38ebc197314f6909c9fd6051ef (diff)
efi/arm: libstub: move ARM specific code out of generic routines
Move some code that is only reachable when IS_ENABLED(CONFIG_ARM) into the ARM EFI arch code. Cc: Russell King <linux@armlinux.org.uk> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/efi.c79
-rw-r--r--arch/arm/kernel/setup.c2
2 files changed, 80 insertions, 1 deletions
diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c
index e57dbcc89123..e50ad7eefc02 100644
--- a/arch/arm/kernel/efi.c
+++ b/arch/arm/kernel/efi.c
@@ -4,6 +4,7 @@
*/
#include <linux/efi.h>
+#include <linux/memblock.h>
#include <asm/efi.h>
#include <asm/mach/map.h>
#include <asm/mmu_context.h>
@@ -73,3 +74,81 @@ int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
return efi_set_mapping_permissions(mm, md);
return 0;
}
+
+static unsigned long __initdata screen_info_table = EFI_INVALID_TABLE_ADDR;
+static unsigned long __initdata cpu_state_table = EFI_INVALID_TABLE_ADDR;
+
+const efi_config_table_type_t efi_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 load_screen_info_table(void)
+{
+ struct screen_info *si;
+
+ if (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");
+ return;
+ }
+ screen_info = *si;
+ early_memunmap(si, sizeof(*si));
+
+ /* dummycon on ARM needs non-zero values for columns/lines */
+ screen_info.orig_video_cols = 80;
+ screen_info.orig_video_lines = 25;
+
+ if (memblock_is_map_memory(screen_info.lfb_base))
+ memblock_mark_nomap(screen_info.lfb_base,
+ screen_info.lfb_size);
+ }
+}
+
+static void __init load_cpu_state_table(void)
+{
+ 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));
+ }
+}
+
+void __init arm_efi_init(void)
+{
+ efi_init();
+
+ load_screen_info_table();
+
+ /* ARM does not permit early mappings to persist across paging_init() */
+ efi_memmap_unmap();
+
+ load_cpu_state_table();
+}
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 1e8a50a97edf..cb88c6e69377 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -1141,7 +1141,7 @@ void __init setup_arch(char **cmdline_p)
#endif
setup_dma_zone(mdesc);
xen_early_init();
- efi_init();
+ arm_efi_init();
/*
* Make sure the calculation for lowmem/highmem is set appropriately
* before reserving/allocating any memory