]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/firmware/efi/efi.c
usb: chipidea: udc: remove unused value assignment
[karo-tx-linux.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.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 }