blob: ff0bbe383b31ab231d5cacfd9c78f3da26696e7d [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
115static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor);
116static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
117static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);
118
Tom Gundersena9499fa2013-02-08 15:37:06 +0000119static struct attribute *efi_subsys_attrs[] = {
120 &efi_attr_systab.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800121 &efi_attr_fw_vendor.attr,
122 &efi_attr_runtime.attr,
123 &efi_attr_config_table.attr,
124 NULL,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000125};
126
Dave Younga0998eb2013-12-20 18:02:17 +0800127static umode_t efi_attr_is_visible(struct kobject *kobj,
128 struct attribute *attr, int n)
129{
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200130 if (attr == &efi_attr_fw_vendor.attr) {
131 if (efi_enabled(EFI_PARAVIRT) ||
132 efi.fw_vendor == EFI_INVALID_TABLE_ADDR)
133 return 0;
134 } else if (attr == &efi_attr_runtime.attr) {
135 if (efi.runtime == EFI_INVALID_TABLE_ADDR)
136 return 0;
137 } else if (attr == &efi_attr_config_table.attr) {
138 if (efi.config_table == EFI_INVALID_TABLE_ADDR)
139 return 0;
140 }
Dave Younga0998eb2013-12-20 18:02:17 +0800141
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200142 return attr->mode;
Dave Younga0998eb2013-12-20 18:02:17 +0800143}
144
Tom Gundersena9499fa2013-02-08 15:37:06 +0000145static struct attribute_group efi_subsys_attr_group = {
146 .attrs = efi_subsys_attrs,
Dave Younga0998eb2013-12-20 18:02:17 +0800147 .is_visible = efi_attr_is_visible,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000148};
149
150static struct efivars generic_efivars;
151static struct efivar_operations generic_ops;
152
153static int generic_ops_register(void)
154{
155 generic_ops.get_variable = efi.get_variable;
156 generic_ops.set_variable = efi.set_variable;
157 generic_ops.get_next_variable = efi.get_next_variable;
Matt Fleminga614e192013-04-30 11:30:24 +0100158 generic_ops.query_variable_store = efi_query_variable_store;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000159
160 return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
161}
162
163static void generic_ops_unregister(void)
164{
165 efivars_unregister(&generic_efivars);
166}
167
168/*
169 * We register the efi subsystem with the firmware subsystem and the
170 * efivars subsystem with the efi subsystem, if the system was booted with
171 * EFI.
172 */
173static int __init efisubsys_init(void)
174{
175 int error;
176
177 if (!efi_enabled(EFI_BOOT))
178 return 0;
179
180 /* We register the efi directory at /sys/firmware/efi */
181 efi_kobj = kobject_create_and_add("efi", firmware_kobj);
182 if (!efi_kobj) {
183 pr_err("efi: Firmware registration failed.\n");
184 return -ENOMEM;
185 }
186
187 error = generic_ops_register();
188 if (error)
189 goto err_put;
190
191 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
192 if (error) {
193 pr_err("efi: Sysfs attribute export failed with error %d.\n",
194 error);
195 goto err_unregister;
196 }
197
Dave Young926172d2013-12-20 18:02:18 +0800198 error = efi_runtime_map_init(efi_kobj);
199 if (error)
200 goto err_remove_group;
201
Tom Gundersena9499fa2013-02-08 15:37:06 +0000202 /* and the standard mountpoint for efivarfs */
203 efivars_kobj = kobject_create_and_add("efivars", efi_kobj);
204 if (!efivars_kobj) {
205 pr_err("efivars: Subsystem registration failed.\n");
206 error = -ENOMEM;
207 goto err_remove_group;
208 }
209
210 return 0;
211
212err_remove_group:
213 sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
214err_unregister:
215 generic_ops_unregister();
216err_put:
217 kobject_put(efi_kobj);
218 return error;
219}
220
221subsys_initcall(efisubsys_init);
Leif Lindholm272686b2013-09-05 11:34:54 +0100222
223
Leif Lindholm258f6fd2013-09-05 11:34:55 +0100224/*
225 * We can't ioremap data in EFI boot services RAM, because we've already mapped
226 * it as RAM. So, look it up in the existing EFI memory map instead. Only
227 * callable after efi_enter_virtual_mode and before efi_free_boot_services.
228 */
229void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
230{
231 struct efi_memory_map *map;
232 void *p;
233 map = efi.memmap;
234 if (!map)
235 return NULL;
236 if (WARN_ON(!map->map))
237 return NULL;
238 for (p = map->map; p < map->map_end; p += map->desc_size) {
239 efi_memory_desc_t *md = p;
240 u64 size = md->num_pages << EFI_PAGE_SHIFT;
241 u64 end = md->phys_addr + size;
242 if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
243 md->type != EFI_BOOT_SERVICES_CODE &&
244 md->type != EFI_BOOT_SERVICES_DATA)
245 continue;
246 if (!md->virt_addr)
247 continue;
248 if (phys_addr >= md->phys_addr && phys_addr < end) {
249 phys_addr += md->virt_addr - md->phys_addr;
250 return (__force void __iomem *)(unsigned long)phys_addr;
251 }
252 }
253 return NULL;
254}
255
Leif Lindholm272686b2013-09-05 11:34:54 +0100256static __initdata efi_config_table_type_t common_tables[] = {
257 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
258 {ACPI_TABLE_GUID, "ACPI", &efi.acpi},
259 {HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
260 {MPS_TABLE_GUID, "MPS", &efi.mps},
261 {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
262 {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
263 {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
Daeseok Youn69e60842014-02-13 17:16:36 +0900264 {NULL_GUID, NULL, NULL},
Leif Lindholm272686b2013-09-05 11:34:54 +0100265};
266
267static __init int match_config_table(efi_guid_t *guid,
268 unsigned long table,
269 efi_config_table_type_t *table_types)
270{
271 u8 str[EFI_VARIABLE_GUID_LEN + 1];
272 int i;
273
274 if (table_types) {
Borislav Petkov26e02272014-12-18 16:02:17 +0100275 efi_guid_to_str(guid, str);
Leif Lindholm272686b2013-09-05 11:34:54 +0100276
277 for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
Borislav Petkov26e02272014-12-18 16:02:17 +0100278 efi_guid_to_str(&table_types[i].guid, str);
Leif Lindholm272686b2013-09-05 11:34:54 +0100279
280 if (!efi_guidcmp(*guid, table_types[i].guid)) {
281 *(table_types[i].ptr) = table;
282 pr_cont(" %s=0x%lx ",
283 table_types[i].name, table);
284 return 1;
285 }
286 }
287 }
288
289 return 0;
290}
291
292int __init efi_config_init(efi_config_table_type_t *arch_tables)
293{
294 void *config_tables, *tablep;
295 int i, sz;
296
297 if (efi_enabled(EFI_64BIT))
298 sz = sizeof(efi_config_table_64_t);
299 else
300 sz = sizeof(efi_config_table_32_t);
301
302 /*
303 * Let's see what config tables the firmware passed to us.
304 */
305 config_tables = early_memremap(efi.systab->tables,
306 efi.systab->nr_tables * sz);
307 if (config_tables == NULL) {
308 pr_err("Could not map Configuration table!\n");
309 return -ENOMEM;
310 }
311
312 tablep = config_tables;
313 pr_info("");
314 for (i = 0; i < efi.systab->nr_tables; i++) {
315 efi_guid_t guid;
316 unsigned long table;
317
318 if (efi_enabled(EFI_64BIT)) {
319 u64 table64;
320 guid = ((efi_config_table_64_t *)tablep)->guid;
321 table64 = ((efi_config_table_64_t *)tablep)->table;
322 table = table64;
323#ifndef CONFIG_64BIT
324 if (table64 >> 32) {
325 pr_cont("\n");
326 pr_err("Table located above 4GB, disabling EFI.\n");
Daniel Kiperabc93f82014-06-30 19:52:56 +0200327 early_memunmap(config_tables,
Leif Lindholm272686b2013-09-05 11:34:54 +0100328 efi.systab->nr_tables * sz);
329 return -EINVAL;
330 }
331#endif
332 } else {
333 guid = ((efi_config_table_32_t *)tablep)->guid;
334 table = ((efi_config_table_32_t *)tablep)->table;
335 }
336
337 if (!match_config_table(&guid, table, common_tables))
338 match_config_table(&guid, table, arch_tables);
339
340 tablep += sz;
341 }
342 pr_cont("\n");
Daniel Kiperabc93f82014-06-30 19:52:56 +0200343 early_memunmap(config_tables, efi.systab->nr_tables * sz);
Matt Fleming0f8093a2014-01-15 13:36:33 +0000344
345 set_bit(EFI_CONFIG_TABLES, &efi.flags);
346
Leif Lindholm272686b2013-09-05 11:34:54 +0100347 return 0;
348}
Mark Salter0302f712013-12-30 12:12:12 -0500349
Lee, Chun-Yi28d54022014-07-09 18:39:29 +0800350#ifdef CONFIG_EFI_VARS_MODULE
351static int __init efi_load_efivars(void)
352{
353 struct platform_device *pdev;
354
355 if (!efi_enabled(EFI_RUNTIME_SERVICES))
356 return 0;
357
358 pdev = platform_device_register_simple("efivars", 0, NULL, 0);
359 return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
360}
361device_initcall(efi_load_efivars);
362#endif
363
Mark Salter0302f712013-12-30 12:12:12 -0500364#ifdef CONFIG_EFI_PARAMS_FROM_FDT
365
366#define UEFI_PARAM(name, prop, field) \
367 { \
368 { name }, \
369 { prop }, \
370 offsetof(struct efi_fdt_params, field), \
371 FIELD_SIZEOF(struct efi_fdt_params, field) \
372 }
373
374static __initdata struct {
375 const char name[32];
376 const char propname[32];
377 int offset;
378 int size;
379} dt_params[] = {
380 UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
381 UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
382 UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
383 UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
384 UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
385};
386
387struct param_info {
388 int verbose;
Catalin Marinas29e24352014-07-08 16:54:18 +0100389 int found;
Mark Salter0302f712013-12-30 12:12:12 -0500390 void *params;
391};
392
393static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
394 int depth, void *data)
395{
396 struct param_info *info = data;
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100397 const void *prop;
398 void *dest;
Mark Salter0302f712013-12-30 12:12:12 -0500399 u64 val;
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100400 int i, len;
Mark Salter0302f712013-12-30 12:12:12 -0500401
402 if (depth != 1 ||
403 (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
404 return 0;
405
Mark Salter0302f712013-12-30 12:12:12 -0500406 for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
407 prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
Catalin Marinas29e24352014-07-08 16:54:18 +0100408 if (!prop)
Mark Salter0302f712013-12-30 12:12:12 -0500409 return 0;
Mark Salter0302f712013-12-30 12:12:12 -0500410 dest = info->params + dt_params[i].offset;
Catalin Marinas29e24352014-07-08 16:54:18 +0100411 info->found++;
Mark Salter0302f712013-12-30 12:12:12 -0500412
413 val = of_read_number(prop, len / sizeof(u32));
414
415 if (dt_params[i].size == sizeof(u32))
416 *(u32 *)dest = val;
417 else
418 *(u64 *)dest = val;
419
420 if (info->verbose)
421 pr_info(" %s: 0x%0*llx\n", dt_params[i].name,
422 dt_params[i].size * 2, val);
423 }
424 return 1;
425}
426
427int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
428{
429 struct param_info info;
Catalin Marinas29e24352014-07-08 16:54:18 +0100430 int ret;
431
432 pr_info("Getting EFI parameters from FDT:\n");
Mark Salter0302f712013-12-30 12:12:12 -0500433
434 info.verbose = verbose;
Catalin Marinas29e24352014-07-08 16:54:18 +0100435 info.found = 0;
Mark Salter0302f712013-12-30 12:12:12 -0500436 info.params = params;
437
Catalin Marinas29e24352014-07-08 16:54:18 +0100438 ret = of_scan_flat_dt(fdt_find_uefi_params, &info);
439 if (!info.found)
440 pr_info("UEFI not found.\n");
441 else if (!ret)
442 pr_err("Can't find '%s' in device tree!\n",
443 dt_params[info.found].name);
444
445 return ret;
Mark Salter0302f712013-12-30 12:12:12 -0500446}
447#endif /* CONFIG_EFI_PARAMS_FROM_FDT */
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200448
449static __initdata char memory_type_name[][20] = {
450 "Reserved",
451 "Loader Code",
452 "Loader Data",
453 "Boot Code",
454 "Boot Data",
455 "Runtime Code",
456 "Runtime Data",
457 "Conventional Memory",
458 "Unusable Memory",
459 "ACPI Reclaim Memory",
460 "ACPI Memory NVS",
461 "Memory Mapped I/O",
462 "MMIO Port Space",
463 "PAL Code"
464};
465
466char * __init efi_md_typeattr_format(char *buf, size_t size,
467 const efi_memory_desc_t *md)
468{
469 char *pos;
470 int type_len;
471 u64 attr;
472
473 pos = buf;
474 if (md->type >= ARRAY_SIZE(memory_type_name))
475 type_len = snprintf(pos, size, "[type=%u", md->type);
476 else
477 type_len = snprintf(pos, size, "[%-*s",
478 (int)(sizeof(memory_type_name[0]) - 1),
479 memory_type_name[md->type]);
480 if (type_len >= size)
481 return buf;
482
483 pos += type_len;
484 size -= type_len;
485
486 attr = md->attribute;
487 if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
488 EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP |
489 EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RUNTIME))
490 snprintf(pos, size, "|attr=0x%016llx]",
491 (unsigned long long)attr);
492 else
493 snprintf(pos, size, "|%3s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
494 attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
495 attr & EFI_MEMORY_XP ? "XP" : "",
496 attr & EFI_MEMORY_RP ? "RP" : "",
497 attr & EFI_MEMORY_WP ? "WP" : "",
498 attr & EFI_MEMORY_UCE ? "UCE" : "",
499 attr & EFI_MEMORY_WB ? "WB" : "",
500 attr & EFI_MEMORY_WT ? "WT" : "",
501 attr & EFI_MEMORY_WC ? "WC" : "",
502 attr & EFI_MEMORY_UC ? "UC" : "");
503 return buf;
504}