1/*
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
16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
18#include <linux/kobject.h>
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/device.h>
22#include <linux/efi.h>
23#include <linux/of.h>
24#include <linux/of_fdt.h>
25#include <linux/io.h>
26#include <linux/platform_device.h>
27
28struct efi __read_mostly efi = {
29	.mps        = EFI_INVALID_TABLE_ADDR,
30	.acpi       = EFI_INVALID_TABLE_ADDR,
31	.acpi20     = EFI_INVALID_TABLE_ADDR,
32	.smbios     = EFI_INVALID_TABLE_ADDR,
33	.smbios3    = EFI_INVALID_TABLE_ADDR,
34	.sal_systab = EFI_INVALID_TABLE_ADDR,
35	.boot_info  = EFI_INVALID_TABLE_ADDR,
36	.hcdp       = EFI_INVALID_TABLE_ADDR,
37	.uga        = EFI_INVALID_TABLE_ADDR,
38	.uv_systab  = EFI_INVALID_TABLE_ADDR,
39	.fw_vendor  = EFI_INVALID_TABLE_ADDR,
40	.runtime    = EFI_INVALID_TABLE_ADDR,
41	.config_table  = EFI_INVALID_TABLE_ADDR,
42};
43EXPORT_SYMBOL(efi);
44
45static bool disable_runtime;
46static int __init setup_noefi(char *arg)
47{
48	disable_runtime = true;
49	return 0;
50}
51early_param("noefi", setup_noefi);
52
53bool efi_runtime_disabled(void)
54{
55	return disable_runtime;
56}
57
58static int __init parse_efi_cmdline(char *str)
59{
60	if (!str) {
61		pr_warn("need at least one option\n");
62		return -EINVAL;
63	}
64
65	if (parse_option_str(str, "noruntime"))
66		disable_runtime = true;
67
68	return 0;
69}
70early_param("efi", parse_efi_cmdline);
71
72static struct kobject *efi_kobj;
73
74/*
75 * Let's not leave out systab information that snuck into
76 * the efivars driver
77 */
78static ssize_t systab_show(struct kobject *kobj,
79			   struct kobj_attribute *attr, char *buf)
80{
81	char *str = buf;
82
83	if (!kobj || !buf)
84		return -EINVAL;
85
86	if (efi.mps != EFI_INVALID_TABLE_ADDR)
87		str += sprintf(str, "MPS=0x%lx\n", efi.mps);
88	if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
89		str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
90	if (efi.acpi != EFI_INVALID_TABLE_ADDR)
91		str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
92	if (efi.smbios != EFI_INVALID_TABLE_ADDR)
93		str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
94	if (efi.smbios3 != EFI_INVALID_TABLE_ADDR)
95		str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3);
96	if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
97		str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
98	if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
99		str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
100	if (efi.uga != EFI_INVALID_TABLE_ADDR)
101		str += sprintf(str, "UGA=0x%lx\n", efi.uga);
102
103	return str - buf;
104}
105
106static struct kobj_attribute efi_attr_systab =
107			__ATTR(systab, 0400, systab_show, NULL);
108
109#define EFI_FIELD(var) efi.var
110
111#define EFI_ATTR_SHOW(name) \
112static ssize_t name##_show(struct kobject *kobj, \
113				struct kobj_attribute *attr, char *buf) \
114{ \
115	return sprintf(buf, "0x%lx\n", EFI_FIELD(name)); \
116}
117
118EFI_ATTR_SHOW(fw_vendor);
119EFI_ATTR_SHOW(runtime);
120EFI_ATTR_SHOW(config_table);
121
122static ssize_t fw_platform_size_show(struct kobject *kobj,
123				     struct kobj_attribute *attr, char *buf)
124{
125	return sprintf(buf, "%d\n", efi_enabled(EFI_64BIT) ? 64 : 32);
126}
127
128static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor);
129static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
130static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);
131static struct kobj_attribute efi_attr_fw_platform_size =
132	__ATTR_RO(fw_platform_size);
133
134static struct attribute *efi_subsys_attrs[] = {
135	&efi_attr_systab.attr,
136	&efi_attr_fw_vendor.attr,
137	&efi_attr_runtime.attr,
138	&efi_attr_config_table.attr,
139	&efi_attr_fw_platform_size.attr,
140	NULL,
141};
142
143static umode_t efi_attr_is_visible(struct kobject *kobj,
144				   struct attribute *attr, int n)
145{
146	if (attr == &efi_attr_fw_vendor.attr) {
147		if (efi_enabled(EFI_PARAVIRT) ||
148				efi.fw_vendor == EFI_INVALID_TABLE_ADDR)
149			return 0;
150	} else if (attr == &efi_attr_runtime.attr) {
151		if (efi.runtime == EFI_INVALID_TABLE_ADDR)
152			return 0;
153	} else if (attr == &efi_attr_config_table.attr) {
154		if (efi.config_table == EFI_INVALID_TABLE_ADDR)
155			return 0;
156	}
157
158	return attr->mode;
159}
160
161static struct attribute_group efi_subsys_attr_group = {
162	.attrs = efi_subsys_attrs,
163	.is_visible = efi_attr_is_visible,
164};
165
166static struct efivars generic_efivars;
167static struct efivar_operations generic_ops;
168
169static int generic_ops_register(void)
170{
171	generic_ops.get_variable = efi.get_variable;
172	generic_ops.set_variable = efi.set_variable;
173	generic_ops.get_next_variable = efi.get_next_variable;
174	generic_ops.query_variable_store = efi_query_variable_store;
175
176	return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
177}
178
179static void generic_ops_unregister(void)
180{
181	efivars_unregister(&generic_efivars);
182}
183
184/*
185 * We register the efi subsystem with the firmware subsystem and the
186 * efivars subsystem with the efi subsystem, if the system was booted with
187 * EFI.
188 */
189static int __init efisubsys_init(void)
190{
191	int error;
192
193	if (!efi_enabled(EFI_BOOT))
194		return 0;
195
196	/* We register the efi directory at /sys/firmware/efi */
197	efi_kobj = kobject_create_and_add("efi", firmware_kobj);
198	if (!efi_kobj) {
199		pr_err("efi: Firmware registration failed.\n");
200		return -ENOMEM;
201	}
202
203	error = generic_ops_register();
204	if (error)
205		goto err_put;
206
207	error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
208	if (error) {
209		pr_err("efi: Sysfs attribute export failed with error %d.\n",
210		       error);
211		goto err_unregister;
212	}
213
214	error = efi_runtime_map_init(efi_kobj);
215	if (error)
216		goto err_remove_group;
217
218	/* and the standard mountpoint for efivarfs */
219	error = sysfs_create_mount_point(efi_kobj, "efivars");
220	if (error) {
221		pr_err("efivars: Subsystem registration failed.\n");
222		goto err_remove_group;
223	}
224
225	return 0;
226
227err_remove_group:
228	sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
229err_unregister:
230	generic_ops_unregister();
231err_put:
232	kobject_put(efi_kobj);
233	return error;
234}
235
236subsys_initcall(efisubsys_init);
237
238
239/*
240 * We can't ioremap data in EFI boot services RAM, because we've already mapped
241 * it as RAM.  So, look it up in the existing EFI memory map instead.  Only
242 * callable after efi_enter_virtual_mode and before efi_free_boot_services.
243 */
244void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
245{
246	struct efi_memory_map *map;
247	void *p;
248	map = efi.memmap;
249	if (!map)
250		return NULL;
251	if (WARN_ON(!map->map))
252		return NULL;
253	for (p = map->map; p < map->map_end; p += map->desc_size) {
254		efi_memory_desc_t *md = p;
255		u64 size = md->num_pages << EFI_PAGE_SHIFT;
256		u64 end = md->phys_addr + size;
257		if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
258		    md->type != EFI_BOOT_SERVICES_CODE &&
259		    md->type != EFI_BOOT_SERVICES_DATA)
260			continue;
261		if (!md->virt_addr)
262			continue;
263		if (phys_addr >= md->phys_addr && phys_addr < end) {
264			phys_addr += md->virt_addr - md->phys_addr;
265			return (__force void __iomem *)(unsigned long)phys_addr;
266		}
267	}
268	return NULL;
269}
270
271static __initdata efi_config_table_type_t common_tables[] = {
272	{ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
273	{ACPI_TABLE_GUID, "ACPI", &efi.acpi},
274	{HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
275	{MPS_TABLE_GUID, "MPS", &efi.mps},
276	{SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
277	{SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
278	{SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
279	{UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
280	{NULL_GUID, NULL, NULL},
281};
282
283static __init int match_config_table(efi_guid_t *guid,
284				     unsigned long table,
285				     efi_config_table_type_t *table_types)
286{
287	int i;
288
289	if (table_types) {
290		for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
291			if (!efi_guidcmp(*guid, table_types[i].guid)) {
292				*(table_types[i].ptr) = table;
293				pr_cont(" %s=0x%lx ",
294					table_types[i].name, table);
295				return 1;
296			}
297		}
298	}
299
300	return 0;
301}
302
303int __init efi_config_parse_tables(void *config_tables, int count, int sz,
304				   efi_config_table_type_t *arch_tables)
305{
306	void *tablep;
307	int i;
308
309	tablep = config_tables;
310	pr_info("");
311	for (i = 0; i < count; i++) {
312		efi_guid_t guid;
313		unsigned long table;
314
315		if (efi_enabled(EFI_64BIT)) {
316			u64 table64;
317			guid = ((efi_config_table_64_t *)tablep)->guid;
318			table64 = ((efi_config_table_64_t *)tablep)->table;
319			table = table64;
320#ifndef CONFIG_64BIT
321			if (table64 >> 32) {
322				pr_cont("\n");
323				pr_err("Table located above 4GB, disabling EFI.\n");
324				return -EINVAL;
325			}
326#endif
327		} else {
328			guid = ((efi_config_table_32_t *)tablep)->guid;
329			table = ((efi_config_table_32_t *)tablep)->table;
330		}
331
332		if (!match_config_table(&guid, table, common_tables))
333			match_config_table(&guid, table, arch_tables);
334
335		tablep += sz;
336	}
337	pr_cont("\n");
338	set_bit(EFI_CONFIG_TABLES, &efi.flags);
339	return 0;
340}
341
342int __init efi_config_init(efi_config_table_type_t *arch_tables)
343{
344	void *config_tables;
345	int sz, ret;
346
347	if (efi_enabled(EFI_64BIT))
348		sz = sizeof(efi_config_table_64_t);
349	else
350		sz = sizeof(efi_config_table_32_t);
351
352	/*
353	 * Let's see what config tables the firmware passed to us.
354	 */
355	config_tables = early_memremap(efi.systab->tables,
356				       efi.systab->nr_tables * sz);
357	if (config_tables == NULL) {
358		pr_err("Could not map Configuration table!\n");
359		return -ENOMEM;
360	}
361
362	ret = efi_config_parse_tables(config_tables, efi.systab->nr_tables, sz,
363				      arch_tables);
364
365	early_memunmap(config_tables, efi.systab->nr_tables * sz);
366	return ret;
367}
368
369#ifdef CONFIG_EFI_VARS_MODULE
370static int __init efi_load_efivars(void)
371{
372	struct platform_device *pdev;
373
374	if (!efi_enabled(EFI_RUNTIME_SERVICES))
375		return 0;
376
377	pdev = platform_device_register_simple("efivars", 0, NULL, 0);
378	return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
379}
380device_initcall(efi_load_efivars);
381#endif
382
383#ifdef CONFIG_EFI_PARAMS_FROM_FDT
384
385#define UEFI_PARAM(name, prop, field)			   \
386	{						   \
387		{ name },				   \
388		{ prop },				   \
389		offsetof(struct efi_fdt_params, field),    \
390		FIELD_SIZEOF(struct efi_fdt_params, field) \
391	}
392
393static __initdata struct {
394	const char name[32];
395	const char propname[32];
396	int offset;
397	int size;
398} dt_params[] = {
399	UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
400	UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
401	UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
402	UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
403	UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
404};
405
406struct param_info {
407	int verbose;
408	int found;
409	void *params;
410};
411
412static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
413				       int depth, void *data)
414{
415	struct param_info *info = data;
416	const void *prop;
417	void *dest;
418	u64 val;
419	int i, len;
420
421	if (depth != 1 || strcmp(uname, "chosen") != 0)
422		return 0;
423
424	for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
425		prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
426		if (!prop)
427			return 0;
428		dest = info->params + dt_params[i].offset;
429		info->found++;
430
431		val = of_read_number(prop, len / sizeof(u32));
432
433		if (dt_params[i].size == sizeof(u32))
434			*(u32 *)dest = val;
435		else
436			*(u64 *)dest = val;
437
438		if (info->verbose)
439			pr_info("  %s: 0x%0*llx\n", dt_params[i].name,
440				dt_params[i].size * 2, val);
441	}
442	return 1;
443}
444
445int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
446{
447	struct param_info info;
448	int ret;
449
450	pr_info("Getting EFI parameters from FDT:\n");
451
452	info.verbose = verbose;
453	info.found = 0;
454	info.params = params;
455
456	ret = of_scan_flat_dt(fdt_find_uefi_params, &info);
457	if (!info.found)
458		pr_info("UEFI not found.\n");
459	else if (!ret)
460		pr_err("Can't find '%s' in device tree!\n",
461		       dt_params[info.found].name);
462
463	return ret;
464}
465#endif /* CONFIG_EFI_PARAMS_FROM_FDT */
466
467static __initdata char memory_type_name[][20] = {
468	"Reserved",
469	"Loader Code",
470	"Loader Data",
471	"Boot Code",
472	"Boot Data",
473	"Runtime Code",
474	"Runtime Data",
475	"Conventional Memory",
476	"Unusable Memory",
477	"ACPI Reclaim Memory",
478	"ACPI Memory NVS",
479	"Memory Mapped I/O",
480	"MMIO Port Space",
481	"PAL Code"
482};
483
484char * __init efi_md_typeattr_format(char *buf, size_t size,
485				     const efi_memory_desc_t *md)
486{
487	char *pos;
488	int type_len;
489	u64 attr;
490
491	pos = buf;
492	if (md->type >= ARRAY_SIZE(memory_type_name))
493		type_len = snprintf(pos, size, "[type=%u", md->type);
494	else
495		type_len = snprintf(pos, size, "[%-*s",
496				    (int)(sizeof(memory_type_name[0]) - 1),
497				    memory_type_name[md->type]);
498	if (type_len >= size)
499		return buf;
500
501	pos += type_len;
502	size -= type_len;
503
504	attr = md->attribute;
505	if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
506		     EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP |
507		     EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RUNTIME))
508		snprintf(pos, size, "|attr=0x%016llx]",
509			 (unsigned long long)attr);
510	else
511		snprintf(pos, size, "|%3s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
512			 attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
513			 attr & EFI_MEMORY_XP      ? "XP"  : "",
514			 attr & EFI_MEMORY_RP      ? "RP"  : "",
515			 attr & EFI_MEMORY_WP      ? "WP"  : "",
516			 attr & EFI_MEMORY_UCE     ? "UCE" : "",
517			 attr & EFI_MEMORY_WB      ? "WB"  : "",
518			 attr & EFI_MEMORY_WT      ? "WT"  : "",
519			 attr & EFI_MEMORY_WC      ? "WC"  : "",
520			 attr & EFI_MEMORY_UC      ? "UC"  : "");
521	return buf;
522}
523