blob: 521a541d02ad0bb5f818430adf09d85a53248c64 [file] [log] [blame]
Tom Gundersena9499fa2013-02-08 15:37:06 +00001/*
2 * efi.c - EFI subsystem
3 *
4 * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
5 * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com>
6 * Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
7 *
8 * This code registers /sys/firmware/efi{,/efivars} when EFI is supported,
9 * allowing the efivarfs to be mounted or the efivars module to be loaded.
10 * The existance of /sys/firmware/efi may also be used by userspace to
11 * determine that the system supports EFI.
12 *
13 * This file is released under the GPLv2.
14 */
15
Leif Lindholm272686b2013-09-05 11:34:54 +010016#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
Tom Gundersena9499fa2013-02-08 15:37:06 +000018#include <linux/kobject.h>
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/device.h>
22#include <linux/efi.h>
Mark Salter0302f712013-12-30 12:12:12 -050023#include <linux/of.h>
24#include <linux/of_fdt.h>
Leif Lindholm272686b2013-09-05 11:34:54 +010025#include <linux/io.h>
Ard Biesheuvel63625982016-11-12 21:32:31 +000026#include <linux/kexec.h>
Lee, Chun-Yi28d54022014-07-09 18:39:29 +080027#include <linux/platform_device.h>
Ard Biesheuvel63625982016-11-12 21:32:31 +000028#include <linux/random.h>
29#include <linux/reboot.h>
Octavian Purdila475fb4e2016-07-08 19:13:12 +030030#include <linux/slab.h>
31#include <linux/acpi.h>
32#include <linux/ucs2_string.h>
Matt Fleming816e7612016-02-29 21:22:52 +000033#include <linux/memblock.h>
Leif Lindholm272686b2013-09-05 11:34:54 +010034
Ard Biesheuvel0f7f2f02016-01-12 14:22:46 +010035#include <asm/early_ioremap.h>
Ard Biesheuvelf7d92482015-11-30 13:28:19 +010036
Leif Lindholm272686b2013-09-05 11:34:54 +010037struct efi __read_mostly efi = {
Ard Biesheuvelbf924862015-09-09 10:08:15 +020038 .mps = EFI_INVALID_TABLE_ADDR,
39 .acpi = EFI_INVALID_TABLE_ADDR,
40 .acpi20 = EFI_INVALID_TABLE_ADDR,
41 .smbios = EFI_INVALID_TABLE_ADDR,
42 .smbios3 = EFI_INVALID_TABLE_ADDR,
43 .sal_systab = EFI_INVALID_TABLE_ADDR,
44 .boot_info = EFI_INVALID_TABLE_ADDR,
45 .hcdp = EFI_INVALID_TABLE_ADDR,
46 .uga = EFI_INVALID_TABLE_ADDR,
47 .uv_systab = EFI_INVALID_TABLE_ADDR,
48 .fw_vendor = EFI_INVALID_TABLE_ADDR,
49 .runtime = EFI_INVALID_TABLE_ADDR,
50 .config_table = EFI_INVALID_TABLE_ADDR,
51 .esrt = EFI_INVALID_TABLE_ADDR,
52 .properties_table = EFI_INVALID_TABLE_ADDR,
Ard Biesheuvela604af02016-04-25 21:06:44 +010053 .mem_attr_table = EFI_INVALID_TABLE_ADDR,
Ard Biesheuvel63625982016-11-12 21:32:31 +000054 .rng_seed = EFI_INVALID_TABLE_ADDR,
Ard Biesheuvel71e09402018-09-21 09:32:44 -070055 .tpm_log = EFI_INVALID_TABLE_ADDR,
56 .mem_reserve = EFI_INVALID_TABLE_ADDR,
Leif Lindholm272686b2013-09-05 11:34:54 +010057};
58EXPORT_SYMBOL(efi);
Tom Gundersena9499fa2013-02-08 15:37:06 +000059
Tom Lendackya19d66c2017-07-17 16:10:13 -050060static unsigned long *efi_tables[] = {
61 &efi.mps,
62 &efi.acpi,
63 &efi.acpi20,
64 &efi.smbios,
65 &efi.smbios3,
66 &efi.sal_systab,
67 &efi.boot_info,
68 &efi.hcdp,
69 &efi.uga,
70 &efi.uv_systab,
71 &efi.fw_vendor,
72 &efi.runtime,
73 &efi.config_table,
74 &efi.esrt,
75 &efi.properties_table,
76 &efi.mem_attr_table,
77};
78
Sai Praneeth7e904a92018-03-12 08:44:56 +000079struct mm_struct efi_mm = {
80 .mm_rb = RB_ROOT,
81 .mm_users = ATOMIC_INIT(2),
82 .mm_count = ATOMIC_INIT(1),
83 .mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem),
84 .page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
85 .mmlist = LIST_HEAD_INIT(efi_mm.mmlist),
Rik van Rielc1a2f7f2018-07-16 15:03:31 -040086 .cpu_bitmap = { [BITS_TO_LONGS(NR_CPUS)] = 0},
Sai Praneeth7e904a92018-03-12 08:44:56 +000087};
88
Sai Praneeth3eb420e2018-07-11 11:40:35 +020089struct workqueue_struct *efi_rts_wq;
90
Dave Youngb2e0a542014-08-14 17:15:26 +080091static bool disable_runtime;
92static int __init setup_noefi(char *arg)
93{
94 disable_runtime = true;
95 return 0;
96}
97early_param("noefi", setup_noefi);
98
99bool efi_runtime_disabled(void)
100{
101 return disable_runtime;
102}
103
Dave Young5ae36832014-08-14 17:15:28 +0800104static int __init parse_efi_cmdline(char *str)
105{
Ricardo Neri9115c752015-07-15 19:36:03 -0700106 if (!str) {
107 pr_warn("need at least one option\n");
108 return -EINVAL;
109 }
110
Leif Lindholm12dd00e2015-08-26 14:24:56 +0100111 if (parse_option_str(str, "debug"))
112 set_bit(EFI_DBG, &efi.flags);
113
Dave Young5ae36832014-08-14 17:15:28 +0800114 if (parse_option_str(str, "noruntime"))
115 disable_runtime = true;
116
117 return 0;
118}
119early_param("efi", parse_efi_cmdline);
120
Peter Jones0bb54902015-04-28 18:44:31 -0400121struct kobject *efi_kobj;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000122
123/*
124 * Let's not leave out systab information that snuck into
125 * the efivars driver
Dave Young0b02e442017-12-06 09:50:10 +0000126 * Note, do not add more fields in systab sysfs file as it breaks sysfs
127 * one value per file rule!
Tom Gundersena9499fa2013-02-08 15:37:06 +0000128 */
129static ssize_t systab_show(struct kobject *kobj,
130 struct kobj_attribute *attr, char *buf)
131{
132 char *str = buf;
133
134 if (!kobj || !buf)
135 return -EINVAL;
136
137 if (efi.mps != EFI_INVALID_TABLE_ADDR)
138 str += sprintf(str, "MPS=0x%lx\n", efi.mps);
139 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
140 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
141 if (efi.acpi != EFI_INVALID_TABLE_ADDR)
142 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
Jean Delvareb119fe02015-04-30 15:23:05 +0200143 /*
144 * If both SMBIOS and SMBIOS3 entry points are implemented, the
145 * SMBIOS3 entry point shall be preferred, so we list it first to
146 * let applications stop parsing after the first match.
147 */
Ard Biesheuvele1ccbbc2014-10-14 16:34:47 +0200148 if (efi.smbios3 != EFI_INVALID_TABLE_ADDR)
149 str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3);
Jean Delvareb119fe02015-04-30 15:23:05 +0200150 if (efi.smbios != EFI_INVALID_TABLE_ADDR)
151 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
Tom Gundersena9499fa2013-02-08 15:37:06 +0000152 if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
153 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
154 if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
155 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
156 if (efi.uga != EFI_INVALID_TABLE_ADDR)
157 str += sprintf(str, "UGA=0x%lx\n", efi.uga);
158
159 return str - buf;
160}
161
Greg Kroah-Hartmanaf97a772017-12-06 09:50:08 +0000162static struct kobj_attribute efi_attr_systab = __ATTR_RO_MODE(systab, 0400);
Tom Gundersena9499fa2013-02-08 15:37:06 +0000163
Dave Younga0998eb2013-12-20 18:02:17 +0800164#define EFI_FIELD(var) efi.var
165
166#define EFI_ATTR_SHOW(name) \
167static ssize_t name##_show(struct kobject *kobj, \
168 struct kobj_attribute *attr, char *buf) \
169{ \
170 return sprintf(buf, "0x%lx\n", EFI_FIELD(name)); \
171}
172
173EFI_ATTR_SHOW(fw_vendor);
174EFI_ATTR_SHOW(runtime);
175EFI_ATTR_SHOW(config_table);
176
Steve McIntyre2859dff2015-01-09 15:29:53 +0000177static ssize_t fw_platform_size_show(struct kobject *kobj,
178 struct kobj_attribute *attr, char *buf)
179{
180 return sprintf(buf, "%d\n", efi_enabled(EFI_64BIT) ? 64 : 32);
181}
182
Dave Younga0998eb2013-12-20 18:02:17 +0800183static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor);
184static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
185static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);
Steve McIntyre2859dff2015-01-09 15:29:53 +0000186static struct kobj_attribute efi_attr_fw_platform_size =
187 __ATTR_RO(fw_platform_size);
Dave Younga0998eb2013-12-20 18:02:17 +0800188
Tom Gundersena9499fa2013-02-08 15:37:06 +0000189static struct attribute *efi_subsys_attrs[] = {
190 &efi_attr_systab.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800191 &efi_attr_fw_vendor.attr,
192 &efi_attr_runtime.attr,
193 &efi_attr_config_table.attr,
Steve McIntyre2859dff2015-01-09 15:29:53 +0000194 &efi_attr_fw_platform_size.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800195 NULL,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000196};
197
Dave Younga0998eb2013-12-20 18:02:17 +0800198static umode_t efi_attr_is_visible(struct kobject *kobj,
199 struct attribute *attr, int n)
200{
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200201 if (attr == &efi_attr_fw_vendor.attr) {
202 if (efi_enabled(EFI_PARAVIRT) ||
203 efi.fw_vendor == EFI_INVALID_TABLE_ADDR)
204 return 0;
205 } else if (attr == &efi_attr_runtime.attr) {
206 if (efi.runtime == EFI_INVALID_TABLE_ADDR)
207 return 0;
208 } else if (attr == &efi_attr_config_table.attr) {
209 if (efi.config_table == EFI_INVALID_TABLE_ADDR)
210 return 0;
211 }
Dave Younga0998eb2013-12-20 18:02:17 +0800212
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200213 return attr->mode;
Dave Younga0998eb2013-12-20 18:02:17 +0800214}
215
Arvind Yadav3ad6bd72017-08-18 20:49:46 +0100216static const struct attribute_group efi_subsys_attr_group = {
Tom Gundersena9499fa2013-02-08 15:37:06 +0000217 .attrs = efi_subsys_attrs,
Dave Younga0998eb2013-12-20 18:02:17 +0800218 .is_visible = efi_attr_is_visible,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000219};
220
221static struct efivars generic_efivars;
222static struct efivar_operations generic_ops;
223
224static int generic_ops_register(void)
225{
226 generic_ops.get_variable = efi.get_variable;
227 generic_ops.set_variable = efi.set_variable;
Ard Biesheuvel9c6672a2016-02-01 22:06:55 +0000228 generic_ops.set_variable_nonblocking = efi.set_variable_nonblocking;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000229 generic_ops.get_next_variable = efi.get_next_variable;
Matt Fleminga614e192013-04-30 11:30:24 +0100230 generic_ops.query_variable_store = efi_query_variable_store;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000231
232 return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
233}
234
235static void generic_ops_unregister(void)
236{
237 efivars_unregister(&generic_efivars);
238}
239
Octavian Purdila475fb4e2016-07-08 19:13:12 +0300240#if IS_ENABLED(CONFIG_ACPI)
241#define EFIVAR_SSDT_NAME_MAX 16
242static char efivar_ssdt[EFIVAR_SSDT_NAME_MAX] __initdata;
243static int __init efivar_ssdt_setup(char *str)
244{
245 if (strlen(str) < sizeof(efivar_ssdt))
246 memcpy(efivar_ssdt, str, strlen(str));
247 else
248 pr_warn("efivar_ssdt: name too long: %s\n", str);
249 return 0;
250}
251__setup("efivar_ssdt=", efivar_ssdt_setup);
252
253static __init int efivar_ssdt_iter(efi_char16_t *name, efi_guid_t vendor,
254 unsigned long name_size, void *data)
255{
256 struct efivar_entry *entry;
257 struct list_head *list = data;
258 char utf8_name[EFIVAR_SSDT_NAME_MAX];
259 int limit = min_t(unsigned long, EFIVAR_SSDT_NAME_MAX, name_size);
260
261 ucs2_as_utf8(utf8_name, name, limit - 1);
262 if (strncmp(utf8_name, efivar_ssdt, limit) != 0)
263 return 0;
264
265 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
266 if (!entry)
267 return 0;
268
269 memcpy(entry->var.VariableName, name, name_size);
270 memcpy(&entry->var.VendorGuid, &vendor, sizeof(efi_guid_t));
271
272 efivar_entry_add(entry, list);
273
274 return 0;
275}
276
277static __init int efivar_ssdt_load(void)
278{
279 LIST_HEAD(entries);
280 struct efivar_entry *entry, *aux;
281 unsigned long size;
282 void *data;
283 int ret;
284
285 ret = efivar_init(efivar_ssdt_iter, &entries, true, &entries);
286
287 list_for_each_entry_safe(entry, aux, &entries, list) {
288 pr_info("loading SSDT from variable %s-%pUl\n", efivar_ssdt,
289 &entry->var.VendorGuid);
290
291 list_del(&entry->list);
292
293 ret = efivar_entry_size(entry, &size);
294 if (ret) {
295 pr_err("failed to get var size\n");
296 goto free_entry;
297 }
298
299 data = kmalloc(size, GFP_KERNEL);
Dan Carpentera75dcb52016-10-18 15:33:18 +0100300 if (!data) {
301 ret = -ENOMEM;
Octavian Purdila475fb4e2016-07-08 19:13:12 +0300302 goto free_entry;
Dan Carpentera75dcb52016-10-18 15:33:18 +0100303 }
Octavian Purdila475fb4e2016-07-08 19:13:12 +0300304
305 ret = efivar_entry_get(entry, NULL, &size, data);
306 if (ret) {
307 pr_err("failed to get var data\n");
308 goto free_data;
309 }
310
311 ret = acpi_load_table(data);
312 if (ret) {
313 pr_err("failed to load table: %d\n", ret);
314 goto free_data;
315 }
316
317 goto free_entry;
318
319free_data:
320 kfree(data);
321
322free_entry:
323 kfree(entry);
324 }
325
326 return ret;
327}
328#else
329static inline int efivar_ssdt_load(void) { return 0; }
330#endif
331
Tom Gundersena9499fa2013-02-08 15:37:06 +0000332/*
333 * We register the efi subsystem with the firmware subsystem and the
334 * efivars subsystem with the efi subsystem, if the system was booted with
335 * EFI.
336 */
337static int __init efisubsys_init(void)
338{
339 int error;
340
341 if (!efi_enabled(EFI_BOOT))
342 return 0;
343
Sai Praneeth3eb420e2018-07-11 11:40:35 +0200344 /*
345 * Since we process only one efi_runtime_service() at a time, an
346 * ordered workqueue (which creates only one execution context)
347 * should suffice all our needs.
348 */
349 efi_rts_wq = alloc_ordered_workqueue("efi_rts_wq", 0);
350 if (!efi_rts_wq) {
351 pr_err("Creating efi_rts_wq failed, EFI runtime services disabled.\n");
352 clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
353 return 0;
354 }
355
Tom Gundersena9499fa2013-02-08 15:37:06 +0000356 /* We register the efi directory at /sys/firmware/efi */
357 efi_kobj = kobject_create_and_add("efi", firmware_kobj);
358 if (!efi_kobj) {
359 pr_err("efi: Firmware registration failed.\n");
360 return -ENOMEM;
361 }
362
363 error = generic_ops_register();
364 if (error)
365 goto err_put;
366
Octavian Purdila475fb4e2016-07-08 19:13:12 +0300367 if (efi_enabled(EFI_RUNTIME_SERVICES))
368 efivar_ssdt_load();
369
Tom Gundersena9499fa2013-02-08 15:37:06 +0000370 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
371 if (error) {
372 pr_err("efi: Sysfs attribute export failed with error %d.\n",
373 error);
374 goto err_unregister;
375 }
376
Dave Young926172d2013-12-20 18:02:18 +0800377 error = efi_runtime_map_init(efi_kobj);
378 if (error)
379 goto err_remove_group;
380
Tom Gundersena9499fa2013-02-08 15:37:06 +0000381 /* and the standard mountpoint for efivarfs */
Eric W. Biedermanf9bb4882015-05-13 17:35:41 -0500382 error = sysfs_create_mount_point(efi_kobj, "efivars");
383 if (error) {
Tom Gundersena9499fa2013-02-08 15:37:06 +0000384 pr_err("efivars: Subsystem registration failed.\n");
Tom Gundersena9499fa2013-02-08 15:37:06 +0000385 goto err_remove_group;
386 }
387
388 return 0;
389
390err_remove_group:
391 sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
392err_unregister:
393 generic_ops_unregister();
394err_put:
395 kobject_put(efi_kobj);
396 return error;
397}
398
399subsys_initcall(efisubsys_init);
Leif Lindholm272686b2013-09-05 11:34:54 +0100400
Peter Jones0bb54902015-04-28 18:44:31 -0400401/*
402 * Find the efi memory descriptor for a given physical address. Given a
Matt Flemingdca0f972016-02-27 15:52:50 +0000403 * physical address, determine if it exists within an EFI Memory Map entry,
Peter Jones0bb54902015-04-28 18:44:31 -0400404 * and if so, populate the supplied memory descriptor with the appropriate
405 * data.
406 */
Ard Biesheuvel7e1550b2018-07-11 11:40:39 +0200407int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
Peter Jones0bb54902015-04-28 18:44:31 -0400408{
Matt Flemingdca0f972016-02-27 15:52:50 +0000409 efi_memory_desc_t *md;
Peter Jones0bb54902015-04-28 18:44:31 -0400410
411 if (!efi_enabled(EFI_MEMMAP)) {
412 pr_err_once("EFI_MEMMAP is not enabled.\n");
413 return -EINVAL;
414 }
415
Peter Jones0bb54902015-04-28 18:44:31 -0400416 if (!out_md) {
417 pr_err_once("out_md is null.\n");
418 return -EINVAL;
419 }
Peter Jones0bb54902015-04-28 18:44:31 -0400420
Matt Flemingdca0f972016-02-27 15:52:50 +0000421 for_each_efi_memory_desc(md) {
Peter Jones0bb54902015-04-28 18:44:31 -0400422 u64 size;
423 u64 end;
424
Peter Jones0bb54902015-04-28 18:44:31 -0400425 size = md->num_pages << EFI_PAGE_SHIFT;
426 end = md->phys_addr + size;
427 if (phys_addr >= md->phys_addr && phys_addr < end) {
428 memcpy(out_md, md, sizeof(*out_md));
Peter Jones0bb54902015-04-28 18:44:31 -0400429 return 0;
430 }
Peter Jones0bb54902015-04-28 18:44:31 -0400431 }
Peter Jones0bb54902015-04-28 18:44:31 -0400432 return -ENOENT;
433}
434
435/*
436 * Calculate the highest address of an efi memory descriptor.
437 */
438u64 __init efi_mem_desc_end(efi_memory_desc_t *md)
439{
440 u64 size = md->num_pages << EFI_PAGE_SHIFT;
441 u64 end = md->phys_addr + size;
442 return end;
443}
Leif Lindholm272686b2013-09-05 11:34:54 +0100444
Matt Fleming816e7612016-02-29 21:22:52 +0000445void __init __weak efi_arch_mem_reserve(phys_addr_t addr, u64 size) {}
446
447/**
448 * efi_mem_reserve - Reserve an EFI memory region
449 * @addr: Physical address to reserve
450 * @size: Size of reservation
451 *
452 * Mark a region as reserved from general kernel allocation and
453 * prevent it being released by efi_free_boot_services().
454 *
455 * This function should be called drivers once they've parsed EFI
456 * configuration tables to figure out where their data lives, e.g.
457 * efi_esrt_init().
458 */
459void __init efi_mem_reserve(phys_addr_t addr, u64 size)
460{
461 if (!memblock_is_region_reserved(addr, size))
462 memblock_reserve(addr, size);
463
464 /*
465 * Some architectures (x86) reserve all boot services ranges
466 * until efi_free_boot_services() because of buggy firmware
467 * implementations. This means the above memblock_reserve() is
468 * superfluous on x86 and instead what it needs to do is
469 * ensure the @start, @size is not freed.
470 */
471 efi_arch_mem_reserve(addr, size);
472}
473
Leif Lindholm272686b2013-09-05 11:34:54 +0100474static __initdata efi_config_table_type_t common_tables[] = {
475 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
476 {ACPI_TABLE_GUID, "ACPI", &efi.acpi},
477 {HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
478 {MPS_TABLE_GUID, "MPS", &efi.mps},
479 {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
480 {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
Ard Biesheuvele1ccbbc2014-10-14 16:34:47 +0200481 {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
Leif Lindholm272686b2013-09-05 11:34:54 +0100482 {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
Peter Jones0bb54902015-04-28 18:44:31 -0400483 {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
Ard Biesheuvelbf924862015-09-09 10:08:15 +0200484 {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
Ard Biesheuvela604af02016-04-25 21:06:44 +0100485 {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
Ard Biesheuvel63625982016-11-12 21:32:31 +0000486 {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
Thiebaud Weksteen33b6d032017-09-20 10:13:39 +0200487 {LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log},
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700488 {LINUX_EFI_MEMRESERVE_TABLE_GUID, "MEMRESERVE", &efi.mem_reserve},
Daeseok Youn69e60842014-02-13 17:16:36 +0900489 {NULL_GUID, NULL, NULL},
Leif Lindholm272686b2013-09-05 11:34:54 +0100490};
491
492static __init int match_config_table(efi_guid_t *guid,
493 unsigned long table,
494 efi_config_table_type_t *table_types)
495{
Leif Lindholm272686b2013-09-05 11:34:54 +0100496 int i;
497
498 if (table_types) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100499 for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100500 if (!efi_guidcmp(*guid, table_types[i].guid)) {
501 *(table_types[i].ptr) = table;
Ard Biesheuvel801820b2016-04-25 21:06:53 +0100502 if (table_types[i].name)
503 pr_cont(" %s=0x%lx ",
504 table_types[i].name, table);
Leif Lindholm272686b2013-09-05 11:34:54 +0100505 return 1;
506 }
507 }
508 }
509
510 return 0;
511}
512
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200513int __init efi_config_parse_tables(void *config_tables, int count, int sz,
514 efi_config_table_type_t *arch_tables)
515{
516 void *tablep;
517 int i;
518
519 tablep = config_tables;
520 pr_info("");
521 for (i = 0; i < count; i++) {
522 efi_guid_t guid;
523 unsigned long table;
524
525 if (efi_enabled(EFI_64BIT)) {
526 u64 table64;
527 guid = ((efi_config_table_64_t *)tablep)->guid;
528 table64 = ((efi_config_table_64_t *)tablep)->table;
529 table = table64;
530#ifndef CONFIG_64BIT
531 if (table64 >> 32) {
532 pr_cont("\n");
533 pr_err("Table located above 4GB, disabling EFI.\n");
534 return -EINVAL;
535 }
536#endif
537 } else {
538 guid = ((efi_config_table_32_t *)tablep)->guid;
539 table = ((efi_config_table_32_t *)tablep)->table;
540 }
541
542 if (!match_config_table(&guid, table, common_tables))
543 match_config_table(&guid, table, arch_tables);
544
545 tablep += sz;
546 }
547 pr_cont("\n");
548 set_bit(EFI_CONFIG_TABLES, &efi.flags);
Ard Biesheuvela1041712015-09-23 07:29:34 -0700549
Ard Biesheuvel63625982016-11-12 21:32:31 +0000550 if (efi.rng_seed != EFI_INVALID_TABLE_ADDR) {
551 struct linux_efi_random_seed *seed;
552 u32 size = 0;
553
554 seed = early_memremap(efi.rng_seed, sizeof(*seed));
555 if (seed != NULL) {
556 size = seed->size;
557 early_memunmap(seed, sizeof(*seed));
558 } else {
559 pr_err("Could not map UEFI random seed!\n");
560 }
561 if (size > 0) {
562 seed = early_memremap(efi.rng_seed,
563 sizeof(*seed) + size);
564 if (seed != NULL) {
Ard Biesheuvel5b4e4c32018-03-08 08:00:18 +0000565 pr_notice("seeding entropy pool\n");
Ard Biesheuvel63625982016-11-12 21:32:31 +0000566 add_device_randomness(seed->bits, seed->size);
567 early_memunmap(seed, sizeof(*seed) + size);
568 } else {
569 pr_err("Could not map UEFI random seed!\n");
570 }
571 }
572 }
573
Daniel Kiper457ea3f2017-06-22 12:51:36 +0200574 if (efi_enabled(EFI_MEMMAP))
575 efi_memattr_init();
Sai Praneeth3a6b6c62017-01-31 13:21:35 +0000576
Thiebaud Weksteen33b6d032017-09-20 10:13:39 +0200577 efi_tpm_eventlog_init();
578
Ard Biesheuvela1041712015-09-23 07:29:34 -0700579 /* Parse the EFI Properties table if it exists */
580 if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
581 efi_properties_table_t *tbl;
582
583 tbl = early_memremap(efi.properties_table, sizeof(*tbl));
584 if (tbl == NULL) {
585 pr_err("Could not map Properties table!\n");
586 return -ENOMEM;
587 }
588
589 if (tbl->memory_protection_attribute &
590 EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA)
591 set_bit(EFI_NX_PE_DATA, &efi.flags);
592
593 early_memunmap(tbl, sizeof(*tbl));
594 }
595
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700596 if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) {
597 unsigned long prsv = efi.mem_reserve;
598
599 while (prsv) {
600 struct linux_efi_memreserve *rsv;
Ard Biesheuvel5f0b0ec2018-11-29 18:12:28 +0100601 u8 *p;
602 int i;
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700603
Ard Biesheuvel5f0b0ec2018-11-29 18:12:28 +0100604 /*
605 * Just map a full page: that is what we will get
606 * anyway, and it permits us to map the entire entry
607 * before knowing its size.
608 */
609 p = early_memremap(ALIGN_DOWN(prsv, PAGE_SIZE),
610 PAGE_SIZE);
611 if (p == NULL) {
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700612 pr_err("Could not map UEFI memreserve entry!\n");
613 return -ENOMEM;
614 }
615
Ard Biesheuvel5f0b0ec2018-11-29 18:12:28 +0100616 rsv = (void *)(p + prsv % PAGE_SIZE);
617
618 /* reserve the entry itself */
619 memblock_reserve(prsv, EFI_MEMRESERVE_SIZE(rsv->size));
620
621 for (i = 0; i < atomic_read(&rsv->count); i++) {
622 memblock_reserve(rsv->entry[i].base,
623 rsv->entry[i].size);
624 }
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700625
626 prsv = rsv->next;
Ard Biesheuvel5f0b0ec2018-11-29 18:12:28 +0100627 early_memunmap(p, PAGE_SIZE);
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700628 }
629 }
630
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200631 return 0;
632}
633
Leif Lindholm272686b2013-09-05 11:34:54 +0100634int __init efi_config_init(efi_config_table_type_t *arch_tables)
635{
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200636 void *config_tables;
637 int sz, ret;
Leif Lindholm272686b2013-09-05 11:34:54 +0100638
Rob Bradford88447c52019-05-25 13:25:59 +0200639 if (efi.systab->nr_tables == 0)
640 return 0;
641
Leif Lindholm272686b2013-09-05 11:34:54 +0100642 if (efi_enabled(EFI_64BIT))
643 sz = sizeof(efi_config_table_64_t);
644 else
645 sz = sizeof(efi_config_table_32_t);
646
647 /*
648 * Let's see what config tables the firmware passed to us.
649 */
650 config_tables = early_memremap(efi.systab->tables,
651 efi.systab->nr_tables * sz);
652 if (config_tables == NULL) {
653 pr_err("Could not map Configuration table!\n");
654 return -ENOMEM;
655 }
656
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200657 ret = efi_config_parse_tables(config_tables, efi.systab->nr_tables, sz,
658 arch_tables);
Leif Lindholm272686b2013-09-05 11:34:54 +0100659
Daniel Kiperabc93f82014-06-30 19:52:56 +0200660 early_memunmap(config_tables, efi.systab->nr_tables * sz);
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200661 return ret;
Leif Lindholm272686b2013-09-05 11:34:54 +0100662}
Mark Salter0302f712013-12-30 12:12:12 -0500663
Lee, Chun-Yi28d54022014-07-09 18:39:29 +0800664#ifdef CONFIG_EFI_VARS_MODULE
665static int __init efi_load_efivars(void)
666{
667 struct platform_device *pdev;
668
669 if (!efi_enabled(EFI_RUNTIME_SERVICES))
670 return 0;
671
672 pdev = platform_device_register_simple("efivars", 0, NULL, 0);
Vasyl Gomonovych50342b22018-01-02 18:10:40 +0000673 return PTR_ERR_OR_ZERO(pdev);
Lee, Chun-Yi28d54022014-07-09 18:39:29 +0800674}
675device_initcall(efi_load_efivars);
676#endif
677
Mark Salter0302f712013-12-30 12:12:12 -0500678#ifdef CONFIG_EFI_PARAMS_FROM_FDT
679
680#define UEFI_PARAM(name, prop, field) \
681 { \
682 { name }, \
683 { prop }, \
684 offsetof(struct efi_fdt_params, field), \
685 FIELD_SIZEOF(struct efi_fdt_params, field) \
686 }
687
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800688struct params {
Mark Salter0302f712013-12-30 12:12:12 -0500689 const char name[32];
690 const char propname[32];
691 int offset;
692 int size;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800693};
694
695static __initdata struct params fdt_params[] = {
Mark Salter0302f712013-12-30 12:12:12 -0500696 UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
697 UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
698 UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
699 UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
700 UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
701};
702
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800703static __initdata struct params xen_fdt_params[] = {
704 UEFI_PARAM("System Table", "xen,uefi-system-table", system_table),
705 UEFI_PARAM("MemMap Address", "xen,uefi-mmap-start", mmap),
706 UEFI_PARAM("MemMap Size", "xen,uefi-mmap-size", mmap_size),
707 UEFI_PARAM("MemMap Desc. Size", "xen,uefi-mmap-desc-size", desc_size),
708 UEFI_PARAM("MemMap Desc. Version", "xen,uefi-mmap-desc-ver", desc_ver)
709};
710
711#define EFI_FDT_PARAMS_SIZE ARRAY_SIZE(fdt_params)
712
713static __initdata struct {
714 const char *uname;
715 const char *subnode;
716 struct params *params;
717} dt_params[] = {
718 { "hypervisor", "uefi", xen_fdt_params },
719 { "chosen", NULL, fdt_params },
720};
721
Mark Salter0302f712013-12-30 12:12:12 -0500722struct param_info {
Catalin Marinas29e24352014-07-08 16:54:18 +0100723 int found;
Mark Salter0302f712013-12-30 12:12:12 -0500724 void *params;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800725 const char *missing;
Mark Salter0302f712013-12-30 12:12:12 -0500726};
727
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800728static int __init __find_uefi_params(unsigned long node,
729 struct param_info *info,
730 struct params *params)
Mark Salter0302f712013-12-30 12:12:12 -0500731{
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100732 const void *prop;
733 void *dest;
Mark Salter0302f712013-12-30 12:12:12 -0500734 u64 val;
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100735 int i, len;
Mark Salter0302f712013-12-30 12:12:12 -0500736
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800737 for (i = 0; i < EFI_FDT_PARAMS_SIZE; i++) {
738 prop = of_get_flat_dt_prop(node, params[i].propname, &len);
739 if (!prop) {
740 info->missing = params[i].name;
Mark Salter0302f712013-12-30 12:12:12 -0500741 return 0;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800742 }
743
744 dest = info->params + params[i].offset;
Catalin Marinas29e24352014-07-08 16:54:18 +0100745 info->found++;
Mark Salter0302f712013-12-30 12:12:12 -0500746
747 val = of_read_number(prop, len / sizeof(u32));
748
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800749 if (params[i].size == sizeof(u32))
Mark Salter0302f712013-12-30 12:12:12 -0500750 *(u32 *)dest = val;
751 else
752 *(u64 *)dest = val;
753
Leif Lindholm7968c0e2015-08-26 14:24:58 +0100754 if (efi_enabled(EFI_DBG))
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800755 pr_info(" %s: 0x%0*llx\n", params[i].name,
756 params[i].size * 2, val);
Mark Salter0302f712013-12-30 12:12:12 -0500757 }
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800758
Mark Salter0302f712013-12-30 12:12:12 -0500759 return 1;
760}
761
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800762static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
763 int depth, void *data)
764{
765 struct param_info *info = data;
766 int i;
767
768 for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
769 const char *subnode = dt_params[i].subnode;
770
771 if (depth != 1 || strcmp(uname, dt_params[i].uname) != 0) {
772 info->missing = dt_params[i].params[0].name;
773 continue;
774 }
775
776 if (subnode) {
Andrzej Hajda4af9ed52016-08-30 12:41:37 +0200777 int err = of_get_flat_dt_subnode_by_name(node, subnode);
778
779 if (err < 0)
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800780 return 0;
Andrzej Hajda4af9ed52016-08-30 12:41:37 +0200781
782 node = err;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800783 }
784
785 return __find_uefi_params(node, info, dt_params[i].params);
786 }
787
788 return 0;
789}
790
Leif Lindholm7968c0e2015-08-26 14:24:58 +0100791int __init efi_get_fdt_params(struct efi_fdt_params *params)
Mark Salter0302f712013-12-30 12:12:12 -0500792{
793 struct param_info info;
Catalin Marinas29e24352014-07-08 16:54:18 +0100794 int ret;
795
796 pr_info("Getting EFI parameters from FDT:\n");
Mark Salter0302f712013-12-30 12:12:12 -0500797
Catalin Marinas29e24352014-07-08 16:54:18 +0100798 info.found = 0;
Mark Salter0302f712013-12-30 12:12:12 -0500799 info.params = params;
800
Catalin Marinas29e24352014-07-08 16:54:18 +0100801 ret = of_scan_flat_dt(fdt_find_uefi_params, &info);
802 if (!info.found)
803 pr_info("UEFI not found.\n");
804 else if (!ret)
805 pr_err("Can't find '%s' in device tree!\n",
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800806 info.missing);
Catalin Marinas29e24352014-07-08 16:54:18 +0100807
808 return ret;
Mark Salter0302f712013-12-30 12:12:12 -0500809}
810#endif /* CONFIG_EFI_PARAMS_FROM_FDT */
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200811
812static __initdata char memory_type_name[][20] = {
813 "Reserved",
814 "Loader Code",
815 "Loader Data",
816 "Boot Code",
817 "Boot Data",
818 "Runtime Code",
819 "Runtime Data",
820 "Conventional Memory",
821 "Unusable Memory",
822 "ACPI Reclaim Memory",
823 "ACPI Memory NVS",
824 "Memory Mapped I/O",
825 "MMIO Port Space",
Robert Elliott35575e02016-02-01 22:07:07 +0000826 "PAL Code",
827 "Persistent Memory",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200828};
829
830char * __init efi_md_typeattr_format(char *buf, size_t size,
831 const efi_memory_desc_t *md)
832{
833 char *pos;
834 int type_len;
835 u64 attr;
836
837 pos = buf;
838 if (md->type >= ARRAY_SIZE(memory_type_name))
839 type_len = snprintf(pos, size, "[type=%u", md->type);
840 else
841 type_len = snprintf(pos, size, "[%-*s",
842 (int)(sizeof(memory_type_name[0]) - 1),
843 memory_type_name[md->type]);
844 if (type_len >= size)
845 return buf;
846
847 pos += type_len;
848 size -= type_len;
849
850 attr = md->attribute;
851 if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
Ard Biesheuvel87db73ae2015-08-07 09:36:54 +0100852 EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO |
853 EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP |
Robert Elliottc016ca02016-02-01 22:07:06 +0000854 EFI_MEMORY_NV |
Taku Izumi8be44322015-08-27 02:11:19 +0900855 EFI_MEMORY_RUNTIME | EFI_MEMORY_MORE_RELIABLE))
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200856 snprintf(pos, size, "|attr=0x%016llx]",
857 (unsigned long long)attr);
858 else
Robert Elliottc016ca02016-02-01 22:07:06 +0000859 snprintf(pos, size,
860 "|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200861 attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
Taku Izumi8be44322015-08-27 02:11:19 +0900862 attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "",
Robert Elliottc016ca02016-02-01 22:07:06 +0000863 attr & EFI_MEMORY_NV ? "NV" : "",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200864 attr & EFI_MEMORY_XP ? "XP" : "",
865 attr & EFI_MEMORY_RP ? "RP" : "",
866 attr & EFI_MEMORY_WP ? "WP" : "",
Ard Biesheuvel87db73ae2015-08-07 09:36:54 +0100867 attr & EFI_MEMORY_RO ? "RO" : "",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200868 attr & EFI_MEMORY_UCE ? "UCE" : "",
869 attr & EFI_MEMORY_WB ? "WB" : "",
870 attr & EFI_MEMORY_WT ? "WT" : "",
871 attr & EFI_MEMORY_WC ? "WC" : "",
872 attr & EFI_MEMORY_UC ? "UC" : "");
873 return buf;
874}
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100875
876/*
Jan Beulich23f05712017-08-25 16:50:18 +0100877 * IA64 has a funky EFI memory map that doesn't work the same way as
878 * other architectures.
879 */
880#ifndef CONFIG_IA64
881/*
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100882 * efi_mem_attributes - lookup memmap attributes for physical address
883 * @phys_addr: the physical address to lookup
884 *
885 * Search in the EFI memory map for the region covering
886 * @phys_addr. Returns the EFI memory attributes if the region
887 * was found in the memory map, 0 otherwise.
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100888 */
Jan Beulich23f05712017-08-25 16:50:18 +0100889u64 efi_mem_attributes(unsigned long phys_addr)
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100890{
891 efi_memory_desc_t *md;
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100892
893 if (!efi_enabled(EFI_MEMMAP))
894 return 0;
895
Matt Fleming78ce2482016-04-25 21:06:38 +0100896 for_each_efi_memory_desc(md) {
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100897 if ((md->phys_addr <= phys_addr) &&
898 (phys_addr < (md->phys_addr +
899 (md->num_pages << EFI_PAGE_SHIFT))))
900 return md->attribute;
901 }
902 return 0;
903}
Matt Fleming806b0352016-04-25 21:06:58 +0100904
Jan Beulich23f05712017-08-25 16:50:18 +0100905/*
906 * efi_mem_type - lookup memmap type for physical address
907 * @phys_addr: the physical address to lookup
908 *
909 * Search in the EFI memory map for the region covering @phys_addr.
910 * Returns the EFI memory type if the region was found in the memory
911 * map, EFI_RESERVED_TYPE (zero) otherwise.
912 */
913int efi_mem_type(unsigned long phys_addr)
914{
915 const efi_memory_desc_t *md;
916
917 if (!efi_enabled(EFI_MEMMAP))
918 return -ENOTSUPP;
919
920 for_each_efi_memory_desc(md) {
921 if ((md->phys_addr <= phys_addr) &&
922 (phys_addr < (md->phys_addr +
923 (md->num_pages << EFI_PAGE_SHIFT))))
924 return md->type;
925 }
926 return -EINVAL;
927}
928#endif
929
Matt Fleming806b0352016-04-25 21:06:58 +0100930int efi_status_to_err(efi_status_t status)
931{
932 int err;
933
934 switch (status) {
935 case EFI_SUCCESS:
936 err = 0;
937 break;
938 case EFI_INVALID_PARAMETER:
939 err = -EINVAL;
940 break;
941 case EFI_OUT_OF_RESOURCES:
942 err = -ENOSPC;
943 break;
944 case EFI_DEVICE_ERROR:
945 err = -EIO;
946 break;
947 case EFI_WRITE_PROTECTED:
948 err = -EROFS;
949 break;
950 case EFI_SECURITY_VIOLATION:
951 err = -EACCES;
952 break;
953 case EFI_NOT_FOUND:
954 err = -ENOENT;
955 break;
Ard Biesheuveldce48e32016-07-15 21:36:31 +0200956 case EFI_ABORTED:
957 err = -EINTR;
958 break;
Matt Fleming806b0352016-04-25 21:06:58 +0100959 default:
960 err = -EINVAL;
961 }
962
963 return err;
964}
Ard Biesheuvel63625982016-11-12 21:32:31 +0000965
Tom Lendackya19d66c2017-07-17 16:10:13 -0500966bool efi_is_table_address(unsigned long phys_addr)
967{
968 unsigned int i;
969
970 if (phys_addr == EFI_INVALID_TABLE_ADDR)
971 return false;
972
973 for (i = 0; i < ARRAY_SIZE(efi_tables); i++)
974 if (*(efi_tables[i]) == phys_addr)
975 return true;
976
977 return false;
978}
979
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -0700980static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock);
Ard Biesheuvel63eb3222018-11-14 09:55:44 -0800981static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init;
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -0700982
Ard Biesheuvel976b4892018-11-23 22:51:32 +0100983static int __init efi_memreserve_map_root(void)
984{
985 if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR)
986 return -ENODEV;
987
988 efi_memreserve_root = memremap(efi.mem_reserve,
989 sizeof(*efi_memreserve_root),
990 MEMREMAP_WB);
991 if (WARN_ON_ONCE(!efi_memreserve_root))
992 return -ENOMEM;
993 return 0;
994}
995
996int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -0700997{
Ard Biesheuvel63eb3222018-11-14 09:55:44 -0800998 struct linux_efi_memreserve *rsv;
Ard Biesheuvel80424b02018-11-29 18:12:29 +0100999 unsigned long prsv;
1000 int rc, index;
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -07001001
Ard Biesheuvel976b4892018-11-23 22:51:32 +01001002 if (efi_memreserve_root == (void *)ULONG_MAX)
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -07001003 return -ENODEV;
1004
Ard Biesheuvel976b4892018-11-23 22:51:32 +01001005 if (!efi_memreserve_root) {
1006 rc = efi_memreserve_map_root();
1007 if (rc)
1008 return rc;
1009 }
1010
Ard Biesheuvel80424b02018-11-29 18:12:29 +01001011 /* first try to find a slot in an existing linked list entry */
1012 for (prsv = efi_memreserve_root->next; prsv; prsv = rsv->next) {
1013 rsv = __va(prsv);
1014 index = atomic_fetch_add_unless(&rsv->count, 1, rsv->size);
1015 if (index < rsv->size) {
1016 rsv->entry[index].base = addr;
1017 rsv->entry[index].size = size;
1018
1019 return 0;
1020 }
1021 }
1022
1023 /* no slot found - allocate a new linked list entry */
1024 rsv = (struct linux_efi_memreserve *)__get_free_page(GFP_ATOMIC);
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -07001025 if (!rsv)
1026 return -ENOMEM;
1027
Ard Biesheuvel80424b02018-11-29 18:12:29 +01001028 rsv->size = EFI_MEMRESERVE_COUNT(PAGE_SIZE);
Ard Biesheuvel5f0b0ec2018-11-29 18:12:28 +01001029 atomic_set(&rsv->count, 1);
1030 rsv->entry[0].base = addr;
1031 rsv->entry[0].size = size;
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -07001032
1033 spin_lock(&efi_mem_reserve_persistent_lock);
Ard Biesheuvel63eb3222018-11-14 09:55:44 -08001034 rsv->next = efi_memreserve_root->next;
1035 efi_memreserve_root->next = __pa(rsv);
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -07001036 spin_unlock(&efi_mem_reserve_persistent_lock);
1037
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -07001038 return 0;
1039}
1040
Ard Biesheuvel63eb3222018-11-14 09:55:44 -08001041static int __init efi_memreserve_root_init(void)
1042{
Ard Biesheuvel976b4892018-11-23 22:51:32 +01001043 if (efi_memreserve_root)
1044 return 0;
1045 if (efi_memreserve_map_root())
1046 efi_memreserve_root = (void *)ULONG_MAX;
Ard Biesheuvel63eb3222018-11-14 09:55:44 -08001047 return 0;
1048}
1049early_initcall(efi_memreserve_root_init);
1050
Ard Biesheuvel63625982016-11-12 21:32:31 +00001051#ifdef CONFIG_KEXEC
1052static int update_efi_random_seed(struct notifier_block *nb,
1053 unsigned long code, void *unused)
1054{
1055 struct linux_efi_random_seed *seed;
1056 u32 size = 0;
1057
1058 if (!kexec_in_progress)
1059 return NOTIFY_DONE;
1060
1061 seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
1062 if (seed != NULL) {
Ard Biesheuvelc2ceb5f2017-08-25 16:50:16 +01001063 size = min(seed->size, EFI_RANDOM_SEED_SIZE);
Ard Biesheuvel63625982016-11-12 21:32:31 +00001064 memunmap(seed);
1065 } else {
1066 pr_err("Could not map UEFI random seed!\n");
1067 }
1068 if (size > 0) {
1069 seed = memremap(efi.rng_seed, sizeof(*seed) + size,
1070 MEMREMAP_WB);
1071 if (seed != NULL) {
1072 seed->size = size;
1073 get_random_bytes(seed->bits, seed->size);
1074 memunmap(seed);
1075 } else {
1076 pr_err("Could not map UEFI random seed!\n");
1077 }
1078 }
1079 return NOTIFY_DONE;
1080}
1081
1082static struct notifier_block efi_random_seed_nb = {
1083 .notifier_call = update_efi_random_seed,
1084};
1085
1086static int register_update_efi_random_seed(void)
1087{
1088 if (efi.rng_seed == EFI_INVALID_TABLE_ADDR)
1089 return 0;
1090 return register_reboot_notifier(&efi_random_seed_nb);
1091}
1092late_initcall(register_update_efi_random_seed);
1093#endif