1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Extensible Firmware Interface 4 * 5 * Copyright (C) 2020 Western Digital Corporation or its affiliates. 6 * 7 * Based on Extensible Firmware Interface Specification version 2.4 8 * Adapted from drivers/firmware/efi/arm-runtime.c 9 * 10 */ 11 12 #include <linux/dmi.h> 13 #include <linux/efi.h> 14 #include <linux/io.h> 15 #include <linux/memblock.h> 16 #include <linux/mm_types.h> 17 #include <linux/pgalloc.h> 18 #include <linux/pgtable.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 30 static bool __init efi_virtmap_init(void) 31 { 32 efi_memory_desc_t *md; 33 34 efi_mm.pgd = pgd_alloc(&efi_mm); 35 mm_init_cpumask(&efi_mm); 36 init_new_context(NULL, &efi_mm); 37 38 for_each_efi_memory_desc(md) { 39 if (!(md->attribute & EFI_MEMORY_RUNTIME)) 40 continue; 41 if (md->virt_addr == U64_MAX) 42 return false; 43 44 efi_create_mapping(&efi_mm, md); 45 } 46 47 if (efi_memattr_apply_permissions(&efi_mm, efi_set_mapping_permissions)) 48 return false; 49 50 return true; 51 } 52 53 /* 54 * Enable the UEFI Runtime Services if all prerequisites are in place, i.e., 55 * non-early mapping of the UEFI system table and virtual mappings for all 56 * EFI_MEMORY_RUNTIME regions. 57 */ 58 static int __init riscv_enable_runtime_services(void) 59 { 60 u64 mapsize; 61 62 if (!efi_enabled(EFI_BOOT)) { 63 pr_info("EFI services will not be available.\n"); 64 return 0; 65 } 66 67 efi_memmap_unmap(); 68 69 mapsize = efi.memmap.desc_size * efi.memmap.nr_map; 70 71 if (efi_memmap_init_late(efi.memmap.phys_map, mapsize)) { 72 pr_err("Failed to remap EFI memory map\n"); 73 return 0; 74 } 75 76 if (efi_soft_reserve_enabled()) { 77 efi_memory_desc_t *md; 78 79 for_each_efi_memory_desc(md) { 80 u64 md_size = md->num_pages << EFI_PAGE_SHIFT; 81 struct resource *res; 82 83 if (!(md->attribute & EFI_MEMORY_SP)) 84 continue; 85 86 res = kzalloc(sizeof(*res), GFP_KERNEL); 87 if (WARN_ON(!res)) 88 break; 89 90 res->start = md->phys_addr; 91 res->end = md->phys_addr + md_size - 1; 92 res->name = "Soft Reserved"; 93 res->flags = IORESOURCE_MEM; 94 res->desc = IORES_DESC_SOFT_RESERVED; 95 96 insert_resource(&iomem_resource, res); 97 } 98 } 99 100 if (efi_runtime_disabled()) { 101 pr_info("EFI runtime services will be disabled.\n"); 102 return 0; 103 } 104 105 if (efi_enabled(EFI_RUNTIME_SERVICES)) { 106 pr_info("EFI runtime services access via paravirt.\n"); 107 return 0; 108 } 109 110 pr_info("Remapping and enabling EFI services.\n"); 111 112 if (!efi_virtmap_init()) { 113 pr_err("UEFI virtual mapping missing or invalid -- runtime services will not be available\n"); 114 return -ENOMEM; 115 } 116 117 /* Set up runtime services function pointers */ 118 efi_native_runtime_setup(); 119 set_bit(EFI_RUNTIME_SERVICES, &efi.flags); 120 121 return 0; 122 } 123 early_initcall(riscv_enable_runtime_services); 124 125 static void efi_virtmap_load(void) 126 { 127 preempt_disable(); 128 switch_mm(current->active_mm, &efi_mm, NULL); 129 } 130 131 static void efi_virtmap_unload(void) 132 { 133 switch_mm(&efi_mm, current->active_mm, NULL); 134 preempt_enable(); 135 } 136 137 void arch_efi_call_virt_setup(void) 138 { 139 sync_kernel_mappings(efi_mm.pgd); 140 efi_virtmap_load(); 141 } 142 143 void arch_efi_call_virt_teardown(void) 144 { 145 efi_virtmap_unload(); 146 } 147 148 static int __init riscv_dmi_init(void) 149 { 150 /* 151 * On riscv, DMI depends on UEFI, and dmi_setup() needs to 152 * be called early because dmi_id_init(), which is an arch_initcall 153 * itself, depends on dmi_scan_machine() having been called already. 154 */ 155 dmi_setup(); 156 157 return 0; 158 } 159 core_initcall(riscv_dmi_init); 160