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