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