xref: /openbmc/linux/drivers/of/fdt.c (revision 5c68b823)
1af6074fcSRob Herring // SPDX-License-Identifier: GPL-2.0
2e169cfbeSGrant Likely /*
3e169cfbeSGrant Likely  * Functions for working with the Flattened Device Tree data format
4e169cfbeSGrant Likely  *
5e169cfbeSGrant Likely  * Copyright 2009 Benjamin Herrenschmidt, IBM Corp
6e169cfbeSGrant Likely  * benh@kernel.crashing.org
7e169cfbeSGrant Likely  */
8e169cfbeSGrant Likely 
9606ad42aSRob Herring #define pr_fmt(fmt)	"OF: fdt: " fmt
10606ad42aSRob Herring 
1108d53aa5SArd Biesheuvel #include <linux/crc32.h>
1241f88009SGrant Likely #include <linux/kernel.h>
13f7b3a835SGrant Likely #include <linux/initrd.h>
14a1727da5SGrant Likely #include <linux/memblock.h>
15f8062386SGuenter Roeck #include <linux/mutex.h>
16e169cfbeSGrant Likely #include <linux/of.h>
17e169cfbeSGrant Likely #include <linux/of_fdt.h>
183f0c8206SMarek Szyprowski #include <linux/of_reserved_mem.h>
19e8d9d1f5SMarek Szyprowski #include <linux/sizes.h>
204ef7b373SJeremy Kerr #include <linux/string.h>
214ef7b373SJeremy Kerr #include <linux/errno.h>
22fe140423SStephen Neuendorffer #include <linux/slab.h>
23e6a6928cSRob Herring #include <linux/libfdt.h>
24b0a6fb36SRob Herring #include <linux/debugfs.h>
25fb11ffe7SRob Herring #include <linux/serial_core.h>
2608d53aa5SArd Biesheuvel #include <linux/sysfs.h>
2751975db0SGrant Likely 
28c89810acSFabio Estevam #include <asm/setup.h>  /* for COMMAND_LINE_SIZE */
294ef7b373SJeremy Kerr #include <asm/page.h>
304ef7b373SJeremy Kerr 
3181d0848fSFrank Rowand #include "of_private.h"
3281d0848fSFrank Rowand 
33704033ceSLaura Abbott /*
34704033ceSLaura Abbott  * of_fdt_limit_memory - limit the number of regions in the /memory node
35704033ceSLaura Abbott  * @limit: maximum entries
36704033ceSLaura Abbott  *
37704033ceSLaura Abbott  * Adjust the flattened device tree to have at most 'limit' number of
38704033ceSLaura Abbott  * memory entries in the /memory node. This function may be called
39704033ceSLaura Abbott  * any time after initial_boot_param is set.
40704033ceSLaura Abbott  */
419b4d2b63SStephen Boyd void __init of_fdt_limit_memory(int limit)
42704033ceSLaura Abbott {
43704033ceSLaura Abbott 	int memory;
44704033ceSLaura Abbott 	int len;
45704033ceSLaura Abbott 	const void *val;
46704033ceSLaura Abbott 	int nr_address_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
47704033ceSLaura Abbott 	int nr_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
4817a70355SRob Herring 	const __be32 *addr_prop;
4917a70355SRob Herring 	const __be32 *size_prop;
50704033ceSLaura Abbott 	int root_offset;
51704033ceSLaura Abbott 	int cell_size;
52704033ceSLaura Abbott 
53704033ceSLaura Abbott 	root_offset = fdt_path_offset(initial_boot_params, "/");
54704033ceSLaura Abbott 	if (root_offset < 0)
55704033ceSLaura Abbott 		return;
56704033ceSLaura Abbott 
57704033ceSLaura Abbott 	addr_prop = fdt_getprop(initial_boot_params, root_offset,
58704033ceSLaura Abbott 				"#address-cells", NULL);
59704033ceSLaura Abbott 	if (addr_prop)
60704033ceSLaura Abbott 		nr_address_cells = fdt32_to_cpu(*addr_prop);
61704033ceSLaura Abbott 
62704033ceSLaura Abbott 	size_prop = fdt_getprop(initial_boot_params, root_offset,
63704033ceSLaura Abbott 				"#size-cells", NULL);
64704033ceSLaura Abbott 	if (size_prop)
65704033ceSLaura Abbott 		nr_size_cells = fdt32_to_cpu(*size_prop);
66704033ceSLaura Abbott 
67704033ceSLaura Abbott 	cell_size = sizeof(uint32_t)*(nr_address_cells + nr_size_cells);
68704033ceSLaura Abbott 
69704033ceSLaura Abbott 	memory = fdt_path_offset(initial_boot_params, "/memory");
70704033ceSLaura Abbott 	if (memory > 0) {
71704033ceSLaura Abbott 		val = fdt_getprop(initial_boot_params, memory, "reg", &len);
72704033ceSLaura Abbott 		if (len > limit*cell_size) {
73704033ceSLaura Abbott 			len = limit*cell_size;
74704033ceSLaura Abbott 			pr_debug("Limiting number of entries to %d\n", limit);
75704033ceSLaura Abbott 			fdt_setprop(initial_boot_params, memory, "reg", val,
76704033ceSLaura Abbott 					len);
77704033ceSLaura Abbott 		}
78704033ceSLaura Abbott 	}
79704033ceSLaura Abbott }
80704033ceSLaura Abbott 
81ecc8a96eSRob Herring static bool of_fdt_device_is_available(const void *blob, unsigned long node)
82ecc8a96eSRob Herring {
83ecc8a96eSRob Herring 	const char *status = fdt_getprop(blob, node, "status", NULL);
84ecc8a96eSRob Herring 
85ecc8a96eSRob Herring 	if (!status)
86ecc8a96eSRob Herring 		return true;
87ecc8a96eSRob Herring 
88ecc8a96eSRob Herring 	if (!strcmp(status, "ok") || !strcmp(status, "okay"))
89ecc8a96eSRob Herring 		return true;
90ecc8a96eSRob Herring 
91ecc8a96eSRob Herring 	return false;
92ecc8a96eSRob Herring }
93ecc8a96eSRob Herring 
9444856819SGrant Likely static void *unflatten_dt_alloc(void **mem, unsigned long size,
95bbd33931SGrant Likely 				       unsigned long align)
96bbd33931SGrant Likely {
97bbd33931SGrant Likely 	void *res;
98bbd33931SGrant Likely 
9944856819SGrant Likely 	*mem = PTR_ALIGN(*mem, align);
10044856819SGrant Likely 	res = *mem;
101bbd33931SGrant Likely 	*mem += size;
102bbd33931SGrant Likely 
103bbd33931SGrant Likely 	return res;
104bbd33931SGrant Likely }
105bbd33931SGrant Likely 
106dfbd4c6eSGavin Shan static void populate_properties(const void *blob,
107dfbd4c6eSGavin Shan 				int offset,
108dfbd4c6eSGavin Shan 				void **mem,
109dfbd4c6eSGavin Shan 				struct device_node *np,
110dfbd4c6eSGavin Shan 				const char *nodename,
1115063e25aSGrant Likely 				bool dryrun)
112bbd33931SGrant Likely {
113dfbd4c6eSGavin Shan 	struct property *pp, **pprev = NULL;
114dfbd4c6eSGavin Shan 	int cur;
115dfbd4c6eSGavin Shan 	bool has_name = false;
116dfbd4c6eSGavin Shan 
117dfbd4c6eSGavin Shan 	pprev = &np->properties;
118dfbd4c6eSGavin Shan 	for (cur = fdt_first_property_offset(blob, offset);
119dfbd4c6eSGavin Shan 	     cur >= 0;
120dfbd4c6eSGavin Shan 	     cur = fdt_next_property_offset(blob, cur)) {
121dfbd4c6eSGavin Shan 		const __be32 *val;
122dfbd4c6eSGavin Shan 		const char *pname;
123dfbd4c6eSGavin Shan 		u32 sz;
124dfbd4c6eSGavin Shan 
125dfbd4c6eSGavin Shan 		val = fdt_getprop_by_offset(blob, cur, &pname, &sz);
126dfbd4c6eSGavin Shan 		if (!val) {
127606ad42aSRob Herring 			pr_warn("Cannot locate property at 0x%x\n", cur);
128dfbd4c6eSGavin Shan 			continue;
129dfbd4c6eSGavin Shan 		}
130dfbd4c6eSGavin Shan 
131dfbd4c6eSGavin Shan 		if (!pname) {
132606ad42aSRob Herring 			pr_warn("Cannot find property name at 0x%x\n", cur);
133dfbd4c6eSGavin Shan 			continue;
134dfbd4c6eSGavin Shan 		}
135dfbd4c6eSGavin Shan 
136dfbd4c6eSGavin Shan 		if (!strcmp(pname, "name"))
137dfbd4c6eSGavin Shan 			has_name = true;
138dfbd4c6eSGavin Shan 
139dfbd4c6eSGavin Shan 		pp = unflatten_dt_alloc(mem, sizeof(struct property),
140dfbd4c6eSGavin Shan 					__alignof__(struct property));
141dfbd4c6eSGavin Shan 		if (dryrun)
142dfbd4c6eSGavin Shan 			continue;
143dfbd4c6eSGavin Shan 
144dfbd4c6eSGavin Shan 		/* We accept flattened tree phandles either in
145dfbd4c6eSGavin Shan 		 * ePAPR-style "phandle" properties, or the
146dfbd4c6eSGavin Shan 		 * legacy "linux,phandle" properties.  If both
147dfbd4c6eSGavin Shan 		 * appear and have different values, things
148dfbd4c6eSGavin Shan 		 * will get weird. Don't do that.
149dfbd4c6eSGavin Shan 		 */
150dfbd4c6eSGavin Shan 		if (!strcmp(pname, "phandle") ||
151dfbd4c6eSGavin Shan 		    !strcmp(pname, "linux,phandle")) {
152dfbd4c6eSGavin Shan 			if (!np->phandle)
153dfbd4c6eSGavin Shan 				np->phandle = be32_to_cpup(val);
154dfbd4c6eSGavin Shan 		}
155dfbd4c6eSGavin Shan 
156dfbd4c6eSGavin Shan 		/* And we process the "ibm,phandle" property
157dfbd4c6eSGavin Shan 		 * used in pSeries dynamic device tree
158dfbd4c6eSGavin Shan 		 * stuff
159dfbd4c6eSGavin Shan 		 */
160dfbd4c6eSGavin Shan 		if (!strcmp(pname, "ibm,phandle"))
161dfbd4c6eSGavin Shan 			np->phandle = be32_to_cpup(val);
162dfbd4c6eSGavin Shan 
163dfbd4c6eSGavin Shan 		pp->name   = (char *)pname;
164dfbd4c6eSGavin Shan 		pp->length = sz;
165dfbd4c6eSGavin Shan 		pp->value  = (__be32 *)val;
166dfbd4c6eSGavin Shan 		*pprev     = pp;
167dfbd4c6eSGavin Shan 		pprev      = &pp->next;
168dfbd4c6eSGavin Shan 	}
169dfbd4c6eSGavin Shan 
170dfbd4c6eSGavin Shan 	/* With version 0x10 we may not have the name property,
171dfbd4c6eSGavin Shan 	 * recreate it here from the unit name if absent
172dfbd4c6eSGavin Shan 	 */
173dfbd4c6eSGavin Shan 	if (!has_name) {
174dfbd4c6eSGavin Shan 		const char *p = nodename, *ps = p, *pa = NULL;
175dfbd4c6eSGavin Shan 		int len;
176dfbd4c6eSGavin Shan 
177dfbd4c6eSGavin Shan 		while (*p) {
178dfbd4c6eSGavin Shan 			if ((*p) == '@')
179dfbd4c6eSGavin Shan 				pa = p;
180dfbd4c6eSGavin Shan 			else if ((*p) == '/')
181dfbd4c6eSGavin Shan 				ps = p + 1;
182dfbd4c6eSGavin Shan 			p++;
183dfbd4c6eSGavin Shan 		}
184dfbd4c6eSGavin Shan 
185dfbd4c6eSGavin Shan 		if (pa < ps)
186dfbd4c6eSGavin Shan 			pa = p;
187dfbd4c6eSGavin Shan 		len = (pa - ps) + 1;
188dfbd4c6eSGavin Shan 		pp = unflatten_dt_alloc(mem, sizeof(struct property) + len,
189dfbd4c6eSGavin Shan 					__alignof__(struct property));
190dfbd4c6eSGavin Shan 		if (!dryrun) {
191dfbd4c6eSGavin Shan 			pp->name   = "name";
192dfbd4c6eSGavin Shan 			pp->length = len;
193dfbd4c6eSGavin Shan 			pp->value  = pp + 1;
194dfbd4c6eSGavin Shan 			*pprev     = pp;
195dfbd4c6eSGavin Shan 			pprev      = &pp->next;
196dfbd4c6eSGavin Shan 			memcpy(pp->value, ps, len - 1);
197dfbd4c6eSGavin Shan 			((char *)pp->value)[len - 1] = 0;
198dfbd4c6eSGavin Shan 			pr_debug("fixed up name for %s -> %s\n",
199dfbd4c6eSGavin Shan 				 nodename, (char *)pp->value);
200dfbd4c6eSGavin Shan 		}
201dfbd4c6eSGavin Shan 	}
202dfbd4c6eSGavin Shan 
203dfbd4c6eSGavin Shan 	if (!dryrun)
204dfbd4c6eSGavin Shan 		*pprev = NULL;
205dfbd4c6eSGavin Shan }
206dfbd4c6eSGavin Shan 
207a7e4cfb0SRob Herring static bool populate_node(const void *blob,
208dfbd4c6eSGavin Shan 			  int offset,
209dfbd4c6eSGavin Shan 			  void **mem,
210dfbd4c6eSGavin Shan 			  struct device_node *dad,
211dfbd4c6eSGavin Shan 			  struct device_node **pnp,
212dfbd4c6eSGavin Shan 			  bool dryrun)
213dfbd4c6eSGavin Shan {
214bbd33931SGrant Likely 	struct device_node *np;
215e6a6928cSRob Herring 	const char *pathp;
216bbd33931SGrant Likely 	unsigned int l, allocl;
217bbd33931SGrant Likely 
218dfbd4c6eSGavin Shan 	pathp = fdt_get_name(blob, offset, &l);
219dfbd4c6eSGavin Shan 	if (!pathp) {
220dfbd4c6eSGavin Shan 		*pnp = NULL;
221a7e4cfb0SRob Herring 		return false;
222dfbd4c6eSGavin Shan 	}
223e6a6928cSRob Herring 
22405f4647bSRicky Liang 	allocl = ++l;
225bbd33931SGrant Likely 
226dfbd4c6eSGavin Shan 	np = unflatten_dt_alloc(mem, sizeof(struct device_node) + allocl,
227bbd33931SGrant Likely 				__alignof__(struct device_node));
2285063e25aSGrant Likely 	if (!dryrun) {
229c22618a1SGrant Likely 		char *fn;
2300829f6d1SPantelis Antoniou 		of_node_init(np);
231c22618a1SGrant Likely 		np->full_name = fn = ((char *)np) + sizeof(*np);
232a7e4cfb0SRob Herring 
233bbd33931SGrant Likely 		memcpy(fn, pathp, l);
234c22618a1SGrant Likely 
235bbd33931SGrant Likely 		if (dad != NULL) {
236bbd33931SGrant Likely 			np->parent = dad;
23770161ff3SGrant Likely 			np->sibling = dad->child;
238bbd33931SGrant Likely 			dad->child = np;
239bbd33931SGrant Likely 		}
240bbd33931SGrant Likely 	}
241bbd33931SGrant Likely 
242dfbd4c6eSGavin Shan 	populate_properties(blob, offset, mem, np, pathp, dryrun);
2435063e25aSGrant Likely 	if (!dryrun) {
244bbd33931SGrant Likely 		np->name = of_get_property(np, "name", NULL);
245bbd33931SGrant Likely 		if (!np->name)
246bbd33931SGrant Likely 			np->name = "<NULL>";
247bbd33931SGrant Likely 	}
248e6a6928cSRob Herring 
249dfbd4c6eSGavin Shan 	*pnp = np;
250a7e4cfb0SRob Herring 	return true;
251dfbd4c6eSGavin Shan }
252dfbd4c6eSGavin Shan 
25350800082SGavin Shan static void reverse_nodes(struct device_node *parent)
25450800082SGavin Shan {
25550800082SGavin Shan 	struct device_node *child, *next;
25650800082SGavin Shan 
25750800082SGavin Shan 	/* In-depth first */
25850800082SGavin Shan 	child = parent->child;
25950800082SGavin Shan 	while (child) {
26050800082SGavin Shan 		reverse_nodes(child);
26150800082SGavin Shan 
26250800082SGavin Shan 		child = child->sibling;
26350800082SGavin Shan 	}
26450800082SGavin Shan 
26550800082SGavin Shan 	/* Reverse the nodes in the child list */
26650800082SGavin Shan 	child = parent->child;
26750800082SGavin Shan 	parent->child = NULL;
26850800082SGavin Shan 	while (child) {
26950800082SGavin Shan 		next = child->sibling;
27050800082SGavin Shan 
27150800082SGavin Shan 		child->sibling = parent->child;
27250800082SGavin Shan 		parent->child = child;
27350800082SGavin Shan 		child = next;
27450800082SGavin Shan 	}
27550800082SGavin Shan }
27650800082SGavin Shan 
277dfbd4c6eSGavin Shan /**
278947c82cbSGavin Shan  * unflatten_dt_nodes - Alloc and populate a device_node from the flat tree
279dfbd4c6eSGavin Shan  * @blob: The parent device tree blob
280dfbd4c6eSGavin Shan  * @mem: Memory chunk to use for allocating device nodes and properties
281dfbd4c6eSGavin Shan  * @dad: Parent struct device_node
282dfbd4c6eSGavin Shan  * @nodepp: The device_node tree created by the call
28350800082SGavin Shan  *
28450800082SGavin Shan  * It returns the size of unflattened device tree or error code
285dfbd4c6eSGavin Shan  */
286947c82cbSGavin Shan static int unflatten_dt_nodes(const void *blob,
287dfbd4c6eSGavin Shan 			      void *mem,
288dfbd4c6eSGavin Shan 			      struct device_node *dad,
28950800082SGavin Shan 			      struct device_node **nodepp)
290dfbd4c6eSGavin Shan {
29150800082SGavin Shan 	struct device_node *root;
2928c237cd0SGavin Shan 	int offset = 0, depth = 0, initial_depth = 0;
29350800082SGavin Shan #define FDT_MAX_DEPTH	64
29450800082SGavin Shan 	struct device_node *nps[FDT_MAX_DEPTH];
29550800082SGavin Shan 	void *base = mem;
29650800082SGavin Shan 	bool dryrun = !base;
297dfbd4c6eSGavin Shan 
29850800082SGavin Shan 	if (nodepp)
29950800082SGavin Shan 		*nodepp = NULL;
300dfbd4c6eSGavin Shan 
3018c237cd0SGavin Shan 	/*
3028c237cd0SGavin Shan 	 * We're unflattening device sub-tree if @dad is valid. There are
3038c237cd0SGavin Shan 	 * possibly multiple nodes in the first level of depth. We need
3048c237cd0SGavin Shan 	 * set @depth to 1 to make fdt_next_node() happy as it bails
3058c237cd0SGavin Shan 	 * immediately when negative @depth is found. Otherwise, the device
3068c237cd0SGavin Shan 	 * nodes except the first one won't be unflattened successfully.
3078c237cd0SGavin Shan 	 */
3088c237cd0SGavin Shan 	if (dad)
3098c237cd0SGavin Shan 		depth = initial_depth = 1;
3108c237cd0SGavin Shan 
31150800082SGavin Shan 	root = dad;
31278c44d91SRhyland Klein 	nps[depth] = dad;
3138c237cd0SGavin Shan 
31450800082SGavin Shan 	for (offset = 0;
3158c237cd0SGavin Shan 	     offset >= 0 && depth >= initial_depth;
31650800082SGavin Shan 	     offset = fdt_next_node(blob, offset, &depth)) {
31750800082SGavin Shan 		if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH))
31850800082SGavin Shan 			continue;
319e6a6928cSRob Herring 
32077ea8a68SRob Herring 		if (!IS_ENABLED(CONFIG_OF_KOBJ) &&
32177ea8a68SRob Herring 		    !of_fdt_device_is_available(blob, offset))
32277ea8a68SRob Herring 			continue;
32377ea8a68SRob Herring 
324a7e4cfb0SRob Herring 		if (!populate_node(blob, offset, &mem, nps[depth],
325a7e4cfb0SRob Herring 				   &nps[depth+1], dryrun))
32650800082SGavin Shan 			return mem - base;
32750800082SGavin Shan 
32850800082SGavin Shan 		if (!dryrun && nodepp && !*nodepp)
32978c44d91SRhyland Klein 			*nodepp = nps[depth+1];
33050800082SGavin Shan 		if (!dryrun && !root)
33178c44d91SRhyland Klein 			root = nps[depth+1];
33250800082SGavin Shan 	}
33350800082SGavin Shan 
33450800082SGavin Shan 	if (offset < 0 && offset != -FDT_ERR_NOTFOUND) {
335606ad42aSRob Herring 		pr_err("Error %d processing FDT\n", offset);
33650800082SGavin Shan 		return -EINVAL;
33750800082SGavin Shan 	}
338e6a6928cSRob Herring 
33970161ff3SGrant Likely 	/*
34070161ff3SGrant Likely 	 * Reverse the child list. Some drivers assumes node order matches .dts
34170161ff3SGrant Likely 	 * node order
34270161ff3SGrant Likely 	 */
34350800082SGavin Shan 	if (!dryrun)
34450800082SGavin Shan 		reverse_nodes(root);
34570161ff3SGrant Likely 
34650800082SGavin Shan 	return mem - base;
347bbd33931SGrant Likely }
34841f88009SGrant Likely 
349fe140423SStephen Neuendorffer /**
350fe140423SStephen Neuendorffer  * __unflatten_device_tree - create tree of device_nodes from flat blob
351fe140423SStephen Neuendorffer  *
352fe140423SStephen Neuendorffer  * unflattens a device-tree, creating the
353fe140423SStephen Neuendorffer  * tree of struct device_node. It also fills the "name" and "type"
354fe140423SStephen Neuendorffer  * pointers of the nodes so the normal device-tree walking functions
355fe140423SStephen Neuendorffer  * can be used.
356fe140423SStephen Neuendorffer  * @blob: The blob to expand
357c4263233SGavin Shan  * @dad: Parent device node
358fe140423SStephen Neuendorffer  * @mynodes: The device_node tree created by the call
359fe140423SStephen Neuendorffer  * @dt_alloc: An allocator that provides a virtual address to memory
360fe140423SStephen Neuendorffer  * for the resulting tree
361f5d2da67SStephen Boyd  * @detached: if true set OF_DETACHED on @mynodes
36283262418SGavin Shan  *
36383262418SGavin Shan  * Returns NULL on failure or the memory chunk containing the unflattened
36483262418SGavin Shan  * device tree on success.
365fe140423SStephen Neuendorffer  */
36681d0848fSFrank Rowand void *__unflatten_device_tree(const void *blob,
367c4263233SGavin Shan 			      struct device_node *dad,
368fe140423SStephen Neuendorffer 			      struct device_node **mynodes,
3691d1bde55SMichal Suchanek 			      void *(*dt_alloc)(u64 size, u64 align),
3701d1bde55SMichal Suchanek 			      bool detached)
371fe140423SStephen Neuendorffer {
37250800082SGavin Shan 	int size;
373e6a6928cSRob Herring 	void *mem;
374fe140423SStephen Neuendorffer 
375fe140423SStephen Neuendorffer 	pr_debug(" -> unflatten_device_tree()\n");
376fe140423SStephen Neuendorffer 
377fe140423SStephen Neuendorffer 	if (!blob) {
378fe140423SStephen Neuendorffer 		pr_debug("No device tree pointer\n");
37983262418SGavin Shan 		return NULL;
380fe140423SStephen Neuendorffer 	}
381fe140423SStephen Neuendorffer 
382fe140423SStephen Neuendorffer 	pr_debug("Unflattening device tree:\n");
383c972de14SRob Herring 	pr_debug("magic: %08x\n", fdt_magic(blob));
384c972de14SRob Herring 	pr_debug("size: %08x\n", fdt_totalsize(blob));
385c972de14SRob Herring 	pr_debug("version: %08x\n", fdt_version(blob));
386fe140423SStephen Neuendorffer 
387c972de14SRob Herring 	if (fdt_check_header(blob)) {
388fe140423SStephen Neuendorffer 		pr_err("Invalid device tree blob header\n");
38983262418SGavin Shan 		return NULL;
390fe140423SStephen Neuendorffer 	}
391fe140423SStephen Neuendorffer 
392fe140423SStephen Neuendorffer 	/* First pass, scan for size */
393c4263233SGavin Shan 	size = unflatten_dt_nodes(blob, NULL, dad, NULL);
39450800082SGavin Shan 	if (size < 0)
39583262418SGavin Shan 		return NULL;
396fe140423SStephen Neuendorffer 
39750800082SGavin Shan 	size = ALIGN(size, 4);
39850800082SGavin Shan 	pr_debug("  size is %d, allocating...\n", size);
399fe140423SStephen Neuendorffer 
400fe140423SStephen Neuendorffer 	/* Allocate memory for the expanded device tree */
40144856819SGrant Likely 	mem = dt_alloc(size + 4, __alignof__(struct device_node));
40249e67dd1SJohan Hovold 	if (!mem)
40349e67dd1SJohan Hovold 		return NULL;
40449e67dd1SJohan Hovold 
40544856819SGrant Likely 	memset(mem, 0, size);
406fe140423SStephen Neuendorffer 
40744856819SGrant Likely 	*(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef);
4089e401275SWladislav Wiebe 
40944856819SGrant Likely 	pr_debug("  unflattening %p...\n", mem);
410fe140423SStephen Neuendorffer 
411fe140423SStephen Neuendorffer 	/* Second pass, do actual unflattening */
412c4263233SGavin Shan 	unflatten_dt_nodes(blob, mem, dad, mynodes);
41344856819SGrant Likely 	if (be32_to_cpup(mem + size) != 0xdeadbeef)
414fe140423SStephen Neuendorffer 		pr_warning("End of tree marker overwritten: %08x\n",
41544856819SGrant Likely 			   be32_to_cpup(mem + size));
416fe140423SStephen Neuendorffer 
41789c67752SGavin Shan 	if (detached && mynodes) {
4181d1bde55SMichal Suchanek 		of_node_set_flag(*mynodes, OF_DETACHED);
4191d1bde55SMichal Suchanek 		pr_debug("unflattened tree is detached\n");
4201d1bde55SMichal Suchanek 	}
4211d1bde55SMichal Suchanek 
422fe140423SStephen Neuendorffer 	pr_debug(" <- unflatten_device_tree()\n");
42383262418SGavin Shan 	return mem;
424fe140423SStephen Neuendorffer }
425fe140423SStephen Neuendorffer 
426fe140423SStephen Neuendorffer static void *kernel_tree_alloc(u64 size, u64 align)
427fe140423SStephen Neuendorffer {
428fe140423SStephen Neuendorffer 	return kzalloc(size, GFP_KERNEL);
429fe140423SStephen Neuendorffer }
430fe140423SStephen Neuendorffer 
431f8062386SGuenter Roeck static DEFINE_MUTEX(of_fdt_unflatten_mutex);
432f8062386SGuenter Roeck 
433fe140423SStephen Neuendorffer /**
434fe140423SStephen Neuendorffer  * of_fdt_unflatten_tree - create tree of device_nodes from flat blob
435c4263233SGavin Shan  * @blob: Flat device tree blob
436c4263233SGavin Shan  * @dad: Parent device node
437c4263233SGavin Shan  * @mynodes: The device tree created by the call
438fe140423SStephen Neuendorffer  *
439fe140423SStephen Neuendorffer  * unflattens the device-tree passed by the firmware, creating the
440fe140423SStephen Neuendorffer  * tree of struct device_node. It also fills the "name" and "type"
441fe140423SStephen Neuendorffer  * pointers of the nodes so the normal device-tree walking functions
442fe140423SStephen Neuendorffer  * can be used.
44383262418SGavin Shan  *
44483262418SGavin Shan  * Returns NULL on failure or the memory chunk containing the unflattened
44583262418SGavin Shan  * device tree on success.
446fe140423SStephen Neuendorffer  */
44783262418SGavin Shan void *of_fdt_unflatten_tree(const unsigned long *blob,
448c4263233SGavin Shan 			    struct device_node *dad,
449fe140423SStephen Neuendorffer 			    struct device_node **mynodes)
450fe140423SStephen Neuendorffer {
45183262418SGavin Shan 	void *mem;
45283262418SGavin Shan 
453f8062386SGuenter Roeck 	mutex_lock(&of_fdt_unflatten_mutex);
4541d1bde55SMichal Suchanek 	mem = __unflatten_device_tree(blob, dad, mynodes, &kernel_tree_alloc,
4551d1bde55SMichal Suchanek 				      true);
456f8062386SGuenter Roeck 	mutex_unlock(&of_fdt_unflatten_mutex);
45783262418SGavin Shan 
45883262418SGavin Shan 	return mem;
459fe140423SStephen Neuendorffer }
460fe140423SStephen Neuendorffer EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
461fe140423SStephen Neuendorffer 
46257d00ecfSStephen Neuendorffer /* Everything below here references initial_boot_params directly. */
46357d00ecfSStephen Neuendorffer int __initdata dt_root_addr_cells;
46457d00ecfSStephen Neuendorffer int __initdata dt_root_size_cells;
46557d00ecfSStephen Neuendorffer 
4667c71650fSStephen Boyd void *initial_boot_params __ro_after_init;
46757d00ecfSStephen Neuendorffer 
46857d00ecfSStephen Neuendorffer #ifdef CONFIG_OF_EARLY_FLATTREE
46957d00ecfSStephen Neuendorffer 
47008d53aa5SArd Biesheuvel static u32 of_fdt_crc32;
47108d53aa5SArd Biesheuvel 
47257d00ecfSStephen Neuendorffer /**
473e8d9d1f5SMarek Szyprowski  * res_mem_reserve_reg() - reserve all memory described in 'reg' property
474e8d9d1f5SMarek Szyprowski  */
475e8d9d1f5SMarek Szyprowski static int __init __reserved_mem_reserve_reg(unsigned long node,
476e8d9d1f5SMarek Szyprowski 					     const char *uname)
477e8d9d1f5SMarek Szyprowski {
478e8d9d1f5SMarek Szyprowski 	int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
479e8d9d1f5SMarek Szyprowski 	phys_addr_t base, size;
4809d0c4dfeSRob Herring 	int len;
4819d0c4dfeSRob Herring 	const __be32 *prop;
4825c68b823SMasahiro Yamada 	int first = 1;
4835c68b823SMasahiro Yamada 	bool nomap;
484e8d9d1f5SMarek Szyprowski 
485e8d9d1f5SMarek Szyprowski 	prop = of_get_flat_dt_prop(node, "reg", &len);
486e8d9d1f5SMarek Szyprowski 	if (!prop)
487e8d9d1f5SMarek Szyprowski 		return -ENOENT;
488e8d9d1f5SMarek Szyprowski 
489e8d9d1f5SMarek Szyprowski 	if (len && len % t_len != 0) {
490e8d9d1f5SMarek Szyprowski 		pr_err("Reserved memory: invalid reg property in '%s', skipping node.\n",
491e8d9d1f5SMarek Szyprowski 		       uname);
492e8d9d1f5SMarek Szyprowski 		return -EINVAL;
493e8d9d1f5SMarek Szyprowski 	}
494e8d9d1f5SMarek Szyprowski 
495e8d9d1f5SMarek Szyprowski 	nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL;
496e8d9d1f5SMarek Szyprowski 
497e8d9d1f5SMarek Szyprowski 	while (len >= t_len) {
498e8d9d1f5SMarek Szyprowski 		base = dt_mem_next_cell(dt_root_addr_cells, &prop);
499e8d9d1f5SMarek Szyprowski 		size = dt_mem_next_cell(dt_root_size_cells, &prop);
500e8d9d1f5SMarek Szyprowski 
501b5f2a8c0SAl Cooper 		if (size &&
502e8d9d1f5SMarek Szyprowski 		    early_init_dt_reserve_memory_arch(base, size, nomap) == 0)
503e8d9d1f5SMarek Szyprowski 			pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n",
504e8d9d1f5SMarek Szyprowski 				uname, &base, (unsigned long)size / SZ_1M);
505e8d9d1f5SMarek Szyprowski 		else
506e8d9d1f5SMarek Szyprowski 			pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %ld MiB\n",
507e8d9d1f5SMarek Szyprowski 				uname, &base, (unsigned long)size / SZ_1M);
508e8d9d1f5SMarek Szyprowski 
509e8d9d1f5SMarek Szyprowski 		len -= t_len;
5103f0c8206SMarek Szyprowski 		if (first) {
5113f0c8206SMarek Szyprowski 			fdt_reserved_mem_save_node(node, uname, base, size);
5123f0c8206SMarek Szyprowski 			first = 0;
5133f0c8206SMarek Szyprowski 		}
514e8d9d1f5SMarek Szyprowski 	}
515e8d9d1f5SMarek Szyprowski 	return 0;
516e8d9d1f5SMarek Szyprowski }
517e8d9d1f5SMarek Szyprowski 
518e8d9d1f5SMarek Szyprowski /**
519e8d9d1f5SMarek Szyprowski  * __reserved_mem_check_root() - check if #size-cells, #address-cells provided
520e8d9d1f5SMarek Szyprowski  * in /reserved-memory matches the values supported by the current implementation,
521e8d9d1f5SMarek Szyprowski  * also check if ranges property has been provided
522e8d9d1f5SMarek Szyprowski  */
5235b624118SXiubo Li static int __init __reserved_mem_check_root(unsigned long node)
524e8d9d1f5SMarek Szyprowski {
5259d0c4dfeSRob Herring 	const __be32 *prop;
526e8d9d1f5SMarek Szyprowski 
527e8d9d1f5SMarek Szyprowski 	prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
528e8d9d1f5SMarek Szyprowski 	if (!prop || be32_to_cpup(prop) != dt_root_size_cells)
529e8d9d1f5SMarek Szyprowski 		return -EINVAL;
530e8d9d1f5SMarek Szyprowski 
531e8d9d1f5SMarek Szyprowski 	prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
532e8d9d1f5SMarek Szyprowski 	if (!prop || be32_to_cpup(prop) != dt_root_addr_cells)
533e8d9d1f5SMarek Szyprowski 		return -EINVAL;
534e8d9d1f5SMarek Szyprowski 
535e8d9d1f5SMarek Szyprowski 	prop = of_get_flat_dt_prop(node, "ranges", NULL);
536e8d9d1f5SMarek Szyprowski 	if (!prop)
537e8d9d1f5SMarek Szyprowski 		return -EINVAL;
538e8d9d1f5SMarek Szyprowski 	return 0;
539e8d9d1f5SMarek Szyprowski }
540e8d9d1f5SMarek Szyprowski 
541e8d9d1f5SMarek Szyprowski /**
542e8d9d1f5SMarek Szyprowski  * fdt_scan_reserved_mem() - scan a single FDT node for reserved memory
543e8d9d1f5SMarek Szyprowski  */
544e8d9d1f5SMarek Szyprowski static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname,
545e8d9d1f5SMarek Szyprowski 					  int depth, void *data)
546e8d9d1f5SMarek Szyprowski {
547e8d9d1f5SMarek Szyprowski 	static int found;
5483f0c8206SMarek Szyprowski 	int err;
549e8d9d1f5SMarek Szyprowski 
550e8d9d1f5SMarek Szyprowski 	if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) {
551e8d9d1f5SMarek Szyprowski 		if (__reserved_mem_check_root(node) != 0) {
552e8d9d1f5SMarek Szyprowski 			pr_err("Reserved memory: unsupported node format, ignoring\n");
553e8d9d1f5SMarek Szyprowski 			/* break scan */
554e8d9d1f5SMarek Szyprowski 			return 1;
555e8d9d1f5SMarek Szyprowski 		}
556e8d9d1f5SMarek Szyprowski 		found = 1;
557e8d9d1f5SMarek Szyprowski 		/* scan next node */
558e8d9d1f5SMarek Szyprowski 		return 0;
559e8d9d1f5SMarek Szyprowski 	} else if (!found) {
560e8d9d1f5SMarek Szyprowski 		/* scan next node */
561e8d9d1f5SMarek Szyprowski 		return 0;
562e8d9d1f5SMarek Szyprowski 	} else if (found && depth < 2) {
563e8d9d1f5SMarek Szyprowski 		/* scanning of /reserved-memory has been finished */
564e8d9d1f5SMarek Szyprowski 		return 1;
565e8d9d1f5SMarek Szyprowski 	}
566e8d9d1f5SMarek Szyprowski 
567ecc8a96eSRob Herring 	if (!of_fdt_device_is_available(initial_boot_params, node))
568e8d9d1f5SMarek Szyprowski 		return 0;
569e8d9d1f5SMarek Szyprowski 
5703f0c8206SMarek Szyprowski 	err = __reserved_mem_reserve_reg(node, uname);
5713f0c8206SMarek Szyprowski 	if (err == -ENOENT && of_get_flat_dt_prop(node, "size", NULL))
5723f0c8206SMarek Szyprowski 		fdt_reserved_mem_save_node(node, uname, 0, 0);
573e8d9d1f5SMarek Szyprowski 
574e8d9d1f5SMarek Szyprowski 	/* scan next node */
575e8d9d1f5SMarek Szyprowski 	return 0;
576e8d9d1f5SMarek Szyprowski }
577e8d9d1f5SMarek Szyprowski 
578e8d9d1f5SMarek Szyprowski /**
579e8d9d1f5SMarek Szyprowski  * early_init_fdt_scan_reserved_mem() - create reserved memory regions
580e8d9d1f5SMarek Szyprowski  *
581e8d9d1f5SMarek Szyprowski  * This function grabs memory from early allocator for device exclusive use
582e8d9d1f5SMarek Szyprowski  * defined in device tree structures. It should be called by arch specific code
583e8d9d1f5SMarek Szyprowski  * once the early allocator (i.e. memblock) has been fully activated.
584e8d9d1f5SMarek Szyprowski  */
585e8d9d1f5SMarek Szyprowski void __init early_init_fdt_scan_reserved_mem(void)
586e8d9d1f5SMarek Szyprowski {
587d1552ce4SRob Herring 	int n;
588d1552ce4SRob Herring 	u64 base, size;
589d1552ce4SRob Herring 
5902040b527SJosh Cartwright 	if (!initial_boot_params)
5912040b527SJosh Cartwright 		return;
5922040b527SJosh Cartwright 
593d1552ce4SRob Herring 	/* Process header /memreserve/ fields */
594d1552ce4SRob Herring 	for (n = 0; ; n++) {
595d1552ce4SRob Herring 		fdt_get_mem_rsv(initial_boot_params, n, &base, &size);
596d1552ce4SRob Herring 		if (!size)
597d1552ce4SRob Herring 			break;
5985c68b823SMasahiro Yamada 		early_init_dt_reserve_memory_arch(base, size, false);
599d1552ce4SRob Herring 	}
600d1552ce4SRob Herring 
601e8d9d1f5SMarek Szyprowski 	of_scan_flat_dt(__fdt_scan_reserved_mem, NULL);
6023f0c8206SMarek Szyprowski 	fdt_init_reserved_mem();
603e8d9d1f5SMarek Szyprowski }
604e8d9d1f5SMarek Szyprowski 
605e8d9d1f5SMarek Szyprowski /**
60624bbd929SArd Biesheuvel  * early_init_fdt_reserve_self() - reserve the memory used by the FDT blob
60724bbd929SArd Biesheuvel  */
60824bbd929SArd Biesheuvel void __init early_init_fdt_reserve_self(void)
60924bbd929SArd Biesheuvel {
61024bbd929SArd Biesheuvel 	if (!initial_boot_params)
61124bbd929SArd Biesheuvel 		return;
61224bbd929SArd Biesheuvel 
61324bbd929SArd Biesheuvel 	/* Reserve the dtb region */
61424bbd929SArd Biesheuvel 	early_init_dt_reserve_memory_arch(__pa(initial_boot_params),
61524bbd929SArd Biesheuvel 					  fdt_totalsize(initial_boot_params),
6165c68b823SMasahiro Yamada 					  false);
61724bbd929SArd Biesheuvel }
61824bbd929SArd Biesheuvel 
61924bbd929SArd Biesheuvel /**
62057d00ecfSStephen Neuendorffer  * of_scan_flat_dt - scan flattened tree blob and call callback on each.
62157d00ecfSStephen Neuendorffer  * @it: callback function
62257d00ecfSStephen Neuendorffer  * @data: context data pointer
62357d00ecfSStephen Neuendorffer  *
62457d00ecfSStephen Neuendorffer  * This function is used to scan the flattened device-tree, it is
62557d00ecfSStephen Neuendorffer  * used to extract the memory information at boot before we can
62657d00ecfSStephen Neuendorffer  * unflatten the tree
62757d00ecfSStephen Neuendorffer  */
62857d00ecfSStephen Neuendorffer int __init of_scan_flat_dt(int (*it)(unsigned long node,
62957d00ecfSStephen Neuendorffer 				     const char *uname, int depth,
63057d00ecfSStephen Neuendorffer 				     void *data),
63157d00ecfSStephen Neuendorffer 			   void *data)
63257d00ecfSStephen Neuendorffer {
633e6a6928cSRob Herring 	const void *blob = initial_boot_params;
634e55b0829SFabio Estevam 	const char *pathp;
635e6a6928cSRob Herring 	int offset, rc = 0, depth = -1;
63657d00ecfSStephen Neuendorffer 
6373ec75441STobias Wolf 	if (!blob)
6383ec75441STobias Wolf 		return 0;
6393ec75441STobias Wolf 
640e6a6928cSRob Herring 	for (offset = fdt_next_node(blob, -1, &depth);
641e6a6928cSRob Herring 	     offset >= 0 && depth >= 0 && !rc;
642e6a6928cSRob Herring 	     offset = fdt_next_node(blob, offset, &depth)) {
643e6a6928cSRob Herring 
644e6a6928cSRob Herring 		pathp = fdt_get_name(blob, offset, NULL);
645375da3a7SAndy Shevchenko 		if (*pathp == '/')
646375da3a7SAndy Shevchenko 			pathp = kbasename(pathp);
647e6a6928cSRob Herring 		rc = it(offset, pathp, depth, data);
648e6a6928cSRob Herring 	}
64957d00ecfSStephen Neuendorffer 	return rc;
65057d00ecfSStephen Neuendorffer }
65157d00ecfSStephen Neuendorffer 
65257d00ecfSStephen Neuendorffer /**
653ea47dd19SNicholas Piggin  * of_scan_flat_dt_subnodes - scan sub-nodes of a node call callback on each.
654ea47dd19SNicholas Piggin  * @it: callback function
655ea47dd19SNicholas Piggin  * @data: context data pointer
656ea47dd19SNicholas Piggin  *
657ea47dd19SNicholas Piggin  * This function is used to scan sub-nodes of a node.
658ea47dd19SNicholas Piggin  */
659ea47dd19SNicholas Piggin int __init of_scan_flat_dt_subnodes(unsigned long parent,
660ea47dd19SNicholas Piggin 				    int (*it)(unsigned long node,
661ea47dd19SNicholas Piggin 					      const char *uname,
662ea47dd19SNicholas Piggin 					      void *data),
663ea47dd19SNicholas Piggin 				    void *data)
664ea47dd19SNicholas Piggin {
665ea47dd19SNicholas Piggin 	const void *blob = initial_boot_params;
666ea47dd19SNicholas Piggin 	int node;
667ea47dd19SNicholas Piggin 
668ea47dd19SNicholas Piggin 	fdt_for_each_subnode(node, blob, parent) {
669ea47dd19SNicholas Piggin 		const char *pathp;
670ea47dd19SNicholas Piggin 		int rc;
671ea47dd19SNicholas Piggin 
672ea47dd19SNicholas Piggin 		pathp = fdt_get_name(blob, node, NULL);
673ea47dd19SNicholas Piggin 		if (*pathp == '/')
674ea47dd19SNicholas Piggin 			pathp = kbasename(pathp);
675ea47dd19SNicholas Piggin 		rc = it(node, pathp, data);
676ea47dd19SNicholas Piggin 		if (rc)
677ea47dd19SNicholas Piggin 			return rc;
678ea47dd19SNicholas Piggin 	}
679ea47dd19SNicholas Piggin 	return 0;
680ea47dd19SNicholas Piggin }
681ea47dd19SNicholas Piggin 
682ea47dd19SNicholas Piggin /**
6839c609868SShannon Zhao  * of_get_flat_dt_subnode_by_name - get the subnode by given name
6849c609868SShannon Zhao  *
6859c609868SShannon Zhao  * @node: the parent node
6869c609868SShannon Zhao  * @uname: the name of subnode
6879c609868SShannon Zhao  * @return offset of the subnode, or -FDT_ERR_NOTFOUND if there is none
6889c609868SShannon Zhao  */
6899c609868SShannon Zhao 
6909b4d2b63SStephen Boyd int __init of_get_flat_dt_subnode_by_name(unsigned long node, const char *uname)
6919c609868SShannon Zhao {
6929c609868SShannon Zhao 	return fdt_subnode_offset(initial_boot_params, node, uname);
6939c609868SShannon Zhao }
6949c609868SShannon Zhao 
6959c609868SShannon Zhao /**
69657d00ecfSStephen Neuendorffer  * of_get_flat_dt_root - find the root node in the flat blob
69757d00ecfSStephen Neuendorffer  */
69857d00ecfSStephen Neuendorffer unsigned long __init of_get_flat_dt_root(void)
69957d00ecfSStephen Neuendorffer {
700e6a6928cSRob Herring 	return 0;
70157d00ecfSStephen Neuendorffer }
70257d00ecfSStephen Neuendorffer 
70357d00ecfSStephen Neuendorffer /**
70457d00ecfSStephen Neuendorffer  * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr
70557d00ecfSStephen Neuendorffer  *
70657d00ecfSStephen Neuendorffer  * This function can be used within scan_flattened_dt callback to get
70757d00ecfSStephen Neuendorffer  * access to properties
70857d00ecfSStephen Neuendorffer  */
7099d0c4dfeSRob Herring const void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
7109d0c4dfeSRob Herring 				       int *size)
71157d00ecfSStephen Neuendorffer {
712e6a6928cSRob Herring 	return fdt_getprop(initial_boot_params, node, name, size);
71357d00ecfSStephen Neuendorffer }
71457d00ecfSStephen Neuendorffer 
71557d00ecfSStephen Neuendorffer /**
7165d9c4e95SKefeng Wang  * of_fdt_is_compatible - Return true if given node from the given blob has
7175d9c4e95SKefeng Wang  * compat in its compatible list
7185d9c4e95SKefeng Wang  * @blob: A device tree blob
7195d9c4e95SKefeng Wang  * @node: node to test
7205d9c4e95SKefeng Wang  * @compat: compatible string to compare with compatible list.
7215d9c4e95SKefeng Wang  *
7225d9c4e95SKefeng Wang  * On match, returns a non-zero value with smaller values returned for more
7235d9c4e95SKefeng Wang  * specific compatible values.
7245d9c4e95SKefeng Wang  */
7255d9c4e95SKefeng Wang static int of_fdt_is_compatible(const void *blob,
7265d9c4e95SKefeng Wang 		      unsigned long node, const char *compat)
7275d9c4e95SKefeng Wang {
7285d9c4e95SKefeng Wang 	const char *cp;
7295d9c4e95SKefeng Wang 	int cplen;
7305d9c4e95SKefeng Wang 	unsigned long l, score = 0;
7315d9c4e95SKefeng Wang 
7325d9c4e95SKefeng Wang 	cp = fdt_getprop(blob, node, "compatible", &cplen);
7335d9c4e95SKefeng Wang 	if (cp == NULL)
7345d9c4e95SKefeng Wang 		return 0;
7355d9c4e95SKefeng Wang 	while (cplen > 0) {
7365d9c4e95SKefeng Wang 		score++;
7375d9c4e95SKefeng Wang 		if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
7385d9c4e95SKefeng Wang 			return score;
7395d9c4e95SKefeng Wang 		l = strlen(cp) + 1;
7405d9c4e95SKefeng Wang 		cp += l;
7415d9c4e95SKefeng Wang 		cplen -= l;
7425d9c4e95SKefeng Wang 	}
7435d9c4e95SKefeng Wang 
7445d9c4e95SKefeng Wang 	return 0;
7455d9c4e95SKefeng Wang }
7465d9c4e95SKefeng Wang 
7475d9c4e95SKefeng Wang /**
74857d00ecfSStephen Neuendorffer  * of_flat_dt_is_compatible - Return true if given node has compat in compatible list
74957d00ecfSStephen Neuendorffer  * @node: node to test
75057d00ecfSStephen Neuendorffer  * @compat: compatible string to compare with compatible list.
75157d00ecfSStephen Neuendorffer  */
75257d00ecfSStephen Neuendorffer int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
75357d00ecfSStephen Neuendorffer {
75457d00ecfSStephen Neuendorffer 	return of_fdt_is_compatible(initial_boot_params, node, compat);
75557d00ecfSStephen Neuendorffer }
75657d00ecfSStephen Neuendorffer 
757a4f740cfSGrant Likely /**
758a4f740cfSGrant Likely  * of_flat_dt_match - Return true if node matches a list of compatible values
759a4f740cfSGrant Likely  */
7609b4d2b63SStephen Boyd static int __init of_flat_dt_match(unsigned long node, const char *const *compat)
761a4f740cfSGrant Likely {
7625d9c4e95SKefeng Wang 	unsigned int tmp, score = 0;
7635d9c4e95SKefeng Wang 
7645d9c4e95SKefeng Wang 	if (!compat)
7655d9c4e95SKefeng Wang 		return 0;
7665d9c4e95SKefeng Wang 
7675d9c4e95SKefeng Wang 	while (*compat) {
7685d9c4e95SKefeng Wang 		tmp = of_fdt_is_compatible(initial_boot_params, node, *compat);
7695d9c4e95SKefeng Wang 		if (tmp && (score == 0 || (tmp < score)))
7705d9c4e95SKefeng Wang 			score = tmp;
7715d9c4e95SKefeng Wang 		compat++;
7725d9c4e95SKefeng Wang 	}
7735d9c4e95SKefeng Wang 
7745d9c4e95SKefeng Wang 	return score;
775a4f740cfSGrant Likely }
776a4f740cfSGrant Likely 
777ea47dd19SNicholas Piggin /**
778ea47dd19SNicholas Piggin  * of_get_flat_dt_prop - Given a node in the flat blob, return the phandle
779ea47dd19SNicholas Piggin  */
780ea47dd19SNicholas Piggin uint32_t __init of_get_flat_dt_phandle(unsigned long node)
781ea47dd19SNicholas Piggin {
782ea47dd19SNicholas Piggin 	return fdt_get_phandle(initial_boot_params, node);
783ea47dd19SNicholas Piggin }
784ea47dd19SNicholas Piggin 
78557d74bcfSMarek Szyprowski struct fdt_scan_status {
78657d74bcfSMarek Szyprowski 	const char *name;
78757d74bcfSMarek Szyprowski 	int namelen;
78857d74bcfSMarek Szyprowski 	int depth;
78957d74bcfSMarek Szyprowski 	int found;
79057d74bcfSMarek Szyprowski 	int (*iterator)(unsigned long node, const char *uname, int depth, void *data);
79157d74bcfSMarek Szyprowski 	void *data;
79257d74bcfSMarek Szyprowski };
79357d74bcfSMarek Szyprowski 
7946a903a25SRob Herring const char * __init of_flat_dt_get_machine_name(void)
7956a903a25SRob Herring {
7966a903a25SRob Herring 	const char *name;
7976a903a25SRob Herring 	unsigned long dt_root = of_get_flat_dt_root();
7986a903a25SRob Herring 
7996a903a25SRob Herring 	name = of_get_flat_dt_prop(dt_root, "model", NULL);
8006a903a25SRob Herring 	if (!name)
8016a903a25SRob Herring 		name = of_get_flat_dt_prop(dt_root, "compatible", NULL);
8026a903a25SRob Herring 	return name;
8036a903a25SRob Herring }
8046a903a25SRob Herring 
8056a903a25SRob Herring /**
8066a903a25SRob Herring  * of_flat_dt_match_machine - Iterate match tables to find matching machine.
8076a903a25SRob Herring  *
8086a903a25SRob Herring  * @default_match: A machine specific ptr to return in case of no match.
8096a903a25SRob Herring  * @get_next_compat: callback function to return next compatible match table.
8106a903a25SRob Herring  *
8116a903a25SRob Herring  * Iterate through machine match tables to find the best match for the machine
8126a903a25SRob Herring  * compatible string in the FDT.
8136a903a25SRob Herring  */
8146a903a25SRob Herring const void * __init of_flat_dt_match_machine(const void *default_match,
8156a903a25SRob Herring 		const void * (*get_next_compat)(const char * const**))
8166a903a25SRob Herring {
8176a903a25SRob Herring 	const void *data = NULL;
8186a903a25SRob Herring 	const void *best_data = default_match;
8196a903a25SRob Herring 	const char *const *compat;
8206a903a25SRob Herring 	unsigned long dt_root;
8216a903a25SRob Herring 	unsigned int best_score = ~1, score = 0;
8226a903a25SRob Herring 
8236a903a25SRob Herring 	dt_root = of_get_flat_dt_root();
8246a903a25SRob Herring 	while ((data = get_next_compat(&compat))) {
8256a903a25SRob Herring 		score = of_flat_dt_match(dt_root, compat);
8266a903a25SRob Herring 		if (score > 0 && score < best_score) {
8276a903a25SRob Herring 			best_data = data;
8286a903a25SRob Herring 			best_score = score;
8296a903a25SRob Herring 		}
8306a903a25SRob Herring 	}
8316a903a25SRob Herring 	if (!best_data) {
8326a903a25SRob Herring 		const char *prop;
8339d0c4dfeSRob Herring 		int size;
8346a903a25SRob Herring 
8356a903a25SRob Herring 		pr_err("\n unrecognized device tree list:\n[ ");
8366a903a25SRob Herring 
8376a903a25SRob Herring 		prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
8386a903a25SRob Herring 		if (prop) {
8396a903a25SRob Herring 			while (size > 0) {
8406a903a25SRob Herring 				printk("'%s' ", prop);
8416a903a25SRob Herring 				size -= strlen(prop) + 1;
8426a903a25SRob Herring 				prop += strlen(prop) + 1;
8436a903a25SRob Herring 			}
8446a903a25SRob Herring 		}
8456a903a25SRob Herring 		printk("]\n\n");
8466a903a25SRob Herring 		return NULL;
8476a903a25SRob Herring 	}
8486a903a25SRob Herring 
8496a903a25SRob Herring 	pr_info("Machine model: %s\n", of_flat_dt_get_machine_name());
8506a903a25SRob Herring 
8516a903a25SRob Herring 	return best_data;
8526a903a25SRob Herring }
8536a903a25SRob Herring 
854f7b3a835SGrant Likely #ifdef CONFIG_BLK_DEV_INITRD
855369bc9abSArd Biesheuvel static void __early_init_dt_declare_initrd(unsigned long start,
856369bc9abSArd Biesheuvel 					   unsigned long end)
857369bc9abSArd Biesheuvel {
858cdbc848bSFlorian Fainelli 	/* ARM64 would cause a BUG to occur here when CONFIG_DEBUG_VM is
859cdbc848bSFlorian Fainelli 	 * enabled since __va() is called too early. ARM64 does make use
860cdbc848bSFlorian Fainelli 	 * of phys_initrd_start/phys_initrd_size so we can skip this
861cdbc848bSFlorian Fainelli 	 * conversion.
862cdbc848bSFlorian Fainelli 	 */
863cdbc848bSFlorian Fainelli 	if (!IS_ENABLED(CONFIG_ARM64)) {
864369bc9abSArd Biesheuvel 		initrd_start = (unsigned long)__va(start);
865369bc9abSArd Biesheuvel 		initrd_end = (unsigned long)__va(end);
866369bc9abSArd Biesheuvel 		initrd_below_start_ok = 1;
867369bc9abSArd Biesheuvel 	}
868cdbc848bSFlorian Fainelli }
869369bc9abSArd Biesheuvel 
870f7b3a835SGrant Likely /**
871f7b3a835SGrant Likely  * early_init_dt_check_for_initrd - Decode initrd location from flat tree
872f7b3a835SGrant Likely  * @node: reference to node containing initrd location ('chosen')
873f7b3a835SGrant Likely  */
87429eb45a9SRob Herring static void __init early_init_dt_check_for_initrd(unsigned long node)
875f7b3a835SGrant Likely {
876374d5c99SSantosh Shilimkar 	u64 start, end;
8779d0c4dfeSRob Herring 	int len;
8789d0c4dfeSRob Herring 	const __be32 *prop;
879f7b3a835SGrant Likely 
880f7b3a835SGrant Likely 	pr_debug("Looking for initrd properties... ");
881f7b3a835SGrant Likely 
882f7b3a835SGrant Likely 	prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len);
8831406bc2fSJeremy Kerr 	if (!prop)
8841406bc2fSJeremy Kerr 		return;
885374d5c99SSantosh Shilimkar 	start = of_read_number(prop, len/4);
886f7b3a835SGrant Likely 
887f7b3a835SGrant Likely 	prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len);
8881406bc2fSJeremy Kerr 	if (!prop)
8891406bc2fSJeremy Kerr 		return;
890374d5c99SSantosh Shilimkar 	end = of_read_number(prop, len/4);
891f7b3a835SGrant Likely 
892369bc9abSArd Biesheuvel 	__early_init_dt_declare_initrd(start, end);
893fe7db757SFlorian Fainelli 	phys_initrd_start = start;
894fe7db757SFlorian Fainelli 	phys_initrd_size = end - start;
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 
907d503187bSLeif Lindholm int __init early_init_dt_scan_chosen_stdout(void)
908fb11ffe7SRob Herring {
909fb11ffe7SRob Herring 	int offset;
9104d118c9aSPeter Hurley 	const char *p, *q, *options = NULL;
911fb11ffe7SRob Herring 	int l;
912dd709e72SDaniel Kurtz 	const struct earlycon_id **p_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 
939dd709e72SDaniel Kurtz 	for (p_match = __earlycon_table; p_match < __earlycon_table_end;
940dd709e72SDaniel Kurtz 	     p_match++) {
941dd709e72SDaniel Kurtz 		const struct earlycon_id *match = *p_match;
942dd709e72SDaniel Kurtz 
9432eaa7909SPeter Hurley 		if (!match->compatible[0])
944fb11ffe7SRob Herring 			continue;
9452eaa7909SPeter Hurley 
9462eaa7909SPeter Hurley 		if (fdt_node_check_compatible(fdt, offset, match->compatible))
9472eaa7909SPeter Hurley 			continue;
948fb11ffe7SRob Herring 
949c90fe9c0SPeter Hurley 		of_setup_earlycon(match, offset, options);
950fb11ffe7SRob Herring 		return 0;
951fb11ffe7SRob Herring 	}
952fb11ffe7SRob Herring 	return -ENODEV;
953fb11ffe7SRob Herring }
954fb11ffe7SRob Herring #endif
955fb11ffe7SRob Herring 
95641f88009SGrant Likely /**
957f00abd94SGrant Likely  * early_init_dt_scan_root - fetch the top level address and size cells
958f00abd94SGrant Likely  */
959f00abd94SGrant Likely int __init early_init_dt_scan_root(unsigned long node, const char *uname,
960f00abd94SGrant Likely 				   int depth, void *data)
961f00abd94SGrant Likely {
9629d0c4dfeSRob Herring 	const __be32 *prop;
963f00abd94SGrant Likely 
964f00abd94SGrant Likely 	if (depth != 0)
965f00abd94SGrant Likely 		return 0;
966f00abd94SGrant Likely 
96733714881SJeremy Kerr 	dt_root_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
96833714881SJeremy Kerr 	dt_root_addr_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
96933714881SJeremy Kerr 
970f00abd94SGrant Likely 	prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
97133714881SJeremy Kerr 	if (prop)
97233714881SJeremy Kerr 		dt_root_size_cells = be32_to_cpup(prop);
973f00abd94SGrant Likely 	pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells);
974f00abd94SGrant Likely 
975f00abd94SGrant Likely 	prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
97633714881SJeremy Kerr 	if (prop)
97733714881SJeremy Kerr 		dt_root_addr_cells = be32_to_cpup(prop);
978f00abd94SGrant Likely 	pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);
979f00abd94SGrant Likely 
980f00abd94SGrant Likely 	/* break now */
981f00abd94SGrant Likely 	return 1;
982f00abd94SGrant Likely }
983f00abd94SGrant Likely 
9849d0c4dfeSRob Herring u64 __init dt_mem_next_cell(int s, const __be32 **cellp)
98583f7a06eSGrant Likely {
9869d0c4dfeSRob Herring 	const __be32 *p = *cellp;
98783f7a06eSGrant Likely 
98883f7a06eSGrant Likely 	*cellp = p + s;
98983f7a06eSGrant Likely 	return of_read_number(p, s);
99083f7a06eSGrant Likely }
99183f7a06eSGrant Likely 
99251975db0SGrant Likely /**
9930ef5adcaSFrank Rowand  * early_init_dt_scan_memory - Look for and parse memory nodes
99451975db0SGrant Likely  */
99551975db0SGrant Likely int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
99651975db0SGrant Likely 				     int depth, void *data)
99751975db0SGrant Likely {
9989d0c4dfeSRob Herring 	const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
9999d0c4dfeSRob Herring 	const __be32 *reg, *endp;
10009d0c4dfeSRob Herring 	int l;
100141a9ada3SReza Arbab 	bool hotpluggable;
100251975db0SGrant Likely 
100351975db0SGrant Likely 	/* We are scanning "memory" nodes only */
1004da653130SMichael Ellerman 	if (type == NULL || strcmp(type, "memory") != 0)
100551975db0SGrant Likely 		return 0;
100651975db0SGrant Likely 
100751975db0SGrant Likely 	reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
100851975db0SGrant Likely 	if (reg == NULL)
100951975db0SGrant Likely 		reg = of_get_flat_dt_prop(node, "reg", &l);
101051975db0SGrant Likely 	if (reg == NULL)
101151975db0SGrant Likely 		return 0;
101251975db0SGrant Likely 
101351975db0SGrant Likely 	endp = reg + (l / sizeof(__be32));
101441a9ada3SReza Arbab 	hotpluggable = of_get_flat_dt_prop(node, "hotpluggable", NULL);
101551975db0SGrant Likely 
1016c954b36eSFlorian Fainelli 	pr_debug("memory scan node %s, reg size %d,\n", uname, l);
101751975db0SGrant Likely 
101851975db0SGrant Likely 	while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
101951975db0SGrant Likely 		u64 base, size;
102051975db0SGrant Likely 
102151975db0SGrant Likely 		base = dt_mem_next_cell(dt_root_addr_cells, &reg);
102251975db0SGrant Likely 		size = dt_mem_next_cell(dt_root_size_cells, &reg);
102351975db0SGrant Likely 
102451975db0SGrant Likely 		if (size == 0)
102551975db0SGrant Likely 			continue;
102651975db0SGrant Likely 		pr_debug(" - %llx ,  %llx\n", (unsigned long long)base,
102751975db0SGrant Likely 		    (unsigned long long)size);
102851975db0SGrant Likely 
102951975db0SGrant Likely 		early_init_dt_add_memory_arch(base, size);
103041a9ada3SReza Arbab 
103141a9ada3SReza Arbab 		if (!hotpluggable)
103241a9ada3SReza Arbab 			continue;
103341a9ada3SReza Arbab 
103441a9ada3SReza Arbab 		if (early_init_dt_mark_hotplug_memory_arch(base, size))
103541a9ada3SReza Arbab 			pr_warn("failed to mark hotplug range 0x%llx - 0x%llx\n",
103641a9ada3SReza Arbab 				base, base + size);
103751975db0SGrant Likely 	}
103851975db0SGrant Likely 
103951975db0SGrant Likely 	return 0;
104051975db0SGrant Likely }
104151975db0SGrant Likely 
104286e03221SGrant Likely int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
104386e03221SGrant Likely 				     int depth, void *data)
104486e03221SGrant Likely {
10459d0c4dfeSRob Herring 	int l;
10469d0c4dfeSRob Herring 	const char *p;
104786e03221SGrant Likely 
104886e03221SGrant Likely 	pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
104986e03221SGrant Likely 
105085f60ae4SGrant Likely 	if (depth != 1 || !data ||
105186e03221SGrant Likely 	    (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
105286e03221SGrant Likely 		return 0;
105386e03221SGrant Likely 
105486e03221SGrant Likely 	early_init_dt_check_for_initrd(node);
105586e03221SGrant Likely 
105625985edcSLucas De Marchi 	/* Retrieve command line */
105786e03221SGrant Likely 	p = of_get_flat_dt_prop(node, "bootargs", &l);
105886e03221SGrant Likely 	if (p != NULL && l > 0)
1059b827bcbbSxiaojiangfeng 		strlcpy(data, p, min(l, COMMAND_LINE_SIZE));
106086e03221SGrant Likely 
106178b782cbSBenjamin Herrenschmidt 	/*
106278b782cbSBenjamin Herrenschmidt 	 * CONFIG_CMDLINE is meant to be a default in case nothing else
106378b782cbSBenjamin Herrenschmidt 	 * managed to set the command line, unless CONFIG_CMDLINE_FORCE
106478b782cbSBenjamin Herrenschmidt 	 * is set in which case we override whatever was found earlier.
106578b782cbSBenjamin Herrenschmidt 	 */
106686e03221SGrant Likely #ifdef CONFIG_CMDLINE
106734b82026SMax Uvarov #if defined(CONFIG_CMDLINE_EXTEND)
106834b82026SMax Uvarov 	strlcat(data, " ", COMMAND_LINE_SIZE);
106934b82026SMax Uvarov 	strlcat(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
107034b82026SMax Uvarov #elif defined(CONFIG_CMDLINE_FORCE)
107185f60ae4SGrant Likely 	strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
107234b82026SMax Uvarov #else
107334b82026SMax Uvarov 	/* No arguments from boot loader, use kernel's  cmdl*/
107434b82026SMax Uvarov 	if (!((char *)data)[0])
107534b82026SMax Uvarov 		strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
107634b82026SMax Uvarov #endif
107786e03221SGrant Likely #endif /* CONFIG_CMDLINE */
107886e03221SGrant Likely 
107985f60ae4SGrant Likely 	pr_debug("Command line is: %s\n", (char*)data);
108086e03221SGrant Likely 
108186e03221SGrant Likely 	/* break now */
108286e03221SGrant Likely 	return 1;
108386e03221SGrant Likely }
108486e03221SGrant Likely 
1085270522a0SArd Biesheuvel #ifndef MIN_MEMBLOCK_ADDR
1086270522a0SArd Biesheuvel #define MIN_MEMBLOCK_ADDR	__pa(PAGE_OFFSET)
1087270522a0SArd Biesheuvel #endif
10888eafeb48SArd Biesheuvel #ifndef MAX_MEMBLOCK_ADDR
10898eafeb48SArd Biesheuvel #define MAX_MEMBLOCK_ADDR	((phys_addr_t)~0)
10908eafeb48SArd Biesheuvel #endif
10913069f0c0SLaura Abbott 
1092068f6310SRob Herring void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
1093068f6310SRob Herring {
1094270522a0SArd Biesheuvel 	const u64 phys_offset = MIN_MEMBLOCK_ADDR;
10958f73d4b7SGeert Uytterhoeven 
10968cccffc5SArd Biesheuvel 	if (size < PAGE_SIZE - (base & ~PAGE_MASK)) {
10978cccffc5SArd Biesheuvel 		pr_warn("Ignoring memory block 0x%llx - 0x%llx\n",
10988cccffc5SArd Biesheuvel 			base, base + size);
10998cccffc5SArd Biesheuvel 		return;
11008cccffc5SArd Biesheuvel 	}
11016072cf56SMike Rapoport 
11026072cf56SMike Rapoport 	if (!PAGE_ALIGNED(base)) {
11038f73d4b7SGeert Uytterhoeven 		size -= PAGE_SIZE - (base & ~PAGE_MASK);
11048f73d4b7SGeert Uytterhoeven 		base = PAGE_ALIGN(base);
11058f73d4b7SGeert Uytterhoeven 	}
1106068f6310SRob Herring 	size &= PAGE_MASK;
1107a67a6ed1SLaura Abbott 
11088eafeb48SArd Biesheuvel 	if (base > MAX_MEMBLOCK_ADDR) {
1109a67a6ed1SLaura Abbott 		pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
1110a67a6ed1SLaura Abbott 				base, base + size);
1111a67a6ed1SLaura Abbott 		return;
1112a67a6ed1SLaura Abbott 	}
1113a67a6ed1SLaura Abbott 
11148eafeb48SArd Biesheuvel 	if (base + size - 1 > MAX_MEMBLOCK_ADDR) {
11159aacd602SSrinivas Kandagatla 		pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
11168eafeb48SArd Biesheuvel 				((u64)MAX_MEMBLOCK_ADDR) + 1, base + size);
11178eafeb48SArd Biesheuvel 		size = MAX_MEMBLOCK_ADDR - base + 1;
1118a67a6ed1SLaura Abbott 	}
1119a67a6ed1SLaura Abbott 
1120068f6310SRob Herring 	if (base + size < phys_offset) {
1121068f6310SRob Herring 		pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
1122068f6310SRob Herring 			   base, base + size);
1123068f6310SRob Herring 		return;
1124068f6310SRob Herring 	}
1125068f6310SRob Herring 	if (base < phys_offset) {
1126068f6310SRob Herring 		pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
1127068f6310SRob Herring 			   base, phys_offset);
1128068f6310SRob Herring 		size -= phys_offset - base;
1129068f6310SRob Herring 		base = phys_offset;
1130068f6310SRob Herring 	}
1131068f6310SRob Herring 	memblock_add(base, size);
1132068f6310SRob Herring }
1133068f6310SRob Herring 
113441a9ada3SReza Arbab int __init __weak early_init_dt_mark_hotplug_memory_arch(u64 base, u64 size)
113541a9ada3SReza Arbab {
113641a9ada3SReza Arbab 	return memblock_mark_hotplug(base, size);
113741a9ada3SReza Arbab }
113841a9ada3SReza Arbab 
1139e8d9d1f5SMarek Szyprowski int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
1140e8d9d1f5SMarek Szyprowski 					phys_addr_t size, bool nomap)
1141e8d9d1f5SMarek Szyprowski {
1142e8d9d1f5SMarek Szyprowski 	if (nomap)
1143e8d9d1f5SMarek Szyprowski 		return memblock_remove(base, size);
1144e8d9d1f5SMarek Szyprowski 	return memblock_reserve(base, size);
1145e8d9d1f5SMarek Szyprowski }
1146e8d9d1f5SMarek Szyprowski 
11470fa1c579SRob Herring static void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
11480fa1c579SRob Herring {
11498a7f97b9SMike Rapoport 	void *ptr = memblock_alloc(size, align);
11508a7f97b9SMike Rapoport 
11518a7f97b9SMike Rapoport 	if (!ptr)
11528a7f97b9SMike Rapoport 		panic("%s: Failed to allocate %llu bytes align=0x%llx\n",
11538a7f97b9SMike Rapoport 		      __func__, size, align);
11548a7f97b9SMike Rapoport 
11558a7f97b9SMike Rapoport 	return ptr;
11560fa1c579SRob Herring }
11570fa1c579SRob Herring 
11584972a74bSLaura Abbott bool __init early_init_dt_verify(void *params)
11590288ffcbSRob Herring {
11600288ffcbSRob Herring 	if (!params)
11610288ffcbSRob Herring 		return false;
11620288ffcbSRob Herring 
116350ba08f3SBjorn Helgaas 	/* check device tree validity */
116450ba08f3SBjorn Helgaas 	if (fdt_check_header(params))
116550ba08f3SBjorn Helgaas 		return false;
116650ba08f3SBjorn Helgaas 
11670288ffcbSRob Herring 	/* Setup flat device-tree pointer */
11680288ffcbSRob Herring 	initial_boot_params = params;
116908d53aa5SArd Biesheuvel 	of_fdt_crc32 = crc32_be(~0, initial_boot_params,
117008d53aa5SArd Biesheuvel 				fdt_totalsize(initial_boot_params));
11714972a74bSLaura Abbott 	return true;
11724972a74bSLaura Abbott }
11734972a74bSLaura Abbott 
11744972a74bSLaura Abbott 
11754972a74bSLaura Abbott void __init early_init_dt_scan_nodes(void)
11764972a74bSLaura Abbott {
1177e1e52544SNick Kossifidis 	int rc = 0;
1178e1e52544SNick Kossifidis 
11790288ffcbSRob Herring 	/* Retrieve various information from the /chosen node */
1180e1e52544SNick Kossifidis 	rc = of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
1181e1e52544SNick Kossifidis 	if (!rc)
1182e1e52544SNick Kossifidis 		pr_warn("No chosen node found, continuing without\n");
11830288ffcbSRob Herring 
11840288ffcbSRob Herring 	/* Initialize {size,address}-cells info */
11850288ffcbSRob Herring 	of_scan_flat_dt(early_init_dt_scan_root, NULL);
11860288ffcbSRob Herring 
11870288ffcbSRob Herring 	/* Setup memory, calling early_init_dt_add_memory_arch */
11880288ffcbSRob Herring 	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
11894972a74bSLaura Abbott }
11900288ffcbSRob Herring 
11914972a74bSLaura Abbott bool __init early_init_dt_scan(void *params)
11924972a74bSLaura Abbott {
11934972a74bSLaura Abbott 	bool status;
11944972a74bSLaura Abbott 
11954972a74bSLaura Abbott 	status = early_init_dt_verify(params);
11964972a74bSLaura Abbott 	if (!status)
11974972a74bSLaura Abbott 		return false;
11984972a74bSLaura Abbott 
11994972a74bSLaura Abbott 	early_init_dt_scan_nodes();
12000288ffcbSRob Herring 	return true;
12010288ffcbSRob Herring }
12020288ffcbSRob Herring 
1203f00abd94SGrant Likely /**
120441f88009SGrant Likely  * unflatten_device_tree - create tree of device_nodes from flat blob
120541f88009SGrant Likely  *
120641f88009SGrant Likely  * unflattens the device-tree passed by the firmware, creating the
120741f88009SGrant Likely  * tree of struct device_node. It also fills the "name" and "type"
120841f88009SGrant Likely  * pointers of the nodes so the normal device-tree walking functions
120941f88009SGrant Likely  * can be used.
121041f88009SGrant Likely  */
121141f88009SGrant Likely void __init unflatten_device_tree(void)
121241f88009SGrant Likely {
1213c4263233SGavin Shan 	__unflatten_device_tree(initial_boot_params, NULL, &of_root,
12141d1bde55SMichal Suchanek 				early_init_dt_alloc_memory_arch, false);
121541f88009SGrant Likely 
12164c7d6361SRobert P. J. Day 	/* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */
1217611cad72SShawn Guo 	of_alias_scan(early_init_dt_alloc_memory_arch);
121881d0848fSFrank Rowand 
121981d0848fSFrank Rowand 	unittest_unflatten_overlay_base();
122041f88009SGrant Likely }
1221e6ce1324SStephen Neuendorffer 
1222a8bf7527SRob Herring /**
1223a8bf7527SRob Herring  * unflatten_and_copy_device_tree - copy and create tree of device_nodes from flat blob
1224a8bf7527SRob Herring  *
1225a8bf7527SRob Herring  * Copies and unflattens the device-tree passed by the firmware, creating the
1226a8bf7527SRob Herring  * tree of struct device_node. It also fills the "name" and "type"
1227a8bf7527SRob Herring  * pointers of the nodes so the normal device-tree walking functions
1228a8bf7527SRob Herring  * can be used. This should only be used when the FDT memory has not been
1229a8bf7527SRob Herring  * reserved such is the case when the FDT is built-in to the kernel init
1230a8bf7527SRob Herring  * section. If the FDT memory is reserved already then unflatten_device_tree
1231a8bf7527SRob Herring  * should be used instead.
1232a8bf7527SRob Herring  */
1233a8bf7527SRob Herring void __init unflatten_and_copy_device_tree(void)
1234a8bf7527SRob Herring {
12356f041e99SJames Hogan 	int size;
12366f041e99SJames Hogan 	void *dt;
12376f041e99SJames Hogan 
12386f041e99SJames Hogan 	if (!initial_boot_params) {
12396f041e99SJames Hogan 		pr_warn("No valid device tree found, continuing without\n");
12406f041e99SJames Hogan 		return;
12416f041e99SJames Hogan 	}
12426f041e99SJames Hogan 
1243c972de14SRob Herring 	size = fdt_totalsize(initial_boot_params);
12446f041e99SJames Hogan 	dt = early_init_dt_alloc_memory_arch(size,
1245c972de14SRob Herring 					     roundup_pow_of_two(FDT_V17_SIZE));
1246a8bf7527SRob Herring 
1247a8bf7527SRob Herring 	if (dt) {
1248a8bf7527SRob Herring 		memcpy(dt, initial_boot_params, size);
1249a8bf7527SRob Herring 		initial_boot_params = dt;
1250a8bf7527SRob Herring 	}
1251a8bf7527SRob Herring 	unflatten_device_tree();
1252a8bf7527SRob Herring }
1253a8bf7527SRob Herring 
125408d53aa5SArd Biesheuvel #ifdef CONFIG_SYSFS
125508d53aa5SArd Biesheuvel static ssize_t of_fdt_raw_read(struct file *filp, struct kobject *kobj,
125608d53aa5SArd Biesheuvel 			       struct bin_attribute *bin_attr,
125708d53aa5SArd Biesheuvel 			       char *buf, loff_t off, size_t count)
1258b0a6fb36SRob Herring {
125908d53aa5SArd Biesheuvel 	memcpy(buf, initial_boot_params + off, count);
126008d53aa5SArd Biesheuvel 	return count;
126108d53aa5SArd Biesheuvel }
1262b0a6fb36SRob Herring 
126308d53aa5SArd Biesheuvel static int __init of_fdt_raw_init(void)
126408d53aa5SArd Biesheuvel {
126508d53aa5SArd Biesheuvel 	static struct bin_attribute of_fdt_raw_attr =
126608d53aa5SArd Biesheuvel 		__BIN_ATTR(fdt, S_IRUSR, of_fdt_raw_read, NULL, 0);
1267b0a6fb36SRob Herring 
126808d53aa5SArd Biesheuvel 	if (!initial_boot_params)
126908d53aa5SArd Biesheuvel 		return 0;
1270b0a6fb36SRob Herring 
127108d53aa5SArd Biesheuvel 	if (of_fdt_crc32 != crc32_be(~0, initial_boot_params,
127208d53aa5SArd Biesheuvel 				     fdt_totalsize(initial_boot_params))) {
1273606ad42aSRob Herring 		pr_warn("not creating '/sys/firmware/fdt': CRC check failed\n");
1274b0a6fb36SRob Herring 		return 0;
1275b0a6fb36SRob Herring 	}
127608d53aa5SArd Biesheuvel 	of_fdt_raw_attr.size = fdt_totalsize(initial_boot_params);
127708d53aa5SArd Biesheuvel 	return sysfs_create_bin_file(firmware_kobj, &of_fdt_raw_attr);
127808d53aa5SArd Biesheuvel }
127908d53aa5SArd Biesheuvel late_initcall(of_fdt_raw_init);
1280b0a6fb36SRob Herring #endif
1281b0a6fb36SRob Herring 
1282e6ce1324SStephen Neuendorffer #endif /* CONFIG_OF_EARLY_FLATTREE */
1283