18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Common EFI memory map functions. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "efi: " fmt 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/init.h> 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci#include <linux/efi.h> 118c2ecf20Sopenharmony_ci#include <linux/io.h> 128c2ecf20Sopenharmony_ci#include <asm/early_ioremap.h> 138c2ecf20Sopenharmony_ci#include <linux/memblock.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistatic phys_addr_t __init __efi_memmap_alloc_early(unsigned long size) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci return memblock_phys_alloc(size, SMP_CACHE_BYTES); 198c2ecf20Sopenharmony_ci} 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic phys_addr_t __init __efi_memmap_alloc_late(unsigned long size) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci unsigned int order = get_order(size); 248c2ecf20Sopenharmony_ci struct page *p = alloc_pages(GFP_KERNEL, order); 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci if (!p) 278c2ecf20Sopenharmony_ci return 0; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci return PFN_PHYS(page_to_pfn(p)); 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_civoid __init __efi_memmap_free(u64 phys, unsigned long size, unsigned long flags) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci if (flags & EFI_MEMMAP_MEMBLOCK) { 358c2ecf20Sopenharmony_ci if (slab_is_available()) 368c2ecf20Sopenharmony_ci memblock_free_late(phys, size); 378c2ecf20Sopenharmony_ci else 388c2ecf20Sopenharmony_ci memblock_free(phys, size); 398c2ecf20Sopenharmony_ci } else if (flags & EFI_MEMMAP_SLAB) { 408c2ecf20Sopenharmony_ci struct page *p = pfn_to_page(PHYS_PFN(phys)); 418c2ecf20Sopenharmony_ci unsigned int order = get_order(size); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci free_pages((unsigned long) page_address(p), order); 448c2ecf20Sopenharmony_ci } 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic void __init efi_memmap_free(void) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci __efi_memmap_free(efi.memmap.phys_map, 508c2ecf20Sopenharmony_ci efi.memmap.desc_size * efi.memmap.nr_map, 518c2ecf20Sopenharmony_ci efi.memmap.flags); 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/** 558c2ecf20Sopenharmony_ci * efi_memmap_alloc - Allocate memory for the EFI memory map 568c2ecf20Sopenharmony_ci * @num_entries: Number of entries in the allocated map. 578c2ecf20Sopenharmony_ci * @data: efi memmap installation parameters 588c2ecf20Sopenharmony_ci * 598c2ecf20Sopenharmony_ci * Depending on whether mm_init() has already been invoked or not, 608c2ecf20Sopenharmony_ci * either memblock or "normal" page allocation is used. 618c2ecf20Sopenharmony_ci * 628c2ecf20Sopenharmony_ci * Returns the physical address of the allocated memory map on 638c2ecf20Sopenharmony_ci * success, zero on failure. 648c2ecf20Sopenharmony_ci */ 658c2ecf20Sopenharmony_ciint __init efi_memmap_alloc(unsigned int num_entries, 668c2ecf20Sopenharmony_ci struct efi_memory_map_data *data) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci /* Expect allocation parameters are zero initialized */ 698c2ecf20Sopenharmony_ci WARN_ON(data->phys_map || data->size); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci data->size = num_entries * efi.memmap.desc_size; 728c2ecf20Sopenharmony_ci data->desc_version = efi.memmap.desc_version; 738c2ecf20Sopenharmony_ci data->desc_size = efi.memmap.desc_size; 748c2ecf20Sopenharmony_ci data->flags &= ~(EFI_MEMMAP_SLAB | EFI_MEMMAP_MEMBLOCK); 758c2ecf20Sopenharmony_ci data->flags |= efi.memmap.flags & EFI_MEMMAP_LATE; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if (slab_is_available()) { 788c2ecf20Sopenharmony_ci data->flags |= EFI_MEMMAP_SLAB; 798c2ecf20Sopenharmony_ci data->phys_map = __efi_memmap_alloc_late(data->size); 808c2ecf20Sopenharmony_ci } else { 818c2ecf20Sopenharmony_ci data->flags |= EFI_MEMMAP_MEMBLOCK; 828c2ecf20Sopenharmony_ci data->phys_map = __efi_memmap_alloc_early(data->size); 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci if (!data->phys_map) 868c2ecf20Sopenharmony_ci return -ENOMEM; 878c2ecf20Sopenharmony_ci return 0; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/** 918c2ecf20Sopenharmony_ci * __efi_memmap_init - Common code for mapping the EFI memory map 928c2ecf20Sopenharmony_ci * @data: EFI memory map data 938c2ecf20Sopenharmony_ci * 948c2ecf20Sopenharmony_ci * This function takes care of figuring out which function to use to 958c2ecf20Sopenharmony_ci * map the EFI memory map in efi.memmap based on how far into the boot 968c2ecf20Sopenharmony_ci * we are. 978c2ecf20Sopenharmony_ci * 988c2ecf20Sopenharmony_ci * During bootup EFI_MEMMAP_LATE in data->flags should be clear since we 998c2ecf20Sopenharmony_ci * only have access to the early_memremap*() functions as the vmalloc 1008c2ecf20Sopenharmony_ci * space isn't setup. Once the kernel is fully booted we can fallback 1018c2ecf20Sopenharmony_ci * to the more robust memremap*() API. 1028c2ecf20Sopenharmony_ci * 1038c2ecf20Sopenharmony_ci * Returns zero on success, a negative error code on failure. 1048c2ecf20Sopenharmony_ci */ 1058c2ecf20Sopenharmony_cistatic int __init __efi_memmap_init(struct efi_memory_map_data *data) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci struct efi_memory_map map; 1088c2ecf20Sopenharmony_ci phys_addr_t phys_map; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (efi_enabled(EFI_PARAVIRT)) 1118c2ecf20Sopenharmony_ci return 0; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci phys_map = data->phys_map; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci if (data->flags & EFI_MEMMAP_LATE) 1168c2ecf20Sopenharmony_ci map.map = memremap(phys_map, data->size, MEMREMAP_WB); 1178c2ecf20Sopenharmony_ci else 1188c2ecf20Sopenharmony_ci map.map = early_memremap(phys_map, data->size); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci if (!map.map) { 1218c2ecf20Sopenharmony_ci pr_err("Could not map the memory map!\n"); 1228c2ecf20Sopenharmony_ci return -ENOMEM; 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci /* NOP if data->flags & (EFI_MEMMAP_MEMBLOCK | EFI_MEMMAP_SLAB) == 0 */ 1268c2ecf20Sopenharmony_ci efi_memmap_free(); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci map.phys_map = data->phys_map; 1298c2ecf20Sopenharmony_ci map.nr_map = data->size / data->desc_size; 1308c2ecf20Sopenharmony_ci map.map_end = map.map + data->size; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci map.desc_version = data->desc_version; 1338c2ecf20Sopenharmony_ci map.desc_size = data->desc_size; 1348c2ecf20Sopenharmony_ci map.flags = data->flags; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci set_bit(EFI_MEMMAP, &efi.flags); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci efi.memmap = map; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci return 0; 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci/** 1448c2ecf20Sopenharmony_ci * efi_memmap_init_early - Map the EFI memory map data structure 1458c2ecf20Sopenharmony_ci * @data: EFI memory map data 1468c2ecf20Sopenharmony_ci * 1478c2ecf20Sopenharmony_ci * Use early_memremap() to map the passed in EFI memory map and assign 1488c2ecf20Sopenharmony_ci * it to efi.memmap. 1498c2ecf20Sopenharmony_ci */ 1508c2ecf20Sopenharmony_ciint __init efi_memmap_init_early(struct efi_memory_map_data *data) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci /* Cannot go backwards */ 1538c2ecf20Sopenharmony_ci WARN_ON(efi.memmap.flags & EFI_MEMMAP_LATE); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci data->flags = 0; 1568c2ecf20Sopenharmony_ci return __efi_memmap_init(data); 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_civoid __init efi_memmap_unmap(void) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci if (!efi_enabled(EFI_MEMMAP)) 1628c2ecf20Sopenharmony_ci return; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci if (!(efi.memmap.flags & EFI_MEMMAP_LATE)) { 1658c2ecf20Sopenharmony_ci unsigned long size; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci size = efi.memmap.desc_size * efi.memmap.nr_map; 1688c2ecf20Sopenharmony_ci early_memunmap(efi.memmap.map, size); 1698c2ecf20Sopenharmony_ci } else { 1708c2ecf20Sopenharmony_ci memunmap(efi.memmap.map); 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci efi.memmap.map = NULL; 1748c2ecf20Sopenharmony_ci clear_bit(EFI_MEMMAP, &efi.flags); 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci/** 1788c2ecf20Sopenharmony_ci * efi_memmap_init_late - Map efi.memmap with memremap() 1798c2ecf20Sopenharmony_ci * @phys_addr: Physical address of the new EFI memory map 1808c2ecf20Sopenharmony_ci * @size: Size in bytes of the new EFI memory map 1818c2ecf20Sopenharmony_ci * 1828c2ecf20Sopenharmony_ci * Setup a mapping of the EFI memory map using ioremap_cache(). This 1838c2ecf20Sopenharmony_ci * function should only be called once the vmalloc space has been 1848c2ecf20Sopenharmony_ci * setup and is therefore not suitable for calling during early EFI 1858c2ecf20Sopenharmony_ci * initialise, e.g. in efi_init(). Additionally, it expects 1868c2ecf20Sopenharmony_ci * efi_memmap_init_early() to have already been called. 1878c2ecf20Sopenharmony_ci * 1888c2ecf20Sopenharmony_ci * The reason there are two EFI memmap initialisation 1898c2ecf20Sopenharmony_ci * (efi_memmap_init_early() and this late version) is because the 1908c2ecf20Sopenharmony_ci * early EFI memmap should be explicitly unmapped once EFI 1918c2ecf20Sopenharmony_ci * initialisation is complete as the fixmap space used to map the EFI 1928c2ecf20Sopenharmony_ci * memmap (via early_memremap()) is a scarce resource. 1938c2ecf20Sopenharmony_ci * 1948c2ecf20Sopenharmony_ci * This late mapping is intended to persist for the duration of 1958c2ecf20Sopenharmony_ci * runtime so that things like efi_mem_desc_lookup() and 1968c2ecf20Sopenharmony_ci * efi_mem_attributes() always work. 1978c2ecf20Sopenharmony_ci * 1988c2ecf20Sopenharmony_ci * Returns zero on success, a negative error code on failure. 1998c2ecf20Sopenharmony_ci */ 2008c2ecf20Sopenharmony_ciint __init efi_memmap_init_late(phys_addr_t addr, unsigned long size) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci struct efi_memory_map_data data = { 2038c2ecf20Sopenharmony_ci .phys_map = addr, 2048c2ecf20Sopenharmony_ci .size = size, 2058c2ecf20Sopenharmony_ci .flags = EFI_MEMMAP_LATE, 2068c2ecf20Sopenharmony_ci }; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci /* Did we forget to unmap the early EFI memmap? */ 2098c2ecf20Sopenharmony_ci WARN_ON(efi.memmap.map); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci /* Were we already called? */ 2128c2ecf20Sopenharmony_ci WARN_ON(efi.memmap.flags & EFI_MEMMAP_LATE); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci /* 2158c2ecf20Sopenharmony_ci * It makes no sense to allow callers to register different 2168c2ecf20Sopenharmony_ci * values for the following fields. Copy them out of the 2178c2ecf20Sopenharmony_ci * existing early EFI memmap. 2188c2ecf20Sopenharmony_ci */ 2198c2ecf20Sopenharmony_ci data.desc_version = efi.memmap.desc_version; 2208c2ecf20Sopenharmony_ci data.desc_size = efi.memmap.desc_size; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci return __efi_memmap_init(&data); 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci/** 2268c2ecf20Sopenharmony_ci * efi_memmap_install - Install a new EFI memory map in efi.memmap 2278c2ecf20Sopenharmony_ci * @ctx: map allocation parameters (address, size, flags) 2288c2ecf20Sopenharmony_ci * 2298c2ecf20Sopenharmony_ci * Unlike efi_memmap_init_*(), this function does not allow the caller 2308c2ecf20Sopenharmony_ci * to switch from early to late mappings. It simply uses the existing 2318c2ecf20Sopenharmony_ci * mapping function and installs the new memmap. 2328c2ecf20Sopenharmony_ci * 2338c2ecf20Sopenharmony_ci * Returns zero on success, a negative error code on failure. 2348c2ecf20Sopenharmony_ci */ 2358c2ecf20Sopenharmony_ciint __init efi_memmap_install(struct efi_memory_map_data *data) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci efi_memmap_unmap(); 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci return __efi_memmap_init(data); 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci/** 2438c2ecf20Sopenharmony_ci * efi_memmap_split_count - Count number of additional EFI memmap entries 2448c2ecf20Sopenharmony_ci * @md: EFI memory descriptor to split 2458c2ecf20Sopenharmony_ci * @range: Address range (start, end) to split around 2468c2ecf20Sopenharmony_ci * 2478c2ecf20Sopenharmony_ci * Returns the number of additional EFI memmap entries required to 2488c2ecf20Sopenharmony_ci * accomodate @range. 2498c2ecf20Sopenharmony_ci */ 2508c2ecf20Sopenharmony_ciint __init efi_memmap_split_count(efi_memory_desc_t *md, struct range *range) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci u64 m_start, m_end; 2538c2ecf20Sopenharmony_ci u64 start, end; 2548c2ecf20Sopenharmony_ci int count = 0; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci start = md->phys_addr; 2578c2ecf20Sopenharmony_ci end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci /* modifying range */ 2608c2ecf20Sopenharmony_ci m_start = range->start; 2618c2ecf20Sopenharmony_ci m_end = range->end; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci if (m_start <= start) { 2648c2ecf20Sopenharmony_ci /* split into 2 parts */ 2658c2ecf20Sopenharmony_ci if (start < m_end && m_end < end) 2668c2ecf20Sopenharmony_ci count++; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci if (start < m_start && m_start < end) { 2708c2ecf20Sopenharmony_ci /* split into 3 parts */ 2718c2ecf20Sopenharmony_ci if (m_end < end) 2728c2ecf20Sopenharmony_ci count += 2; 2738c2ecf20Sopenharmony_ci /* split into 2 parts */ 2748c2ecf20Sopenharmony_ci if (end <= m_end) 2758c2ecf20Sopenharmony_ci count++; 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci return count; 2798c2ecf20Sopenharmony_ci} 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci/** 2828c2ecf20Sopenharmony_ci * efi_memmap_insert - Insert a memory region in an EFI memmap 2838c2ecf20Sopenharmony_ci * @old_memmap: The existing EFI memory map structure 2848c2ecf20Sopenharmony_ci * @buf: Address of buffer to store new map 2858c2ecf20Sopenharmony_ci * @mem: Memory map entry to insert 2868c2ecf20Sopenharmony_ci * 2878c2ecf20Sopenharmony_ci * It is suggested that you call efi_memmap_split_count() first 2888c2ecf20Sopenharmony_ci * to see how large @buf needs to be. 2898c2ecf20Sopenharmony_ci */ 2908c2ecf20Sopenharmony_civoid __init efi_memmap_insert(struct efi_memory_map *old_memmap, void *buf, 2918c2ecf20Sopenharmony_ci struct efi_mem_range *mem) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci u64 m_start, m_end, m_attr; 2948c2ecf20Sopenharmony_ci efi_memory_desc_t *md; 2958c2ecf20Sopenharmony_ci u64 start, end; 2968c2ecf20Sopenharmony_ci void *old, *new; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci /* modifying range */ 2998c2ecf20Sopenharmony_ci m_start = mem->range.start; 3008c2ecf20Sopenharmony_ci m_end = mem->range.end; 3018c2ecf20Sopenharmony_ci m_attr = mem->attribute; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci /* 3048c2ecf20Sopenharmony_ci * The EFI memory map deals with regions in EFI_PAGE_SIZE 3058c2ecf20Sopenharmony_ci * units. Ensure that the region described by 'mem' is aligned 3068c2ecf20Sopenharmony_ci * correctly. 3078c2ecf20Sopenharmony_ci */ 3088c2ecf20Sopenharmony_ci if (!IS_ALIGNED(m_start, EFI_PAGE_SIZE) || 3098c2ecf20Sopenharmony_ci !IS_ALIGNED(m_end + 1, EFI_PAGE_SIZE)) { 3108c2ecf20Sopenharmony_ci WARN_ON(1); 3118c2ecf20Sopenharmony_ci return; 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci for (old = old_memmap->map, new = buf; 3158c2ecf20Sopenharmony_ci old < old_memmap->map_end; 3168c2ecf20Sopenharmony_ci old += old_memmap->desc_size, new += old_memmap->desc_size) { 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci /* copy original EFI memory descriptor */ 3198c2ecf20Sopenharmony_ci memcpy(new, old, old_memmap->desc_size); 3208c2ecf20Sopenharmony_ci md = new; 3218c2ecf20Sopenharmony_ci start = md->phys_addr; 3228c2ecf20Sopenharmony_ci end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci if (m_start <= start && end <= m_end) 3258c2ecf20Sopenharmony_ci md->attribute |= m_attr; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci if (m_start <= start && 3288c2ecf20Sopenharmony_ci (start < m_end && m_end < end)) { 3298c2ecf20Sopenharmony_ci /* first part */ 3308c2ecf20Sopenharmony_ci md->attribute |= m_attr; 3318c2ecf20Sopenharmony_ci md->num_pages = (m_end - md->phys_addr + 1) >> 3328c2ecf20Sopenharmony_ci EFI_PAGE_SHIFT; 3338c2ecf20Sopenharmony_ci /* latter part */ 3348c2ecf20Sopenharmony_ci new += old_memmap->desc_size; 3358c2ecf20Sopenharmony_ci memcpy(new, old, old_memmap->desc_size); 3368c2ecf20Sopenharmony_ci md = new; 3378c2ecf20Sopenharmony_ci md->phys_addr = m_end + 1; 3388c2ecf20Sopenharmony_ci md->num_pages = (end - md->phys_addr + 1) >> 3398c2ecf20Sopenharmony_ci EFI_PAGE_SHIFT; 3408c2ecf20Sopenharmony_ci } 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci if ((start < m_start && m_start < end) && m_end < end) { 3438c2ecf20Sopenharmony_ci /* first part */ 3448c2ecf20Sopenharmony_ci md->num_pages = (m_start - md->phys_addr) >> 3458c2ecf20Sopenharmony_ci EFI_PAGE_SHIFT; 3468c2ecf20Sopenharmony_ci /* middle part */ 3478c2ecf20Sopenharmony_ci new += old_memmap->desc_size; 3488c2ecf20Sopenharmony_ci memcpy(new, old, old_memmap->desc_size); 3498c2ecf20Sopenharmony_ci md = new; 3508c2ecf20Sopenharmony_ci md->attribute |= m_attr; 3518c2ecf20Sopenharmony_ci md->phys_addr = m_start; 3528c2ecf20Sopenharmony_ci md->num_pages = (m_end - m_start + 1) >> 3538c2ecf20Sopenharmony_ci EFI_PAGE_SHIFT; 3548c2ecf20Sopenharmony_ci /* last part */ 3558c2ecf20Sopenharmony_ci new += old_memmap->desc_size; 3568c2ecf20Sopenharmony_ci memcpy(new, old, old_memmap->desc_size); 3578c2ecf20Sopenharmony_ci md = new; 3588c2ecf20Sopenharmony_ci md->phys_addr = m_end + 1; 3598c2ecf20Sopenharmony_ci md->num_pages = (end - m_end) >> 3608c2ecf20Sopenharmony_ci EFI_PAGE_SHIFT; 3618c2ecf20Sopenharmony_ci } 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci if ((start < m_start && m_start < end) && 3648c2ecf20Sopenharmony_ci (end <= m_end)) { 3658c2ecf20Sopenharmony_ci /* first part */ 3668c2ecf20Sopenharmony_ci md->num_pages = (m_start - md->phys_addr) >> 3678c2ecf20Sopenharmony_ci EFI_PAGE_SHIFT; 3688c2ecf20Sopenharmony_ci /* latter part */ 3698c2ecf20Sopenharmony_ci new += old_memmap->desc_size; 3708c2ecf20Sopenharmony_ci memcpy(new, old, old_memmap->desc_size); 3718c2ecf20Sopenharmony_ci md = new; 3728c2ecf20Sopenharmony_ci md->phys_addr = m_start; 3738c2ecf20Sopenharmony_ci md->num_pages = (end - md->phys_addr + 1) >> 3748c2ecf20Sopenharmony_ci EFI_PAGE_SHIFT; 3758c2ecf20Sopenharmony_ci md->attribute |= m_attr; 3768c2ecf20Sopenharmony_ci } 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci} 379