1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <linux/kernel.h> 4 #include <linux/libfdt.h> 5 #include <linux/sizes.h> 6 7 static const void *get_prop(const void *fdt, const char *node_path, 8 const char *property, int minlen) 9 { 10 const void *prop; 11 int offset, len; 12 13 offset = fdt_path_offset(fdt, node_path); 14 if (offset < 0) 15 return NULL; 16 17 prop = fdt_getprop(fdt, offset, property, &len); 18 if (!prop || len < minlen) 19 return NULL; 20 21 return prop; 22 } 23 24 static uint32_t get_cells(const void *fdt, const char *name) 25 { 26 const fdt32_t *prop = get_prop(fdt, "/", name, sizeof(fdt32_t)); 27 28 if (!prop) { 29 /* default */ 30 return 1; 31 } 32 33 return fdt32_ld(prop); 34 } 35 36 static uint64_t get_val(const fdt32_t *cells, uint32_t ncells) 37 { 38 uint64_t r; 39 40 r = fdt32_ld(cells); 41 if (ncells > 1) 42 r = (r << 32) | fdt32_ld(cells + 1); 43 44 return r; 45 } 46 47 /* 48 * Check the start of physical memory 49 * 50 * Traditionally, the start address of physical memory is obtained by masking 51 * the program counter. However, this does require that this address is a 52 * multiple of 128 MiB, precluding booting Linux on platforms where this 53 * requirement is not fulfilled. 54 * Hence validate the calculated address against the memory information in the 55 * DTB, and, if out-of-range, replace it by the real start address. 56 * To preserve backwards compatibility (systems reserving a block of memory 57 * at the start of physical memory, kdump, ...), the traditional method is 58 * always used if it yields a valid address. 59 * 60 * Return value: start address of physical memory to use 61 */ 62 uint32_t fdt_check_mem_start(uint32_t mem_start, const void *fdt) 63 { 64 uint32_t addr_cells, size_cells, base; 65 uint32_t fdt_mem_start = 0xffffffff; 66 const fdt32_t *reg, *endp; 67 uint64_t size, end; 68 const char *type; 69 int offset, len; 70 71 if (!fdt) 72 return mem_start; 73 74 if (fdt_magic(fdt) != FDT_MAGIC) 75 return mem_start; 76 77 /* There may be multiple cells on LPAE platforms */ 78 addr_cells = get_cells(fdt, "#address-cells"); 79 size_cells = get_cells(fdt, "#size-cells"); 80 if (addr_cells > 2 || size_cells > 2) 81 return mem_start; 82 83 /* Walk all memory nodes and regions */ 84 for (offset = fdt_next_node(fdt, -1, NULL); offset >= 0; 85 offset = fdt_next_node(fdt, offset, NULL)) { 86 type = fdt_getprop(fdt, offset, "device_type", NULL); 87 if (!type || strcmp(type, "memory")) 88 continue; 89 90 reg = fdt_getprop(fdt, offset, "linux,usable-memory", &len); 91 if (!reg) 92 reg = fdt_getprop(fdt, offset, "reg", &len); 93 if (!reg) 94 continue; 95 96 for (endp = reg + (len / sizeof(fdt32_t)); 97 endp - reg >= addr_cells + size_cells; 98 reg += addr_cells + size_cells) { 99 size = get_val(reg + addr_cells, size_cells); 100 if (!size) 101 continue; 102 103 if (addr_cells > 1 && fdt32_ld(reg)) { 104 /* Outside 32-bit address space, skipping */ 105 continue; 106 } 107 108 base = fdt32_ld(reg + addr_cells - 1); 109 end = base + size; 110 if (mem_start >= base && mem_start < end) { 111 /* Calculated address is valid, use it */ 112 return mem_start; 113 } 114 115 if (base < fdt_mem_start) 116 fdt_mem_start = base; 117 } 118 } 119 120 if (fdt_mem_start == 0xffffffff) { 121 /* No usable memory found, falling back to default */ 122 return mem_start; 123 } 124 125 /* 126 * The calculated address is not usable. 127 * Use the lowest usable physical memory address from the DTB instead, 128 * and make sure this is a multiple of 2 MiB for phys/virt patching. 129 */ 130 return round_up(fdt_mem_start, SZ_2M); 131 } 132