Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/firmware/efi/libstub/efi-stub.c
26483 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* EFI stub implementation that is shared by arm and arm64 architectures.
4
* This should be #included by the EFI stub implementation files.
5
*
6
* Copyright (C) 2013,2014 Linaro Limited
7
* Roy Franz <[email protected]
8
* Copyright (C) 2013 Red Hat, Inc.
9
* Mark Salter <[email protected]>
10
*/
11
12
#include <linux/efi.h>
13
#include <linux/screen_info.h>
14
#include <asm/efi.h>
15
16
#include "efistub.h"
17
18
/*
19
* This is the base address at which to start allocating virtual memory ranges
20
* for UEFI Runtime Services.
21
*
22
* For ARM/ARM64:
23
* This is in the low TTBR0 range so that we can use
24
* any allocation we choose, and eliminate the risk of a conflict after kexec.
25
* The value chosen is the largest non-zero power of 2 suitable for this purpose
26
* both on 32-bit and 64-bit ARM CPUs, to maximize the likelihood that it can
27
* be mapped efficiently.
28
* Since 32-bit ARM could potentially execute with a 1G/3G user/kernel split,
29
* map everything below 1 GB. (512 MB is a reasonable upper bound for the
30
* entire footprint of the UEFI runtime services memory regions)
31
*
32
* For RISC-V:
33
* There is no specific reason for which, this address (512MB) can't be used
34
* EFI runtime virtual address for RISC-V. It also helps to use EFI runtime
35
* services on both RV32/RV64. Keep the same runtime virtual address for RISC-V
36
* as well to minimize the code churn.
37
*/
38
#define EFI_RT_VIRTUAL_BASE SZ_512M
39
40
/*
41
* Some architectures map the EFI regions into the kernel's linear map using a
42
* fixed offset.
43
*/
44
#ifndef EFI_RT_VIRTUAL_OFFSET
45
#define EFI_RT_VIRTUAL_OFFSET 0
46
#endif
47
48
static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
49
static bool flat_va_mapping = (EFI_RT_VIRTUAL_OFFSET != 0);
50
51
void __weak free_screen_info(struct screen_info *si)
52
{
53
}
54
55
static struct screen_info *setup_graphics(void)
56
{
57
struct screen_info *si, tmp = {};
58
59
if (efi_setup_gop(&tmp) != EFI_SUCCESS)
60
return NULL;
61
62
si = alloc_screen_info();
63
if (!si)
64
return NULL;
65
66
*si = tmp;
67
return si;
68
}
69
70
static void install_memreserve_table(void)
71
{
72
struct linux_efi_memreserve *rsv;
73
efi_guid_t memreserve_table_guid = LINUX_EFI_MEMRESERVE_TABLE_GUID;
74
efi_status_t status;
75
76
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv),
77
(void **)&rsv);
78
if (status != EFI_SUCCESS) {
79
efi_err("Failed to allocate memreserve entry!\n");
80
return;
81
}
82
83
rsv->next = 0;
84
rsv->size = 0;
85
atomic_set(&rsv->count, 0);
86
87
status = efi_bs_call(install_configuration_table,
88
&memreserve_table_guid, rsv);
89
if (status != EFI_SUCCESS)
90
efi_err("Failed to install memreserve config table!\n");
91
}
92
93
static u32 get_supported_rt_services(void)
94
{
95
const efi_rt_properties_table_t *rt_prop_table;
96
u32 supported = EFI_RT_SUPPORTED_ALL;
97
98
rt_prop_table = get_efi_config_table(EFI_RT_PROPERTIES_TABLE_GUID);
99
if (rt_prop_table)
100
supported &= rt_prop_table->runtime_services_supported;
101
102
return supported;
103
}
104
105
efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
106
{
107
char *cmdline __free(efi_pool) = NULL;
108
efi_status_t status;
109
110
/*
111
* Get the command line from EFI, using the LOADED_IMAGE
112
* protocol. We are going to copy the command line into the
113
* device tree, so this can be allocated anywhere.
114
*/
115
cmdline = efi_convert_cmdline(image);
116
if (!cmdline) {
117
efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
118
return EFI_OUT_OF_RESOURCES;
119
}
120
121
if (!IS_ENABLED(CONFIG_CMDLINE_FORCE)) {
122
status = efi_parse_options(cmdline);
123
if (status != EFI_SUCCESS) {
124
efi_err("Failed to parse EFI load options\n");
125
return status;
126
}
127
}
128
129
if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
130
IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
131
cmdline[0] == 0) {
132
status = efi_parse_options(CONFIG_CMDLINE);
133
if (status != EFI_SUCCESS) {
134
efi_err("Failed to parse built-in command line\n");
135
return status;
136
}
137
}
138
139
*cmdline_ptr = no_free_ptr(cmdline);
140
return EFI_SUCCESS;
141
}
142
143
efi_status_t efi_stub_common(efi_handle_t handle,
144
efi_loaded_image_t *image,
145
unsigned long image_addr,
146
char *cmdline_ptr)
147
{
148
struct screen_info *si;
149
efi_status_t status;
150
151
status = check_platform_features();
152
if (status != EFI_SUCCESS)
153
return status;
154
155
si = setup_graphics();
156
157
efi_retrieve_eventlog();
158
159
/* Ask the firmware to clear memory on unclean shutdown */
160
efi_enable_reset_attack_mitigation();
161
162
efi_load_initrd(image, ULONG_MAX, efi_get_max_initrd_addr(image_addr),
163
NULL);
164
165
efi_random_get_seed();
166
167
/* force efi_novamap if SetVirtualAddressMap() is unsupported */
168
efi_novamap |= !(get_supported_rt_services() &
169
EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP);
170
171
install_memreserve_table();
172
173
status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr);
174
175
free_screen_info(si);
176
return status;
177
}
178
179
/*
180
* efi_allocate_virtmap() - create a pool allocation for the virtmap
181
*
182
* Create an allocation that is of sufficient size to hold all the memory
183
* descriptors that will be passed to SetVirtualAddressMap() to inform the
184
* firmware about the virtual mapping that will be used under the OS to call
185
* into the firmware.
186
*/
187
efi_status_t efi_alloc_virtmap(efi_memory_desc_t **virtmap,
188
unsigned long *desc_size, u32 *desc_ver)
189
{
190
unsigned long size, mmap_key;
191
efi_status_t status;
192
193
/*
194
* Use the size of the current memory map as an upper bound for the
195
* size of the buffer we need to pass to SetVirtualAddressMap() to
196
* cover all EFI_MEMORY_RUNTIME regions.
197
*/
198
size = 0;
199
status = efi_bs_call(get_memory_map, &size, NULL, &mmap_key, desc_size,
200
desc_ver);
201
if (status != EFI_BUFFER_TOO_SMALL)
202
return EFI_LOAD_ERROR;
203
204
return efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
205
(void **)virtmap);
206
}
207
208
/*
209
* efi_get_virtmap() - create a virtual mapping for the EFI memory map
210
*
211
* This function populates the virt_addr fields of all memory region descriptors
212
* in @memory_map whose EFI_MEMORY_RUNTIME attribute is set. Those descriptors
213
* are also copied to @runtime_map, and their total count is returned in @count.
214
*/
215
void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
216
unsigned long desc_size, efi_memory_desc_t *runtime_map,
217
int *count)
218
{
219
u64 efi_virt_base = virtmap_base;
220
efi_memory_desc_t *in, *out = runtime_map;
221
int l;
222
223
*count = 0;
224
225
for (l = 0; l < map_size; l += desc_size) {
226
u64 paddr, size;
227
228
in = (void *)memory_map + l;
229
if (!(in->attribute & EFI_MEMORY_RUNTIME))
230
continue;
231
232
paddr = in->phys_addr;
233
size = in->num_pages * EFI_PAGE_SIZE;
234
235
in->virt_addr = in->phys_addr + EFI_RT_VIRTUAL_OFFSET;
236
if (efi_novamap) {
237
continue;
238
}
239
240
/*
241
* Make the mapping compatible with 64k pages: this allows
242
* a 4k page size kernel to kexec a 64k page size kernel and
243
* vice versa.
244
*/
245
if (!flat_va_mapping) {
246
247
paddr = round_down(in->phys_addr, SZ_64K);
248
size += in->phys_addr - paddr;
249
250
/*
251
* Avoid wasting memory on PTEs by choosing a virtual
252
* base that is compatible with section mappings if this
253
* region has the appropriate size and physical
254
* alignment. (Sections are 2 MB on 4k granule kernels)
255
*/
256
if (IS_ALIGNED(in->phys_addr, SZ_2M) && size >= SZ_2M)
257
efi_virt_base = round_up(efi_virt_base, SZ_2M);
258
else
259
efi_virt_base = round_up(efi_virt_base, SZ_64K);
260
261
in->virt_addr += efi_virt_base - paddr;
262
efi_virt_base += size;
263
}
264
265
memcpy(out, in, desc_size);
266
out = (void *)out + desc_size;
267
++*count;
268
}
269
}
270
271