xref: /openbmc/linux/drivers/of/fdt.c (revision 606ad42a)
1e169cfbeSGrant Likely /*
2e169cfbeSGrant Likely  * Functions for working with the Flattened Device Tree data format
3e169cfbeSGrant Likely  *
4e169cfbeSGrant Likely  * Copyright 2009 Benjamin Herrenschmidt, IBM Corp
5e169cfbeSGrant Likely  * benh@kernel.crashing.org
6e169cfbeSGrant Likely  *
7e169cfbeSGrant Likely  * This program is free software; you can redistribute it and/or
8e169cfbeSGrant Likely  * modify it under the terms of the GNU General Public License
9e169cfbeSGrant Likely  * version 2 as published by the Free Software Foundation.
10e169cfbeSGrant Likely  */
11e169cfbeSGrant Likely 
12606ad42aSRob Herring #define pr_fmt(fmt)	"OF: fdt:" fmt
13606ad42aSRob Herring 
1408d53aa5SArd Biesheuvel #include <linux/crc32.h>
1541f88009SGrant Likely #include <linux/kernel.h>
16f7b3a835SGrant Likely #include <linux/initrd.h>
17a1727da5SGrant Likely #include <linux/memblock.h>
18f8062386SGuenter Roeck #include <linux/mutex.h>
19e169cfbeSGrant Likely #include <linux/of.h>
20e169cfbeSGrant Likely #include <linux/of_fdt.h>
213f0c8206SMarek Szyprowski #include <linux/of_reserved_mem.h>
22e8d9d1f5SMarek Szyprowski #include <linux/sizes.h>
234ef7b373SJeremy Kerr #include <linux/string.h>
244ef7b373SJeremy Kerr #include <linux/errno.h>
25fe140423SStephen Neuendorffer #include <linux/slab.h>
26e6a6928cSRob Herring #include <linux/libfdt.h>
27b0a6fb36SRob Herring #include <linux/debugfs.h>
28fb11ffe7SRob Herring #include <linux/serial_core.h>
2908d53aa5SArd Biesheuvel #include <linux/sysfs.h>
3051975db0SGrant Likely 
31c89810acSFabio Estevam #include <asm/setup.h>  /* for COMMAND_LINE_SIZE */
324ef7b373SJeremy Kerr #include <asm/page.h>
334ef7b373SJeremy Kerr 
34704033ceSLaura Abbott /*
35704033ceSLaura Abbott  * of_fdt_limit_memory - limit the number of regions in the /memory node
36704033ceSLaura Abbott  * @limit: maximum entries
37704033ceSLaura Abbott  *
38704033ceSLaura Abbott  * Adjust the flattened device tree to have at most 'limit' number of
39704033ceSLaura Abbott  * memory entries in the /memory node. This function may be called
40704033ceSLaura Abbott  * any time after initial_boot_param is set.
41704033ceSLaura Abbott  */
42704033ceSLaura Abbott void of_fdt_limit_memory(int limit)
43704033ceSLaura Abbott {
44704033ceSLaura Abbott 	int memory;
45704033ceSLaura Abbott 	int len;
46704033ceSLaura Abbott 	const void *val;
47704033ceSLaura Abbott 	int nr_address_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
48704033ceSLaura Abbott 	int nr_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
49704033ceSLaura Abbott 	const uint32_t *addr_prop;
50704033ceSLaura Abbott 	const uint32_t *size_prop;
51704033ceSLaura Abbott 	int root_offset;
52704033ceSLaura Abbott 	int cell_size;
53704033ceSLaura Abbott 
54704033ceSLaura Abbott 	root_offset = fdt_path_offset(initial_boot_params, "/");
55704033ceSLaura Abbott 	if (root_offset < 0)
56704033ceSLaura Abbott 		return;
57704033ceSLaura Abbott 
58704033ceSLaura Abbott 	addr_prop = fdt_getprop(initial_boot_params, root_offset,
59704033ceSLaura Abbott 				"#address-cells", NULL);
60704033ceSLaura Abbott 	if (addr_prop)
61704033ceSLaura Abbott 		nr_address_cells = fdt32_to_cpu(*addr_prop);
62704033ceSLaura Abbott 
63704033ceSLaura Abbott 	size_prop = fdt_getprop(initial_boot_params, root_offset,
64704033ceSLaura Abbott 				"#size-cells", NULL);
65704033ceSLaura Abbott 	if (size_prop)
66704033ceSLaura Abbott 		nr_size_cells = fdt32_to_cpu(*size_prop);
67704033ceSLaura Abbott 
68704033ceSLaura Abbott 	cell_size = sizeof(uint32_t)*(nr_address_cells + nr_size_cells);
69704033ceSLaura Abbott 
70704033ceSLaura Abbott 	memory = fdt_path_offset(initial_boot_params, "/memory");
71704033ceSLaura Abbott 	if (memory > 0) {
72704033ceSLaura Abbott 		val = fdt_getprop(initial_boot_params, memory, "reg", &len);
73704033ceSLaura Abbott 		if (len > limit*cell_size) {
74704033ceSLaura Abbott 			len = limit*cell_size;
75704033ceSLaura Abbott 			pr_debug("Limiting number of entries to %d\n", limit);
76704033ceSLaura Abbott 			fdt_setprop(initial_boot_params, memory, "reg", val,
77704033ceSLaura Abbott 					len);
78704033ceSLaura Abbott 		}
79704033ceSLaura Abbott 	}
80704033ceSLaura Abbott }
81704033ceSLaura Abbott 
829706a36eSStephen Neuendorffer /**
839706a36eSStephen Neuendorffer  * of_fdt_is_compatible - Return true if given node from the given blob has
849706a36eSStephen Neuendorffer  * compat in its compatible list
859706a36eSStephen Neuendorffer  * @blob: A device tree blob
869706a36eSStephen Neuendorffer  * @node: node to test
879706a36eSStephen Neuendorffer  * @compat: compatible string to compare with compatible list.
88a4f740cfSGrant Likely  *
89a4f740cfSGrant Likely  * On match, returns a non-zero value with smaller values returned for more
90a4f740cfSGrant Likely  * specific compatible values.
919706a36eSStephen Neuendorffer  */
92c972de14SRob Herring int of_fdt_is_compatible(const void *blob,
939706a36eSStephen Neuendorffer 		      unsigned long node, const char *compat)
949706a36eSStephen Neuendorffer {
959706a36eSStephen Neuendorffer 	const char *cp;
969d0c4dfeSRob Herring 	int cplen;
979d0c4dfeSRob Herring 	unsigned long l, score = 0;
989706a36eSStephen Neuendorffer 
99e6a6928cSRob Herring 	cp = fdt_getprop(blob, node, "compatible", &cplen);
1009706a36eSStephen Neuendorffer 	if (cp == NULL)
1019706a36eSStephen Neuendorffer 		return 0;
1029706a36eSStephen Neuendorffer 	while (cplen > 0) {
103a4f740cfSGrant Likely 		score++;
1049706a36eSStephen Neuendorffer 		if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
105a4f740cfSGrant Likely 			return score;
1069706a36eSStephen Neuendorffer 		l = strlen(cp) + 1;
1079706a36eSStephen Neuendorffer 		cp += l;
1089706a36eSStephen Neuendorffer 		cplen -= l;
1099706a36eSStephen Neuendorffer 	}
1109706a36eSStephen Neuendorffer 
1119706a36eSStephen Neuendorffer 	return 0;
1129706a36eSStephen Neuendorffer }
1139706a36eSStephen Neuendorffer 
114a4f740cfSGrant Likely /**
115cc783786SKevin Cernekee  * of_fdt_is_big_endian - Return true if given node needs BE MMIO accesses
116cc783786SKevin Cernekee  * @blob: A device tree blob
117cc783786SKevin Cernekee  * @node: node to test
118cc783786SKevin Cernekee  *
119cc783786SKevin Cernekee  * Returns true if the node has a "big-endian" property, or if the kernel
120cc783786SKevin Cernekee  * was compiled for BE *and* the node has a "native-endian" property.
121cc783786SKevin Cernekee  * Returns false otherwise.
122cc783786SKevin Cernekee  */
123cc783786SKevin Cernekee bool of_fdt_is_big_endian(const void *blob, unsigned long node)
124cc783786SKevin Cernekee {
125cc783786SKevin Cernekee 	if (fdt_getprop(blob, node, "big-endian", NULL))
126cc783786SKevin Cernekee 		return true;
127cc783786SKevin Cernekee 	if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
128cc783786SKevin Cernekee 	    fdt_getprop(blob, node, "native-endian", NULL))
129cc783786SKevin Cernekee 		return true;
130cc783786SKevin Cernekee 	return false;
131cc783786SKevin Cernekee }
132cc783786SKevin Cernekee 
133cc783786SKevin Cernekee /**
134a4f740cfSGrant Likely  * of_fdt_match - Return true if node matches a list of compatible values
135a4f740cfSGrant Likely  */
136c972de14SRob Herring int of_fdt_match(const void *blob, unsigned long node,
1377b482c83SUwe Kleine-König                  const char *const *compat)
138a4f740cfSGrant Likely {
139a4f740cfSGrant Likely 	unsigned int tmp, score = 0;
140a4f740cfSGrant Likely 
141a4f740cfSGrant Likely 	if (!compat)
142a4f740cfSGrant Likely 		return 0;
143a4f740cfSGrant Likely 
144a4f740cfSGrant Likely 	while (*compat) {
145a4f740cfSGrant Likely 		tmp = of_fdt_is_compatible(blob, node, *compat);
146a4f740cfSGrant Likely 		if (tmp && (score == 0 || (tmp < score)))
147a4f740cfSGrant Likely 			score = tmp;
148a4f740cfSGrant Likely 		compat++;
149a4f740cfSGrant Likely 	}
150a4f740cfSGrant Likely 
151a4f740cfSGrant Likely 	return score;
152a4f740cfSGrant Likely }
153a4f740cfSGrant Likely 
15444856819SGrant Likely static void *unflatten_dt_alloc(void **mem, unsigned long size,
155bbd33931SGrant Likely 				       unsigned long align)
156bbd33931SGrant Likely {
157bbd33931SGrant Likely 	void *res;
158bbd33931SGrant Likely 
15944856819SGrant Likely 	*mem = PTR_ALIGN(*mem, align);
16044856819SGrant Likely 	res = *mem;
161bbd33931SGrant Likely 	*mem += size;
162bbd33931SGrant Likely 
163bbd33931SGrant Likely 	return res;
164bbd33931SGrant Likely }
165bbd33931SGrant Likely 
166dfbd4c6eSGavin Shan static void populate_properties(const void *blob,
167dfbd4c6eSGavin Shan 				int offset,
168dfbd4c6eSGavin Shan 				void **mem,
169dfbd4c6eSGavin Shan 				struct device_node *np,
170dfbd4c6eSGavin Shan 				const char *nodename,
1715063e25aSGrant Likely 				bool dryrun)
172bbd33931SGrant Likely {
173dfbd4c6eSGavin Shan 	struct property *pp, **pprev = NULL;
174dfbd4c6eSGavin Shan 	int cur;
175dfbd4c6eSGavin Shan 	bool has_name = false;
176dfbd4c6eSGavin Shan 
177dfbd4c6eSGavin Shan 	pprev = &np->properties;
178dfbd4c6eSGavin Shan 	for (cur = fdt_first_property_offset(blob, offset);
179dfbd4c6eSGavin Shan 	     cur >= 0;
180dfbd4c6eSGavin Shan 	     cur = fdt_next_property_offset(blob, cur)) {
181dfbd4c6eSGavin Shan 		const __be32 *val;
182dfbd4c6eSGavin Shan 		const char *pname;
183dfbd4c6eSGavin Shan 		u32 sz;
184dfbd4c6eSGavin Shan 
185dfbd4c6eSGavin Shan 		val = fdt_getprop_by_offset(blob, cur, &pname, &sz);
186dfbd4c6eSGavin Shan 		if (!val) {
187606ad42aSRob Herring 			pr_warn("Cannot locate property at 0x%x\n", cur);
188dfbd4c6eSGavin Shan 			continue;
189dfbd4c6eSGavin Shan 		}
190dfbd4c6eSGavin Shan 
191dfbd4c6eSGavin Shan 		if (!pname) {
192606ad42aSRob Herring 			pr_warn("Cannot find property name at 0x%x\n", cur);
193dfbd4c6eSGavin Shan 			continue;
194dfbd4c6eSGavin Shan 		}
195dfbd4c6eSGavin Shan 
196dfbd4c6eSGavin Shan 		if (!strcmp(pname, "name"))
197dfbd4c6eSGavin Shan 			has_name = true;
198dfbd4c6eSGavin Shan 
199dfbd4c6eSGavin Shan 		pp = unflatten_dt_alloc(mem, sizeof(struct property),
200dfbd4c6eSGavin Shan 					__alignof__(struct property));
201dfbd4c6eSGavin Shan 		if (dryrun)
202dfbd4c6eSGavin Shan 			continue;
203dfbd4c6eSGavin Shan 
204dfbd4c6eSGavin Shan 		/* We accept flattened tree phandles either in
205dfbd4c6eSGavin Shan 		 * ePAPR-style "phandle" properties, or the
206dfbd4c6eSGavin Shan 		 * legacy "linux,phandle" properties.  If both
207dfbd4c6eSGavin Shan 		 * appear and have different values, things
208dfbd4c6eSGavin Shan 		 * will get weird. Don't do that.
209dfbd4c6eSGavin Shan 		 */
210dfbd4c6eSGavin Shan 		if (!strcmp(pname, "phandle") ||
211dfbd4c6eSGavin Shan 		    !strcmp(pname, "linux,phandle")) {
212dfbd4c6eSGavin Shan 			if (!np->phandle)
213dfbd4c6eSGavin Shan 				np->phandle = be32_to_cpup(val);
214dfbd4c6eSGavin Shan 		}
215dfbd4c6eSGavin Shan 
216dfbd4c6eSGavin Shan 		/* And we process the "ibm,phandle" property
217dfbd4c6eSGavin Shan 		 * used in pSeries dynamic device tree
218dfbd4c6eSGavin Shan 		 * stuff
219dfbd4c6eSGavin Shan 		 */
220dfbd4c6eSGavin Shan 		if (!strcmp(pname, "ibm,phandle"))
221dfbd4c6eSGavin Shan 			np->phandle = be32_to_cpup(val);
222dfbd4c6eSGavin Shan 
223dfbd4c6eSGavin Shan 		pp->name   = (char *)pname;
224dfbd4c6eSGavin Shan 		pp->length = sz;
225dfbd4c6eSGavin Shan 		pp->value  = (__be32 *)val;
226dfbd4c6eSGavin Shan 		*pprev     = pp;
227dfbd4c6eSGavin Shan 		pprev      = &pp->next;
228dfbd4c6eSGavin Shan 	}
229dfbd4c6eSGavin Shan 
230dfbd4c6eSGavin Shan 	/* With version 0x10 we may not have the name property,
231dfbd4c6eSGavin Shan 	 * recreate it here from the unit name if absent
232dfbd4c6eSGavin Shan 	 */
233dfbd4c6eSGavin Shan 	if (!has_name) {
234dfbd4c6eSGavin Shan 		const char *p = nodename, *ps = p, *pa = NULL;
235dfbd4c6eSGavin Shan 		int len;
236dfbd4c6eSGavin Shan 
237dfbd4c6eSGavin Shan 		while (*p) {
238dfbd4c6eSGavin Shan 			if ((*p) == '@')
239dfbd4c6eSGavin Shan 				pa = p;
240dfbd4c6eSGavin Shan 			else if ((*p) == '/')
241dfbd4c6eSGavin Shan 				ps = p + 1;
242dfbd4c6eSGavin Shan 			p++;
243dfbd4c6eSGavin Shan 		}
244dfbd4c6eSGavin Shan 
245dfbd4c6eSGavin Shan 		if (pa < ps)
246dfbd4c6eSGavin Shan 			pa = p;
247dfbd4c6eSGavin Shan 		len = (pa - ps) + 1;
248dfbd4c6eSGavin Shan 		pp = unflatten_dt_alloc(mem, sizeof(struct property) + len,
249dfbd4c6eSGavin Shan 					__alignof__(struct property));
250dfbd4c6eSGavin Shan 		if (!dryrun) {
251dfbd4c6eSGavin Shan 			pp->name   = "name";
252dfbd4c6eSGavin Shan 			pp->length = len;
253dfbd4c6eSGavin Shan 			pp->value  = pp + 1;
254dfbd4c6eSGavin Shan 			*pprev     = pp;
255dfbd4c6eSGavin Shan 			pprev      = &pp->next;
256dfbd4c6eSGavin Shan 			memcpy(pp->value, ps, len - 1);
257dfbd4c6eSGavin Shan 			((char *)pp->value)[len - 1] = 0;
258dfbd4c6eSGavin Shan 			pr_debug("fixed up name for %s -> %s\n",
259dfbd4c6eSGavin Shan 				 nodename, (char *)pp->value);
260dfbd4c6eSGavin Shan 		}
261dfbd4c6eSGavin Shan 	}
262dfbd4c6eSGavin Shan 
263dfbd4c6eSGavin Shan 	if (!dryrun)
264dfbd4c6eSGavin Shan 		*pprev = NULL;
265dfbd4c6eSGavin Shan }
266dfbd4c6eSGavin Shan 
267dddc33e5SGavin Shan static unsigned int populate_node(const void *blob,
268dfbd4c6eSGavin Shan 				  int offset,
269dfbd4c6eSGavin Shan 				  void **mem,
270dfbd4c6eSGavin Shan 				  struct device_node *dad,
271dddc33e5SGavin Shan 				  unsigned int fpsize,
272dfbd4c6eSGavin Shan 				  struct device_node **pnp,
273dfbd4c6eSGavin Shan 				  bool dryrun)
274dfbd4c6eSGavin Shan {
275bbd33931SGrant Likely 	struct device_node *np;
276e6a6928cSRob Herring 	const char *pathp;
277bbd33931SGrant Likely 	unsigned int l, allocl;
278bbd33931SGrant Likely 	int new_format = 0;
279bbd33931SGrant Likely 
280dfbd4c6eSGavin Shan 	pathp = fdt_get_name(blob, offset, &l);
281dfbd4c6eSGavin Shan 	if (!pathp) {
282dfbd4c6eSGavin Shan 		*pnp = NULL;
283dfbd4c6eSGavin Shan 		return 0;
284dfbd4c6eSGavin Shan 	}
285e6a6928cSRob Herring 
28605f4647bSRicky Liang 	allocl = ++l;
287bbd33931SGrant Likely 
288bbd33931SGrant Likely 	/* version 0x10 has a more compact unit name here instead of the full
289bbd33931SGrant Likely 	 * path. we accumulate the full path size using "fpsize", we'll rebuild
290bbd33931SGrant Likely 	 * it later. We detect this because the first character of the name is
291bbd33931SGrant Likely 	 * not '/'.
292bbd33931SGrant Likely 	 */
293bbd33931SGrant Likely 	if ((*pathp) != '/') {
294bbd33931SGrant Likely 		new_format = 1;
295bbd33931SGrant Likely 		if (fpsize == 0) {
296bbd33931SGrant Likely 			/* root node: special case. fpsize accounts for path
297bbd33931SGrant Likely 			 * plus terminating zero. root node only has '/', so
298bbd33931SGrant Likely 			 * fpsize should be 2, but we want to avoid the first
299bbd33931SGrant Likely 			 * level nodes to have two '/' so we use fpsize 1 here
300bbd33931SGrant Likely 			 */
301bbd33931SGrant Likely 			fpsize = 1;
302bbd33931SGrant Likely 			allocl = 2;
3030fca5deaSCatalin Marinas 			l = 1;
304e6a6928cSRob Herring 			pathp = "";
305bbd33931SGrant Likely 		} else {
306bbd33931SGrant Likely 			/* account for '/' and path size minus terminal 0
307bbd33931SGrant Likely 			 * already in 'l'
308bbd33931SGrant Likely 			 */
309bbd33931SGrant Likely 			fpsize += l;
310bbd33931SGrant Likely 			allocl = fpsize;
311bbd33931SGrant Likely 		}
312bbd33931SGrant Likely 	}
313bbd33931SGrant Likely 
314dfbd4c6eSGavin Shan 	np = unflatten_dt_alloc(mem, sizeof(struct device_node) + allocl,
315bbd33931SGrant Likely 				__alignof__(struct device_node));
3165063e25aSGrant Likely 	if (!dryrun) {
317c22618a1SGrant Likely 		char *fn;
3180829f6d1SPantelis Antoniou 		of_node_init(np);
319c22618a1SGrant Likely 		np->full_name = fn = ((char *)np) + sizeof(*np);
320bbd33931SGrant Likely 		if (new_format) {
321bbd33931SGrant Likely 			/* rebuild full path for new format */
322bbd33931SGrant Likely 			if (dad && dad->parent) {
323bbd33931SGrant Likely 				strcpy(fn, dad->full_name);
324bbd33931SGrant Likely #ifdef DEBUG
325bbd33931SGrant Likely 				if ((strlen(fn) + l + 1) != allocl) {
326bbd33931SGrant Likely 					pr_debug("%s: p: %d, l: %d, a: %d\n",
327bbd33931SGrant Likely 						pathp, (int)strlen(fn),
328bbd33931SGrant Likely 						l, allocl);
329bbd33931SGrant Likely 				}
330bbd33931SGrant Likely #endif
331bbd33931SGrant Likely 				fn += strlen(fn);
332bbd33931SGrant Likely 			}
333bbd33931SGrant Likely 			*(fn++) = '/';
334c22618a1SGrant Likely 		}
335bbd33931SGrant Likely 		memcpy(fn, pathp, l);
336c22618a1SGrant Likely 
337bbd33931SGrant Likely 		if (dad != NULL) {
338bbd33931SGrant Likely 			np->parent = dad;
33970161ff3SGrant Likely 			np->sibling = dad->child;
340bbd33931SGrant Likely 			dad->child = np;
341bbd33931SGrant Likely 		}
342bbd33931SGrant Likely 	}
343bbd33931SGrant Likely 
344dfbd4c6eSGavin Shan 	populate_properties(blob, offset, mem, np, pathp, dryrun);
3455063e25aSGrant Likely 	if (!dryrun) {
346bbd33931SGrant Likely 		np->name = of_get_property(np, "name", NULL);
347bbd33931SGrant Likely 		np->type = of_get_property(np, "device_type", NULL);
348bbd33931SGrant Likely 
349bbd33931SGrant Likely 		if (!np->name)
350bbd33931SGrant Likely 			np->name = "<NULL>";
351bbd33931SGrant Likely 		if (!np->type)
352bbd33931SGrant Likely 			np->type = "<NULL>";
353bbd33931SGrant Likely 	}
354e6a6928cSRob Herring 
355dfbd4c6eSGavin Shan 	*pnp = np;
356dfbd4c6eSGavin Shan 	return fpsize;
357dfbd4c6eSGavin Shan }
358dfbd4c6eSGavin Shan 
35950800082SGavin Shan static void reverse_nodes(struct device_node *parent)
36050800082SGavin Shan {
36150800082SGavin Shan 	struct device_node *child, *next;
36250800082SGavin Shan 
36350800082SGavin Shan 	/* In-depth first */
36450800082SGavin Shan 	child = parent->child;
36550800082SGavin Shan 	while (child) {
36650800082SGavin Shan 		reverse_nodes(child);
36750800082SGavin Shan 
36850800082SGavin Shan 		child = child->sibling;
36950800082SGavin Shan 	}
37050800082SGavin Shan 
37150800082SGavin Shan 	/* Reverse the nodes in the child list */
37250800082SGavin Shan 	child = parent->child;
37350800082SGavin Shan 	parent->child = NULL;
37450800082SGavin Shan 	while (child) {
37550800082SGavin Shan 		next = child->sibling;
37650800082SGavin Shan 
37750800082SGavin Shan 		child->sibling = parent->child;
37850800082SGavin Shan 		parent->child = child;
37950800082SGavin Shan 		child = next;
38050800082SGavin Shan 	}
38150800082SGavin Shan }
38250800082SGavin Shan 
383dfbd4c6eSGavin Shan /**
384947c82cbSGavin Shan  * unflatten_dt_nodes - Alloc and populate a device_node from the flat tree
385dfbd4c6eSGavin Shan  * @blob: The parent device tree blob
386dfbd4c6eSGavin Shan  * @mem: Memory chunk to use for allocating device nodes and properties
387dfbd4c6eSGavin Shan  * @dad: Parent struct device_node
388dfbd4c6eSGavin Shan  * @nodepp: The device_node tree created by the call
38950800082SGavin Shan  *
39050800082SGavin Shan  * It returns the size of unflattened device tree or error code
391dfbd4c6eSGavin Shan  */
392947c82cbSGavin Shan static int unflatten_dt_nodes(const void *blob,
393dfbd4c6eSGavin Shan 			      void *mem,
394dfbd4c6eSGavin Shan 			      struct device_node *dad,
39550800082SGavin Shan 			      struct device_node **nodepp)
396dfbd4c6eSGavin Shan {
39750800082SGavin Shan 	struct device_node *root;
3988c237cd0SGavin Shan 	int offset = 0, depth = 0, initial_depth = 0;
39950800082SGavin Shan #define FDT_MAX_DEPTH	64
400dddc33e5SGavin Shan 	unsigned int fpsizes[FDT_MAX_DEPTH];
40150800082SGavin Shan 	struct device_node *nps[FDT_MAX_DEPTH];
40250800082SGavin Shan 	void *base = mem;
40350800082SGavin Shan 	bool dryrun = !base;
404dfbd4c6eSGavin Shan 
40550800082SGavin Shan 	if (nodepp)
40650800082SGavin Shan 		*nodepp = NULL;
407dfbd4c6eSGavin Shan 
4088c237cd0SGavin Shan 	/*
4098c237cd0SGavin Shan 	 * We're unflattening device sub-tree if @dad is valid. There are
4108c237cd0SGavin Shan 	 * possibly multiple nodes in the first level of depth. We need
4118c237cd0SGavin Shan 	 * set @depth to 1 to make fdt_next_node() happy as it bails
4128c237cd0SGavin Shan 	 * immediately when negative @depth is found. Otherwise, the device
4138c237cd0SGavin Shan 	 * nodes except the first one won't be unflattened successfully.
4148c237cd0SGavin Shan 	 */
4158c237cd0SGavin Shan 	if (dad)
4168c237cd0SGavin Shan 		depth = initial_depth = 1;
4178c237cd0SGavin Shan 
41850800082SGavin Shan 	root = dad;
41950800082SGavin Shan 	fpsizes[depth] = dad ? strlen(of_node_full_name(dad)) : 0;
42078c44d91SRhyland Klein 	nps[depth] = dad;
4218c237cd0SGavin Shan 
42250800082SGavin Shan 	for (offset = 0;
4238c237cd0SGavin Shan 	     offset >= 0 && depth >= initial_depth;
42450800082SGavin Shan 	     offset = fdt_next_node(blob, offset, &depth)) {
42550800082SGavin Shan 		if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH))
42650800082SGavin Shan 			continue;
427e6a6928cSRob Herring 
42878c44d91SRhyland Klein 		fpsizes[depth+1] = populate_node(blob, offset, &mem,
42978c44d91SRhyland Klein 						 nps[depth],
43078c44d91SRhyland Klein 						 fpsizes[depth],
43178c44d91SRhyland Klein 						 &nps[depth+1], dryrun);
43278c44d91SRhyland Klein 		if (!fpsizes[depth+1])
43350800082SGavin Shan 			return mem - base;
43450800082SGavin Shan 
43550800082SGavin Shan 		if (!dryrun && nodepp && !*nodepp)
43678c44d91SRhyland Klein 			*nodepp = nps[depth+1];
43750800082SGavin Shan 		if (!dryrun && !root)
43878c44d91SRhyland Klein 			root = nps[depth+1];
43950800082SGavin Shan 	}
44050800082SGavin Shan 
44150800082SGavin Shan 	if (offset < 0 && offset != -FDT_ERR_NOTFOUND) {
442606ad42aSRob Herring 		pr_err("Error %d processing FDT\n", offset);
44350800082SGavin Shan 		return -EINVAL;
44450800082SGavin Shan 	}
445e6a6928cSRob Herring 
44670161ff3SGrant Likely 	/*
44770161ff3SGrant Likely 	 * Reverse the child list. Some drivers assumes node order matches .dts
44870161ff3SGrant Likely 	 * node order
44970161ff3SGrant Likely 	 */
45050800082SGavin Shan 	if (!dryrun)
45150800082SGavin Shan 		reverse_nodes(root);
45270161ff3SGrant Likely 
45350800082SGavin Shan 	return mem - base;
454bbd33931SGrant Likely }
45541f88009SGrant Likely 
456fe140423SStephen Neuendorffer /**
457fe140423SStephen Neuendorffer  * __unflatten_device_tree - create tree of device_nodes from flat blob
458fe140423SStephen Neuendorffer  *
459fe140423SStephen Neuendorffer  * unflattens a device-tree, creating the
460fe140423SStephen Neuendorffer  * tree of struct device_node. It also fills the "name" and "type"
461fe140423SStephen Neuendorffer  * pointers of the nodes so the normal device-tree walking functions
462fe140423SStephen Neuendorffer  * can be used.
463fe140423SStephen Neuendorffer  * @blob: The blob to expand
464c4263233SGavin Shan  * @dad: Parent device node
465fe140423SStephen Neuendorffer  * @mynodes: The device_node tree created by the call
466fe140423SStephen Neuendorffer  * @dt_alloc: An allocator that provides a virtual address to memory
467fe140423SStephen Neuendorffer  * for the resulting tree
46883262418SGavin Shan  *
46983262418SGavin Shan  * Returns NULL on failure or the memory chunk containing the unflattened
47083262418SGavin Shan  * device tree on success.
471fe140423SStephen Neuendorffer  */
47283262418SGavin Shan static void *__unflatten_device_tree(const void *blob,
473c4263233SGavin Shan 				     struct device_node *dad,
474fe140423SStephen Neuendorffer 				     struct device_node **mynodes,
475fe140423SStephen Neuendorffer 				     void *(*dt_alloc)(u64 size, u64 align))
476fe140423SStephen Neuendorffer {
47750800082SGavin Shan 	int size;
478e6a6928cSRob Herring 	void *mem;
479fe140423SStephen Neuendorffer 
480fe140423SStephen Neuendorffer 	pr_debug(" -> unflatten_device_tree()\n");
481fe140423SStephen Neuendorffer 
482fe140423SStephen Neuendorffer 	if (!blob) {
483fe140423SStephen Neuendorffer 		pr_debug("No device tree pointer\n");
48483262418SGavin Shan 		return NULL;
485fe140423SStephen Neuendorffer 	}
486fe140423SStephen Neuendorffer 
487fe140423SStephen Neuendorffer 	pr_debug("Unflattening device tree:\n");
488c972de14SRob Herring 	pr_debug("magic: %08x\n", fdt_magic(blob));
489c972de14SRob Herring 	pr_debug("size: %08x\n", fdt_totalsize(blob));
490c972de14SRob Herring 	pr_debug("version: %08x\n", fdt_version(blob));
491fe140423SStephen Neuendorffer 
492c972de14SRob Herring 	if (fdt_check_header(blob)) {
493fe140423SStephen Neuendorffer 		pr_err("Invalid device tree blob header\n");
49483262418SGavin Shan 		return NULL;
495fe140423SStephen Neuendorffer 	}
496fe140423SStephen Neuendorffer 
497fe140423SStephen Neuendorffer 	/* First pass, scan for size */
498c4263233SGavin Shan 	size = unflatten_dt_nodes(blob, NULL, dad, NULL);
49950800082SGavin Shan 	if (size < 0)
50083262418SGavin Shan 		return NULL;
501fe140423SStephen Neuendorffer 
50250800082SGavin Shan 	size = ALIGN(size, 4);
50350800082SGavin Shan 	pr_debug("  size is %d, allocating...\n", size);
504fe140423SStephen Neuendorffer 
505fe140423SStephen Neuendorffer 	/* Allocate memory for the expanded device tree */
50644856819SGrant Likely 	mem = dt_alloc(size + 4, __alignof__(struct device_node));
50744856819SGrant Likely 	memset(mem, 0, size);
508fe140423SStephen Neuendorffer 
50944856819SGrant Likely 	*(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef);
5109e401275SWladislav Wiebe 
51144856819SGrant Likely 	pr_debug("  unflattening %p...\n", mem);
512fe140423SStephen Neuendorffer 
513fe140423SStephen Neuendorffer 	/* Second pass, do actual unflattening */
514c4263233SGavin Shan 	unflatten_dt_nodes(blob, mem, dad, mynodes);
51544856819SGrant Likely 	if (be32_to_cpup(mem + size) != 0xdeadbeef)
516fe140423SStephen Neuendorffer 		pr_warning("End of tree marker overwritten: %08x\n",
51744856819SGrant Likely 			   be32_to_cpup(mem + size));
518fe140423SStephen Neuendorffer 
519fe140423SStephen Neuendorffer 	pr_debug(" <- unflatten_device_tree()\n");
52083262418SGavin Shan 	return mem;
521fe140423SStephen Neuendorffer }
522fe140423SStephen Neuendorffer 
523fe140423SStephen Neuendorffer static void *kernel_tree_alloc(u64 size, u64 align)
524fe140423SStephen Neuendorffer {
525fe140423SStephen Neuendorffer 	return kzalloc(size, GFP_KERNEL);
526fe140423SStephen Neuendorffer }
527fe140423SStephen Neuendorffer 
528f8062386SGuenter Roeck static DEFINE_MUTEX(of_fdt_unflatten_mutex);
529f8062386SGuenter Roeck 
530fe140423SStephen Neuendorffer /**
531fe140423SStephen Neuendorffer  * of_fdt_unflatten_tree - create tree of device_nodes from flat blob
532c4263233SGavin Shan  * @blob: Flat device tree blob
533c4263233SGavin Shan  * @dad: Parent device node
534c4263233SGavin Shan  * @mynodes: The device tree created by the call
535fe140423SStephen Neuendorffer  *
536fe140423SStephen Neuendorffer  * unflattens the device-tree passed by the firmware, creating the
537fe140423SStephen Neuendorffer  * tree of struct device_node. It also fills the "name" and "type"
538fe140423SStephen Neuendorffer  * pointers of the nodes so the normal device-tree walking functions
539fe140423SStephen Neuendorffer  * can be used.
54083262418SGavin Shan  *
54183262418SGavin Shan  * Returns NULL on failure or the memory chunk containing the unflattened
54283262418SGavin Shan  * device tree on success.
543fe140423SStephen Neuendorffer  */
54483262418SGavin Shan void *of_fdt_unflatten_tree(const unsigned long *blob,
545c4263233SGavin Shan 			    struct device_node *dad,
546fe140423SStephen Neuendorffer 			    struct device_node **mynodes)
547fe140423SStephen Neuendorffer {
54883262418SGavin Shan 	void *mem;
54983262418SGavin Shan 
550f8062386SGuenter Roeck 	mutex_lock(&of_fdt_unflatten_mutex);
55183262418SGavin Shan 	mem = __unflatten_device_tree(blob, dad, mynodes, &kernel_tree_alloc);
552f8062386SGuenter Roeck 	mutex_unlock(&of_fdt_unflatten_mutex);
55383262418SGavin Shan 
55483262418SGavin Shan 	return mem;
555fe140423SStephen Neuendorffer }
556fe140423SStephen Neuendorffer EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
557fe140423SStephen Neuendorffer 
55857d00ecfSStephen Neuendorffer /* Everything below here references initial_boot_params directly. */
55957d00ecfSStephen Neuendorffer int __initdata dt_root_addr_cells;
56057d00ecfSStephen Neuendorffer int __initdata dt_root_size_cells;
56157d00ecfSStephen Neuendorffer 
5621daa0c4cSRob Herring void *initial_boot_params;
56357d00ecfSStephen Neuendorffer 
56457d00ecfSStephen Neuendorffer #ifdef CONFIG_OF_EARLY_FLATTREE
56557d00ecfSStephen Neuendorffer 
56608d53aa5SArd Biesheuvel static u32 of_fdt_crc32;
56708d53aa5SArd Biesheuvel 
56857d00ecfSStephen Neuendorffer /**
569e8d9d1f5SMarek Szyprowski  * res_mem_reserve_reg() - reserve all memory described in 'reg' property
570e8d9d1f5SMarek Szyprowski  */
571e8d9d1f5SMarek Szyprowski static int __init __reserved_mem_reserve_reg(unsigned long node,
572e8d9d1f5SMarek Szyprowski 					     const char *uname)
573e8d9d1f5SMarek Szyprowski {
574e8d9d1f5SMarek Szyprowski 	int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
575e8d9d1f5SMarek Szyprowski 	phys_addr_t base, size;
5769d0c4dfeSRob Herring 	int len;
5779d0c4dfeSRob Herring 	const __be32 *prop;
5783f0c8206SMarek Szyprowski 	int nomap, first = 1;
579e8d9d1f5SMarek Szyprowski 
580e8d9d1f5SMarek Szyprowski 	prop = of_get_flat_dt_prop(node, "reg", &len);
581e8d9d1f5SMarek Szyprowski 	if (!prop)
582e8d9d1f5SMarek Szyprowski 		return -ENOENT;
583e8d9d1f5SMarek Szyprowski 
584e8d9d1f5SMarek Szyprowski 	if (len && len % t_len != 0) {
585e8d9d1f5SMarek Szyprowski 		pr_err("Reserved memory: invalid reg property in '%s', skipping node.\n",
586e8d9d1f5SMarek Szyprowski 		       uname);
587e8d9d1f5SMarek Szyprowski 		return -EINVAL;
588e8d9d1f5SMarek Szyprowski 	}
589e8d9d1f5SMarek Szyprowski 
590e8d9d1f5SMarek Szyprowski 	nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL;
591e8d9d1f5SMarek Szyprowski 
592e8d9d1f5SMarek Szyprowski 	while (len >= t_len) {
593e8d9d1f5SMarek Szyprowski 		base = dt_mem_next_cell(dt_root_addr_cells, &prop);
594e8d9d1f5SMarek Szyprowski 		size = dt_mem_next_cell(dt_root_size_cells, &prop);
595e8d9d1f5SMarek Szyprowski 
596b5f2a8c0SAl Cooper 		if (size &&
597e8d9d1f5SMarek Szyprowski 		    early_init_dt_reserve_memory_arch(base, size, nomap) == 0)
598e8d9d1f5SMarek Szyprowski 			pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n",
599e8d9d1f5SMarek Szyprowski 				uname, &base, (unsigned long)size / SZ_1M);
600e8d9d1f5SMarek Szyprowski 		else
601e8d9d1f5SMarek Szyprowski 			pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %ld MiB\n",
602e8d9d1f5SMarek Szyprowski 				uname, &base, (unsigned long)size / SZ_1M);
603e8d9d1f5SMarek Szyprowski 
604e8d9d1f5SMarek Szyprowski 		len -= t_len;
6053f0c8206SMarek Szyprowski 		if (first) {
6063f0c8206SMarek Szyprowski 			fdt_reserved_mem_save_node(node, uname, base, size);
6073f0c8206SMarek Szyprowski 			first = 0;
6083f0c8206SMarek Szyprowski 		}
609e8d9d1f5SMarek Szyprowski 	}
610e8d9d1f5SMarek Szyprowski 	return 0;
611e8d9d1f5SMarek Szyprowski }
612e8d9d1f5SMarek Szyprowski 
613e8d9d1f5SMarek Szyprowski /**
614e8d9d1f5SMarek Szyprowski  * __reserved_mem_check_root() - check if #size-cells, #address-cells provided
615e8d9d1f5SMarek Szyprowski  * in /reserved-memory matches the values supported by the current implementation,
616e8d9d1f5SMarek Szyprowski  * also check if ranges property has been provided
617e8d9d1f5SMarek Szyprowski  */
6185b624118SXiubo Li static int __init __reserved_mem_check_root(unsigned long node)
619e8d9d1f5SMarek Szyprowski {
6209d0c4dfeSRob Herring 	const __be32 *prop;
621e8d9d1f5SMarek Szyprowski 
622e8d9d1f5SMarek Szyprowski 	prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
623e8d9d1f5SMarek Szyprowski 	if (!prop || be32_to_cpup(prop) != dt_root_size_cells)
624e8d9d1f5SMarek Szyprowski 		return -EINVAL;
625e8d9d1f5SMarek Szyprowski 
626e8d9d1f5SMarek Szyprowski 	prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
627e8d9d1f5SMarek Szyprowski 	if (!prop || be32_to_cpup(prop) != dt_root_addr_cells)
628e8d9d1f5SMarek Szyprowski 		return -EINVAL;
629e8d9d1f5SMarek Szyprowski 
630e8d9d1f5SMarek Szyprowski 	prop = of_get_flat_dt_prop(node, "ranges", NULL);
631e8d9d1f5SMarek Szyprowski 	if (!prop)
632e8d9d1f5SMarek Szyprowski 		return -EINVAL;
633e8d9d1f5SMarek Szyprowski 	return 0;
634e8d9d1f5SMarek Szyprowski }
635e8d9d1f5SMarek Szyprowski 
636e8d9d1f5SMarek Szyprowski /**
637e8d9d1f5SMarek Szyprowski  * fdt_scan_reserved_mem() - scan a single FDT node for reserved memory
638e8d9d1f5SMarek Szyprowski  */
639e8d9d1f5SMarek Szyprowski static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname,
640e8d9d1f5SMarek Szyprowski 					  int depth, void *data)
641e8d9d1f5SMarek Szyprowski {
642e8d9d1f5SMarek Szyprowski 	static int found;
643e8d9d1f5SMarek Szyprowski 	const char *status;
6443f0c8206SMarek Szyprowski 	int err;
645e8d9d1f5SMarek Szyprowski 
646e8d9d1f5SMarek Szyprowski 	if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) {
647e8d9d1f5SMarek Szyprowski 		if (__reserved_mem_check_root(node) != 0) {
648e8d9d1f5SMarek Szyprowski 			pr_err("Reserved memory: unsupported node format, ignoring\n");
649e8d9d1f5SMarek Szyprowski 			/* break scan */
650e8d9d1f5SMarek Szyprowski 			return 1;
651e8d9d1f5SMarek Szyprowski 		}
652e8d9d1f5SMarek Szyprowski 		found = 1;
653e8d9d1f5SMarek Szyprowski 		/* scan next node */
654e8d9d1f5SMarek Szyprowski 		return 0;
655e8d9d1f5SMarek Szyprowski 	} else if (!found) {
656e8d9d1f5SMarek Szyprowski 		/* scan next node */
657e8d9d1f5SMarek Szyprowski 		return 0;
658e8d9d1f5SMarek Szyprowski 	} else if (found && depth < 2) {
659e8d9d1f5SMarek Szyprowski 		/* scanning of /reserved-memory has been finished */
660e8d9d1f5SMarek Szyprowski 		return 1;
661e8d9d1f5SMarek Szyprowski 	}
662e8d9d1f5SMarek Szyprowski 
663e8d9d1f5SMarek Szyprowski 	status = of_get_flat_dt_prop(node, "status", NULL);
664e8d9d1f5SMarek Szyprowski 	if (status && strcmp(status, "okay") != 0 && strcmp(status, "ok") != 0)
665e8d9d1f5SMarek Szyprowski 		return 0;
666e8d9d1f5SMarek Szyprowski 
6673f0c8206SMarek Szyprowski 	err = __reserved_mem_reserve_reg(node, uname);
6683f0c8206SMarek Szyprowski 	if (err == -ENOENT && of_get_flat_dt_prop(node, "size", NULL))
6693f0c8206SMarek Szyprowski 		fdt_reserved_mem_save_node(node, uname, 0, 0);
670e8d9d1f5SMarek Szyprowski 
671e8d9d1f5SMarek Szyprowski 	/* scan next node */
672e8d9d1f5SMarek Szyprowski 	return 0;
673e8d9d1f5SMarek Szyprowski }
674e8d9d1f5SMarek Szyprowski 
675e8d9d1f5SMarek Szyprowski /**
676e8d9d1f5SMarek Szyprowski  * early_init_fdt_scan_reserved_mem() - create reserved memory regions
677e8d9d1f5SMarek Szyprowski  *
678e8d9d1f5SMarek Szyprowski  * This function grabs memory from early allocator for device exclusive use
679e8d9d1f5SMarek Szyprowski  * defined in device tree structures. It should be called by arch specific code
680e8d9d1f5SMarek Szyprowski  * once the early allocator (i.e. memblock) has been fully activated.
681e8d9d1f5SMarek Szyprowski  */
682e8d9d1f5SMarek Szyprowski void __init early_init_fdt_scan_reserved_mem(void)
683e8d9d1f5SMarek Szyprowski {
684d1552ce4SRob Herring 	int n;
685d1552ce4SRob Herring 	u64 base, size;
686d1552ce4SRob Herring 
6872040b527SJosh Cartwright 	if (!initial_boot_params)
6882040b527SJosh Cartwright 		return;
6892040b527SJosh Cartwright 
690d1552ce4SRob Herring 	/* Process header /memreserve/ fields */
691d1552ce4SRob Herring 	for (n = 0; ; n++) {
692d1552ce4SRob Herring 		fdt_get_mem_rsv(initial_boot_params, n, &base, &size);
693d1552ce4SRob Herring 		if (!size)
694d1552ce4SRob Herring 			break;
695d1552ce4SRob Herring 		early_init_dt_reserve_memory_arch(base, size, 0);
696d1552ce4SRob Herring 	}
697d1552ce4SRob Herring 
698e8d9d1f5SMarek Szyprowski 	of_scan_flat_dt(__fdt_scan_reserved_mem, NULL);
6993f0c8206SMarek Szyprowski 	fdt_init_reserved_mem();
700e8d9d1f5SMarek Szyprowski }
701e8d9d1f5SMarek Szyprowski 
702e8d9d1f5SMarek Szyprowski /**
70324bbd929SArd Biesheuvel  * early_init_fdt_reserve_self() - reserve the memory used by the FDT blob
70424bbd929SArd Biesheuvel  */
70524bbd929SArd Biesheuvel void __init early_init_fdt_reserve_self(void)
70624bbd929SArd Biesheuvel {
70724bbd929SArd Biesheuvel 	if (!initial_boot_params)
70824bbd929SArd Biesheuvel 		return;
70924bbd929SArd Biesheuvel 
71024bbd929SArd Biesheuvel 	/* Reserve the dtb region */
71124bbd929SArd Biesheuvel 	early_init_dt_reserve_memory_arch(__pa(initial_boot_params),
71224bbd929SArd Biesheuvel 					  fdt_totalsize(initial_boot_params),
71324bbd929SArd Biesheuvel 					  0);
71424bbd929SArd Biesheuvel }
71524bbd929SArd Biesheuvel 
71624bbd929SArd Biesheuvel /**
71757d00ecfSStephen Neuendorffer  * of_scan_flat_dt - scan flattened tree blob and call callback on each.
71857d00ecfSStephen Neuendorffer  * @it: callback function
71957d00ecfSStephen Neuendorffer  * @data: context data pointer
72057d00ecfSStephen Neuendorffer  *
72157d00ecfSStephen Neuendorffer  * This function is used to scan the flattened device-tree, it is
72257d00ecfSStephen Neuendorffer  * used to extract the memory information at boot before we can
72357d00ecfSStephen Neuendorffer  * unflatten the tree
72457d00ecfSStephen Neuendorffer  */
72557d00ecfSStephen Neuendorffer int __init of_scan_flat_dt(int (*it)(unsigned long node,
72657d00ecfSStephen Neuendorffer 				     const char *uname, int depth,
72757d00ecfSStephen Neuendorffer 				     void *data),
72857d00ecfSStephen Neuendorffer 			   void *data)
72957d00ecfSStephen Neuendorffer {
730e6a6928cSRob Herring 	const void *blob = initial_boot_params;
731e55b0829SFabio Estevam 	const char *pathp;
732e6a6928cSRob Herring 	int offset, rc = 0, depth = -1;
73357d00ecfSStephen Neuendorffer 
734e6a6928cSRob Herring         for (offset = fdt_next_node(blob, -1, &depth);
735e6a6928cSRob Herring              offset >= 0 && depth >= 0 && !rc;
736e6a6928cSRob Herring              offset = fdt_next_node(blob, offset, &depth)) {
737e6a6928cSRob Herring 
738e6a6928cSRob Herring 		pathp = fdt_get_name(blob, offset, NULL);
739375da3a7SAndy Shevchenko 		if (*pathp == '/')
740375da3a7SAndy Shevchenko 			pathp = kbasename(pathp);
741e6a6928cSRob Herring 		rc = it(offset, pathp, depth, data);
742e6a6928cSRob Herring 	}
74357d00ecfSStephen Neuendorffer 	return rc;
74457d00ecfSStephen Neuendorffer }
74557d00ecfSStephen Neuendorffer 
74657d00ecfSStephen Neuendorffer /**
74757d00ecfSStephen Neuendorffer  * of_get_flat_dt_root - find the root node in the flat blob
74857d00ecfSStephen Neuendorffer  */
74957d00ecfSStephen Neuendorffer unsigned long __init of_get_flat_dt_root(void)
75057d00ecfSStephen Neuendorffer {
751e6a6928cSRob Herring 	return 0;
75257d00ecfSStephen Neuendorffer }
75357d00ecfSStephen Neuendorffer 
75457d00ecfSStephen Neuendorffer /**
755c0556d3fSRob Herring  * of_get_flat_dt_size - Return the total size of the FDT
756c0556d3fSRob Herring  */
757c0556d3fSRob Herring int __init of_get_flat_dt_size(void)
758c0556d3fSRob Herring {
759c0556d3fSRob Herring 	return fdt_totalsize(initial_boot_params);
760c0556d3fSRob Herring }
761c0556d3fSRob Herring 
762c0556d3fSRob Herring /**
76357d00ecfSStephen Neuendorffer  * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr
76457d00ecfSStephen Neuendorffer  *
76557d00ecfSStephen Neuendorffer  * This function can be used within scan_flattened_dt callback to get
76657d00ecfSStephen Neuendorffer  * access to properties
76757d00ecfSStephen Neuendorffer  */
7689d0c4dfeSRob Herring const void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
7699d0c4dfeSRob Herring 				       int *size)
77057d00ecfSStephen Neuendorffer {
771e6a6928cSRob Herring 	return fdt_getprop(initial_boot_params, node, name, size);
77257d00ecfSStephen Neuendorffer }
77357d00ecfSStephen Neuendorffer 
77457d00ecfSStephen Neuendorffer /**
77557d00ecfSStephen Neuendorffer  * of_flat_dt_is_compatible - Return true if given node has compat in compatible list
77657d00ecfSStephen Neuendorffer  * @node: node to test
77757d00ecfSStephen Neuendorffer  * @compat: compatible string to compare with compatible list.
77857d00ecfSStephen Neuendorffer  */
77957d00ecfSStephen Neuendorffer int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
78057d00ecfSStephen Neuendorffer {
78157d00ecfSStephen Neuendorffer 	return of_fdt_is_compatible(initial_boot_params, node, compat);
78257d00ecfSStephen Neuendorffer }
78357d00ecfSStephen Neuendorffer 
784a4f740cfSGrant Likely /**
785a4f740cfSGrant Likely  * of_flat_dt_match - Return true if node matches a list of compatible values
786a4f740cfSGrant Likely  */
7877b482c83SUwe Kleine-König int __init of_flat_dt_match(unsigned long node, const char *const *compat)
788a4f740cfSGrant Likely {
789a4f740cfSGrant Likely 	return of_fdt_match(initial_boot_params, node, compat);
790a4f740cfSGrant Likely }
791a4f740cfSGrant Likely 
79257d74bcfSMarek Szyprowski struct fdt_scan_status {
79357d74bcfSMarek Szyprowski 	const char *name;
79457d74bcfSMarek Szyprowski 	int namelen;
79557d74bcfSMarek Szyprowski 	int depth;
79657d74bcfSMarek Szyprowski 	int found;
79757d74bcfSMarek Szyprowski 	int (*iterator)(unsigned long node, const char *uname, int depth, void *data);
79857d74bcfSMarek Szyprowski 	void *data;
79957d74bcfSMarek Szyprowski };
80057d74bcfSMarek Szyprowski 
8016a903a25SRob Herring const char * __init of_flat_dt_get_machine_name(void)
8026a903a25SRob Herring {
8036a903a25SRob Herring 	const char *name;
8046a903a25SRob Herring 	unsigned long dt_root = of_get_flat_dt_root();
8056a903a25SRob Herring 
8066a903a25SRob Herring 	name = of_get_flat_dt_prop(dt_root, "model", NULL);
8076a903a25SRob Herring 	if (!name)
8086a903a25SRob Herring 		name = of_get_flat_dt_prop(dt_root, "compatible", NULL);
8096a903a25SRob Herring 	return name;
8106a903a25SRob Herring }
8116a903a25SRob Herring 
8126a903a25SRob Herring /**
8136a903a25SRob Herring  * of_flat_dt_match_machine - Iterate match tables to find matching machine.
8146a903a25SRob Herring  *
8156a903a25SRob Herring  * @default_match: A machine specific ptr to return in case of no match.
8166a903a25SRob Herring  * @get_next_compat: callback function to return next compatible match table.
8176a903a25SRob Herring  *
8186a903a25SRob Herring  * Iterate through machine match tables to find the best match for the machine
8196a903a25SRob Herring  * compatible string in the FDT.
8206a903a25SRob Herring  */
8216a903a25SRob Herring const void * __init of_flat_dt_match_machine(const void *default_match,
8226a903a25SRob Herring 		const void * (*get_next_compat)(const char * const**))
8236a903a25SRob Herring {
8246a903a25SRob Herring 	const void *data = NULL;
8256a903a25SRob Herring 	const void *best_data = default_match;
8266a903a25SRob Herring 	const char *const *compat;
8276a903a25SRob Herring 	unsigned long dt_root;
8286a903a25SRob Herring 	unsigned int best_score = ~1, score = 0;
8296a903a25SRob Herring 
8306a903a25SRob Herring 	dt_root = of_get_flat_dt_root();
8316a903a25SRob Herring 	while ((data = get_next_compat(&compat))) {
8326a903a25SRob Herring 		score = of_flat_dt_match(dt_root, compat);
8336a903a25SRob Herring 		if (score > 0 && score < best_score) {
8346a903a25SRob Herring 			best_data = data;
8356a903a25SRob Herring 			best_score = score;
8366a903a25SRob Herring 		}
8376a903a25SRob Herring 	}
8386a903a25SRob Herring 	if (!best_data) {
8396a903a25SRob Herring 		const char *prop;
8409d0c4dfeSRob Herring 		int size;
8416a903a25SRob Herring 
8426a903a25SRob Herring 		pr_err("\n unrecognized device tree list:\n[ ");
8436a903a25SRob Herring 
8446a903a25SRob Herring 		prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
8456a903a25SRob Herring 		if (prop) {
8466a903a25SRob Herring 			while (size > 0) {
8476a903a25SRob Herring 				printk("'%s' ", prop);
8486a903a25SRob Herring 				size -= strlen(prop) + 1;
8496a903a25SRob Herring 				prop += strlen(prop) + 1;
8506a903a25SRob Herring 			}
8516a903a25SRob Herring 		}
8526a903a25SRob Herring 		printk("]\n\n");
8536a903a25SRob Herring 		return NULL;
8546a903a25SRob Herring 	}
8556a903a25SRob Herring 
8566a903a25SRob Herring 	pr_info("Machine model: %s\n", of_flat_dt_get_machine_name());
8576a903a25SRob Herring 
8586a903a25SRob Herring 	return best_data;
8596a903a25SRob Herring }
8606a903a25SRob Herring 
861f7b3a835SGrant Likely #ifdef CONFIG_BLK_DEV_INITRD
862369bc9abSArd Biesheuvel #ifndef __early_init_dt_declare_initrd
863369bc9abSArd Biesheuvel static void __early_init_dt_declare_initrd(unsigned long start,
864369bc9abSArd Biesheuvel 					   unsigned long end)
865369bc9abSArd Biesheuvel {
866369bc9abSArd Biesheuvel 	initrd_start = (unsigned long)__va(start);
867369bc9abSArd Biesheuvel 	initrd_end = (unsigned long)__va(end);
868369bc9abSArd Biesheuvel 	initrd_below_start_ok = 1;
869369bc9abSArd Biesheuvel }
870369bc9abSArd Biesheuvel #endif
871369bc9abSArd Biesheuvel 
872f7b3a835SGrant Likely /**
873f7b3a835SGrant Likely  * early_init_dt_check_for_initrd - Decode initrd location from flat tree
874f7b3a835SGrant Likely  * @node: reference to node containing initrd location ('chosen')
875f7b3a835SGrant Likely  */
87629eb45a9SRob Herring static void __init early_init_dt_check_for_initrd(unsigned long node)
877f7b3a835SGrant Likely {
878374d5c99SSantosh Shilimkar 	u64 start, end;
8799d0c4dfeSRob Herring 	int len;
8809d0c4dfeSRob Herring 	const __be32 *prop;
881f7b3a835SGrant Likely 
882f7b3a835SGrant Likely 	pr_debug("Looking for initrd properties... ");
883f7b3a835SGrant Likely 
884f7b3a835SGrant Likely 	prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len);
8851406bc2fSJeremy Kerr 	if (!prop)
8861406bc2fSJeremy Kerr 		return;
887374d5c99SSantosh Shilimkar 	start = of_read_number(prop, len/4);
888f7b3a835SGrant Likely 
889f7b3a835SGrant Likely 	prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len);
8901406bc2fSJeremy Kerr 	if (!prop)
8911406bc2fSJeremy Kerr 		return;
892374d5c99SSantosh Shilimkar 	end = of_read_number(prop, len/4);
893f7b3a835SGrant Likely 
894369bc9abSArd Biesheuvel 	__early_init_dt_declare_initrd(start, end);
89529eb45a9SRob Herring 
896374d5c99SSantosh Shilimkar 	pr_debug("initrd_start=0x%llx  initrd_end=0x%llx\n",
897374d5c99SSantosh Shilimkar 		 (unsigned long long)start, (unsigned long long)end);
898f7b3a835SGrant Likely }
899f7b3a835SGrant Likely #else
90029eb45a9SRob Herring static inline void early_init_dt_check_for_initrd(unsigned long node)
901f7b3a835SGrant Likely {
902f7b3a835SGrant Likely }
903f7b3a835SGrant Likely #endif /* CONFIG_BLK_DEV_INITRD */
904f7b3a835SGrant Likely 
905fb11ffe7SRob Herring #ifdef CONFIG_SERIAL_EARLYCON
906fb11ffe7SRob Herring 
907523bf17fSLad, Prabhakar static int __init early_init_dt_scan_chosen_serial(void)
908fb11ffe7SRob Herring {
909fb11ffe7SRob Herring 	int offset;
9104d118c9aSPeter Hurley 	const char *p, *q, *options = NULL;
911fb11ffe7SRob Herring 	int l;
9122eaa7909SPeter Hurley 	const struct earlycon_id *match;
913fb11ffe7SRob Herring 	const void *fdt = initial_boot_params;
914fb11ffe7SRob Herring 
915fb11ffe7SRob Herring 	offset = fdt_path_offset(fdt, "/chosen");
916fb11ffe7SRob Herring 	if (offset < 0)
917fb11ffe7SRob Herring 		offset = fdt_path_offset(fdt, "/chosen@0");
918fb11ffe7SRob Herring 	if (offset < 0)
919fb11ffe7SRob Herring 		return -ENOENT;
920fb11ffe7SRob Herring 
921fb11ffe7SRob Herring 	p = fdt_getprop(fdt, offset, "stdout-path", &l);
922fb11ffe7SRob Herring 	if (!p)
923fb11ffe7SRob Herring 		p = fdt_getprop(fdt, offset, "linux,stdout-path", &l);
924fb11ffe7SRob Herring 	if (!p || !l)
925fb11ffe7SRob Herring 		return -ENOENT;
926fb11ffe7SRob Herring 
9274d118c9aSPeter Hurley 	q = strchrnul(p, ':');
9284d118c9aSPeter Hurley 	if (*q != '\0')
9294d118c9aSPeter Hurley 		options = q + 1;
9300fcc286fSPeter Hurley 	l = q - p;
9316296ad9eSStefan Agner 
932fb11ffe7SRob Herring 	/* Get the node specified by stdout-path */
9330fcc286fSPeter Hurley 	offset = fdt_path_offset_namelen(fdt, p, l);
9340fcc286fSPeter Hurley 	if (offset < 0) {
9350fcc286fSPeter Hurley 		pr_warn("earlycon: stdout-path %.*s not found\n", l, p);
9360fcc286fSPeter Hurley 		return 0;
9370fcc286fSPeter Hurley 	}
938fb11ffe7SRob Herring 
9392eaa7909SPeter Hurley 	for (match = __earlycon_table; match < __earlycon_table_end; match++) {
9402eaa7909SPeter Hurley 		if (!match->compatible[0])
941fb11ffe7SRob Herring 			continue;
9422eaa7909SPeter Hurley 
9432eaa7909SPeter Hurley 		if (fdt_node_check_compatible(fdt, offset, match->compatible))
9442eaa7909SPeter Hurley 			continue;
945fb11ffe7SRob Herring 
946c90fe9c0SPeter Hurley 		of_setup_earlycon(match, offset, options);
947fb11ffe7SRob Herring 		return 0;
948fb11ffe7SRob Herring 	}
949fb11ffe7SRob Herring 	return -ENODEV;
950fb11ffe7SRob Herring }
951fb11ffe7SRob Herring 
952fb11ffe7SRob Herring static int __init setup_of_earlycon(char *buf)
953fb11ffe7SRob Herring {
954fb11ffe7SRob Herring 	if (buf)
955fb11ffe7SRob Herring 		return 0;
956fb11ffe7SRob Herring 
957fb11ffe7SRob Herring 	return early_init_dt_scan_chosen_serial();
958fb11ffe7SRob Herring }
959fb11ffe7SRob Herring early_param("earlycon", setup_of_earlycon);
960fb11ffe7SRob Herring #endif
961fb11ffe7SRob Herring 
96241f88009SGrant Likely /**
963f00abd94SGrant Likely  * early_init_dt_scan_root - fetch the top level address and size cells
964f00abd94SGrant Likely  */
965f00abd94SGrant Likely int __init early_init_dt_scan_root(unsigned long node, const char *uname,
966f00abd94SGrant Likely 				   int depth, void *data)
967f00abd94SGrant Likely {
9689d0c4dfeSRob Herring 	const __be32 *prop;
969f00abd94SGrant Likely 
970f00abd94SGrant Likely 	if (depth != 0)
971f00abd94SGrant Likely 		return 0;
972f00abd94SGrant Likely 
97333714881SJeremy Kerr 	dt_root_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
97433714881SJeremy Kerr 	dt_root_addr_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
97533714881SJeremy Kerr 
976f00abd94SGrant Likely 	prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
97733714881SJeremy Kerr 	if (prop)
97833714881SJeremy Kerr 		dt_root_size_cells = be32_to_cpup(prop);
979f00abd94SGrant Likely 	pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells);
980f00abd94SGrant Likely 
981f00abd94SGrant Likely 	prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
98233714881SJeremy Kerr 	if (prop)
98333714881SJeremy Kerr 		dt_root_addr_cells = be32_to_cpup(prop);
984f00abd94SGrant Likely 	pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);
985f00abd94SGrant Likely 
986f00abd94SGrant Likely 	/* break now */
987f00abd94SGrant Likely 	return 1;
988f00abd94SGrant Likely }
989f00abd94SGrant Likely 
9909d0c4dfeSRob Herring u64 __init dt_mem_next_cell(int s, const __be32 **cellp)
99183f7a06eSGrant Likely {
9929d0c4dfeSRob Herring 	const __be32 *p = *cellp;
99383f7a06eSGrant Likely 
99483f7a06eSGrant Likely 	*cellp = p + s;
99583f7a06eSGrant Likely 	return of_read_number(p, s);
99683f7a06eSGrant Likely }
99783f7a06eSGrant Likely 
99851975db0SGrant Likely /**
99951975db0SGrant Likely  * early_init_dt_scan_memory - Look for an parse memory nodes
100051975db0SGrant Likely  */
100151975db0SGrant Likely int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
100251975db0SGrant Likely 				     int depth, void *data)
100351975db0SGrant Likely {
10049d0c4dfeSRob Herring 	const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
10059d0c4dfeSRob Herring 	const __be32 *reg, *endp;
10069d0c4dfeSRob Herring 	int l;
100751975db0SGrant Likely 
100851975db0SGrant Likely 	/* We are scanning "memory" nodes only */
100951975db0SGrant Likely 	if (type == NULL) {
101051975db0SGrant Likely 		/*
101151975db0SGrant Likely 		 * The longtrail doesn't have a device_type on the
101251975db0SGrant Likely 		 * /memory node, so look for the node called /memory@0.
101351975db0SGrant Likely 		 */
1014b44aa25dSLeif Lindholm 		if (!IS_ENABLED(CONFIG_PPC32) || depth != 1 || strcmp(uname, "memory@0") != 0)
101551975db0SGrant Likely 			return 0;
101651975db0SGrant Likely 	} else if (strcmp(type, "memory") != 0)
101751975db0SGrant Likely 		return 0;
101851975db0SGrant Likely 
101951975db0SGrant Likely 	reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
102051975db0SGrant Likely 	if (reg == NULL)
102151975db0SGrant Likely 		reg = of_get_flat_dt_prop(node, "reg", &l);
102251975db0SGrant Likely 	if (reg == NULL)
102351975db0SGrant Likely 		return 0;
102451975db0SGrant Likely 
102551975db0SGrant Likely 	endp = reg + (l / sizeof(__be32));
102651975db0SGrant Likely 
1027c954b36eSFlorian Fainelli 	pr_debug("memory scan node %s, reg size %d,\n", uname, l);
102851975db0SGrant Likely 
102951975db0SGrant Likely 	while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
103051975db0SGrant Likely 		u64 base, size;
103151975db0SGrant Likely 
103251975db0SGrant Likely 		base = dt_mem_next_cell(dt_root_addr_cells, &reg);
103351975db0SGrant Likely 		size = dt_mem_next_cell(dt_root_size_cells, &reg);
103451975db0SGrant Likely 
103551975db0SGrant Likely 		if (size == 0)
103651975db0SGrant Likely 			continue;
103751975db0SGrant Likely 		pr_debug(" - %llx ,  %llx\n", (unsigned long long)base,
103851975db0SGrant Likely 		    (unsigned long long)size);
103951975db0SGrant Likely 
104051975db0SGrant Likely 		early_init_dt_add_memory_arch(base, size);
104151975db0SGrant Likely 	}
104251975db0SGrant Likely 
104351975db0SGrant Likely 	return 0;
104451975db0SGrant Likely }
104551975db0SGrant Likely 
104686e03221SGrant Likely int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
104786e03221SGrant Likely 				     int depth, void *data)
104886e03221SGrant Likely {
10499d0c4dfeSRob Herring 	int l;
10509d0c4dfeSRob Herring 	const char *p;
105186e03221SGrant Likely 
105286e03221SGrant Likely 	pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
105386e03221SGrant Likely 
105485f60ae4SGrant Likely 	if (depth != 1 || !data ||
105586e03221SGrant Likely 	    (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
105686e03221SGrant Likely 		return 0;
105786e03221SGrant Likely 
105886e03221SGrant Likely 	early_init_dt_check_for_initrd(node);
105986e03221SGrant Likely 
106025985edcSLucas De Marchi 	/* Retrieve command line */
106186e03221SGrant Likely 	p = of_get_flat_dt_prop(node, "bootargs", &l);
106286e03221SGrant Likely 	if (p != NULL && l > 0)
106385f60ae4SGrant Likely 		strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));
106486e03221SGrant Likely 
106578b782cbSBenjamin Herrenschmidt 	/*
106678b782cbSBenjamin Herrenschmidt 	 * CONFIG_CMDLINE is meant to be a default in case nothing else
106778b782cbSBenjamin Herrenschmidt 	 * managed to set the command line, unless CONFIG_CMDLINE_FORCE
106878b782cbSBenjamin Herrenschmidt 	 * is set in which case we override whatever was found earlier.
106978b782cbSBenjamin Herrenschmidt 	 */
107086e03221SGrant Likely #ifdef CONFIG_CMDLINE
107134b82026SMax Uvarov #if defined(CONFIG_CMDLINE_EXTEND)
107234b82026SMax Uvarov 	strlcat(data, " ", COMMAND_LINE_SIZE);
107334b82026SMax Uvarov 	strlcat(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
107434b82026SMax Uvarov #elif defined(CONFIG_CMDLINE_FORCE)
107585f60ae4SGrant Likely 	strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
107634b82026SMax Uvarov #else
107734b82026SMax Uvarov 	/* No arguments from boot loader, use kernel's  cmdl*/
107834b82026SMax Uvarov 	if (!((char *)data)[0])
107934b82026SMax Uvarov 		strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
108034b82026SMax Uvarov #endif
108186e03221SGrant Likely #endif /* CONFIG_CMDLINE */
108286e03221SGrant Likely 
108385f60ae4SGrant Likely 	pr_debug("Command line is: %s\n", (char*)data);
108486e03221SGrant Likely 
108586e03221SGrant Likely 	/* break now */
108686e03221SGrant Likely 	return 1;
108786e03221SGrant Likely }
108886e03221SGrant Likely 
1089a1727da5SGrant Likely #ifdef CONFIG_HAVE_MEMBLOCK
1090270522a0SArd Biesheuvel #ifndef MIN_MEMBLOCK_ADDR
1091270522a0SArd Biesheuvel #define MIN_MEMBLOCK_ADDR	__pa(PAGE_OFFSET)
1092270522a0SArd Biesheuvel #endif
10938eafeb48SArd Biesheuvel #ifndef MAX_MEMBLOCK_ADDR
10948eafeb48SArd Biesheuvel #define MAX_MEMBLOCK_ADDR	((phys_addr_t)~0)
10958eafeb48SArd Biesheuvel #endif
10963069f0c0SLaura Abbott 
1097068f6310SRob Herring void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
1098068f6310SRob Herring {
1099270522a0SArd Biesheuvel 	const u64 phys_offset = MIN_MEMBLOCK_ADDR;
11008f73d4b7SGeert Uytterhoeven 
11018f73d4b7SGeert Uytterhoeven 	if (!PAGE_ALIGNED(base)) {
11028cccffc5SArd Biesheuvel 		if (size < PAGE_SIZE - (base & ~PAGE_MASK)) {
11038cccffc5SArd Biesheuvel 			pr_warn("Ignoring memory block 0x%llx - 0x%llx\n",
11048cccffc5SArd Biesheuvel 				base, base + size);
11058cccffc5SArd Biesheuvel 			return;
11068cccffc5SArd Biesheuvel 		}
11078f73d4b7SGeert Uytterhoeven 		size -= PAGE_SIZE - (base & ~PAGE_MASK);
11088f73d4b7SGeert Uytterhoeven 		base = PAGE_ALIGN(base);
11098f73d4b7SGeert Uytterhoeven 	}
1110068f6310SRob Herring 	size &= PAGE_MASK;
1111a67a6ed1SLaura Abbott 
11128eafeb48SArd Biesheuvel 	if (base > MAX_MEMBLOCK_ADDR) {
1113a67a6ed1SLaura Abbott 		pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
1114a67a6ed1SLaura Abbott 				base, base + size);
1115a67a6ed1SLaura Abbott 		return;
1116a67a6ed1SLaura Abbott 	}
1117a67a6ed1SLaura Abbott 
11188eafeb48SArd Biesheuvel 	if (base + size - 1 > MAX_MEMBLOCK_ADDR) {
11199aacd602SSrinivas Kandagatla 		pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
11208eafeb48SArd Biesheuvel 				((u64)MAX_MEMBLOCK_ADDR) + 1, base + size);
11218eafeb48SArd Biesheuvel 		size = MAX_MEMBLOCK_ADDR - base + 1;
1122a67a6ed1SLaura Abbott 	}
1123a67a6ed1SLaura Abbott 
1124068f6310SRob Herring 	if (base + size < phys_offset) {
1125068f6310SRob Herring 		pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
1126068f6310SRob Herring 			   base, base + size);
1127068f6310SRob Herring 		return;
1128068f6310SRob Herring 	}
1129068f6310SRob Herring 	if (base < phys_offset) {
1130068f6310SRob Herring 		pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
1131068f6310SRob Herring 			   base, phys_offset);
1132068f6310SRob Herring 		size -= phys_offset - base;
1133068f6310SRob Herring 		base = phys_offset;
1134068f6310SRob Herring 	}
1135068f6310SRob Herring 	memblock_add(base, size);
1136068f6310SRob Herring }
1137068f6310SRob Herring 
1138e8d9d1f5SMarek Szyprowski int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
1139e8d9d1f5SMarek Szyprowski 					phys_addr_t size, bool nomap)
1140e8d9d1f5SMarek Szyprowski {
1141e8d9d1f5SMarek Szyprowski 	if (nomap)
1142e8d9d1f5SMarek Szyprowski 		return memblock_remove(base, size);
1143e8d9d1f5SMarek Szyprowski 	return memblock_reserve(base, size);
1144e8d9d1f5SMarek Szyprowski }
1145e8d9d1f5SMarek Szyprowski 
1146a1727da5SGrant Likely /*
1147a1727da5SGrant Likely  * called from unflatten_device_tree() to bootstrap devicetree itself
1148a1727da5SGrant Likely  * Architectures can override this definition if memblock isn't used
1149a1727da5SGrant Likely  */
1150a1727da5SGrant Likely void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align)
1151a1727da5SGrant Likely {
1152a1727da5SGrant Likely 	return __va(memblock_alloc(size, align));
1153a1727da5SGrant Likely }
1154e8d9d1f5SMarek Szyprowski #else
1155aefc7ec2SRob Herring void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
1156aefc7ec2SRob Herring {
1157aefc7ec2SRob Herring 	WARN_ON(1);
1158aefc7ec2SRob Herring }
1159aefc7ec2SRob Herring 
1160e8d9d1f5SMarek Szyprowski int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
1161e8d9d1f5SMarek Szyprowski 					phys_addr_t size, bool nomap)
1162e8d9d1f5SMarek Szyprowski {
116378bb2abeSDmitry V. Krivenok 	pr_err("Reserved memory not supported, ignoring range %pa - %pa%s\n",
11641d1a661dSRob Herring 		  &base, &size, nomap ? " (nomap)" : "");
1165e8d9d1f5SMarek Szyprowski 	return -ENOSYS;
1166e8d9d1f5SMarek Szyprowski }
1167aefc7ec2SRob Herring 
1168aefc7ec2SRob Herring void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align)
1169aefc7ec2SRob Herring {
1170aefc7ec2SRob Herring 	WARN_ON(1);
1171aefc7ec2SRob Herring 	return NULL;
1172aefc7ec2SRob Herring }
1173a1727da5SGrant Likely #endif
1174a1727da5SGrant Likely 
11754972a74bSLaura Abbott bool __init early_init_dt_verify(void *params)
11760288ffcbSRob Herring {
11770288ffcbSRob Herring 	if (!params)
11780288ffcbSRob Herring 		return false;
11790288ffcbSRob Herring 
118050ba08f3SBjorn Helgaas 	/* check device tree validity */
118150ba08f3SBjorn Helgaas 	if (fdt_check_header(params))
118250ba08f3SBjorn Helgaas 		return false;
118350ba08f3SBjorn Helgaas 
11840288ffcbSRob Herring 	/* Setup flat device-tree pointer */
11850288ffcbSRob Herring 	initial_boot_params = params;
118608d53aa5SArd Biesheuvel 	of_fdt_crc32 = crc32_be(~0, initial_boot_params,
118708d53aa5SArd Biesheuvel 				fdt_totalsize(initial_boot_params));
11884972a74bSLaura Abbott 	return true;
11894972a74bSLaura Abbott }
11904972a74bSLaura Abbott 
11914972a74bSLaura Abbott 
11924972a74bSLaura Abbott void __init early_init_dt_scan_nodes(void)
11934972a74bSLaura Abbott {
11940288ffcbSRob Herring 	/* Retrieve various information from the /chosen node */
11950288ffcbSRob Herring 	of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
11960288ffcbSRob Herring 
11970288ffcbSRob Herring 	/* Initialize {size,address}-cells info */
11980288ffcbSRob Herring 	of_scan_flat_dt(early_init_dt_scan_root, NULL);
11990288ffcbSRob Herring 
12000288ffcbSRob Herring 	/* Setup memory, calling early_init_dt_add_memory_arch */
12010288ffcbSRob Herring 	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
12024972a74bSLaura Abbott }
12030288ffcbSRob Herring 
12044972a74bSLaura Abbott bool __init early_init_dt_scan(void *params)
12054972a74bSLaura Abbott {
12064972a74bSLaura Abbott 	bool status;
12074972a74bSLaura Abbott 
12084972a74bSLaura Abbott 	status = early_init_dt_verify(params);
12094972a74bSLaura Abbott 	if (!status)
12104972a74bSLaura Abbott 		return false;
12114972a74bSLaura Abbott 
12124972a74bSLaura Abbott 	early_init_dt_scan_nodes();
12130288ffcbSRob Herring 	return true;
12140288ffcbSRob Herring }
12150288ffcbSRob Herring 
1216f00abd94SGrant Likely /**
121741f88009SGrant Likely  * unflatten_device_tree - create tree of device_nodes from flat blob
121841f88009SGrant Likely  *
121941f88009SGrant Likely  * unflattens the device-tree passed by the firmware, creating the
122041f88009SGrant Likely  * tree of struct device_node. It also fills the "name" and "type"
122141f88009SGrant Likely  * pointers of the nodes so the normal device-tree walking functions
122241f88009SGrant Likely  * can be used.
122341f88009SGrant Likely  */
122441f88009SGrant Likely void __init unflatten_device_tree(void)
122541f88009SGrant Likely {
1226c4263233SGavin Shan 	__unflatten_device_tree(initial_boot_params, NULL, &of_root,
1227672c5446SGrant Likely 				early_init_dt_alloc_memory_arch);
122841f88009SGrant Likely 
12294c7d6361SRobert P. J. Day 	/* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */
1230611cad72SShawn Guo 	of_alias_scan(early_init_dt_alloc_memory_arch);
123141f88009SGrant Likely }
1232e6ce1324SStephen Neuendorffer 
1233a8bf7527SRob Herring /**
1234a8bf7527SRob Herring  * unflatten_and_copy_device_tree - copy and create tree of device_nodes from flat blob
1235a8bf7527SRob Herring  *
1236a8bf7527SRob Herring  * Copies and unflattens the device-tree passed by the firmware, creating the
1237a8bf7527SRob Herring  * tree of struct device_node. It also fills the "name" and "type"
1238a8bf7527SRob Herring  * pointers of the nodes so the normal device-tree walking functions
1239a8bf7527SRob Herring  * can be used. This should only be used when the FDT memory has not been
1240a8bf7527SRob Herring  * reserved such is the case when the FDT is built-in to the kernel init
1241a8bf7527SRob Herring  * section. If the FDT memory is reserved already then unflatten_device_tree
1242a8bf7527SRob Herring  * should be used instead.
1243a8bf7527SRob Herring  */
1244a8bf7527SRob Herring void __init unflatten_and_copy_device_tree(void)
1245a8bf7527SRob Herring {
12466f041e99SJames Hogan 	int size;
12476f041e99SJames Hogan 	void *dt;
12486f041e99SJames Hogan 
12496f041e99SJames Hogan 	if (!initial_boot_params) {
12506f041e99SJames Hogan 		pr_warn("No valid device tree found, continuing without\n");
12516f041e99SJames Hogan 		return;
12526f041e99SJames Hogan 	}
12536f041e99SJames Hogan 
1254c972de14SRob Herring 	size = fdt_totalsize(initial_boot_params);
12556f041e99SJames Hogan 	dt = early_init_dt_alloc_memory_arch(size,
1256c972de14SRob Herring 					     roundup_pow_of_two(FDT_V17_SIZE));
1257a8bf7527SRob Herring 
1258a8bf7527SRob Herring 	if (dt) {
1259a8bf7527SRob Herring 		memcpy(dt, initial_boot_params, size);
1260a8bf7527SRob Herring 		initial_boot_params = dt;
1261a8bf7527SRob Herring 	}
1262a8bf7527SRob Herring 	unflatten_device_tree();
1263a8bf7527SRob Herring }
1264a8bf7527SRob Herring 
126508d53aa5SArd Biesheuvel #ifdef CONFIG_SYSFS
126608d53aa5SArd Biesheuvel static ssize_t of_fdt_raw_read(struct file *filp, struct kobject *kobj,
126708d53aa5SArd Biesheuvel 			       struct bin_attribute *bin_attr,
126808d53aa5SArd Biesheuvel 			       char *buf, loff_t off, size_t count)
1269b0a6fb36SRob Herring {
127008d53aa5SArd Biesheuvel 	memcpy(buf, initial_boot_params + off, count);
127108d53aa5SArd Biesheuvel 	return count;
127208d53aa5SArd Biesheuvel }
1273b0a6fb36SRob Herring 
127408d53aa5SArd Biesheuvel static int __init of_fdt_raw_init(void)
127508d53aa5SArd Biesheuvel {
127608d53aa5SArd Biesheuvel 	static struct bin_attribute of_fdt_raw_attr =
127708d53aa5SArd Biesheuvel 		__BIN_ATTR(fdt, S_IRUSR, of_fdt_raw_read, NULL, 0);
1278b0a6fb36SRob Herring 
127908d53aa5SArd Biesheuvel 	if (!initial_boot_params)
128008d53aa5SArd Biesheuvel 		return 0;
1281b0a6fb36SRob Herring 
128208d53aa5SArd Biesheuvel 	if (of_fdt_crc32 != crc32_be(~0, initial_boot_params,
128308d53aa5SArd Biesheuvel 				     fdt_totalsize(initial_boot_params))) {
1284606ad42aSRob Herring 		pr_warn("not creating '/sys/firmware/fdt': CRC check failed\n");
1285b0a6fb36SRob Herring 		return 0;
1286b0a6fb36SRob Herring 	}
128708d53aa5SArd Biesheuvel 	of_fdt_raw_attr.size = fdt_totalsize(initial_boot_params);
128808d53aa5SArd Biesheuvel 	return sysfs_create_bin_file(firmware_kobj, &of_fdt_raw_attr);
128908d53aa5SArd Biesheuvel }
129008d53aa5SArd Biesheuvel late_initcall(of_fdt_raw_init);
1291b0a6fb36SRob Herring #endif
1292b0a6fb36SRob Herring 
1293e6ce1324SStephen Neuendorffer #endif /* CONFIG_OF_EARLY_FLATTREE */
1294