aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2015-11-30 07:28:18 -0500
committerWill Deacon <will.deacon@arm.com>2015-12-09 11:57:23 -0500
commite5bc22a42e4d46cc203fdfb6d2c76202b08666a0 (patch)
tree17e4fb14f10906ef57fb7937d03ffc8a1ded9d64
parent4dffbfc48d65e5d8157a634fd670065d237a9377 (diff)
arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM
This splits off the early EFI init and runtime code that - discovers the EFI params and the memory map from the FDT, and installs the memblocks and config tables. - prepares and installs the EFI page tables so that UEFI Runtime Services can be invoked at the virtual address installed by the stub. This will allow it to be reused for 32-bit ARM. Reviewed-by: Matt Fleming <matt@codeblueprint.co.uk> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--arch/arm64/kernel/efi.c326
-rw-r--r--drivers/firmware/efi/Makefile3
-rw-r--r--drivers/firmware/efi/arm-init.c208
-rw-r--r--drivers/firmware/efi/arm-runtime.c151
4 files changed, 363 insertions, 325 deletions
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 04531d35f1df..bd3b2f5adf0c 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -11,318 +11,11 @@
11 * 11 *
12 */ 12 */
13 13
14#include <linux/atomic.h>
15#include <linux/dmi.h> 14#include <linux/dmi.h>
16#include <linux/efi.h> 15#include <linux/efi.h>
17#include <linux/export.h> 16#include <linux/init.h>
18#include <linux/memblock.h>
19#include <linux/mm_types.h>
20#include <linux/bootmem.h>
21#include <linux/of.h>
22#include <linux/of_fdt.h>
23#include <linux/preempt.h>
24#include <linux/rbtree.h>
25#include <linux/rwsem.h>
26#include <linux/sched.h>
27#include <linux/slab.h>
28#include <linux/spinlock.h>
29 17
30#include <asm/cacheflush.h>
31#include <asm/efi.h> 18#include <asm/efi.h>
32#include <asm/tlbflush.h>
33#include <asm/mmu_context.h>
34#include <asm/mmu.h>
35#include <asm/pgtable.h>
36
37struct efi_memory_map memmap;
38
39static u64 efi_system_table;
40
41static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss;
42
43static struct mm_struct efi_mm = {
44 .mm_rb = RB_ROOT,
45 .pgd = efi_pgd,
46 .mm_users = ATOMIC_INIT(2),
47 .mm_count = ATOMIC_INIT(1),
48 .mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem),
49 .page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
50 .mmlist = LIST_HEAD_INIT(efi_mm.mmlist),
51};
52
53static int __init is_normal_ram(efi_memory_desc_t *md)
54{
55 if (md->attribute & EFI_MEMORY_WB)
56 return 1;
57 return 0;
58}
59
60/*
61 * Translate a EFI virtual address into a physical address: this is necessary,
62 * as some data members of the EFI system table are virtually remapped after
63 * SetVirtualAddressMap() has been called.
64 */
65static phys_addr_t efi_to_phys(unsigned long addr)
66{
67 efi_memory_desc_t *md;
68
69 for_each_efi_memory_desc(&memmap, md) {
70 if (!(md->attribute & EFI_MEMORY_RUNTIME))
71 continue;
72 if (md->virt_addr == 0)
73 /* no virtual mapping has been installed by the stub */
74 break;
75 if (md->virt_addr <= addr &&
76 (addr - md->virt_addr) < (md->num_pages << EFI_PAGE_SHIFT))
77 return md->phys_addr + addr - md->virt_addr;
78 }
79 return addr;
80}
81
82static int __init uefi_init(void)
83{
84 efi_char16_t *c16;
85 void *config_tables;
86 u64 table_size;
87 char vendor[100] = "unknown";
88 int i, retval;
89
90 efi.systab = early_memremap(efi_system_table,
91 sizeof(efi_system_table_t));
92 if (efi.systab == NULL) {
93 pr_warn("Unable to map EFI system table.\n");
94 return -ENOMEM;
95 }
96
97 set_bit(EFI_BOOT, &efi.flags);
98 set_bit(EFI_64BIT, &efi.flags);
99
100 /*
101 * Verify the EFI Table
102 */
103 if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
104 pr_err("System table signature incorrect\n");
105 retval = -EINVAL;
106 goto out;
107 }
108 if ((efi.systab->hdr.revision >> 16) < 2)
109 pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
110 efi.systab->hdr.revision >> 16,
111 efi.systab->hdr.revision & 0xffff);
112
113 /* Show what we know for posterity */
114 c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor),
115 sizeof(vendor) * sizeof(efi_char16_t));
116 if (c16) {
117 for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
118 vendor[i] = c16[i];
119 vendor[i] = '\0';
120 early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t));
121 }
122
123 pr_info("EFI v%u.%.02u by %s\n",
124 efi.systab->hdr.revision >> 16,
125 efi.systab->hdr.revision & 0xffff, vendor);
126
127 table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
128 config_tables = early_memremap(efi_to_phys(efi.systab->tables),
129 table_size);
130 if (config_tables == NULL) {
131 pr_warn("Unable to map EFI config table array.\n");
132 retval = -ENOMEM;
133 goto out;
134 }
135 retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
136 sizeof(efi_config_table_64_t), NULL);
137
138 early_memunmap(config_tables, table_size);
139out:
140 early_memunmap(efi.systab, sizeof(efi_system_table_t));
141 return retval;
142}
143
144/*
145 * Return true for RAM regions we want to permanently reserve.
146 */
147static __init int is_reserve_region(efi_memory_desc_t *md)
148{
149 switch (md->type) {
150 case EFI_LOADER_CODE:
151 case EFI_LOADER_DATA:
152 case EFI_BOOT_SERVICES_CODE:
153 case EFI_BOOT_SERVICES_DATA:
154 case EFI_CONVENTIONAL_MEMORY:
155 case EFI_PERSISTENT_MEMORY:
156 return 0;
157 default:
158 break;
159 }
160 return is_normal_ram(md);
161}
162
163static __init void reserve_regions(void)
164{
165 efi_memory_desc_t *md;
166 u64 paddr, npages, size;
167
168 if (efi_enabled(EFI_DBG))
169 pr_info("Processing EFI memory map:\n");
170
171 for_each_efi_memory_desc(&memmap, md) {
172 paddr = md->phys_addr;
173 npages = md->num_pages;
174
175 if (efi_enabled(EFI_DBG)) {
176 char buf[64];
177
178 pr_info(" 0x%012llx-0x%012llx %s",
179 paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
180 efi_md_typeattr_format(buf, sizeof(buf), md));
181 }
182
183 memrange_efi_to_native(&paddr, &npages);
184 size = npages << PAGE_SHIFT;
185
186 if (is_normal_ram(md))
187 early_init_dt_add_memory_arch(paddr, size);
188
189 if (is_reserve_region(md)) {
190 memblock_mark_nomap(paddr, size);
191 if (efi_enabled(EFI_DBG))
192 pr_cont("*");
193 }
194
195 if (efi_enabled(EFI_DBG))
196 pr_cont("\n");
197 }
198
199 set_bit(EFI_MEMMAP, &efi.flags);
200}
201
202void __init efi_init(void)
203{
204 struct efi_fdt_params params;
205
206 /* Grab UEFI information placed in FDT by stub */
207 if (!efi_get_fdt_params(&params))
208 return;
209
210 efi_system_table = params.system_table;
211
212 memmap.phys_map = params.mmap;
213 memmap.map = early_memremap(params.mmap, params.mmap_size);
214 if (memmap.map == NULL) {
215 /*
216 * If we are booting via UEFI, the UEFI memory map is the only
217 * description of memory we have, so there is little point in
218 * proceeding if we cannot access it.
219 */
220 panic("Unable to map EFI memory map.\n");
221 }
222 memmap.map_end = memmap.map + params.mmap_size;
223 memmap.desc_size = params.desc_size;
224 memmap.desc_version = params.desc_ver;
225
226 if (uefi_init() < 0)
227 return;
228
229 reserve_regions();
230 early_memunmap(memmap.map, params.mmap_size);
231 memblock_mark_nomap(params.mmap & PAGE_MASK,
232 PAGE_ALIGN(params.mmap_size +
233 (params.mmap & ~PAGE_MASK)));
234}
235
236static bool __init efi_virtmap_init(void)
237{
238 efi_memory_desc_t *md;
239
240 init_new_context(NULL, &efi_mm);
241
242 for_each_efi_memory_desc(&memmap, md) {
243 pgprot_t prot;
244
245 if (!(md->attribute & EFI_MEMORY_RUNTIME))
246 continue;
247 if (md->virt_addr == 0)
248 return false;
249
250 pr_info(" EFI remap 0x%016llx => %p\n",
251 md->phys_addr, (void *)md->virt_addr);
252
253 /*
254 * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
255 * executable, everything else can be mapped with the XN bits
256 * set.
257 */
258 if (!is_normal_ram(md))
259 prot = __pgprot(PROT_DEVICE_nGnRE);
260 else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
261 !PAGE_ALIGNED(md->phys_addr))
262 prot = PAGE_KERNEL_EXEC;
263 else
264 prot = PAGE_KERNEL;
265
266 create_pgd_mapping(&efi_mm, md->phys_addr, md->virt_addr,
267 md->num_pages << EFI_PAGE_SHIFT,
268 __pgprot(pgprot_val(prot) | PTE_NG));
269 }
270 return true;
271}
272
273/*
274 * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
275 * non-early mapping of the UEFI system table and virtual mappings for all
276 * EFI_MEMORY_RUNTIME regions.
277 */
278static int __init arm64_enable_runtime_services(void)
279{
280 u64 mapsize;
281
282 if (!efi_enabled(EFI_BOOT)) {
283 pr_info("EFI services will not be available.\n");
284 return 0;
285 }
286
287 if (efi_runtime_disabled()) {
288 pr_info("EFI runtime services will be disabled.\n");
289 return 0;
290 }
291
292 pr_info("Remapping and enabling EFI services.\n");
293
294 mapsize = memmap.map_end - memmap.map;
295 memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
296 mapsize);
297 if (!memmap.map) {
298 pr_err("Failed to remap EFI memory map\n");
299 return -ENOMEM;
300 }
301 memmap.map_end = memmap.map + mapsize;
302 efi.memmap = &memmap;
303
304 efi.systab = (__force void *)ioremap_cache(efi_system_table,
305 sizeof(efi_system_table_t));
306 if (!efi.systab) {
307 pr_err("Failed to remap EFI System Table\n");
308 return -ENOMEM;
309 }
310 set_bit(EFI_SYSTEM_TABLES, &efi.flags);
311
312 if (!efi_virtmap_init()) {
313 pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
314 return -ENOMEM;
315 }
316
317 /* Set up runtime services function pointers */
318 efi_native_runtime_setup();
319 set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
320
321 efi.runtime_version = efi.systab->hdr.revision;
322
323 return 0;
324}
325early_initcall(arm64_enable_runtime_services);
326 19
327static int __init arm64_dmi_init(void) 20static int __init arm64_dmi_init(void)
328{ 21{
@@ -338,23 +31,6 @@ static int __init arm64_dmi_init(void)
338} 31}
339core_initcall(arm64_dmi_init); 32core_initcall(arm64_dmi_init);
340 33
341static void efi_set_pgd(struct mm_struct *mm)
342{
343 switch_mm(NULL, mm, NULL);
344}
345
346void efi_virtmap_load(void)
347{
348 preempt_disable();
349 efi_set_pgd(&efi_mm);
350}
351
352void efi_virtmap_unload(void)
353{
354 efi_set_pgd(current->active_mm);
355 preempt_enable();
356}
357
358/* 34/*
359 * UpdateCapsule() depends on the system being shutdown via 35 * UpdateCapsule() depends on the system being shutdown via
360 * ResetSystem(). 36 * ResetSystem().
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index ec379a4164cc..f292917b00e7 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -18,3 +18,6 @@ obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o
18obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o 18obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o
19obj-$(CONFIG_EFI_STUB) += libstub/ 19obj-$(CONFIG_EFI_STUB) += libstub/
20obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o 20obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o
21
22arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o
23obj-$(CONFIG_ARM64) += $(arm-obj-y)
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
new file mode 100644
index 000000000000..ffdd76a51929
--- /dev/null
+++ b/drivers/firmware/efi/arm-init.c
@@ -0,0 +1,208 @@
1/*
2 * Extensible Firmware Interface
3 *
4 * Based on Extensible Firmware Interface Specification version 2.4
5 *
6 * Copyright (C) 2013 - 2015 Linaro Ltd.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13
14#include <linux/efi.h>
15#include <linux/init.h>
16#include <linux/memblock.h>
17#include <linux/mm_types.h>
18#include <linux/of.h>
19#include <linux/of_fdt.h>
20
21#include <asm/efi.h>
22
23struct efi_memory_map memmap;
24
25u64 efi_system_table;
26
27static int __init is_normal_ram(efi_memory_desc_t *md)
28{
29 if (md->attribute & EFI_MEMORY_WB)
30 return 1;
31 return 0;
32}
33
34/*
35 * Translate a EFI virtual address into a physical address: this is necessary,
36 * as some data members of the EFI system table are virtually remapped after
37 * SetVirtualAddressMap() has been called.
38 */
39static phys_addr_t efi_to_phys(unsigned long addr)
40{
41 efi_memory_desc_t *md;
42
43 for_each_efi_memory_desc(&memmap, md) {
44 if (!(md->attribute & EFI_MEMORY_RUNTIME))
45 continue;
46 if (md->virt_addr == 0)
47 /* no virtual mapping has been installed by the stub */
48 break;
49 if (md->virt_addr <= addr &&
50 (addr - md->virt_addr) < (md->num_pages << EFI_PAGE_SHIFT))
51 return md->phys_addr + addr - md->virt_addr;
52 }
53 return addr;
54}
55
56static int __init uefi_init(void)
57{
58 efi_char16_t *c16;
59 void *config_tables;
60 u64 table_size;
61 char vendor[100] = "unknown";
62 int i, retval;
63
64 efi.systab = early_memremap(efi_system_table,
65 sizeof(efi_system_table_t));
66 if (efi.systab == NULL) {
67 pr_warn("Unable to map EFI system table.\n");
68 return -ENOMEM;
69 }
70
71 set_bit(EFI_BOOT, &efi.flags);
72 set_bit(EFI_64BIT, &efi.flags);
73
74 /*
75 * Verify the EFI Table
76 */
77 if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
78 pr_err("System table signature incorrect\n");
79 retval = -EINVAL;
80 goto out;
81 }
82 if ((efi.systab->hdr.revision >> 16) < 2)
83 pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
84 efi.systab->hdr.revision >> 16,
85 efi.systab->hdr.revision & 0xffff);
86
87 /* Show what we know for posterity */
88 c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor),
89 sizeof(vendor) * sizeof(efi_char16_t));
90 if (c16) {
91 for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
92 vendor[i] = c16[i];
93 vendor[i] = '\0';
94 early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t));
95 }
96
97 pr_info("EFI v%u.%.02u by %s\n",
98 efi.systab->hdr.revision >> 16,
99 efi.systab->hdr.revision & 0xffff, vendor);
100
101 table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
102 config_tables = early_memremap(efi_to_phys(efi.systab->tables),
103 table_size);
104 if (config_tables == NULL) {
105 pr_warn("Unable to map EFI config table array.\n");
106 retval = -ENOMEM;
107 goto out;
108 }
109 retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
110 sizeof(efi_config_table_64_t), NULL);
111
112 early_memunmap(config_tables, table_size);
113out:
114 early_memunmap(efi.systab, sizeof(efi_system_table_t));
115 return retval;
116}
117
118/*
119 * Return true for RAM regions we want to permanently reserve.
120 */
121static __init int is_reserve_region(efi_memory_desc_t *md)
122{
123 switch (md->type) {
124 case EFI_LOADER_CODE:
125 case EFI_LOADER_DATA:
126 case EFI_BOOT_SERVICES_CODE:
127 case EFI_BOOT_SERVICES_DATA:
128 case EFI_CONVENTIONAL_MEMORY:
129 case EFI_PERSISTENT_MEMORY:
130 return 0;
131 default:
132 break;
133 }
134 return is_normal_ram(md);
135}
136
137static __init void reserve_regions(void)
138{
139 efi_memory_desc_t *md;
140 u64 paddr, npages, size;
141
142 if (efi_enabled(EFI_DBG))
143 pr_info("Processing EFI memory map:\n");
144
145 for_each_efi_memory_desc(&memmap, md) {
146 paddr = md->phys_addr;
147 npages = md->num_pages;
148
149 if (efi_enabled(EFI_DBG)) {
150 char buf[64];
151
152 pr_info(" 0x%012llx-0x%012llx %s",
153 paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
154 efi_md_typeattr_format(buf, sizeof(buf), md));
155 }
156
157 memrange_efi_to_native(&paddr, &npages);
158 size = npages << PAGE_SHIFT;
159
160 if (is_normal_ram(md))
161 early_init_dt_add_memory_arch(paddr, size);
162
163 if (is_reserve_region(md)) {
164 memblock_mark_nomap(paddr, size);
165 if (efi_enabled(EFI_DBG))
166 pr_cont("*");
167 }
168
169 if (efi_enabled(EFI_DBG))
170 pr_cont("\n");
171 }
172
173 set_bit(EFI_MEMMAP, &efi.flags);
174}
175
176void __init efi_init(void)
177{
178 struct efi_fdt_params params;
179
180 /* Grab UEFI information placed in FDT by stub */
181 if (!efi_get_fdt_params(&params))
182 return;
183
184 efi_system_table = params.system_table;
185
186 memmap.phys_map = params.mmap;
187 memmap.map = early_memremap(params.mmap, params.mmap_size);
188 if (memmap.map == NULL) {
189 /*
190 * If we are booting via UEFI, the UEFI memory map is the only
191 * description of memory we have, so there is little point in
192 * proceeding if we cannot access it.
193 */
194 panic("Unable to map EFI memory map.\n");
195 }
196 memmap.map_end = memmap.map + params.mmap_size;
197 memmap.desc_size = params.desc_size;
198 memmap.desc_version = params.desc_ver;
199
200 if (uefi_init() < 0)
201 return;
202
203 reserve_regions();
204 early_memunmap(memmap.map, params.mmap_size);
205 memblock_mark_nomap(params.mmap & PAGE_MASK,
206 PAGE_ALIGN(params.mmap_size +
207 (params.mmap & ~PAGE_MASK)));
208}
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
new file mode 100644
index 000000000000..974743e13a4d
--- /dev/null
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -0,0 +1,151 @@
1/*
2 * Extensible Firmware Interface
3 *
4 * Based on Extensible Firmware Interface Specification version 2.4
5 *
6 * Copyright (C) 2013, 2014 Linaro Ltd.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13
14#include <linux/efi.h>
15#include <linux/memblock.h>
16#include <linux/mm_types.h>
17#include <linux/preempt.h>
18#include <linux/rbtree.h>
19#include <linux/rwsem.h>
20#include <linux/sched.h>
21#include <linux/slab.h>
22#include <linux/spinlock.h>
23
24#include <asm/cacheflush.h>
25#include <asm/efi.h>
26#include <asm/tlbflush.h>
27#include <asm/mmu_context.h>
28#include <asm/mmu.h>
29#include <asm/pgtable.h>
30
31static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss;
32
33extern u64 efi_system_table;
34
35static struct mm_struct efi_mm = {
36 .mm_rb = RB_ROOT,
37 .pgd = efi_pgd,
38 .mm_users = ATOMIC_INIT(2),
39 .mm_count = ATOMIC_INIT(1),
40 .mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem),
41 .page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
42 .mmlist = LIST_HEAD_INIT(efi_mm.mmlist),
43};
44
45static bool __init efi_virtmap_init(void)
46{
47 efi_memory_desc_t *md;
48
49 init_new_context(NULL, &efi_mm);
50
51 for_each_efi_memory_desc(&memmap, md) {
52 pgprot_t prot;
53
54 if (!(md->attribute & EFI_MEMORY_RUNTIME))
55 continue;
56 if (md->virt_addr == 0)
57 return false;
58
59 pr_info(" EFI remap 0x%016llx => %p\n",
60 md->phys_addr, (void *)md->virt_addr);
61
62 /*
63 * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
64 * executable, everything else can be mapped with the XN bits
65 * set.
66 */
67 if ((md->attribute & EFI_MEMORY_WB) == 0)
68 prot = __pgprot(PROT_DEVICE_nGnRE);
69 else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
70 !PAGE_ALIGNED(md->phys_addr))
71 prot = PAGE_KERNEL_EXEC;
72 else
73 prot = PAGE_KERNEL;
74
75 create_pgd_mapping(&efi_mm, md->phys_addr, md->virt_addr,
76 md->num_pages << EFI_PAGE_SHIFT,
77 __pgprot(pgprot_val(prot) | PTE_NG));
78 }
79 return true;
80}
81
82/*
83 * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
84 * non-early mapping of the UEFI system table and virtual mappings for all
85 * EFI_MEMORY_RUNTIME regions.
86 */
87static int __init arm64_enable_runtime_services(void)
88{
89 u64 mapsize;
90
91 if (!efi_enabled(EFI_BOOT)) {
92 pr_info("EFI services will not be available.\n");
93 return 0;
94 }
95
96 if (efi_runtime_disabled()) {
97 pr_info("EFI runtime services will be disabled.\n");
98 return 0;
99 }
100
101 pr_info("Remapping and enabling EFI services.\n");
102
103 mapsize = memmap.map_end - memmap.map;
104 memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
105 mapsize);
106 if (!memmap.map) {
107 pr_err("Failed to remap EFI memory map\n");
108 return -ENOMEM;
109 }
110 memmap.map_end = memmap.map + mapsize;
111 efi.memmap = &memmap;
112
113 efi.systab = (__force void *)ioremap_cache(efi_system_table,
114 sizeof(efi_system_table_t));
115 if (!efi.systab) {
116 pr_err("Failed to remap EFI System Table\n");
117 return -ENOMEM;
118 }
119 set_bit(EFI_SYSTEM_TABLES, &efi.flags);
120
121 if (!efi_virtmap_init()) {
122 pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
123 return -ENOMEM;
124 }
125
126 /* Set up runtime services function pointers */
127 efi_native_runtime_setup();
128 set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
129
130 efi.runtime_version = efi.systab->hdr.revision;
131
132 return 0;
133}
134early_initcall(arm64_enable_runtime_services);
135
136static void efi_set_pgd(struct mm_struct *mm)
137{
138 switch_mm(NULL, mm, NULL);
139}
140
141void efi_virtmap_load(void)
142{
143 preempt_disable();
144 efi_set_pgd(&efi_mm);
145}
146
147void efi_virtmap_unload(void)
148{
149 efi_set_pgd(current->active_mm);
150 preempt_enable();
151}