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