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(mm: &efi_mm); |
58 | init_new_context(NULL, mm: &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(mm: &efi_mm, fn: 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(addr: efi.memmap.phys_map, size: 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(size: 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(parent: &iomem_resource, new: 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, addr: &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 | |