2 * EFI application memory management
4 * Copyright (c) 2016 Alexander Graf
6 * SPDX-License-Identifier: GPL-2.0+
10 #include <efi_loader.h>
12 #include <asm/global_data.h>
13 #include <libfdt_env.h>
14 #include <linux/list_sort.h>
18 DECLARE_GLOBAL_DATA_PTR
;
21 struct list_head link
;
22 struct efi_mem_desc desc
;
25 #define EFI_CARVE_NO_OVERLAP -1
26 #define EFI_CARVE_LOOP_AGAIN -2
27 #define EFI_CARVE_OVERLAPS_NONRAM -3
29 /* This list contains all memory map items */
32 #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
33 void *efi_bounce_buffer
;
37 * U-Boot services each EFI AllocatePool request as a separate
38 * (multiple) page allocation. We have to track the number of pages
39 * to be able to free the correct amount later.
40 * EFI requires 8 byte alignment for pool allocations, so we can
41 * prepend each allocation with an 64 bit header tracking the
42 * allocation size, and hand out the remainder to the caller.
44 struct efi_pool_allocation
{
46 char data
[] __aligned(ARCH_DMA_MINALIGN
);
50 * Sorts the memory list from highest address to lowest address
52 * When allocating memory we should always start from the highest
53 * address chunk, so sort the memory list such that the first list
54 * iterator gets the highest address and goes lower from there.
56 static int efi_mem_cmp(void *priv
, struct list_head
*a
, struct list_head
*b
)
58 struct efi_mem_list
*mema
= list_entry(a
, struct efi_mem_list
, link
);
59 struct efi_mem_list
*memb
= list_entry(b
, struct efi_mem_list
, link
);
61 if (mema
->desc
.physical_start
== memb
->desc
.physical_start
)
63 else if (mema
->desc
.physical_start
< memb
->desc
.physical_start
)
69 static void efi_mem_sort(void)
71 list_sort(NULL
, &efi_mem
, efi_mem_cmp
);
75 * Unmaps all memory occupied by the carve_desc region from the
76 * list entry pointed to by map.
78 * Returns EFI_CARVE_NO_OVERLAP if the regions don't overlap.
79 * Returns EFI_CARVE_OVERLAPS_NONRAM if the carve and map overlap,
80 * and the map contains anything but free ram.
81 * (only when overlap_only_ram is true)
82 * Returns EFI_CARVE_LOOP_AGAIN if the mapping list should be traversed
83 * again, as it has been altered
84 * Returns the number of overlapping pages. The pages are removed from
87 * In case of EFI_CARVE_OVERLAPS_NONRAM it is the callers responsibility
88 * to readd the already carved out pages to the mapping.
90 static int efi_mem_carve_out(struct efi_mem_list
*map
,
91 struct efi_mem_desc
*carve_desc
,
92 bool overlap_only_ram
)
94 struct efi_mem_list
*newmap
;
95 struct efi_mem_desc
*map_desc
= &map
->desc
;
96 uint64_t map_start
= map_desc
->physical_start
;
97 uint64_t map_end
= map_start
+ (map_desc
->num_pages
<< EFI_PAGE_SHIFT
);
98 uint64_t carve_start
= carve_desc
->physical_start
;
99 uint64_t carve_end
= carve_start
+
100 (carve_desc
->num_pages
<< EFI_PAGE_SHIFT
);
102 /* check whether we're overlapping */
103 if ((carve_end
<= map_start
) || (carve_start
>= map_end
))
104 return EFI_CARVE_NO_OVERLAP
;
106 /* We're overlapping with non-RAM, warn the caller if desired */
107 if (overlap_only_ram
&& (map_desc
->type
!= EFI_CONVENTIONAL_MEMORY
))
108 return EFI_CARVE_OVERLAPS_NONRAM
;
110 /* Sanitize carve_start and carve_end to lie within our bounds */
111 carve_start
= max(carve_start
, map_start
);
112 carve_end
= min(carve_end
, map_end
);
114 /* Carving at the beginning of our map? Just move it! */
115 if (carve_start
== map_start
) {
116 if (map_end
== carve_end
) {
117 /* Full overlap, just remove map */
118 list_del(&map
->link
);
121 map
->desc
.physical_start
= carve_end
;
122 map
->desc
.num_pages
= (map_end
- carve_end
)
126 return (carve_end
- carve_start
) >> EFI_PAGE_SHIFT
;
130 * Overlapping maps, just split the list map at carve_start,
131 * it will get moved or removed in the next iteration.
133 * [ map_desc |__carve_start__| newmap ]
136 /* Create a new map from [ carve_start ... map_end ] */
137 newmap
= calloc(1, sizeof(*newmap
));
138 newmap
->desc
= map
->desc
;
139 newmap
->desc
.physical_start
= carve_start
;
140 newmap
->desc
.num_pages
= (map_end
- carve_start
) >> EFI_PAGE_SHIFT
;
141 /* Insert before current entry (descending address order) */
142 list_add_tail(&newmap
->link
, &map
->link
);
144 /* Shrink the map to [ map_start ... carve_start ] */
145 map_desc
->num_pages
= (carve_start
- map_start
) >> EFI_PAGE_SHIFT
;
147 return EFI_CARVE_LOOP_AGAIN
;
150 uint64_t efi_add_memory_map(uint64_t start
, uint64_t pages
, int memory_type
,
151 bool overlap_only_ram
)
153 struct list_head
*lhandle
;
154 struct efi_mem_list
*newlist
;
156 uint64_t carved_pages
= 0;
158 debug("%s: 0x%" PRIx64
" 0x%" PRIx64
" %d %s\n", __func__
,
159 start
, pages
, memory_type
, overlap_only_ram
? "yes" : "no");
164 newlist
= calloc(1, sizeof(*newlist
));
165 newlist
->desc
.type
= memory_type
;
166 newlist
->desc
.physical_start
= start
;
167 newlist
->desc
.virtual_start
= start
;
168 newlist
->desc
.num_pages
= pages
;
170 switch (memory_type
) {
171 case EFI_RUNTIME_SERVICES_CODE
:
172 case EFI_RUNTIME_SERVICES_DATA
:
173 newlist
->desc
.attribute
= (1 << EFI_MEMORY_WB_SHIFT
) |
174 (1ULL << EFI_MEMORY_RUNTIME_SHIFT
);
177 newlist
->desc
.attribute
= 1ULL << EFI_MEMORY_RUNTIME_SHIFT
;
180 newlist
->desc
.attribute
= 1 << EFI_MEMORY_WB_SHIFT
;
184 /* Add our new map */
187 list_for_each(lhandle
, &efi_mem
) {
188 struct efi_mem_list
*lmem
;
191 lmem
= list_entry(lhandle
, struct efi_mem_list
, link
);
192 r
= efi_mem_carve_out(lmem
, &newlist
->desc
,
195 case EFI_CARVE_OVERLAPS_NONRAM
:
197 * The user requested to only have RAM overlaps,
198 * but we hit a non-RAM region. Error out.
201 case EFI_CARVE_NO_OVERLAP
:
202 /* Just ignore this list entry */
204 case EFI_CARVE_LOOP_AGAIN
:
206 * We split an entry, but need to loop through
207 * the list again to actually carve it.
212 /* We carved a number of pages */
219 /* The list changed, we need to start over */
223 } while (carve_again
);
225 if (overlap_only_ram
&& (carved_pages
!= pages
)) {
227 * The payload wanted to have RAM overlaps, but we overlapped
228 * with an unallocated region. Error out.
233 /* Add our new map */
234 list_add_tail(&newlist
->link
, &efi_mem
);
236 /* And make sure memory is listed in descending order */
242 static uint64_t efi_find_free_memory(uint64_t len
, uint64_t max_addr
)
244 struct list_head
*lhandle
;
246 list_for_each(lhandle
, &efi_mem
) {
247 struct efi_mem_list
*lmem
= list_entry(lhandle
,
248 struct efi_mem_list
, link
);
249 struct efi_mem_desc
*desc
= &lmem
->desc
;
250 uint64_t desc_len
= desc
->num_pages
<< EFI_PAGE_SHIFT
;
251 uint64_t desc_end
= desc
->physical_start
+ desc_len
;
252 uint64_t curmax
= min(max_addr
, desc_end
);
253 uint64_t ret
= curmax
- len
;
255 /* We only take memory from free RAM */
256 if (desc
->type
!= EFI_CONVENTIONAL_MEMORY
)
259 /* Out of bounds for max_addr */
260 if ((ret
+ len
) > max_addr
)
263 /* Out of bounds for upper map limit */
264 if ((ret
+ len
) > desc_end
)
267 /* Out of bounds for lower map limit */
268 if (ret
< desc
->physical_start
)
271 /* Return the highest address in this map within bounds */
279 * Allocate memory pages.
281 * @type type of allocation to be performed
282 * @memory_type usage type of the allocated memory
283 * @pages number of pages to be allocated
284 * @memory allocated memory
285 * @return status code
287 efi_status_t
efi_allocate_pages(int type
, int memory_type
,
288 efi_uintn_t pages
, uint64_t *memory
)
290 u64 len
= pages
<< EFI_PAGE_SHIFT
;
291 efi_status_t r
= EFI_SUCCESS
;
297 addr
= efi_find_free_memory(len
, gd
->start_addr_sp
);
305 addr
= efi_find_free_memory(len
, *memory
);
312 /* Exact address, reserve it. The addr is already in *memory. */
316 /* UEFI doesn't specify other allocation types */
317 r
= EFI_INVALID_PARAMETER
;
321 if (r
== EFI_SUCCESS
) {
324 /* Reserve that map in our memory maps */
325 ret
= efi_add_memory_map(addr
, pages
, memory_type
, true);
329 /* Map would overlap, bail out */
330 r
= EFI_OUT_OF_RESOURCES
;
337 void *efi_alloc(uint64_t len
, int memory_type
)
340 uint64_t pages
= (len
+ EFI_PAGE_MASK
) >> EFI_PAGE_SHIFT
;
343 r
= efi_allocate_pages(0, memory_type
, pages
, &ret
);
344 if (r
== EFI_SUCCESS
)
345 return (void*)(uintptr_t)ret
;
353 * @memory start of the memory area to be freed
354 * @pages number of pages to be freed
355 * @return status code
357 efi_status_t
efi_free_pages(uint64_t memory
, efi_uintn_t pages
)
361 r
= efi_add_memory_map(memory
, pages
, EFI_CONVENTIONAL_MEMORY
, false);
362 /* Merging of adjacent free regions is missing */
367 return EFI_NOT_FOUND
;
371 * Allocate memory from pool.
373 * @pool_type type of the pool from which memory is to be allocated
374 * @size number of bytes to be allocated
375 * @buffer allocated memory
376 * @return status code
378 efi_status_t
efi_allocate_pool(int pool_type
, efi_uintn_t size
, void **buffer
)
381 efi_physical_addr_t t
;
382 u64 num_pages
= (size
+ sizeof(struct efi_pool_allocation
) +
383 EFI_PAGE_MASK
) >> EFI_PAGE_SHIFT
;
390 r
= efi_allocate_pages(0, pool_type
, num_pages
, &t
);
392 if (r
== EFI_SUCCESS
) {
393 struct efi_pool_allocation
*alloc
= (void *)(uintptr_t)t
;
394 alloc
->num_pages
= num_pages
;
395 *buffer
= alloc
->data
;
402 * Free memory from pool.
404 * @buffer start of memory to be freed
405 * @return status code
407 efi_status_t
efi_free_pool(void *buffer
)
410 struct efi_pool_allocation
*alloc
;
413 return EFI_INVALID_PARAMETER
;
415 alloc
= container_of(buffer
, struct efi_pool_allocation
, data
);
416 /* Sanity check, was the supplied address returned by allocate_pool */
417 assert(((uintptr_t)alloc
& EFI_PAGE_MASK
) == 0);
419 r
= efi_free_pages((uintptr_t)alloc
, alloc
->num_pages
);
425 * Get map describing memory usage.
427 * @memory_map_size on entry the size, in bytes, of the memory map buffer,
428 * on exit the size of the copied memory map
429 * @memory_map buffer to which the memory map is written
430 * @map_key key for the memory map
431 * @descriptor_size size of an individual memory descriptor
432 * @descriptor_version version number of the memory descriptor structure
433 * @return status code
435 efi_status_t
efi_get_memory_map(efi_uintn_t
*memory_map_size
,
436 struct efi_mem_desc
*memory_map
,
437 efi_uintn_t
*map_key
,
438 efi_uintn_t
*descriptor_size
,
439 uint32_t *descriptor_version
)
441 efi_uintn_t map_size
= 0;
443 struct list_head
*lhandle
;
444 efi_uintn_t provided_map_size
= *memory_map_size
;
446 list_for_each(lhandle
, &efi_mem
)
449 map_size
= map_entries
* sizeof(struct efi_mem_desc
);
451 *memory_map_size
= map_size
;
453 if (provided_map_size
< map_size
)
454 return EFI_BUFFER_TOO_SMALL
;
457 *descriptor_size
= sizeof(struct efi_mem_desc
);
459 if (descriptor_version
)
460 *descriptor_version
= EFI_MEMORY_DESCRIPTOR_VERSION
;
462 /* Copy list into array */
464 /* Return the list in ascending order */
465 memory_map
= &memory_map
[map_entries
- 1];
466 list_for_each(lhandle
, &efi_mem
) {
467 struct efi_mem_list
*lmem
;
469 lmem
= list_entry(lhandle
, struct efi_mem_list
, link
);
470 *memory_map
= lmem
->desc
;
480 __weak
void efi_add_known_memory(void)
485 for (i
= 0; i
< CONFIG_NR_DRAM_BANKS
; i
++) {
486 u64 ram_start
= gd
->bd
->bi_dram
[i
].start
;
487 u64 ram_size
= gd
->bd
->bi_dram
[i
].size
;
488 u64 start
= (ram_start
+ EFI_PAGE_MASK
) & ~EFI_PAGE_MASK
;
489 u64 pages
= (ram_size
+ EFI_PAGE_MASK
) >> EFI_PAGE_SHIFT
;
491 efi_add_memory_map(start
, pages
, EFI_CONVENTIONAL_MEMORY
,
496 int efi_memory_init(void)
498 unsigned long runtime_start
, runtime_end
, runtime_pages
;
499 unsigned long uboot_start
, uboot_pages
;
500 unsigned long uboot_stack_size
= 16 * 1024 * 1024;
502 efi_add_known_memory();
505 uboot_start
= (gd
->start_addr_sp
- uboot_stack_size
) & ~EFI_PAGE_MASK
;
506 uboot_pages
= (gd
->ram_top
- uboot_start
) >> EFI_PAGE_SHIFT
;
507 efi_add_memory_map(uboot_start
, uboot_pages
, EFI_LOADER_DATA
, false);
509 /* Add Runtime Services */
510 runtime_start
= (ulong
)&__efi_runtime_start
& ~EFI_PAGE_MASK
;
511 runtime_end
= (ulong
)&__efi_runtime_stop
;
512 runtime_end
= (runtime_end
+ EFI_PAGE_MASK
) & ~EFI_PAGE_MASK
;
513 runtime_pages
= (runtime_end
- runtime_start
) >> EFI_PAGE_SHIFT
;
514 efi_add_memory_map(runtime_start
, runtime_pages
,
515 EFI_RUNTIME_SERVICES_CODE
, false);
517 #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
518 /* Request a 32bit 64MB bounce buffer region */
519 uint64_t efi_bounce_buffer_addr
= 0xffffffff;
521 if (efi_allocate_pages(1, EFI_LOADER_DATA
,
522 (64 * 1024 * 1024) >> EFI_PAGE_SHIFT
,
523 &efi_bounce_buffer_addr
) != EFI_SUCCESS
)
526 efi_bounce_buffer
= (void*)(uintptr_t)efi_bounce_buffer_addr
;