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