1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2016 Linaro Ltd; <ard.biesheuvel@linaro.org> 4 */ 5 6 #include <linux/efi.h> 7 #include <linux/log2.h> 8 #include <asm/efi.h> 9 10 #include "efistub.h" 11 12 typedef struct efi_rng_protocol efi_rng_protocol_t; 13 14 typedef struct { 15 u32 get_info; 16 u32 get_rng; 17 } efi_rng_protocol_32_t; 18 19 typedef struct { 20 u64 get_info; 21 u64 get_rng; 22 } efi_rng_protocol_64_t; 23 24 struct efi_rng_protocol { 25 efi_status_t (*get_info)(struct efi_rng_protocol *, 26 unsigned long *, efi_guid_t *); 27 efi_status_t (*get_rng)(struct efi_rng_protocol *, 28 efi_guid_t *, unsigned long, u8 *out); 29 }; 30 31 efi_status_t efi_get_random_bytes(efi_system_table_t *sys_table_arg, 32 unsigned long size, u8 *out) 33 { 34 efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID; 35 efi_status_t status; 36 struct efi_rng_protocol *rng; 37 38 status = efi_call_early(locate_protocol, &rng_proto, NULL, 39 (void **)&rng); 40 if (status != EFI_SUCCESS) 41 return status; 42 43 return efi_call_proto(efi_rng_protocol, get_rng, rng, NULL, size, out); 44 } 45 46 /* 47 * Return the number of slots covered by this entry, i.e., the number of 48 * addresses it covers that are suitably aligned and supply enough room 49 * for the allocation. 50 */ 51 static unsigned long get_entry_num_slots(efi_memory_desc_t *md, 52 unsigned long size, 53 unsigned long align_shift) 54 { 55 unsigned long align = 1UL << align_shift; 56 u64 first_slot, last_slot, region_end; 57 58 if (md->type != EFI_CONVENTIONAL_MEMORY) 59 return 0; 60 61 if (efi_soft_reserve_enabled() && 62 (md->attribute & EFI_MEMORY_SP)) 63 return 0; 64 65 region_end = min((u64)ULONG_MAX, md->phys_addr + md->num_pages*EFI_PAGE_SIZE - 1); 66 67 first_slot = round_up(md->phys_addr, align); 68 last_slot = round_down(region_end - size + 1, align); 69 70 if (first_slot > last_slot) 71 return 0; 72 73 return ((unsigned long)(last_slot - first_slot) >> align_shift) + 1; 74 } 75 76 /* 77 * The UEFI memory descriptors have a virtual address field that is only used 78 * when installing the virtual mapping using SetVirtualAddressMap(). Since it 79 * is unused here, we can reuse it to keep track of each descriptor's slot 80 * count. 81 */ 82 #define MD_NUM_SLOTS(md) ((md)->virt_addr) 83 84 efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg, 85 unsigned long size, 86 unsigned long align, 87 unsigned long *addr, 88 unsigned long random_seed) 89 { 90 unsigned long map_size, desc_size, total_slots = 0, target_slot; 91 unsigned long buff_size; 92 efi_status_t status; 93 efi_memory_desc_t *memory_map; 94 int map_offset; 95 struct efi_boot_memmap map; 96 97 map.map = &memory_map; 98 map.map_size = &map_size; 99 map.desc_size = &desc_size; 100 map.desc_ver = NULL; 101 map.key_ptr = NULL; 102 map.buff_size = &buff_size; 103 104 status = efi_get_memory_map(sys_table_arg, &map); 105 if (status != EFI_SUCCESS) 106 return status; 107 108 if (align < EFI_ALLOC_ALIGN) 109 align = EFI_ALLOC_ALIGN; 110 111 /* count the suitable slots in each memory map entry */ 112 for (map_offset = 0; map_offset < map_size; map_offset += desc_size) { 113 efi_memory_desc_t *md = (void *)memory_map + map_offset; 114 unsigned long slots; 115 116 slots = get_entry_num_slots(md, size, ilog2(align)); 117 MD_NUM_SLOTS(md) = slots; 118 total_slots += slots; 119 } 120 121 /* find a random number between 0 and total_slots */ 122 target_slot = (total_slots * (u16)random_seed) >> 16; 123 124 /* 125 * target_slot is now a value in the range [0, total_slots), and so 126 * it corresponds with exactly one of the suitable slots we recorded 127 * when iterating over the memory map the first time around. 128 * 129 * So iterate over the memory map again, subtracting the number of 130 * slots of each entry at each iteration, until we have found the entry 131 * that covers our chosen slot. Use the residual value of target_slot 132 * to calculate the randomly chosen address, and allocate it directly 133 * using EFI_ALLOCATE_ADDRESS. 134 */ 135 for (map_offset = 0; map_offset < map_size; map_offset += desc_size) { 136 efi_memory_desc_t *md = (void *)memory_map + map_offset; 137 efi_physical_addr_t target; 138 unsigned long pages; 139 140 if (target_slot >= MD_NUM_SLOTS(md)) { 141 target_slot -= MD_NUM_SLOTS(md); 142 continue; 143 } 144 145 target = round_up(md->phys_addr, align) + target_slot * align; 146 pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; 147 148 status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS, 149 EFI_LOADER_DATA, pages, &target); 150 if (status == EFI_SUCCESS) 151 *addr = target; 152 break; 153 } 154 155 efi_call_early(free_pool, memory_map); 156 157 return status; 158 } 159 160 efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg) 161 { 162 efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID; 163 efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW; 164 efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID; 165 struct efi_rng_protocol *rng; 166 struct linux_efi_random_seed *seed; 167 efi_status_t status; 168 169 status = efi_call_early(locate_protocol, &rng_proto, NULL, 170 (void **)&rng); 171 if (status != EFI_SUCCESS) 172 return status; 173 174 status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA, 175 sizeof(*seed) + EFI_RANDOM_SEED_SIZE, 176 (void **)&seed); 177 if (status != EFI_SUCCESS) 178 return status; 179 180 status = efi_call_proto(efi_rng_protocol, get_rng, rng, &rng_algo_raw, 181 EFI_RANDOM_SEED_SIZE, seed->bits); 182 183 if (status == EFI_UNSUPPORTED) 184 /* 185 * Use whatever algorithm we have available if the raw algorithm 186 * is not implemented. 187 */ 188 status = efi_call_proto(efi_rng_protocol, get_rng, rng, NULL, 189 EFI_RANDOM_SEED_SIZE, seed->bits); 190 191 if (status != EFI_SUCCESS) 192 goto err_freepool; 193 194 seed->size = EFI_RANDOM_SEED_SIZE; 195 status = efi_call_early(install_configuration_table, &rng_table_guid, 196 seed); 197 if (status != EFI_SUCCESS) 198 goto err_freepool; 199 200 return EFI_SUCCESS; 201 202 err_freepool: 203 efi_call_early(free_pool, seed); 204 return status; 205 } 206