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 18fdc6d38dSArd Biesheuvel #ifndef __efi_memmap_free 19fdc6d38dSArd Biesheuvel #define __efi_memmap_free(phys, size, flags) do { } while (0) 20fdc6d38dSArd Biesheuvel #endif 2160863c0dSMatt Fleming 2260863c0dSMatt Fleming /** 2360863c0dSMatt Fleming * __efi_memmap_init - Common code for mapping the EFI memory map 2460863c0dSMatt Fleming * @data: EFI memory map data 2560863c0dSMatt Fleming * 2660863c0dSMatt Fleming * This function takes care of figuring out which function to use to 2760863c0dSMatt Fleming * map the EFI memory map in efi.memmap based on how far into the boot 2860863c0dSMatt Fleming * we are. 2960863c0dSMatt Fleming * 3026c0e44aSDan Williams * During bootup EFI_MEMMAP_LATE in data->flags should be clear since we 3126c0e44aSDan Williams * only have access to the early_memremap*() functions as the vmalloc 3226c0e44aSDan Williams * space isn't setup. Once the kernel is fully booted we can fallback 3326c0e44aSDan Williams * to the more robust memremap*() API. 3460863c0dSMatt Fleming * 35*4afa688dSRandy Dunlap * Returns: zero on success, a negative error code on failure. 3660863c0dSMatt Fleming */ 37fdc6d38dSArd Biesheuvel int __init __efi_memmap_init(struct efi_memory_map_data *data) 3860863c0dSMatt Fleming { 3960863c0dSMatt Fleming struct efi_memory_map map; 4060863c0dSMatt Fleming phys_addr_t phys_map; 4160863c0dSMatt Fleming 4260863c0dSMatt Fleming phys_map = data->phys_map; 4360863c0dSMatt Fleming 4426c0e44aSDan Williams if (data->flags & EFI_MEMMAP_LATE) 4560863c0dSMatt Fleming map.map = memremap(phys_map, data->size, MEMREMAP_WB); 4660863c0dSMatt Fleming else 4760863c0dSMatt Fleming map.map = early_memremap(phys_map, data->size); 4860863c0dSMatt Fleming 4960863c0dSMatt Fleming if (!map.map) { 5060863c0dSMatt Fleming pr_err("Could not map the memory map!\n"); 5160863c0dSMatt Fleming return -ENOMEM; 5260863c0dSMatt Fleming } 5360863c0dSMatt Fleming 54fdc6d38dSArd Biesheuvel if (efi.memmap.flags & (EFI_MEMMAP_MEMBLOCK | EFI_MEMMAP_SLAB)) 55fdc6d38dSArd Biesheuvel __efi_memmap_free(efi.memmap.phys_map, 56fdc6d38dSArd Biesheuvel efi.memmap.desc_size * efi.memmap.nr_map, 57fdc6d38dSArd Biesheuvel efi.memmap.flags); 58f0ef6523SDan Williams 5960863c0dSMatt Fleming map.phys_map = data->phys_map; 6060863c0dSMatt Fleming map.nr_map = data->size / data->desc_size; 6160863c0dSMatt Fleming map.map_end = map.map + data->size; 6260863c0dSMatt Fleming 6360863c0dSMatt Fleming map.desc_version = data->desc_version; 6460863c0dSMatt Fleming map.desc_size = data->desc_size; 6526c0e44aSDan Williams map.flags = data->flags; 6660863c0dSMatt Fleming 6760863c0dSMatt Fleming set_bit(EFI_MEMMAP, &efi.flags); 6860863c0dSMatt Fleming 6960863c0dSMatt Fleming efi.memmap = map; 7060863c0dSMatt Fleming 7160863c0dSMatt Fleming return 0; 7260863c0dSMatt Fleming } 7360863c0dSMatt Fleming 7460863c0dSMatt Fleming /** 7560863c0dSMatt Fleming * efi_memmap_init_early - Map the EFI memory map data structure 7660863c0dSMatt Fleming * @data: EFI memory map data 7760863c0dSMatt Fleming * 7860863c0dSMatt Fleming * Use early_memremap() to map the passed in EFI memory map and assign 7960863c0dSMatt Fleming * it to efi.memmap. 80*4afa688dSRandy Dunlap * 81*4afa688dSRandy Dunlap * Returns: zero on success, a negative error code on failure. 8260863c0dSMatt Fleming */ 8360863c0dSMatt Fleming int __init efi_memmap_init_early(struct efi_memory_map_data *data) 8460863c0dSMatt Fleming { 8560863c0dSMatt Fleming /* Cannot go backwards */ 8626c0e44aSDan Williams WARN_ON(efi.memmap.flags & EFI_MEMMAP_LATE); 8760863c0dSMatt Fleming 8826c0e44aSDan Williams data->flags = 0; 8926c0e44aSDan Williams return __efi_memmap_init(data); 9060863c0dSMatt Fleming } 9160863c0dSMatt Fleming 9260863c0dSMatt Fleming void __init efi_memmap_unmap(void) 9360863c0dSMatt Fleming { 9433412b86SArd Biesheuvel if (!efi_enabled(EFI_MEMMAP)) 9533412b86SArd Biesheuvel return; 9633412b86SArd Biesheuvel 9726c0e44aSDan Williams if (!(efi.memmap.flags & EFI_MEMMAP_LATE)) { 9860863c0dSMatt Fleming unsigned long size; 9960863c0dSMatt Fleming 10060863c0dSMatt Fleming size = efi.memmap.desc_size * efi.memmap.nr_map; 10160863c0dSMatt Fleming early_memunmap(efi.memmap.map, size); 10260863c0dSMatt Fleming } else { 10360863c0dSMatt Fleming memunmap(efi.memmap.map); 10460863c0dSMatt Fleming } 10560863c0dSMatt Fleming 10660863c0dSMatt Fleming efi.memmap.map = NULL; 10760863c0dSMatt Fleming clear_bit(EFI_MEMMAP, &efi.flags); 10860863c0dSMatt Fleming } 10960863c0dSMatt Fleming 11060863c0dSMatt Fleming /** 11160863c0dSMatt Fleming * efi_memmap_init_late - Map efi.memmap with memremap() 112*4afa688dSRandy Dunlap * @addr: Physical address of the new EFI memory map 11360863c0dSMatt Fleming * @size: Size in bytes of the new EFI memory map 11460863c0dSMatt Fleming * 11560863c0dSMatt Fleming * Setup a mapping of the EFI memory map using ioremap_cache(). This 11660863c0dSMatt Fleming * function should only be called once the vmalloc space has been 11760863c0dSMatt Fleming * setup and is therefore not suitable for calling during early EFI 11860863c0dSMatt Fleming * initialise, e.g. in efi_init(). Additionally, it expects 11960863c0dSMatt Fleming * efi_memmap_init_early() to have already been called. 12060863c0dSMatt Fleming * 12160863c0dSMatt Fleming * The reason there are two EFI memmap initialisation 12260863c0dSMatt Fleming * (efi_memmap_init_early() and this late version) is because the 12360863c0dSMatt Fleming * early EFI memmap should be explicitly unmapped once EFI 12460863c0dSMatt Fleming * initialisation is complete as the fixmap space used to map the EFI 12560863c0dSMatt Fleming * memmap (via early_memremap()) is a scarce resource. 12660863c0dSMatt Fleming * 12760863c0dSMatt Fleming * This late mapping is intended to persist for the duration of 12860863c0dSMatt Fleming * runtime so that things like efi_mem_desc_lookup() and 12960863c0dSMatt Fleming * efi_mem_attributes() always work. 13060863c0dSMatt Fleming * 131*4afa688dSRandy Dunlap * Returns: zero on success, a negative error code on failure. 13260863c0dSMatt Fleming */ 13360863c0dSMatt Fleming int __init efi_memmap_init_late(phys_addr_t addr, unsigned long size) 13460863c0dSMatt Fleming { 13560863c0dSMatt Fleming struct efi_memory_map_data data = { 13660863c0dSMatt Fleming .phys_map = addr, 13760863c0dSMatt Fleming .size = size, 13826c0e44aSDan Williams .flags = EFI_MEMMAP_LATE, 13960863c0dSMatt Fleming }; 14060863c0dSMatt Fleming 14160863c0dSMatt Fleming /* Did we forget to unmap the early EFI memmap? */ 14260863c0dSMatt Fleming WARN_ON(efi.memmap.map); 14360863c0dSMatt Fleming 14460863c0dSMatt Fleming /* Were we already called? */ 14526c0e44aSDan Williams WARN_ON(efi.memmap.flags & EFI_MEMMAP_LATE); 14660863c0dSMatt Fleming 14760863c0dSMatt Fleming /* 14860863c0dSMatt Fleming * It makes no sense to allow callers to register different 14960863c0dSMatt Fleming * values for the following fields. Copy them out of the 15060863c0dSMatt Fleming * existing early EFI memmap. 15160863c0dSMatt Fleming */ 15260863c0dSMatt Fleming data.desc_version = efi.memmap.desc_version; 15360863c0dSMatt Fleming data.desc_size = efi.memmap.desc_size; 15460863c0dSMatt Fleming 15526c0e44aSDan Williams return __efi_memmap_init(&data); 15660863c0dSMatt Fleming } 157