From patchwork Fri Nov 29 22:05:12 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Salter X-Patchwork-Id: 21899 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pd0-f199.google.com (mail-pd0-f199.google.com [209.85.192.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 9D41923FD0 for ; Fri, 29 Nov 2013 22:05:32 +0000 (UTC) Received: by mail-pd0-f199.google.com with SMTP id r10sf26084089pdi.10 for ; Fri, 29 Nov 2013 14:05:31 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=jKEtXmA2L5GrM9vf0EHnFPPVjhXzm1cMMqZscBaNhTA=; b=Qtn0ZZo/CUdz50qVuMuK81Cqr7Jaw19ZRgPjK6XaFu9hXQ2di7AS9KNWRi/cV5enFY 05KDoNqaeobAI9aSlLKcDz/TM3mtUbRTeWwEgh6jmxkphVmS/S3w2ei+CZnXUoqHZ31k LsyN0G53NbH+f33j6GUhoIAV9KLcd7VhncjCT6aGg76jvUCvyPtHmUWPzcTESmBuq5Xu 6PDcxY6ewtk6N7zgKByna+pyictGzQHjznBaZBa8LGf3uCzXBBlfZFrBdQ2/+xE7q+0w V4ZeHMpQt7DMEYEAamYMORx28PnggAyyVNJFc5dCbFtT12Am8D+rwPVnxlnWrWFFCgZ8 mkBA== X-Gm-Message-State: ALoCoQktynpnzHLRhc8Th6M7ZDt7BdJSjbC7GhSIG4bPhQfYtV8ytrR8HJlkOkljglDRolydPXiW X-Received: by 10.66.51.33 with SMTP id h1mr19067945pao.30.1385762731813; Fri, 29 Nov 2013 14:05:31 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.94.41 with SMTP id cz9ls3311611qeb.57.gmail; Fri, 29 Nov 2013 14:05:31 -0800 (PST) X-Received: by 10.220.244.132 with SMTP id lq4mr2965138vcb.31.1385762731654; Fri, 29 Nov 2013 14:05:31 -0800 (PST) Received: from mail-vc0-f171.google.com (mail-vc0-f171.google.com [209.85.220.171]) by mx.google.com with ESMTPS id bq2si25332341vcb.40.2013.11.29.14.05.31 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 29 Nov 2013 14:05:31 -0800 (PST) Received-SPF: neutral (google.com: 209.85.220.171 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.171; Received: by mail-vc0-f171.google.com with SMTP id ik5so6974883vcb.16 for ; Fri, 29 Nov 2013 14:05:31 -0800 (PST) X-Received: by 10.220.159.4 with SMTP id h4mr42499434vcx.1.1385762731495; Fri, 29 Nov 2013 14:05:31 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp121534vcz; Fri, 29 Nov 2013 14:05:30 -0800 (PST) X-Received: by 10.50.61.137 with SMTP id p9mr7933481igr.45.1385762730669; Fri, 29 Nov 2013 14:05:30 -0800 (PST) Received: from mx1.redhat.com (mx1.redhat.com. [209.132.183.28]) by mx.google.com with ESMTP id ow5si48651828icc.25.2013.11.29.14.05.30 for ; Fri, 29 Nov 2013 14:05:30 -0800 (PST) Received-SPF: pass (google.com: domain of msalter@redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id rATM5Op1007973 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 29 Nov 2013 17:05:24 -0500 Received: from deneb.redhat.com (ovpn-113-148.phx2.redhat.com [10.3.113.148]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id rATM5JjN005904; Fri, 29 Nov 2013 17:05:23 -0500 From: Mark Salter To: linux-kernel@vger.kernel.org Cc: patches@linaro.org, Mark Salter , Catalin Marinas , Will Deacon , linux-arm-kernel@lists.infradead.org, matt.fleming@intel.com, linux-efi@vger.kernel.org, Leif Lindholm , roy.franz@linaro.org Subject: [PATCH 3/3] arm64: add EFI runtime services Date: Fri, 29 Nov 2013 17:05:12 -0500 Message-Id: <1385762712-17043-4-git-send-email-msalter@redhat.com> In-Reply-To: <1385762712-17043-1-git-send-email-msalter@redhat.com> References: <1385762712-17043-1-git-send-email-msalter@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: msalter@redhat.com X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.171 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , This patch adds EFI runtime support for arm64. The runtime support allows the kernel to access various EFI runtime services provided by EFI firmware. Things like reboot, real time clock, EFI boot variables, and others. Signed-off-by: Mark Salter CC: Catalin Marinas CC: Will Deacon CC: linux-arm-kernel@lists.infradead.org CC: matt.fleming@intel.com CC: linux-efi@vger.kernel.org CC: Leif Lindholm CC: roy.franz@linaro.org --- arch/arm64/Kconfig | 15 ++ arch/arm64/include/asm/efi.h | 18 ++ arch/arm64/kernel/Makefile | 1 + arch/arm64/kernel/efi.c | 507 +++++++++++++++++++++++++++++++++++++++++++ arch/arm64/kernel/setup.c | 6 + include/linux/efi.h | 2 +- 6 files changed, 548 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/include/asm/efi.h create mode 100644 arch/arm64/kernel/efi.c diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 10b0e93..6baaf75 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -250,6 +250,19 @@ config CMDLINE_FORCE This is useful if you cannot or don't want to change the command-line options your boot loader passes to the kernel. +config EFI + bool "EFI runtime service support" + depends on !CPU_BIG_ENDIAN && !ARM64_64K_PAGES && OF + select UCS2_STRING + select LIBFDT + help + This enables the kernel to use UEFI runtime services that are + available (such as the UEFI variable services). + + This option is only useful on systems that have UEFI firmware. + However, even with this option, the resultant kernel should + continue to boot on existing non-UEFI platforms. + config EFI_STUB bool "EFI stub support" depends on !CPU_BIG_ENDIAN && !ARM64_64K_PAGES && OF @@ -291,6 +304,8 @@ source "net/Kconfig" source "drivers/Kconfig" +source "drivers/firmware/Kconfig" + source "fs/Kconfig" source "arch/arm64/kvm/Kconfig" diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h new file mode 100644 index 0000000..7384048 --- /dev/null +++ b/arch/arm64/include/asm/efi.h @@ -0,0 +1,18 @@ +#ifndef _ASM_ARM64_EFI_H +#define _ASM_ARM64_EFI_H + +#include + +#ifdef CONFIG_EFI +extern void efi_init(void); +#else +#define efi_init() +#endif + +#define efi_remap(cookie, size) __ioremap((cookie), (size), PAGE_KERNEL_EXEC) +#define efi_ioremap(cookie, size) __ioremap((cookie), (size), \ + __pgprot(PROT_DEVICE_nGnRE)) +#define efi_unmap(cookie) __iounmap((cookie)) +#define efi_iounmap(cookie) __iounmap((cookie)) + +#endif /* _ASM_ARM64_EFI_H */ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 1c52b84..8897cf5a5 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -21,6 +21,7 @@ arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o arm64-obj-$(CONFIG_EFI_STUB) += efi-stub.o efi-entry.o +arm64-obj-$(CONFIG_EFI) += efi.o obj-y += $(arm64-obj-y) vdso/ obj-m += $(arm64-obj-m) diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c new file mode 100644 index 0000000..1bad8a7 --- /dev/null +++ b/arch/arm64/kernel/efi.c @@ -0,0 +1,507 @@ +/* + * Extensible Firmware Interface + * + * Based on Extensible Firmware Interface Specification version 2.3.1 + * + * Copyright (C) 2013 Linaro Ltd. + * + * Adapted for arm64 from arch/arm/kernel/efi.c code + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define efi_early_remap(a, b) \ + ((__force void *)early_ioremap((a), (b))) +#define efi_early_unmap(a, b) \ + early_iounmap((void __iomem *)(a), (b)) + +struct efi_memory_map memmap; + +static efi_runtime_services_t *runtime; + +static u64 efi_system_table; + +static unsigned long arm_efi_facility; + +/* + * Returns 1 if 'facility' is enabled, 0 otherwise. + */ +int efi_enabled(int facility) +{ + return test_bit(facility, &arm_efi_facility) != 0; +} +EXPORT_SYMBOL(efi_enabled); + +static int uefi_debug __initdata; +static int __init uefi_debug_setup(char *str) +{ + uefi_debug = 1; + + return 0; +} +early_param("uefi_debug", uefi_debug_setup); + +static int __init fdt_find_efi_params(unsigned long node, const char *uname, + int depth, void *data) +{ + unsigned long len, size; + __be32 *prop; + + if (depth != 1 || + (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) + return 0; + + pr_info("Getting EFI parameters from FDT.\n"); + + prop = of_get_flat_dt_prop(node, "linux,uefi-system-table", &len); + if (!prop) { + pr_err("No EFI system table in FDT\n"); + return 0; + } + efi_system_table = of_read_ulong(prop, len/4); + + prop = of_get_flat_dt_prop(node, "linux,uefi-mmap-start", &len); + if (!prop) { + pr_err("No EFI memmap in FDT\n"); + return 0; + } + memmap.phys_map = (void *)of_read_ulong(prop, len/4); + + prop = of_get_flat_dt_prop(node, "linux,uefi-mmap-size", &len); + if (!prop) { + pr_err("No EFI memmap size in FDT\n"); + return 0; + } + size = of_read_ulong(prop, len/4); + memmap.map_end = memmap.phys_map + size; + + /* reserve memmap */ + memblock_reserve((u64)memmap.phys_map, size); + + prop = of_get_flat_dt_prop(node, "linux,uefi-mmap-desc-size", &len); + if (!prop) { + pr_err("No EFI memmap descriptor size in FDT\n"); + return 0; + } + memmap.desc_size = of_read_ulong(prop, len/4); + + memmap.nr_map = size / memmap.desc_size; + + prop = of_get_flat_dt_prop(node, "linux,uefi-mmap-desc-ver", &len); + if (!prop) { + pr_err("No EFI memmap descriptor version in FDT\n"); + return 0; + } + memmap.desc_version = of_read_ulong(prop, len/4); + + if (uefi_debug) { + pr_info(" EFI system table @ %p\n", (void *)efi_system_table); + pr_info(" EFI mmap @ %p-%p\n", memmap.phys_map, + memmap.map_end); + pr_info(" EFI mmap descriptor size = 0x%lx\n", + memmap.desc_size); + pr_info(" EFI mmap descriptor version = 0x%lx\n", + memmap.desc_version); + } + + return 1; +} + +#define PGD_END (&idmap_pg_dir[sizeof(idmap_pg_dir)/sizeof(pgd_t)]) +#ifndef CONFIG_SMP +#define PMD_FLAGS (PMD_ATTRINDX(MT_NORMAL) | PMD_TYPE_SECT | PMD_SECT_AF) +#else +#define PMD_FLAGS (PMD_ATTRINDX(MT_NORMAL) | PMD_TYPE_SECT | PMD_SECT_AF | \ + PMD_SECT_S) +#endif + +static void __init create_idmap(unsigned long addr, unsigned long len) +{ + unsigned long end, next, p; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + + /* section align it */ + len = ALIGN(len + (addr & ~SECTION_MASK), SECTION_SIZE); + addr &= SECTION_MASK; + + end = addr + len; + pgd = &idmap_pg_dir[pgd_index(addr)]; + + do { + next = pgd_addr_end(addr, end); + if (pgd >= PGD_END) + continue; + + pud = pud_offset(pgd, addr); + if (pud_none(*pud)) { + pmd = alloc_bootmem_pages(PAGE_SIZE); + if (!pmd) + continue; + set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE)); + } + + for (p = addr; p < next; p += SECTION_SIZE) { + pmd = pmd_offset(pud, p); + + if (pmd_none(*pmd)) + set_pmd(pmd, __pmd(p | PMD_FLAGS)); + } + } while (pgd++, addr = next, addr != end); +} + +static void __init efi_setup_idmap(void) +{ + struct memblock_region *r; + + for_each_memblock(memory, r) + create_idmap(r->base, r->size); +} + +static int __init uefi_init(void) +{ + efi_char16_t *c16; + char vendor[100] = "unknown"; + int i, retval; + + efi.systab = efi_early_remap(efi_system_table, + sizeof(efi_system_table_t)); + + /* + * Verify the EFI Table + */ + if (efi.systab == NULL) + panic("Whoa! Can't map EFI system table.\n"); + if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) + panic("Whoa! EFI system table signature incorrect\n"); + if ((efi.systab->hdr.revision >> 16) == 0) + pr_warn("Warning: EFI system table version %d.%02d, expected 1.00 or greater\n", + efi.systab->hdr.revision >> 16, + efi.systab->hdr.revision & 0xffff); + + /* Show what we know for posterity */ + c16 = efi_early_remap(efi.systab->fw_vendor, + sizeof(vendor)); + if (c16) { + for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i) + vendor[i] = c16[i]; + vendor[i] = '\0'; + } + + pr_info("EFI v%u.%.02u by %s\n", + efi.systab->hdr.revision >> 16, + efi.systab->hdr.revision & 0xffff, vendor); + + retval = efi_config_init(NULL); + if (retval == 0) + set_bit(EFI_CONFIG_TABLES, &arm_efi_facility); + + efi_early_unmap(c16, sizeof(vendor)); + efi_early_unmap(efi.systab, sizeof(efi_system_table_t)); + + return retval; +} + +static __initdata struct { + u32 type; + const char *name; +} memory_type_name_map[] = { + {EFI_RESERVED_TYPE, "Reserved"}, + {EFI_LOADER_CODE, "Loader Code"}, + {EFI_LOADER_DATA, "Loader Data"}, + {EFI_BOOT_SERVICES_CODE, "Boot Code"}, + {EFI_BOOT_SERVICES_DATA, "Boot Data"}, + {EFI_RUNTIME_SERVICES_CODE, "Runtime Code"}, + {EFI_RUNTIME_SERVICES_DATA, "Runtime Data"}, + {EFI_CONVENTIONAL_MEMORY, "Conventional Memory"}, + {EFI_UNUSABLE_MEMORY, "Unusable Memory"}, + {EFI_ACPI_RECLAIM_MEMORY, "ACPI Reclaim Memory"}, + {EFI_ACPI_MEMORY_NVS, "ACPI Memory NVS"}, + {EFI_MEMORY_MAPPED_IO, "Memory Mapped I/O"}, + {EFI_MEMORY_MAPPED_IO_PORT_SPACE, "MMIO Port Space"}, + {EFI_PAL_CODE, "PAL Code"}, + {EFI_MAX_MEMORY_TYPE, NULL}, +}; + +/* memmap walk functions may return one of these or a negative error */ +#define MEMMAP_WALK_CONT 0 +#define MEMMAP_WALK_STOP 1 + +static __init int memmap_walk(struct efi_memory_map *memmap, + int (*func)(efi_memory_desc_t *, void *), + void *private_data, int early) +{ + void *start, *map; + unsigned long len; + int i, ret; + + if (early) { + len = memmap->map_end - memmap->phys_map; + map = start = efi_early_remap((u64)memmap->phys_map, len); + if (map == NULL) + panic("Can't map EFI memory map.\n"); + + } else { + len = memmap->map_end - memmap->map; + map = memmap->map; + } + + for (i = 0; i < memmap->nr_map; i++, map += memmap->desc_size) { + ret = func(map, private_data); + if (ret) + break; + } + + if (early) + efi_early_unmap(start, len); + + if (ret < 0) + return ret; + + return 0; +} + +static __init int reserve_region(efi_memory_desc_t *md, void *priv) +{ + u64 paddr, npages; + int *count = priv; + + paddr = md->phys_addr; + npages = md->num_pages; + memrange_efi_to_native(&paddr, &npages); + + if (uefi_debug) + pr_info(" 0x%012llx-0x%012llx [%s]", + paddr, paddr + (npages << PAGE_SHIFT) - 1, + memory_type_name_map[md->type].name); + + if ((md->attribute & EFI_MEMORY_RUNTIME) || + md->type == EFI_BOOT_SERVICES_CODE || + md->type == EFI_BOOT_SERVICES_DATA || + md->type == EFI_ACPI_RECLAIM_MEMORY) { + if (md->type != EFI_MEMORY_MAPPED_IO) { + memblock_reserve(paddr, npages << PAGE_SHIFT); + if (uefi_debug) + pr_cont("*"); + *count += 1; + } + } + + if (uefi_debug) + pr_cont("\n"); + + return MEMMAP_WALK_CONT; +} + +static __init void reserve_regions(void) +{ + int nr_reserved = 0; + + if (uefi_debug) + pr_info("Processing EFI memory map:\n"); + + memmap_walk(&memmap, reserve_region, &nr_reserved, 1); + + if (uefi_debug) + pr_info("%d EFI regions reserved.\n", nr_reserved); +} + +void __init efi_init(void) +{ + /* Grab EFI information from FDT */ + if (!of_scan_flat_dt(fdt_find_efi_params, NULL)) + return; + + set_bit(EFI_BOOT, &arm_efi_facility); + set_bit(EFI_64BIT, &arm_efi_facility); + + uefi_init(); + + reserve_regions(); +} + +static int __init remap_region(efi_memory_desc_t *md, void *priv) +{ + efi_memory_desc_t *new; + u64 paddr, npages, size; + + if (!(md->attribute & EFI_MEMORY_RUNTIME) && + md->type != EFI_ACPI_RECLAIM_MEMORY) + return MEMMAP_WALK_CONT; + + paddr = md->phys_addr; + npages = md->num_pages; + memrange_efi_to_native(&paddr, &npages); + size = npages << PAGE_SHIFT; + + /* + * Map everything writeback-capable as coherent memory, + * anything else as device. + */ + if (md->attribute & EFI_MEMORY_WB) { + if (memblock_is_memory(paddr)) + md->virt_addr = (u64)phys_to_virt(paddr); + else + md->virt_addr = (__force u64)efi_remap(paddr, size); + } else + md->virt_addr = (__force u64)efi_ioremap(paddr, size); + + if (!md->virt_addr) + panic("EFI unable to remap 0x%llx pages @ %p\n", + npages, (void *)paddr); + + if (uefi_debug) + pr_info(" EFI remap 0x%012llx => %p\n", + md->phys_addr, (void *)md->virt_addr); + + new = *(efi_memory_desc_t **)priv; + *new = *md; + *(efi_memory_desc_t **)priv = (void *)new + memmap.desc_size; + + return MEMMAP_WALK_CONT; +} + +static int __init remap_regions(efi_memory_desc_t *map) +{ + efi_memory_desc_t *new = map; + + memmap_walk(&memmap, remap_region, &new, 0); + + return new - map; +} + +static int __init free_boot_region(efi_memory_desc_t *md, void *priv) +{ + u64 *total = priv; + u64 paddr, npages, size; + + if (md->type != EFI_BOOT_SERVICES_CODE && + md->type != EFI_BOOT_SERVICES_DATA) + return MEMMAP_WALK_CONT; + + paddr = md->phys_addr; + npages = md->num_pages; + memrange_efi_to_native(&paddr, &npages); + size = npages << PAGE_SHIFT; + + if (uefi_debug) + pr_info(" EFI freeing: 0x%012llx-0x%012llx [%s]\n", + paddr, paddr + (npages << PAGE_SHIFT) - 1, + memory_type_name_map[md->type].name); + + free_bootmem(paddr, size); + *total += size; + + return MEMMAP_WALK_CONT; +} + +/* + * Called from setup_arch with interrupts disabled. + */ +void __init efi_enter_virtual_mode(void) +{ + void *newmap; + efi_status_t status; + u64 mapsize, total_freed = 0; + int count; + + if (!efi_enabled(EFI_BOOT)) { + pr_info("EFI services will not be available.\n"); + return; + } + + pr_info("Remapping and enabling EFI services.\n"); + + mapsize = memmap.map_end - memmap.phys_map; + memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map, + mapsize); + memmap.map_end = memmap.map + mapsize; + + /* Map the regions we reserved earlier */ + newmap = alloc_bootmem(mapsize); + if (newmap == NULL) { + pr_err("Failed to allocate new EFI memmap\n"); + return; + } + + count = remap_regions(newmap); + if (count <= 0) { + pr_err("Failed to remap EFI regions.\n"); + return; + } + + efi.memmap = &memmap; + + efi.systab = (__force void *)efi_lookup_mapped_addr(efi_system_table); + if (efi.systab) + set_bit(EFI_SYSTEM_TABLES, &arm_efi_facility); + + /* + * efi.systab->runtime is a pointer to something guaranteed by + * the UEFI specification to be 1:1 mapped. + */ + runtime = (__force void *)efi_lookup_mapped_addr((u64)efi.systab->runtime); + + /* Call SetVirtualAddressMap with the physical address of the map */ + efi.set_virtual_address_map = runtime->set_virtual_address_map; + + /* boot time idmap_pg_dir is incomplete, so fill in missing parts */ + efi_setup_idmap(); + + cpu_switch_mm(idmap_pg_dir, &init_mm); + flush_tlb_all(); + flush_cache_all(); + + status = efi.set_virtual_address_map(count * memmap.desc_size, + memmap.desc_size, + memmap.desc_version, + newmap); + cpu_set_reserved_ttbr0(); + flush_tlb_all(); + flush_cache_all(); + + free_bootmem((unsigned long)newmap, mapsize); + + if (status != EFI_SUCCESS) { + pr_err("Failed to set EFI virtual address map! [%lx]\n", + status); + return; + } + + pr_info("EFI Virtual address map set\n"); + + /* Okay to free boot services memory now */ + memmap_walk(&memmap, free_boot_region, &total_freed, 0); + if (total_freed) + pr_info("Freed 0x%llx bytes of EFI boot services memory", + total_freed); + + /* Set up runtime services function pointers */ + efi.get_time = runtime->get_time; + efi.set_time = runtime->set_time; + efi.get_wakeup_time = runtime->get_wakeup_time; + efi.set_wakeup_time = runtime->set_wakeup_time; + efi.get_variable = runtime->get_variable; + efi.get_next_variable = runtime->get_next_variable; + efi.set_variable = runtime->set_variable; + efi.query_variable_info = runtime->query_variable_info; + efi.update_capsule = runtime->update_capsule; + efi.query_capsule_caps = runtime->query_capsule_caps; + efi.get_next_high_mono_count = runtime->get_next_high_mono_count; + efi.reset_system = runtime->reset_system; + + set_bit(EFI_RUNTIME_SERVICES, &arm_efi_facility); +} diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 790871a..395ab1d 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -55,6 +56,7 @@ #include #include #include +#include unsigned int processor_id; EXPORT_SYMBOL(processor_id); @@ -222,9 +224,13 @@ void __init setup_arch(char **cmdline_p) arm64_memblock_init(); + efi_init(); paging_init(); request_standard_resources(); + if (efi_enabled(EFI_BOOT)) + efi_enter_virtual_mode(); + unflatten_device_tree(); psci_init(); diff --git a/include/linux/efi.h b/include/linux/efi.h index bc5687d..510a6d0 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -655,7 +655,7 @@ extern int __init efi_setup_pcdp_console(char *); #define EFI_64BIT 5 /* Is the firmware 64-bit? */ #ifdef CONFIG_EFI -# ifdef CONFIG_X86 +# if defined(CONFIG_X86) || defined(CONFIG_ARM64) extern int efi_enabled(int facility); # else static inline int efi_enabled(int facility)