blob: 16b2137d117c24af336f62ee998844075913467c [file] [log] [blame]
Thomas Gleixner55716d22019-06-01 10:08:42 +02001// SPDX-License-Identifier: GPL-2.0-only
Tom Gundersena9499fa2013-02-08 15:37:06 +00002/*
3 * efi.c - EFI subsystem
4 *
5 * Copyright (C) 2001,2003,2004 Dell <Matt_Domsch@dell.com>
6 * Copyright (C) 2004 Intel Corporation <matthew.e.tolentino@intel.com>
7 * Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
8 *
9 * This code registers /sys/firmware/efi{,/efivars} when EFI is supported,
10 * allowing the efivarfs to be mounted or the efivars module to be loaded.
11 * The existance of /sys/firmware/efi may also be used by userspace to
12 * determine that the system supports EFI.
Tom Gundersena9499fa2013-02-08 15:37:06 +000013 */
14
Leif Lindholm272686b2013-09-05 11:34:54 +010015#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16
Tom Gundersena9499fa2013-02-08 15:37:06 +000017#include <linux/kobject.h>
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/device.h>
21#include <linux/efi.h>
Mark Salter0302f712013-12-30 12:12:12 -050022#include <linux/of.h>
23#include <linux/of_fdt.h>
Leif Lindholm272686b2013-09-05 11:34:54 +010024#include <linux/io.h>
Ard Biesheuvel63625982016-11-12 21:32:31 +000025#include <linux/kexec.h>
Lee, Chun-Yi28d54022014-07-09 18:39:29 +080026#include <linux/platform_device.h>
Ard Biesheuvel63625982016-11-12 21:32:31 +000027#include <linux/random.h>
28#include <linux/reboot.h>
Octavian Purdila475fb4e2016-07-08 19:13:12 +030029#include <linux/slab.h>
30#include <linux/acpi.h>
31#include <linux/ucs2_string.h>
Matt Fleming816e7612016-02-29 21:22:52 +000032#include <linux/memblock.h>
Leif Lindholm272686b2013-09-05 11:34:54 +010033
Ard Biesheuvel0f7f2f02016-01-12 14:22:46 +010034#include <asm/early_ioremap.h>
Ard Biesheuvelf7d92482015-11-30 13:28:19 +010035
Leif Lindholm272686b2013-09-05 11:34:54 +010036struct efi __read_mostly efi = {
Ard Biesheuvelbf924862015-09-09 10:08:15 +020037 .mps = EFI_INVALID_TABLE_ADDR,
38 .acpi = EFI_INVALID_TABLE_ADDR,
39 .acpi20 = EFI_INVALID_TABLE_ADDR,
40 .smbios = EFI_INVALID_TABLE_ADDR,
41 .smbios3 = EFI_INVALID_TABLE_ADDR,
42 .sal_systab = EFI_INVALID_TABLE_ADDR,
43 .boot_info = EFI_INVALID_TABLE_ADDR,
44 .hcdp = EFI_INVALID_TABLE_ADDR,
45 .uga = EFI_INVALID_TABLE_ADDR,
46 .uv_systab = EFI_INVALID_TABLE_ADDR,
47 .fw_vendor = EFI_INVALID_TABLE_ADDR,
48 .runtime = EFI_INVALID_TABLE_ADDR,
49 .config_table = EFI_INVALID_TABLE_ADDR,
50 .esrt = EFI_INVALID_TABLE_ADDR,
51 .properties_table = EFI_INVALID_TABLE_ADDR,
Ard Biesheuvela604af02016-04-25 21:06:44 +010052 .mem_attr_table = EFI_INVALID_TABLE_ADDR,
Ard Biesheuvel63625982016-11-12 21:32:31 +000053 .rng_seed = EFI_INVALID_TABLE_ADDR,
Ard Biesheuvel71e09402018-09-21 09:32:44 -070054 .tpm_log = EFI_INVALID_TABLE_ADDR,
55 .mem_reserve = EFI_INVALID_TABLE_ADDR,
Leif Lindholm272686b2013-09-05 11:34:54 +010056};
57EXPORT_SYMBOL(efi);
Tom Gundersena9499fa2013-02-08 15:37:06 +000058
Tom Lendackya19d66c2017-07-17 16:10:13 -050059static unsigned long *efi_tables[] = {
60 &efi.mps,
61 &efi.acpi,
62 &efi.acpi20,
63 &efi.smbios,
64 &efi.smbios3,
65 &efi.sal_systab,
66 &efi.boot_info,
67 &efi.hcdp,
68 &efi.uga,
69 &efi.uv_systab,
70 &efi.fw_vendor,
71 &efi.runtime,
72 &efi.config_table,
73 &efi.esrt,
74 &efi.properties_table,
75 &efi.mem_attr_table,
76};
77
Sai Praneeth7e904a92018-03-12 08:44:56 +000078struct mm_struct efi_mm = {
79 .mm_rb = RB_ROOT,
80 .mm_users = ATOMIC_INIT(2),
81 .mm_count = ATOMIC_INIT(1),
82 .mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem),
83 .page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
84 .mmlist = LIST_HEAD_INIT(efi_mm.mmlist),
Rik van Rielc1a2f7f2018-07-16 15:03:31 -040085 .cpu_bitmap = { [BITS_TO_LONGS(NR_CPUS)] = 0},
Sai Praneeth7e904a92018-03-12 08:44:56 +000086};
87
Sai Praneeth3eb420e2018-07-11 11:40:35 +020088struct workqueue_struct *efi_rts_wq;
89
Dave Youngb2e0a542014-08-14 17:15:26 +080090static bool disable_runtime;
91static int __init setup_noefi(char *arg)
92{
93 disable_runtime = true;
94 return 0;
95}
96early_param("noefi", setup_noefi);
97
98bool efi_runtime_disabled(void)
99{
100 return disable_runtime;
101}
102
Dave Young5ae36832014-08-14 17:15:28 +0800103static int __init parse_efi_cmdline(char *str)
104{
Ricardo Neri9115c752015-07-15 19:36:03 -0700105 if (!str) {
106 pr_warn("need at least one option\n");
107 return -EINVAL;
108 }
109
Leif Lindholm12dd00e2015-08-26 14:24:56 +0100110 if (parse_option_str(str, "debug"))
111 set_bit(EFI_DBG, &efi.flags);
112
Dave Young5ae36832014-08-14 17:15:28 +0800113 if (parse_option_str(str, "noruntime"))
114 disable_runtime = true;
115
116 return 0;
117}
118early_param("efi", parse_efi_cmdline);
119
Peter Jones0bb54902015-04-28 18:44:31 -0400120struct kobject *efi_kobj;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000121
122/*
123 * Let's not leave out systab information that snuck into
124 * the efivars driver
Dave Young0b02e442017-12-06 09:50:10 +0000125 * Note, do not add more fields in systab sysfs file as it breaks sysfs
126 * one value per file rule!
Tom Gundersena9499fa2013-02-08 15:37:06 +0000127 */
128static ssize_t systab_show(struct kobject *kobj,
129 struct kobj_attribute *attr, char *buf)
130{
131 char *str = buf;
132
133 if (!kobj || !buf)
134 return -EINVAL;
135
136 if (efi.mps != EFI_INVALID_TABLE_ADDR)
137 str += sprintf(str, "MPS=0x%lx\n", efi.mps);
138 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
139 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
140 if (efi.acpi != EFI_INVALID_TABLE_ADDR)
141 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
Jean Delvareb119fe02015-04-30 15:23:05 +0200142 /*
143 * If both SMBIOS and SMBIOS3 entry points are implemented, the
144 * SMBIOS3 entry point shall be preferred, so we list it first to
145 * let applications stop parsing after the first match.
146 */
Ard Biesheuvele1ccbbc2014-10-14 16:34:47 +0200147 if (efi.smbios3 != EFI_INVALID_TABLE_ADDR)
148 str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3);
Jean Delvareb119fe02015-04-30 15:23:05 +0200149 if (efi.smbios != EFI_INVALID_TABLE_ADDR)
150 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
Tom Gundersena9499fa2013-02-08 15:37:06 +0000151 if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
152 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
153 if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
154 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
155 if (efi.uga != EFI_INVALID_TABLE_ADDR)
156 str += sprintf(str, "UGA=0x%lx\n", efi.uga);
157
158 return str - buf;
159}
160
Greg Kroah-Hartmanaf97a772017-12-06 09:50:08 +0000161static struct kobj_attribute efi_attr_systab = __ATTR_RO_MODE(systab, 0400);
Tom Gundersena9499fa2013-02-08 15:37:06 +0000162
Dave Younga0998eb2013-12-20 18:02:17 +0800163#define EFI_FIELD(var) efi.var
164
165#define EFI_ATTR_SHOW(name) \
166static ssize_t name##_show(struct kobject *kobj, \
167 struct kobj_attribute *attr, char *buf) \
168{ \
169 return sprintf(buf, "0x%lx\n", EFI_FIELD(name)); \
170}
171
172EFI_ATTR_SHOW(fw_vendor);
173EFI_ATTR_SHOW(runtime);
174EFI_ATTR_SHOW(config_table);
175
Steve McIntyre2859dff2015-01-09 15:29:53 +0000176static ssize_t fw_platform_size_show(struct kobject *kobj,
177 struct kobj_attribute *attr, char *buf)
178{
179 return sprintf(buf, "%d\n", efi_enabled(EFI_64BIT) ? 64 : 32);
180}
181
Dave Younga0998eb2013-12-20 18:02:17 +0800182static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor);
183static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
184static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);
Steve McIntyre2859dff2015-01-09 15:29:53 +0000185static struct kobj_attribute efi_attr_fw_platform_size =
186 __ATTR_RO(fw_platform_size);
Dave Younga0998eb2013-12-20 18:02:17 +0800187
Tom Gundersena9499fa2013-02-08 15:37:06 +0000188static struct attribute *efi_subsys_attrs[] = {
189 &efi_attr_systab.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800190 &efi_attr_fw_vendor.attr,
191 &efi_attr_runtime.attr,
192 &efi_attr_config_table.attr,
Steve McIntyre2859dff2015-01-09 15:29:53 +0000193 &efi_attr_fw_platform_size.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800194 NULL,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000195};
196
Dave Younga0998eb2013-12-20 18:02:17 +0800197static umode_t efi_attr_is_visible(struct kobject *kobj,
198 struct attribute *attr, int n)
199{
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200200 if (attr == &efi_attr_fw_vendor.attr) {
201 if (efi_enabled(EFI_PARAVIRT) ||
202 efi.fw_vendor == EFI_INVALID_TABLE_ADDR)
203 return 0;
204 } else if (attr == &efi_attr_runtime.attr) {
205 if (efi.runtime == EFI_INVALID_TABLE_ADDR)
206 return 0;
207 } else if (attr == &efi_attr_config_table.attr) {
208 if (efi.config_table == EFI_INVALID_TABLE_ADDR)
209 return 0;
210 }
Dave Younga0998eb2013-12-20 18:02:17 +0800211
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200212 return attr->mode;
Dave Younga0998eb2013-12-20 18:02:17 +0800213}
214
Arvind Yadav3ad6bd72017-08-18 20:49:46 +0100215static const struct attribute_group efi_subsys_attr_group = {
Tom Gundersena9499fa2013-02-08 15:37:06 +0000216 .attrs = efi_subsys_attrs,
Dave Younga0998eb2013-12-20 18:02:17 +0800217 .is_visible = efi_attr_is_visible,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000218};
219
220static struct efivars generic_efivars;
221static struct efivar_operations generic_ops;
222
223static int generic_ops_register(void)
224{
225 generic_ops.get_variable = efi.get_variable;
226 generic_ops.set_variable = efi.set_variable;
Ard Biesheuvel9c6672a2016-02-01 22:06:55 +0000227 generic_ops.set_variable_nonblocking = efi.set_variable_nonblocking;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000228 generic_ops.get_next_variable = efi.get_next_variable;
Matt Fleminga614e192013-04-30 11:30:24 +0100229 generic_ops.query_variable_store = efi_query_variable_store;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000230
231 return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
232}
233
234static void generic_ops_unregister(void)
235{
236 efivars_unregister(&generic_efivars);
237}
238
Octavian Purdila475fb4e2016-07-08 19:13:12 +0300239#if IS_ENABLED(CONFIG_ACPI)
240#define EFIVAR_SSDT_NAME_MAX 16
241static char efivar_ssdt[EFIVAR_SSDT_NAME_MAX] __initdata;
242static int __init efivar_ssdt_setup(char *str)
243{
244 if (strlen(str) < sizeof(efivar_ssdt))
245 memcpy(efivar_ssdt, str, strlen(str));
246 else
247 pr_warn("efivar_ssdt: name too long: %s\n", str);
248 return 0;
249}
250__setup("efivar_ssdt=", efivar_ssdt_setup);
251
252static __init int efivar_ssdt_iter(efi_char16_t *name, efi_guid_t vendor,
253 unsigned long name_size, void *data)
254{
255 struct efivar_entry *entry;
256 struct list_head *list = data;
257 char utf8_name[EFIVAR_SSDT_NAME_MAX];
258 int limit = min_t(unsigned long, EFIVAR_SSDT_NAME_MAX, name_size);
259
260 ucs2_as_utf8(utf8_name, name, limit - 1);
261 if (strncmp(utf8_name, efivar_ssdt, limit) != 0)
262 return 0;
263
264 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
265 if (!entry)
266 return 0;
267
268 memcpy(entry->var.VariableName, name, name_size);
269 memcpy(&entry->var.VendorGuid, &vendor, sizeof(efi_guid_t));
270
271 efivar_entry_add(entry, list);
272
273 return 0;
274}
275
276static __init int efivar_ssdt_load(void)
277{
278 LIST_HEAD(entries);
279 struct efivar_entry *entry, *aux;
280 unsigned long size;
281 void *data;
282 int ret;
283
284 ret = efivar_init(efivar_ssdt_iter, &entries, true, &entries);
285
286 list_for_each_entry_safe(entry, aux, &entries, list) {
287 pr_info("loading SSDT from variable %s-%pUl\n", efivar_ssdt,
288 &entry->var.VendorGuid);
289
290 list_del(&entry->list);
291
292 ret = efivar_entry_size(entry, &size);
293 if (ret) {
294 pr_err("failed to get var size\n");
295 goto free_entry;
296 }
297
298 data = kmalloc(size, GFP_KERNEL);
Dan Carpentera75dcb52016-10-18 15:33:18 +0100299 if (!data) {
300 ret = -ENOMEM;
Octavian Purdila475fb4e2016-07-08 19:13:12 +0300301 goto free_entry;
Dan Carpentera75dcb52016-10-18 15:33:18 +0100302 }
Octavian Purdila475fb4e2016-07-08 19:13:12 +0300303
304 ret = efivar_entry_get(entry, NULL, &size, data);
305 if (ret) {
306 pr_err("failed to get var data\n");
307 goto free_data;
308 }
309
310 ret = acpi_load_table(data);
311 if (ret) {
312 pr_err("failed to load table: %d\n", ret);
313 goto free_data;
314 }
315
316 goto free_entry;
317
318free_data:
319 kfree(data);
320
321free_entry:
322 kfree(entry);
323 }
324
325 return ret;
326}
327#else
328static inline int efivar_ssdt_load(void) { return 0; }
329#endif
330
Tom Gundersena9499fa2013-02-08 15:37:06 +0000331/*
332 * We register the efi subsystem with the firmware subsystem and the
333 * efivars subsystem with the efi subsystem, if the system was booted with
334 * EFI.
335 */
336static int __init efisubsys_init(void)
337{
338 int error;
339
340 if (!efi_enabled(EFI_BOOT))
341 return 0;
342
Sai Praneeth3eb420e2018-07-11 11:40:35 +0200343 /*
344 * Since we process only one efi_runtime_service() at a time, an
345 * ordered workqueue (which creates only one execution context)
346 * should suffice all our needs.
347 */
348 efi_rts_wq = alloc_ordered_workqueue("efi_rts_wq", 0);
349 if (!efi_rts_wq) {
350 pr_err("Creating efi_rts_wq failed, EFI runtime services disabled.\n");
351 clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
352 return 0;
353 }
354
Tom Gundersena9499fa2013-02-08 15:37:06 +0000355 /* We register the efi directory at /sys/firmware/efi */
356 efi_kobj = kobject_create_and_add("efi", firmware_kobj);
357 if (!efi_kobj) {
358 pr_err("efi: Firmware registration failed.\n");
359 return -ENOMEM;
360 }
361
362 error = generic_ops_register();
363 if (error)
364 goto err_put;
365
Octavian Purdila475fb4e2016-07-08 19:13:12 +0300366 if (efi_enabled(EFI_RUNTIME_SERVICES))
367 efivar_ssdt_load();
368
Tom Gundersena9499fa2013-02-08 15:37:06 +0000369 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
370 if (error) {
371 pr_err("efi: Sysfs attribute export failed with error %d.\n",
372 error);
373 goto err_unregister;
374 }
375
Dave Young926172d2013-12-20 18:02:18 +0800376 error = efi_runtime_map_init(efi_kobj);
377 if (error)
378 goto err_remove_group;
379
Tom Gundersena9499fa2013-02-08 15:37:06 +0000380 /* and the standard mountpoint for efivarfs */
Eric W. Biedermanf9bb4882015-05-13 17:35:41 -0500381 error = sysfs_create_mount_point(efi_kobj, "efivars");
382 if (error) {
Tom Gundersena9499fa2013-02-08 15:37:06 +0000383 pr_err("efivars: Subsystem registration failed.\n");
Tom Gundersena9499fa2013-02-08 15:37:06 +0000384 goto err_remove_group;
385 }
386
387 return 0;
388
389err_remove_group:
390 sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
391err_unregister:
392 generic_ops_unregister();
393err_put:
394 kobject_put(efi_kobj);
395 return error;
396}
397
398subsys_initcall(efisubsys_init);
Leif Lindholm272686b2013-09-05 11:34:54 +0100399
Peter Jones0bb54902015-04-28 18:44:31 -0400400/*
401 * Find the efi memory descriptor for a given physical address. Given a
Matt Flemingdca0f972016-02-27 15:52:50 +0000402 * physical address, determine if it exists within an EFI Memory Map entry,
Peter Jones0bb54902015-04-28 18:44:31 -0400403 * and if so, populate the supplied memory descriptor with the appropriate
404 * data.
405 */
Ard Biesheuvel7e1550b2018-07-11 11:40:39 +0200406int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
Peter Jones0bb54902015-04-28 18:44:31 -0400407{
Matt Flemingdca0f972016-02-27 15:52:50 +0000408 efi_memory_desc_t *md;
Peter Jones0bb54902015-04-28 18:44:31 -0400409
410 if (!efi_enabled(EFI_MEMMAP)) {
411 pr_err_once("EFI_MEMMAP is not enabled.\n");
412 return -EINVAL;
413 }
414
Peter Jones0bb54902015-04-28 18:44:31 -0400415 if (!out_md) {
416 pr_err_once("out_md is null.\n");
417 return -EINVAL;
418 }
Peter Jones0bb54902015-04-28 18:44:31 -0400419
Matt Flemingdca0f972016-02-27 15:52:50 +0000420 for_each_efi_memory_desc(md) {
Peter Jones0bb54902015-04-28 18:44:31 -0400421 u64 size;
422 u64 end;
423
Peter Jones0bb54902015-04-28 18:44:31 -0400424 size = md->num_pages << EFI_PAGE_SHIFT;
425 end = md->phys_addr + size;
426 if (phys_addr >= md->phys_addr && phys_addr < end) {
427 memcpy(out_md, md, sizeof(*out_md));
Peter Jones0bb54902015-04-28 18:44:31 -0400428 return 0;
429 }
Peter Jones0bb54902015-04-28 18:44:31 -0400430 }
Peter Jones0bb54902015-04-28 18:44:31 -0400431 return -ENOENT;
432}
433
434/*
435 * Calculate the highest address of an efi memory descriptor.
436 */
437u64 __init efi_mem_desc_end(efi_memory_desc_t *md)
438{
439 u64 size = md->num_pages << EFI_PAGE_SHIFT;
440 u64 end = md->phys_addr + size;
441 return end;
442}
Leif Lindholm272686b2013-09-05 11:34:54 +0100443
Matt Fleming816e7612016-02-29 21:22:52 +0000444void __init __weak efi_arch_mem_reserve(phys_addr_t addr, u64 size) {}
445
446/**
447 * efi_mem_reserve - Reserve an EFI memory region
448 * @addr: Physical address to reserve
449 * @size: Size of reservation
450 *
451 * Mark a region as reserved from general kernel allocation and
452 * prevent it being released by efi_free_boot_services().
453 *
454 * This function should be called drivers once they've parsed EFI
455 * configuration tables to figure out where their data lives, e.g.
456 * efi_esrt_init().
457 */
458void __init efi_mem_reserve(phys_addr_t addr, u64 size)
459{
460 if (!memblock_is_region_reserved(addr, size))
461 memblock_reserve(addr, size);
462
463 /*
464 * Some architectures (x86) reserve all boot services ranges
465 * until efi_free_boot_services() because of buggy firmware
466 * implementations. This means the above memblock_reserve() is
467 * superfluous on x86 and instead what it needs to do is
468 * ensure the @start, @size is not freed.
469 */
470 efi_arch_mem_reserve(addr, size);
471}
472
Leif Lindholm272686b2013-09-05 11:34:54 +0100473static __initdata efi_config_table_type_t common_tables[] = {
474 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
475 {ACPI_TABLE_GUID, "ACPI", &efi.acpi},
476 {HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
477 {MPS_TABLE_GUID, "MPS", &efi.mps},
478 {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
479 {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
Ard Biesheuvele1ccbbc2014-10-14 16:34:47 +0200480 {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
Leif Lindholm272686b2013-09-05 11:34:54 +0100481 {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
Peter Jones0bb54902015-04-28 18:44:31 -0400482 {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
Ard Biesheuvelbf924862015-09-09 10:08:15 +0200483 {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
Ard Biesheuvela604af02016-04-25 21:06:44 +0100484 {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
Ard Biesheuvel63625982016-11-12 21:32:31 +0000485 {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
Thiebaud Weksteen33b6d032017-09-20 10:13:39 +0200486 {LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log},
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700487 {LINUX_EFI_MEMRESERVE_TABLE_GUID, "MEMRESERVE", &efi.mem_reserve},
Daeseok Youn69e60842014-02-13 17:16:36 +0900488 {NULL_GUID, NULL, NULL},
Leif Lindholm272686b2013-09-05 11:34:54 +0100489};
490
491static __init int match_config_table(efi_guid_t *guid,
492 unsigned long table,
493 efi_config_table_type_t *table_types)
494{
Leif Lindholm272686b2013-09-05 11:34:54 +0100495 int i;
496
497 if (table_types) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100498 for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100499 if (!efi_guidcmp(*guid, table_types[i].guid)) {
500 *(table_types[i].ptr) = table;
Ard Biesheuvel801820b2016-04-25 21:06:53 +0100501 if (table_types[i].name)
502 pr_cont(" %s=0x%lx ",
503 table_types[i].name, table);
Leif Lindholm272686b2013-09-05 11:34:54 +0100504 return 1;
505 }
506 }
507 }
508
509 return 0;
510}
511
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200512int __init efi_config_parse_tables(void *config_tables, int count, int sz,
513 efi_config_table_type_t *arch_tables)
514{
515 void *tablep;
516 int i;
517
518 tablep = config_tables;
519 pr_info("");
520 for (i = 0; i < count; i++) {
521 efi_guid_t guid;
522 unsigned long table;
523
524 if (efi_enabled(EFI_64BIT)) {
525 u64 table64;
526 guid = ((efi_config_table_64_t *)tablep)->guid;
527 table64 = ((efi_config_table_64_t *)tablep)->table;
528 table = table64;
529#ifndef CONFIG_64BIT
530 if (table64 >> 32) {
531 pr_cont("\n");
532 pr_err("Table located above 4GB, disabling EFI.\n");
533 return -EINVAL;
534 }
535#endif
536 } else {
537 guid = ((efi_config_table_32_t *)tablep)->guid;
538 table = ((efi_config_table_32_t *)tablep)->table;
539 }
540
541 if (!match_config_table(&guid, table, common_tables))
542 match_config_table(&guid, table, arch_tables);
543
544 tablep += sz;
545 }
546 pr_cont("\n");
547 set_bit(EFI_CONFIG_TABLES, &efi.flags);
Ard Biesheuvela1041712015-09-23 07:29:34 -0700548
Ard Biesheuvel63625982016-11-12 21:32:31 +0000549 if (efi.rng_seed != EFI_INVALID_TABLE_ADDR) {
550 struct linux_efi_random_seed *seed;
551 u32 size = 0;
552
553 seed = early_memremap(efi.rng_seed, sizeof(*seed));
554 if (seed != NULL) {
555 size = seed->size;
556 early_memunmap(seed, sizeof(*seed));
557 } else {
558 pr_err("Could not map UEFI random seed!\n");
559 }
560 if (size > 0) {
561 seed = early_memremap(efi.rng_seed,
562 sizeof(*seed) + size);
563 if (seed != NULL) {
Ard Biesheuvel5b4e4c32018-03-08 08:00:18 +0000564 pr_notice("seeding entropy pool\n");
Ard Biesheuvel63625982016-11-12 21:32:31 +0000565 add_device_randomness(seed->bits, seed->size);
566 early_memunmap(seed, sizeof(*seed) + size);
567 } else {
568 pr_err("Could not map UEFI random seed!\n");
569 }
570 }
571 }
572
Daniel Kiper457ea3f2017-06-22 12:51:36 +0200573 if (efi_enabled(EFI_MEMMAP))
574 efi_memattr_init();
Sai Praneeth3a6b6c62017-01-31 13:21:35 +0000575
Thiebaud Weksteen33b6d032017-09-20 10:13:39 +0200576 efi_tpm_eventlog_init();
577
Ard Biesheuvela1041712015-09-23 07:29:34 -0700578 /* Parse the EFI Properties table if it exists */
579 if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
580 efi_properties_table_t *tbl;
581
582 tbl = early_memremap(efi.properties_table, sizeof(*tbl));
583 if (tbl == NULL) {
584 pr_err("Could not map Properties table!\n");
585 return -ENOMEM;
586 }
587
588 if (tbl->memory_protection_attribute &
589 EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA)
590 set_bit(EFI_NX_PE_DATA, &efi.flags);
591
592 early_memunmap(tbl, sizeof(*tbl));
593 }
594
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700595 if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) {
596 unsigned long prsv = efi.mem_reserve;
597
598 while (prsv) {
599 struct linux_efi_memreserve *rsv;
Ard Biesheuvel5f0b0ec2018-11-29 18:12:28 +0100600 u8 *p;
601 int i;
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700602
Ard Biesheuvel5f0b0ec2018-11-29 18:12:28 +0100603 /*
604 * Just map a full page: that is what we will get
605 * anyway, and it permits us to map the entire entry
606 * before knowing its size.
607 */
608 p = early_memremap(ALIGN_DOWN(prsv, PAGE_SIZE),
609 PAGE_SIZE);
610 if (p == NULL) {
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700611 pr_err("Could not map UEFI memreserve entry!\n");
612 return -ENOMEM;
613 }
614
Ard Biesheuvel5f0b0ec2018-11-29 18:12:28 +0100615 rsv = (void *)(p + prsv % PAGE_SIZE);
616
617 /* reserve the entry itself */
618 memblock_reserve(prsv, EFI_MEMRESERVE_SIZE(rsv->size));
619
620 for (i = 0; i < atomic_read(&rsv->count); i++) {
621 memblock_reserve(rsv->entry[i].base,
622 rsv->entry[i].size);
623 }
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700624
625 prsv = rsv->next;
Ard Biesheuvel5f0b0ec2018-11-29 18:12:28 +0100626 early_memunmap(p, PAGE_SIZE);
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700627 }
628 }
629
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200630 return 0;
631}
632
Leif Lindholm272686b2013-09-05 11:34:54 +0100633int __init efi_config_init(efi_config_table_type_t *arch_tables)
634{
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200635 void *config_tables;
636 int sz, ret;
Leif Lindholm272686b2013-09-05 11:34:54 +0100637
Rob Bradford88447c52019-05-25 13:25:59 +0200638 if (efi.systab->nr_tables == 0)
639 return 0;
640
Leif Lindholm272686b2013-09-05 11:34:54 +0100641 if (efi_enabled(EFI_64BIT))
642 sz = sizeof(efi_config_table_64_t);
643 else
644 sz = sizeof(efi_config_table_32_t);
645
646 /*
647 * Let's see what config tables the firmware passed to us.
648 */
649 config_tables = early_memremap(efi.systab->tables,
650 efi.systab->nr_tables * sz);
651 if (config_tables == NULL) {
652 pr_err("Could not map Configuration table!\n");
653 return -ENOMEM;
654 }
655
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200656 ret = efi_config_parse_tables(config_tables, efi.systab->nr_tables, sz,
657 arch_tables);
Leif Lindholm272686b2013-09-05 11:34:54 +0100658
Daniel Kiperabc93f82014-06-30 19:52:56 +0200659 early_memunmap(config_tables, efi.systab->nr_tables * sz);
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200660 return ret;
Leif Lindholm272686b2013-09-05 11:34:54 +0100661}
Mark Salter0302f712013-12-30 12:12:12 -0500662
Lee, Chun-Yi28d54022014-07-09 18:39:29 +0800663#ifdef CONFIG_EFI_VARS_MODULE
664static int __init efi_load_efivars(void)
665{
666 struct platform_device *pdev;
667
668 if (!efi_enabled(EFI_RUNTIME_SERVICES))
669 return 0;
670
671 pdev = platform_device_register_simple("efivars", 0, NULL, 0);
Vasyl Gomonovych50342b22018-01-02 18:10:40 +0000672 return PTR_ERR_OR_ZERO(pdev);
Lee, Chun-Yi28d54022014-07-09 18:39:29 +0800673}
674device_initcall(efi_load_efivars);
675#endif
676
Mark Salter0302f712013-12-30 12:12:12 -0500677#ifdef CONFIG_EFI_PARAMS_FROM_FDT
678
679#define UEFI_PARAM(name, prop, field) \
680 { \
681 { name }, \
682 { prop }, \
683 offsetof(struct efi_fdt_params, field), \
684 FIELD_SIZEOF(struct efi_fdt_params, field) \
685 }
686
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800687struct params {
Mark Salter0302f712013-12-30 12:12:12 -0500688 const char name[32];
689 const char propname[32];
690 int offset;
691 int size;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800692};
693
694static __initdata struct params fdt_params[] = {
Mark Salter0302f712013-12-30 12:12:12 -0500695 UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
696 UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
697 UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
698 UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
699 UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
700};
701
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800702static __initdata struct params xen_fdt_params[] = {
703 UEFI_PARAM("System Table", "xen,uefi-system-table", system_table),
704 UEFI_PARAM("MemMap Address", "xen,uefi-mmap-start", mmap),
705 UEFI_PARAM("MemMap Size", "xen,uefi-mmap-size", mmap_size),
706 UEFI_PARAM("MemMap Desc. Size", "xen,uefi-mmap-desc-size", desc_size),
707 UEFI_PARAM("MemMap Desc. Version", "xen,uefi-mmap-desc-ver", desc_ver)
708};
709
710#define EFI_FDT_PARAMS_SIZE ARRAY_SIZE(fdt_params)
711
712static __initdata struct {
713 const char *uname;
714 const char *subnode;
715 struct params *params;
716} dt_params[] = {
717 { "hypervisor", "uefi", xen_fdt_params },
718 { "chosen", NULL, fdt_params },
719};
720
Mark Salter0302f712013-12-30 12:12:12 -0500721struct param_info {
Catalin Marinas29e24352014-07-08 16:54:18 +0100722 int found;
Mark Salter0302f712013-12-30 12:12:12 -0500723 void *params;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800724 const char *missing;
Mark Salter0302f712013-12-30 12:12:12 -0500725};
726
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800727static int __init __find_uefi_params(unsigned long node,
728 struct param_info *info,
729 struct params *params)
Mark Salter0302f712013-12-30 12:12:12 -0500730{
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100731 const void *prop;
732 void *dest;
Mark Salter0302f712013-12-30 12:12:12 -0500733 u64 val;
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100734 int i, len;
Mark Salter0302f712013-12-30 12:12:12 -0500735
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800736 for (i = 0; i < EFI_FDT_PARAMS_SIZE; i++) {
737 prop = of_get_flat_dt_prop(node, params[i].propname, &len);
738 if (!prop) {
739 info->missing = params[i].name;
Mark Salter0302f712013-12-30 12:12:12 -0500740 return 0;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800741 }
742
743 dest = info->params + params[i].offset;
Catalin Marinas29e24352014-07-08 16:54:18 +0100744 info->found++;
Mark Salter0302f712013-12-30 12:12:12 -0500745
746 val = of_read_number(prop, len / sizeof(u32));
747
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800748 if (params[i].size == sizeof(u32))
Mark Salter0302f712013-12-30 12:12:12 -0500749 *(u32 *)dest = val;
750 else
751 *(u64 *)dest = val;
752
Leif Lindholm7968c0e2015-08-26 14:24:58 +0100753 if (efi_enabled(EFI_DBG))
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800754 pr_info(" %s: 0x%0*llx\n", params[i].name,
755 params[i].size * 2, val);
Mark Salter0302f712013-12-30 12:12:12 -0500756 }
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800757
Mark Salter0302f712013-12-30 12:12:12 -0500758 return 1;
759}
760
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800761static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
762 int depth, void *data)
763{
764 struct param_info *info = data;
765 int i;
766
767 for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
768 const char *subnode = dt_params[i].subnode;
769
770 if (depth != 1 || strcmp(uname, dt_params[i].uname) != 0) {
771 info->missing = dt_params[i].params[0].name;
772 continue;
773 }
774
775 if (subnode) {
Andrzej Hajda4af9ed52016-08-30 12:41:37 +0200776 int err = of_get_flat_dt_subnode_by_name(node, subnode);
777
778 if (err < 0)
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800779 return 0;
Andrzej Hajda4af9ed52016-08-30 12:41:37 +0200780
781 node = err;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800782 }
783
784 return __find_uefi_params(node, info, dt_params[i].params);
785 }
786
787 return 0;
788}
789
Leif Lindholm7968c0e2015-08-26 14:24:58 +0100790int __init efi_get_fdt_params(struct efi_fdt_params *params)
Mark Salter0302f712013-12-30 12:12:12 -0500791{
792 struct param_info info;
Catalin Marinas29e24352014-07-08 16:54:18 +0100793 int ret;
794
795 pr_info("Getting EFI parameters from FDT:\n");
Mark Salter0302f712013-12-30 12:12:12 -0500796
Catalin Marinas29e24352014-07-08 16:54:18 +0100797 info.found = 0;
Mark Salter0302f712013-12-30 12:12:12 -0500798 info.params = params;
799
Catalin Marinas29e24352014-07-08 16:54:18 +0100800 ret = of_scan_flat_dt(fdt_find_uefi_params, &info);
801 if (!info.found)
802 pr_info("UEFI not found.\n");
803 else if (!ret)
804 pr_err("Can't find '%s' in device tree!\n",
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800805 info.missing);
Catalin Marinas29e24352014-07-08 16:54:18 +0100806
807 return ret;
Mark Salter0302f712013-12-30 12:12:12 -0500808}
809#endif /* CONFIG_EFI_PARAMS_FROM_FDT */
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200810
811static __initdata char memory_type_name[][20] = {
812 "Reserved",
813 "Loader Code",
814 "Loader Data",
815 "Boot Code",
816 "Boot Data",
817 "Runtime Code",
818 "Runtime Data",
819 "Conventional Memory",
820 "Unusable Memory",
821 "ACPI Reclaim Memory",
822 "ACPI Memory NVS",
823 "Memory Mapped I/O",
824 "MMIO Port Space",
Robert Elliott35575e02016-02-01 22:07:07 +0000825 "PAL Code",
826 "Persistent Memory",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200827};
828
829char * __init efi_md_typeattr_format(char *buf, size_t size,
830 const efi_memory_desc_t *md)
831{
832 char *pos;
833 int type_len;
834 u64 attr;
835
836 pos = buf;
837 if (md->type >= ARRAY_SIZE(memory_type_name))
838 type_len = snprintf(pos, size, "[type=%u", md->type);
839 else
840 type_len = snprintf(pos, size, "[%-*s",
841 (int)(sizeof(memory_type_name[0]) - 1),
842 memory_type_name[md->type]);
843 if (type_len >= size)
844 return buf;
845
846 pos += type_len;
847 size -= type_len;
848
849 attr = md->attribute;
850 if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
Ard Biesheuvel87db73ae2015-08-07 09:36:54 +0100851 EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO |
852 EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP |
Robert Elliottc016ca02016-02-01 22:07:06 +0000853 EFI_MEMORY_NV |
Taku Izumi8be44322015-08-27 02:11:19 +0900854 EFI_MEMORY_RUNTIME | EFI_MEMORY_MORE_RELIABLE))
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200855 snprintf(pos, size, "|attr=0x%016llx]",
856 (unsigned long long)attr);
857 else
Robert Elliottc016ca02016-02-01 22:07:06 +0000858 snprintf(pos, size,
859 "|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200860 attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
Taku Izumi8be44322015-08-27 02:11:19 +0900861 attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "",
Robert Elliottc016ca02016-02-01 22:07:06 +0000862 attr & EFI_MEMORY_NV ? "NV" : "",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200863 attr & EFI_MEMORY_XP ? "XP" : "",
864 attr & EFI_MEMORY_RP ? "RP" : "",
865 attr & EFI_MEMORY_WP ? "WP" : "",
Ard Biesheuvel87db73ae2015-08-07 09:36:54 +0100866 attr & EFI_MEMORY_RO ? "RO" : "",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200867 attr & EFI_MEMORY_UCE ? "UCE" : "",
868 attr & EFI_MEMORY_WB ? "WB" : "",
869 attr & EFI_MEMORY_WT ? "WT" : "",
870 attr & EFI_MEMORY_WC ? "WC" : "",
871 attr & EFI_MEMORY_UC ? "UC" : "");
872 return buf;
873}
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100874
875/*
Jan Beulich23f05712017-08-25 16:50:18 +0100876 * IA64 has a funky EFI memory map that doesn't work the same way as
877 * other architectures.
878 */
879#ifndef CONFIG_IA64
880/*
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100881 * efi_mem_attributes - lookup memmap attributes for physical address
882 * @phys_addr: the physical address to lookup
883 *
884 * Search in the EFI memory map for the region covering
885 * @phys_addr. Returns the EFI memory attributes if the region
886 * was found in the memory map, 0 otherwise.
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100887 */
Jan Beulich23f05712017-08-25 16:50:18 +0100888u64 efi_mem_attributes(unsigned long phys_addr)
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100889{
890 efi_memory_desc_t *md;
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100891
892 if (!efi_enabled(EFI_MEMMAP))
893 return 0;
894
Matt Fleming78ce2482016-04-25 21:06:38 +0100895 for_each_efi_memory_desc(md) {
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100896 if ((md->phys_addr <= phys_addr) &&
897 (phys_addr < (md->phys_addr +
898 (md->num_pages << EFI_PAGE_SHIFT))))
899 return md->attribute;
900 }
901 return 0;
902}
Matt Fleming806b0352016-04-25 21:06:58 +0100903
Jan Beulich23f05712017-08-25 16:50:18 +0100904/*
905 * efi_mem_type - lookup memmap type for physical address
906 * @phys_addr: the physical address to lookup
907 *
908 * Search in the EFI memory map for the region covering @phys_addr.
909 * Returns the EFI memory type if the region was found in the memory
910 * map, EFI_RESERVED_TYPE (zero) otherwise.
911 */
912int efi_mem_type(unsigned long phys_addr)
913{
914 const efi_memory_desc_t *md;
915
916 if (!efi_enabled(EFI_MEMMAP))
917 return -ENOTSUPP;
918
919 for_each_efi_memory_desc(md) {
920 if ((md->phys_addr <= phys_addr) &&
921 (phys_addr < (md->phys_addr +
922 (md->num_pages << EFI_PAGE_SHIFT))))
923 return md->type;
924 }
925 return -EINVAL;
926}
927#endif
928
Matt Fleming806b0352016-04-25 21:06:58 +0100929int efi_status_to_err(efi_status_t status)
930{
931 int err;
932
933 switch (status) {
934 case EFI_SUCCESS:
935 err = 0;
936 break;
937 case EFI_INVALID_PARAMETER:
938 err = -EINVAL;
939 break;
940 case EFI_OUT_OF_RESOURCES:
941 err = -ENOSPC;
942 break;
943 case EFI_DEVICE_ERROR:
944 err = -EIO;
945 break;
946 case EFI_WRITE_PROTECTED:
947 err = -EROFS;
948 break;
949 case EFI_SECURITY_VIOLATION:
950 err = -EACCES;
951 break;
952 case EFI_NOT_FOUND:
953 err = -ENOENT;
954 break;
Ard Biesheuveldce48e32016-07-15 21:36:31 +0200955 case EFI_ABORTED:
956 err = -EINTR;
957 break;
Matt Fleming806b0352016-04-25 21:06:58 +0100958 default:
959 err = -EINVAL;
960 }
961
962 return err;
963}
Ard Biesheuvel63625982016-11-12 21:32:31 +0000964
Tom Lendackya19d66c2017-07-17 16:10:13 -0500965bool efi_is_table_address(unsigned long phys_addr)
966{
967 unsigned int i;
968
969 if (phys_addr == EFI_INVALID_TABLE_ADDR)
970 return false;
971
972 for (i = 0; i < ARRAY_SIZE(efi_tables); i++)
973 if (*(efi_tables[i]) == phys_addr)
974 return true;
975
976 return false;
977}
978
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -0700979static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock);
Ard Biesheuvel63eb3222018-11-14 09:55:44 -0800980static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init;
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -0700981
Ard Biesheuvel976b4892018-11-23 22:51:32 +0100982static int __init efi_memreserve_map_root(void)
983{
984 if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR)
985 return -ENODEV;
986
987 efi_memreserve_root = memremap(efi.mem_reserve,
988 sizeof(*efi_memreserve_root),
989 MEMREMAP_WB);
990 if (WARN_ON_ONCE(!efi_memreserve_root))
991 return -ENOMEM;
992 return 0;
993}
994
995int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -0700996{
Ard Biesheuvel63eb3222018-11-14 09:55:44 -0800997 struct linux_efi_memreserve *rsv;
Ard Biesheuvel80424b02018-11-29 18:12:29 +0100998 unsigned long prsv;
999 int rc, index;
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -07001000
Ard Biesheuvel976b4892018-11-23 22:51:32 +01001001 if (efi_memreserve_root == (void *)ULONG_MAX)
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -07001002 return -ENODEV;
1003
Ard Biesheuvel976b4892018-11-23 22:51:32 +01001004 if (!efi_memreserve_root) {
1005 rc = efi_memreserve_map_root();
1006 if (rc)
1007 return rc;
1008 }
1009
Ard Biesheuvel80424b02018-11-29 18:12:29 +01001010 /* first try to find a slot in an existing linked list entry */
1011 for (prsv = efi_memreserve_root->next; prsv; prsv = rsv->next) {
1012 rsv = __va(prsv);
1013 index = atomic_fetch_add_unless(&rsv->count, 1, rsv->size);
1014 if (index < rsv->size) {
1015 rsv->entry[index].base = addr;
1016 rsv->entry[index].size = size;
1017
1018 return 0;
1019 }
1020 }
1021
1022 /* no slot found - allocate a new linked list entry */
1023 rsv = (struct linux_efi_memreserve *)__get_free_page(GFP_ATOMIC);
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -07001024 if (!rsv)
1025 return -ENOMEM;
1026
Ard Biesheuvel80424b02018-11-29 18:12:29 +01001027 rsv->size = EFI_MEMRESERVE_COUNT(PAGE_SIZE);
Ard Biesheuvel5f0b0ec2018-11-29 18:12:28 +01001028 atomic_set(&rsv->count, 1);
1029 rsv->entry[0].base = addr;
1030 rsv->entry[0].size = size;
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -07001031
1032 spin_lock(&efi_mem_reserve_persistent_lock);
Ard Biesheuvel63eb3222018-11-14 09:55:44 -08001033 rsv->next = efi_memreserve_root->next;
1034 efi_memreserve_root->next = __pa(rsv);
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -07001035 spin_unlock(&efi_mem_reserve_persistent_lock);
1036
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -07001037 return 0;
1038}
1039
Ard Biesheuvel63eb3222018-11-14 09:55:44 -08001040static int __init efi_memreserve_root_init(void)
1041{
Ard Biesheuvel976b4892018-11-23 22:51:32 +01001042 if (efi_memreserve_root)
1043 return 0;
1044 if (efi_memreserve_map_root())
1045 efi_memreserve_root = (void *)ULONG_MAX;
Ard Biesheuvel63eb3222018-11-14 09:55:44 -08001046 return 0;
1047}
1048early_initcall(efi_memreserve_root_init);
1049
Ard Biesheuvel63625982016-11-12 21:32:31 +00001050#ifdef CONFIG_KEXEC
1051static int update_efi_random_seed(struct notifier_block *nb,
1052 unsigned long code, void *unused)
1053{
1054 struct linux_efi_random_seed *seed;
1055 u32 size = 0;
1056
1057 if (!kexec_in_progress)
1058 return NOTIFY_DONE;
1059
1060 seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
1061 if (seed != NULL) {
Ard Biesheuvelc2ceb5f2017-08-25 16:50:16 +01001062 size = min(seed->size, EFI_RANDOM_SEED_SIZE);
Ard Biesheuvel63625982016-11-12 21:32:31 +00001063 memunmap(seed);
1064 } else {
1065 pr_err("Could not map UEFI random seed!\n");
1066 }
1067 if (size > 0) {
1068 seed = memremap(efi.rng_seed, sizeof(*seed) + size,
1069 MEMREMAP_WB);
1070 if (seed != NULL) {
1071 seed->size = size;
1072 get_random_bytes(seed->bits, seed->size);
1073 memunmap(seed);
1074 } else {
1075 pr_err("Could not map UEFI random seed!\n");
1076 }
1077 }
1078 return NOTIFY_DONE;
1079}
1080
1081static struct notifier_block efi_random_seed_nb = {
1082 .notifier_call = update_efi_random_seed,
1083};
1084
1085static int register_update_efi_random_seed(void)
1086{
1087 if (efi.rng_seed == EFI_INVALID_TABLE_ADDR)
1088 return 0;
1089 return register_reboot_notifier(&efi_random_seed_nb);
1090}
1091late_initcall(register_update_efi_random_seed);
1092#endif