blob: 23f1eca92dc4b16b4f9b07012e14d8d22b306561 [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
Leif Lindholm11629302015-01-20 16:34:38 +0000406 if (depth != 1 || strcmp(uname, "chosen") != 0)
Mark Salter0302f712013-12-30 12:12:12 -0500407 return 0;
408
Mark Salter0302f712013-12-30 12:12:12 -0500409 for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
410 prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
Catalin Marinas29e24352014-07-08 16:54:18 +0100411 if (!prop)
Mark Salter0302f712013-12-30 12:12:12 -0500412 return 0;
Mark Salter0302f712013-12-30 12:12:12 -0500413 dest = info->params + dt_params[i].offset;
Catalin Marinas29e24352014-07-08 16:54:18 +0100414 info->found++;
Mark Salter0302f712013-12-30 12:12:12 -0500415
416 val = of_read_number(prop, len / sizeof(u32));
417
418 if (dt_params[i].size == sizeof(u32))
419 *(u32 *)dest = val;
420 else
421 *(u64 *)dest = val;
422
423 if (info->verbose)
424 pr_info(" %s: 0x%0*llx\n", dt_params[i].name,
425 dt_params[i].size * 2, val);
426 }
427 return 1;
428}
429
430int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
431{
432 struct param_info info;
Catalin Marinas29e24352014-07-08 16:54:18 +0100433 int ret;
434
435 pr_info("Getting EFI parameters from FDT:\n");
Mark Salter0302f712013-12-30 12:12:12 -0500436
437 info.verbose = verbose;
Catalin Marinas29e24352014-07-08 16:54:18 +0100438 info.found = 0;
Mark Salter0302f712013-12-30 12:12:12 -0500439 info.params = params;
440
Catalin Marinas29e24352014-07-08 16:54:18 +0100441 ret = of_scan_flat_dt(fdt_find_uefi_params, &info);
442 if (!info.found)
443 pr_info("UEFI not found.\n");
444 else if (!ret)
445 pr_err("Can't find '%s' in device tree!\n",
446 dt_params[info.found].name);
447
448 return ret;
Mark Salter0302f712013-12-30 12:12:12 -0500449}
450#endif /* CONFIG_EFI_PARAMS_FROM_FDT */
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200451
452static __initdata char memory_type_name[][20] = {
453 "Reserved",
454 "Loader Code",
455 "Loader Data",
456 "Boot Code",
457 "Boot Data",
458 "Runtime Code",
459 "Runtime Data",
460 "Conventional Memory",
461 "Unusable Memory",
462 "ACPI Reclaim Memory",
463 "ACPI Memory NVS",
464 "Memory Mapped I/O",
465 "MMIO Port Space",
466 "PAL Code"
467};
468
469char * __init efi_md_typeattr_format(char *buf, size_t size,
470 const efi_memory_desc_t *md)
471{
472 char *pos;
473 int type_len;
474 u64 attr;
475
476 pos = buf;
477 if (md->type >= ARRAY_SIZE(memory_type_name))
478 type_len = snprintf(pos, size, "[type=%u", md->type);
479 else
480 type_len = snprintf(pos, size, "[%-*s",
481 (int)(sizeof(memory_type_name[0]) - 1),
482 memory_type_name[md->type]);
483 if (type_len >= size)
484 return buf;
485
486 pos += type_len;
487 size -= type_len;
488
489 attr = md->attribute;
490 if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
491 EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP |
492 EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RUNTIME))
493 snprintf(pos, size, "|attr=0x%016llx]",
494 (unsigned long long)attr);
495 else
496 snprintf(pos, size, "|%3s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
497 attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
498 attr & EFI_MEMORY_XP ? "XP" : "",
499 attr & EFI_MEMORY_RP ? "RP" : "",
500 attr & EFI_MEMORY_WP ? "WP" : "",
501 attr & EFI_MEMORY_UCE ? "UCE" : "",
502 attr & EFI_MEMORY_WB ? "WB" : "",
503 attr & EFI_MEMORY_WT ? "WT" : "",
504 attr & EFI_MEMORY_WC ? "WC" : "",
505 attr & EFI_MEMORY_UC ? "UC" : "");
506 return buf;
507}