1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/efi.h> 4 #include <asm/efi.h> 5 6 #include "efistub.h" 7 8 #define EFI_MMAP_NR_SLACK_SLOTS 8 9 10 static inline bool mmap_has_headroom(unsigned long buff_size, 11 unsigned long map_size, 12 unsigned long desc_size) 13 { 14 unsigned long slack = buff_size - map_size; 15 16 return slack / desc_size >= EFI_MMAP_NR_SLACK_SLOTS; 17 } 18 19 /** 20 * efi_get_memory_map() - get memory map 21 * @map: on return pointer to memory map 22 * 23 * Retrieve the UEFI memory map. The allocated memory leaves room for 24 * up to EFI_MMAP_NR_SLACK_SLOTS additional memory map entries. 25 * 26 * Return: status code 27 */ 28 efi_status_t efi_get_memory_map(struct efi_boot_memmap *map) 29 { 30 efi_memory_desc_t *m = NULL; 31 efi_status_t status; 32 unsigned long key; 33 u32 desc_version; 34 35 *map->desc_size = sizeof(*m); 36 *map->map_size = *map->desc_size * 32; 37 *map->buff_size = *map->map_size; 38 again: 39 status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, 40 *map->map_size, (void **)&m); 41 if (status != EFI_SUCCESS) 42 goto fail; 43 44 *map->desc_size = 0; 45 key = 0; 46 status = efi_bs_call(get_memory_map, map->map_size, m, 47 &key, map->desc_size, &desc_version); 48 if (status == EFI_BUFFER_TOO_SMALL || 49 !mmap_has_headroom(*map->buff_size, *map->map_size, 50 *map->desc_size)) { 51 efi_bs_call(free_pool, m); 52 /* 53 * Make sure there is some entries of headroom so that the 54 * buffer can be reused for a new map after allocations are 55 * no longer permitted. Its unlikely that the map will grow to 56 * exceed this headroom once we are ready to trigger 57 * ExitBootServices() 58 */ 59 *map->map_size += *map->desc_size * EFI_MMAP_NR_SLACK_SLOTS; 60 *map->buff_size = *map->map_size; 61 goto again; 62 } 63 64 if (status == EFI_SUCCESS) { 65 if (map->key_ptr) 66 *map->key_ptr = key; 67 if (map->desc_ver) 68 *map->desc_ver = desc_version; 69 } else { 70 efi_bs_call(free_pool, m); 71 } 72 73 fail: 74 *map->map = m; 75 return status; 76 } 77 78 /** 79 * efi_allocate_pages() - Allocate memory pages 80 * @size: minimum number of bytes to allocate 81 * @addr: On return the address of the first allocated page. The first 82 * allocated page has alignment EFI_ALLOC_ALIGN which is an 83 * architecture dependent multiple of the page size. 84 * @max: the address that the last allocated memory page shall not 85 * exceed 86 * 87 * Allocate pages as EFI_LOADER_DATA. The allocated pages are aligned according 88 * to EFI_ALLOC_ALIGN. The last allocated page will not exceed the address 89 * given by @max. 90 * 91 * Return: status code 92 */ 93 efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr, 94 unsigned long max) 95 { 96 efi_physical_addr_t alloc_addr; 97 efi_status_t status; 98 99 if (EFI_ALLOC_ALIGN > EFI_PAGE_SIZE) 100 return efi_allocate_pages_aligned(size, addr, max, 101 EFI_ALLOC_ALIGN); 102 103 alloc_addr = ALIGN_DOWN(max + 1, EFI_ALLOC_ALIGN) - 1; 104 status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS, 105 EFI_LOADER_DATA, DIV_ROUND_UP(size, EFI_PAGE_SIZE), 106 &alloc_addr); 107 if (status != EFI_SUCCESS) 108 return status; 109 110 *addr = alloc_addr; 111 return EFI_SUCCESS; 112 } 113 114 /** 115 * efi_free() - free memory pages 116 * @size: size of the memory area to free in bytes 117 * @addr: start of the memory area to free (must be EFI_PAGE_SIZE 118 * aligned) 119 * 120 * @size is rounded up to a multiple of EFI_ALLOC_ALIGN which is an 121 * architecture specific multiple of EFI_PAGE_SIZE. So this function should 122 * only be used to return pages allocated with efi_allocate_pages() or 123 * efi_low_alloc_above(). 124 */ 125 void efi_free(unsigned long size, unsigned long addr) 126 { 127 unsigned long nr_pages; 128 129 if (!size) 130 return; 131 132 nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE; 133 efi_bs_call(free_pages, addr, nr_pages); 134 } 135