]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/firmware/efi/efi.c
efi: dmi: add support for SMBIOS 3.0 UEFI configuration table
[mirror_ubuntu-bionic-kernel.git] / drivers / firmware / efi / efi.c
CommitLineData
a9499fa7
TG
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
272686bf
LL
16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
a9499fa7
TG
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>
0302f71c
MS
23#include <linux/of.h>
24#include <linux/of_fdt.h>
272686bf 25#include <linux/io.h>
28d54022 26#include <linux/platform_device.h>
272686bf
LL
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,
e1ccbbc9 33 .smbios3 = EFI_INVALID_TABLE_ADDR,
272686bf
LL
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,
a0998eb1
DY
39 .fw_vendor = EFI_INVALID_TABLE_ADDR,
40 .runtime = EFI_INVALID_TABLE_ADDR,
41 .config_table = EFI_INVALID_TABLE_ADDR,
272686bf
LL
42};
43EXPORT_SYMBOL(efi);
a9499fa7 44
b2e0a54a
DY
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
5ae3683c
DY
58static int __init parse_efi_cmdline(char *str)
59{
60 if (parse_option_str(str, "noruntime"))
61 disable_runtime = true;
62
63 return 0;
64}
65early_param("efi", parse_efi_cmdline);
66
a9499fa7
TG
67static struct kobject *efi_kobj;
68static struct kobject *efivars_kobj;
69
70/*
71 * Let's not leave out systab information that snuck into
72 * the efivars driver
73 */
74static ssize_t systab_show(struct kobject *kobj,
75 struct kobj_attribute *attr, char *buf)
76{
77 char *str = buf;
78
79 if (!kobj || !buf)
80 return -EINVAL;
81
82 if (efi.mps != EFI_INVALID_TABLE_ADDR)
83 str += sprintf(str, "MPS=0x%lx\n", efi.mps);
84 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
85 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
86 if (efi.acpi != EFI_INVALID_TABLE_ADDR)
87 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
88 if (efi.smbios != EFI_INVALID_TABLE_ADDR)
89 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
e1ccbbc9
AB
90 if (efi.smbios3 != EFI_INVALID_TABLE_ADDR)
91 str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3);
a9499fa7
TG
92 if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
93 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
94 if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
95 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
96 if (efi.uga != EFI_INVALID_TABLE_ADDR)
97 str += sprintf(str, "UGA=0x%lx\n", efi.uga);
98
99 return str - buf;
100}
101
102static struct kobj_attribute efi_attr_systab =
103 __ATTR(systab, 0400, systab_show, NULL);
104
a0998eb1
DY
105#define EFI_FIELD(var) efi.var
106
107#define EFI_ATTR_SHOW(name) \
108static ssize_t name##_show(struct kobject *kobj, \
109 struct kobj_attribute *attr, char *buf) \
110{ \
111 return sprintf(buf, "0x%lx\n", EFI_FIELD(name)); \
112}
113
114EFI_ATTR_SHOW(fw_vendor);
115EFI_ATTR_SHOW(runtime);
116EFI_ATTR_SHOW(config_table);
117
118static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor);
119static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
120static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);
121
a9499fa7
TG
122static struct attribute *efi_subsys_attrs[] = {
123 &efi_attr_systab.attr,
a0998eb1
DY
124 &efi_attr_fw_vendor.attr,
125 &efi_attr_runtime.attr,
126 &efi_attr_config_table.attr,
127 NULL,
a9499fa7
TG
128};
129
a0998eb1
DY
130static umode_t efi_attr_is_visible(struct kobject *kobj,
131 struct attribute *attr, int n)
132{
9f27bc54
DK
133 if (attr == &efi_attr_fw_vendor.attr) {
134 if (efi_enabled(EFI_PARAVIRT) ||
135 efi.fw_vendor == EFI_INVALID_TABLE_ADDR)
136 return 0;
137 } else if (attr == &efi_attr_runtime.attr) {
138 if (efi.runtime == EFI_INVALID_TABLE_ADDR)
139 return 0;
140 } else if (attr == &efi_attr_config_table.attr) {
141 if (efi.config_table == EFI_INVALID_TABLE_ADDR)
142 return 0;
143 }
a0998eb1 144
9f27bc54 145 return attr->mode;
a0998eb1
DY
146}
147
a9499fa7
TG
148static struct attribute_group efi_subsys_attr_group = {
149 .attrs = efi_subsys_attrs,
a0998eb1 150 .is_visible = efi_attr_is_visible,
a9499fa7
TG
151};
152
153static struct efivars generic_efivars;
154static struct efivar_operations generic_ops;
155
156static int generic_ops_register(void)
157{
158 generic_ops.get_variable = efi.get_variable;
159 generic_ops.set_variable = efi.set_variable;
160 generic_ops.get_next_variable = efi.get_next_variable;
a614e192 161 generic_ops.query_variable_store = efi_query_variable_store;
a9499fa7
TG
162
163 return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
164}
165
166static void generic_ops_unregister(void)
167{
168 efivars_unregister(&generic_efivars);
169}
170
171/*
172 * We register the efi subsystem with the firmware subsystem and the
173 * efivars subsystem with the efi subsystem, if the system was booted with
174 * EFI.
175 */
176static int __init efisubsys_init(void)
177{
178 int error;
179
180 if (!efi_enabled(EFI_BOOT))
181 return 0;
182
183 /* We register the efi directory at /sys/firmware/efi */
184 efi_kobj = kobject_create_and_add("efi", firmware_kobj);
185 if (!efi_kobj) {
186 pr_err("efi: Firmware registration failed.\n");
187 return -ENOMEM;
188 }
189
190 error = generic_ops_register();
191 if (error)
192 goto err_put;
193
194 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
195 if (error) {
196 pr_err("efi: Sysfs attribute export failed with error %d.\n",
197 error);
198 goto err_unregister;
199 }
200
926172d4
DY
201 error = efi_runtime_map_init(efi_kobj);
202 if (error)
203 goto err_remove_group;
204
a9499fa7
TG
205 /* and the standard mountpoint for efivarfs */
206 efivars_kobj = kobject_create_and_add("efivars", efi_kobj);
207 if (!efivars_kobj) {
208 pr_err("efivars: Subsystem registration failed.\n");
209 error = -ENOMEM;
210 goto err_remove_group;
211 }
212
213 return 0;
214
215err_remove_group:
216 sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
217err_unregister:
218 generic_ops_unregister();
219err_put:
220 kobject_put(efi_kobj);
221 return error;
222}
223
224subsys_initcall(efisubsys_init);
272686bf
LL
225
226
258f6fd7
LL
227/*
228 * We can't ioremap data in EFI boot services RAM, because we've already mapped
229 * it as RAM. So, look it up in the existing EFI memory map instead. Only
230 * callable after efi_enter_virtual_mode and before efi_free_boot_services.
231 */
232void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
233{
234 struct efi_memory_map *map;
235 void *p;
236 map = efi.memmap;
237 if (!map)
238 return NULL;
239 if (WARN_ON(!map->map))
240 return NULL;
241 for (p = map->map; p < map->map_end; p += map->desc_size) {
242 efi_memory_desc_t *md = p;
243 u64 size = md->num_pages << EFI_PAGE_SHIFT;
244 u64 end = md->phys_addr + size;
245 if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
246 md->type != EFI_BOOT_SERVICES_CODE &&
247 md->type != EFI_BOOT_SERVICES_DATA)
248 continue;
249 if (!md->virt_addr)
250 continue;
251 if (phys_addr >= md->phys_addr && phys_addr < end) {
252 phys_addr += md->virt_addr - md->phys_addr;
253 return (__force void __iomem *)(unsigned long)phys_addr;
254 }
255 }
256 return NULL;
257}
258
272686bf
LL
259static __initdata efi_config_table_type_t common_tables[] = {
260 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
261 {ACPI_TABLE_GUID, "ACPI", &efi.acpi},
262 {HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
263 {MPS_TABLE_GUID, "MPS", &efi.mps},
264 {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
265 {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
e1ccbbc9 266 {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
272686bf 267 {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
69e60841 268 {NULL_GUID, NULL, NULL},
272686bf
LL
269};
270
271static __init int match_config_table(efi_guid_t *guid,
272 unsigned long table,
273 efi_config_table_type_t *table_types)
274{
275 u8 str[EFI_VARIABLE_GUID_LEN + 1];
276 int i;
277
278 if (table_types) {
279 efi_guid_unparse(guid, str);
280
281 for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
282 efi_guid_unparse(&table_types[i].guid, str);
283
284 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");
abc93f8e 331 early_memunmap(config_tables,
272686bf
LL
332 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");
abc93f8e 347 early_memunmap(config_tables, efi.systab->nr_tables * sz);
0f8093a9
MF
348
349 set_bit(EFI_CONFIG_TABLES, &efi.flags);
350
272686bf
LL
351 return 0;
352}
0302f71c 353
28d54022
LCY
354#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
0302f71c
MS
368#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;
29e2435f 393 int found;
0302f71c
MS
394 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;
6fb8cc82
CM
401 const void *prop;
402 void *dest;
0302f71c 403 u64 val;
6fb8cc82 404 int i, len;
0302f71c
MS
405
406 if (depth != 1 ||
407 (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
408 return 0;
409
0302f71c
MS
410 for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
411 prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
29e2435f 412 if (!prop)
0302f71c 413 return 0;
0302f71c 414 dest = info->params + dt_params[i].offset;
29e2435f 415 info->found++;
0302f71c
MS
416
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;
29e2435f
CM
434 int ret;
435
436 pr_info("Getting EFI parameters from FDT:\n");
0302f71c
MS
437
438 info.verbose = verbose;
29e2435f 439 info.found = 0;
0302f71c
MS
440 info.params = params;
441
29e2435f
CM
442 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;
0302f71c
MS
450}
451#endif /* CONFIG_EFI_PARAMS_FROM_FDT */
98d2a6ca
LE
452
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}