1*5d00995cSAlexander Graf /* 2*5d00995cSAlexander Graf * EFI application memory management 3*5d00995cSAlexander Graf * 4*5d00995cSAlexander Graf * Copyright (c) 2016 Alexander Graf 5*5d00995cSAlexander Graf * 6*5d00995cSAlexander Graf * SPDX-License-Identifier: GPL-2.0+ 7*5d00995cSAlexander Graf */ 8*5d00995cSAlexander Graf 9*5d00995cSAlexander Graf /* #define DEBUG_EFI */ 10*5d00995cSAlexander Graf 11*5d00995cSAlexander Graf #include <common.h> 12*5d00995cSAlexander Graf #include <efi_loader.h> 13*5d00995cSAlexander Graf #include <malloc.h> 14*5d00995cSAlexander Graf #include <asm/global_data.h> 15*5d00995cSAlexander Graf #include <libfdt_env.h> 16*5d00995cSAlexander Graf #include <inttypes.h> 17*5d00995cSAlexander Graf #include <watchdog.h> 18*5d00995cSAlexander Graf 19*5d00995cSAlexander Graf DECLARE_GLOBAL_DATA_PTR; 20*5d00995cSAlexander Graf 21*5d00995cSAlexander Graf struct efi_mem_list { 22*5d00995cSAlexander Graf struct list_head link; 23*5d00995cSAlexander Graf struct efi_mem_desc desc; 24*5d00995cSAlexander Graf }; 25*5d00995cSAlexander Graf 26*5d00995cSAlexander Graf /* This list contains all memory map items */ 27*5d00995cSAlexander Graf LIST_HEAD(efi_mem); 28*5d00995cSAlexander Graf 29*5d00995cSAlexander Graf /* 30*5d00995cSAlexander Graf * Unmaps all memory occupied by the carve_desc region from the 31*5d00995cSAlexander Graf * list entry pointed to by map. 32*5d00995cSAlexander Graf * 33*5d00995cSAlexander Graf * Returns 1 if carving was performed or 0 if the regions don't overlap. 34*5d00995cSAlexander Graf * Returns -1 if it would affect non-RAM regions but overlap_only_ram is set. 35*5d00995cSAlexander Graf * Carving is only guaranteed to complete when all regions return 0. 36*5d00995cSAlexander Graf */ 37*5d00995cSAlexander Graf static int efi_mem_carve_out(struct efi_mem_list *map, 38*5d00995cSAlexander Graf struct efi_mem_desc *carve_desc, 39*5d00995cSAlexander Graf bool overlap_only_ram) 40*5d00995cSAlexander Graf { 41*5d00995cSAlexander Graf struct efi_mem_list *newmap; 42*5d00995cSAlexander Graf struct efi_mem_desc *map_desc = &map->desc; 43*5d00995cSAlexander Graf uint64_t map_start = map_desc->physical_start; 44*5d00995cSAlexander Graf uint64_t map_end = map_start + (map_desc->num_pages << EFI_PAGE_SHIFT); 45*5d00995cSAlexander Graf uint64_t carve_start = carve_desc->physical_start; 46*5d00995cSAlexander Graf uint64_t carve_end = carve_start + 47*5d00995cSAlexander Graf (carve_desc->num_pages << EFI_PAGE_SHIFT); 48*5d00995cSAlexander Graf 49*5d00995cSAlexander Graf /* check whether we're overlapping */ 50*5d00995cSAlexander Graf if ((carve_end <= map_start) || (carve_start >= map_end)) 51*5d00995cSAlexander Graf return 0; 52*5d00995cSAlexander Graf 53*5d00995cSAlexander Graf /* We're overlapping with non-RAM, warn the caller if desired */ 54*5d00995cSAlexander Graf if (overlap_only_ram && (map_desc->type != EFI_CONVENTIONAL_MEMORY)) 55*5d00995cSAlexander Graf return -1; 56*5d00995cSAlexander Graf 57*5d00995cSAlexander Graf /* Sanitize carve_start and carve_end to lie within our bounds */ 58*5d00995cSAlexander Graf carve_start = max(carve_start, map_start); 59*5d00995cSAlexander Graf carve_end = min(carve_end, map_end); 60*5d00995cSAlexander Graf 61*5d00995cSAlexander Graf /* Carving at the beginning of our map? Just move it! */ 62*5d00995cSAlexander Graf if (carve_start == map_start) { 63*5d00995cSAlexander Graf if (map_end == carve_end) { 64*5d00995cSAlexander Graf /* Full overlap, just remove map */ 65*5d00995cSAlexander Graf list_del(&map->link); 66*5d00995cSAlexander Graf } 67*5d00995cSAlexander Graf 68*5d00995cSAlexander Graf map_desc->physical_start = carve_end; 69*5d00995cSAlexander Graf map_desc->num_pages = (map_end - carve_end) >> EFI_PAGE_SHIFT; 70*5d00995cSAlexander Graf return 1; 71*5d00995cSAlexander Graf } 72*5d00995cSAlexander Graf 73*5d00995cSAlexander Graf /* 74*5d00995cSAlexander Graf * Overlapping maps, just split the list map at carve_start, 75*5d00995cSAlexander Graf * it will get moved or removed in the next iteration. 76*5d00995cSAlexander Graf * 77*5d00995cSAlexander Graf * [ map_desc |__carve_start__| newmap ] 78*5d00995cSAlexander Graf */ 79*5d00995cSAlexander Graf 80*5d00995cSAlexander Graf /* Create a new map from [ carve_start ... map_end ] */ 81*5d00995cSAlexander Graf newmap = calloc(1, sizeof(*newmap)); 82*5d00995cSAlexander Graf newmap->desc = map->desc; 83*5d00995cSAlexander Graf newmap->desc.physical_start = carve_start; 84*5d00995cSAlexander Graf newmap->desc.num_pages = (map_end - carve_start) >> EFI_PAGE_SHIFT; 85*5d00995cSAlexander Graf list_add_tail(&newmap->link, &efi_mem); 86*5d00995cSAlexander Graf 87*5d00995cSAlexander Graf /* Shrink the map to [ map_start ... carve_start ] */ 88*5d00995cSAlexander Graf map_desc->num_pages = (carve_start - map_start) >> EFI_PAGE_SHIFT; 89*5d00995cSAlexander Graf 90*5d00995cSAlexander Graf return 1; 91*5d00995cSAlexander Graf } 92*5d00995cSAlexander Graf 93*5d00995cSAlexander Graf uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, 94*5d00995cSAlexander Graf bool overlap_only_ram) 95*5d00995cSAlexander Graf { 96*5d00995cSAlexander Graf struct list_head *lhandle; 97*5d00995cSAlexander Graf struct efi_mem_list *newlist; 98*5d00995cSAlexander Graf bool do_carving; 99*5d00995cSAlexander Graf 100*5d00995cSAlexander Graf if (!pages) 101*5d00995cSAlexander Graf return start; 102*5d00995cSAlexander Graf 103*5d00995cSAlexander Graf newlist = calloc(1, sizeof(*newlist)); 104*5d00995cSAlexander Graf newlist->desc.type = memory_type; 105*5d00995cSAlexander Graf newlist->desc.physical_start = start; 106*5d00995cSAlexander Graf newlist->desc.virtual_start = start; 107*5d00995cSAlexander Graf newlist->desc.num_pages = pages; 108*5d00995cSAlexander Graf 109*5d00995cSAlexander Graf switch (memory_type) { 110*5d00995cSAlexander Graf case EFI_RUNTIME_SERVICES_CODE: 111*5d00995cSAlexander Graf case EFI_RUNTIME_SERVICES_DATA: 112*5d00995cSAlexander Graf newlist->desc.attribute = (1 << EFI_MEMORY_WB_SHIFT) | 113*5d00995cSAlexander Graf (1ULL << EFI_MEMORY_RUNTIME_SHIFT); 114*5d00995cSAlexander Graf break; 115*5d00995cSAlexander Graf case EFI_MMAP_IO: 116*5d00995cSAlexander Graf newlist->desc.attribute = 1ULL << EFI_MEMORY_RUNTIME_SHIFT; 117*5d00995cSAlexander Graf break; 118*5d00995cSAlexander Graf default: 119*5d00995cSAlexander Graf newlist->desc.attribute = 1 << EFI_MEMORY_WB_SHIFT; 120*5d00995cSAlexander Graf break; 121*5d00995cSAlexander Graf } 122*5d00995cSAlexander Graf 123*5d00995cSAlexander Graf /* Add our new map */ 124*5d00995cSAlexander Graf do { 125*5d00995cSAlexander Graf do_carving = false; 126*5d00995cSAlexander Graf list_for_each(lhandle, &efi_mem) { 127*5d00995cSAlexander Graf struct efi_mem_list *lmem; 128*5d00995cSAlexander Graf int r; 129*5d00995cSAlexander Graf 130*5d00995cSAlexander Graf lmem = list_entry(lhandle, struct efi_mem_list, link); 131*5d00995cSAlexander Graf r = efi_mem_carve_out(lmem, &newlist->desc, 132*5d00995cSAlexander Graf overlap_only_ram); 133*5d00995cSAlexander Graf if (r < 0) { 134*5d00995cSAlexander Graf return 0; 135*5d00995cSAlexander Graf } else if (r) { 136*5d00995cSAlexander Graf do_carving = true; 137*5d00995cSAlexander Graf break; 138*5d00995cSAlexander Graf } 139*5d00995cSAlexander Graf } 140*5d00995cSAlexander Graf } while (do_carving); 141*5d00995cSAlexander Graf 142*5d00995cSAlexander Graf /* Add our new map */ 143*5d00995cSAlexander Graf list_add_tail(&newlist->link, &efi_mem); 144*5d00995cSAlexander Graf 145*5d00995cSAlexander Graf return start; 146*5d00995cSAlexander Graf } 147*5d00995cSAlexander Graf 148*5d00995cSAlexander Graf static uint64_t efi_find_free_memory(uint64_t len, uint64_t max_addr) 149*5d00995cSAlexander Graf { 150*5d00995cSAlexander Graf struct list_head *lhandle; 151*5d00995cSAlexander Graf 152*5d00995cSAlexander Graf list_for_each(lhandle, &efi_mem) { 153*5d00995cSAlexander Graf struct efi_mem_list *lmem = list_entry(lhandle, 154*5d00995cSAlexander Graf struct efi_mem_list, link); 155*5d00995cSAlexander Graf struct efi_mem_desc *desc = &lmem->desc; 156*5d00995cSAlexander Graf uint64_t desc_len = desc->num_pages << EFI_PAGE_SHIFT; 157*5d00995cSAlexander Graf uint64_t desc_end = desc->physical_start + desc_len; 158*5d00995cSAlexander Graf uint64_t curmax = min(max_addr, desc_end); 159*5d00995cSAlexander Graf uint64_t ret = curmax - len; 160*5d00995cSAlexander Graf 161*5d00995cSAlexander Graf /* We only take memory from free RAM */ 162*5d00995cSAlexander Graf if (desc->type != EFI_CONVENTIONAL_MEMORY) 163*5d00995cSAlexander Graf continue; 164*5d00995cSAlexander Graf 165*5d00995cSAlexander Graf /* Out of bounds for max_addr */ 166*5d00995cSAlexander Graf if ((ret + len) > max_addr) 167*5d00995cSAlexander Graf continue; 168*5d00995cSAlexander Graf 169*5d00995cSAlexander Graf /* Out of bounds for upper map limit */ 170*5d00995cSAlexander Graf if ((ret + len) > desc_end) 171*5d00995cSAlexander Graf continue; 172*5d00995cSAlexander Graf 173*5d00995cSAlexander Graf /* Out of bounds for lower map limit */ 174*5d00995cSAlexander Graf if (ret < desc->physical_start) 175*5d00995cSAlexander Graf continue; 176*5d00995cSAlexander Graf 177*5d00995cSAlexander Graf /* Return the highest address in this map within bounds */ 178*5d00995cSAlexander Graf return ret; 179*5d00995cSAlexander Graf } 180*5d00995cSAlexander Graf 181*5d00995cSAlexander Graf return 0; 182*5d00995cSAlexander Graf } 183*5d00995cSAlexander Graf 184*5d00995cSAlexander Graf efi_status_t efi_allocate_pages(int type, int memory_type, 185*5d00995cSAlexander Graf unsigned long pages, uint64_t *memory) 186*5d00995cSAlexander Graf { 187*5d00995cSAlexander Graf u64 len = pages << EFI_PAGE_SHIFT; 188*5d00995cSAlexander Graf efi_status_t r = EFI_SUCCESS; 189*5d00995cSAlexander Graf uint64_t addr; 190*5d00995cSAlexander Graf 191*5d00995cSAlexander Graf switch (type) { 192*5d00995cSAlexander Graf case 0: 193*5d00995cSAlexander Graf /* Any page */ 194*5d00995cSAlexander Graf addr = efi_find_free_memory(len, gd->ram_top); 195*5d00995cSAlexander Graf if (!addr) { 196*5d00995cSAlexander Graf r = EFI_NOT_FOUND; 197*5d00995cSAlexander Graf break; 198*5d00995cSAlexander Graf } 199*5d00995cSAlexander Graf break; 200*5d00995cSAlexander Graf case 1: 201*5d00995cSAlexander Graf /* Max address */ 202*5d00995cSAlexander Graf addr = efi_find_free_memory(len, *memory); 203*5d00995cSAlexander Graf if (!addr) { 204*5d00995cSAlexander Graf r = EFI_NOT_FOUND; 205*5d00995cSAlexander Graf break; 206*5d00995cSAlexander Graf } 207*5d00995cSAlexander Graf break; 208*5d00995cSAlexander Graf case 2: 209*5d00995cSAlexander Graf /* Exact address, reserve it. The addr is already in *memory. */ 210*5d00995cSAlexander Graf addr = *memory; 211*5d00995cSAlexander Graf break; 212*5d00995cSAlexander Graf default: 213*5d00995cSAlexander Graf /* UEFI doesn't specify other allocation types */ 214*5d00995cSAlexander Graf r = EFI_INVALID_PARAMETER; 215*5d00995cSAlexander Graf break; 216*5d00995cSAlexander Graf } 217*5d00995cSAlexander Graf 218*5d00995cSAlexander Graf if (r == EFI_SUCCESS) { 219*5d00995cSAlexander Graf uint64_t ret; 220*5d00995cSAlexander Graf 221*5d00995cSAlexander Graf /* Reserve that map in our memory maps */ 222*5d00995cSAlexander Graf ret = efi_add_memory_map(addr, pages, memory_type, true); 223*5d00995cSAlexander Graf if (ret == addr) { 224*5d00995cSAlexander Graf *memory = addr; 225*5d00995cSAlexander Graf } else { 226*5d00995cSAlexander Graf /* Map would overlap, bail out */ 227*5d00995cSAlexander Graf r = EFI_OUT_OF_RESOURCES; 228*5d00995cSAlexander Graf } 229*5d00995cSAlexander Graf } 230*5d00995cSAlexander Graf 231*5d00995cSAlexander Graf return r; 232*5d00995cSAlexander Graf } 233*5d00995cSAlexander Graf 234*5d00995cSAlexander Graf void *efi_alloc(uint64_t len, int memory_type) 235*5d00995cSAlexander Graf { 236*5d00995cSAlexander Graf uint64_t ret = 0; 237*5d00995cSAlexander Graf uint64_t pages = (len + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; 238*5d00995cSAlexander Graf efi_status_t r; 239*5d00995cSAlexander Graf 240*5d00995cSAlexander Graf r = efi_allocate_pages(0, memory_type, pages, &ret); 241*5d00995cSAlexander Graf if (r == EFI_SUCCESS) 242*5d00995cSAlexander Graf return (void*)(uintptr_t)ret; 243*5d00995cSAlexander Graf 244*5d00995cSAlexander Graf return NULL; 245*5d00995cSAlexander Graf } 246*5d00995cSAlexander Graf 247*5d00995cSAlexander Graf efi_status_t efi_free_pages(uint64_t memory, unsigned long pages) 248*5d00995cSAlexander Graf { 249*5d00995cSAlexander Graf /* We don't free, let's cross our fingers we have plenty RAM */ 250*5d00995cSAlexander Graf return EFI_SUCCESS; 251*5d00995cSAlexander Graf } 252*5d00995cSAlexander Graf 253*5d00995cSAlexander Graf efi_status_t efi_get_memory_map(unsigned long *memory_map_size, 254*5d00995cSAlexander Graf struct efi_mem_desc *memory_map, 255*5d00995cSAlexander Graf unsigned long *map_key, 256*5d00995cSAlexander Graf unsigned long *descriptor_size, 257*5d00995cSAlexander Graf uint32_t *descriptor_version) 258*5d00995cSAlexander Graf { 259*5d00995cSAlexander Graf ulong map_size = 0; 260*5d00995cSAlexander Graf struct list_head *lhandle; 261*5d00995cSAlexander Graf 262*5d00995cSAlexander Graf list_for_each(lhandle, &efi_mem) 263*5d00995cSAlexander Graf map_size += sizeof(struct efi_mem_desc); 264*5d00995cSAlexander Graf 265*5d00995cSAlexander Graf *memory_map_size = map_size; 266*5d00995cSAlexander Graf 267*5d00995cSAlexander Graf if (descriptor_size) 268*5d00995cSAlexander Graf *descriptor_size = sizeof(struct efi_mem_desc); 269*5d00995cSAlexander Graf 270*5d00995cSAlexander Graf if (*memory_map_size < map_size) 271*5d00995cSAlexander Graf return EFI_BUFFER_TOO_SMALL; 272*5d00995cSAlexander Graf 273*5d00995cSAlexander Graf /* Copy list into array */ 274*5d00995cSAlexander Graf if (memory_map) { 275*5d00995cSAlexander Graf list_for_each(lhandle, &efi_mem) { 276*5d00995cSAlexander Graf struct efi_mem_list *lmem; 277*5d00995cSAlexander Graf 278*5d00995cSAlexander Graf lmem = list_entry(lhandle, struct efi_mem_list, link); 279*5d00995cSAlexander Graf *memory_map = lmem->desc; 280*5d00995cSAlexander Graf memory_map++; 281*5d00995cSAlexander Graf } 282*5d00995cSAlexander Graf } 283*5d00995cSAlexander Graf 284*5d00995cSAlexander Graf return EFI_SUCCESS; 285*5d00995cSAlexander Graf } 286*5d00995cSAlexander Graf 287*5d00995cSAlexander Graf int efi_memory_init(void) 288*5d00995cSAlexander Graf { 289*5d00995cSAlexander Graf uint64_t runtime_start, runtime_end, runtime_pages; 290*5d00995cSAlexander Graf uint64_t uboot_start, uboot_pages; 291*5d00995cSAlexander Graf uint64_t uboot_stack_size = 16 * 1024 * 1024; 292*5d00995cSAlexander Graf int i; 293*5d00995cSAlexander Graf 294*5d00995cSAlexander Graf /* Add RAM */ 295*5d00995cSAlexander Graf for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 296*5d00995cSAlexander Graf u64 ram_start = gd->bd->bi_dram[i].start; 297*5d00995cSAlexander Graf u64 ram_size = gd->bd->bi_dram[i].size; 298*5d00995cSAlexander Graf u64 start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK; 299*5d00995cSAlexander Graf u64 pages = (ram_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; 300*5d00995cSAlexander Graf 301*5d00995cSAlexander Graf efi_add_memory_map(start, pages, EFI_CONVENTIONAL_MEMORY, 302*5d00995cSAlexander Graf false); 303*5d00995cSAlexander Graf } 304*5d00995cSAlexander Graf 305*5d00995cSAlexander Graf /* Add U-Boot */ 306*5d00995cSAlexander Graf uboot_start = (gd->start_addr_sp - uboot_stack_size) & ~EFI_PAGE_MASK; 307*5d00995cSAlexander Graf uboot_pages = (gd->ram_top - uboot_start) >> EFI_PAGE_SHIFT; 308*5d00995cSAlexander Graf efi_add_memory_map(uboot_start, uboot_pages, EFI_LOADER_DATA, false); 309*5d00995cSAlexander Graf 310*5d00995cSAlexander Graf /* Add Runtime Services */ 311*5d00995cSAlexander Graf runtime_start = (ulong)&__efi_runtime_start & ~EFI_PAGE_MASK; 312*5d00995cSAlexander Graf runtime_end = (ulong)&__efi_runtime_stop; 313*5d00995cSAlexander Graf runtime_end = (runtime_end + EFI_PAGE_MASK) & ~EFI_PAGE_MASK; 314*5d00995cSAlexander Graf runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT; 315*5d00995cSAlexander Graf efi_add_memory_map(runtime_start, runtime_pages, 316*5d00995cSAlexander Graf EFI_RUNTIME_SERVICES_CODE, false); 317*5d00995cSAlexander Graf 318*5d00995cSAlexander Graf return 0; 319*5d00995cSAlexander Graf } 320