.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * FDT related Helper functions used by the EFI stub on multiple |
---|
3 | 4 | * architectures. This should be #included by the EFI stub |
---|
4 | 5 | * implementation files. |
---|
5 | 6 | * |
---|
6 | 7 | * Copyright 2013 Linaro Limited; author Roy Franz |
---|
7 | | - * |
---|
8 | | - * This file is part of the Linux kernel, and is made available |
---|
9 | | - * under the terms of the GNU General Public License version 2. |
---|
10 | | - * |
---|
11 | 8 | */ |
---|
12 | 9 | |
---|
13 | 10 | #include <linux/efi.h> |
---|
.. | .. |
---|
19 | 16 | #define EFI_DT_ADDR_CELLS_DEFAULT 2 |
---|
20 | 17 | #define EFI_DT_SIZE_CELLS_DEFAULT 2 |
---|
21 | 18 | |
---|
22 | | -static void fdt_update_cell_size(efi_system_table_t *sys_table, void *fdt) |
---|
| 19 | +static void fdt_update_cell_size(void *fdt) |
---|
23 | 20 | { |
---|
24 | 21 | int offset; |
---|
25 | 22 | |
---|
26 | 23 | offset = fdt_path_offset(fdt, "/"); |
---|
27 | 24 | /* Set the #address-cells and #size-cells values for an empty tree */ |
---|
28 | 25 | |
---|
29 | | - fdt_setprop_u32(fdt, offset, "#address-cells", |
---|
30 | | - EFI_DT_ADDR_CELLS_DEFAULT); |
---|
31 | | - |
---|
32 | | - fdt_setprop_u32(fdt, offset, "#size-cells", EFI_DT_SIZE_CELLS_DEFAULT); |
---|
| 26 | + fdt_setprop_u32(fdt, offset, "#address-cells", EFI_DT_ADDR_CELLS_DEFAULT); |
---|
| 27 | + fdt_setprop_u32(fdt, offset, "#size-cells", EFI_DT_SIZE_CELLS_DEFAULT); |
---|
33 | 28 | } |
---|
34 | 29 | |
---|
35 | | -static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, |
---|
36 | | - unsigned long orig_fdt_size, |
---|
| 30 | +static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size, |
---|
37 | 31 | void *fdt, int new_fdt_size, char *cmdline_ptr, |
---|
38 | 32 | u64 initrd_addr, u64 initrd_size) |
---|
39 | 33 | { |
---|
.. | .. |
---|
42 | 36 | u32 fdt_val32; |
---|
43 | 37 | u64 fdt_val64; |
---|
44 | 38 | |
---|
45 | | - /* Do some checks on provided FDT, if it exists*/ |
---|
| 39 | + /* Do some checks on provided FDT, if it exists: */ |
---|
46 | 40 | if (orig_fdt) { |
---|
47 | 41 | if (fdt_check_header(orig_fdt)) { |
---|
48 | | - pr_efi_err(sys_table, "Device Tree header not valid!\n"); |
---|
| 42 | + efi_err("Device Tree header not valid!\n"); |
---|
49 | 43 | return EFI_LOAD_ERROR; |
---|
50 | 44 | } |
---|
51 | 45 | /* |
---|
52 | 46 | * We don't get the size of the FDT if we get if from a |
---|
53 | | - * configuration table. |
---|
| 47 | + * configuration table: |
---|
54 | 48 | */ |
---|
55 | 49 | if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) { |
---|
56 | | - pr_efi_err(sys_table, "Truncated device tree! foo!\n"); |
---|
| 50 | + efi_err("Truncated device tree! foo!\n"); |
---|
57 | 51 | return EFI_LOAD_ERROR; |
---|
58 | 52 | } |
---|
59 | 53 | } |
---|
.. | .. |
---|
64 | 58 | status = fdt_create_empty_tree(fdt, new_fdt_size); |
---|
65 | 59 | if (status == 0) { |
---|
66 | 60 | /* |
---|
67 | | - * Any failure from the following function is non |
---|
68 | | - * critical |
---|
| 61 | + * Any failure from the following function is |
---|
| 62 | + * non-critical: |
---|
69 | 63 | */ |
---|
70 | | - fdt_update_cell_size(sys_table, fdt); |
---|
| 64 | + fdt_update_cell_size(fdt); |
---|
71 | 65 | } |
---|
72 | 66 | } |
---|
73 | 67 | |
---|
.. | .. |
---|
86 | 80 | if (node < 0) { |
---|
87 | 81 | node = fdt_add_subnode(fdt, 0, "chosen"); |
---|
88 | 82 | if (node < 0) { |
---|
89 | | - status = node; /* node is error code when negative */ |
---|
| 83 | + /* 'node' is an error code when negative: */ |
---|
| 84 | + status = node; |
---|
90 | 85 | goto fdt_set_fail; |
---|
91 | 86 | } |
---|
92 | 87 | } |
---|
93 | 88 | |
---|
94 | | - if ((cmdline_ptr != NULL) && (strlen(cmdline_ptr) > 0)) { |
---|
| 89 | + if (cmdline_ptr != NULL && strlen(cmdline_ptr) > 0) { |
---|
95 | 90 | status = fdt_setprop(fdt, node, "bootargs", cmdline_ptr, |
---|
96 | 91 | strlen(cmdline_ptr) + 1); |
---|
97 | 92 | if (status) |
---|
.. | .. |
---|
103 | 98 | u64 initrd_image_end; |
---|
104 | 99 | u64 initrd_image_start = cpu_to_fdt64(initrd_addr); |
---|
105 | 100 | |
---|
106 | | - status = fdt_setprop(fdt, node, "linux,initrd-start", |
---|
107 | | - &initrd_image_start, sizeof(u64)); |
---|
| 101 | + status = fdt_setprop_var(fdt, node, "linux,initrd-start", initrd_image_start); |
---|
108 | 102 | if (status) |
---|
109 | 103 | goto fdt_set_fail; |
---|
| 104 | + |
---|
110 | 105 | initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size); |
---|
111 | | - status = fdt_setprop(fdt, node, "linux,initrd-end", |
---|
112 | | - &initrd_image_end, sizeof(u64)); |
---|
| 106 | + status = fdt_setprop_var(fdt, node, "linux,initrd-end", initrd_image_end); |
---|
113 | 107 | if (status) |
---|
114 | 108 | goto fdt_set_fail; |
---|
115 | 109 | } |
---|
116 | 110 | |
---|
117 | 111 | /* Add FDT entries for EFI runtime services in chosen node. */ |
---|
118 | 112 | node = fdt_subnode_offset(fdt, 0, "chosen"); |
---|
119 | | - fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table); |
---|
120 | | - status = fdt_setprop(fdt, node, "linux,uefi-system-table", |
---|
121 | | - &fdt_val64, sizeof(fdt_val64)); |
---|
| 113 | + fdt_val64 = cpu_to_fdt64((u64)(unsigned long)efi_system_table); |
---|
| 114 | + |
---|
| 115 | + status = fdt_setprop_var(fdt, node, "linux,uefi-system-table", fdt_val64); |
---|
122 | 116 | if (status) |
---|
123 | 117 | goto fdt_set_fail; |
---|
124 | 118 | |
---|
125 | 119 | fdt_val64 = U64_MAX; /* placeholder */ |
---|
126 | | - status = fdt_setprop(fdt, node, "linux,uefi-mmap-start", |
---|
127 | | - &fdt_val64, sizeof(fdt_val64)); |
---|
| 120 | + |
---|
| 121 | + status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-start", fdt_val64); |
---|
128 | 122 | if (status) |
---|
129 | 123 | goto fdt_set_fail; |
---|
130 | 124 | |
---|
131 | 125 | fdt_val32 = U32_MAX; /* placeholder */ |
---|
132 | | - status = fdt_setprop(fdt, node, "linux,uefi-mmap-size", |
---|
133 | | - &fdt_val32, sizeof(fdt_val32)); |
---|
| 126 | + |
---|
| 127 | + status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-size", fdt_val32); |
---|
134 | 128 | if (status) |
---|
135 | 129 | goto fdt_set_fail; |
---|
136 | 130 | |
---|
137 | | - status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size", |
---|
138 | | - &fdt_val32, sizeof(fdt_val32)); |
---|
| 131 | + status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-desc-size", fdt_val32); |
---|
139 | 132 | if (status) |
---|
140 | 133 | goto fdt_set_fail; |
---|
141 | 134 | |
---|
142 | | - status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver", |
---|
143 | | - &fdt_val32, sizeof(fdt_val32)); |
---|
| 135 | + status = fdt_setprop_var(fdt, node, "linux,uefi-mmap-desc-ver", fdt_val32); |
---|
144 | 136 | if (status) |
---|
145 | 137 | goto fdt_set_fail; |
---|
146 | 138 | |
---|
147 | | - if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { |
---|
| 139 | + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && !efi_nokaslr) { |
---|
148 | 140 | efi_status_t efi_status; |
---|
149 | 141 | |
---|
150 | | - efi_status = efi_get_random_bytes(sys_table, sizeof(fdt_val64), |
---|
| 142 | + efi_status = efi_get_random_bytes(sizeof(fdt_val64), |
---|
151 | 143 | (u8 *)&fdt_val64); |
---|
152 | 144 | if (efi_status == EFI_SUCCESS) { |
---|
153 | | - status = fdt_setprop(fdt, node, "kaslr-seed", |
---|
154 | | - &fdt_val64, sizeof(fdt_val64)); |
---|
| 145 | + status = fdt_setprop_var(fdt, node, "kaslr-seed", fdt_val64); |
---|
155 | 146 | if (status) |
---|
156 | 147 | goto fdt_set_fail; |
---|
157 | | - } else if (efi_status != EFI_NOT_FOUND) { |
---|
158 | | - return efi_status; |
---|
159 | 148 | } |
---|
160 | 149 | } |
---|
161 | 150 | |
---|
162 | | - /* shrink the FDT back to its minimum size */ |
---|
| 151 | + /* Shrink the FDT back to its minimum size: */ |
---|
163 | 152 | fdt_pack(fdt); |
---|
164 | 153 | |
---|
165 | 154 | return EFI_SUCCESS; |
---|
.. | .. |
---|
182 | 171 | return EFI_LOAD_ERROR; |
---|
183 | 172 | |
---|
184 | 173 | fdt_val64 = cpu_to_fdt64((unsigned long)*map->map); |
---|
185 | | - err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-start", |
---|
186 | | - &fdt_val64, sizeof(fdt_val64)); |
---|
| 174 | + |
---|
| 175 | + err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-start", fdt_val64); |
---|
187 | 176 | if (err) |
---|
188 | 177 | return EFI_LOAD_ERROR; |
---|
189 | 178 | |
---|
190 | 179 | fdt_val32 = cpu_to_fdt32(*map->map_size); |
---|
191 | | - err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-size", |
---|
192 | | - &fdt_val32, sizeof(fdt_val32)); |
---|
| 180 | + |
---|
| 181 | + err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-size", fdt_val32); |
---|
193 | 182 | if (err) |
---|
194 | 183 | return EFI_LOAD_ERROR; |
---|
195 | 184 | |
---|
196 | 185 | fdt_val32 = cpu_to_fdt32(*map->desc_size); |
---|
197 | | - err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-size", |
---|
198 | | - &fdt_val32, sizeof(fdt_val32)); |
---|
| 186 | + |
---|
| 187 | + err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-desc-size", fdt_val32); |
---|
199 | 188 | if (err) |
---|
200 | 189 | return EFI_LOAD_ERROR; |
---|
201 | 190 | |
---|
202 | 191 | fdt_val32 = cpu_to_fdt32(*map->desc_ver); |
---|
203 | | - err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-ver", |
---|
204 | | - &fdt_val32, sizeof(fdt_val32)); |
---|
| 192 | + |
---|
| 193 | + err = fdt_setprop_inplace_var(fdt, node, "linux,uefi-mmap-desc-ver", fdt_val32); |
---|
205 | 194 | if (err) |
---|
206 | 195 | return EFI_LOAD_ERROR; |
---|
207 | 196 | |
---|
208 | 197 | return EFI_SUCCESS; |
---|
209 | 198 | } |
---|
210 | 199 | |
---|
211 | | -#ifndef EFI_FDT_ALIGN |
---|
212 | | -#define EFI_FDT_ALIGN EFI_PAGE_SIZE |
---|
213 | | -#endif |
---|
214 | | - |
---|
215 | 200 | struct exit_boot_struct { |
---|
216 | | - efi_memory_desc_t *runtime_map; |
---|
217 | | - int *runtime_entry_count; |
---|
218 | | - void *new_fdt_addr; |
---|
| 201 | + efi_memory_desc_t *runtime_map; |
---|
| 202 | + int *runtime_entry_count; |
---|
| 203 | + void *new_fdt_addr; |
---|
219 | 204 | }; |
---|
220 | 205 | |
---|
221 | | -static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg, |
---|
222 | | - struct efi_boot_memmap *map, |
---|
| 206 | +static efi_status_t exit_boot_func(struct efi_boot_memmap *map, |
---|
223 | 207 | void *priv) |
---|
224 | 208 | { |
---|
225 | 209 | struct exit_boot_struct *p = priv; |
---|
.. | .. |
---|
235 | 219 | } |
---|
236 | 220 | |
---|
237 | 221 | #ifndef MAX_FDT_SIZE |
---|
238 | | -#define MAX_FDT_SIZE SZ_2M |
---|
| 222 | +# define MAX_FDT_SIZE SZ_2M |
---|
239 | 223 | #endif |
---|
240 | 224 | |
---|
241 | 225 | /* |
---|
.. | .. |
---|
252 | 236 | * with the final memory map in it. |
---|
253 | 237 | */ |
---|
254 | 238 | |
---|
255 | | -efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, |
---|
256 | | - void *handle, |
---|
| 239 | +efi_status_t allocate_new_fdt_and_exit_boot(void *handle, |
---|
257 | 240 | unsigned long *new_fdt_addr, |
---|
258 | 241 | unsigned long max_addr, |
---|
259 | 242 | u64 initrd_addr, u64 initrd_size, |
---|
.. | .. |
---|
266 | 249 | unsigned long mmap_key; |
---|
267 | 250 | efi_memory_desc_t *memory_map, *runtime_map; |
---|
268 | 251 | efi_status_t status; |
---|
269 | | - int runtime_entry_count = 0; |
---|
| 252 | + int runtime_entry_count; |
---|
270 | 253 | struct efi_boot_memmap map; |
---|
271 | 254 | struct exit_boot_struct priv; |
---|
272 | 255 | |
---|
273 | | - map.map = &runtime_map; |
---|
274 | | - map.map_size = &map_size; |
---|
275 | | - map.desc_size = &desc_size; |
---|
276 | | - map.desc_ver = &desc_ver; |
---|
277 | | - map.key_ptr = &mmap_key; |
---|
278 | | - map.buff_size = &buff_size; |
---|
| 256 | + map.map = &runtime_map; |
---|
| 257 | + map.map_size = &map_size; |
---|
| 258 | + map.desc_size = &desc_size; |
---|
| 259 | + map.desc_ver = &desc_ver; |
---|
| 260 | + map.key_ptr = &mmap_key; |
---|
| 261 | + map.buff_size = &buff_size; |
---|
279 | 262 | |
---|
280 | 263 | /* |
---|
281 | 264 | * Get a copy of the current memory map that we will use to prepare |
---|
.. | .. |
---|
283 | 266 | * subsequent allocations adding entries, since they could not affect |
---|
284 | 267 | * the number of EFI_MEMORY_RUNTIME regions. |
---|
285 | 268 | */ |
---|
286 | | - status = efi_get_memory_map(sys_table, &map); |
---|
| 269 | + status = efi_get_memory_map(&map); |
---|
287 | 270 | if (status != EFI_SUCCESS) { |
---|
288 | | - pr_efi_err(sys_table, "Unable to retrieve UEFI memory map.\n"); |
---|
| 271 | + efi_err("Unable to retrieve UEFI memory map.\n"); |
---|
289 | 272 | return status; |
---|
290 | 273 | } |
---|
291 | 274 | |
---|
292 | | - pr_efi(sys_table, |
---|
293 | | - "Exiting boot services and installing virtual address map...\n"); |
---|
| 275 | + efi_info("Exiting boot services and installing virtual address map...\n"); |
---|
294 | 276 | |
---|
295 | 277 | map.map = &memory_map; |
---|
296 | | - status = efi_high_alloc(sys_table, MAX_FDT_SIZE, EFI_FDT_ALIGN, |
---|
297 | | - new_fdt_addr, max_addr); |
---|
| 278 | + status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, max_addr); |
---|
298 | 279 | if (status != EFI_SUCCESS) { |
---|
299 | | - pr_efi_err(sys_table, |
---|
300 | | - "Unable to allocate memory for new device tree.\n"); |
---|
| 280 | + efi_err("Unable to allocate memory for new device tree.\n"); |
---|
301 | 281 | goto fail; |
---|
302 | 282 | } |
---|
303 | 283 | |
---|
304 | | - /* |
---|
305 | | - * Now that we have done our final memory allocation (and free) |
---|
306 | | - * we can get the memory map key needed for exit_boot_services(). |
---|
307 | | - */ |
---|
308 | | - status = efi_get_memory_map(sys_table, &map); |
---|
309 | | - if (status != EFI_SUCCESS) |
---|
310 | | - goto fail_free_new_fdt; |
---|
311 | | - |
---|
312 | | - status = update_fdt(sys_table, (void *)fdt_addr, fdt_size, |
---|
| 284 | + status = update_fdt((void *)fdt_addr, fdt_size, |
---|
313 | 285 | (void *)*new_fdt_addr, MAX_FDT_SIZE, cmdline_ptr, |
---|
314 | 286 | initrd_addr, initrd_size); |
---|
315 | 287 | |
---|
316 | 288 | if (status != EFI_SUCCESS) { |
---|
317 | | - pr_efi_err(sys_table, "Unable to construct new device tree.\n"); |
---|
| 289 | + efi_err("Unable to construct new device tree.\n"); |
---|
318 | 290 | goto fail_free_new_fdt; |
---|
319 | 291 | } |
---|
320 | 292 | |
---|
321 | | - priv.runtime_map = runtime_map; |
---|
322 | | - priv.runtime_entry_count = &runtime_entry_count; |
---|
323 | | - priv.new_fdt_addr = (void *)*new_fdt_addr; |
---|
324 | | - status = efi_exit_boot_services(sys_table, handle, &map, &priv, |
---|
325 | | - exit_boot_func); |
---|
| 293 | + runtime_entry_count = 0; |
---|
| 294 | + priv.runtime_map = runtime_map; |
---|
| 295 | + priv.runtime_entry_count = &runtime_entry_count; |
---|
| 296 | + priv.new_fdt_addr = (void *)*new_fdt_addr; |
---|
| 297 | + |
---|
| 298 | + status = efi_exit_boot_services(handle, &map, &priv, exit_boot_func); |
---|
326 | 299 | |
---|
327 | 300 | if (status == EFI_SUCCESS) { |
---|
328 | 301 | efi_set_virtual_address_map_t *svam; |
---|
329 | 302 | |
---|
330 | | - if (novamap()) |
---|
| 303 | + if (efi_novamap) |
---|
331 | 304 | return EFI_SUCCESS; |
---|
332 | 305 | |
---|
333 | 306 | /* Install the new virtual address map */ |
---|
334 | | - svam = sys_table->runtime->set_virtual_address_map; |
---|
| 307 | + svam = efi_system_table->runtime->set_virtual_address_map; |
---|
335 | 308 | status = svam(runtime_entry_count * desc_size, desc_size, |
---|
336 | 309 | desc_ver, runtime_map); |
---|
337 | 310 | |
---|
.. | .. |
---|
359 | 332 | return EFI_SUCCESS; |
---|
360 | 333 | } |
---|
361 | 334 | |
---|
362 | | - pr_efi_err(sys_table, "Exit boot services failed.\n"); |
---|
| 335 | + efi_err("Exit boot services failed.\n"); |
---|
363 | 336 | |
---|
364 | 337 | fail_free_new_fdt: |
---|
365 | | - efi_free(sys_table, MAX_FDT_SIZE, *new_fdt_addr); |
---|
| 338 | + efi_free(MAX_FDT_SIZE, *new_fdt_addr); |
---|
366 | 339 | |
---|
367 | 340 | fail: |
---|
368 | | - sys_table->boottime->free_pool(runtime_map); |
---|
| 341 | + efi_system_table->boottime->free_pool(runtime_map); |
---|
| 342 | + |
---|
369 | 343 | return EFI_LOAD_ERROR; |
---|
370 | 344 | } |
---|
371 | 345 | |
---|
372 | | -void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size) |
---|
| 346 | +void *get_fdt(unsigned long *fdt_size) |
---|
373 | 347 | { |
---|
374 | | - efi_guid_t fdt_guid = DEVICE_TREE_GUID; |
---|
375 | | - efi_config_table_t *tables; |
---|
376 | 348 | void *fdt; |
---|
377 | | - int i; |
---|
378 | 349 | |
---|
379 | | - tables = (efi_config_table_t *) sys_table->tables; |
---|
380 | | - fdt = NULL; |
---|
| 350 | + fdt = get_efi_config_table(DEVICE_TREE_GUID); |
---|
381 | 351 | |
---|
382 | | - for (i = 0; i < sys_table->nr_tables; i++) |
---|
383 | | - if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) { |
---|
384 | | - fdt = (void *) tables[i].table; |
---|
385 | | - if (fdt_check_header(fdt) != 0) { |
---|
386 | | - pr_efi_err(sys_table, "Invalid header detected on UEFI supplied FDT, ignoring ...\n"); |
---|
387 | | - return NULL; |
---|
388 | | - } |
---|
389 | | - *fdt_size = fdt_totalsize(fdt); |
---|
390 | | - break; |
---|
391 | | - } |
---|
| 352 | + if (!fdt) |
---|
| 353 | + return NULL; |
---|
392 | 354 | |
---|
| 355 | + if (fdt_check_header(fdt) != 0) { |
---|
| 356 | + efi_err("Invalid header detected on UEFI supplied FDT, ignoring ...\n"); |
---|
| 357 | + return NULL; |
---|
| 358 | + } |
---|
| 359 | + *fdt_size = fdt_totalsize(fdt); |
---|
393 | 360 | return fdt; |
---|
394 | 361 | } |
---|