diff options
-rw-r--r-- | arch/x86/platform/efi/efi.c | 28 | ||||
-rw-r--r-- | include/linux/efi.h | 1 |
2 files changed, 29 insertions, 0 deletions
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index b3dbbdbd2a42..f7f928c315da 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
@@ -777,6 +777,34 @@ static void __init runtime_code_page_mkexec(void) | |||
777 | } | 777 | } |
778 | 778 | ||
779 | /* | 779 | /* |
780 | * We can't ioremap data in EFI boot services RAM, because we've already mapped | ||
781 | * it as RAM. So, look it up in the existing EFI memory map instead. Only | ||
782 | * callable after efi_enter_virtual_mode and before efi_free_boot_services. | ||
783 | */ | ||
784 | void __iomem *efi_lookup_mapped_addr(u64 phys_addr) | ||
785 | { | ||
786 | void *p; | ||
787 | if (WARN_ON(!memmap.map)) | ||
788 | return NULL; | ||
789 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | ||
790 | efi_memory_desc_t *md = p; | ||
791 | u64 size = md->num_pages << EFI_PAGE_SHIFT; | ||
792 | u64 end = md->phys_addr + size; | ||
793 | if (!(md->attribute & EFI_MEMORY_RUNTIME) && | ||
794 | md->type != EFI_BOOT_SERVICES_CODE && | ||
795 | md->type != EFI_BOOT_SERVICES_DATA) | ||
796 | continue; | ||
797 | if (!md->virt_addr) | ||
798 | continue; | ||
799 | if (phys_addr >= md->phys_addr && phys_addr < end) { | ||
800 | phys_addr += md->virt_addr - md->phys_addr; | ||
801 | return (__force void __iomem *)(unsigned long)phys_addr; | ||
802 | } | ||
803 | } | ||
804 | return NULL; | ||
805 | } | ||
806 | |||
807 | /* | ||
780 | * This function will switch the EFI runtime services to virtual mode. | 808 | * This function will switch the EFI runtime services to virtual mode. |
781 | * Essentially, look through the EFI memmap and map every region that | 809 | * Essentially, look through the EFI memmap and map every region that |
782 | * has the runtime attribute bit set in its memory descriptor and update | 810 | * has the runtime attribute bit set in its memory descriptor and update |
diff --git a/include/linux/efi.h b/include/linux/efi.h index 5782114f4838..fff135d9375e 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
@@ -501,6 +501,7 @@ extern void efi_free_boot_services(void); | |||
501 | #else | 501 | #else |
502 | static inline void efi_free_boot_services(void) {} | 502 | static inline void efi_free_boot_services(void) {} |
503 | #endif | 503 | #endif |
504 | extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); | ||
504 | extern u64 efi_get_iobase (void); | 505 | extern u64 efi_get_iobase (void); |
505 | extern u32 efi_mem_type (unsigned long phys_addr); | 506 | extern u32 efi_mem_type (unsigned long phys_addr); |
506 | extern u64 efi_mem_attributes (unsigned long phys_addr); | 507 | extern u64 efi_mem_attributes (unsigned long phys_addr); |