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