blob: f8f126812656705a4ed21409613f20fdf80c19b6 [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>
Leif Lindholm272686b2013-09-05 11:34:54 +010027
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 .sal_systab = EFI_INVALID_TABLE_ADDR,
34 .boot_info = EFI_INVALID_TABLE_ADDR,
35 .hcdp = EFI_INVALID_TABLE_ADDR,
36 .uga = EFI_INVALID_TABLE_ADDR,
37 .uv_systab = EFI_INVALID_TABLE_ADDR,
Dave Younga0998eb2013-12-20 18:02:17 +080038 .fw_vendor = EFI_INVALID_TABLE_ADDR,
39 .runtime = EFI_INVALID_TABLE_ADDR,
40 .config_table = EFI_INVALID_TABLE_ADDR,
Leif Lindholm272686b2013-09-05 11:34:54 +010041};
42EXPORT_SYMBOL(efi);
Tom Gundersena9499fa2013-02-08 15:37:06 +000043
Dave Youngb2e0a542014-08-14 17:15:26 +080044static bool disable_runtime;
45static int __init setup_noefi(char *arg)
46{
47 disable_runtime = true;
48 return 0;
49}
50early_param("noefi", setup_noefi);
51
52bool efi_runtime_disabled(void)
53{
54 return disable_runtime;
55}
56
Dave Young5ae36832014-08-14 17:15:28 +080057static int __init parse_efi_cmdline(char *str)
58{
59 if (parse_option_str(str, "noruntime"))
60 disable_runtime = true;
61
62 return 0;
63}
64early_param("efi", parse_efi_cmdline);
65
Tom Gundersena9499fa2013-02-08 15:37:06 +000066static struct kobject *efi_kobj;
67static struct kobject *efivars_kobj;
68
69/*
70 * Let's not leave out systab information that snuck into
71 * the efivars driver
72 */
73static ssize_t systab_show(struct kobject *kobj,
74 struct kobj_attribute *attr, char *buf)
75{
76 char *str = buf;
77
78 if (!kobj || !buf)
79 return -EINVAL;
80
81 if (efi.mps != EFI_INVALID_TABLE_ADDR)
82 str += sprintf(str, "MPS=0x%lx\n", efi.mps);
83 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
84 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
85 if (efi.acpi != EFI_INVALID_TABLE_ADDR)
86 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
87 if (efi.smbios != EFI_INVALID_TABLE_ADDR)
88 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
89 if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
90 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
91 if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
92 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
93 if (efi.uga != EFI_INVALID_TABLE_ADDR)
94 str += sprintf(str, "UGA=0x%lx\n", efi.uga);
95
96 return str - buf;
97}
98
99static struct kobj_attribute efi_attr_systab =
100 __ATTR(systab, 0400, systab_show, NULL);
101
Dave Younga0998eb2013-12-20 18:02:17 +0800102#define EFI_FIELD(var) efi.var
103
104#define EFI_ATTR_SHOW(name) \
105static ssize_t name##_show(struct kobject *kobj, \
106 struct kobj_attribute *attr, char *buf) \
107{ \
108 return sprintf(buf, "0x%lx\n", EFI_FIELD(name)); \
109}
110
111EFI_ATTR_SHOW(fw_vendor);
112EFI_ATTR_SHOW(runtime);
113EFI_ATTR_SHOW(config_table);
114
Steve McIntyre2859dff2015-01-09 15:29:53 +0000115static ssize_t fw_platform_size_show(struct kobject *kobj,
116 struct kobj_attribute *attr, char *buf)
117{
118 return sprintf(buf, "%d\n", efi_enabled(EFI_64BIT) ? 64 : 32);
119}
120
Dave Younga0998eb2013-12-20 18:02:17 +0800121static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor);
122static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
123static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);
Steve McIntyre2859dff2015-01-09 15:29:53 +0000124static struct kobj_attribute efi_attr_fw_platform_size =
125 __ATTR_RO(fw_platform_size);
Dave Younga0998eb2013-12-20 18:02:17 +0800126
Tom Gundersena9499fa2013-02-08 15:37:06 +0000127static struct attribute *efi_subsys_attrs[] = {
128 &efi_attr_systab.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800129 &efi_attr_fw_vendor.attr,
130 &efi_attr_runtime.attr,
131 &efi_attr_config_table.attr,
Steve McIntyre2859dff2015-01-09 15:29:53 +0000132 &efi_attr_fw_platform_size.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800133 NULL,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000134};
135
Dave Younga0998eb2013-12-20 18:02:17 +0800136static umode_t efi_attr_is_visible(struct kobject *kobj,
137 struct attribute *attr, int n)
138{
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200139 if (attr == &efi_attr_fw_vendor.attr) {
140 if (efi_enabled(EFI_PARAVIRT) ||
141 efi.fw_vendor == EFI_INVALID_TABLE_ADDR)
142 return 0;
143 } else if (attr == &efi_attr_runtime.attr) {
144 if (efi.runtime == EFI_INVALID_TABLE_ADDR)
145 return 0;
146 } else if (attr == &efi_attr_config_table.attr) {
147 if (efi.config_table == EFI_INVALID_TABLE_ADDR)
148 return 0;
149 }
Dave Younga0998eb2013-12-20 18:02:17 +0800150
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200151 return attr->mode;
Dave Younga0998eb2013-12-20 18:02:17 +0800152}
153
Tom Gundersena9499fa2013-02-08 15:37:06 +0000154static struct attribute_group efi_subsys_attr_group = {
155 .attrs = efi_subsys_attrs,
Dave Younga0998eb2013-12-20 18:02:17 +0800156 .is_visible = efi_attr_is_visible,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000157};
158
159static struct efivars generic_efivars;
160static struct efivar_operations generic_ops;
161
162static int generic_ops_register(void)
163{
164 generic_ops.get_variable = efi.get_variable;
165 generic_ops.set_variable = efi.set_variable;
166 generic_ops.get_next_variable = efi.get_next_variable;
Matt Fleminga614e192013-04-30 11:30:24 +0100167 generic_ops.query_variable_store = efi_query_variable_store;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000168
169 return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
170}
171
172static void generic_ops_unregister(void)
173{
174 efivars_unregister(&generic_efivars);
175}
176
177/*
178 * We register the efi subsystem with the firmware subsystem and the
179 * efivars subsystem with the efi subsystem, if the system was booted with
180 * EFI.
181 */
182static int __init efisubsys_init(void)
183{
184 int error;
185
186 if (!efi_enabled(EFI_BOOT))
187 return 0;
188
189 /* We register the efi directory at /sys/firmware/efi */
190 efi_kobj = kobject_create_and_add("efi", firmware_kobj);
191 if (!efi_kobj) {
192 pr_err("efi: Firmware registration failed.\n");
193 return -ENOMEM;
194 }
195
196 error = generic_ops_register();
197 if (error)
198 goto err_put;
199
200 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
201 if (error) {
202 pr_err("efi: Sysfs attribute export failed with error %d.\n",
203 error);
204 goto err_unregister;
205 }
206
Dave Young926172d2013-12-20 18:02:18 +0800207 error = efi_runtime_map_init(efi_kobj);
208 if (error)
209 goto err_remove_group;
210
Tom Gundersena9499fa2013-02-08 15:37:06 +0000211 /* and the standard mountpoint for efivarfs */
212 efivars_kobj = kobject_create_and_add("efivars", efi_kobj);
213 if (!efivars_kobj) {
214 pr_err("efivars: Subsystem registration failed.\n");
215 error = -ENOMEM;
216 goto err_remove_group;
217 }
218
219 return 0;
220
221err_remove_group:
222 sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
223err_unregister:
224 generic_ops_unregister();
225err_put:
226 kobject_put(efi_kobj);
227 return error;
228}
229
230subsys_initcall(efisubsys_init);
Leif Lindholm272686b2013-09-05 11:34:54 +0100231
232
Leif Lindholm258f6fd2013-09-05 11:34:55 +0100233/*
234 * We can't ioremap data in EFI boot services RAM, because we've already mapped
235 * it as RAM. So, look it up in the existing EFI memory map instead. Only
236 * callable after efi_enter_virtual_mode and before efi_free_boot_services.
237 */
238void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
239{
240 struct efi_memory_map *map;
241 void *p;
242 map = efi.memmap;
243 if (!map)
244 return NULL;
245 if (WARN_ON(!map->map))
246 return NULL;
247 for (p = map->map; p < map->map_end; p += map->desc_size) {
248 efi_memory_desc_t *md = p;
249 u64 size = md->num_pages << EFI_PAGE_SHIFT;
250 u64 end = md->phys_addr + size;
251 if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
252 md->type != EFI_BOOT_SERVICES_CODE &&
253 md->type != EFI_BOOT_SERVICES_DATA)
254 continue;
255 if (!md->virt_addr)
256 continue;
257 if (phys_addr >= md->phys_addr && phys_addr < end) {
258 phys_addr += md->virt_addr - md->phys_addr;
259 return (__force void __iomem *)(unsigned long)phys_addr;
260 }
261 }
262 return NULL;
263}
264
Leif Lindholm272686b2013-09-05 11:34:54 +0100265static __initdata efi_config_table_type_t common_tables[] = {
266 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
267 {ACPI_TABLE_GUID, "ACPI", &efi.acpi},
268 {HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
269 {MPS_TABLE_GUID, "MPS", &efi.mps},
270 {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
271 {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
272 {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
Daeseok Youn69e60842014-02-13 17:16:36 +0900273 {NULL_GUID, NULL, NULL},
Leif Lindholm272686b2013-09-05 11:34:54 +0100274};
275
276static __init int match_config_table(efi_guid_t *guid,
277 unsigned long table,
278 efi_config_table_type_t *table_types)
279{
Leif Lindholm272686b2013-09-05 11:34:54 +0100280 int i;
281
282 if (table_types) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100283 for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100284 if (!efi_guidcmp(*guid, table_types[i].guid)) {
285 *(table_types[i].ptr) = table;
286 pr_cont(" %s=0x%lx ",
287 table_types[i].name, table);
288 return 1;
289 }
290 }
291 }
292
293 return 0;
294}
295
296int __init efi_config_init(efi_config_table_type_t *arch_tables)
297{
298 void *config_tables, *tablep;
299 int i, sz;
300
301 if (efi_enabled(EFI_64BIT))
302 sz = sizeof(efi_config_table_64_t);
303 else
304 sz = sizeof(efi_config_table_32_t);
305
306 /*
307 * Let's see what config tables the firmware passed to us.
308 */
309 config_tables = early_memremap(efi.systab->tables,
310 efi.systab->nr_tables * sz);
311 if (config_tables == NULL) {
312 pr_err("Could not map Configuration table!\n");
313 return -ENOMEM;
314 }
315
316 tablep = config_tables;
317 pr_info("");
318 for (i = 0; i < efi.systab->nr_tables; i++) {
319 efi_guid_t guid;
320 unsigned long table;
321
322 if (efi_enabled(EFI_64BIT)) {
323 u64 table64;
324 guid = ((efi_config_table_64_t *)tablep)->guid;
325 table64 = ((efi_config_table_64_t *)tablep)->table;
326 table = table64;
327#ifndef CONFIG_64BIT
328 if (table64 >> 32) {
329 pr_cont("\n");
330 pr_err("Table located above 4GB, disabling EFI.\n");
Daniel Kiperabc93f82014-06-30 19:52:56 +0200331 early_memunmap(config_tables,
Leif Lindholm272686b2013-09-05 11:34:54 +0100332 efi.systab->nr_tables * sz);
333 return -EINVAL;
334 }
335#endif
336 } else {
337 guid = ((efi_config_table_32_t *)tablep)->guid;
338 table = ((efi_config_table_32_t *)tablep)->table;
339 }
340
341 if (!match_config_table(&guid, table, common_tables))
342 match_config_table(&guid, table, arch_tables);
343
344 tablep += sz;
345 }
346 pr_cont("\n");
Daniel Kiperabc93f82014-06-30 19:52:56 +0200347 early_memunmap(config_tables, efi.systab->nr_tables * sz);
Matt Fleming0f8093a2014-01-15 13:36:33 +0000348
349 set_bit(EFI_CONFIG_TABLES, &efi.flags);
350
Leif Lindholm272686b2013-09-05 11:34:54 +0100351 return 0;
352}
Mark Salter0302f712013-12-30 12:12:12 -0500353
Lee, Chun-Yi28d54022014-07-09 18:39:29 +0800354#ifdef CONFIG_EFI_VARS_MODULE
355static int __init efi_load_efivars(void)
356{
357 struct platform_device *pdev;
358
359 if (!efi_enabled(EFI_RUNTIME_SERVICES))
360 return 0;
361
362 pdev = platform_device_register_simple("efivars", 0, NULL, 0);
363 return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
364}
365device_initcall(efi_load_efivars);
366#endif
367
Mark Salter0302f712013-12-30 12:12:12 -0500368#ifdef CONFIG_EFI_PARAMS_FROM_FDT
369
370#define UEFI_PARAM(name, prop, field) \
371 { \
372 { name }, \
373 { prop }, \
374 offsetof(struct efi_fdt_params, field), \
375 FIELD_SIZEOF(struct efi_fdt_params, field) \
376 }
377
378static __initdata struct {
379 const char name[32];
380 const char propname[32];
381 int offset;
382 int size;
383} dt_params[] = {
384 UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
385 UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
386 UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
387 UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
388 UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
389};
390
391struct param_info {
392 int verbose;
Catalin Marinas29e24352014-07-08 16:54:18 +0100393 int found;
Mark Salter0302f712013-12-30 12:12:12 -0500394 void *params;
395};
396
397static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
398 int depth, void *data)
399{
400 struct param_info *info = data;
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100401 const void *prop;
402 void *dest;
Mark Salter0302f712013-12-30 12:12:12 -0500403 u64 val;
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100404 int i, len;
Mark Salter0302f712013-12-30 12:12:12 -0500405
406 if (depth != 1 ||
407 (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
408 return 0;
409
Mark Salter0302f712013-12-30 12:12:12 -0500410 for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
411 prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
Catalin Marinas29e24352014-07-08 16:54:18 +0100412 if (!prop)
Mark Salter0302f712013-12-30 12:12:12 -0500413 return 0;
Mark Salter0302f712013-12-30 12:12:12 -0500414 dest = info->params + dt_params[i].offset;
Catalin Marinas29e24352014-07-08 16:54:18 +0100415 info->found++;
Mark Salter0302f712013-12-30 12:12:12 -0500416
417 val = of_read_number(prop, len / sizeof(u32));
418
419 if (dt_params[i].size == sizeof(u32))
420 *(u32 *)dest = val;
421 else
422 *(u64 *)dest = val;
423
424 if (info->verbose)
425 pr_info(" %s: 0x%0*llx\n", dt_params[i].name,
426 dt_params[i].size * 2, val);
427 }
428 return 1;
429}
430
431int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
432{
433 struct param_info info;
Catalin Marinas29e24352014-07-08 16:54:18 +0100434 int ret;
435
436 pr_info("Getting EFI parameters from FDT:\n");
Mark Salter0302f712013-12-30 12:12:12 -0500437
438 info.verbose = verbose;
Catalin Marinas29e24352014-07-08 16:54:18 +0100439 info.found = 0;
Mark Salter0302f712013-12-30 12:12:12 -0500440 info.params = params;
441
Catalin Marinas29e24352014-07-08 16:54:18 +0100442 ret = of_scan_flat_dt(fdt_find_uefi_params, &info);
443 if (!info.found)
444 pr_info("UEFI not found.\n");
445 else if (!ret)
446 pr_err("Can't find '%s' in device tree!\n",
447 dt_params[info.found].name);
448
449 return ret;
Mark Salter0302f712013-12-30 12:12:12 -0500450}
451#endif /* CONFIG_EFI_PARAMS_FROM_FDT */
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200452
453static __initdata char memory_type_name[][20] = {
454 "Reserved",
455 "Loader Code",
456 "Loader Data",
457 "Boot Code",
458 "Boot Data",
459 "Runtime Code",
460 "Runtime Data",
461 "Conventional Memory",
462 "Unusable Memory",
463 "ACPI Reclaim Memory",
464 "ACPI Memory NVS",
465 "Memory Mapped I/O",
466 "MMIO Port Space",
467 "PAL Code"
468};
469
470char * __init efi_md_typeattr_format(char *buf, size_t size,
471 const efi_memory_desc_t *md)
472{
473 char *pos;
474 int type_len;
475 u64 attr;
476
477 pos = buf;
478 if (md->type >= ARRAY_SIZE(memory_type_name))
479 type_len = snprintf(pos, size, "[type=%u", md->type);
480 else
481 type_len = snprintf(pos, size, "[%-*s",
482 (int)(sizeof(memory_type_name[0]) - 1),
483 memory_type_name[md->type]);
484 if (type_len >= size)
485 return buf;
486
487 pos += type_len;
488 size -= type_len;
489
490 attr = md->attribute;
491 if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
492 EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP |
493 EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RUNTIME))
494 snprintf(pos, size, "|attr=0x%016llx]",
495 (unsigned long long)attr);
496 else
497 snprintf(pos, size, "|%3s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
498 attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
499 attr & EFI_MEMORY_XP ? "XP" : "",
500 attr & EFI_MEMORY_RP ? "RP" : "",
501 attr & EFI_MEMORY_WP ? "WP" : "",
502 attr & EFI_MEMORY_UCE ? "UCE" : "",
503 attr & EFI_MEMORY_WB ? "WB" : "",
504 attr & EFI_MEMORY_WT ? "WT" : "",
505 attr & EFI_MEMORY_WC ? "WC" : "",
506 attr & EFI_MEMORY_UC ? "UC" : "");
507 return buf;
508}