blob: 8f1ab04f6743ae9c402ac813195fd1a19d8f5b63 [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,
Ard Biesheuvelbf924862015-09-09 10:08:15 +020042 .boot_info = EFI_INVALID_TABLE_ADDR,
43 .hcdp = EFI_INVALID_TABLE_ADDR,
44 .uga = EFI_INVALID_TABLE_ADDR,
Ard Biesheuvelbf924862015-09-09 10:08:15 +020045 .fw_vendor = EFI_INVALID_TABLE_ADDR,
46 .runtime = EFI_INVALID_TABLE_ADDR,
47 .config_table = EFI_INVALID_TABLE_ADDR,
48 .esrt = EFI_INVALID_TABLE_ADDR,
49 .properties_table = EFI_INVALID_TABLE_ADDR,
Ard Biesheuvela604af02016-04-25 21:06:44 +010050 .mem_attr_table = EFI_INVALID_TABLE_ADDR,
Ard Biesheuvel63625982016-11-12 21:32:31 +000051 .rng_seed = EFI_INVALID_TABLE_ADDR,
Ard Biesheuvel71e09402018-09-21 09:32:44 -070052 .tpm_log = EFI_INVALID_TABLE_ADDR,
Matthew Garrettc46f3402019-05-20 13:54:59 -070053 .tpm_final_log = EFI_INVALID_TABLE_ADDR,
Ard Biesheuvel71e09402018-09-21 09:32:44 -070054 .mem_reserve = EFI_INVALID_TABLE_ADDR,
Leif Lindholm272686b2013-09-05 11:34:54 +010055};
56EXPORT_SYMBOL(efi);
Tom Gundersena9499fa2013-02-08 15:37:06 +000057
Sai Praneeth7e904a92018-03-12 08:44:56 +000058struct mm_struct efi_mm = {
59 .mm_rb = RB_ROOT,
60 .mm_users = ATOMIC_INIT(2),
61 .mm_count = ATOMIC_INIT(1),
62 .mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem),
63 .page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock),
64 .mmlist = LIST_HEAD_INIT(efi_mm.mmlist),
Rik van Rielc1a2f7f2018-07-16 15:03:31 -040065 .cpu_bitmap = { [BITS_TO_LONGS(NR_CPUS)] = 0},
Sai Praneeth7e904a92018-03-12 08:44:56 +000066};
67
Sai Praneeth3eb420e2018-07-11 11:40:35 +020068struct workqueue_struct *efi_rts_wq;
69
Dave Youngb2e0a542014-08-14 17:15:26 +080070static bool disable_runtime;
71static int __init setup_noefi(char *arg)
72{
73 disable_runtime = true;
74 return 0;
75}
76early_param("noefi", setup_noefi);
77
78bool efi_runtime_disabled(void)
79{
80 return disable_runtime;
81}
82
Dave Young5ae36832014-08-14 17:15:28 +080083static int __init parse_efi_cmdline(char *str)
84{
Ricardo Neri9115c752015-07-15 19:36:03 -070085 if (!str) {
86 pr_warn("need at least one option\n");
87 return -EINVAL;
88 }
89
Leif Lindholm12dd00e2015-08-26 14:24:56 +010090 if (parse_option_str(str, "debug"))
91 set_bit(EFI_DBG, &efi.flags);
92
Dave Young5ae36832014-08-14 17:15:28 +080093 if (parse_option_str(str, "noruntime"))
94 disable_runtime = true;
95
96 return 0;
97}
98early_param("efi", parse_efi_cmdline);
99
Peter Jones0bb54902015-04-28 18:44:31 -0400100struct kobject *efi_kobj;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000101
102/*
103 * Let's not leave out systab information that snuck into
104 * the efivars driver
Dave Young0b02e442017-12-06 09:50:10 +0000105 * Note, do not add more fields in systab sysfs file as it breaks sysfs
106 * one value per file rule!
Tom Gundersena9499fa2013-02-08 15:37:06 +0000107 */
108static ssize_t systab_show(struct kobject *kobj,
109 struct kobj_attribute *attr, char *buf)
110{
111 char *str = buf;
112
113 if (!kobj || !buf)
114 return -EINVAL;
115
116 if (efi.mps != EFI_INVALID_TABLE_ADDR)
117 str += sprintf(str, "MPS=0x%lx\n", efi.mps);
118 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
119 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
120 if (efi.acpi != EFI_INVALID_TABLE_ADDR)
121 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
Jean Delvareb119fe02015-04-30 15:23:05 +0200122 /*
123 * If both SMBIOS and SMBIOS3 entry points are implemented, the
124 * SMBIOS3 entry point shall be preferred, so we list it first to
125 * let applications stop parsing after the first match.
126 */
Ard Biesheuvele1ccbbc2014-10-14 16:34:47 +0200127 if (efi.smbios3 != EFI_INVALID_TABLE_ADDR)
128 str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3);
Jean Delvareb119fe02015-04-30 15:23:05 +0200129 if (efi.smbios != EFI_INVALID_TABLE_ADDR)
130 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
Tom Gundersena9499fa2013-02-08 15:37:06 +0000131 if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
132 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
133 if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
134 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
135 if (efi.uga != EFI_INVALID_TABLE_ADDR)
136 str += sprintf(str, "UGA=0x%lx\n", efi.uga);
137
138 return str - buf;
139}
140
Greg Kroah-Hartmanaf97a772017-12-06 09:50:08 +0000141static struct kobj_attribute efi_attr_systab = __ATTR_RO_MODE(systab, 0400);
Tom Gundersena9499fa2013-02-08 15:37:06 +0000142
Dave Younga0998eb2013-12-20 18:02:17 +0800143#define EFI_FIELD(var) efi.var
144
145#define EFI_ATTR_SHOW(name) \
146static ssize_t name##_show(struct kobject *kobj, \
147 struct kobj_attribute *attr, char *buf) \
148{ \
149 return sprintf(buf, "0x%lx\n", EFI_FIELD(name)); \
150}
151
152EFI_ATTR_SHOW(fw_vendor);
153EFI_ATTR_SHOW(runtime);
154EFI_ATTR_SHOW(config_table);
155
Steve McIntyre2859dff2015-01-09 15:29:53 +0000156static ssize_t fw_platform_size_show(struct kobject *kobj,
157 struct kobj_attribute *attr, char *buf)
158{
159 return sprintf(buf, "%d\n", efi_enabled(EFI_64BIT) ? 64 : 32);
160}
161
Dave Younga0998eb2013-12-20 18:02:17 +0800162static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor);
163static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
164static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);
Steve McIntyre2859dff2015-01-09 15:29:53 +0000165static struct kobj_attribute efi_attr_fw_platform_size =
166 __ATTR_RO(fw_platform_size);
Dave Younga0998eb2013-12-20 18:02:17 +0800167
Tom Gundersena9499fa2013-02-08 15:37:06 +0000168static struct attribute *efi_subsys_attrs[] = {
169 &efi_attr_systab.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800170 &efi_attr_fw_vendor.attr,
171 &efi_attr_runtime.attr,
172 &efi_attr_config_table.attr,
Steve McIntyre2859dff2015-01-09 15:29:53 +0000173 &efi_attr_fw_platform_size.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800174 NULL,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000175};
176
Dave Younga0998eb2013-12-20 18:02:17 +0800177static umode_t efi_attr_is_visible(struct kobject *kobj,
178 struct attribute *attr, int n)
179{
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200180 if (attr == &efi_attr_fw_vendor.attr) {
181 if (efi_enabled(EFI_PARAVIRT) ||
182 efi.fw_vendor == EFI_INVALID_TABLE_ADDR)
183 return 0;
184 } else if (attr == &efi_attr_runtime.attr) {
185 if (efi.runtime == EFI_INVALID_TABLE_ADDR)
186 return 0;
187 } else if (attr == &efi_attr_config_table.attr) {
188 if (efi.config_table == EFI_INVALID_TABLE_ADDR)
189 return 0;
190 }
Dave Younga0998eb2013-12-20 18:02:17 +0800191
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200192 return attr->mode;
Dave Younga0998eb2013-12-20 18:02:17 +0800193}
194
Arvind Yadav3ad6bd72017-08-18 20:49:46 +0100195static const struct attribute_group efi_subsys_attr_group = {
Tom Gundersena9499fa2013-02-08 15:37:06 +0000196 .attrs = efi_subsys_attrs,
Dave Younga0998eb2013-12-20 18:02:17 +0800197 .is_visible = efi_attr_is_visible,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000198};
199
200static struct efivars generic_efivars;
201static struct efivar_operations generic_ops;
202
203static int generic_ops_register(void)
204{
205 generic_ops.get_variable = efi.get_variable;
206 generic_ops.set_variable = efi.set_variable;
Ard Biesheuvel9c6672a2016-02-01 22:06:55 +0000207 generic_ops.set_variable_nonblocking = efi.set_variable_nonblocking;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000208 generic_ops.get_next_variable = efi.get_next_variable;
Matt Fleminga614e192013-04-30 11:30:24 +0100209 generic_ops.query_variable_store = efi_query_variable_store;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000210
211 return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
212}
213
214static void generic_ops_unregister(void)
215{
216 efivars_unregister(&generic_efivars);
217}
218
Octavian Purdila475fb4e2016-07-08 19:13:12 +0300219#if IS_ENABLED(CONFIG_ACPI)
220#define EFIVAR_SSDT_NAME_MAX 16
221static char efivar_ssdt[EFIVAR_SSDT_NAME_MAX] __initdata;
222static int __init efivar_ssdt_setup(char *str)
223{
224 if (strlen(str) < sizeof(efivar_ssdt))
225 memcpy(efivar_ssdt, str, strlen(str));
226 else
227 pr_warn("efivar_ssdt: name too long: %s\n", str);
228 return 0;
229}
230__setup("efivar_ssdt=", efivar_ssdt_setup);
231
232static __init int efivar_ssdt_iter(efi_char16_t *name, efi_guid_t vendor,
233 unsigned long name_size, void *data)
234{
235 struct efivar_entry *entry;
236 struct list_head *list = data;
237 char utf8_name[EFIVAR_SSDT_NAME_MAX];
238 int limit = min_t(unsigned long, EFIVAR_SSDT_NAME_MAX, name_size);
239
240 ucs2_as_utf8(utf8_name, name, limit - 1);
241 if (strncmp(utf8_name, efivar_ssdt, limit) != 0)
242 return 0;
243
244 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
245 if (!entry)
246 return 0;
247
248 memcpy(entry->var.VariableName, name, name_size);
249 memcpy(&entry->var.VendorGuid, &vendor, sizeof(efi_guid_t));
250
251 efivar_entry_add(entry, list);
252
253 return 0;
254}
255
256static __init int efivar_ssdt_load(void)
257{
258 LIST_HEAD(entries);
259 struct efivar_entry *entry, *aux;
260 unsigned long size;
261 void *data;
262 int ret;
263
264 ret = efivar_init(efivar_ssdt_iter, &entries, true, &entries);
265
266 list_for_each_entry_safe(entry, aux, &entries, list) {
267 pr_info("loading SSDT from variable %s-%pUl\n", efivar_ssdt,
268 &entry->var.VendorGuid);
269
270 list_del(&entry->list);
271
272 ret = efivar_entry_size(entry, &size);
273 if (ret) {
274 pr_err("failed to get var size\n");
275 goto free_entry;
276 }
277
278 data = kmalloc(size, GFP_KERNEL);
Dan Carpentera75dcb52016-10-18 15:33:18 +0100279 if (!data) {
280 ret = -ENOMEM;
Octavian Purdila475fb4e2016-07-08 19:13:12 +0300281 goto free_entry;
Dan Carpentera75dcb52016-10-18 15:33:18 +0100282 }
Octavian Purdila475fb4e2016-07-08 19:13:12 +0300283
284 ret = efivar_entry_get(entry, NULL, &size, data);
285 if (ret) {
286 pr_err("failed to get var data\n");
287 goto free_data;
288 }
289
290 ret = acpi_load_table(data);
291 if (ret) {
292 pr_err("failed to load table: %d\n", ret);
293 goto free_data;
294 }
295
296 goto free_entry;
297
298free_data:
299 kfree(data);
300
301free_entry:
302 kfree(entry);
303 }
304
305 return ret;
306}
307#else
308static inline int efivar_ssdt_load(void) { return 0; }
309#endif
310
Tom Gundersena9499fa2013-02-08 15:37:06 +0000311/*
312 * We register the efi subsystem with the firmware subsystem and the
313 * efivars subsystem with the efi subsystem, if the system was booted with
314 * EFI.
315 */
316static int __init efisubsys_init(void)
317{
318 int error;
319
320 if (!efi_enabled(EFI_BOOT))
321 return 0;
322
Sai Praneeth3eb420e2018-07-11 11:40:35 +0200323 /*
324 * Since we process only one efi_runtime_service() at a time, an
325 * ordered workqueue (which creates only one execution context)
326 * should suffice all our needs.
327 */
328 efi_rts_wq = alloc_ordered_workqueue("efi_rts_wq", 0);
329 if (!efi_rts_wq) {
330 pr_err("Creating efi_rts_wq failed, EFI runtime services disabled.\n");
331 clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
332 return 0;
333 }
334
Tom Gundersena9499fa2013-02-08 15:37:06 +0000335 /* We register the efi directory at /sys/firmware/efi */
336 efi_kobj = kobject_create_and_add("efi", firmware_kobj);
337 if (!efi_kobj) {
338 pr_err("efi: Firmware registration failed.\n");
339 return -ENOMEM;
340 }
341
342 error = generic_ops_register();
343 if (error)
344 goto err_put;
345
Octavian Purdila475fb4e2016-07-08 19:13:12 +0300346 if (efi_enabled(EFI_RUNTIME_SERVICES))
347 efivar_ssdt_load();
348
Tom Gundersena9499fa2013-02-08 15:37:06 +0000349 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
350 if (error) {
351 pr_err("efi: Sysfs attribute export failed with error %d.\n",
352 error);
353 goto err_unregister;
354 }
355
Dave Young926172d2013-12-20 18:02:18 +0800356 error = efi_runtime_map_init(efi_kobj);
357 if (error)
358 goto err_remove_group;
359
Tom Gundersena9499fa2013-02-08 15:37:06 +0000360 /* and the standard mountpoint for efivarfs */
Eric W. Biedermanf9bb4882015-05-13 17:35:41 -0500361 error = sysfs_create_mount_point(efi_kobj, "efivars");
362 if (error) {
Tom Gundersena9499fa2013-02-08 15:37:06 +0000363 pr_err("efivars: Subsystem registration failed.\n");
Tom Gundersena9499fa2013-02-08 15:37:06 +0000364 goto err_remove_group;
365 }
366
367 return 0;
368
369err_remove_group:
370 sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
371err_unregister:
372 generic_ops_unregister();
373err_put:
374 kobject_put(efi_kobj);
375 return error;
376}
377
378subsys_initcall(efisubsys_init);
Leif Lindholm272686b2013-09-05 11:34:54 +0100379
Peter Jones0bb54902015-04-28 18:44:31 -0400380/*
381 * Find the efi memory descriptor for a given physical address. Given a
Matt Flemingdca0f972016-02-27 15:52:50 +0000382 * physical address, determine if it exists within an EFI Memory Map entry,
Peter Jones0bb54902015-04-28 18:44:31 -0400383 * and if so, populate the supplied memory descriptor with the appropriate
384 * data.
385 */
Ard Biesheuvel7e1550b2018-07-11 11:40:39 +0200386int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
Peter Jones0bb54902015-04-28 18:44:31 -0400387{
Matt Flemingdca0f972016-02-27 15:52:50 +0000388 efi_memory_desc_t *md;
Peter Jones0bb54902015-04-28 18:44:31 -0400389
390 if (!efi_enabled(EFI_MEMMAP)) {
391 pr_err_once("EFI_MEMMAP is not enabled.\n");
392 return -EINVAL;
393 }
394
Peter Jones0bb54902015-04-28 18:44:31 -0400395 if (!out_md) {
396 pr_err_once("out_md is null.\n");
397 return -EINVAL;
398 }
Peter Jones0bb54902015-04-28 18:44:31 -0400399
Matt Flemingdca0f972016-02-27 15:52:50 +0000400 for_each_efi_memory_desc(md) {
Peter Jones0bb54902015-04-28 18:44:31 -0400401 u64 size;
402 u64 end;
403
Peter Jones0bb54902015-04-28 18:44:31 -0400404 size = md->num_pages << EFI_PAGE_SHIFT;
405 end = md->phys_addr + size;
406 if (phys_addr >= md->phys_addr && phys_addr < end) {
407 memcpy(out_md, md, sizeof(*out_md));
Peter Jones0bb54902015-04-28 18:44:31 -0400408 return 0;
409 }
Peter Jones0bb54902015-04-28 18:44:31 -0400410 }
Peter Jones0bb54902015-04-28 18:44:31 -0400411 return -ENOENT;
412}
413
414/*
415 * Calculate the highest address of an efi memory descriptor.
416 */
417u64 __init efi_mem_desc_end(efi_memory_desc_t *md)
418{
419 u64 size = md->num_pages << EFI_PAGE_SHIFT;
420 u64 end = md->phys_addr + size;
421 return end;
422}
Leif Lindholm272686b2013-09-05 11:34:54 +0100423
Matt Fleming816e7612016-02-29 21:22:52 +0000424void __init __weak efi_arch_mem_reserve(phys_addr_t addr, u64 size) {}
425
426/**
427 * efi_mem_reserve - Reserve an EFI memory region
428 * @addr: Physical address to reserve
429 * @size: Size of reservation
430 *
431 * Mark a region as reserved from general kernel allocation and
432 * prevent it being released by efi_free_boot_services().
433 *
434 * This function should be called drivers once they've parsed EFI
435 * configuration tables to figure out where their data lives, e.g.
436 * efi_esrt_init().
437 */
438void __init efi_mem_reserve(phys_addr_t addr, u64 size)
439{
440 if (!memblock_is_region_reserved(addr, size))
441 memblock_reserve(addr, size);
442
443 /*
444 * Some architectures (x86) reserve all boot services ranges
445 * until efi_free_boot_services() because of buggy firmware
446 * implementations. This means the above memblock_reserve() is
447 * superfluous on x86 and instead what it needs to do is
448 * ensure the @start, @size is not freed.
449 */
450 efi_arch_mem_reserve(addr, size);
451}
452
Leif Lindholm272686b2013-09-05 11:34:54 +0100453static __initdata efi_config_table_type_t common_tables[] = {
454 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
455 {ACPI_TABLE_GUID, "ACPI", &efi.acpi},
456 {HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
457 {MPS_TABLE_GUID, "MPS", &efi.mps},
Leif Lindholm272686b2013-09-05 11:34:54 +0100458 {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
Ard Biesheuvele1ccbbc2014-10-14 16:34:47 +0200459 {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
Leif Lindholm272686b2013-09-05 11:34:54 +0100460 {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
Peter Jones0bb54902015-04-28 18:44:31 -0400461 {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
Ard Biesheuvelbf924862015-09-09 10:08:15 +0200462 {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
Ard Biesheuvela604af02016-04-25 21:06:44 +0100463 {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
Ard Biesheuvel63625982016-11-12 21:32:31 +0000464 {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
Thiebaud Weksteen33b6d032017-09-20 10:13:39 +0200465 {LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log},
Matthew Garrettc46f3402019-05-20 13:54:59 -0700466 {LINUX_EFI_TPM_FINAL_LOG_GUID, "TPMFinalLog", &efi.tpm_final_log},
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700467 {LINUX_EFI_MEMRESERVE_TABLE_GUID, "MEMRESERVE", &efi.mem_reserve},
Narendra K1c5fecb2019-07-10 18:59:15 +0000468#ifdef CONFIG_EFI_RCI2_TABLE
469 {DELLEMC_EFI_RCI2_TABLE_GUID, NULL, &rci2_table_phys},
470#endif
Daeseok Youn69e60842014-02-13 17:16:36 +0900471 {NULL_GUID, NULL, NULL},
Leif Lindholm272686b2013-09-05 11:34:54 +0100472};
473
474static __init int match_config_table(efi_guid_t *guid,
475 unsigned long table,
476 efi_config_table_type_t *table_types)
477{
Leif Lindholm272686b2013-09-05 11:34:54 +0100478 int i;
479
480 if (table_types) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100481 for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100482 if (!efi_guidcmp(*guid, table_types[i].guid)) {
483 *(table_types[i].ptr) = table;
Ard Biesheuvel801820b2016-04-25 21:06:53 +0100484 if (table_types[i].name)
485 pr_cont(" %s=0x%lx ",
486 table_types[i].name, table);
Leif Lindholm272686b2013-09-05 11:34:54 +0100487 return 1;
488 }
489 }
490 }
491
492 return 0;
493}
494
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200495int __init efi_config_parse_tables(void *config_tables, int count, int sz,
496 efi_config_table_type_t *arch_tables)
497{
498 void *tablep;
499 int i;
500
501 tablep = config_tables;
502 pr_info("");
503 for (i = 0; i < count; i++) {
504 efi_guid_t guid;
505 unsigned long table;
506
507 if (efi_enabled(EFI_64BIT)) {
508 u64 table64;
509 guid = ((efi_config_table_64_t *)tablep)->guid;
510 table64 = ((efi_config_table_64_t *)tablep)->table;
511 table = table64;
512#ifndef CONFIG_64BIT
513 if (table64 >> 32) {
514 pr_cont("\n");
515 pr_err("Table located above 4GB, disabling EFI.\n");
516 return -EINVAL;
517 }
518#endif
519 } else {
520 guid = ((efi_config_table_32_t *)tablep)->guid;
521 table = ((efi_config_table_32_t *)tablep)->table;
522 }
523
524 if (!match_config_table(&guid, table, common_tables))
525 match_config_table(&guid, table, arch_tables);
526
527 tablep += sz;
528 }
529 pr_cont("\n");
530 set_bit(EFI_CONFIG_TABLES, &efi.flags);
Ard Biesheuvela1041712015-09-23 07:29:34 -0700531
Ard Biesheuvel63625982016-11-12 21:32:31 +0000532 if (efi.rng_seed != EFI_INVALID_TABLE_ADDR) {
533 struct linux_efi_random_seed *seed;
534 u32 size = 0;
535
536 seed = early_memremap(efi.rng_seed, sizeof(*seed));
537 if (seed != NULL) {
538 size = seed->size;
539 early_memunmap(seed, sizeof(*seed));
540 } else {
541 pr_err("Could not map UEFI random seed!\n");
542 }
543 if (size > 0) {
544 seed = early_memremap(efi.rng_seed,
545 sizeof(*seed) + size);
546 if (seed != NULL) {
Ard Biesheuvel5b4e4c32018-03-08 08:00:18 +0000547 pr_notice("seeding entropy pool\n");
Ard Biesheuvel63625982016-11-12 21:32:31 +0000548 add_device_randomness(seed->bits, seed->size);
549 early_memunmap(seed, sizeof(*seed) + size);
550 } else {
551 pr_err("Could not map UEFI random seed!\n");
552 }
553 }
554 }
555
Daniel Kiper457ea3f2017-06-22 12:51:36 +0200556 if (efi_enabled(EFI_MEMMAP))
557 efi_memattr_init();
Sai Praneeth3a6b6c62017-01-31 13:21:35 +0000558
Thiebaud Weksteen33b6d032017-09-20 10:13:39 +0200559 efi_tpm_eventlog_init();
560
Ard Biesheuvela1041712015-09-23 07:29:34 -0700561 /* Parse the EFI Properties table if it exists */
562 if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
563 efi_properties_table_t *tbl;
564
565 tbl = early_memremap(efi.properties_table, sizeof(*tbl));
566 if (tbl == NULL) {
567 pr_err("Could not map Properties table!\n");
568 return -ENOMEM;
569 }
570
571 if (tbl->memory_protection_attribute &
572 EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA)
573 set_bit(EFI_NX_PE_DATA, &efi.flags);
574
575 early_memunmap(tbl, sizeof(*tbl));
576 }
577
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700578 if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) {
579 unsigned long prsv = efi.mem_reserve;
580
581 while (prsv) {
582 struct linux_efi_memreserve *rsv;
Ard Biesheuvel5f0b0ec2018-11-29 18:12:28 +0100583 u8 *p;
584 int i;
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700585
Ard Biesheuvel5f0b0ec2018-11-29 18:12:28 +0100586 /*
587 * Just map a full page: that is what we will get
588 * anyway, and it permits us to map the entire entry
589 * before knowing its size.
590 */
591 p = early_memremap(ALIGN_DOWN(prsv, PAGE_SIZE),
592 PAGE_SIZE);
593 if (p == NULL) {
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700594 pr_err("Could not map UEFI memreserve entry!\n");
595 return -ENOMEM;
596 }
597
Ard Biesheuvel5f0b0ec2018-11-29 18:12:28 +0100598 rsv = (void *)(p + prsv % PAGE_SIZE);
599
600 /* reserve the entry itself */
601 memblock_reserve(prsv, EFI_MEMRESERVE_SIZE(rsv->size));
602
603 for (i = 0; i < atomic_read(&rsv->count); i++) {
604 memblock_reserve(rsv->entry[i].base,
605 rsv->entry[i].size);
606 }
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700607
608 prsv = rsv->next;
Ard Biesheuvel5f0b0ec2018-11-29 18:12:28 +0100609 early_memunmap(p, PAGE_SIZE);
Ard Biesheuvel71e09402018-09-21 09:32:44 -0700610 }
611 }
612
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200613 return 0;
614}
615
Leif Lindholm272686b2013-09-05 11:34:54 +0100616int __init efi_config_init(efi_config_table_type_t *arch_tables)
617{
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200618 void *config_tables;
619 int sz, ret;
Leif Lindholm272686b2013-09-05 11:34:54 +0100620
Rob Bradford88447c52019-05-25 13:25:59 +0200621 if (efi.systab->nr_tables == 0)
622 return 0;
623
Leif Lindholm272686b2013-09-05 11:34:54 +0100624 if (efi_enabled(EFI_64BIT))
625 sz = sizeof(efi_config_table_64_t);
626 else
627 sz = sizeof(efi_config_table_32_t);
628
629 /*
630 * Let's see what config tables the firmware passed to us.
631 */
632 config_tables = early_memremap(efi.systab->tables,
633 efi.systab->nr_tables * sz);
634 if (config_tables == NULL) {
635 pr_err("Could not map Configuration table!\n");
636 return -ENOMEM;
637 }
638
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200639 ret = efi_config_parse_tables(config_tables, efi.systab->nr_tables, sz,
640 arch_tables);
Leif Lindholm272686b2013-09-05 11:34:54 +0100641
Daniel Kiperabc93f82014-06-30 19:52:56 +0200642 early_memunmap(config_tables, efi.systab->nr_tables * sz);
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200643 return ret;
Leif Lindholm272686b2013-09-05 11:34:54 +0100644}
Mark Salter0302f712013-12-30 12:12:12 -0500645
Lee, Chun-Yi28d54022014-07-09 18:39:29 +0800646#ifdef CONFIG_EFI_VARS_MODULE
647static int __init efi_load_efivars(void)
648{
649 struct platform_device *pdev;
650
651 if (!efi_enabled(EFI_RUNTIME_SERVICES))
652 return 0;
653
654 pdev = platform_device_register_simple("efivars", 0, NULL, 0);
Vasyl Gomonovych50342b22018-01-02 18:10:40 +0000655 return PTR_ERR_OR_ZERO(pdev);
Lee, Chun-Yi28d54022014-07-09 18:39:29 +0800656}
657device_initcall(efi_load_efivars);
658#endif
659
Mark Salter0302f712013-12-30 12:12:12 -0500660#ifdef CONFIG_EFI_PARAMS_FROM_FDT
661
662#define UEFI_PARAM(name, prop, field) \
663 { \
664 { name }, \
665 { prop }, \
666 offsetof(struct efi_fdt_params, field), \
667 FIELD_SIZEOF(struct efi_fdt_params, field) \
668 }
669
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800670struct params {
Mark Salter0302f712013-12-30 12:12:12 -0500671 const char name[32];
672 const char propname[32];
673 int offset;
674 int size;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800675};
676
677static __initdata struct params fdt_params[] = {
Mark Salter0302f712013-12-30 12:12:12 -0500678 UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
679 UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
680 UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
681 UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
682 UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
683};
684
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800685static __initdata struct params xen_fdt_params[] = {
686 UEFI_PARAM("System Table", "xen,uefi-system-table", system_table),
687 UEFI_PARAM("MemMap Address", "xen,uefi-mmap-start", mmap),
688 UEFI_PARAM("MemMap Size", "xen,uefi-mmap-size", mmap_size),
689 UEFI_PARAM("MemMap Desc. Size", "xen,uefi-mmap-desc-size", desc_size),
690 UEFI_PARAM("MemMap Desc. Version", "xen,uefi-mmap-desc-ver", desc_ver)
691};
692
693#define EFI_FDT_PARAMS_SIZE ARRAY_SIZE(fdt_params)
694
695static __initdata struct {
696 const char *uname;
697 const char *subnode;
698 struct params *params;
699} dt_params[] = {
700 { "hypervisor", "uefi", xen_fdt_params },
701 { "chosen", NULL, fdt_params },
702};
703
Mark Salter0302f712013-12-30 12:12:12 -0500704struct param_info {
Catalin Marinas29e24352014-07-08 16:54:18 +0100705 int found;
Mark Salter0302f712013-12-30 12:12:12 -0500706 void *params;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800707 const char *missing;
Mark Salter0302f712013-12-30 12:12:12 -0500708};
709
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800710static int __init __find_uefi_params(unsigned long node,
711 struct param_info *info,
712 struct params *params)
Mark Salter0302f712013-12-30 12:12:12 -0500713{
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100714 const void *prop;
715 void *dest;
Mark Salter0302f712013-12-30 12:12:12 -0500716 u64 val;
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100717 int i, len;
Mark Salter0302f712013-12-30 12:12:12 -0500718
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800719 for (i = 0; i < EFI_FDT_PARAMS_SIZE; i++) {
720 prop = of_get_flat_dt_prop(node, params[i].propname, &len);
721 if (!prop) {
722 info->missing = params[i].name;
Mark Salter0302f712013-12-30 12:12:12 -0500723 return 0;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800724 }
725
726 dest = info->params + params[i].offset;
Catalin Marinas29e24352014-07-08 16:54:18 +0100727 info->found++;
Mark Salter0302f712013-12-30 12:12:12 -0500728
729 val = of_read_number(prop, len / sizeof(u32));
730
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800731 if (params[i].size == sizeof(u32))
Mark Salter0302f712013-12-30 12:12:12 -0500732 *(u32 *)dest = val;
733 else
734 *(u64 *)dest = val;
735
Leif Lindholm7968c0e2015-08-26 14:24:58 +0100736 if (efi_enabled(EFI_DBG))
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800737 pr_info(" %s: 0x%0*llx\n", params[i].name,
738 params[i].size * 2, val);
Mark Salter0302f712013-12-30 12:12:12 -0500739 }
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800740
Mark Salter0302f712013-12-30 12:12:12 -0500741 return 1;
742}
743
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800744static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
745 int depth, void *data)
746{
747 struct param_info *info = data;
748 int i;
749
750 for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
751 const char *subnode = dt_params[i].subnode;
752
753 if (depth != 1 || strcmp(uname, dt_params[i].uname) != 0) {
754 info->missing = dt_params[i].params[0].name;
755 continue;
756 }
757
758 if (subnode) {
Andrzej Hajda4af9ed52016-08-30 12:41:37 +0200759 int err = of_get_flat_dt_subnode_by_name(node, subnode);
760
761 if (err < 0)
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800762 return 0;
Andrzej Hajda4af9ed52016-08-30 12:41:37 +0200763
764 node = err;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800765 }
766
767 return __find_uefi_params(node, info, dt_params[i].params);
768 }
769
770 return 0;
771}
772
Leif Lindholm7968c0e2015-08-26 14:24:58 +0100773int __init efi_get_fdt_params(struct efi_fdt_params *params)
Mark Salter0302f712013-12-30 12:12:12 -0500774{
775 struct param_info info;
Catalin Marinas29e24352014-07-08 16:54:18 +0100776 int ret;
777
778 pr_info("Getting EFI parameters from FDT:\n");
Mark Salter0302f712013-12-30 12:12:12 -0500779
Catalin Marinas29e24352014-07-08 16:54:18 +0100780 info.found = 0;
Mark Salter0302f712013-12-30 12:12:12 -0500781 info.params = params;
782
Catalin Marinas29e24352014-07-08 16:54:18 +0100783 ret = of_scan_flat_dt(fdt_find_uefi_params, &info);
784 if (!info.found)
785 pr_info("UEFI not found.\n");
786 else if (!ret)
787 pr_err("Can't find '%s' in device tree!\n",
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800788 info.missing);
Catalin Marinas29e24352014-07-08 16:54:18 +0100789
790 return ret;
Mark Salter0302f712013-12-30 12:12:12 -0500791}
792#endif /* CONFIG_EFI_PARAMS_FROM_FDT */
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200793
794static __initdata char memory_type_name[][20] = {
795 "Reserved",
796 "Loader Code",
797 "Loader Data",
798 "Boot Code",
799 "Boot Data",
800 "Runtime Code",
801 "Runtime Data",
802 "Conventional Memory",
803 "Unusable Memory",
804 "ACPI Reclaim Memory",
805 "ACPI Memory NVS",
806 "Memory Mapped I/O",
807 "MMIO Port Space",
Robert Elliott35575e02016-02-01 22:07:07 +0000808 "PAL Code",
809 "Persistent Memory",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200810};
811
812char * __init efi_md_typeattr_format(char *buf, size_t size,
813 const efi_memory_desc_t *md)
814{
815 char *pos;
816 int type_len;
817 u64 attr;
818
819 pos = buf;
820 if (md->type >= ARRAY_SIZE(memory_type_name))
821 type_len = snprintf(pos, size, "[type=%u", md->type);
822 else
823 type_len = snprintf(pos, size, "[%-*s",
824 (int)(sizeof(memory_type_name[0]) - 1),
825 memory_type_name[md->type]);
826 if (type_len >= size)
827 return buf;
828
829 pos += type_len;
830 size -= type_len;
831
832 attr = md->attribute;
833 if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
Ard Biesheuvel87db73ae2015-08-07 09:36:54 +0100834 EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO |
835 EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP |
Robert Elliottc016ca02016-02-01 22:07:06 +0000836 EFI_MEMORY_NV |
Taku Izumi8be44322015-08-27 02:11:19 +0900837 EFI_MEMORY_RUNTIME | EFI_MEMORY_MORE_RELIABLE))
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200838 snprintf(pos, size, "|attr=0x%016llx]",
839 (unsigned long long)attr);
840 else
Robert Elliottc016ca02016-02-01 22:07:06 +0000841 snprintf(pos, size,
842 "|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200843 attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
Taku Izumi8be44322015-08-27 02:11:19 +0900844 attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "",
Robert Elliottc016ca02016-02-01 22:07:06 +0000845 attr & EFI_MEMORY_NV ? "NV" : "",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200846 attr & EFI_MEMORY_XP ? "XP" : "",
847 attr & EFI_MEMORY_RP ? "RP" : "",
848 attr & EFI_MEMORY_WP ? "WP" : "",
Ard Biesheuvel87db73ae2015-08-07 09:36:54 +0100849 attr & EFI_MEMORY_RO ? "RO" : "",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200850 attr & EFI_MEMORY_UCE ? "UCE" : "",
851 attr & EFI_MEMORY_WB ? "WB" : "",
852 attr & EFI_MEMORY_WT ? "WT" : "",
853 attr & EFI_MEMORY_WC ? "WC" : "",
854 attr & EFI_MEMORY_UC ? "UC" : "");
855 return buf;
856}
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100857
858/*
Jan Beulich23f05712017-08-25 16:50:18 +0100859 * IA64 has a funky EFI memory map that doesn't work the same way as
860 * other architectures.
861 */
862#ifndef CONFIG_IA64
863/*
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100864 * efi_mem_attributes - lookup memmap attributes for physical address
865 * @phys_addr: the physical address to lookup
866 *
867 * Search in the EFI memory map for the region covering
868 * @phys_addr. Returns the EFI memory attributes if the region
869 * was found in the memory map, 0 otherwise.
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100870 */
Jan Beulich23f05712017-08-25 16:50:18 +0100871u64 efi_mem_attributes(unsigned long phys_addr)
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100872{
873 efi_memory_desc_t *md;
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100874
875 if (!efi_enabled(EFI_MEMMAP))
876 return 0;
877
Matt Fleming78ce2482016-04-25 21:06:38 +0100878 for_each_efi_memory_desc(md) {
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100879 if ((md->phys_addr <= phys_addr) &&
880 (phys_addr < (md->phys_addr +
881 (md->num_pages << EFI_PAGE_SHIFT))))
882 return md->attribute;
883 }
884 return 0;
885}
Matt Fleming806b0352016-04-25 21:06:58 +0100886
Jan Beulich23f05712017-08-25 16:50:18 +0100887/*
888 * efi_mem_type - lookup memmap type for physical address
889 * @phys_addr: the physical address to lookup
890 *
891 * Search in the EFI memory map for the region covering @phys_addr.
892 * Returns the EFI memory type if the region was found in the memory
893 * map, EFI_RESERVED_TYPE (zero) otherwise.
894 */
895int efi_mem_type(unsigned long phys_addr)
896{
897 const efi_memory_desc_t *md;
898
899 if (!efi_enabled(EFI_MEMMAP))
900 return -ENOTSUPP;
901
902 for_each_efi_memory_desc(md) {
903 if ((md->phys_addr <= phys_addr) &&
904 (phys_addr < (md->phys_addr +
905 (md->num_pages << EFI_PAGE_SHIFT))))
906 return md->type;
907 }
908 return -EINVAL;
909}
910#endif
911
Matt Fleming806b0352016-04-25 21:06:58 +0100912int efi_status_to_err(efi_status_t status)
913{
914 int err;
915
916 switch (status) {
917 case EFI_SUCCESS:
918 err = 0;
919 break;
920 case EFI_INVALID_PARAMETER:
921 err = -EINVAL;
922 break;
923 case EFI_OUT_OF_RESOURCES:
924 err = -ENOSPC;
925 break;
926 case EFI_DEVICE_ERROR:
927 err = -EIO;
928 break;
929 case EFI_WRITE_PROTECTED:
930 err = -EROFS;
931 break;
932 case EFI_SECURITY_VIOLATION:
933 err = -EACCES;
934 break;
935 case EFI_NOT_FOUND:
936 err = -ENOENT;
937 break;
Ard Biesheuveldce48e32016-07-15 21:36:31 +0200938 case EFI_ABORTED:
939 err = -EINTR;
940 break;
Matt Fleming806b0352016-04-25 21:06:58 +0100941 default:
942 err = -EINVAL;
943 }
944
945 return err;
946}
Ard Biesheuvel63625982016-11-12 21:32:31 +0000947
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -0700948static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock);
Ard Biesheuvel63eb3222018-11-14 09:55:44 -0800949static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init;
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -0700950
Ard Biesheuvel976b4892018-11-23 22:51:32 +0100951static int __init efi_memreserve_map_root(void)
952{
953 if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR)
954 return -ENODEV;
955
956 efi_memreserve_root = memremap(efi.mem_reserve,
957 sizeof(*efi_memreserve_root),
958 MEMREMAP_WB);
959 if (WARN_ON_ONCE(!efi_memreserve_root))
960 return -ENOMEM;
961 return 0;
962}
963
964int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -0700965{
Ard Biesheuvel63eb3222018-11-14 09:55:44 -0800966 struct linux_efi_memreserve *rsv;
Ard Biesheuvel80424b02018-11-29 18:12:29 +0100967 unsigned long prsv;
968 int rc, index;
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -0700969
Ard Biesheuvel976b4892018-11-23 22:51:32 +0100970 if (efi_memreserve_root == (void *)ULONG_MAX)
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -0700971 return -ENODEV;
972
Ard Biesheuvel976b4892018-11-23 22:51:32 +0100973 if (!efi_memreserve_root) {
974 rc = efi_memreserve_map_root();
975 if (rc)
976 return rc;
977 }
978
Ard Biesheuvel80424b02018-11-29 18:12:29 +0100979 /* first try to find a slot in an existing linked list entry */
980 for (prsv = efi_memreserve_root->next; prsv; prsv = rsv->next) {
Ard Biesheuvel18df7572019-06-09 20:17:44 +0200981 rsv = memremap(prsv, sizeof(*rsv), MEMREMAP_WB);
Ard Biesheuvel80424b02018-11-29 18:12:29 +0100982 index = atomic_fetch_add_unless(&rsv->count, 1, rsv->size);
983 if (index < rsv->size) {
984 rsv->entry[index].base = addr;
985 rsv->entry[index].size = size;
986
Ard Biesheuvel18df7572019-06-09 20:17:44 +0200987 memunmap(rsv);
Ard Biesheuvel80424b02018-11-29 18:12:29 +0100988 return 0;
989 }
Ard Biesheuvel18df7572019-06-09 20:17:44 +0200990 memunmap(rsv);
Ard Biesheuvel80424b02018-11-29 18:12:29 +0100991 }
992
993 /* no slot found - allocate a new linked list entry */
994 rsv = (struct linux_efi_memreserve *)__get_free_page(GFP_ATOMIC);
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -0700995 if (!rsv)
996 return -ENOMEM;
997
Ard Biesheuvel18df7572019-06-09 20:17:44 +0200998 /*
999 * The memremap() call above assumes that a linux_efi_memreserve entry
1000 * never crosses a page boundary, so let's ensure that this remains true
1001 * even when kexec'ing a 4k pages kernel from a >4k pages kernel, by
1002 * using SZ_4K explicitly in the size calculation below.
1003 */
1004 rsv->size = EFI_MEMRESERVE_COUNT(SZ_4K);
Ard Biesheuvel5f0b0ec2018-11-29 18:12:28 +01001005 atomic_set(&rsv->count, 1);
1006 rsv->entry[0].base = addr;
1007 rsv->entry[0].size = size;
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -07001008
1009 spin_lock(&efi_mem_reserve_persistent_lock);
Ard Biesheuvel63eb3222018-11-14 09:55:44 -08001010 rsv->next = efi_memreserve_root->next;
1011 efi_memreserve_root->next = __pa(rsv);
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -07001012 spin_unlock(&efi_mem_reserve_persistent_lock);
1013
Ard Biesheuvela23d3bb2018-09-21 09:32:46 -07001014 return 0;
1015}
1016
Ard Biesheuvel63eb3222018-11-14 09:55:44 -08001017static int __init efi_memreserve_root_init(void)
1018{
Ard Biesheuvel976b4892018-11-23 22:51:32 +01001019 if (efi_memreserve_root)
1020 return 0;
1021 if (efi_memreserve_map_root())
1022 efi_memreserve_root = (void *)ULONG_MAX;
Ard Biesheuvel63eb3222018-11-14 09:55:44 -08001023 return 0;
1024}
1025early_initcall(efi_memreserve_root_init);
1026
Ard Biesheuvel63625982016-11-12 21:32:31 +00001027#ifdef CONFIG_KEXEC
1028static int update_efi_random_seed(struct notifier_block *nb,
1029 unsigned long code, void *unused)
1030{
1031 struct linux_efi_random_seed *seed;
1032 u32 size = 0;
1033
1034 if (!kexec_in_progress)
1035 return NOTIFY_DONE;
1036
1037 seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
1038 if (seed != NULL) {
Ard Biesheuvelc2ceb5f2017-08-25 16:50:16 +01001039 size = min(seed->size, EFI_RANDOM_SEED_SIZE);
Ard Biesheuvel63625982016-11-12 21:32:31 +00001040 memunmap(seed);
1041 } else {
1042 pr_err("Could not map UEFI random seed!\n");
1043 }
1044 if (size > 0) {
1045 seed = memremap(efi.rng_seed, sizeof(*seed) + size,
1046 MEMREMAP_WB);
1047 if (seed != NULL) {
1048 seed->size = size;
1049 get_random_bytes(seed->bits, seed->size);
1050 memunmap(seed);
1051 } else {
1052 pr_err("Could not map UEFI random seed!\n");
1053 }
1054 }
1055 return NOTIFY_DONE;
1056}
1057
1058static struct notifier_block efi_random_seed_nb = {
1059 .notifier_call = update_efi_random_seed,
1060};
1061
1062static int register_update_efi_random_seed(void)
1063{
1064 if (efi.rng_seed == EFI_INVALID_TABLE_ADDR)
1065 return 0;
1066 return register_reboot_notifier(&efi_random_seed_nb);
1067}
1068late_initcall(register_update_efi_random_seed);
1069#endif