Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

efi: Add a function to look up existing IO memory mappings

The EFI initialization creates virtual mappings for EFI boot services
memory, so if a driver wants to access EFI boot services memory, it
cannot call ioremap itself; doing so will trip the WARN about mapping
RAM twice. Thus, a driver accessing EFI boot services memory must do so
via the existing mapping already created during EFI intiialization.
Since the EFI code already maintains a memory map for that memory, add a
function efi_lookup_mapped_addr to look up mappings in that memory map.

Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Link: http://lkml.kernel.org/r/0eb48ae012797912874919110660ad420b90268b.1348876882.git.josh@joshtriplett.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>

authored by

Josh Triplett and committed by
H. Peter Anvin
7bc90e01 78510792

+29
+28
arch/x86/platform/efi/efi.c
··· 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 808 * This function will switch the EFI runtime services to virtual mode. 781 809 * Essentially, look through the EFI memmap and map every region that 782 810 * has the runtime attribute bit set in its memory descriptor and update
+1
include/linux/efi.h
··· 501 501 #else 502 502 static inline void efi_free_boot_services(void) {} 503 503 #endif 504 + extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); 504 505 extern u64 efi_get_iobase (void); 505 506 extern u32 efi_mem_type (unsigned long phys_addr); 506 507 extern u64 efi_mem_attributes (unsigned long phys_addr);