diff options
| -rw-r--r-- | arch/arm64/include/asm/efi.h | 34 | ||||
| -rw-r--r-- | arch/arm64/kernel/efi.c | 230 | ||||
| -rw-r--r-- | arch/arm64/kernel/setup.c | 1 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/arm-stub.c | 59 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/efistub.h | 4 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/fdt.c | 62 |
6 files changed, 282 insertions, 108 deletions
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 71291253114f..effef3713c5a 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h | |||
| @@ -7,28 +7,36 @@ | |||
| 7 | #ifdef CONFIG_EFI | 7 | #ifdef CONFIG_EFI |
| 8 | extern void efi_init(void); | 8 | extern void efi_init(void); |
| 9 | extern void efi_idmap_init(void); | 9 | extern void efi_idmap_init(void); |
| 10 | extern void efi_virtmap_init(void); | ||
| 10 | #else | 11 | #else |
| 11 | #define efi_init() | 12 | #define efi_init() |
| 12 | #define efi_idmap_init() | 13 | #define efi_idmap_init() |
| 14 | #define efi_virtmap_init() | ||
| 13 | #endif | 15 | #endif |
| 14 | 16 | ||
| 15 | #define efi_call_virt(f, ...) \ | 17 | #define efi_call_virt(f, ...) \ |
| 16 | ({ \ | 18 | ({ \ |
| 17 | efi_##f##_t *__f = efi.systab->runtime->f; \ | 19 | efi_##f##_t *__f; \ |
| 18 | efi_status_t __s; \ | 20 | efi_status_t __s; \ |
| 19 | \ | 21 | \ |
| 20 | kernel_neon_begin(); \ | 22 | kernel_neon_begin(); \ |
| 23 | efi_virtmap_load(); \ | ||
| 24 | __f = efi.systab->runtime->f; \ | ||
| 21 | __s = __f(__VA_ARGS__); \ | 25 | __s = __f(__VA_ARGS__); \ |
| 26 | efi_virtmap_unload(); \ | ||
| 22 | kernel_neon_end(); \ | 27 | kernel_neon_end(); \ |
| 23 | __s; \ | 28 | __s; \ |
| 24 | }) | 29 | }) |
| 25 | 30 | ||
| 26 | #define __efi_call_virt(f, ...) \ | 31 | #define __efi_call_virt(f, ...) \ |
| 27 | ({ \ | 32 | ({ \ |
| 28 | efi_##f##_t *__f = efi.systab->runtime->f; \ | 33 | efi_##f##_t *__f; \ |
| 29 | \ | 34 | \ |
| 30 | kernel_neon_begin(); \ | 35 | kernel_neon_begin(); \ |
| 36 | efi_virtmap_load(); \ | ||
| 37 | __f = efi.systab->runtime->f; \ | ||
| 31 | __f(__VA_ARGS__); \ | 38 | __f(__VA_ARGS__); \ |
| 39 | efi_virtmap_unload(); \ | ||
| 32 | kernel_neon_end(); \ | 40 | kernel_neon_end(); \ |
| 33 | }) | 41 | }) |
| 34 | 42 | ||
| @@ -46,4 +54,26 @@ extern void efi_idmap_init(void); | |||
| 46 | 54 | ||
| 47 | #define EFI_ALLOC_ALIGN SZ_64K | 55 | #define EFI_ALLOC_ALIGN SZ_64K |
| 48 | 56 | ||
| 57 | /* | ||
| 58 | * On ARM systems, virtually remapped UEFI runtime services are set up in three | ||
| 59 | * distinct stages: | ||
| 60 | * - The stub retrieves the final version of the memory map from UEFI, populates | ||
| 61 | * the virt_addr fields and calls the SetVirtualAddressMap() [SVAM] runtime | ||
| 62 | * service to communicate the new mapping to the firmware (Note that the new | ||
| 63 | * mapping is not live at this time) | ||
| 64 | * - During early boot, the page tables are allocated and populated based on the | ||
| 65 | * virt_addr fields in the memory map, but only if all descriptors with the | ||
| 66 | * EFI_MEMORY_RUNTIME attribute have a non-zero value for virt_addr. If this | ||
| 67 | * succeeds, the EFI_VIRTMAP flag is set to indicate that the virtual mappings | ||
| 68 | * have been installed successfully. | ||
| 69 | * - During an early initcall(), the UEFI Runtime Services are enabled and the | ||
| 70 | * EFI_RUNTIME_SERVICES bit set if some conditions are met, i.e., we need a | ||
| 71 | * non-early mapping of the UEFI system table, and we need to have the virtmap | ||
| 72 | * installed. | ||
| 73 | */ | ||
| 74 | #define EFI_VIRTMAP EFI_ARCH_1 | ||
| 75 | |||
| 76 | void efi_virtmap_load(void); | ||
| 77 | void efi_virtmap_unload(void); | ||
| 78 | |||
| 49 | #endif /* _ASM_EFI_H */ | 79 | #endif /* _ASM_EFI_H */ |
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 2bb4347d0edf..755e545144ea 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c | |||
| @@ -11,25 +11,31 @@ | |||
| 11 | * | 11 | * |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/atomic.h> | ||
| 14 | #include <linux/dmi.h> | 15 | #include <linux/dmi.h> |
| 15 | #include <linux/efi.h> | 16 | #include <linux/efi.h> |
| 16 | #include <linux/export.h> | 17 | #include <linux/export.h> |
| 17 | #include <linux/memblock.h> | 18 | #include <linux/memblock.h> |
| 19 | #include <linux/mm_types.h> | ||
| 18 | #include <linux/bootmem.h> | 20 | #include <linux/bootmem.h> |
| 19 | #include <linux/of.h> | 21 | #include <linux/of.h> |
| 20 | #include <linux/of_fdt.h> | 22 | #include <linux/of_fdt.h> |
| 23 | #include <linux/preempt.h> | ||
| 24 | #include <linux/rbtree.h> | ||
| 25 | #include <linux/rwsem.h> | ||
| 21 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
| 22 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include <linux/spinlock.h> | ||
| 23 | 29 | ||
| 24 | #include <asm/cacheflush.h> | 30 | #include <asm/cacheflush.h> |
| 25 | #include <asm/efi.h> | 31 | #include <asm/efi.h> |
| 26 | #include <asm/tlbflush.h> | 32 | #include <asm/tlbflush.h> |
| 27 | #include <asm/mmu_context.h> | 33 | #include <asm/mmu_context.h> |
| 34 | #include <asm/mmu.h> | ||
| 35 | #include <asm/pgtable.h> | ||
| 28 | 36 | ||
| 29 | struct efi_memory_map memmap; | 37 | struct efi_memory_map memmap; |
| 30 | 38 | ||
| 31 | static efi_runtime_services_t *runtime; | ||
| 32 | |||
| 33 | static u64 efi_system_table; | 39 | static u64 efi_system_table; |
| 34 | 40 | ||
| 35 | static int uefi_debug __initdata; | 41 | static int uefi_debug __initdata; |
| @@ -69,9 +75,33 @@ static void __init efi_setup_idmap(void) | |||
| 69 | } | 75 | } |
| 70 | } | 76 | } |
| 71 | 77 | ||
| 78 | /* | ||
| 79 | * Translate a EFI virtual address into a physical address: this is necessary, | ||
| 80 | * as some data members of the EFI system table are virtually remapped after | ||
| 81 | * SetVirtualAddressMap() has been called. | ||
| 82 | */ | ||
| 83 | static phys_addr_t efi_to_phys(unsigned long addr) | ||
| 84 | { | ||
| 85 | efi_memory_desc_t *md; | ||
| 86 | |||
| 87 | for_each_efi_memory_desc(&memmap, md) { | ||
| 88 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) | ||
| 89 | continue; | ||
| 90 | if (md->virt_addr == 0) | ||
| 91 | /* no virtual mapping has been installed by the stub */ | ||
| 92 | break; | ||
| 93 | if (md->virt_addr <= addr && | ||
| 94 | (addr - md->virt_addr) < (md->num_pages << EFI_PAGE_SHIFT)) | ||
| 95 | return md->phys_addr + addr - md->virt_addr; | ||
| 96 | } | ||
| 97 | return addr; | ||
| 98 | } | ||
| 99 | |||
| 72 | static int __init uefi_init(void) | 100 | static int __init uefi_init(void) |
| 73 | { | 101 | { |
| 74 | efi_char16_t *c16; | 102 | efi_char16_t *c16; |
| 103 | void *config_tables; | ||
| 104 | u64 table_size; | ||
| 75 | char vendor[100] = "unknown"; | 105 | char vendor[100] = "unknown"; |
| 76 | int i, retval; | 106 | int i, retval; |
| 77 | 107 | ||
| @@ -99,7 +129,7 @@ static int __init uefi_init(void) | |||
| 99 | efi.systab->hdr.revision & 0xffff); | 129 | efi.systab->hdr.revision & 0xffff); |
| 100 | 130 | ||
| 101 | /* Show what we know for posterity */ | 131 | /* Show what we know for posterity */ |
| 102 | c16 = early_memremap(efi.systab->fw_vendor, | 132 | c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor), |
| 103 | sizeof(vendor)); | 133 | sizeof(vendor)); |
| 104 | if (c16) { | 134 | if (c16) { |
| 105 | for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i) | 135 | for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i) |
| @@ -112,8 +142,14 @@ static int __init uefi_init(void) | |||
| 112 | efi.systab->hdr.revision >> 16, | 142 | efi.systab->hdr.revision >> 16, |
| 113 | efi.systab->hdr.revision & 0xffff, vendor); | 143 | efi.systab->hdr.revision & 0xffff, vendor); |
| 114 | 144 | ||
| 115 | retval = efi_config_init(NULL); | 145 | table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables; |
| 146 | config_tables = early_memremap(efi_to_phys(efi.systab->tables), | ||
| 147 | table_size); | ||
| 148 | |||
| 149 | retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables, | ||
| 150 | sizeof(efi_config_table_64_t), NULL); | ||
| 116 | |||
