blob: ca617f40574ac2bb8e5697b858a1c52f93c8fad9 [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{
61 if (parse_option_str(str, "noruntime"))
62 disable_runtime = true;
63
64 return 0;
65}
66early_param("efi", parse_efi_cmdline);
67
Peter Jones0bb54902015-04-28 18:44:31 -040068struct kobject *efi_kobj;
Tom Gundersena9499fa2013-02-08 15:37:06 +000069static struct kobject *efivars_kobj;
70
71/*
72 * Let's not leave out systab information that snuck into
73 * the efivars driver
74 */
75static ssize_t systab_show(struct kobject *kobj,
76 struct kobj_attribute *attr, char *buf)
77{
78 char *str = buf;
79
80 if (!kobj || !buf)
81 return -EINVAL;
82
83 if (efi.mps != EFI_INVALID_TABLE_ADDR)
84 str += sprintf(str, "MPS=0x%lx\n", efi.mps);
85 if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
86 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
87 if (efi.acpi != EFI_INVALID_TABLE_ADDR)
88 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
Jean Delvareb119fe02015-04-30 15:23:05 +020089 /*
90 * If both SMBIOS and SMBIOS3 entry points are implemented, the
91 * SMBIOS3 entry point shall be preferred, so we list it first to
92 * let applications stop parsing after the first match.
93 */
Ard Biesheuvele1ccbbc2014-10-14 16:34:47 +020094 if (efi.smbios3 != EFI_INVALID_TABLE_ADDR)
95 str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3);
Jean Delvareb119fe02015-04-30 15:23:05 +020096 if (efi.smbios != EFI_INVALID_TABLE_ADDR)
97 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
Tom Gundersena9499fa2013-02-08 15:37:06 +000098 if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
99 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
100 if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
101 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
102 if (efi.uga != EFI_INVALID_TABLE_ADDR)
103 str += sprintf(str, "UGA=0x%lx\n", efi.uga);
104
105 return str - buf;
106}
107
108static struct kobj_attribute efi_attr_systab =
109 __ATTR(systab, 0400, systab_show, NULL);
110
Dave Younga0998eb2013-12-20 18:02:17 +0800111#define EFI_FIELD(var) efi.var
112
113#define EFI_ATTR_SHOW(name) \
114static ssize_t name##_show(struct kobject *kobj, \
115 struct kobj_attribute *attr, char *buf) \
116{ \
117 return sprintf(buf, "0x%lx\n", EFI_FIELD(name)); \
118}
119
120EFI_ATTR_SHOW(fw_vendor);
121EFI_ATTR_SHOW(runtime);
122EFI_ATTR_SHOW(config_table);
123
Steve McIntyre2859dff2015-01-09 15:29:53 +0000124static ssize_t fw_platform_size_show(struct kobject *kobj,
125 struct kobj_attribute *attr, char *buf)
126{
127 return sprintf(buf, "%d\n", efi_enabled(EFI_64BIT) ? 64 : 32);
128}
129
Dave Younga0998eb2013-12-20 18:02:17 +0800130static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor);
131static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
132static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);
Steve McIntyre2859dff2015-01-09 15:29:53 +0000133static struct kobj_attribute efi_attr_fw_platform_size =
134 __ATTR_RO(fw_platform_size);
Dave Younga0998eb2013-12-20 18:02:17 +0800135
Tom Gundersena9499fa2013-02-08 15:37:06 +0000136static struct attribute *efi_subsys_attrs[] = {
137 &efi_attr_systab.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800138 &efi_attr_fw_vendor.attr,
139 &efi_attr_runtime.attr,
140 &efi_attr_config_table.attr,
Steve McIntyre2859dff2015-01-09 15:29:53 +0000141 &efi_attr_fw_platform_size.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800142 NULL,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000143};
144
Dave Younga0998eb2013-12-20 18:02:17 +0800145static umode_t efi_attr_is_visible(struct kobject *kobj,
146 struct attribute *attr, int n)
147{
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200148 if (attr == &efi_attr_fw_vendor.attr) {
149 if (efi_enabled(EFI_PARAVIRT) ||
150 efi.fw_vendor == EFI_INVALID_TABLE_ADDR)
151 return 0;
152 } else if (attr == &efi_attr_runtime.attr) {
153 if (efi.runtime == EFI_INVALID_TABLE_ADDR)
154 return 0;
155 } else if (attr == &efi_attr_config_table.attr) {
156 if (efi.config_table == EFI_INVALID_TABLE_ADDR)
157 return 0;
158 }
Dave Younga0998eb2013-12-20 18:02:17 +0800159
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200160 return attr->mode;
Dave Younga0998eb2013-12-20 18:02:17 +0800161}
162
Tom Gundersena9499fa2013-02-08 15:37:06 +0000163static struct attribute_group efi_subsys_attr_group = {
164 .attrs = efi_subsys_attrs,
Dave Younga0998eb2013-12-20 18:02:17 +0800165 .is_visible = efi_attr_is_visible,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000166};
167
168static struct efivars generic_efivars;
169static struct efivar_operations generic_ops;
170
171static int generic_ops_register(void)
172{
173 generic_ops.get_variable = efi.get_variable;
174 generic_ops.set_variable = efi.set_variable;
175 generic_ops.get_next_variable = efi.get_next_variable;
Matt Fleminga614e192013-04-30 11:30:24 +0100176 generic_ops.query_variable_store = efi_query_variable_store;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000177
178 return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
179}
180
181static void generic_ops_unregister(void)
182{
183 efivars_unregister(&generic_efivars);
184}
185
186/*
187 * We register the efi subsystem with the firmware subsystem and the
188 * efivars subsystem with the efi subsystem, if the system was booted with
189 * EFI.
190 */
191static int __init efisubsys_init(void)
192{
193 int error;
194
195 if (!efi_enabled(EFI_BOOT))
196 return 0;
197
198 /* We register the efi directory at /sys/firmware/efi */
199 efi_kobj = kobject_create_and_add("efi", firmware_kobj);
200 if (!efi_kobj) {
201 pr_err("efi: Firmware registration failed.\n");
202 return -ENOMEM;
203 }
204
205 error = generic_ops_register();
206 if (error)
207 goto err_put;
208
209 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
210 if (error) {
211 pr_err("efi: Sysfs attribute export failed with error %d.\n",
212 error);
213 goto err_unregister;
214 }
215
Dave Young926172d2013-12-20 18:02:18 +0800216 error = efi_runtime_map_init(efi_kobj);
217 if (error)
218 goto err_remove_group;
219
Tom Gundersena9499fa2013-02-08 15:37:06 +0000220 /* and the standard mountpoint for efivarfs */
221 efivars_kobj = kobject_create_and_add("efivars", efi_kobj);
222 if (!efivars_kobj) {
223 pr_err("efivars: Subsystem registration failed.\n");
224 error = -ENOMEM;
225 goto err_remove_group;
226 }
227
228 return 0;
229
230err_remove_group:
231 sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
232err_unregister:
233 generic_ops_unregister();
234err_put:
235 kobject_put(efi_kobj);
236 return error;
237}
238
239subsys_initcall(efisubsys_init);
Leif Lindholm272686b2013-09-05 11:34:54 +0100240
Peter Jones0bb54902015-04-28 18:44:31 -0400241/*
242 * Find the efi memory descriptor for a given physical address. Given a
243 * physicall address, determine if it exists within an EFI Memory Map entry,
244 * and if so, populate the supplied memory descriptor with the appropriate
245 * data.
246 */
247int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
248{
249 struct efi_memory_map *map = efi.memmap;
250 void *p, *e;
251
252 if (!efi_enabled(EFI_MEMMAP)) {
253 pr_err_once("EFI_MEMMAP is not enabled.\n");
254 return -EINVAL;
255 }
256
257 if (!map) {
258 pr_err_once("efi.memmap is not set.\n");
259 return -EINVAL;
260 }
261 if (!out_md) {
262 pr_err_once("out_md is null.\n");
263 return -EINVAL;
264 }
265 if (WARN_ON_ONCE(!map->phys_map))
266 return -EINVAL;
267 if (WARN_ON_ONCE(map->nr_map == 0) || WARN_ON_ONCE(map->desc_size == 0))
268 return -EINVAL;
269
270 e = map->phys_map + map->nr_map * map->desc_size;
271 for (p = map->phys_map; p < e; p += map->desc_size) {
272 efi_memory_desc_t *md;
273 u64 size;
274 u64 end;
275
276 /*
277 * If a driver calls this after efi_free_boot_services,
278 * ->map will be NULL, and the target may also not be mapped.
279 * So just always get our own virtual map on the CPU.
280 *
281 */
282 md = early_memremap((phys_addr_t)p, sizeof (*md));
283 if (!md) {
284 pr_err_once("early_memremap(%p, %zu) failed.\n",
285 p, sizeof (*md));
286 return -ENOMEM;
287 }
288
289 if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
290 md->type != EFI_BOOT_SERVICES_DATA &&
291 md->type != EFI_RUNTIME_SERVICES_DATA) {
292 early_memunmap(md, sizeof (*md));
293 continue;
294 }
295
296 size = md->num_pages << EFI_PAGE_SHIFT;
297 end = md->phys_addr + size;
298 if (phys_addr >= md->phys_addr && phys_addr < end) {
299 memcpy(out_md, md, sizeof(*out_md));
300 early_memunmap(md, sizeof (*md));
301 return 0;
302 }
303
304 early_memunmap(md, sizeof (*md));
305 }
306 pr_err_once("requested map not found.\n");
307 return -ENOENT;
308}
309
310/*
311 * Calculate the highest address of an efi memory descriptor.
312 */
313u64 __init efi_mem_desc_end(efi_memory_desc_t *md)
314{
315 u64 size = md->num_pages << EFI_PAGE_SHIFT;
316 u64 end = md->phys_addr + size;
317 return end;
318}
Leif Lindholm272686b2013-09-05 11:34:54 +0100319
Leif Lindholm258f6fd2013-09-05 11:34:55 +0100320/*
321 * We can't ioremap data in EFI boot services RAM, because we've already mapped
322 * it as RAM. So, look it up in the existing EFI memory map instead. Only
323 * callable after efi_enter_virtual_mode and before efi_free_boot_services.
324 */
325void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
326{
327 struct efi_memory_map *map;
328 void *p;
329 map = efi.memmap;
330 if (!map)
331 return NULL;
332 if (WARN_ON(!map->map))
333 return NULL;
334 for (p = map->map; p < map->map_end; p += map->desc_size) {
335 efi_memory_desc_t *md = p;
336 u64 size = md->num_pages << EFI_PAGE_SHIFT;
337 u64 end = md->phys_addr + size;
338 if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
339 md->type != EFI_BOOT_SERVICES_CODE &&
340 md->type != EFI_BOOT_SERVICES_DATA)
341 continue;
342 if (!md->virt_addr)
343 continue;
344 if (phys_addr >= md->phys_addr && phys_addr < end) {
345 phys_addr += md->virt_addr - md->phys_addr;
346 return (__force void __iomem *)(unsigned long)phys_addr;
347 }
348 }
349 return NULL;
350}
351
Leif Lindholm272686b2013-09-05 11:34:54 +0100352static __initdata efi_config_table_type_t common_tables[] = {
353 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
354 {ACPI_TABLE_GUID, "ACPI", &efi.acpi},
355 {HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
356 {MPS_TABLE_GUID, "MPS", &efi.mps},
357 {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
358 {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
Ard Biesheuvele1ccbbc2014-10-14 16:34:47 +0200359 {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
Leif Lindholm272686b2013-09-05 11:34:54 +0100360 {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
Peter Jones0bb54902015-04-28 18:44:31 -0400361 {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
Daeseok Youn69e60842014-02-13 17:16:36 +0900362 {NULL_GUID, NULL, NULL},
Leif Lindholm272686b2013-09-05 11:34:54 +0100363};
364
365static __init int match_config_table(efi_guid_t *guid,
366 unsigned long table,
367 efi_config_table_type_t *table_types)
368{
Leif Lindholm272686b2013-09-05 11:34:54 +0100369 int i;
370
371 if (table_types) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100372 for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100373 if (!efi_guidcmp(*guid, table_types[i].guid)) {
374 *(table_types[i].ptr) = table;
375 pr_cont(" %s=0x%lx ",
376 table_types[i].name, table);
377 return 1;
378 }
379 }
380 }
381
382 return 0;
383}
384
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200385int __init efi_config_parse_tables(void *config_tables, int count, int sz,
386 efi_config_table_type_t *arch_tables)
387{
388 void *tablep;
389 int i;
390
391 tablep = config_tables;
392 pr_info("");
393 for (i = 0; i < count; i++) {
394 efi_guid_t guid;
395 unsigned long table;
396
397 if (efi_enabled(EFI_64BIT)) {
398 u64 table64;
399 guid = ((efi_config_table_64_t *)tablep)->guid;
400 table64 = ((efi_config_table_64_t *)tablep)->table;
401 table = table64;
402#ifndef CONFIG_64BIT
403 if (table64 >> 32) {
404 pr_cont("\n");
405 pr_err("Table located above 4GB, disabling EFI.\n");
406 return -EINVAL;
407 }
408#endif
409 } else {
410 guid = ((efi_config_table_32_t *)tablep)->guid;
411 table = ((efi_config_table_32_t *)tablep)->table;
412 }
413
414 if (!match_config_table(&guid, table, common_tables))
415 match_config_table(&guid, table, arch_tables);
416
417 tablep += sz;
418 }
419 pr_cont("\n");
420 set_bit(EFI_CONFIG_TABLES, &efi.flags);
421 return 0;
422}
423
Leif Lindholm272686b2013-09-05 11:34:54 +0100424int __init efi_config_init(efi_config_table_type_t *arch_tables)
425{
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200426 void *config_tables;
427 int sz, ret;
Leif Lindholm272686b2013-09-05 11:34:54 +0100428
429 if (efi_enabled(EFI_64BIT))
430 sz = sizeof(efi_config_table_64_t);
431 else
432 sz = sizeof(efi_config_table_32_t);
433
434 /*
435 * Let's see what config tables the firmware passed to us.
436 */
437 config_tables = early_memremap(efi.systab->tables,
438 efi.systab->nr_tables * sz);
439 if (config_tables == NULL) {
440 pr_err("Could not map Configuration table!\n");
441 return -ENOMEM;
442 }
443
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200444 ret = efi_config_parse_tables(config_tables, efi.systab->nr_tables, sz,
445 arch_tables);
Leif Lindholm272686b2013-09-05 11:34:54 +0100446
Daniel Kiperabc93f82014-06-30 19:52:56 +0200447 early_memunmap(config_tables, efi.systab->nr_tables * sz);
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200448 return ret;
Leif Lindholm272686b2013-09-05 11:34:54 +0100449}
Mark Salter0302f712013-12-30 12:12:12 -0500450
Lee, Chun-Yi28d54022014-07-09 18:39:29 +0800451#ifdef CONFIG_EFI_VARS_MODULE
452static int __init efi_load_efivars(void)
453{
454 struct platform_device *pdev;
455
456 if (!efi_enabled(EFI_RUNTIME_SERVICES))
457 return 0;
458
459 pdev = platform_device_register_simple("efivars", 0, NULL, 0);
460 return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
461}
462device_initcall(efi_load_efivars);
463#endif
464
Mark Salter0302f712013-12-30 12:12:12 -0500465#ifdef CONFIG_EFI_PARAMS_FROM_FDT
466
467#define UEFI_PARAM(name, prop, field) \
468 { \
469 { name }, \
470 { prop }, \
471 offsetof(struct efi_fdt_params, field), \
472 FIELD_SIZEOF(struct efi_fdt_params, field) \
473 }
474
475static __initdata struct {
476 const char name[32];
477 const char propname[32];
478 int offset;
479 int size;
480} dt_params[] = {
481 UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
482 UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
483 UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
484 UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
485 UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
486};
487
488struct param_info {
489 int verbose;
Catalin Marinas29e24352014-07-08 16:54:18 +0100490 int found;
Mark Salter0302f712013-12-30 12:12:12 -0500491 void *params;
492};
493
494static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
495 int depth, void *data)
496{
497 struct param_info *info = data;
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100498 const void *prop;
499 void *dest;
Mark Salter0302f712013-12-30 12:12:12 -0500500 u64 val;
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100501 int i, len;
Mark Salter0302f712013-12-30 12:12:12 -0500502
Leif Lindholm11629302015-01-20 16:34:38 +0000503 if (depth != 1 || strcmp(uname, "chosen") != 0)
Mark Salter0302f712013-12-30 12:12:12 -0500504 return 0;
505
Mark Salter0302f712013-12-30 12:12:12 -0500506 for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
507 prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
Catalin Marinas29e24352014-07-08 16:54:18 +0100508 if (!prop)
Mark Salter0302f712013-12-30 12:12:12 -0500509 return 0;
Mark Salter0302f712013-12-30 12:12:12 -0500510 dest = info->params + dt_params[i].offset;
Catalin Marinas29e24352014-07-08 16:54:18 +0100511 info->found++;
Mark Salter0302f712013-12-30 12:12:12 -0500512
513 val = of_read_number(prop, len / sizeof(u32));
514
515 if (dt_params[i].size == sizeof(u32))
516 *(u32 *)dest = val;
517 else
518 *(u64 *)dest = val;
519
520 if (info->verbose)
521 pr_info(" %s: 0x%0*llx\n", dt_params[i].name,
522 dt_params[i].size * 2, val);
523 }
524 return 1;
525}
526
527int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
528{
529 struct param_info info;
Catalin Marinas29e24352014-07-08 16:54:18 +0100530 int ret;
531
532 pr_info("Getting EFI parameters from FDT:\n");
Mark Salter0302f712013-12-30 12:12:12 -0500533
534 info.verbose = verbose;
Catalin Marinas29e24352014-07-08 16:54:18 +0100535 info.found = 0;
Mark Salter0302f712013-12-30 12:12:12 -0500536 info.params = params;
537
Catalin Marinas29e24352014-07-08 16:54:18 +0100538 ret = of_scan_flat_dt(fdt_find_uefi_params, &info);
539 if (!info.found)
540 pr_info("UEFI not found.\n");
541 else if (!ret)
542 pr_err("Can't find '%s' in device tree!\n",
543 dt_params[info.found].name);
544
545 return ret;
Mark Salter0302f712013-12-30 12:12:12 -0500546}
547#endif /* CONFIG_EFI_PARAMS_FROM_FDT */
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200548
549static __initdata char memory_type_name[][20] = {
550 "Reserved",
551 "Loader Code",
552 "Loader Data",
553 "Boot Code",
554 "Boot Data",
555 "Runtime Code",
556 "Runtime Data",
557 "Conventional Memory",
558 "Unusable Memory",
559 "ACPI Reclaim Memory",
560 "ACPI Memory NVS",
561 "Memory Mapped I/O",
562 "MMIO Port Space",
563 "PAL Code"
564};
565
566char * __init efi_md_typeattr_format(char *buf, size_t size,
567 const efi_memory_desc_t *md)
568{
569 char *pos;
570 int type_len;
571 u64 attr;
572
573 pos = buf;
574 if (md->type >= ARRAY_SIZE(memory_type_name))
575 type_len = snprintf(pos, size, "[type=%u", md->type);
576 else
577 type_len = snprintf(pos, size, "[%-*s",
578 (int)(sizeof(memory_type_name[0]) - 1),
579 memory_type_name[md->type]);
580 if (type_len >= size)
581 return buf;
582
583 pos += type_len;
584 size -= type_len;
585
586 attr = md->attribute;
587 if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
588 EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP |
589 EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RUNTIME))
590 snprintf(pos, size, "|attr=0x%016llx]",
591 (unsigned long long)attr);
592 else
593 snprintf(pos, size, "|%3s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
594 attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
595 attr & EFI_MEMORY_XP ? "XP" : "",
596 attr & EFI_MEMORY_RP ? "RP" : "",
597 attr & EFI_MEMORY_WP ? "WP" : "",
598 attr & EFI_MEMORY_UCE ? "UCE" : "",
599 attr & EFI_MEMORY_WB ? "WB" : "",
600 attr & EFI_MEMORY_WT ? "WT" : "",
601 attr & EFI_MEMORY_WC ? "WC" : "",
602 attr & EFI_MEMORY_UC ? "UC" : "");
603 return buf;
604}