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