xref: /openbmc/linux/drivers/firmware/efi/efi.c (revision 23c2b932)
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 
16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17 
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>
23 #include <linux/of.h>
24 #include <linux/of_fdt.h>
25 #include <linux/io.h>
26 #include <linux/platform_device.h>
27 
28 #include <asm/early_ioremap.h>
29 
30 struct efi __read_mostly efi = {
31 	.mps			= EFI_INVALID_TABLE_ADDR,
32 	.acpi			= EFI_INVALID_TABLE_ADDR,
33 	.acpi20			= EFI_INVALID_TABLE_ADDR,
34 	.smbios			= EFI_INVALID_TABLE_ADDR,
35 	.smbios3		= EFI_INVALID_TABLE_ADDR,
36 	.sal_systab		= EFI_INVALID_TABLE_ADDR,
37 	.boot_info		= EFI_INVALID_TABLE_ADDR,
38 	.hcdp			= EFI_INVALID_TABLE_ADDR,
39 	.uga			= EFI_INVALID_TABLE_ADDR,
40 	.uv_systab		= EFI_INVALID_TABLE_ADDR,
41 	.fw_vendor		= EFI_INVALID_TABLE_ADDR,
42 	.runtime		= EFI_INVALID_TABLE_ADDR,
43 	.config_table		= EFI_INVALID_TABLE_ADDR,
44 	.esrt			= EFI_INVALID_TABLE_ADDR,
45 	.properties_table	= EFI_INVALID_TABLE_ADDR,
46 	.mem_attr_table		= EFI_INVALID_TABLE_ADDR,
47 };
48 EXPORT_SYMBOL(efi);
49 
50 static bool disable_runtime;
51 static int __init setup_noefi(char *arg)
52 {
53 	disable_runtime = true;
54 	return 0;
55 }
56 early_param("noefi", setup_noefi);
57 
58 bool efi_runtime_disabled(void)
59 {
60 	return disable_runtime;
61 }
62 
63 static int __init parse_efi_cmdline(char *str)
64 {
65 	if (!str) {
66 		pr_warn("need at least one option\n");
67 		return -EINVAL;
68 	}
69 
70 	if (parse_option_str(str, "debug"))
71 		set_bit(EFI_DBG, &efi.flags);
72 
73 	if (parse_option_str(str, "noruntime"))
74 		disable_runtime = true;
75 
76 	return 0;
77 }
78 early_param("efi", parse_efi_cmdline);
79 
80 struct kobject *efi_kobj;
81 
82 /*
83  * Let's not leave out systab information that snuck into
84  * the efivars driver
85  */
86 static ssize_t systab_show(struct kobject *kobj,
87 			   struct kobj_attribute *attr, char *buf)
88 {
89 	char *str = buf;
90 
91 	if (!kobj || !buf)
92 		return -EINVAL;
93 
94 	if (efi.mps != EFI_INVALID_TABLE_ADDR)
95 		str += sprintf(str, "MPS=0x%lx\n", efi.mps);
96 	if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
97 		str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20);
98 	if (efi.acpi != EFI_INVALID_TABLE_ADDR)
99 		str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
100 	/*
101 	 * If both SMBIOS and SMBIOS3 entry points are implemented, the
102 	 * SMBIOS3 entry point shall be preferred, so we list it first to
103 	 * let applications stop parsing after the first match.
104 	 */
105 	if (efi.smbios3 != EFI_INVALID_TABLE_ADDR)
106 		str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3);
107 	if (efi.smbios != EFI_INVALID_TABLE_ADDR)
108 		str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
109 	if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
110 		str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
111 	if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
112 		str += sprintf(str, "BOOTINFO=0x%lx\n", efi.boot_info);
113 	if (efi.uga != EFI_INVALID_TABLE_ADDR)
114 		str += sprintf(str, "UGA=0x%lx\n", efi.uga);
115 
116 	return str - buf;
117 }
118 
119 static struct kobj_attribute efi_attr_systab =
120 			__ATTR(systab, 0400, systab_show, NULL);
121 
122 #define EFI_FIELD(var) efi.var
123 
124 #define EFI_ATTR_SHOW(name) \
125 static ssize_t name##_show(struct kobject *kobj, \
126 				struct kobj_attribute *attr, char *buf) \
127 { \
128 	return sprintf(buf, "0x%lx\n", EFI_FIELD(name)); \
129 }
130 
131 EFI_ATTR_SHOW(fw_vendor);
132 EFI_ATTR_SHOW(runtime);
133 EFI_ATTR_SHOW(config_table);
134 
135 static ssize_t fw_platform_size_show(struct kobject *kobj,
136 				     struct kobj_attribute *attr, char *buf)
137 {
138 	return sprintf(buf, "%d\n", efi_enabled(EFI_64BIT) ? 64 : 32);
139 }
140 
141 static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor);
142 static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
143 static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);
144 static struct kobj_attribute efi_attr_fw_platform_size =
145 	__ATTR_RO(fw_platform_size);
146 
147 static struct attribute *efi_subsys_attrs[] = {
148 	&efi_attr_systab.attr,
149 	&efi_attr_fw_vendor.attr,
150 	&efi_attr_runtime.attr,
151 	&efi_attr_config_table.attr,
152 	&efi_attr_fw_platform_size.attr,
153 	NULL,
154 };
155 
156 static umode_t efi_attr_is_visible(struct kobject *kobj,
157 				   struct attribute *attr, int n)
158 {
159 	if (attr == &efi_attr_fw_vendor.attr) {
160 		if (efi_enabled(EFI_PARAVIRT) ||
161 				efi.fw_vendor == EFI_INVALID_TABLE_ADDR)
162 			return 0;
163 	} else if (attr == &efi_attr_runtime.attr) {
164 		if (efi.runtime == EFI_INVALID_TABLE_ADDR)
165 			return 0;
166 	} else if (attr == &efi_attr_config_table.attr) {
167 		if (efi.config_table == EFI_INVALID_TABLE_ADDR)
168 			return 0;
169 	}
170 
171 	return attr->mode;
172 }
173 
174 static struct attribute_group efi_subsys_attr_group = {
175 	.attrs = efi_subsys_attrs,
176 	.is_visible = efi_attr_is_visible,
177 };
178 
179 static struct efivars generic_efivars;
180 static struct efivar_operations generic_ops;
181 
182 static int generic_ops_register(void)
183 {
184 	generic_ops.get_variable = efi.get_variable;
185 	generic_ops.set_variable = efi.set_variable;
186 	generic_ops.set_variable_nonblocking = efi.set_variable_nonblocking;
187 	generic_ops.get_next_variable = efi.get_next_variable;
188 	generic_ops.query_variable_store = efi_query_variable_store;
189 
190 	return efivars_register(&generic_efivars, &generic_ops, efi_kobj);
191 }
192 
193 static void generic_ops_unregister(void)
194 {
195 	efivars_unregister(&generic_efivars);
196 }
197 
198 /*
199  * We register the efi subsystem with the firmware subsystem and the
200  * efivars subsystem with the efi subsystem, if the system was booted with
201  * EFI.
202  */
203 static int __init efisubsys_init(void)
204 {
205 	int error;
206 
207 	if (!efi_enabled(EFI_BOOT))
208 		return 0;
209 
210 	/* We register the efi directory at /sys/firmware/efi */
211 	efi_kobj = kobject_create_and_add("efi", firmware_kobj);
212 	if (!efi_kobj) {
213 		pr_err("efi: Firmware registration failed.\n");
214 		return -ENOMEM;
215 	}
216 
217 	error = generic_ops_register();
218 	if (error)
219 		goto err_put;
220 
221 	error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
222 	if (error) {
223 		pr_err("efi: Sysfs attribute export failed with error %d.\n",
224 		       error);
225 		goto err_unregister;
226 	}
227 
228 	error = efi_runtime_map_init(efi_kobj);
229 	if (error)
230 		goto err_remove_group;
231 
232 	/* and the standard mountpoint for efivarfs */
233 	error = sysfs_create_mount_point(efi_kobj, "efivars");
234 	if (error) {
235 		pr_err("efivars: Subsystem registration failed.\n");
236 		goto err_remove_group;
237 	}
238 
239 	return 0;
240 
241 err_remove_group:
242 	sysfs_remove_group(efi_kobj, &efi_subsys_attr_group);
243 err_unregister:
244 	generic_ops_unregister();
245 err_put:
246 	kobject_put(efi_kobj);
247 	return error;
248 }
249 
250 subsys_initcall(efisubsys_init);
251 
252 /*
253  * Find the efi memory descriptor for a given physical address.  Given a
254  * physicall address, determine if it exists within an EFI Memory Map entry,
255  * and if so, populate the supplied memory descriptor with the appropriate
256  * data.
257  */
258 int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
259 {
260 	struct efi_memory_map *map = &efi.memmap;
261 	phys_addr_t p, e;
262 
263 	if (!efi_enabled(EFI_MEMMAP)) {
264 		pr_err_once("EFI_MEMMAP is not enabled.\n");
265 		return -EINVAL;
266 	}
267 
268 	if (!map) {
269 		pr_err_once("efi.memmap is not set.\n");
270 		return -EINVAL;
271 	}
272 	if (!out_md) {
273 		pr_err_once("out_md is null.\n");
274 		return -EINVAL;
275         }
276 	if (WARN_ON_ONCE(!map->phys_map))
277 		return -EINVAL;
278 	if (WARN_ON_ONCE(map->nr_map == 0) || WARN_ON_ONCE(map->desc_size == 0))
279 		return -EINVAL;
280 
281 	e = map->phys_map + map->nr_map * map->desc_size;
282 	for (p = map->phys_map; p < e; p += map->desc_size) {
283 		efi_memory_desc_t *md;
284 		u64 size;
285 		u64 end;
286 
287 		/*
288 		 * If a driver calls this after efi_free_boot_services,
289 		 * ->map will be NULL, and the target may also not be mapped.
290 		 * So just always get our own virtual map on the CPU.
291 		 *
292 		 */
293 		md = early_memremap(p, sizeof (*md));
294 		if (!md) {
295 			pr_err_once("early_memremap(%pa, %zu) failed.\n",
296 				    &p, sizeof (*md));
297 			return -ENOMEM;
298 		}
299 
300 		if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
301 		    md->type != EFI_BOOT_SERVICES_DATA &&
302 		    md->type != EFI_RUNTIME_SERVICES_DATA) {
303 			early_memunmap(md, sizeof (*md));
304 			continue;
305 		}
306 
307 		size = md->num_pages << EFI_PAGE_SHIFT;
308 		end = md->phys_addr + size;
309 		if (phys_addr >= md->phys_addr && phys_addr < end) {
310 			memcpy(out_md, md, sizeof(*out_md));
311 			early_memunmap(md, sizeof (*md));
312 			return 0;
313 		}
314 
315 		early_memunmap(md, sizeof (*md));
316 	}
317 	pr_err_once("requested map not found.\n");
318 	return -ENOENT;
319 }
320 
321 /*
322  * Calculate the highest address of an efi memory descriptor.
323  */
324 u64 __init efi_mem_desc_end(efi_memory_desc_t *md)
325 {
326 	u64 size = md->num_pages << EFI_PAGE_SHIFT;
327 	u64 end = md->phys_addr + size;
328 	return end;
329 }
330 
331 static __initdata efi_config_table_type_t common_tables[] = {
332 	{ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
333 	{ACPI_TABLE_GUID, "ACPI", &efi.acpi},
334 	{HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
335 	{MPS_TABLE_GUID, "MPS", &efi.mps},
336 	{SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
337 	{SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
338 	{SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
339 	{UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
340 	{EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
341 	{EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
342 	{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
343 	{NULL_GUID, NULL, NULL},
344 };
345 
346 static __init int match_config_table(efi_guid_t *guid,
347 				     unsigned long table,
348 				     efi_config_table_type_t *table_types)
349 {
350 	int i;
351 
352 	if (table_types) {
353 		for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
354 			if (!efi_guidcmp(*guid, table_types[i].guid)) {
355 				*(table_types[i].ptr) = table;
356 				if (table_types[i].name)
357 					pr_cont(" %s=0x%lx ",
358 						table_types[i].name, table);
359 				return 1;
360 			}
361 		}
362 	}
363 
364 	return 0;
365 }
366 
367 int __init efi_config_parse_tables(void *config_tables, int count, int sz,
368 				   efi_config_table_type_t *arch_tables)
369 {
370 	void *tablep;
371 	int i;
372 
373 	tablep = config_tables;
374 	pr_info("");
375 	for (i = 0; i < count; i++) {
376 		efi_guid_t guid;
377 		unsigned long table;
378 
379 		if (efi_enabled(EFI_64BIT)) {
380 			u64 table64;
381 			guid = ((efi_config_table_64_t *)tablep)->guid;
382 			table64 = ((efi_config_table_64_t *)tablep)->table;
383 			table = table64;
384 #ifndef CONFIG_64BIT
385 			if (table64 >> 32) {
386 				pr_cont("\n");
387 				pr_err("Table located above 4GB, disabling EFI.\n");
388 				return -EINVAL;
389 			}
390 #endif
391 		} else {
392 			guid = ((efi_config_table_32_t *)tablep)->guid;
393 			table = ((efi_config_table_32_t *)tablep)->table;
394 		}
395 
396 		if (!match_config_table(&guid, table, common_tables))
397 			match_config_table(&guid, table, arch_tables);
398 
399 		tablep += sz;
400 	}
401 	pr_cont("\n");
402 	set_bit(EFI_CONFIG_TABLES, &efi.flags);
403 
404 	/* Parse the EFI Properties table if it exists */
405 	if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
406 		efi_properties_table_t *tbl;
407 
408 		tbl = early_memremap(efi.properties_table, sizeof(*tbl));
409 		if (tbl == NULL) {
410 			pr_err("Could not map Properties table!\n");
411 			return -ENOMEM;
412 		}
413 
414 		if (tbl->memory_protection_attribute &
415 		    EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA)
416 			set_bit(EFI_NX_PE_DATA, &efi.flags);
417 
418 		early_memunmap(tbl, sizeof(*tbl));
419 	}
420 
421 	return 0;
422 }
423 
424 int __init efi_config_init(efi_config_table_type_t *arch_tables)
425 {
426 	void *config_tables;
427 	int sz, ret;
428 
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 
444 	ret = efi_config_parse_tables(config_tables, efi.systab->nr_tables, sz,
445 				      arch_tables);
446 
447 	early_memunmap(config_tables, efi.systab->nr_tables * sz);
448 	return ret;
449 }
450 
451 #ifdef CONFIG_EFI_VARS_MODULE
452 static 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 }
462 device_initcall(efi_load_efivars);
463 #endif
464 
465 #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 
475 static __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 
488 struct param_info {
489 	int found;
490 	void *params;
491 };
492 
493 static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
494 				       int depth, void *data)
495 {
496 	struct param_info *info = data;
497 	const void *prop;
498 	void *dest;
499 	u64 val;
500 	int i, len;
501 
502 	if (depth != 1 || strcmp(uname, "chosen") != 0)
503 		return 0;
504 
505 	for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
506 		prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
507 		if (!prop)
508 			return 0;
509 		dest = info->params + dt_params[i].offset;
510 		info->found++;
511 
512 		val = of_read_number(prop, len / sizeof(u32));
513 
514 		if (dt_params[i].size == sizeof(u32))
515 			*(u32 *)dest = val;
516 		else
517 			*(u64 *)dest = val;
518 
519 		if (efi_enabled(EFI_DBG))
520 			pr_info("  %s: 0x%0*llx\n", dt_params[i].name,
521 				dt_params[i].size * 2, val);
522 	}
523 	return 1;
524 }
525 
526 int __init efi_get_fdt_params(struct efi_fdt_params *params)
527 {
528 	struct param_info info;
529 	int ret;
530 
531 	pr_info("Getting EFI parameters from FDT:\n");
532 
533 	info.found = 0;
534 	info.params = params;
535 
536 	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;
544 }
545 #endif /* CONFIG_EFI_PARAMS_FROM_FDT */
546 
547 static __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 	"Persistent Memory",
563 };
564 
565 char * __init efi_md_typeattr_format(char *buf, size_t size,
566 				     const efi_memory_desc_t *md)
567 {
568 	char *pos;
569 	int type_len;
570 	u64 attr;
571 
572 	pos = buf;
573 	if (md->type >= ARRAY_SIZE(memory_type_name))
574 		type_len = snprintf(pos, size, "[type=%u", md->type);
575 	else
576 		type_len = snprintf(pos, size, "[%-*s",
577 				    (int)(sizeof(memory_type_name[0]) - 1),
578 				    memory_type_name[md->type]);
579 	if (type_len >= size)
580 		return buf;
581 
582 	pos += type_len;
583 	size -= type_len;
584 
585 	attr = md->attribute;
586 	if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
587 		     EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO |
588 		     EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP |
589 		     EFI_MEMORY_NV |
590 		     EFI_MEMORY_RUNTIME | EFI_MEMORY_MORE_RELIABLE))
591 		snprintf(pos, size, "|attr=0x%016llx]",
592 			 (unsigned long long)attr);
593 	else
594 		snprintf(pos, size,
595 			 "|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
596 			 attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
597 			 attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "",
598 			 attr & EFI_MEMORY_NV      ? "NV"  : "",
599 			 attr & EFI_MEMORY_XP      ? "XP"  : "",
600 			 attr & EFI_MEMORY_RP      ? "RP"  : "",
601 			 attr & EFI_MEMORY_WP      ? "WP"  : "",
602 			 attr & EFI_MEMORY_RO      ? "RO"  : "",
603 			 attr & EFI_MEMORY_UCE     ? "UCE" : "",
604 			 attr & EFI_MEMORY_WB      ? "WB"  : "",
605 			 attr & EFI_MEMORY_WT      ? "WT"  : "",
606 			 attr & EFI_MEMORY_WC      ? "WC"  : "",
607 			 attr & EFI_MEMORY_UC      ? "UC"  : "");
608 	return buf;
609 }
610 
611 /*
612  * efi_mem_attributes - lookup memmap attributes for physical address
613  * @phys_addr: the physical address to lookup
614  *
615  * Search in the EFI memory map for the region covering
616  * @phys_addr. Returns the EFI memory attributes if the region
617  * was found in the memory map, 0 otherwise.
618  *
619  * Despite being marked __weak, most architectures should *not*
620  * override this function. It is __weak solely for the benefit
621  * of ia64 which has a funky EFI memory map that doesn't work
622  * the same way as other architectures.
623  */
624 u64 __weak efi_mem_attributes(unsigned long phys_addr)
625 {
626 	efi_memory_desc_t *md;
627 
628 	if (!efi_enabled(EFI_MEMMAP))
629 		return 0;
630 
631 	for_each_efi_memory_desc(md) {
632 		if ((md->phys_addr <= phys_addr) &&
633 		    (phys_addr < (md->phys_addr +
634 		    (md->num_pages << EFI_PAGE_SHIFT))))
635 			return md->attribute;
636 	}
637 	return 0;
638 }
639 
640 int efi_status_to_err(efi_status_t status)
641 {
642 	int err;
643 
644 	switch (status) {
645 	case EFI_SUCCESS:
646 		err = 0;
647 		break;
648 	case EFI_INVALID_PARAMETER:
649 		err = -EINVAL;
650 		break;
651 	case EFI_OUT_OF_RESOURCES:
652 		err = -ENOSPC;
653 		break;
654 	case EFI_DEVICE_ERROR:
655 		err = -EIO;
656 		break;
657 	case EFI_WRITE_PROTECTED:
658 		err = -EROFS;
659 		break;
660 	case EFI_SECURITY_VIOLATION:
661 		err = -EACCES;
662 		break;
663 	case EFI_NOT_FOUND:
664 		err = -ENOENT;
665 		break;
666 	default:
667 		err = -EINVAL;
668 	}
669 
670 	return err;
671 }
672