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