blob: 9fa8084a7c8d7d9e5aff23bdd372af512e39047a [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 +000069
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);
Jean Delvareb119fe02015-04-30 15:23:05 +020088 /*
89 * If both SMBIOS and SMBIOS3 entry points are implemented, the
90 * SMBIOS3 entry point shall be preferred, so we list it first to
91 * let applications stop parsing after the first match.
92 */
Ard Biesheuvele1ccbbc2014-10-14 16:34:47 +020093 if (efi.smbios3 != EFI_INVALID_TABLE_ADDR)
94 str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3);
Jean Delvareb119fe02015-04-30 15:23:05 +020095 if (efi.smbios != EFI_INVALID_TABLE_ADDR)
96 str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
Tom Gundersena9499fa2013-02-08 15:37:06 +000097 if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
98 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
99 if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
100 str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
101 if (efi.uga != EFI_INVALID_TABLE_ADDR)
102 str += sprintf(str, "UGA=0x%lx\n", efi.uga);
103
104 return str - buf;
105}
106
107static struct kobj_attribute efi_attr_systab =
108 __ATTR(systab, 0400, systab_show, NULL);
109
Dave Younga0998eb2013-12-20 18:02:17 +0800110#define EFI_FIELD(var) efi.var
111
112#define EFI_ATTR_SHOW(name) \
113static ssize_t name##_show(struct kobject *kobj, \
114 struct kobj_attribute *attr, char *buf) \
115{ \
116 return sprintf(buf, "0x%lx\n", EFI_FIELD(name)); \
117}
118
119EFI_ATTR_SHOW(fw_vendor);
120EFI_ATTR_SHOW(runtime);
121EFI_ATTR_SHOW(config_table);
122
Steve McIntyre2859dff2015-01-09 15:29:53 +0000123static ssize_t fw_platform_size_show(struct kobject *kobj,
124 struct kobj_attribute *attr, char *buf)
125{
126 return sprintf(buf, "%d\n", efi_enabled(EFI_64BIT) ? 64 : 32);
127}
128
Dave Younga0998eb2013-12-20 18:02:17 +0800129static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor);
130static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
131static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);
Steve McIntyre2859dff2015-01-09 15:29:53 +0000132static struct kobj_attribute efi_attr_fw_platform_size =
133 __ATTR_RO(fw_platform_size);
Dave Younga0998eb2013-12-20 18:02:17 +0800134
Tom Gundersena9499fa2013-02-08 15:37:06 +0000135static struct attribute *efi_subsys_attrs[] = {
136 &efi_attr_systab.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800137 &efi_attr_fw_vendor.attr,
138 &efi_attr_runtime.attr,
139 &efi_attr_config_table.attr,
Steve McIntyre2859dff2015-01-09 15:29:53 +0000140 &efi_attr_fw_platform_size.attr,
Dave Younga0998eb2013-12-20 18:02:17 +0800141 NULL,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000142};
143
Dave Younga0998eb2013-12-20 18:02:17 +0800144static umode_t efi_attr_is_visible(struct kobject *kobj,
145 struct attribute *attr, int n)
146{
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200147 if (attr == &efi_attr_fw_vendor.attr) {
148 if (efi_enabled(EFI_PARAVIRT) ||
149 efi.fw_vendor == EFI_INVALID_TABLE_ADDR)
150 return 0;
151 } else if (attr == &efi_attr_runtime.attr) {
152 if (efi.runtime == EFI_INVALID_TABLE_ADDR)
153 return 0;
154 } else if (attr == &efi_attr_config_table.attr) {
155 if (efi.config_table == EFI_INVALID_TABLE_ADDR)
156 return 0;
157 }
Dave Younga0998eb2013-12-20 18:02:17 +0800158
Daniel Kiper9f27bc52014-06-30 19:52:58 +0200159 return attr->mode;
Dave Younga0998eb2013-12-20 18:02:17 +0800160}
161
Tom Gundersena9499fa2013-02-08 15:37:06 +0000162static struct attribute_group efi_subsys_attr_group = {
163 .attrs = efi_subsys_attrs,
Dave Younga0998eb2013-12-20 18:02:17 +0800164 .is_visible = efi_attr_is_visible,
Tom Gundersena9499fa2013-02-08 15:37:06 +0000165};
166
167static struct efivars generic_efivars;
168static struct efivar_operations generic_ops;
169
170static int generic_ops_register(void)
171{
172 generic_ops.get_variable = efi.get_variable;
173 generic_ops.set_variable = efi.set_variable;
174 generic_ops.get_next_variable = efi.get_next_variable;
Matt Fleminga614e192013-04-30 11:30:24 +0100175 generic_ops.query_variable_store = efi_query_variable_store;
Tom Gundersena9499fa2013-02-08 15:37:06 +0000176
177 return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
178}
179
180static void generic_ops_unregister(void)
181{
182 efivars_unregister(&generic_efivars);
183}
184
185/*
186 * We register the efi subsystem with the firmware subsystem and the
187 * efivars subsystem with the efi subsystem, if the system was booted with
188 * EFI.
189 */
190static int __init efisubsys_init(void)
191{
192 int error;
193
194 if (!efi_enabled(EFI_BOOT))
195 return 0;
196
197 /* We register the efi directory at /sys/firmware/efi */
198 efi_kobj = kobject_create_and_add("efi", firmware_kobj);
199 if (!efi_kobj) {
200 pr_err("efi: Firmware registration failed.\n");
201 return -ENOMEM;
202 }
203
204 error = generic_ops_register();
205 if (error)
206 goto err_put;
207
208 error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
209 if (error) {
210 pr_err("efi: Sysfs attribute export failed with error %d.\n",
211 error);
212 goto err_unregister;
213 }
214
Dave Young926172d2013-12-20 18:02:18 +0800215 error = efi_runtime_map_init(efi_kobj);
216 if (error)
217 goto err_remove_group;
218
Tom Gundersena9499fa2013-02-08 15:37:06 +0000219 /* and the standard mountpoint for efivarfs */
Eric W. Biedermanf9bb4882015-05-13 17:35:41 -0500220 error = sysfs_create_mount_point(efi_kobj, "efivars");
221 if (error) {
Tom Gundersena9499fa2013-02-08 15:37:06 +0000222 pr_err("efivars: Subsystem registration failed.\n");
Tom Gundersena9499fa2013-02-08 15:37:06 +0000223 goto err_remove_group;
224 }
225
226 return 0;
227
228err_remove_group:
229 sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
230err_unregister:
231 generic_ops_unregister();
232err_put:
233 kobject_put(efi_kobj);
234 return error;
235}
236
237subsys_initcall(efisubsys_init);
Leif Lindholm272686b2013-09-05 11:34:54 +0100238
Peter Jones0bb54902015-04-28 18:44:31 -0400239/*
240 * Find the efi memory descriptor for a given physical address. Given a
241 * physicall address, determine if it exists within an EFI Memory Map entry,
242 * and if so, populate the supplied memory descriptor with the appropriate
243 * data.
244 */
245int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
246{
247 struct efi_memory_map *map = efi.memmap;
248 void *p, *e;
249
250 if (!efi_enabled(EFI_MEMMAP)) {
251 pr_err_once("EFI_MEMMAP is not enabled.\n");
252 return -EINVAL;
253 }
254
255 if (!map) {
256 pr_err_once("efi.memmap is not set.\n");
257 return -EINVAL;
258 }
259 if (!out_md) {
260 pr_err_once("out_md is null.\n");
261 return -EINVAL;
262 }
263 if (WARN_ON_ONCE(!map->phys_map))
264 return -EINVAL;
265 if (WARN_ON_ONCE(map->nr_map == 0) || WARN_ON_ONCE(map->desc_size == 0))
266 return -EINVAL;
267
268 e = map->phys_map + map->nr_map * map->desc_size;
269 for (p = map->phys_map; p < e; p += map->desc_size) {
270 efi_memory_desc_t *md;
271 u64 size;
272 u64 end;
273
274 /*
275 * If a driver calls this after efi_free_boot_services,
276 * ->map will be NULL, and the target may also not be mapped.
277 * So just always get our own virtual map on the CPU.
278 *
279 */
280 md = early_memremap((phys_addr_t)p, sizeof (*md));
281 if (!md) {
282 pr_err_once("early_memremap(%p, %zu) failed.\n",
283 p, sizeof (*md));
284 return -ENOMEM;
285 }
286
287 if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
288 md->type != EFI_BOOT_SERVICES_DATA &&
289 md->type != EFI_RUNTIME_SERVICES_DATA) {
290 early_memunmap(md, sizeof (*md));
291 continue;
292 }
293
294 size = md->num_pages << EFI_PAGE_SHIFT;
295 end = md->phys_addr + size;
296 if (phys_addr >= md->phys_addr && phys_addr < end) {
297 memcpy(out_md, md, sizeof(*out_md));
298 early_memunmap(md, sizeof (*md));
299 return 0;
300 }
301
302 early_memunmap(md, sizeof (*md));
303 }
304 pr_err_once("requested map not found.\n");
305 return -ENOENT;
306}
307
308/*
309 * Calculate the highest address of an efi memory descriptor.
310 */
311u64 __init efi_mem_desc_end(efi_memory_desc_t *md)
312{
313 u64 size = md->num_pages << EFI_PAGE_SHIFT;
314 u64 end = md->phys_addr + size;
315 return end;
316}
Leif Lindholm272686b2013-09-05 11:34:54 +0100317
Leif Lindholm258f6fd2013-09-05 11:34:55 +0100318/*
319 * We can't ioremap data in EFI boot services RAM, because we've already mapped
320 * it as RAM. So, look it up in the existing EFI memory map instead. Only
321 * callable after efi_enter_virtual_mode and before efi_free_boot_services.
322 */
323void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
324{
325 struct efi_memory_map *map;
326 void *p;
327 map = efi.memmap;
328 if (!map)
329 return NULL;
330 if (WARN_ON(!map->map))
331 return NULL;
332 for (p = map->map; p < map->map_end; p += map->desc_size) {
333 efi_memory_desc_t *md = p;
334 u64 size = md->num_pages << EFI_PAGE_SHIFT;
335 u64 end = md->phys_addr + size;
336 if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
337 md->type != EFI_BOOT_SERVICES_CODE &&
338 md->type != EFI_BOOT_SERVICES_DATA)
339 continue;
340 if (!md->virt_addr)
341 continue;
342 if (phys_addr >= md->phys_addr && phys_addr < end) {
343 phys_addr += md->virt_addr - md->phys_addr;
344 return (__force void __iomem *)(unsigned long)phys_addr;
345 }
346 }
347 return NULL;
348}
349
Leif Lindholm272686b2013-09-05 11:34:54 +0100350static __initdata efi_config_table_type_t common_tables[] = {
351 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
352 {ACPI_TABLE_GUID, "ACPI", &efi.acpi},
353 {HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
354 {MPS_TABLE_GUID, "MPS", &efi.mps},
355 {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
356 {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
Ard Biesheuvele1ccbbc2014-10-14 16:34:47 +0200357 {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
Leif Lindholm272686b2013-09-05 11:34:54 +0100358 {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
Peter Jones0bb54902015-04-28 18:44:31 -0400359 {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
Daeseok Youn69e60842014-02-13 17:16:36 +0900360 {NULL_GUID, NULL, NULL},
Leif Lindholm272686b2013-09-05 11:34:54 +0100361};
362
363static __init int match_config_table(efi_guid_t *guid,
364 unsigned long table,
365 efi_config_table_type_t *table_types)
366{
Leif Lindholm272686b2013-09-05 11:34:54 +0100367 int i;
368
369 if (table_types) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100370 for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
Leif Lindholm272686b2013-09-05 11:34:54 +0100371 if (!efi_guidcmp(*guid, table_types[i].guid)) {
372 *(table_types[i].ptr) = table;
373 pr_cont(" %s=0x%lx ",
374 table_types[i].name, table);
375 return 1;
376 }
377 }
378 }
379
380 return 0;
381}
382
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200383int __init efi_config_parse_tables(void *config_tables, int count, int sz,
384 efi_config_table_type_t *arch_tables)
385{
386 void *tablep;
387 int i;
388
389 tablep = config_tables;
390 pr_info("");
391 for (i = 0; i < count; i++) {
392 efi_guid_t guid;
393 unsigned long table;
394
395 if (efi_enabled(EFI_64BIT)) {
396 u64 table64;
397 guid = ((efi_config_table_64_t *)tablep)->guid;
398 table64 = ((efi_config_table_64_t *)tablep)->table;
399 table = table64;
400#ifndef CONFIG_64BIT
401 if (table64 >> 32) {
402 pr_cont("\n");
403 pr_err("Table located above 4GB, disabling EFI.\n");
404 return -EINVAL;
405 }
406#endif
407 } else {
408 guid = ((efi_config_table_32_t *)tablep)->guid;
409 table = ((efi_config_table_32_t *)tablep)->table;
410 }
411
412 if (!match_config_table(&guid, table, common_tables))
413 match_config_table(&guid, table, arch_tables);
414
415 tablep += sz;
416 }
417 pr_cont("\n");
418 set_bit(EFI_CONFIG_TABLES, &efi.flags);
419 return 0;
420}
421
Leif Lindholm272686b2013-09-05 11:34:54 +0100422int __init efi_config_init(efi_config_table_type_t *arch_tables)
423{
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200424 void *config_tables;
425 int sz, ret;
Leif Lindholm272686b2013-09-05 11:34:54 +0100426
427 if (efi_enabled(EFI_64BIT))
428 sz = sizeof(efi_config_table_64_t);
429 else
430 sz = sizeof(efi_config_table_32_t);
431
432 /*
433 * Let's see what config tables the firmware passed to us.
434 */
435 config_tables = early_memremap(efi.systab->tables,
436 efi.systab->nr_tables * sz);
437 if (config_tables == NULL) {
438 pr_err("Could not map Configuration table!\n");
439 return -ENOMEM;
440 }
441
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200442 ret = efi_config_parse_tables(config_tables, efi.systab->nr_tables, sz,
443 arch_tables);
Leif Lindholm272686b2013-09-05 11:34:54 +0100444
Daniel Kiperabc93f82014-06-30 19:52:56 +0200445 early_memunmap(config_tables, efi.systab->nr_tables * sz);
Ard Biesheuvel7bb68412014-10-18 15:04:15 +0200446 return ret;
Leif Lindholm272686b2013-09-05 11:34:54 +0100447}
Mark Salter0302f712013-12-30 12:12:12 -0500448
Lee, Chun-Yi28d54022014-07-09 18:39:29 +0800449#ifdef CONFIG_EFI_VARS_MODULE
450static int __init efi_load_efivars(void)
451{
452 struct platform_device *pdev;
453
454 if (!efi_enabled(EFI_RUNTIME_SERVICES))
455 return 0;
456
457 pdev = platform_device_register_simple("efivars", 0, NULL, 0);
458 return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
459}
460device_initcall(efi_load_efivars);
461#endif
462
Mark Salter0302f712013-12-30 12:12:12 -0500463#ifdef CONFIG_EFI_PARAMS_FROM_FDT
464
465#define UEFI_PARAM(name, prop, field) \
466 { \
467 { name }, \
468 { prop }, \
469 offsetof(struct efi_fdt_params, field), \
470 FIELD_SIZEOF(struct efi_fdt_params, field) \
471 }
472
473static __initdata struct {
474 const char name[32];
475 const char propname[32];
476 int offset;
477 int size;
478} dt_params[] = {
479 UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
480 UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
481 UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
482 UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
483 UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
484};
485
486struct param_info {
487 int verbose;
Catalin Marinas29e24352014-07-08 16:54:18 +0100488 int found;
Mark Salter0302f712013-12-30 12:12:12 -0500489 void *params;
490};
491
492static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
493 int depth, void *data)
494{
495 struct param_info *info = data;
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100496 const void *prop;
497 void *dest;
Mark Salter0302f712013-12-30 12:12:12 -0500498 u64 val;
Catalin Marinas6fb8cc82014-06-02 11:31:06 +0100499 int i, len;
Mark Salter0302f712013-12-30 12:12:12 -0500500
Leif Lindholm11629302015-01-20 16:34:38 +0000501 if (depth != 1 || strcmp(uname, "chosen") != 0)
Mark Salter0302f712013-12-30 12:12:12 -0500502 return 0;
503
Mark Salter0302f712013-12-30 12:12:12 -0500504 for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
505 prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
Catalin Marinas29e24352014-07-08 16:54:18 +0100506 if (!prop)
Mark Salter0302f712013-12-30 12:12:12 -0500507 return 0;
Mark Salter0302f712013-12-30 12:12:12 -0500508 dest = info->params + dt_params[i].offset;
Catalin Marinas29e24352014-07-08 16:54:18 +0100509 info->found++;
Mark Salter0302f712013-12-30 12:12:12 -0500510
511 val = of_read_number(prop, len / sizeof(u32));
512
513 if (dt_params[i].size == sizeof(u32))
514 *(u32 *)dest = val;
515 else
516 *(u64 *)dest = val;
517
518 if (info->verbose)
519 pr_info(" %s: 0x%0*llx\n", dt_params[i].name,
520 dt_params[i].size * 2, val);
521 }
522 return 1;
523}
524
525int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
526{
527 struct param_info info;
Catalin Marinas29e24352014-07-08 16:54:18 +0100528 int ret;
529
530 pr_info("Getting EFI parameters from FDT:\n");
Mark Salter0302f712013-12-30 12:12:12 -0500531
532 info.verbose = verbose;
Catalin Marinas29e24352014-07-08 16:54:18 +0100533 info.found = 0;
Mark Salter0302f712013-12-30 12:12:12 -0500534 info.params = params;
535
Catalin Marinas29e24352014-07-08 16:54:18 +0100536 ret = of_scan_flat_dt(fdt_find_uefi_params, &info);
537 if (!info.found)
538 pr_info("UEFI not found.\n");
539 else if (!ret)
540 pr_err("Can't find '%s' in device tree!\n",
541 dt_params[info.found].name);
542
543 return ret;
Mark Salter0302f712013-12-30 12:12:12 -0500544}
545#endif /* CONFIG_EFI_PARAMS_FROM_FDT */
Laszlo Ersek98d2a6c2014-09-03 13:32:20 +0200546
547static __initdata char memory_type_name[][20] = {
548 "Reserved",
549 "Loader Code",
550 "Loader Data",
551 "Boot Code",
552 "Boot Data",
553 "Runtime Code",
554 "Runtime Data",
555 "Conventional Memory",
556 "Unusable Memory",
557 "ACPI Reclaim Memory",
558 "ACPI Memory NVS",
559 "Memory Mapped I/O",
560 "MMIO Port Space",
561 "PAL Code"
562};
563
564char * __init efi_md_typeattr_format(char *buf, size_t size,
565 const efi_memory_desc_t *md)
566{
567 char *pos;
568 int type_len;
569 u64 attr;
570
571 pos = buf;
572 if (md->type >= ARRAY_SIZE(memory_type_name))
573 type_len = snprintf(pos, size, "[type=%u", md->type);
574 else
575 type_len = snprintf(pos, size, "[%-*s",
576 (int)(sizeof(memory_type_name[0]) - 1),
577 memory_type_name[md->type]);
578 if (type_len >= size)
579 return buf;
580
581 pos += type_len;
582 size -= type_len;
583
584 attr = md->attribute;
585 if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
586 EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP |
587 EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RUNTIME))
588 snprintf(pos, size, "|attr=0x%016llx]",
589 (unsigned long long)attr);
590 else
591 snprintf(pos, size, "|%3s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
592 attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
593 attr & EFI_MEMORY_XP ? "XP" : "",
594 attr & EFI_MEMORY_RP ? "RP" : "",
595 attr & EFI_MEMORY_WP ? "WP" : "",
596 attr & EFI_MEMORY_UCE ? "UCE" : "",
597 attr & EFI_MEMORY_WB ? "WB" : "",
598 attr & EFI_MEMORY_WT ? "WT" : "",
599 attr & EFI_MEMORY_WC ? "WC" : "",
600 attr & EFI_MEMORY_UC ? "UC" : "");
601 return buf;
602}