1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <libcflat.h> 3 #include <devicetree.h> 4 #include <memregions.h> 5 6 static struct mem_region __initial_mem_regions[NR_INITIAL_MEM_REGIONS + 1]; 7 static size_t nr_regions = NR_INITIAL_MEM_REGIONS; 8 9 struct mem_region *mem_regions = __initial_mem_regions; 10 11 void memregions_init(struct mem_region regions[], size_t nr) 12 { 13 mem_regions = regions; 14 nr_regions = nr; 15 } 16 17 struct mem_region *memregions_add(struct mem_region *r) 18 { 19 struct mem_region *r_next = mem_regions; 20 int i = 0; 21 22 for (; r_next->end; ++r_next, ++i) 23 ; 24 assert(i < nr_regions); 25 26 *r_next = *r; 27 28 return r_next; 29 } 30 31 struct mem_region *memregions_find(phys_addr_t paddr) 32 { 33 struct mem_region *r; 34 35 for (r = mem_regions; r->end; ++r) 36 if (paddr >= r->start && paddr < r->end) 37 return r; 38 return NULL; 39 } 40 41 uint32_t memregions_get_flags(phys_addr_t paddr) 42 { 43 struct mem_region *r = memregions_find(paddr); 44 45 return r ? r->flags : MR_F_UNKNOWN; 46 } 47 48 void memregions_split(phys_addr_t addr, struct mem_region **r1, struct mem_region **r2) 49 { 50 *r1 = memregions_find(addr); 51 assert(*r1); 52 53 if ((*r1)->start == addr) { 54 *r2 = *r1; 55 *r1 = NULL; 56 return; 57 } 58 59 *r2 = memregions_add(&(struct mem_region){ 60 .start = addr, 61 .end = (*r1)->end, 62 .flags = (*r1)->flags, 63 }); 64 65 (*r1)->end = addr; 66 } 67 68 void memregions_add_dt_regions(size_t max_nr) 69 { 70 struct dt_pbus_reg regs[max_nr]; 71 int nr_regs, i; 72 73 nr_regs = dt_get_memory_params(regs, max_nr); 74 assert(nr_regs > 0); 75 76 for (i = 0; i < nr_regs; ++i) { 77 memregions_add(&(struct mem_region){ 78 .start = regs[i].addr, 79 .end = regs[i].addr + regs[i].size, 80 }); 81 } 82 } 83