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