linux/drivers/firmware/efi/arm-runtime.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Extensible Firmware Interface
   4 *
   5 * Based on Extensible Firmware Interface Specification version 2.4
   6 *
   7 * Copyright (C) 2013, 2014 Linaro Ltd.
   8 */
   9
  10#include <linux/dmi.h>
  11#include <linux/efi.h>
  12#include <linux/io.h>
  13#include <linux/memblock.h>
  14#include <linux/mm_types.h>
  15#include <linux/preempt.h>
  16#include <linux/rbtree.h>
  17#include <linux/rwsem.h>
  18#include <linux/sched.h>
  19#include <linux/slab.h>
  20#include <linux/spinlock.h>
  21
  22#include <asm/cacheflush.h>
  23#include <asm/efi.h>
  24#include <asm/mmu.h>
  25#include <asm/pgalloc.h>
  26#include <asm/pgtable.h>
  27
  28extern u64 efi_system_table;
  29
  30#ifdef CONFIG_ARM64_PTDUMP_DEBUGFS
  31#include <asm/ptdump.h>
  32
  33static struct ptdump_info efi_ptdump_info = {
  34        .mm             = &efi_mm,
  35        .markers        = (struct addr_marker[]){
  36                { 0,                            "UEFI runtime start" },
  37                { DEFAULT_MAP_WINDOW_64,        "UEFI runtime end" },
  38                { -1,                           NULL }
  39        },
  40        .base_addr      = 0,
  41};
  42
  43static int __init ptdump_init(void)
  44{
  45        if (efi_enabled(EFI_RUNTIME_SERVICES))
  46                ptdump_debugfs_register(&efi_ptdump_info, "efi_page_tables");
  47
  48        return 0;
  49}
  50device_initcall(ptdump_init);
  51
  52#endif
  53
  54static bool __init efi_virtmap_init(void)
  55{
  56        efi_memory_desc_t *md;
  57        bool systab_found;
  58
  59        efi_mm.pgd = pgd_alloc(&efi_mm);
  60        mm_init_cpumask(&efi_mm);
  61        init_new_context(NULL, &efi_mm);
  62
  63        systab_found = false;
  64        for_each_efi_memory_desc(md) {
  65                phys_addr_t phys = md->phys_addr;
  66                int ret;
  67
  68                if (!(md->attribute & EFI_MEMORY_RUNTIME))
  69                        continue;
  70                if (md->virt_addr == 0)
  71                        return false;
  72
  73                ret = efi_create_mapping(&efi_mm, md);
  74                if (ret) {
  75                        pr_warn("  EFI remap %pa: failed to create mapping (%d)\n",
  76                                &phys, ret);
  77                        return false;
  78                }
  79                /*
  80                 * If this entry covers the address of the UEFI system table,
  81                 * calculate and record its virtual address.
  82                 */
  83                if (efi_system_table >= phys &&
  84                    efi_system_table < phys + (md->num_pages * EFI_PAGE_SIZE)) {
  85                        efi.systab = (void *)(unsigned long)(efi_system_table -
  86                                                             phys + md->virt_addr);
  87                        systab_found = true;
  88                }
  89        }
  90        if (!systab_found) {
  91                pr_err("No virtual mapping found for the UEFI System Table\n");
  92                return false;
  93        }
  94
  95        if (efi_memattr_apply_permissions(&efi_mm, efi_set_mapping_permissions))
  96                return false;
  97
  98        return true;
  99}
 100
 101/*
 102 * Enable the UEFI Runtime Services if all prerequisites are in place, i.e.,
 103 * non-early mapping of the UEFI system table and virtual mappings for all
 104 * EFI_MEMORY_RUNTIME regions.
 105 */
 106static int __init arm_enable_runtime_services(void)
 107{
 108        u64 mapsize;
 109
 110        if (!efi_enabled(EFI_BOOT)) {
 111                pr_info("EFI services will not be available.\n");
 112                return 0;
 113        }
 114
 115        efi_memmap_unmap();
 116
 117        mapsize = efi.memmap.desc_size * efi.memmap.nr_map;
 118
 119        if (efi_memmap_init_late(efi.memmap.phys_map, mapsize)) {
 120                pr_err("Failed to remap EFI memory map\n");
 121                return 0;
 122        }
 123
 124        if (efi_runtime_disabled()) {
 125                pr_info("EFI runtime services will be disabled.\n");
 126                return 0;
 127        }
 128
 129        if (efi_enabled(EFI_RUNTIME_SERVICES)) {
 130                pr_info("EFI runtime services access via paravirt.\n");
 131                return 0;
 132        }
 133
 134        pr_info("Remapping and enabling EFI services.\n");
 135
 136        if (!efi_virtmap_init()) {
 137                pr_err("UEFI virtual mapping missing or invalid -- runtime services will not be available\n");
 138                return -ENOMEM;
 139        }
 140
 141        /* Set up runtime services function pointers */
 142        efi_native_runtime_setup();
 143        set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
 144
 145        return 0;
 146}
 147early_initcall(arm_enable_runtime_services);
 148
 149void efi_virtmap_load(void)
 150{
 151        preempt_disable();
 152        efi_set_pgd(&efi_mm);
 153}
 154
 155void efi_virtmap_unload(void)
 156{
 157        efi_set_pgd(current->active_mm);
 158        preempt_enable();
 159}
 160
 161
 162static int __init arm_dmi_init(void)
 163{
 164        /*
 165         * On arm64/ARM, DMI depends on UEFI, and dmi_setup() needs to
 166         * be called early because dmi_id_init(), which is an arch_initcall
 167         * itself, depends on dmi_scan_machine() having been called already.
 168         */
 169        dmi_setup();
 170        return 0;
 171}
 172core_initcall(arm_dmi_init);
 173