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