blob: a0a0469e2869eca83019040268455e5eb17730a6 [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,
Ard Biesheuvele1ccbbc2014-10-14 16:34:47 +020033 .smbios3 = EFI_INVALID_TABLE_ADDR,
Leif Lindholm272686b2013-09-05 11:34:54 +010034 .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,
Dave Younga0998eb2013-12-20 18:02:17 +080039 .fw_vendor = EFI_INVALID_TABLE_ADDR,
40 .runtime = EFI_INVALID_TABLE_ADDR,
41 .config_table = EFI_INVALID_TABLE_ADDR,
Peter Jones0bb54902015-04-28 18:44:31 -040042 .esrt = EFI_INVALID_TABLE_ADDR,
Leif Lindholm272686b2013-09-05 11:34:54 +010043};
44EXPORT_SYMBOL(efi);
Tom Gundersena9499fa2013-02-08 15:37:06 +000045
Dave Youngb2e0a542014-08-14 17:15:26 +080046static bool disable_runtime;
47static int __init setup_noefi(char *arg)
48{
49 disable_runtime = true;
50 return 0;
51}
52early_param("noefi", setup_noefi);
53
54bool efi_runtime_disabled(void)
55{
56 return disable_runtime;
57}
58
Dave Young5ae36832014-08-14 17:15:28 +080059static int __init parse_efi_cmdline(char *str)
60{
Ricardo Neri9115c752015-07-15 19:36:03 -070061 if (!str) {
62 pr_warn("need at least one option\n");
63 return -EINVAL;
64 }
65
Leif Lindholm12dd00e2015-08-26 14:24:56 +010066 if (parse_option_str(str, "debug"))
67 set_bit(EFI_DBG, &efi.flags);
68
Dave Young5ae36832014-08-14 17:15:28 +080069 if (parse_option_str(str, "noruntime"))
70 disable_runtime = true;
71
72 return 0;
73}
74early_param("efi", parse_efi_cmdline);
75
Peter Jones0bb54902015-04-28 18:44:31 -040076struct kobject *efi_kobj;
Tom Gundersena9499fa2013-02-08 15:37:06 +000077
78/*
79 * Let's not leave out systab information that snuck into
80 * the efivars driver
81 */
82static ssize_t systab_show(struct kobject *kobj,
83 struct kobj_attribute *attr, char *buf)
84{
85 char *str = buf;
86
87 if (!kobj || !buf)
88 return -EINVAL;
89
90 if (efi.mps != EFI_INVALID_TABLE_ADDR)
91 str += sprintf(str, "MPS=0x%lx\n", efi.mps);
92 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
93 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
94 if (efi.acpi != EFI_INVALID_TABLE_ADDR)
95 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
Jean Delvareb119fe02015-04-30 15:23:05 +020096 /*
97 * If both SMBIOS and SMBIOS3 entry points are implemented, the
98 * SMBIOS3 entry point shall be preferred, so we list it first to
99 * let applications stop parsing after the first match.
100 */
Ard Biesheuvele1ccbbc2014-10-14 16:34:47 +0200101 if (efi.smbios3 != EFI_INVALID_TABLE_ADDR)
102 str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3);
Jean Delvareb119fe02015-04-30 15:23:05 +0200103 if (efi.smbios != EFI_INVALID_TABLE_ADDR)
104 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
Tom Gundersena9499fa2013-02-08 15:37:06 +0000105 if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
106 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
107 if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
108 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
109 if (efi.uga != EFI_INVALID_TABLE_ADDR)
110 str += sprintf(str, "UGA=0x%lx\n", efi.uga);
111
112 return str - buf;
113}
114
115static struct kobj_attribute efi_attr_systab =
116 __ATTR(systab, 0400, systab_show, NULL);
117
Dave Younga0998eb2013-12-20 18:02:17 +0800118#define EFI_FIELD(var) efi.var
119
120#define EFI_ATTR_SHOW(name) \
121static ssize_t name##_show(struct kobject *kobj, \
122 struct kobj_attribute *attr, char *buf) \
123{ \
124 return sprintf(buf, "0x%lx\n", EFI_FIELD(name)); \
125}
126
127EFI_ATTR_SHOW(fw_vendor);
128EFI_ATTR_SHOW(runtime);
129EFI_ATTR_SHOW(config_table);
130
Steve McIntyre2859dff2015-01-09 15:29:53 +0000131static ssize_t fw_platform_size_show(struct kobject *kobj,
132 struct kobj_attribute *attr, char *buf)
133{
134 return sprintf(buf, "%d\n", efi_enabled(EFI_64BIT) ? 64 : 32);
135}
136
Dave Younga0998eb2013-12-20 18:02:17 +0800137static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor);
138static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
139static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);
Steve McIntyre2859dff2015-01-09 15:29:53 +0000140static struct kobj_attribute efi_attr_fw_platform_size =
141 __ATTR_RO(fw_platform_size);
Dave Younga0998eb2013-12-20 18:02:17 +0800142
Tom Gundersena9499fa2013-02-08 15:37:06 +0000143static struct attribute *efi_subsys_attrs[] = {
144 &efi_attr_systab.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800145 &efi_attr_fw_vendor.attr,
146 &efi_attr_runtime.attr,
147 &efi_attr_config_table.attr,
Steve McIntyre2859dff2015-01-09 15:29:53 +0000148 &efi_attr_fw_platform_size.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800149 NULL,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000150};
151
Dave Younga0998eb2013-12-20 18:02:17 +0800152static umode_t efi_attr_is_visible(struct kobject *kobj,
153 struct attribute *attr, int n)
154{
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200155 if (attr == &efi_attr_fw_vendor.attr) {
156 if (efi_enabled(EFI_PARAVIRT) ||
157 efi.fw_vendor == EFI_INVALID_TABLE_ADDR)
158 return 0;
159 } else if (attr == &efi_attr_runtime.attr) {
160 if (efi.runtime == EFI_INVALID_TABLE_ADDR)
161 return 0;
162 } else if (attr == &efi_attr_config_table.attr) {
163 if (efi.config_table == EFI_INVALID_TABLE_ADDR)
164 return 0;
165 }
Dave Younga0998eb2013-12-20 18:02:17 +0800166
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200167 return attr->mode;
Dave Younga0998eb2013-12-20 18:02:17 +0800168}
169
Tom Gundersena9499fa2013-02-08 15:37:06 +0000170static struct attribute_group efi_subsys_attr_group = {
171 .attrs = efi_subsys_attrs,
Dave Younga0998eb2013-12-20 18:02:17 +0800172 .is_visible = efi_attr_is_visible,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000173};
174
175static struct efivars generic_efivars;
176static struct efivar_operations generic_ops;
177
178static int generic_ops_register(void)
179{
180 generic_ops.get_variable = efi.get_variable;
181 generic_ops.set_variable = efi.set_variable;
182 generic_ops.get_next_variable = efi.get_next_variable;
Matt Fleminga614e192013-04-30 11:30:24 +0100183 generic_ops.query_variable_store = efi_query_variable_store;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000184
185 return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
186}
187
188static void generic_ops_unregister(void)
189{
190 efivars_unregister(&generic_efivars);
191}
192
193/*
194 * We register the efi subsystem with the firmware subsystem and the
195 * efivars subsystem with the efi subsystem, if the system was booted with
196 * EFI.
197 */
198static int __init efisubsys_init(void)
199{
200 int error;
201
202 if (!efi_enabled(EFI_BOOT))
203 return 0;
204
205 /* We register the efi directory at /sys/firmware/efi */
206 efi_kobj = kobject_create_and_add("efi", firmware_kobj);
207 if (!efi_kobj) {
208 pr_err("efi: Firmware registration failed.\n");
209 return -ENOMEM;
210 }
211
212 error = generic_ops_register();
213 if (error)
214 goto err_put;
215
216 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
217 if (error) {
218 pr_err("efi: Sysfs attribute export failed with error %d.\n",
219 error);
220 goto err_unregister;
221 }
222
Dave Young926172d2013-12-20 18:02:18 +0800223 error = efi_runtime_map_init(efi_kobj);
224 if (error)
225 goto err_remove_group;
226
Tom Gundersena9499fa2013-02-08 15:37:06 +0000227 /* and the standard mountpoint for efivarfs */
Eric W. Biedermanf9bb4882015-05-13 17:35:41 -0500228 error = sysfs_create_mount_point(efi_kobj, "efivars");
229 if (error) {
Tom Gundersena9499fa2013-02-08 15:37:06 +0000230 pr_err("efivars: Subsystem registration failed.\n");
Tom Gundersena9499fa2013-02-08 15:37:06 +0000231 goto err_remove_group;
232 }
233
234 return 0;
235
236err_remove_group:
237 sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
238err_unregister:
239 generic_ops_unregister();
240err_put:
241 kobject_put(efi_kobj);
242 return error;
243}
244
245subsys_initcall(efisubsys_init);
Leif Lindholm272686b2013-09-05 11:34:54 +0100246
Peter Jones0bb54902015-04-28 18:44:31 -0400247/*
248 * Find the efi memory descriptor for a given physical address. Given a
249 * physicall address, determine if it exists within an EFI Memory Map entry,
250 * and if so, populate the supplied memory descriptor with the appropriate
251 * data.
252 */
253int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
254{
255 struct efi_memory_map *map = efi.memmap;
256 void *p, *e;
257
258 if (!efi_enabled(EFI_MEMMAP)) {
259 pr_err_once("EFI_MEMMAP is not enabled.\n");
260 return -EINVAL;
261 }
262
263 if (!map) {
264 pr_err_once("efi.memmap is not set.\n");
265 return -EINVAL;
266 }
267 if (!out_md) {
268 pr_err_once("out_md is null.\n");
269 return -EINVAL;
270 }
271 if (WARN_ON_ONCE(!map->phys_map))
272 return -EINVAL;
273 if (WARN_ON_ONCE(map->nr_map == 0) || WARN_ON_ONCE(map->desc_size == 0))
274 return -EINVAL;
275
276 e = map->phys_map + map->nr_map * map->desc_size;
277 for (p = map->phys_map; p < e; p += map->desc_size) {
278 efi_memory_desc_t *md;
279 u64 size;
280 u64 end;
281
282 /*
283 * If a driver calls this after efi_free_boot_services,
284 * ->map will be NULL, and the target may also not be mapped.
285 * So just always get our own virtual map on the CPU.
286 *
287 */
288 md = early_memremap((phys_addr_t)p, sizeof (*md));
289 if (!md) {
290 pr_err_once("early_memremap(%p, %zu) failed.\n",
291 p, sizeof (*md));
292 return -ENOMEM;
293 }
294
295 if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
296 md->type != EFI_BOOT_SERVICES_DATA &&
297 md->type != EFI_RUNTIME_SERVICES_DATA) {
298 early_memunmap(md, sizeof (*md));
299 continue;
300 }
301
302 size = md->num_pages << EFI_PAGE_SHIFT;
303 end = md->phys_addr + size;
304 if (phys_addr >= md->phys_addr && phys_addr < end) {
305 memcpy(out_md, md, sizeof(*out_md));
306 early_memunmap(md, sizeof (*md));
307 return 0;
308 }
309
310 early_memunmap(md, sizeof (*md));
311 }
312 pr_err_once("requested map not found.\n");
313 return -ENOENT;
314}
315
316/*
317 * Calculate the highest address of an efi memory descriptor.
318 */
319u64 __init efi_mem_desc_end(efi_memory_desc_t *md)
320{
321 u64 size = md->num_pages << EFI_PAGE_SHIFT;
322 u64 end = md->phys_addr + size;
323 return end;
324}
Leif Lindholm272686b2013-09-05 11:34:54 +0100325
Leif Lindholm258f6fd2013-09-05 11:34:55 +0100326/*
327 * We can't ioremap data in EFI boot services RAM, because we've already mapped
328 * it as RAM. So, look it up in the existing EFI memory map instead. Only
329 * callable after efi_enter_virtual_mode and before efi_free_boot_services.
330 */
331void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
332{
333 struct efi_memory_map *map;
334 void *p;
335 map = efi.memmap;
336 if (!map)
337 return NULL;
338 if (WARN_ON(!map->map))
339 return NULL;
340 for (p = map->map; p < map->map_end; p += map->desc_size) {
341 efi_memory_desc_t *md = p;
342 u64 size = md->num_pages << EFI_PAGE_SHIFT;
343 u64 end = md->phys_addr + size;
344 if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
345 md->type != EFI_BOOT_SERVICES_CODE &&
346 md->type != EFI_BOOT_SERVICES_DATA)
347 continue;
348 if (!md->virt_addr)
349 continue;
350 if (phys_addr >= md->phys_addr && phys_addr < end) {
351 phys_addr += md->virt_addr - md->phys_addr;
352 return (__force void __iomem *)(unsigned long)phys_addr;
353 }
354 }
355 return NULL;
356}
357
Leif Lindholm272686b2013-09-05 11:34:54 +0100358static __initdata efi_config_table_type_t common_tables[] = {
359 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
360 {ACPI_TABLE_GUID, "ACPI", &efi.acpi},
361 {HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
362 {MPS_TABLE_GUID, "MPS", &efi.mps},
363 {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
364 {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
Ard Biesheuvele1ccbbc2014-10-14 16:34:47 +0200365 {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
Leif Lindholm272686b2013-09-05 11:34:54 +0100366 {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
Peter Jones0bb54902015-04-28 18:44:31 -0400367 {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
Daeseok Youn69e60842014-02-13 17:16:36 +0900368 {NULL_GUID, NULL, NULL},
Leif Lindholm272686b2013-09-05 11:34:54 +0100369};
370
371static __init int match_config_table(efi_guid_t *guid,
372 unsigned long table,
373 efi_config_table_type_t *table_types)
374{
Leif Lindholm272686b2013-09-05 11:34:54 +0100375 int i;
376
377 if (table_types) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100378 for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100379 if (!efi_guidcmp(*guid, table_types[i].guid)) {
380 *(table_types[i].ptr) = table;
381 pr_cont(" %s=0x%lx ",
382 table_types[i].name, table);
383 return 1;
384 }
385 }
386 }
387
388 return 0;
389}
390
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200391int __init efi_config_parse_tables(void *config_tables, int count, int sz,
392 efi_config_table_type_t *arch_tables)
393{
394 void *tablep;
395 int i;
396
397 tablep = config_tables;
398 pr_info("");
399 for (i = 0; i < count; i++) {
400 efi_guid_t guid;
401 unsigned long table;
402
403 if (efi_enabled(EFI_64BIT)) {
404 u64 table64;
405 guid = ((efi_config_table_64_t *)tablep)->guid;
406 table64 = ((efi_config_table_64_t *)tablep)->table;
407 table = table64;
408#ifndef CONFIG_64BIT
409 if (table64 >> 32) {
410 pr_cont("\n");
411 pr_err("Table located above 4GB, disabling EFI.\n");
412 return -EINVAL;
413 }
414#endif
415 } else {
416 guid = ((efi_config_table_32_t *)tablep)->guid;
417 table = ((efi_config_table_32_t *)tablep)->table;
418 }
419
420 if (!match_config_table(&guid, table, common_tables))
421 match_config_table(&guid, table, arch_tables);
422
423 tablep += sz;
424 }
425 pr_cont("\n");
426 set_bit(EFI_CONFIG_TABLES, &efi.flags);
427 return 0;
428}
429
Leif Lindholm272686b2013-09-05 11:34:54 +0100430int __init efi_config_init(efi_config_table_type_t *arch_tables)
431{
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200432 void *config_tables;
433 int sz, ret;
Leif Lindholm272686b2013-09-05 11:34:54 +0100434
435 if (efi_enabled(EFI_64BIT))
436 sz = sizeof(efi_config_table_64_t);
437 else
438 sz = sizeof(efi_config_table_32_t);
439
440 /*
441 * Let's see what config tables the firmware passed to us.
442 */
443 config_tables = early_memremap(efi.systab->tables,
444 efi.systab->nr_tables * sz);
445 if (config_tables == NULL) {
446 pr_err("Could not map Configuration table!\n");
447 return -ENOMEM;
448 }
449
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200450 ret = efi_config_parse_tables(config_tables, efi.systab->nr_tables, sz,
451 arch_tables);
Leif Lindholm272686b2013-09-05 11:34:54 +0100452
Daniel Kiperabc93f82014-06-30 19:52:56 +0200453 early_memunmap(config_tables, efi.systab->nr_tables * sz);
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200454 return ret;
Leif Lindholm272686b2013-09-05 11:34:54 +0100455}
Mark Salter0302f712013-12-30 12:12:12 -0500456
Lee, Chun-Yi28d54022014-07-09 18:39:29 +0800457#ifdef CONFIG_EFI_VARS_MODULE
458static int __init efi_load_efivars(void)
459{
460 struct platform_device *pdev;
461
462 if (!efi_enabled(EFI_RUNTIME_SERVICES))
463 return 0;
464
465 pdev = platform_device_register_simple("efivars", 0, NULL, 0);
466 return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
467}
468device_initcall(efi_load_efivars);
469#endif
470
Mark Salter0302f712013-12-30 12:12:12 -0500471#ifdef CONFIG_EFI_PARAMS_FROM_FDT
472
473#define UEFI_PARAM(name, prop, field) \
474 { \
475 { name }, \
476 { prop }, \
477 offsetof(struct efi_fdt_params, field), \
478 FIELD_SIZEOF(struct efi_fdt_params, field) \
479 }
480
481static __initdata struct {
482 const char name[32];
483 const char propname[32];
484 int offset;
485 int size;
486} dt_params[] = {
487 UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
488 UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
489 UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
490 UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
491 UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
492};
493
494struct param_info {
Catalin Marinas29e24352014-07-08 16:54:18 +0100495 int found;
Mark Salter0302f712013-12-30 12:12:12 -0500496 void *params;
497};
498
499static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
500 int depth, void *data)
501{
502 struct param_info *info = data;
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100503 const void *prop;
504 void *dest;
Mark Salter0302f712013-12-30 12:12:12 -0500505 u64 val;
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100506 int i, len;
Mark Salter0302f712013-12-30 12:12:12 -0500507
Leif Lindholm11629302015-01-20 16:34:38 +0000508 if (depth != 1 || strcmp(uname, "chosen") != 0)
Mark Salter0302f712013-12-30 12:12:12 -0500509 return 0;
510
Mark Salter0302f712013-12-30 12:12:12 -0500511 for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
512 prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
Catalin Marinas29e24352014-07-08 16:54:18 +0100513 if (!prop)
Mark Salter0302f712013-12-30 12:12:12 -0500514 return 0;
Mark Salter0302f712013-12-30 12:12:12 -0500515 dest = info->params + dt_params[i].offset;
Catalin Marinas29e24352014-07-08 16:54:18 +0100516 info->found++;
Mark Salter0302f712013-12-30 12:12:12 -0500517
518 val = of_read_number(prop, len / sizeof(u32));
519
520 if (dt_params[i].size == sizeof(u32))
521 *(u32 *)dest = val;
522 else
523 *(u64 *)dest = val;
524
Leif Lindholm7968c0e2015-08-26 14:24:58 +0100525 if (efi_enabled(EFI_DBG))
Mark Salter0302f712013-12-30 12:12:12 -0500526 pr_info(" %s: 0x%0*llx\n", dt_params[i].name,
527 dt_params[i].size * 2, val);
528 }
529 return 1;
530}
531
Leif Lindholm7968c0e2015-08-26 14:24:58 +0100532int __init efi_get_fdt_params(struct efi_fdt_params *params)
Mark Salter0302f712013-12-30 12:12:12 -0500533{
534 struct param_info info;
Catalin Marinas29e24352014-07-08 16:54:18 +0100535 int ret;
536
537 pr_info("Getting EFI parameters from FDT:\n");
Mark Salter0302f712013-12-30 12:12:12 -0500538
Catalin Marinas29e24352014-07-08 16:54:18 +0100539 info.found = 0;
Mark Salter0302f712013-12-30 12:12:12 -0500540 info.params = params;
541
Catalin Marinas29e24352014-07-08 16:54:18 +0100542 ret = of_scan_flat_dt(fdt_find_uefi_params, &info);
543 if (!info.found)
544 pr_info("UEFI not found.\n");
545 else if (!ret)
546 pr_err("Can't find '%s' in device tree!\n",
547 dt_params[info.found].name);
548
549 return ret;
Mark Salter0302f712013-12-30 12:12:12 -0500550}
551#endif /* CONFIG_EFI_PARAMS_FROM_FDT */
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200552
553static __initdata char memory_type_name[][20] = {
554 "Reserved",
555 "Loader Code",
556 "Loader Data",
557 "Boot Code",
558 "Boot Data",
559 "Runtime Code",
560 "Runtime Data",
561 "Conventional Memory",
562 "Unusable Memory",
563 "ACPI Reclaim Memory",
564 "ACPI Memory NVS",
565 "Memory Mapped I/O",
566 "MMIO Port Space",
567 "PAL Code"
568};
569
570char * __init efi_md_typeattr_format(char *buf, size_t size,
571 const efi_memory_desc_t *md)
572{
573 char *pos;
574 int type_len;
575 u64 attr;
576
577 pos = buf;
578 if (md->type >= ARRAY_SIZE(memory_type_name))
579 type_len = snprintf(pos, size, "[type=%u", md->type);
580 else
581 type_len = snprintf(pos, size, "[%-*s",
582 (int)(sizeof(memory_type_name[0]) - 1),
583 memory_type_name[md->type]);
584 if (type_len >= size)
585 return buf;
586
587 pos += type_len;
588 size -= type_len;
589
590 attr = md->attribute;
591 if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
Ard Biesheuvel87db73ae2015-08-07 09:36:54 +0100592 EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO |
593 EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP |
594 EFI_MEMORY_RUNTIME))
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200595 snprintf(pos, size, "|attr=0x%016llx]",
596 (unsigned long long)attr);
597 else
Ard Biesheuvel87db73ae2015-08-07 09:36:54 +0100598 snprintf(pos, size, "|%3s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200599 attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
600 attr & EFI_MEMORY_XP ? "XP" : "",
601 attr & EFI_MEMORY_RP ? "RP" : "",
602 attr & EFI_MEMORY_WP ? "WP" : "",
Ard Biesheuvel87db73ae2015-08-07 09:36:54 +0100603 attr & EFI_MEMORY_RO ? "RO" : "",
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200604 attr & EFI_MEMORY_UCE ? "UCE" : "",
605 attr & EFI_MEMORY_WB ? "WB" : "",
606 attr & EFI_MEMORY_WT ? "WT" : "",
607 attr & EFI_MEMORY_WC ? "WC" : "",
608 attr & EFI_MEMORY_UC ? "UC" : "");
609 return buf;
610}
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100611
612/*
613 * efi_mem_attributes - lookup memmap attributes for physical address
614 * @phys_addr: the physical address to lookup
615 *
616 * Search in the EFI memory map for the region covering
617 * @phys_addr. Returns the EFI memory attributes if the region
618 * was found in the memory map, 0 otherwise.
619 *
620 * Despite being marked __weak, most architectures should *not*
621 * override this function. It is __weak solely for the benefit
622 * of ia64 which has a funky EFI memory map that doesn't work
623 * the same way as other architectures.
624 */
625u64 __weak efi_mem_attributes(unsigned long phys_addr)
626{
Matt Fleming0ce423b2015-10-03 23:26:07 +0100627 struct efi_memory_map *map;
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100628 efi_memory_desc_t *md;
629 void *p;
630
631 if (!efi_enabled(EFI_MEMMAP))
632 return 0;
633
Matt Fleming0ce423b2015-10-03 23:26:07 +0100634 map = efi.memmap;
635 for (p = map->map; p < map->map_end; p += map->desc_size) {
Jonathan (Zhixiong) Zhang7bf79312015-08-07 09:36:57 +0100636 md = p;
637 if ((md->phys_addr <= phys_addr) &&
638 (phys_addr < (md->phys_addr +
639 (md->num_pages << EFI_PAGE_SHIFT))))
640 return md->attribute;
641 }
642 return 0;
643}