Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f7d92489 authored by Ard Biesheuvel's avatar Ard Biesheuvel Committed by Will Deacon
Browse files

arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM



This refactors the EFI init and runtime code that will be shared
between arm64 and ARM so that it can be built for both archs.

Reviewed-by: default avatarMatt Fleming <matt@codeblueprint.co.uk>
Signed-off-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent e5bc22a4
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -2,7 +2,9 @@
#define _ASM_EFI_H

#include <asm/io.h>
#include <asm/mmu_context.h>
#include <asm/neon.h>
#include <asm/tlbflush.h>

#ifdef CONFIG_EFI
extern void efi_init(void);
@@ -10,6 +12,8 @@ extern void efi_init(void);
#define efi_init()
#endif

int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);

#define efi_call_virt(f, ...)						\
({									\
	efi_##f##_t *__f;						\
@@ -63,6 +67,11 @@ extern void efi_init(void);
 *   Services are enabled and the EFI_RUNTIME_SERVICES bit set.
 */

static inline void efi_set_pgd(struct mm_struct *mm)
{
	switch_mm(NULL, mm, NULL);
}

void efi_virtmap_load(void);
void efi_virtmap_unload(void);

+23 −0
Original line number Diff line number Diff line
@@ -17,6 +17,29 @@

#include <asm/efi.h>

int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
{
	pteval_t prot_val;

	/*
	 * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
	 * executable, everything else can be mapped with the XN bits
	 * set.
	 */
	if ((md->attribute & EFI_MEMORY_WB) == 0)
		prot_val = PROT_DEVICE_nGnRE;
	else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
		 !PAGE_ALIGNED(md->phys_addr))
		prot_val = pgprot_val(PAGE_KERNEL_EXEC);
	else
		prot_val = pgprot_val(PAGE_KERNEL);

	create_pgd_mapping(mm, md->phys_addr, md->virt_addr,
			   md->num_pages << EFI_PAGE_SHIFT,
			   __pgprot(prot_val | PTE_NG));
	return 0;
}

static int __init arm64_dmi_init(void)
{
	/*
+4 −3
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@ static int __init uefi_init(void)
{
	efi_char16_t *c16;
	void *config_tables;
	u64 table_size;
	size_t table_size;
	char vendor[100] = "unknown";
	int i, retval;

@@ -69,6 +69,7 @@ static int __init uefi_init(void)
	}

	set_bit(EFI_BOOT, &efi.flags);
	if (IS_ENABLED(CONFIG_64BIT))
		set_bit(EFI_64BIT, &efi.flags);

	/*
@@ -107,7 +108,7 @@ static int __init uefi_init(void)
		goto out;
	}
	retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
					 sizeof(efi_config_table_64_t), NULL);
					 sizeof(efi_config_table_t), NULL);

	early_memunmap(config_tables, table_size);
out:
+16 −32
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
 */

#include <linux/efi.h>
#include <linux/io.h>
#include <linux/memblock.h>
#include <linux/mm_types.h>
#include <linux/preempt.h>
@@ -23,18 +24,14 @@

#include <asm/cacheflush.h>
#include <asm/efi.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
#include <asm/mmu.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>

static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss;

extern u64 efi_system_table;

static struct mm_struct efi_mm = {
	.mm_rb			= RB_ROOT,
	.pgd			= efi_pgd,
	.mm_users		= ATOMIC_INIT(2),
	.mm_count		= ATOMIC_INIT(1),
	.mmap_sem		= __RWSEM_INITIALIZER(efi_mm.mmap_sem),
@@ -46,35 +43,27 @@ static bool __init efi_virtmap_init(void)
{
	efi_memory_desc_t *md;

	efi_mm.pgd = pgd_alloc(&efi_mm);
	init_new_context(NULL, &efi_mm);

	for_each_efi_memory_desc(&memmap, md) {
		pgprot_t prot;
		phys_addr_t phys = md->phys_addr;
		int ret;

		if (!(md->attribute & EFI_MEMORY_RUNTIME))
			continue;
		if (md->virt_addr == 0)
			return false;

		pr_info("  EFI remap 0x%016llx => %p\n",
			md->phys_addr, (void *)md->virt_addr);

		/*
		 * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
		 * executable, everything else can be mapped with the XN bits
		 * set.
		 */
		if ((md->attribute & EFI_MEMORY_WB) == 0)
			prot = __pgprot(PROT_DEVICE_nGnRE);
		else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
			 !PAGE_ALIGNED(md->phys_addr))
			prot = PAGE_KERNEL_EXEC;
		else
			prot = PAGE_KERNEL;

		create_pgd_mapping(&efi_mm, md->phys_addr, md->virt_addr,
				   md->num_pages << EFI_PAGE_SHIFT,
				   __pgprot(pgprot_val(prot) | PTE_NG));
		ret = efi_create_mapping(&efi_mm, md);
		if  (!ret) {
			pr_info("  EFI remap %pa => %p\n",
				&phys, (void *)(unsigned long)md->virt_addr);
		} else {
			pr_warn("  EFI remap %pa: failed to create mapping (%d)\n",
				&phys, ret);
			return false;
		}
	}
	return true;
}
@@ -84,7 +73,7 @@ static bool __init efi_virtmap_init(void)
 * non-early mapping of the UEFI system table and virtual mappings for all
 * EFI_MEMORY_RUNTIME regions.
 */
static int __init arm64_enable_runtime_services(void)
static int __init arm_enable_runtime_services(void)
{
	u64 mapsize;

@@ -131,12 +120,7 @@ static int __init arm64_enable_runtime_services(void)

	return 0;
}
early_initcall(arm64_enable_runtime_services);

static void efi_set_pgd(struct mm_struct *mm)
{
	switch_mm(NULL, mm, NULL);
}
early_initcall(arm_enable_runtime_services);

void efi_virtmap_load(void)
{
+2 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
#include <linux/io.h>
#include <linux/platform_device.h>

#include <asm/efi.h>

struct efi __read_mostly efi = {
	.mps			= EFI_INVALID_TABLE_ADDR,
	.acpi			= EFI_INVALID_TABLE_ADDR,