xref: /linux/drivers/firmware/efi/arm-runtime.c (revision 24168c5e6dfbdd5b414f048f47f75d64533296ca)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Extensible Firmware Interface
4  *
5  * Based on Extensible Firmware Interface Specification version 2.4
6  *
7  * Copyright (C) 2013, 2014 Linaro Ltd.
8  */
9 
10 #include <linux/dmi.h>
11 #include <linux/efi.h>
12 #include <linux/io.h>
13 #include <linux/memblock.h>
14 #include <linux/mm_types.h>
15 #include <linux/preempt.h>
16 #include <linux/rbtree.h>
17 #include <linux/rwsem.h>
18 #include <linux/sched.h>
19 #include <linux/slab.h>
20 #include <linux/spinlock.h>
21 #include <linux/pgtable.h>
22 
23 #include <asm/cacheflush.h>
24 #include <asm/efi.h>
25 #include <asm/mmu.h>
26 #include <asm/pgalloc.h>
27 
28 #if defined(CONFIG_PTDUMP_DEBUGFS) || defined(CONFIG_ARM_PTDUMP_DEBUGFS)
29 #include <asm/ptdump.h>
30 
31 static struct ptdump_info efi_ptdump_info = {
32 	.mm		= &efi_mm,
33 	.markers	= (struct addr_marker[]){
34 		{ 0,				"UEFI runtime start" },
35 		{ EFI_RUNTIME_MAP_END,		"UEFI runtime end" },
36 		{ -1,				NULL }
37 	},
38 	.base_addr	= 0,
39 };
40 
41 static int __init ptdump_init(void)
42 {
43 	if (efi_enabled(EFI_RUNTIME_SERVICES))
44 		ptdump_debugfs_register(&efi_ptdump_info, "efi_page_tables");
45 
46 	return 0;
47 }
48 device_initcall(ptdump_init);
49 
50 #endif
51 
52 static bool __init efi_virtmap_init(void)
53 {
54 	efi_memory_desc_t *md;
55 
56 	efi_mm.pgd = pgd_alloc(&efi_mm);
57 	mm_init_cpumask(&efi_mm);
58 	init_new_context(NULL, &efi_mm);
59 
60 	for_each_efi_memory_desc(md) {
61 		phys_addr_t phys = md->phys_addr;
62 		int ret;
63 
64 		if (!(md->attribute & EFI_MEMORY_RUNTIME))
65 			continue;
66 		if (md->virt_addr == U64_MAX)
67 			return false;
68 
69 		ret = efi_create_mapping(&efi_mm, md);
70 		if (ret) {
71 			pr_warn("  EFI remap %pa: failed to create mapping (%d)\n",
72 				&phys, ret);
73 			return false;
74 		}
75 	}
76 
77 	if (efi_memattr_apply_permissions(&efi_mm, efi_set_mapping_permissions))
78 		return false;
79 
80 	return true;
81 }
82 
83 /*
84  * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
85  * non-early mapping of the UEFI system table and virtual mappings for all
86  * EFI_MEMORY_RUNTIME regions.
87  */
88 static int __init arm_enable_runtime_services(void)
89 {
90 	u64 mapsize;
91 
92 	if (!efi_enabled(EFI_BOOT)) {
93 		pr_info("EFI services will not be available.\n");
94 		return 0;
95 	}
96 
97 	efi_memmap_unmap();
98 
99 	mapsize = efi.memmap.desc_size * efi.memmap.nr_map;
100 
101 	if (efi_memmap_init_late(efi.memmap.phys_map, mapsize)) {
102 		pr_err("Failed to remap EFI memory map\n");
103 		return 0;
104 	}
105 
106 	if (efi_soft_reserve_enabled()) {
107 		efi_memory_desc_t *md;
108 
109 		for_each_efi_memory_desc(md) {
110 			u64 md_size = md->num_pages << EFI_PAGE_SHIFT;
111 			struct resource *res;
112 
113 			if (!(md->attribute & EFI_MEMORY_SP))
114 				continue;
115 
116 			res = kzalloc(sizeof(*res), GFP_KERNEL);
117 			if (WARN_ON(!res))
118 				break;
119 
120 			res->start	= md->phys_addr;
121 			res->end	= md->phys_addr + md_size - 1;
122 			res->name	= "Soft Reserved";
123 			res->flags	= IORESOURCE_MEM;
124 			res->desc	= IORES_DESC_SOFT_RESERVED;
125 
126 			insert_resource(&iomem_resource, res);
127 		}
128 	}
129 
130 	if (efi_runtime_disabled()) {
131 		pr_info("EFI runtime services will be disabled.\n");
132 		return 0;
133 	}
134 
135 	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
136 		pr_info("EFI runtime services access via paravirt.\n");
137 		return 0;
138 	}
139 
140 	pr_info("Remapping and enabling EFI services.\n");
141 
142 	if (!efi_virtmap_init()) {
143 		pr_err("UEFI virtual mapping missing or invalid -- runtime services will not be available\n");
144 		return -ENOMEM;
145 	}
146 
147 	/* Set up runtime services function pointers */
148 	efi_native_runtime_setup();
149 	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
150 
151 	return 0;
152 }
153 early_initcall(arm_enable_runtime_services);
154 
155 void efi_virtmap_load(void)
156 {
157 	preempt_disable();
158 	efi_set_pgd(&efi_mm);
159 }
160 
161 void efi_virtmap_unload(void)
162 {
163 	efi_set_pgd(current->active_mm);
164 	preempt_enable();
165 }
166 
167 
168 static int __init arm_dmi_init(void)
169 {
170 	/*
171 	 * On arm64/ARM, DMI depends on UEFI, and dmi_setup() needs to
172 	 * be called early because dmi_id_init(), which is an arch_initcall
173 	 * itself, depends on dmi_scan_machine() having been called already.
174 	 */
175 	dmi_setup();
176 	return 0;
177 }
178 core_initcall(arm_dmi_init);
179