1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 260863c0dSMatt Fleming /* 360863c0dSMatt Fleming * Common EFI memory map functions. 460863c0dSMatt Fleming */ 560863c0dSMatt Fleming 660863c0dSMatt Fleming #define pr_fmt(fmt) "efi: " fmt 760863c0dSMatt Fleming 860863c0dSMatt Fleming #include <linux/init.h> 960863c0dSMatt Fleming #include <linux/kernel.h> 1060863c0dSMatt Fleming #include <linux/efi.h> 1160863c0dSMatt Fleming #include <linux/io.h> 1220b1e22dSNicolai Stange #include <linux/memblock.h> 1320b1e22dSNicolai Stange #include <linux/slab.h> 1420b1e22dSNicolai Stange 15fdc6d38dSArd Biesheuvel #include <asm/early_ioremap.h> 16fdc6d38dSArd Biesheuvel #include <asm/efi.h> 1720b1e22dSNicolai Stange 1860863c0dSMatt Fleming /** 1960863c0dSMatt Fleming * __efi_memmap_init - Common code for mapping the EFI memory map 2060863c0dSMatt Fleming * @data: EFI memory map data 2160863c0dSMatt Fleming * 2260863c0dSMatt Fleming * This function takes care of figuring out which function to use to 2360863c0dSMatt Fleming * map the EFI memory map in efi.memmap based on how far into the boot 2460863c0dSMatt Fleming * we are. 2560863c0dSMatt Fleming * 2626c0e44aSDan Williams * During bootup EFI_MEMMAP_LATE in data->flags should be clear since we 2726c0e44aSDan Williams * only have access to the early_memremap*() functions as the vmalloc 2826c0e44aSDan Williams * space isn't setup. Once the kernel is fully booted we can fallback 2926c0e44aSDan Williams * to the more robust memremap*() API. 3060863c0dSMatt Fleming * 31*4afa688dSRandy Dunlap * Returns: zero on success, a negative error code on failure. 3260863c0dSMatt Fleming */ 33fdc6d38dSArd Biesheuvel int __init __efi_memmap_init(struct efi_memory_map_data *data) 3460863c0dSMatt Fleming { 3560863c0dSMatt Fleming struct efi_memory_map map; 3660863c0dSMatt Fleming phys_addr_t phys_map; 3760863c0dSMatt Fleming 3860863c0dSMatt Fleming phys_map = data->phys_map; 3960863c0dSMatt Fleming 4026c0e44aSDan Williams if (data->flags & EFI_MEMMAP_LATE) 4160863c0dSMatt Fleming map.map = memremap(phys_map, data->size, MEMREMAP_WB); 4260863c0dSMatt Fleming else 4360863c0dSMatt Fleming map.map = early_memremap(phys_map, data->size); 4460863c0dSMatt Fleming 4560863c0dSMatt Fleming if (!map.map) { 4660863c0dSMatt Fleming pr_err("Could not map the memory map!\n"); 4760863c0dSMatt Fleming return -ENOMEM; 4860863c0dSMatt Fleming } 4960863c0dSMatt Fleming 5060863c0dSMatt Fleming map.phys_map = data->phys_map; 5160863c0dSMatt Fleming map.nr_map = data->size / data->desc_size; 5260863c0dSMatt Fleming map.map_end = map.map + data->size; 5360863c0dSMatt Fleming 5460863c0dSMatt Fleming map.desc_version = data->desc_version; 5560863c0dSMatt Fleming map.desc_size = data->desc_size; 5626c0e44aSDan Williams map.flags = data->flags; 5760863c0dSMatt Fleming 5860863c0dSMatt Fleming set_bit(EFI_MEMMAP, &efi.flags); 5960863c0dSMatt Fleming 6060863c0dSMatt Fleming efi.memmap = map; 6160863c0dSMatt Fleming 6260863c0dSMatt Fleming return 0; 6360863c0dSMatt Fleming } 6460863c0dSMatt Fleming 6560863c0dSMatt Fleming /** 6660863c0dSMatt Fleming * efi_memmap_init_early - Map the EFI memory map data structure 6760863c0dSMatt Fleming * @data: EFI memory map data 6860863c0dSMatt Fleming * 6960863c0dSMatt Fleming * Use early_memremap() to map the passed in EFI memory map and assign 7060863c0dSMatt Fleming * it to efi.memmap. 71*4afa688dSRandy Dunlap * 72*4afa688dSRandy Dunlap * Returns: zero on success, a negative error code on failure. 7360863c0dSMatt Fleming */ 7460863c0dSMatt Fleming int __init efi_memmap_init_early(struct efi_memory_map_data *data) 7560863c0dSMatt Fleming { 7660863c0dSMatt Fleming /* Cannot go backwards */ 7726c0e44aSDan Williams WARN_ON(efi.memmap.flags & EFI_MEMMAP_LATE); 7860863c0dSMatt Fleming 7926c0e44aSDan Williams data->flags = 0; 8026c0e44aSDan Williams return __efi_memmap_init(data); 8160863c0dSMatt Fleming } 8260863c0dSMatt Fleming 8360863c0dSMatt Fleming void __init efi_memmap_unmap(void) 8460863c0dSMatt Fleming { 8533412b86SArd Biesheuvel if (!efi_enabled(EFI_MEMMAP)) 8633412b86SArd Biesheuvel return; 8733412b86SArd Biesheuvel 8826c0e44aSDan Williams if (!(efi.memmap.flags & EFI_MEMMAP_LATE)) { 8960863c0dSMatt Fleming unsigned long size; 9060863c0dSMatt Fleming 9160863c0dSMatt Fleming size = efi.memmap.desc_size * efi.memmap.nr_map; 9260863c0dSMatt Fleming early_memunmap(efi.memmap.map, size); 9360863c0dSMatt Fleming } else { 9460863c0dSMatt Fleming memunmap(efi.memmap.map); 9560863c0dSMatt Fleming } 9660863c0dSMatt Fleming 9760863c0dSMatt Fleming efi.memmap.map = NULL; 9860863c0dSMatt Fleming clear_bit(EFI_MEMMAP, &efi.flags); 9960863c0dSMatt Fleming } 10060863c0dSMatt Fleming 10160863c0dSMatt Fleming /** 10260863c0dSMatt Fleming * efi_memmap_init_late - Map efi.memmap with memremap() 103*4afa688dSRandy Dunlap * @addr: Physical address of the new EFI memory map 10460863c0dSMatt Fleming * @size: Size in bytes of the new EFI memory map 10560863c0dSMatt Fleming * 10660863c0dSMatt Fleming * Setup a mapping of the EFI memory map using ioremap_cache(). This 10760863c0dSMatt Fleming * function should only be called once the vmalloc space has been 10860863c0dSMatt Fleming * setup and is therefore not suitable for calling during early EFI 10960863c0dSMatt Fleming * initialise, e.g. in efi_init(). Additionally, it expects 11060863c0dSMatt Fleming * efi_memmap_init_early() to have already been called. 11160863c0dSMatt Fleming * 11260863c0dSMatt Fleming * The reason there are two EFI memmap initialisation 11360863c0dSMatt Fleming * (efi_memmap_init_early() and this late version) is because the 11460863c0dSMatt Fleming * early EFI memmap should be explicitly unmapped once EFI 11560863c0dSMatt Fleming * initialisation is complete as the fixmap space used to map the EFI 11660863c0dSMatt Fleming * memmap (via early_memremap()) is a scarce resource. 11760863c0dSMatt Fleming * 11860863c0dSMatt Fleming * This late mapping is intended to persist for the duration of 11960863c0dSMatt Fleming * runtime so that things like efi_mem_desc_lookup() and 12060863c0dSMatt Fleming * efi_mem_attributes() always work. 12160863c0dSMatt Fleming * 122*4afa688dSRandy Dunlap * Returns: zero on success, a negative error code on failure. 12360863c0dSMatt Fleming */ 12460863c0dSMatt Fleming int __init efi_memmap_init_late(phys_addr_t addr, unsigned long size) 12560863c0dSMatt Fleming { 12660863c0dSMatt Fleming struct efi_memory_map_data data = { 12760863c0dSMatt Fleming .phys_map = addr, 12860863c0dSMatt Fleming .size = size, 12926c0e44aSDan Williams .flags = EFI_MEMMAP_LATE, 13060863c0dSMatt Fleming }; 13160863c0dSMatt Fleming 13260863c0dSMatt Fleming /* Did we forget to unmap the early EFI memmap? */ 13360863c0dSMatt Fleming WARN_ON(efi.memmap.map); 13460863c0dSMatt Fleming 13560863c0dSMatt Fleming /* Were we already called? */ 13626c0e44aSDan Williams WARN_ON(efi.memmap.flags & EFI_MEMMAP_LATE); 13760863c0dSMatt Fleming 13860863c0dSMatt Fleming /* 13960863c0dSMatt Fleming * It makes no sense to allow callers to register different 14060863c0dSMatt Fleming * values for the following fields. Copy them out of the 14160863c0dSMatt Fleming * existing early EFI memmap. 14260863c0dSMatt Fleming */ 14360863c0dSMatt Fleming data.desc_version = efi.memmap.desc_version; 14460863c0dSMatt Fleming data.desc_size = efi.memmap.desc_size; 14560863c0dSMatt Fleming 14626c0e44aSDan Williams return __efi_memmap_init(&data); 14760863c0dSMatt Fleming } 148