1 // SPDX-License-Identifier: GPL-2.0-only
3 #include <linux/kernel.h>
4 #include <linux/libfdt.h>
5 #include <linux/sizes.h>
7 static const void *get_prop(const void *fdt, const char *node_path,
8 const char *property, int minlen)
13 offset = fdt_path_offset(fdt, node_path);
17 prop = fdt_getprop(fdt, offset, property, &len);
18 if (!prop || len < minlen)
24 static uint32_t get_cells(const void *fdt, const char *name)
26 const fdt32_t *prop = get_prop(fdt, "/", name, sizeof(fdt32_t));
33 return fdt32_ld(prop);
36 static uint64_t get_val(const fdt32_t *cells, uint32_t ncells)
42 r = (r << 32) | fdt32_ld(cells + 1);
48 * Check the start of physical memory
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 * used if it yields a valid address, unless the "linux,usable-memory-range"
59 * property is present.
61 * Return value: start address of physical memory to use
63 uint32_t fdt_check_mem_start(uint32_t mem_start, const void *fdt)
65 uint32_t addr_cells, size_cells, usable_base, base;
66 uint32_t fdt_mem_start = 0xffffffff;
67 const fdt32_t *usable, *reg, *endp;
68 uint64_t size, usable_end, end;
75 if (fdt_magic(fdt) != FDT_MAGIC)
78 /* There may be multiple cells on LPAE platforms */
79 addr_cells = get_cells(fdt, "#address-cells");
80 size_cells = get_cells(fdt, "#size-cells");
81 if (addr_cells > 2 || size_cells > 2)
85 * Usable memory in case of a crash dump kernel
86 * This property describes a limitation: memory within this range is
87 * only valid when also described through another mechanism
89 usable = get_prop(fdt, "/chosen", "linux,usable-memory-range",
90 (addr_cells + size_cells) * sizeof(fdt32_t));
92 size = get_val(usable + addr_cells, size_cells);
96 if (addr_cells > 1 && fdt32_ld(usable)) {
97 /* Outside 32-bit address space */
101 usable_base = fdt32_ld(usable + addr_cells - 1);
102 usable_end = usable_base + size;
105 /* Walk all memory nodes and regions */
106 for (offset = fdt_next_node(fdt, -1, NULL); offset >= 0;
107 offset = fdt_next_node(fdt, offset, NULL)) {
108 type = fdt_getprop(fdt, offset, "device_type", NULL);
109 if (!type || strcmp(type, "memory"))
112 reg = fdt_getprop(fdt, offset, "linux,usable-memory", &len);
114 reg = fdt_getprop(fdt, offset, "reg", &len);
118 for (endp = reg + (len / sizeof(fdt32_t));
119 endp - reg >= addr_cells + size_cells;
120 reg += addr_cells + size_cells) {
121 size = get_val(reg + addr_cells, size_cells);
125 if (addr_cells > 1 && fdt32_ld(reg)) {
126 /* Outside 32-bit address space, skipping */
130 base = fdt32_ld(reg + addr_cells - 1);
134 * Clip to usable range, which takes precedence
137 if (base < usable_base)
140 if (end > usable_end)
145 } else if (mem_start >= base && mem_start < end) {
146 /* Calculated address is valid, use it */
150 if (base < fdt_mem_start)
151 fdt_mem_start = base;
155 if (fdt_mem_start == 0xffffffff) {
156 /* No usable memory found, falling back to default */
161 * The calculated address is not usable, or was overridden by the
162 * "linux,usable-memory-range" property.
163 * Use the lowest usable physical memory address from the DTB instead,
164 * and make sure this is a multiple of 2 MiB for phys/virt patching.
166 return round_up(fdt_mem_start, SZ_2M);