xref: /openbmc/linux/drivers/firmware/efi/memmap.c (revision 1db91035)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Common EFI memory map functions.
4  */
5 
6 #define pr_fmt(fmt) "efi: " fmt
7 
8 #include <linux/init.h>
9 #include <linux/kernel.h>
10 #include <linux/efi.h>
11 #include <linux/io.h>
12 #include <asm/early_ioremap.h>
13 #include <linux/memblock.h>
14 #include <linux/slab.h>
15 
16 static phys_addr_t __init __efi_memmap_alloc_early(unsigned long size)
17 {
18 	return memblock_phys_alloc(size, SMP_CACHE_BYTES);
19 }
20 
21 static phys_addr_t __init __efi_memmap_alloc_late(unsigned long size)
22 {
23 	unsigned int order = get_order(size);
24 	struct page *p = alloc_pages(GFP_KERNEL, order);
25 
26 	if (!p)
27 		return 0;
28 
29 	return PFN_PHYS(page_to_pfn(p));
30 }
31 
32 /**
33  * efi_memmap_alloc - Allocate memory for the EFI memory map
34  * @num_entries: Number of entries in the allocated map.
35  * @data: efi memmap installation parameters
36  *
37  * Depending on whether mm_init() has already been invoked or not,
38  * either memblock or "normal" page allocation is used.
39  *
40  * Returns the physical address of the allocated memory map on
41  * success, zero on failure.
42  */
43 int __init efi_memmap_alloc(unsigned int num_entries,
44 		struct efi_memory_map_data *data)
45 {
46 	/* Expect allocation parameters are zero initialized */
47 	WARN_ON(data->phys_map || data->size);
48 
49 	data->size = num_entries * efi.memmap.desc_size;
50 	data->desc_version = efi.memmap.desc_version;
51 	data->desc_size = efi.memmap.desc_size;
52 	data->flags &= ~(EFI_MEMMAP_SLAB | EFI_MEMMAP_MEMBLOCK);
53 	data->flags |= efi.memmap.flags & EFI_MEMMAP_LATE;
54 
55 	if (slab_is_available()) {
56 		data->flags |= EFI_MEMMAP_SLAB;
57 		data->phys_map = __efi_memmap_alloc_late(data->size);
58 	} else {
59 		data->flags |= EFI_MEMMAP_MEMBLOCK;
60 		data->phys_map = __efi_memmap_alloc_early(data->size);
61 	}
62 
63 	if (!data->phys_map)
64 		return -ENOMEM;
65 	return 0;
66 }
67 
68 /**
69  * __efi_memmap_init - Common code for mapping the EFI memory map
70  * @data: EFI memory map data
71  *
72  * This function takes care of figuring out which function to use to
73  * map the EFI memory map in efi.memmap based on how far into the boot
74  * we are.
75  *
76  * During bootup EFI_MEMMAP_LATE in data->flags should be clear since we
77  * only have access to the early_memremap*() functions as the vmalloc
78  * space isn't setup.  Once the kernel is fully booted we can fallback
79  * to the more robust memremap*() API.
80  *
81  * Returns zero on success, a negative error code on failure.
82  */
83 static int __init __efi_memmap_init(struct efi_memory_map_data *data)
84 {
85 	struct efi_memory_map map;
86 	phys_addr_t phys_map;
87 
88 	if (efi_enabled(EFI_PARAVIRT))
89 		return 0;
90 
91 	phys_map = data->phys_map;
92 
93 	if (data->flags & EFI_MEMMAP_LATE)
94 		map.map = memremap(phys_map, data->size, MEMREMAP_WB);
95 	else
96 		map.map = early_memremap(phys_map, data->size);
97 
98 	if (!map.map) {
99 		pr_err("Could not map the memory map!\n");
100 		return -ENOMEM;
101 	}
102 
103 	map.phys_map = data->phys_map;
104 	map.nr_map = data->size / data->desc_size;
105 	map.map_end = map.map + data->size;
106 
107 	map.desc_version = data->desc_version;
108 	map.desc_size = data->desc_size;
109 	map.flags = data->flags;
110 
111 	set_bit(EFI_MEMMAP, &efi.flags);
112 
113 	efi.memmap = map;
114 
115 	return 0;
116 }
117 
118 /**
119  * efi_memmap_init_early - Map the EFI memory map data structure
120  * @data: EFI memory map data
121  *
122  * Use early_memremap() to map the passed in EFI memory map and assign
123  * it to efi.memmap.
124  */
125 int __init efi_memmap_init_early(struct efi_memory_map_data *data)
126 {
127 	/* Cannot go backwards */
128 	WARN_ON(efi.memmap.flags & EFI_MEMMAP_LATE);
129 
130 	data->flags = 0;
131 	return __efi_memmap_init(data);
132 }
133 
134 void __init efi_memmap_unmap(void)
135 {
136 	if (!efi_enabled(EFI_MEMMAP))
137 		return;
138 
139 	if (!(efi.memmap.flags & EFI_MEMMAP_LATE)) {
140 		unsigned long size;
141 
142 		size = efi.memmap.desc_size * efi.memmap.nr_map;
143 		early_memunmap(efi.memmap.map, size);
144 	} else {
145 		memunmap(efi.memmap.map);
146 	}
147 
148 	efi.memmap.map = NULL;
149 	clear_bit(EFI_MEMMAP, &efi.flags);
150 }
151 
152 /**
153  * efi_memmap_init_late - Map efi.memmap with memremap()
154  * @phys_addr: Physical address of the new EFI memory map
155  * @size: Size in bytes of the new EFI memory map
156  *
157  * Setup a mapping of the EFI memory map using ioremap_cache(). This
158  * function should only be called once the vmalloc space has been
159  * setup and is therefore not suitable for calling during early EFI
160  * initialise, e.g. in efi_init(). Additionally, it expects
161  * efi_memmap_init_early() to have already been called.
162  *
163  * The reason there are two EFI memmap initialisation
164  * (efi_memmap_init_early() and this late version) is because the
165  * early EFI memmap should be explicitly unmapped once EFI
166  * initialisation is complete as the fixmap space used to map the EFI
167  * memmap (via early_memremap()) is a scarce resource.
168  *
169  * This late mapping is intended to persist for the duration of
170  * runtime so that things like efi_mem_desc_lookup() and
171  * efi_mem_attributes() always work.
172  *
173  * Returns zero on success, a negative error code on failure.
174  */
175 int __init efi_memmap_init_late(phys_addr_t addr, unsigned long size)
176 {
177 	struct efi_memory_map_data data = {
178 		.phys_map = addr,
179 		.size = size,
180 		.flags = EFI_MEMMAP_LATE,
181 	};
182 
183 	/* Did we forget to unmap the early EFI memmap? */
184 	WARN_ON(efi.memmap.map);
185 
186 	/* Were we already called? */
187 	WARN_ON(efi.memmap.flags & EFI_MEMMAP_LATE);
188 
189 	/*
190 	 * It makes no sense to allow callers to register different
191 	 * values for the following fields. Copy them out of the
192 	 * existing early EFI memmap.
193 	 */
194 	data.desc_version = efi.memmap.desc_version;
195 	data.desc_size = efi.memmap.desc_size;
196 
197 	return __efi_memmap_init(&data);
198 }
199 
200 /**
201  * efi_memmap_install - Install a new EFI memory map in efi.memmap
202  * @ctx: map allocation parameters (address, size, flags)
203  *
204  * Unlike efi_memmap_init_*(), this function does not allow the caller
205  * to switch from early to late mappings. It simply uses the existing
206  * mapping function and installs the new memmap.
207  *
208  * Returns zero on success, a negative error code on failure.
209  */
210 int __init efi_memmap_install(struct efi_memory_map_data *data)
211 {
212 	efi_memmap_unmap();
213 
214 	return __efi_memmap_init(data);
215 }
216 
217 /**
218  * efi_memmap_split_count - Count number of additional EFI memmap entries
219  * @md: EFI memory descriptor to split
220  * @range: Address range (start, end) to split around
221  *
222  * Returns the number of additional EFI memmap entries required to
223  * accomodate @range.
224  */
225 int __init efi_memmap_split_count(efi_memory_desc_t *md, struct range *range)
226 {
227 	u64 m_start, m_end;
228 	u64 start, end;
229 	int count = 0;
230 
231 	start = md->phys_addr;
232 	end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1;
233 
234 	/* modifying range */
235 	m_start = range->start;
236 	m_end = range->end;
237 
238 	if (m_start <= start) {
239 		/* split into 2 parts */
240 		if (start < m_end && m_end < end)
241 			count++;
242 	}
243 
244 	if (start < m_start && m_start < end) {
245 		/* split into 3 parts */
246 		if (m_end < end)
247 			count += 2;
248 		/* split into 2 parts */
249 		if (end <= m_end)
250 			count++;
251 	}
252 
253 	return count;
254 }
255 
256 /**
257  * efi_memmap_insert - Insert a memory region in an EFI memmap
258  * @old_memmap: The existing EFI memory map structure
259  * @buf: Address of buffer to store new map
260  * @mem: Memory map entry to insert
261  *
262  * It is suggested that you call efi_memmap_split_count() first
263  * to see how large @buf needs to be.
264  */
265 void __init efi_memmap_insert(struct efi_memory_map *old_memmap, void *buf,
266 			      struct efi_mem_range *mem)
267 {
268 	u64 m_start, m_end, m_attr;
269 	efi_memory_desc_t *md;
270 	u64 start, end;
271 	void *old, *new;
272 
273 	/* modifying range */
274 	m_start = mem->range.start;
275 	m_end = mem->range.end;
276 	m_attr = mem->attribute;
277 
278 	/*
279 	 * The EFI memory map deals with regions in EFI_PAGE_SIZE
280 	 * units. Ensure that the region described by 'mem' is aligned
281 	 * correctly.
282 	 */
283 	if (!IS_ALIGNED(m_start, EFI_PAGE_SIZE) ||
284 	    !IS_ALIGNED(m_end + 1, EFI_PAGE_SIZE)) {
285 		WARN_ON(1);
286 		return;
287 	}
288 
289 	for (old = old_memmap->map, new = buf;
290 	     old < old_memmap->map_end;
291 	     old += old_memmap->desc_size, new += old_memmap->desc_size) {
292 
293 		/* copy original EFI memory descriptor */
294 		memcpy(new, old, old_memmap->desc_size);
295 		md = new;
296 		start = md->phys_addr;
297 		end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
298 
299 		if (m_start <= start && end <= m_end)
300 			md->attribute |= m_attr;
301 
302 		if (m_start <= start &&
303 		    (start < m_end && m_end < end)) {
304 			/* first part */
305 			md->attribute |= m_attr;
306 			md->num_pages = (m_end - md->phys_addr + 1) >>
307 				EFI_PAGE_SHIFT;
308 			/* latter part */
309 			new += old_memmap->desc_size;
310 			memcpy(new, old, old_memmap->desc_size);
311 			md = new;
312 			md->phys_addr = m_end + 1;
313 			md->num_pages = (end - md->phys_addr + 1) >>
314 				EFI_PAGE_SHIFT;
315 		}
316 
317 		if ((start < m_start && m_start < end) && m_end < end) {
318 			/* first part */
319 			md->num_pages = (m_start - md->phys_addr) >>
320 				EFI_PAGE_SHIFT;
321 			/* middle part */
322 			new += old_memmap->desc_size;
323 			memcpy(new, old, old_memmap->desc_size);
324 			md = new;
325 			md->attribute |= m_attr;
326 			md->phys_addr = m_start;
327 			md->num_pages = (m_end - m_start + 1) >>
328 				EFI_PAGE_SHIFT;
329 			/* last part */
330 			new += old_memmap->desc_size;
331 			memcpy(new, old, old_memmap->desc_size);
332 			md = new;
333 			md->phys_addr = m_end + 1;
334 			md->num_pages = (end - m_end) >>
335 				EFI_PAGE_SHIFT;
336 		}
337 
338 		if ((start < m_start && m_start < end) &&
339 		    (end <= m_end)) {
340 			/* first part */
341 			md->num_pages = (m_start - md->phys_addr) >>
342 				EFI_PAGE_SHIFT;
343 			/* latter part */
344 			new += old_memmap->desc_size;
345 			memcpy(new, old, old_memmap->desc_size);
346 			md = new;
347 			md->phys_addr = m_start;
348 			md->num_pages = (end - md->phys_addr + 1) >>
349 				EFI_PAGE_SHIFT;
350 			md->attribute |= m_attr;
351 		}
352 	}
353 }
354