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