11965aae3SH. Peter Anvin #ifndef _ASM_X86_EFI_H 21965aae3SH. Peter Anvin #define _ASM_X86_EFI_H 3bb898558SAl Viro 4df6b35f4SIngo Molnar #include <asm/fpu/api.h> 5744937b0SIngo Molnar #include <asm/pgtable.h> 69788375dSMark Rutland #include <asm/processor-flags.h> 7c9f2a9a6SMatt Fleming #include <asm/tlb.h> 8744937b0SIngo Molnar 9d2f7cbe7SBorislav Petkov /* 10d2f7cbe7SBorislav Petkov * We map the EFI regions needed for runtime services non-contiguously, 11d2f7cbe7SBorislav Petkov * with preserved alignment on virtual addresses starting from -4G down 12d2f7cbe7SBorislav Petkov * for a total max space of 64G. This way, we provide for stable runtime 13d2f7cbe7SBorislav Petkov * services addresses across kernels so that a kexec'd kernel can still 14d2f7cbe7SBorislav Petkov * use them. 15d2f7cbe7SBorislav Petkov * 16d2f7cbe7SBorislav Petkov * This is the main reason why we're doing stable VA mappings for RT 17d2f7cbe7SBorislav Petkov * services. 18d2f7cbe7SBorislav Petkov * 19d2f7cbe7SBorislav Petkov * This flag is used in conjuction with a chicken bit called 20d2f7cbe7SBorislav Petkov * "efi=old_map" which can be used as a fallback to the old runtime 21d2f7cbe7SBorislav Petkov * services mapping method in case there's some b0rkage with a 22d2f7cbe7SBorislav Petkov * particular EFI implementation (haha, it is hard to hold up the 23d2f7cbe7SBorislav Petkov * sarcasm here...). 24d2f7cbe7SBorislav Petkov */ 25d2f7cbe7SBorislav Petkov #define EFI_OLD_MEMMAP EFI_ARCH_1 26d2f7cbe7SBorislav Petkov 27b8ff87a6SMatt Fleming #define EFI32_LOADER_SIGNATURE "EL32" 28b8ff87a6SMatt Fleming #define EFI64_LOADER_SIGNATURE "EL64" 29b8ff87a6SMatt Fleming 3048fcb2d0SArd Biesheuvel #define MAX_CMDLINE_ADDRESS UINT_MAX 3148fcb2d0SArd Biesheuvel 329788375dSMark Rutland #define ARCH_EFI_IRQ_FLAGS_MASK X86_EFLAGS_IF 33bb898558SAl Viro 349788375dSMark Rutland #ifdef CONFIG_X86_32 35f7d7d01bSMatt Fleming 36bb898558SAl Viro extern unsigned long asmlinkage efi_call_phys(void *, ...); 37bb898558SAl Viro 38bc25f9dbSMark Rutland #define arch_efi_call_virt_setup() kernel_fpu_begin() 39bc25f9dbSMark Rutland #define arch_efi_call_virt_teardown() kernel_fpu_end() 40bc25f9dbSMark Rutland 41bb898558SAl Viro /* 42bb898558SAl Viro * Wrap all the virtual calls in a way that forces the parameters on the stack. 43bb898558SAl Viro */ 4480e75596SAlex Thorlton #define arch_efi_call_virt(p, f, args...) \ 45b738c6eaSRicardo Neri ({ \ 4680e75596SAlex Thorlton ((efi_##f##_t __attribute__((regparm(0)))*) p->f)(args); \ 47b738c6eaSRicardo Neri }) 48982e239cSRicardo Neri 493e8fa263SMatt Fleming #define efi_ioremap(addr, size, type, attr) ioremap_cache(addr, size) 50e1ad783bSKeith Packard 51bb898558SAl Viro #else /* !CONFIG_X86_32 */ 52bb898558SAl Viro 5362fa6e69SMatt Fleming #define EFI_LOADER_SIGNATURE "EL64" 54bb898558SAl Viro 5562fa6e69SMatt Fleming extern u64 asmlinkage efi_call(void *fp, ...); 56bb898558SAl Viro 5762fa6e69SMatt Fleming #define efi_call_phys(f, args...) efi_call((f), args) 5862fa6e69SMatt Fleming 59c9f2a9a6SMatt Fleming /* 60c9f2a9a6SMatt Fleming * Scratch space used for switching the pagetable in the EFI stub 61c9f2a9a6SMatt Fleming */ 62c9f2a9a6SMatt Fleming struct efi_scratch { 63c9f2a9a6SMatt Fleming u64 r15; 64c9f2a9a6SMatt Fleming u64 prev_cr3; 65c9f2a9a6SMatt Fleming pgd_t *efi_pgt; 66c9f2a9a6SMatt Fleming bool use_pgd; 67c9f2a9a6SMatt Fleming u64 phys_stack; 68c9f2a9a6SMatt Fleming } __packed; 69c9f2a9a6SMatt Fleming 70bc25f9dbSMark Rutland #define arch_efi_call_virt_setup() \ 71d2f7cbe7SBorislav Petkov ({ \ 72d2f7cbe7SBorislav Petkov efi_sync_low_kernel_mappings(); \ 73d2f7cbe7SBorislav Petkov preempt_disable(); \ 74de05764eSRicardo Neri __kernel_fpu_begin(); \ 75c9f2a9a6SMatt Fleming \ 76c9f2a9a6SMatt Fleming if (efi_scratch.use_pgd) { \ 77c9f2a9a6SMatt Fleming efi_scratch.prev_cr3 = read_cr3(); \ 78c9f2a9a6SMatt Fleming write_cr3((unsigned long)efi_scratch.efi_pgt); \ 79c9f2a9a6SMatt Fleming __flush_tlb_all(); \ 80c9f2a9a6SMatt Fleming } \ 81bc25f9dbSMark Rutland }) 82bc25f9dbSMark Rutland 8380e75596SAlex Thorlton #define arch_efi_call_virt(p, f, args...) \ 8480e75596SAlex Thorlton efi_call((void *)p->f, args) \ 85bc25f9dbSMark Rutland 86bc25f9dbSMark Rutland #define arch_efi_call_virt_teardown() \ 87bc25f9dbSMark Rutland ({ \ 88c9f2a9a6SMatt Fleming if (efi_scratch.use_pgd) { \ 89c9f2a9a6SMatt Fleming write_cr3(efi_scratch.prev_cr3); \ 90c9f2a9a6SMatt Fleming __flush_tlb_all(); \ 91c9f2a9a6SMatt Fleming } \ 92c9f2a9a6SMatt Fleming \ 93de05764eSRicardo Neri __kernel_fpu_end(); \ 94d2f7cbe7SBorislav Petkov preempt_enable(); \ 95d2f7cbe7SBorislav Petkov }) 96d2f7cbe7SBorislav Petkov 974e78eb05SMathias Krause extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size, 983e8fa263SMatt Fleming u32 type, u64 attribute); 99e1ad783bSKeith Packard 100a523841eSAndrey Ryabinin #ifdef CONFIG_KASAN 101769a8089SAndrey Ryabinin /* 102769a8089SAndrey Ryabinin * CONFIG_KASAN may redefine memset to __memset. __memset function is present 103769a8089SAndrey Ryabinin * only in kernel binary. Since the EFI stub linked into a separate binary it 104769a8089SAndrey Ryabinin * doesn't have __memset(). So we should use standard memset from 105769a8089SAndrey Ryabinin * arch/x86/boot/compressed/string.c. The same applies to memcpy and memmove. 106769a8089SAndrey Ryabinin */ 107769a8089SAndrey Ryabinin #undef memcpy 108769a8089SAndrey Ryabinin #undef memset 109769a8089SAndrey Ryabinin #undef memmove 110a523841eSAndrey Ryabinin #endif 111769a8089SAndrey Ryabinin 112bb898558SAl Viro #endif /* CONFIG_X86_32 */ 113bb898558SAl Viro 114d2f7cbe7SBorislav Petkov extern struct efi_scratch efi_scratch; 1154e78eb05SMathias Krause extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable); 1164e78eb05SMathias Krause extern int __init efi_memblock_x86_reserve_range(void); 117744937b0SIngo Molnar extern pgd_t * __init efi_call_phys_prolog(void); 118744937b0SIngo Molnar extern void __init efi_call_phys_epilog(pgd_t *save_pgd); 1190bbea1ceSTaku Izumi extern void __init efi_print_memmap(void); 1204e78eb05SMathias Krause extern void __init efi_memory_uc(u64 addr, unsigned long size); 121d2f7cbe7SBorislav Petkov extern void __init efi_map_region(efi_memory_desc_t *md); 1223b266496SDave Young extern void __init efi_map_region_fixed(efi_memory_desc_t *md); 123d2f7cbe7SBorislav Petkov extern void efi_sync_low_kernel_mappings(void); 12467a9108eSMatt Fleming extern int __init efi_alloc_page_tables(void); 1254e78eb05SMathias Krause extern int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages); 126d2f7cbe7SBorislav Petkov extern void __init old_map_region(efi_memory_desc_t *md); 127c55d016fSBorislav Petkov extern void __init runtime_code_page_mkexec(void); 1286d0cc887SSai Praneeth extern void __init efi_runtime_update_mappings(void); 12911cc8512SBorislav Petkov extern void __init efi_dump_pagetable(void); 130a5d90c92SBorislav Petkov extern void __init efi_apply_memmap_quirks(void); 131eeb9db09SSaurabh Tangri extern int __init efi_reuse_config(u64 tables, int nr_tables); 132eeb9db09SSaurabh Tangri extern void efi_delete_dummy_variable(void); 133bb898558SAl Viro 1341fec0533SDave Young struct efi_setup_data { 1351fec0533SDave Young u64 fw_vendor; 1361fec0533SDave Young u64 runtime; 1371fec0533SDave Young u64 tables; 1381fec0533SDave Young u64 smbios; 1391fec0533SDave Young u64 reserved[8]; 1401fec0533SDave Young }; 1411fec0533SDave Young 1421fec0533SDave Young extern u64 efi_setup; 1431fec0533SDave Young 1446b59e366SSatoru Takeuchi #ifdef CONFIG_EFI 1456b59e366SSatoru Takeuchi 1466b59e366SSatoru Takeuchi static inline bool efi_is_native(void) 1476b59e366SSatoru Takeuchi { 1486b59e366SSatoru Takeuchi return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT); 1496b59e366SSatoru Takeuchi } 1506b59e366SSatoru Takeuchi 1517d453eeeSMatt Fleming static inline bool efi_runtime_supported(void) 1527d453eeeSMatt Fleming { 1537d453eeeSMatt Fleming if (efi_is_native()) 1547d453eeeSMatt Fleming return true; 1557d453eeeSMatt Fleming 1567d453eeeSMatt Fleming if (IS_ENABLED(CONFIG_EFI_MIXED) && !efi_enabled(EFI_OLD_MEMMAP)) 1577d453eeeSMatt Fleming return true; 1587d453eeeSMatt Fleming 1597d453eeeSMatt Fleming return false; 1607d453eeeSMatt Fleming } 1617d453eeeSMatt Fleming 16272548e83SMatt Fleming extern struct console early_efi_console; 1635c12af0cSDave Young extern void parse_efi_setup(u64 phys_addr, u32 data_len); 1644f9dbcfcSMatt Fleming 16521289ec0SArd Biesheuvel extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); 16621289ec0SArd Biesheuvel 1674f9dbcfcSMatt Fleming #ifdef CONFIG_EFI_MIXED 1684f9dbcfcSMatt Fleming extern void efi_thunk_runtime_setup(void); 1694f9dbcfcSMatt Fleming extern efi_status_t efi_thunk_set_virtual_address_map( 1704f9dbcfcSMatt Fleming void *phys_set_virtual_address_map, 1714f9dbcfcSMatt Fleming unsigned long memory_map_size, 1724f9dbcfcSMatt Fleming unsigned long descriptor_size, 1734f9dbcfcSMatt Fleming u32 descriptor_version, 1744f9dbcfcSMatt Fleming efi_memory_desc_t *virtual_map); 1754f9dbcfcSMatt Fleming #else 1764f9dbcfcSMatt Fleming static inline void efi_thunk_runtime_setup(void) {} 1774f9dbcfcSMatt Fleming static inline efi_status_t efi_thunk_set_virtual_address_map( 1784f9dbcfcSMatt Fleming void *phys_set_virtual_address_map, 1794f9dbcfcSMatt Fleming unsigned long memory_map_size, 1804f9dbcfcSMatt Fleming unsigned long descriptor_size, 1814f9dbcfcSMatt Fleming u32 descriptor_version, 1824f9dbcfcSMatt Fleming efi_memory_desc_t *virtual_map) 1834f9dbcfcSMatt Fleming { 1844f9dbcfcSMatt Fleming return EFI_SUCCESS; 1854f9dbcfcSMatt Fleming } 1864f9dbcfcSMatt Fleming #endif /* CONFIG_EFI_MIXED */ 187f23cf8bdSArd Biesheuvel 188243b6754SArd Biesheuvel 189243b6754SArd Biesheuvel /* arch specific definitions used by the stub code */ 190243b6754SArd Biesheuvel 191243b6754SArd Biesheuvel struct efi_config { 192243b6754SArd Biesheuvel u64 image_handle; 193243b6754SArd Biesheuvel u64 table; 194243b6754SArd Biesheuvel u64 allocate_pool; 195243b6754SArd Biesheuvel u64 allocate_pages; 196243b6754SArd Biesheuvel u64 get_memory_map; 197243b6754SArd Biesheuvel u64 free_pool; 198243b6754SArd Biesheuvel u64 free_pages; 199243b6754SArd Biesheuvel u64 locate_handle; 200243b6754SArd Biesheuvel u64 handle_protocol; 201243b6754SArd Biesheuvel u64 exit_boot_services; 202243b6754SArd Biesheuvel u64 text_output; 203243b6754SArd Biesheuvel efi_status_t (*call)(unsigned long, ...); 204243b6754SArd Biesheuvel bool is64; 205243b6754SArd Biesheuvel } __packed; 206243b6754SArd Biesheuvel 207243b6754SArd Biesheuvel __pure const struct efi_config *__efi_early(void); 208243b6754SArd Biesheuvel 209*27571616SLukas Wunner static inline bool efi_is_64bit(void) 210*27571616SLukas Wunner { 211*27571616SLukas Wunner if (!IS_ENABLED(CONFIG_X86_64)) 212*27571616SLukas Wunner return false; 213*27571616SLukas Wunner 214*27571616SLukas Wunner if (!IS_ENABLED(CONFIG_EFI_MIXED)) 215*27571616SLukas Wunner return true; 216*27571616SLukas Wunner 217*27571616SLukas Wunner return __efi_early()->is64; 218*27571616SLukas Wunner } 219*27571616SLukas Wunner 220243b6754SArd Biesheuvel #define efi_call_early(f, ...) \ 221243b6754SArd Biesheuvel __efi_early()->call(__efi_early()->f, __VA_ARGS__); 222243b6754SArd Biesheuvel 2232c23b73cSArd Biesheuvel #define __efi_call_early(f, ...) \ 2242c23b73cSArd Biesheuvel __efi_early()->call((unsigned long)f, __VA_ARGS__); 2252c23b73cSArd Biesheuvel 22644be28e9SMatt Fleming extern bool efi_reboot_required(void); 22744be28e9SMatt Fleming 2286b59e366SSatoru Takeuchi #else 2295c12af0cSDave Young static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {} 23044be28e9SMatt Fleming static inline bool efi_reboot_required(void) 23144be28e9SMatt Fleming { 23244be28e9SMatt Fleming return false; 23344be28e9SMatt Fleming } 234bb898558SAl Viro #endif /* CONFIG_EFI */ 235bb898558SAl Viro 2361965aae3SH. Peter Anvin #endif /* _ASM_X86_EFI_H */ 237