blob: 1ac199cd75e7bdd56ce8d5b9ab91bc2ee9d15133 [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>
Lee, Chun-Yi28d54022014-07-09 18:39:29 +080026#include <linux/platform_device.h>
Octavian Purdila475fb4e2016-07-08 19:13:12 +030027#include <linux/slab.h>
28#include <linux/acpi.h>
29#include <linux/ucs2_string.h>
Matt Fleming816e7612016-02-29 21:22:52 +000030#include <linux/memblock.h>
Leif Lindholm272686b2013-09-05 11:34:54 +010031
Ard Biesheuvel0f7f2f02016-01-12 14:22:46 +010032#include <asm/early_ioremap.h>
Ard Biesheuvelf7d92482015-11-30 13:28:19 +010033
Leif Lindholm272686b2013-09-05 11:34:54 +010034struct efi __read_mostly efi = {
Ard Biesheuvelbf924862015-09-09 10:08:15 +020035 .mps = EFI_INVALID_TABLE_ADDR,
36 .acpi = EFI_INVALID_TABLE_ADDR,
37 .acpi20 = EFI_INVALID_TABLE_ADDR,
38 .smbios = EFI_INVALID_TABLE_ADDR,
39 .smbios3 = EFI_INVALID_TABLE_ADDR,
40 .sal_systab = EFI_INVALID_TABLE_ADDR,
41 .boot_info = EFI_INVALID_TABLE_ADDR,
42 .hcdp = EFI_INVALID_TABLE_ADDR,
43 .uga = EFI_INVALID_TABLE_ADDR,
44 .uv_systab = EFI_INVALID_TABLE_ADDR,
45 .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,
Leif Lindholm272686b2013-09-05 11:34:54 +010051};
52EXPORT_SYMBOL(efi);
Tom Gundersena9499fa2013-02-08 15:37:06 +000053
Dave Youngb2e0a542014-08-14 17:15:26 +080054static bool disable_runtime;
55static int __init setup_noefi(char *arg)
56{
57 disable_runtime = true;
58 return 0;
59}
60early_param("noefi", setup_noefi);
61
62bool efi_runtime_disabled(void)
63{
64 return disable_runtime;
65}
66
Dave Young5ae36832014-08-14 17:15:28 +080067static int __init parse_efi_cmdline(char *str)
68{
Ricardo Neri9115c752015-07-15 19:36:03 -070069 if (!str) {
70 pr_warn("need at least one option\n");
71 return -EINVAL;
72 }
73
Leif Lindholm12dd00e2015-08-26 14:24:56 +010074 if (parse_option_str(str, "debug"))
75 set_bit(EFI_DBG, &efi.flags);
76
Dave Young5ae36832014-08-14 17:15:28 +080077 if (parse_option_str(str, "noruntime"))
78 disable_runtime = true;
79
80 return 0;
81}
82early_param("efi", parse_efi_cmdline);
83
Peter Jones0bb54902015-04-28 18:44:31 -040084struct kobject *efi_kobj;
Tom Gundersena9499fa2013-02-08 15:37:06 +000085
86/*
87 * Let's not leave out systab information that snuck into
88 * the efivars driver
89 */
90static ssize_t systab_show(struct kobject *kobj,
91 struct kobj_attribute *attr, char *buf)
92{
93 char *str = buf;
94
95 if (!kobj || !buf)
96 return -EINVAL;
97
98 if (efi.mps != EFI_INVALID_TABLE_ADDR)
99 str += sprintf(str, "MPS=0x%lx\n", efi.mps);
100 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
101 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
102 if (efi.acpi != EFI_INVALID_TABLE_ADDR)
103 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
Jean Delvareb119fe02015-04-30 15:23:05 +0200104 /*
105 * If both SMBIOS and SMBIOS3 entry points are implemented, the
106 * SMBIOS3 entry point shall be preferred, so we list it first to
107 * let applications stop parsing after the first match.
108 */
Ard Biesheuvele1ccbbc2014-10-14 16:34:47 +0200109 if (efi.smbios3 != EFI_INVALID_TABLE_ADDR)
110 str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3);
Jean Delvareb119fe02015-04-30 15:23:05 +0200111 if (efi.smbios != EFI_INVALID_TABLE_ADDR)
112 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
Tom Gundersena9499fa2013-02-08 15:37:06 +0000113 if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
114 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
115 if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
116 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
117 if (efi.uga != EFI_INVALID_TABLE_ADDR)
118 str += sprintf(str, "UGA=0x%lx\n", efi.uga);
119
120 return str - buf;
121}
122
123static struct kobj_attribute efi_attr_systab =
124 __ATTR(systab, 0400, systab_show, NULL);
125
Dave Younga0998eb2013-12-20 18:02:17 +0800126#define EFI_FIELD(var) efi.var
127
128#define EFI_ATTR_SHOW(name) \
129static ssize_t name##_show(struct kobject *kobj, \
130 struct kobj_attribute *attr, char *buf) \
131{ \
132 return sprintf(buf, "0x%lx\n", EFI_FIELD(name)); \
133}
134
135EFI_ATTR_SHOW(fw_vendor);
136EFI_ATTR_SHOW(runtime);
137EFI_ATTR_SHOW(config_table);
138
Steve McIntyre2859dff2015-01-09 15:29:53 +0000139static ssize_t fw_platform_size_show(struct kobject *kobj,
140 struct kobj_attribute *attr, char *buf)
141{
142 return sprintf(buf, "%d\n", efi_enabled(EFI_64BIT) ? 64 : 32);
143}
144
Dave Younga0998eb2013-12-20 18:02:17 +0800145static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor);
146static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
147static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);
Steve McIntyre2859dff2015-01-09 15:29:53 +0000148static struct kobj_attribute efi_attr_fw_platform_size =
149 __ATTR_RO(fw_platform_size);
Dave Younga0998eb2013-12-20 18:02:17 +0800150
Tom Gundersena9499fa2013-02-08 15:37:06 +0000151static struct attribute *efi_subsys_attrs[] = {
152 &efi_attr_systab.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800153 &efi_attr_fw_vendor.attr,
154 &efi_attr_runtime.attr,
155 &efi_attr_config_table.attr,
Steve McIntyre2859dff2015-01-09 15:29:53 +0000156 &efi_attr_fw_platform_size.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800157 NULL,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000158};
159
Dave Younga0998eb2013-12-20 18:02:17 +0800160static umode_t efi_attr_is_visible(struct kobject *kobj,
161 struct attribute *attr, int n)
162{
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200163 if (attr == &efi_attr_fw_vendor.attr) {
164 if (efi_enabled(EFI_PARAVIRT) ||
165 efi.fw_vendor == EFI_INVALID_TABLE_ADDR)
166 return 0;
167 } else if (attr == &efi_attr_runtime.attr) {
168 if (efi.runtime == EFI_INVALID_TABLE_ADDR)
169 return 0;
170 } else if (attr == &efi_attr_config_table.attr) {
171 if (efi.config_table == EFI_INVALID_TABLE_ADDR)
172 return 0;
173 }
Dave Younga0998eb2013-12-20 18:02:17 +0800174
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200175 return attr->mode;
Dave Younga0998eb2013-12-20 18:02:17 +0800176}
177
Tom Gundersena9499fa2013-02-08 15:37:06 +0000178static struct attribute_group efi_subsys_attr_group = {
179 .attrs = efi_subsys_attrs,
Dave Younga0998eb2013-12-20 18:02:17 +0800180 .is_visible = efi_attr_is_visible,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000181};
182
183static struct efivars generic_efivars;
184static struct efivar_operations generic_ops;
185
186static int generic_ops_register(void)
187{
188 generic_ops.get_variable = efi.get_variable;
189 generic_ops.set_variable = efi.set_variable;
Ard Biesheuvel9c6672a2016-02-01 22:06:55 +0000190 generic_ops.set_variable_nonblocking = efi.set_variable_nonblocking;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000191 generic_ops.get_next_variable = efi.get_next_variable;
Matt Fleminga614e192013-04-30 11:30:24 +0100192 generic_ops.query_variable_store = efi_query_variable_store;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000193
194 return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
195}
196
197static void generic_ops_unregister(void)
198{
199 efivars_unregister(&generic_efivars);
200}
201
Octavian Purdila475fb4e2016-07-08 19:13:12 +0300202#if IS_ENABLED(CONFIG_ACPI)
203#define EFIVAR_SSDT_NAME_MAX 16
204static char efivar_ssdt[EFIVAR_SSDT_NAME_MAX] __initdata;
205static int __init efivar_ssdt_setup(char *str)
206{
207 if (strlen(str) < sizeof(efivar_ssdt))
208 memcpy(efivar_ssdt, str, strlen(str));
209 else
210 pr_warn("efivar_ssdt: name too long: %s\n", str);
211 return 0;
212}
213__setup("efivar_ssdt=", efivar_ssdt_setup);
214
215static __init int efivar_ssdt_iter(efi_char16_t *name, efi_guid_t vendor,
216 unsigned long name_size, void *data)
217{
218 struct efivar_entry *entry;
219 struct list_head *list = data;
220 char utf8_name[EFIVAR_SSDT_NAME_MAX];
221 int limit = min_t(unsigned long, EFIVAR_SSDT_NAME_MAX, name_size);
222
223 ucs2_as_utf8(utf8_name, name, limit - 1);
224 if (strncmp(utf8_name, efivar_ssdt, limit) != 0)
225 return 0;
226
227 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
228 if (!entry)
229 return 0;
230
231 memcpy(entry->var.VariableName, name, name_size);
232 memcpy(&entry->var.VendorGuid, &vendor, sizeof(efi_guid_t));
233
234 efivar_entry_add(entry, list);
235
236 return 0;
237}
238
239static __init int efivar_ssdt_load(void)
240{
241 LIST_HEAD(entries);
242 struct efivar_entry *entry, *aux;
243 unsigned long size;
244 void *data;
245 int ret;
246
247 ret = efivar_init(efivar_ssdt_iter, &entries, true, &entries);
248
249 list_for_each_entry_safe(entry, aux, &entries, list) {
250 pr_info("loading SSDT from variable %s-%pUl\n", efivar_ssdt,
251 &entry->var.VendorGuid);
252
253 list_del(&entry->list);
254
255 ret = efivar_entry_size(entry, &size);
256 if (ret) {
257 pr_err("failed to get var size\n");
258 goto free_entry;
259 }
260
261 data = kmalloc(size, GFP_KERNEL);
262 if (!data)
263 goto free_entry;
264
265 ret = efivar_entry_get(entry, NULL, &size, data);
266 if (ret) {
267 pr_err("failed to get var data\n");
268 goto free_data;
269 }
270
271 ret = acpi_load_table(data);
272 if (ret) {
273 pr_err("failed to load table: %d\n", ret);
274 goto free_data;
275 }
276
277 goto free_entry;
278
279free_data:
280 kfree(data);
281
282free_entry:
283 kfree(entry);
284 }
285
286 return ret;
287}
288#else
289static inline int efivar_ssdt_load(void) { return 0; }
290#endif
291
Tom Gundersena9499fa2013-02-08 15:37:06 +0000292/*
293 * We register the efi subsystem with the firmware subsystem and the
294 * efivars subsystem with the efi subsystem, if the system was booted with
295 * EFI.
296 */
297static int __init efisubsys_init(void)
298{
299 int error;
300
301 if (!efi_enabled(EFI_BOOT))
302 return 0;
303
304 /* We register the efi directory at /sys/firmware/efi */
305 efi_kobj = kobject_create_and_add("efi", firmware_kobj);
306 if (!efi_kobj) {
307 pr_err("efi: Firmware registration failed.\n");
308 return -ENOMEM;
309 }
310
311 error = generic_ops_register();
312 if (error)
313 goto err_put;
314
Octavian Purdila475fb4e2016-07-08 19:13:12 +0300315 if (efi_enabled(EFI_RUNTIME_SERVICES))
316 efivar_ssdt_load();
317
Tom Gundersena9499fa2013-02-08 15:37:06 +0000318 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
319 if (error) {
320 pr_err("efi: Sysfs attribute export failed with error %d.\n",
321 error);
322 goto err_unregister;
323 }
324
Dave Young926172d2013-12-20 18:02:18 +0800325 error = efi_runtime_map_init(efi_kobj);
326 if (error)
327 goto err_remove_group;
328
Tom Gundersena9499fa2013-02-08 15:37:06 +0000329 /* and the standard mountpoint for efivarfs */
Eric W. Biedermanf9bb4882015-05-13 17:35:41 -0500330 error = sysfs_create_mount_point(efi_kobj, "efivars");
331 if (error) {
Tom Gundersena9499fa2013-02-08 15:37:06 +0000332 pr_err("efivars: Subsystem registration failed.\n");
Tom Gundersena9499fa2013-02-08 15:37:06 +0000333 goto err_remove_group;
334 }
335
336 return 0;
337
338err_remove_group:
339 sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
340err_unregister:
341 generic_ops_unregister();
342err_put:
343 kobject_put(efi_kobj);
344 return error;
345}
346
347subsys_initcall(efisubsys_init);
Leif Lindholm272686b2013-09-05 11:34:54 +0100348
Peter Jones0bb54902015-04-28 18:44:31 -0400349/*
350 * Find the efi memory descriptor for a given physical address. Given a
Matt Flemingdca0f972016-02-27 15:52:50 +0000351 * physical address, determine if it exists within an EFI Memory Map entry,
Peter Jones0bb54902015-04-28 18:44:31 -0400352 * and if so, populate the supplied memory descriptor with the appropriate
353 * data.
354 */
355int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
356{
Matt Flemingdca0f972016-02-27 15:52:50 +0000357 efi_memory_desc_t *md;
Peter Jones0bb54902015-04-28 18:44:31 -0400358
359 if (!efi_enabled(EFI_MEMMAP)) {
360 pr_err_once("EFI_MEMMAP is not enabled.\n");
361 return -EINVAL;
362 }
363
Peter Jones0bb54902015-04-28 18:44:31 -0400364 if (!out_md) {
365 pr_err_once("out_md is null.\n");
366 return -EINVAL;
367 }
Peter Jones0bb54902015-04-28 18:44:31 -0400368
Matt Flemingdca0f972016-02-27 15:52:50 +0000369 for_each_efi_memory_desc(md) {
Peter Jones0bb54902015-04-28 18:44:31 -0400370 u64 size;
371 u64 end;
372
Peter Jones0bb54902015-04-28 18:44:31 -0400373 if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
374 md->type != EFI_BOOT_SERVICES_DATA &&
375 md->type != EFI_RUNTIME_SERVICES_DATA) {
Peter Jones0bb54902015-04-28 18:44:31 -0400376 continue;
377 }
378
379 size = md->num_pages << EFI_PAGE_SHIFT;
380 end = md->phys_addr + size;
381 if (phys_addr >= md->phys_addr && phys_addr < end) {
382 memcpy(out_md, md, sizeof(*out_md));
Peter Jones0bb54902015-04-28 18:44:31 -0400383 return 0;
384 }
Peter Jones0bb54902015-04-28 18:44:31 -0400385 }
386 pr_err_once("requested map not found.\n");
387 return -ENOENT;
388}
389
390/*
391 * Calculate the highest address of an efi memory descriptor.
392 */
393u64 __init efi_mem_desc_end(efi_memory_desc_t *md)
394{
395 u64 size = md->num_pages << EFI_PAGE_SHIFT;
396 u64 end = md->phys_addr + size;
397 return end;
398}
Leif Lindholm272686b2013-09-05 11:34:54 +0100399
Matt Fleming816e7612016-02-29 21:22:52 +0000400void __init __weak efi_arch_mem_reserve(phys_addr_t addr, u64 size) {}
401
402/**
403 * efi_mem_reserve - Reserve an EFI memory region
404 * @addr: Physical address to reserve
405 * @size: Size of reservation
406 *
407 * Mark a region as reserved from general kernel allocation and
408 * prevent it being released by efi_free_boot_services().
409 *
410 * This function should be called drivers once they've parsed EFI
411 * configuration tables to figure out where their data lives, e.g.
412 * efi_esrt_init().
413 */
414void __init efi_mem_reserve(phys_addr_t addr, u64 size)
415{
416 if (!memblock_is_region_reserved(addr, size))
417 memblock_reserve(addr, size);
418
419 /*
420 * Some architectures (x86) reserve all boot services ranges
421 * until efi_free_boot_services() because of buggy firmware
422 * implementations. This means the above memblock_reserve() is
423 * superfluous on x86 and instead what it needs to do is
424 * ensure the @start, @size is not freed.
425 */
426 efi_arch_mem_reserve(addr, size);
427}
428
Leif Lindholm272686b2013-09-05 11:34:54 +0100429static __initdata efi_config_table_type_t common_tables[] = {
430 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
431 {ACPI_TABLE_GUID, "ACPI", &efi.acpi},
432 {HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
433 {MPS_TABLE_GUID, "MPS", &efi.mps},
434 {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
435 {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
Ard Biesheuvele1ccbbc2014-10-14 16:34:47 +0200436 {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
Leif Lindholm272686b2013-09-05 11:34:54 +0100437 {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
Peter Jones0bb54902015-04-28 18:44:31 -0400438 {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
Ard Biesheuvelbf924862015-09-09 10:08:15 +0200439 {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
Ard Biesheuvela604af02016-04-25 21:06:44 +0100440 {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
Daeseok Youn69e60842014-02-13 17:16:36 +0900441 {NULL_GUID, NULL, NULL},
Leif Lindholm272686b2013-09-05 11:34:54 +0100442};
443
444static __init int match_config_table(efi_guid_t *guid,
445 unsigned long table,
446 efi_config_table_type_t *table_types)
447{
Leif Lindholm272686b2013-09-05 11:34:54 +0100448 int i;
449
450 if (table_types) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100451 for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100452 if (!efi_guidcmp(*guid, table_types[i].guid)) {
453 *(table_types[i].ptr) = table;
Ard Biesheuvel801820b2016-04-25 21:06:53 +0100454 if (table_types[i].name)
455 pr_cont(" %s=0x%lx ",
456 table_types[i].name, table);
Leif Lindholm272686b2013-09-05 11:34:54 +0100457 return 1;
458 }
459 }
460 }
461
462 return 0;
463}
464
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200465int __init efi_config_parse_tables(void *config_tables, int count, int sz,
466 efi_config_table_type_t *arch_tables)
467{
468 void *tablep;
469 int i;
470
471 tablep = config_tables;
472 pr_info("");
473 for (i = 0; i < count; i++) {
474 efi_guid_t guid;
475 unsigned long table;
476
477 if (efi_enabled(EFI_64BIT)) {
478 u64 table64;
479 guid = ((efi_config_table_64_t *)tablep)->guid;
480 table64 = ((efi_config_table_64_t *)tablep)->table;
481 table = table64;
482#ifndef CONFIG_64BIT
483 if (table64 >> 32) {
484 pr_cont("\n");
485 pr_err("Table located above 4GB, disabling EFI.\n");
486 return -EINVAL;
487 }
488#endif
489 } else {
490 guid = ((efi_config_table_32_t *)tablep)->guid;
491 table = ((efi_config_table_32_t *)tablep)->table;
492 }
493
494 if (!match_config_table(&guid, table, common_tables))
495 match_config_table(&guid, table, arch_tables);
496
497 tablep += sz;
498 }
499 pr_cont("\n");
500 set_bit(EFI_CONFIG_TABLES, &efi.flags);
Ard Biesheuvela1041712015-09-23 07:29:34 -0700501
502 /* Parse the EFI Properties table if it exists */
503 if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
504 efi_properties_table_t *tbl;
505
506 tbl = early_memremap(efi.properties_table, sizeof(*tbl));
507 if (tbl == NULL) {
508 pr_err("Could not map Properties table!\n");
509 return -ENOMEM;
510 }
511
512 if (tbl->memory_protection_attribute &
513 EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA)
514 set_bit(EFI_NX_PE_DATA, &efi.flags);
515
516 early_memunmap(tbl, sizeof(*tbl));
517 }
518
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200519 return 0;
520}
521
Leif Lindholm272686b2013-09-05 11:34:54 +0100522int __init efi_config_init(efi_config_table_type_t *arch_tables)
523{
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200524 void *config_tables;
525 int sz, ret;
Leif Lindholm272686b2013-09-05 11:34:54 +0100526
527 if (efi_enabled(EFI_64BIT))
528 sz = sizeof(efi_config_table_64_t);
529 else
530 sz = sizeof(efi_config_table_32_t);
531
532 /*
533 * Let's see what config tables the firmware passed to us.
534 */
535 config_tables = early_memremap(efi.systab->tables,
536 efi.systab->nr_tables * sz);
537 if (config_tables == NULL) {
538 pr_err("Could not map Configuration table!\n");
539 return -ENOMEM;
540 }
541
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200542 ret = efi_config_parse_tables(config_tables, efi.systab->nr_tables, sz,
543 arch_tables);
Leif Lindholm272686b2013-09-05 11:34:54 +0100544
Daniel Kiperabc93f82014-06-30 19:52:56 +0200545 early_memunmap(config_tables, efi.systab->nr_tables * sz);
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200546 return ret;
Leif Lindholm272686b2013-09-05 11:34:54 +0100547}
Mark Salter0302f712013-12-30 12:12:12 -0500548
Lee, Chun-Yi28d54022014-07-09 18:39:29 +0800549#ifdef CONFIG_EFI_VARS_MODULE
550static int __init efi_load_efivars(void)
551{
552 struct platform_device *pdev;
553
554 if (!efi_enabled(EFI_RUNTIME_SERVICES))
555 return 0;
556
557 pdev = platform_device_register_simple("efivars", 0, NULL, 0);
558 return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
559}
560device_initcall(efi_load_efivars);
561#endif
562
Mark Salter0302f712013-12-30 12:12:12 -0500563#ifdef CONFIG_EFI_PARAMS_FROM_FDT
564
565#define UEFI_PARAM(name, prop, field) \
566 { \
567 { name }, \
568 { prop }, \
569 offsetof(struct efi_fdt_params, field), \
570 FIELD_SIZEOF(struct efi_fdt_params, field) \
571 }
572
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800573struct params {
Mark Salter0302f712013-12-30 12:12:12 -0500574 const char name[32];
575 const char propname[32];
576 int offset;
577 int size;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800578};
579
580static __initdata struct params fdt_params[] = {
Mark Salter0302f712013-12-30 12:12:12 -0500581 UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
582 UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
583 UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
584 UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
585 UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
586};
587
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800588static __initdata struct params xen_fdt_params[] = {
589 UEFI_PARAM("System Table", "xen,uefi-system-table", system_table),
590 UEFI_PARAM("MemMap Address", "xen,uefi-mmap-start", mmap),
591 UEFI_PARAM("MemMap Size", "xen,uefi-mmap-size", mmap_size),
592 UEFI_PARAM("MemMap Desc. Size", "xen,uefi-mmap-desc-size", desc_size),
593 UEFI_PARAM("MemMap Desc. Version", "xen,uefi-mmap-desc-ver", desc_ver)
594};
595
596#define EFI_FDT_PARAMS_SIZE ARRAY_SIZE(fdt_params)
597
598static __initdata struct {
599 const char *uname;
600 const char *subnode;
601 struct params *params;
602} dt_params[] = {
603 { "hypervisor", "uefi", xen_fdt_params },
604 { "chosen", NULL, fdt_params },
605};
606
Mark Salter0302f712013-12-30 12:12:12 -0500607struct param_info {
Catalin Marinas29e24352014-07-08 16:54:18 +0100608 int found;
Mark Salter0302f712013-12-30 12:12:12 -0500609 void *params;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800610 const char *missing;
Mark Salter0302f712013-12-30 12:12:12 -0500611};
612
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800613static int __init __find_uefi_params(unsigned long node,
614 struct param_info *info,
615 struct params *params)
Mark Salter0302f712013-12-30 12:12:12 -0500616{
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100617 const void *prop;
618 void *dest;
Mark Salter0302f712013-12-30 12:12:12 -0500619 u64 val;
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100620 int i, len;
Mark Salter0302f712013-12-30 12:12:12 -0500621
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800622 for (i = 0; i < EFI_FDT_PARAMS_SIZE; i++) {
623 prop = of_get_flat_dt_prop(node, params[i].propname, &len);
624 if (!prop) {
625 info->missing = params[i].name;
Mark Salter0302f712013-12-30 12:12:12 -0500626 return 0;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800627 }
628
629 dest = info->params + params[i].offset;
Catalin Marinas29e24352014-07-08 16:54:18 +0100630 info->found++;
Mark Salter0302f712013-12-30 12:12:12 -0500631
632 val = of_read_number(prop, len / sizeof(u32));
633
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800634 if (params[i].size == sizeof(u32))
Mark Salter0302f712013-12-30 12:12:12 -0500635 *(u32 *)dest = val;
636 else
637 *(u64 *)dest = val;
638
Leif Lindholm7968c0e2015-08-26 14:24:58 +0100639 if (efi_enabled(EFI_DBG))
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800640 pr_info(" %s: 0x%0*llx\n", params[i].name,
641 params[i].size * 2, val);
Mark Salter0302f712013-12-30 12:12:12 -0500642 }
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800643
Mark Salter0302f712013-12-30 12:12:12 -0500644 return 1;
645}
646
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800647static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
648 int depth, void *data)
649{
650 struct param_info *info = data;
651 int i;
652
653 for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
654 const char *subnode = dt_params[i].subnode;
655
656 if (depth != 1 || strcmp(uname, dt_params[i].uname) != 0) {
657 info->missing = dt_params[i].params[0].name;
658 continue;
659 }
660
661 if (subnode) {
Andrzej Hajda4af9ed52016-08-30 12:41:37 +0200662 int err = of_get_flat_dt_subnode_by_name(node, subnode);
663
664 if (err < 0)
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800665 return 0;
Andrzej Hajda4af9ed52016-08-30 12:41:37 +0200666
667 node = err;
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800668 }
669
670 return __find_uefi_params(node, info, dt_params[i].params);
671 }
672
673 return 0;
674}
675
Leif Lindholm7968c0e2015-08-26 14:24:58 +0100676int __init efi_get_fdt_params(struct efi_fdt_params *params)
Mark Salter0302f712013-12-30 12:12:12 -0500677{
678 struct param_info info;
Catalin Marinas29e24352014-07-08 16:54:18 +0100679 int ret;
680
681 pr_info("Getting EFI parameters from FDT:\n");
Mark Salter0302f712013-12-30 12:12:12 -0500682
Catalin Marinas29e24352014-07-08 16:54:18 +0100683 info.found = 0;
Mark Salter0302f712013-12-30 12:12:12 -0500684 info.params = params;
685
Catalin Marinas29e24352014-07-08 16:54:18 +0100686 ret = of_scan_flat_dt(fdt_find_uefi_params, &info);
687 if (!info.found)
688 pr_info("UEFI not found.\n");
689 else if (!ret)
690 pr_err("Can't find '%s' in device tree!\n",
Shannon Zhao0cac5c32016-05-12 20:19:54 +0800691 info.missing);
Catalin Marinas29e24352014-07-08 16:54:18 +0100692
693 return ret;
Mark Salter0302f712013-12-30 12:12:12 -0500694}
695#endif /* CONFIG_EFI_PARAMS_FROM_FDT */
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200696
697static __initdata char memory_type_name[][20] = {
698 "Reserved",
699 "Loader Code",
700 "Loader Data",
701 "Boot Code",
702 "Boot Data",
703 "Runtime Code",
704 "Runtime Data",
705 "Conventional Memory",
706 "Unusable Memory",
707 "ACPI Reclaim Memory",
708 "ACPI Memory NVS",
709 "Memory Mapped I/O",
710 "MMIO Port Space",
Robert Elliott35575e02016-02-01 22:07:07 +0000711 "PAL Code",
712 "Persistent Memory",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200713};
714
715char * __init efi_md_typeattr_format(char *buf, size_t size,
716 const efi_memory_desc_t *md)
717{
718 char *pos;
719 int type_len;
720 u64 attr;
721
722 pos = buf;
723 if (md->type >= ARRAY_SIZE(memory_type_name))
724 type_len = snprintf(pos, size, "[type=%u", md->type);
725 else
726 type_len = snprintf(pos, size, "[%-*s",
727 (int)(sizeof(memory_type_name[0]) - 1),
728 memory_type_name[md->type]);
729 if (type_len >= size)
730 return buf;
731
732 pos += type_len;
733 size -= type_len;
734
735 attr = md->attribute;
736 if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
Ard Biesheuvel87db73ae2015-08-07 09:36:54 +0100737 EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO |
738 EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP |
Robert Elliottc016ca02016-02-01 22:07:06 +0000739 EFI_MEMORY_NV |
Taku Izumi8be44322015-08-27 02:11:19 +0900740 EFI_MEMORY_RUNTIME | EFI_MEMORY_MORE_RELIABLE))
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200741 snprintf(pos, size, "|attr=0x%016llx]",
742 (unsigned long long)attr);
743 else
Robert Elliottc016ca02016-02-01 22:07:06 +0000744 snprintf(pos, size,
745 "|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200746 attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
Taku Izumi8be44322015-08-27 02:11:19 +0900747 attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "",
Robert Elliottc016ca02016-02-01 22:07:06 +0000748 attr & EFI_MEMORY_NV ? "NV" : "",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200749 attr & EFI_MEMORY_XP ? "XP" : "",
750 attr & EFI_MEMORY_RP ? "RP" : "",
751 attr & EFI_MEMORY_WP ? "WP" : "",
Ard Biesheuvel87db73ae2015-08-07 09:36:54 +0100752 attr & EFI_MEMORY_RO ? "RO" : "",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200753 attr & EFI_MEMORY_UCE ? "UCE" : "",
754 attr & EFI_MEMORY_WB ? "WB" : "",
755 attr & EFI_MEMORY_WT ? "WT" : "",
756 attr & EFI_MEMORY_WC ? "WC" : "",
757 attr & EFI_MEMORY_UC ? "UC" : "");
758 return buf;
759}
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100760
761/*
762 * efi_mem_attributes - lookup memmap attributes for physical address
763 * @phys_addr: the physical address to lookup
764 *
765 * Search in the EFI memory map for the region covering
766 * @phys_addr. Returns the EFI memory attributes if the region
767 * was found in the memory map, 0 otherwise.
768 *
769 * Despite being marked __weak, most architectures should *not*
770 * override this function. It is __weak solely for the benefit
771 * of ia64 which has a funky EFI memory map that doesn't work
772 * the same way as other architectures.
773 */
774u64 __weak efi_mem_attributes(unsigned long phys_addr)
775{
776 efi_memory_desc_t *md;
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100777
778 if (!efi_enabled(EFI_MEMMAP))
779 return 0;
780
Matt Fleming78ce2482016-04-25 21:06:38 +0100781 for_each_efi_memory_desc(md) {
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100782 if ((md->phys_addr <= phys_addr) &&
783 (phys_addr < (md->phys_addr +
784 (md->num_pages << EFI_PAGE_SHIFT))))
785 return md->attribute;
786 }
787 return 0;
788}
Matt Fleming806b0352016-04-25 21:06:58 +0100789
790int efi_status_to_err(efi_status_t status)
791{
792 int err;
793
794 switch (status) {
795 case EFI_SUCCESS:
796 err = 0;
797 break;
798 case EFI_INVALID_PARAMETER:
799 err = -EINVAL;
800 break;
801 case EFI_OUT_OF_RESOURCES:
802 err = -ENOSPC;
803 break;
804 case EFI_DEVICE_ERROR:
805 err = -EIO;
806 break;
807 case EFI_WRITE_PROTECTED:
808 err = -EROFS;
809 break;
810 case EFI_SECURITY_VIOLATION:
811 err = -EACCES;
812 break;
813 case EFI_NOT_FOUND:
814 err = -ENOENT;
815 break;
Ard Biesheuveldce48e32016-07-15 21:36:31 +0200816 case EFI_ABORTED:
817 err = -EINTR;
818 break;
Matt Fleming806b0352016-04-25 21:06:58 +0100819 default:
820 err = -EINVAL;
821 }
822
823 return err;
824}