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: 3259611 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 32F649F1F4 for ; Fri, 29 Nov 2013 22:07:57 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A7AE52062E for ; Fri, 29 Nov 2013 22:07:55 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D698620625 for ; Fri, 29 Nov 2013 22:07:53 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VmWD8-0001p2-ME; Fri, 29 Nov 2013 22:06:55 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VmWCo-000390-US; Fri, 29 Nov 2013 22:06:34 +0000 Received: from mx1.redhat.com ([209.132.183.28]) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VmWC7-00035M-Id for linux-arm-kernel@lists.infradead.org; Fri, 29 Nov 2013 22:06:00 +0000 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 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-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20131129_170551_950822_8AF7C9D0 X-CRM114-Status: GOOD ( 27.11 ) X-Spam-Score: -6.9 (------) Cc: matt.fleming@intel.com, patches@linaro.org, Catalin Marinas , Will Deacon , Leif Lindholm , roy.franz@linaro.org, linux-efi@vger.kernel.org, Mark Salter , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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)