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