Branch data Line data Source code
1 : : /*
2 : : * Functions for working with the Flattened Device Tree data format
3 : : *
4 : : * Copyright 2009 Benjamin Herrenschmidt, IBM Corp
5 : : * benh@kernel.crashing.org
6 : : *
7 : : * This program is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU General Public License
9 : : * version 2 as published by the Free Software Foundation.
10 : : */
11 : :
12 : : #include <linux/kernel.h>
13 : : #include <linux/initrd.h>
14 : : #include <linux/memblock.h>
15 : : #include <linux/module.h>
16 : : #include <linux/of.h>
17 : : #include <linux/of_fdt.h>
18 : : #include <linux/string.h>
19 : : #include <linux/errno.h>
20 : : #include <linux/slab.h>
21 : :
22 : : #include <asm/setup.h> /* for COMMAND_LINE_SIZE */
23 : : #ifdef CONFIG_PPC
24 : : #include <asm/machdep.h>
25 : : #endif /* CONFIG_PPC */
26 : :
27 : : #include <asm/page.h>
28 : :
29 : 0 : char *of_fdt_get_string(struct boot_param_header *blob, u32 offset)
30 : : {
31 : 0 : return ((char *)blob) +
32 [ # # ][ # # ]: 0 : be32_to_cpu(blob->off_dt_strings) + offset;
[ # # ]
33 : : }
34 : :
35 : : /**
36 : : * of_fdt_get_property - Given a node in the given flat blob, return
37 : : * the property ptr
38 : : */
39 : 0 : void *of_fdt_get_property(struct boot_param_header *blob,
40 : : unsigned long node, const char *name,
41 : : unsigned long *size)
42 : : {
43 : : unsigned long p = node;
44 : :
45 : : do {
46 : 0 : u32 tag = be32_to_cpup((__be32 *)p);
47 : : u32 sz, noff;
48 : : const char *nstr;
49 : :
50 : 0 : p += 4;
51 [ # # ]: 0 : if (tag == OF_DT_NOP)
52 : 0 : continue;
53 [ # # ]: 0 : if (tag != OF_DT_PROP)
54 : : return NULL;
55 : :
56 : 0 : sz = be32_to_cpup((__be32 *)p);
57 : 0 : noff = be32_to_cpup((__be32 *)(p + 4));
58 : 0 : p += 8;
59 [ # # ][ # # ]: 0 : if (be32_to_cpu(blob->version) < 0x10)
60 [ # # ][ # # ]: 0 : p = ALIGN(p, sz >= 8 ? 8 : 4);
61 : :
62 : : nstr = of_fdt_get_string(blob, noff);
63 [ # # ]: 0 : if (nstr == NULL) {
64 : 0 : pr_warning("Can't find property index name !\n");
65 : 0 : return NULL;
66 : : }
67 [ # # ]: 0 : if (strcmp(name, nstr) == 0) {
68 [ # # ]: 0 : if (size)
69 : 0 : *size = sz;
70 : 0 : return (void *)p;
71 : : }
72 : 0 : p += sz;
73 : 0 : p = ALIGN(p, 4);
74 : : } while (1);
75 : : }
76 : :
77 : : /**
78 : : * of_fdt_is_compatible - Return true if given node from the given blob has
79 : : * compat in its compatible list
80 : : * @blob: A device tree blob
81 : : * @node: node to test
82 : : * @compat: compatible string to compare with compatible list.
83 : : *
84 : : * On match, returns a non-zero value with smaller values returned for more
85 : : * specific compatible values.
86 : : */
87 : 0 : int of_fdt_is_compatible(struct boot_param_header *blob,
88 : : unsigned long node, const char *compat)
89 : : {
90 : : const char *cp;
91 : : unsigned long cplen, l, score = 0;
92 : :
93 : 0 : cp = of_fdt_get_property(blob, node, "compatible", &cplen);
94 [ # # ]: 0 : if (cp == NULL)
95 : : return 0;
96 [ # # ]: 0 : while (cplen > 0) {
97 : 0 : score++;
98 [ # # ]: 0 : if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
99 : 0 : return score;
100 : 0 : l = strlen(cp) + 1;
101 : 0 : cp += l;
102 : 0 : cplen -= l;
103 : : }
104 : :
105 : : return 0;
106 : : }
107 : :
108 : : /**
109 : : * of_fdt_match - Return true if node matches a list of compatible values
110 : : */
111 : 0 : int of_fdt_match(struct boot_param_header *blob, unsigned long node,
112 : : const char *const *compat)
113 : : {
114 : : unsigned int tmp, score = 0;
115 : :
116 [ # # ]: 0 : if (!compat)
117 : : return 0;
118 : :
119 [ # # ]: 0 : while (*compat) {
120 : 0 : tmp = of_fdt_is_compatible(blob, node, *compat);
121 [ # # ][ # # ]: 0 : if (tmp && (score == 0 || (tmp < score)))
122 : : score = tmp;
123 : 0 : compat++;
124 : : }
125 : :
126 : 0 : return score;
127 : : }
128 : :
129 : : static void *unflatten_dt_alloc(void **mem, unsigned long size,
130 : : unsigned long align)
131 : : {
132 : : void *res;
133 : :
134 : 0 : *mem = PTR_ALIGN(*mem, align);
135 : : res = *mem;
136 : 0 : *mem += size;
137 : :
138 : : return res;
139 : : }
140 : :
141 : : /**
142 : : * unflatten_dt_node - Alloc and populate a device_node from the flat tree
143 : : * @blob: The parent device tree blob
144 : : * @mem: Memory chunk to use for allocating device nodes and properties
145 : : * @p: pointer to node in flat tree
146 : : * @dad: Parent struct device_node
147 : : * @allnextpp: pointer to ->allnext from last allocated device_node
148 : : * @fpsize: Size of the node path up at the current depth.
149 : : */
150 : 0 : static void * unflatten_dt_node(struct boot_param_header *blob,
151 : : void *mem,
152 : : void **p,
153 : : struct device_node *dad,
154 : : struct device_node ***allnextpp,
155 : : unsigned long fpsize)
156 : : {
157 : : struct device_node *np;
158 : : struct property *pp, **prev_pp = NULL;
159 : : char *pathp;
160 : : u32 tag;
161 : : unsigned int l, allocl;
162 : : int has_name = 0;
163 : : int new_format = 0;
164 : :
165 : 0 : tag = be32_to_cpup(*p);
166 [ # # ]: 0 : if (tag != OF_DT_BEGIN_NODE) {
167 : 0 : pr_err("Weird tag at start of node: %x\n", tag);
168 : 0 : return mem;
169 : : }
170 : 0 : *p += 4;
171 : : pathp = *p;
172 : 0 : l = allocl = strlen(pathp) + 1;
173 : 0 : *p = PTR_ALIGN(*p + l, 4);
174 : :
175 : : /* version 0x10 has a more compact unit name here instead of the full
176 : : * path. we accumulate the full path size using "fpsize", we'll rebuild
177 : : * it later. We detect this because the first character of the name is
178 : : * not '/'.
179 : : */
180 [ # # ]: 0 : if ((*pathp) != '/') {
181 : : new_format = 1;
182 [ # # ]: 0 : if (fpsize == 0) {
183 : : /* root node: special case. fpsize accounts for path
184 : : * plus terminating zero. root node only has '/', so
185 : : * fpsize should be 2, but we want to avoid the first
186 : : * level nodes to have two '/' so we use fpsize 1 here
187 : : */
188 : : fpsize = 1;
189 : : allocl = 2;
190 : : l = 1;
191 : 0 : *pathp = '\0';
192 : : } else {
193 : : /* account for '/' and path size minus terminal 0
194 : : * already in 'l'
195 : : */
196 : 0 : fpsize += l;
197 : : allocl = fpsize;
198 : : }
199 : : }
200 : :
201 : 0 : np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
202 : : __alignof__(struct device_node));
203 [ # # ]: 0 : if (allnextpp) {
204 : : char *fn;
205 : 0 : np->full_name = fn = ((char *)np) + sizeof(*np);
206 [ # # ]: 0 : if (new_format) {
207 : : /* rebuild full path for new format */
208 [ # # ][ # # ]: 0 : if (dad && dad->parent) {
209 : 0 : strcpy(fn, dad->full_name);
210 : : #ifdef DEBUG
211 : : if ((strlen(fn) + l + 1) != allocl) {
212 : : pr_debug("%s: p: %d, l: %d, a: %d\n",
213 : : pathp, (int)strlen(fn),
214 : : l, allocl);
215 : : }
216 : : #endif
217 : 0 : fn += strlen(fn);
218 : : }
219 : 0 : *(fn++) = '/';
220 : : }
221 : 0 : memcpy(fn, pathp, l);
222 : :
223 : 0 : prev_pp = &np->properties;
224 : 0 : **allnextpp = np;
225 : 0 : *allnextpp = &np->allnext;
226 [ # # ]: 0 : if (dad != NULL) {
227 : 0 : np->parent = dad;
228 : : /* we temporarily use the next field as `last_child'*/
229 [ # # ]: 0 : if (dad->next == NULL)
230 : 0 : dad->child = np;
231 : : else
232 : 0 : dad->next->sibling = np;
233 : 0 : dad->next = np;
234 : : }
235 : : kref_init(&np->kref);
236 : : }
237 : : /* process properties */
238 : : while (1) {
239 : : u32 sz, noff;
240 : : char *pname;
241 : :
242 : 0 : tag = be32_to_cpup(*p);
243 [ # # ]: 0 : if (tag == OF_DT_NOP) {
244 : 0 : *p += 4;
245 : 0 : continue;
246 : : }
247 [ # # ]: 0 : if (tag != OF_DT_PROP)
248 : : break;
249 : 0 : *p += 4;
250 : : sz = be32_to_cpup(*p);
251 : 0 : noff = be32_to_cpup(*p + 4);
252 : 0 : *p += 8;
253 [ # # ][ # # ]: 0 : if (be32_to_cpu(blob->version) < 0x10)
254 [ # # ][ # # ]: 0 : *p = PTR_ALIGN(*p, sz >= 8 ? 8 : 4);
255 : :
256 : : pname = of_fdt_get_string(blob, noff);
257 [ # # ]: 0 : if (pname == NULL) {
258 : 0 : pr_info("Can't find property name in list !\n");
259 : 0 : break;
260 : : }
261 [ # # ]: 0 : if (strcmp(pname, "name") == 0)
262 : : has_name = 1;
263 : : l = strlen(pname) + 1;
264 : : pp = unflatten_dt_alloc(&mem, sizeof(struct property),
265 : : __alignof__(struct property));
266 [ # # ]: 0 : if (allnextpp) {
267 : : /* We accept flattened tree phandles either in
268 : : * ePAPR-style "phandle" properties, or the
269 : : * legacy "linux,phandle" properties. If both
270 : : * appear and have different values, things
271 : : * will get weird. Don't do that. */
272 [ # # ][ # # ]: 0 : if ((strcmp(pname, "phandle") == 0) ||
273 : 0 : (strcmp(pname, "linux,phandle") == 0)) {
274 [ # # ]: 0 : if (np->phandle == 0)
275 : 0 : np->phandle = be32_to_cpup((__be32*)*p);
276 : : }
277 : : /* And we process the "ibm,phandle" property
278 : : * used in pSeries dynamic device tree
279 : : * stuff */
280 [ # # ]: 0 : if (strcmp(pname, "ibm,phandle") == 0)
281 : 0 : np->phandle = be32_to_cpup((__be32 *)*p);
282 : 0 : pp->name = pname;
283 : 0 : pp->length = sz;
284 : 0 : pp->value = *p;
285 : 0 : *prev_pp = pp;
286 : 0 : prev_pp = &pp->next;
287 : : }
288 : 0 : *p = PTR_ALIGN((*p) + sz, 4);
289 : : }
290 : : /* with version 0x10 we may not have the name property, recreate
291 : : * it here from the unit name if absent
292 : : */
293 [ # # ]: 0 : if (!has_name) {
294 : : char *p1 = pathp, *ps = pathp, *pa = NULL;
295 : : int sz;
296 : :
297 [ # # ]: 0 : while (*p1) {
298 [ # # ]: 0 : if ((*p1) == '@')
299 : : pa = p1;
300 [ # # ]: 0 : if ((*p1) == '/')
301 : 0 : ps = p1 + 1;
302 : 0 : p1++;
303 : : }
304 [ # # ]: 0 : if (pa < ps)
305 : : pa = p1;
306 : 0 : sz = (pa - ps) + 1;
307 : 0 : pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
308 : : __alignof__(struct property));
309 [ # # ]: 0 : if (allnextpp) {
310 : 0 : pp->name = "name";
311 : 0 : pp->length = sz;
312 : 0 : pp->value = pp + 1;
313 : 0 : *prev_pp = pp;
314 : 0 : prev_pp = &pp->next;
315 : 0 : memcpy(pp->value, ps, sz - 1);
316 : 0 : ((char *)pp->value)[sz - 1] = 0;
317 : : pr_debug("fixed up name for %s -> %s\n", pathp,
318 : : (char *)pp->value);
319 : : }
320 : : }
321 [ # # ]: 0 : if (allnextpp) {
322 : 0 : *prev_pp = NULL;
323 : 0 : np->name = of_get_property(np, "name", NULL);
324 : 0 : np->type = of_get_property(np, "device_type", NULL);
325 : :
326 [ # # ]: 0 : if (!np->name)
327 : 0 : np->name = "<NULL>";
328 [ # # ]: 0 : if (!np->type)
329 : 0 : np->type = "<NULL>";
330 : : }
331 [ # # ]: 0 : while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) {
332 [ # # ]: 0 : if (tag == OF_DT_NOP)
333 : 0 : *p += 4;
334 : : else
335 : 0 : mem = unflatten_dt_node(blob, mem, p, np, allnextpp,
336 : : fpsize);
337 : 0 : tag = be32_to_cpup(*p);
338 : : }
339 [ # # ]: 0 : if (tag != OF_DT_END_NODE) {
340 : 0 : pr_err("Weird tag at end of node: %x\n", tag);
341 : 0 : return mem;
342 : : }
343 : 0 : *p += 4;
344 : 0 : return mem;
345 : : }
346 : :
347 : : /**
348 : : * __unflatten_device_tree - create tree of device_nodes from flat blob
349 : : *
350 : : * unflattens a device-tree, creating the
351 : : * tree of struct device_node. It also fills the "name" and "type"
352 : : * pointers of the nodes so the normal device-tree walking functions
353 : : * can be used.
354 : : * @blob: The blob to expand
355 : : * @mynodes: The device_node tree created by the call
356 : : * @dt_alloc: An allocator that provides a virtual address to memory
357 : : * for the resulting tree
358 : : */
359 : 0 : static void __unflatten_device_tree(struct boot_param_header *blob,
360 : : struct device_node **mynodes,
361 : : void * (*dt_alloc)(u64 size, u64 align))
362 : : {
363 : : unsigned long size;
364 : : void *start, *mem;
365 : 0 : struct device_node **allnextp = mynodes;
366 : :
367 : : pr_debug(" -> unflatten_device_tree()\n");
368 : :
369 [ # # ]: 0 : if (!blob) {
370 : : pr_debug("No device tree pointer\n");
371 : 0 : return;
372 : : }
373 : :
374 : : pr_debug("Unflattening device tree:\n");
375 [ # # ]: 0 : pr_debug("magic: %08x\n", be32_to_cpu(blob->magic));
376 [ # # ]: 0 : pr_debug("size: %08x\n", be32_to_cpu(blob->totalsize));
377 [ # # ]: 0 : pr_debug("version: %08x\n", be32_to_cpu(blob->version));
378 : :
379 [ # # ][ # # ]: 0 : if (be32_to_cpu(blob->magic) != OF_DT_HEADER) {
380 : 0 : pr_err("Invalid device tree blob header\n");
381 : 0 : return;
382 : : }
383 : :
384 : : /* First pass, scan for size */
385 [ # # ]: 0 : start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct);
386 : 0 : size = (unsigned long)unflatten_dt_node(blob, 0, &start, NULL, NULL, 0);
387 : 0 : size = ALIGN(size, 4);
388 : :
389 : : pr_debug(" size is %lx, allocating...\n", size);
390 : :
391 : : /* Allocate memory for the expanded device tree */
392 : 0 : mem = dt_alloc(size + 4, __alignof__(struct device_node));
393 [ # # ]: 0 : memset(mem, 0, size);
394 : :
395 : 0 : *(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef);
396 : :
397 : : pr_debug(" unflattening %p...\n", mem);
398 : :
399 : : /* Second pass, do actual unflattening */
400 [ # # ]: 0 : start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct);
401 : 0 : unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0);
402 [ # # ]: 0 : if (be32_to_cpup(start) != OF_DT_END)
403 : 0 : pr_warning("Weird tag at end of tree: %08x\n", be32_to_cpup(start));
404 [ # # ]: 0 : if (be32_to_cpup(mem + size) != 0xdeadbeef)
405 : 0 : pr_warning("End of tree marker overwritten: %08x\n",
406 : : be32_to_cpup(mem + size));
407 : 0 : *allnextp = NULL;
408 : :
409 : : pr_debug(" <- unflatten_device_tree()\n");
410 : : }
411 : :
412 : 0 : static void *kernel_tree_alloc(u64 size, u64 align)
413 : : {
414 : 0 : return kzalloc(size, GFP_KERNEL);
415 : : }
416 : :
417 : : /**
418 : : * of_fdt_unflatten_tree - create tree of device_nodes from flat blob
419 : : *
420 : : * unflattens the device-tree passed by the firmware, creating the
421 : : * tree of struct device_node. It also fills the "name" and "type"
422 : : * pointers of the nodes so the normal device-tree walking functions
423 : : * can be used.
424 : : */
425 : 0 : void of_fdt_unflatten_tree(unsigned long *blob,
426 : : struct device_node **mynodes)
427 : : {
428 : : struct boot_param_header *device_tree =
429 : : (struct boot_param_header *)blob;
430 : 0 : __unflatten_device_tree(device_tree, mynodes, &kernel_tree_alloc);
431 : 0 : }
432 : : EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
433 : :
434 : : /* Everything below here references initial_boot_params directly. */
435 : : int __initdata dt_root_addr_cells;
436 : : int __initdata dt_root_size_cells;
437 : :
438 : : struct boot_param_header *initial_boot_params;
439 : :
440 : : #ifdef CONFIG_OF_EARLY_FLATTREE
441 : :
442 : : /**
443 : : * of_scan_flat_dt - scan flattened tree blob and call callback on each.
444 : : * @it: callback function
445 : : * @data: context data pointer
446 : : *
447 : : * This function is used to scan the flattened device-tree, it is
448 : : * used to extract the memory information at boot before we can
449 : : * unflatten the tree
450 : : */
451 : 0 : int __init of_scan_flat_dt(int (*it)(unsigned long node,
452 : : const char *uname, int depth,
453 : : void *data),
454 : : void *data)
455 : : {
456 [ # # ]: 0 : unsigned long p = ((unsigned long)initial_boot_params) +
457 : 0 : be32_to_cpu(initial_boot_params->off_dt_struct);
458 : : int rc = 0;
459 : : int depth = -1;
460 : :
461 : : do {
462 : 0 : u32 tag = be32_to_cpup((__be32 *)p);
463 : : const char *pathp;
464 : :
465 : 0 : p += 4;
466 [ # # ]: 0 : if (tag == OF_DT_END_NODE) {
467 : 0 : depth--;
468 : 0 : continue;
469 : : }
470 [ # # ]: 0 : if (tag == OF_DT_NOP)
471 : 0 : continue;
472 [ # # ]: 0 : if (tag == OF_DT_END)
473 : : break;
474 [ # # ]: 0 : if (tag == OF_DT_PROP) {
475 : 0 : u32 sz = be32_to_cpup((__be32 *)p);
476 : 0 : p += 8;
477 [ # # ][ # # ]: 0 : if (be32_to_cpu(initial_boot_params->version) < 0x10)
478 [ # # ][ # # ]: 0 : p = ALIGN(p, sz >= 8 ? 8 : 4);
479 : 0 : p += sz;
480 : 0 : p = ALIGN(p, 4);
481 : 0 : continue;
482 : : }
483 [ # # ]: 0 : if (tag != OF_DT_BEGIN_NODE) {
484 : 0 : pr_err("Invalid tag %x in flat device tree!\n", tag);
485 : 0 : return -EINVAL;
486 : : }
487 : 0 : depth++;
488 : 0 : pathp = (char *)p;
489 : 0 : p = ALIGN(p + strlen(pathp) + 1, 4);
490 [ # # ]: 0 : if (*pathp == '/')
491 : : pathp = kbasename(pathp);
492 : 0 : rc = it(p, pathp, depth, data);
493 [ # # ]: 0 : if (rc != 0)
494 : : break;
495 : : } while (1);
496 : :
497 : 0 : return rc;
498 : : }
499 : :
500 : : /**
501 : : * of_get_flat_dt_root - find the root node in the flat blob
502 : : */
503 : 0 : unsigned long __init of_get_flat_dt_root(void)
504 : : {
505 [ # # ]: 0 : unsigned long p = ((unsigned long)initial_boot_params) +
506 : 0 : be32_to_cpu(initial_boot_params->off_dt_struct);
507 : :
508 [ # # ]: 0 : while (be32_to_cpup((__be32 *)p) == OF_DT_NOP)
509 : 0 : p += 4;
510 [ # # ]: 0 : BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE);
511 : 0 : p += 4;
512 : 0 : return ALIGN(p + strlen((char *)p) + 1, 4);
513 : : }
514 : :
515 : : /**
516 : : * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr
517 : : *
518 : : * This function can be used within scan_flattened_dt callback to get
519 : : * access to properties
520 : : */
521 : 0 : void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
522 : : unsigned long *size)
523 : : {
524 : 0 : return of_fdt_get_property(initial_boot_params, node, name, size);
525 : : }
526 : :
527 : : /**
528 : : * of_flat_dt_is_compatible - Return true if given node has compat in compatible list
529 : : * @node: node to test
530 : : * @compat: compatible string to compare with compatible list.
531 : : */
532 : 0 : int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
533 : : {
534 : 0 : return of_fdt_is_compatible(initial_boot_params, node, compat);
535 : : }
536 : :
537 : : /**
538 : : * of_flat_dt_match - Return true if node matches a list of compatible values
539 : : */
540 : 0 : int __init of_flat_dt_match(unsigned long node, const char *const *compat)
541 : : {
542 : 0 : return of_fdt_match(initial_boot_params, node, compat);
543 : : }
544 : :
545 : : struct fdt_scan_status {
546 : : const char *name;
547 : : int namelen;
548 : : int depth;
549 : : int found;
550 : : int (*iterator)(unsigned long node, const char *uname, int depth, void *data);
551 : : void *data;
552 : : };
553 : :
554 : : /**
555 : : * fdt_scan_node_by_path - iterator for of_scan_flat_dt_by_path function
556 : : */
557 : 0 : static int __init fdt_scan_node_by_path(unsigned long node, const char *uname,
558 : : int depth, void *data)
559 : : {
560 : : struct fdt_scan_status *st = data;
561 : :
562 : : /*
563 : : * if scan at the requested fdt node has been completed,
564 : : * return -ENXIO to abort further scanning
565 : : */
566 [ # # ]: 0 : if (depth <= st->depth)
567 : : return -ENXIO;
568 : :
569 : : /* requested fdt node has been found, so call iterator function */
570 [ # # ]: 0 : if (st->found)
571 : 0 : return st->iterator(node, uname, depth, st->data);
572 : :
573 : : /* check if scanning automata is entering next level of fdt nodes */
574 [ # # ][ # # ]: 0 : if (depth == st->depth + 1 &&
575 [ # # ]: 0 : strncmp(st->name, uname, st->namelen) == 0 &&
576 : 0 : uname[st->namelen] == 0) {
577 : 0 : st->depth += 1;
578 [ # # ]: 0 : if (st->name[st->namelen] == 0) {
579 : 0 : st->found = 1;
580 : : } else {
581 : 0 : const char *next = st->name + st->namelen + 1;
582 : 0 : st->name = next;
583 : 0 : st->namelen = strcspn(next, "/");
584 : : }
585 : : return 0;
586 : : }
587 : :
588 : : /* scan next fdt node */
589 : : return 0;
590 : : }
591 : :
592 : : /**
593 : : * of_scan_flat_dt_by_path - scan flattened tree blob and call callback on each
594 : : * child of the given path.
595 : : * @path: path to start searching for children
596 : : * @it: callback function
597 : : * @data: context data pointer
598 : : *
599 : : * This function is used to scan the flattened device-tree starting from the
600 : : * node given by path. It is used to extract information (like reserved
601 : : * memory), which is required on ealy boot before we can unflatten the tree.
602 : : */
603 : 0 : int __init of_scan_flat_dt_by_path(const char *path,
604 : : int (*it)(unsigned long node, const char *name, int depth, void *data),
605 : : void *data)
606 : : {
607 : 0 : struct fdt_scan_status st = {path, 0, -1, 0, it, data};
608 : : int ret = 0;
609 : :
610 [ # # ]: 0 : if (initial_boot_params)
611 : 0 : ret = of_scan_flat_dt(fdt_scan_node_by_path, &st);
612 : :
613 [ # # ]: 0 : if (!st.found)
614 : : return -ENOENT;
615 [ # # ]: 0 : else if (ret == -ENXIO) /* scan has been completed */
616 : : return 0;
617 : : else
618 : 0 : return ret;
619 : : }
620 : :
621 : 0 : const char * __init of_flat_dt_get_machine_name(void)
622 : : {
623 : : const char *name;
624 : 0 : unsigned long dt_root = of_get_flat_dt_root();
625 : :
626 : 0 : name = of_get_flat_dt_prop(dt_root, "model", NULL);
627 [ # # ]: 0 : if (!name)
628 : 0 : name = of_get_flat_dt_prop(dt_root, "compatible", NULL);
629 : 0 : return name;
630 : : }
631 : :
632 : : /**
633 : : * of_flat_dt_match_machine - Iterate match tables to find matching machine.
634 : : *
635 : : * @default_match: A machine specific ptr to return in case of no match.
636 : : * @get_next_compat: callback function to return next compatible match table.
637 : : *
638 : : * Iterate through machine match tables to find the best match for the machine
639 : : * compatible string in the FDT.
640 : : */
641 : 0 : const void * __init of_flat_dt_match_machine(const void *default_match,
642 : : const void * (*get_next_compat)(const char * const**))
643 : : {
644 : : const void *data = NULL;
645 : : const void *best_data = default_match;
646 : : const char *const *compat;
647 : : unsigned long dt_root;
648 : : unsigned int best_score = ~1, score = 0;
649 : :
650 : 0 : dt_root = of_get_flat_dt_root();
651 [ # # ]: 0 : while ((data = get_next_compat(&compat))) {
652 : 0 : score = of_flat_dt_match(dt_root, compat);
653 [ # # ]: 0 : if (score > 0 && score < best_score) {
654 : : best_data = data;
655 : : best_score = score;
656 : : }
657 : : }
658 [ # # ]: 0 : if (!best_data) {
659 : : const char *prop;
660 : : long size;
661 : :
662 : 0 : pr_err("\n unrecognized device tree list:\n[ ");
663 : :
664 : 0 : prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
665 [ # # ]: 0 : if (prop) {
666 [ # # ]: 0 : while (size > 0) {
667 : 0 : printk("'%s' ", prop);
668 : 0 : size -= strlen(prop) + 1;
669 : 0 : prop += strlen(prop) + 1;
670 : : }
671 : : }
672 : 0 : printk("]\n\n");
673 : : return NULL;
674 : : }
675 : :
676 : 0 : pr_info("Machine model: %s\n", of_flat_dt_get_machine_name());
677 : :
678 : 0 : return best_data;
679 : : }
680 : :
681 : : #ifdef CONFIG_BLK_DEV_INITRD
682 : : /**
683 : : * early_init_dt_check_for_initrd - Decode initrd location from flat tree
684 : : * @node: reference to node containing initrd location ('chosen')
685 : : */
686 : 0 : static void __init early_init_dt_check_for_initrd(unsigned long node)
687 : : {
688 : : u64 start, end;
689 : : unsigned long len;
690 : : __be32 *prop;
691 : :
692 : : pr_debug("Looking for initrd properties... ");
693 : :
694 : 0 : prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len);
695 [ # # ]: 0 : if (!prop)
696 : 0 : return;
697 : 0 : start = of_read_number(prop, len/4);
698 : :
699 : 0 : prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len);
700 [ # # ]: 0 : if (!prop)
701 : : return;
702 : 0 : end = of_read_number(prop, len/4);
703 : :
704 : 0 : initrd_start = (unsigned long)__va(start);
705 : 0 : initrd_end = (unsigned long)__va(end);
706 : 0 : initrd_below_start_ok = 1;
707 : :
708 : : pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n",
709 : : (unsigned long long)start, (unsigned long long)end);
710 : : }
711 : : #else
712 : : static inline void early_init_dt_check_for_initrd(unsigned long node)
713 : : {
714 : : }
715 : : #endif /* CONFIG_BLK_DEV_INITRD */
716 : :
717 : : /**
718 : : * early_init_dt_scan_root - fetch the top level address and size cells
719 : : */
720 : 0 : int __init early_init_dt_scan_root(unsigned long node, const char *uname,
721 : : int depth, void *data)
722 : : {
723 : 0 : __be32 *prop;
724 : :
725 [ # # ]: 0 : if (depth != 0)
726 : : return 0;
727 : :
728 : 0 : dt_root_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
729 : 0 : dt_root_addr_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
730 : :
731 : 0 : prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
732 [ # # ]: 0 : if (prop)
733 : 0 : dt_root_size_cells = be32_to_cpup(prop);
734 : : pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells);
735 : :
736 : 0 : prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
737 [ # # ]: 0 : if (prop)
738 : 0 : dt_root_addr_cells = be32_to_cpup(prop);
739 : : pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);
740 : :
741 : : /* break now */
742 : : return 1;
743 : : }
744 : :
745 : 0 : u64 __init dt_mem_next_cell(int s, __be32 **cellp)
746 : : {
747 : 0 : __be32 *p = *cellp;
748 : :
749 : 0 : *cellp = p + s;
750 : 0 : return of_read_number(p, s);
751 : : }
752 : :
753 : : /**
754 : : * early_init_dt_scan_memory - Look for an parse memory nodes
755 : : */
756 : 0 : int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
757 : : int depth, void *data)
758 : : {
759 : 0 : char *type = of_get_flat_dt_prop(node, "device_type", NULL);
760 : : __be32 *reg, *endp;
761 : : unsigned long l;
762 : :
763 : : /* We are scanning "memory" nodes only */
764 [ # # ]: 0 : if (type == NULL) {
765 : : /*
766 : : * The longtrail doesn't have a device_type on the
767 : : * /memory node, so look for the node called /memory@0.
768 : : */
769 [ # # ][ # # ]: 0 : if (depth != 1 || strcmp(uname, "memory@0") != 0)
770 : : return 0;
771 [ # # ]: 0 : } else if (strcmp(type, "memory") != 0)
772 : : return 0;
773 : :
774 : 0 : reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
775 [ # # ]: 0 : if (reg == NULL)
776 : 0 : reg = of_get_flat_dt_prop(node, "reg", &l);
777 [ # # ]: 0 : if (reg == NULL)
778 : : return 0;
779 : :
780 : 0 : endp = reg + (l / sizeof(__be32));
781 : :
782 : : pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",
783 : : uname, l, reg[0], reg[1], reg[2], reg[3]);
784 : :
785 [ # # ]: 0 : while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
786 : : u64 base, size;
787 : :
788 : 0 : base = dt_mem_next_cell(dt_root_addr_cells, ®);
789 : 0 : size = dt_mem_next_cell(dt_root_size_cells, ®);
790 : :
791 [ # # ]: 0 : if (size == 0)
792 : 0 : continue;
793 : : pr_debug(" - %llx , %llx\n", (unsigned long long)base,
794 : : (unsigned long long)size);
795 : :
796 : 0 : early_init_dt_add_memory_arch(base, size);
797 : : }
798 : :
799 : : return 0;
800 : : }
801 : :
802 : 0 : int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
803 : : int depth, void *data)
804 : : {
805 : : unsigned long l;
806 : : char *p;
807 : :
808 : : pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
809 : :
810 [ # # ][ # # ]: 0 : if (depth != 1 || !data ||
811 [ # # ]: 0 : (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
812 : : return 0;
813 : :
814 : 0 : early_init_dt_check_for_initrd(node);
815 : :
816 : : /* Retrieve command line */
817 : 0 : p = of_get_flat_dt_prop(node, "bootargs", &l);
818 [ # # ][ # # ]: 0 : if (p != NULL && l > 0)
819 : 0 : strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));
820 : :
821 : : /*
822 : : * CONFIG_CMDLINE is meant to be a default in case nothing else
823 : : * managed to set the command line, unless CONFIG_CMDLINE_FORCE
824 : : * is set in which case we override whatever was found earlier.
825 : : */
826 : : #ifdef CONFIG_CMDLINE
827 : : #ifndef CONFIG_CMDLINE_FORCE
828 [ # # ]: 0 : if (!((char *)data)[0])
829 : : #endif
830 : 0 : strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
831 : : #endif /* CONFIG_CMDLINE */
832 : :
833 : : pr_debug("Command line is: %s\n", (char*)data);
834 : :
835 : : /* break now */
836 : : return 1;
837 : : }
838 : :
839 : : #ifdef CONFIG_HAVE_MEMBLOCK
840 : 0 : void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
841 : : {
842 : 0 : const u64 phys_offset = __pa(PAGE_OFFSET);
843 : 0 : base &= PAGE_MASK;
844 : 0 : size &= PAGE_MASK;
845 [ # # ]: 0 : if (base + size < phys_offset) {
846 : 0 : pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
847 : : base, base + size);
848 : 0 : return;
849 : : }
850 [ # # ]: 0 : if (base < phys_offset) {
851 : 0 : pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
852 : : base, phys_offset);
853 : 0 : size -= phys_offset - base;
854 : : base = phys_offset;
855 : : }
856 : 0 : memblock_add(base, size);
857 : : }
858 : :
859 : : /*
860 : : * called from unflatten_device_tree() to bootstrap devicetree itself
861 : : * Architectures can override this definition if memblock isn't used
862 : : */
863 : 0 : void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align)
864 : : {
865 : 0 : return __va(memblock_alloc(size, align));
866 : : }
867 : : #endif
868 : :
869 : 0 : bool __init early_init_dt_scan(void *params)
870 : : {
871 [ # # ]: 0 : if (!params)
872 : : return false;
873 : :
874 : : /* Setup flat device-tree pointer */
875 : 0 : initial_boot_params = params;
876 : :
877 : : /* check device tree validity */
878 [ # # ][ # # ]: 0 : if (be32_to_cpu(initial_boot_params->magic) != OF_DT_HEADER) {
879 : 0 : initial_boot_params = NULL;
880 : 0 : return false;
881 : : }
882 : :
883 : : /* Retrieve various information from the /chosen node */
884 : 0 : of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
885 : :
886 : : /* Initialize {size,address}-cells info */
887 : 0 : of_scan_flat_dt(early_init_dt_scan_root, NULL);
888 : :
889 : : /* Setup memory, calling early_init_dt_add_memory_arch */
890 : 0 : of_scan_flat_dt(early_init_dt_scan_memory, NULL);
891 : :
892 : 0 : return true;
893 : : }
894 : :
895 : : /**
896 : : * unflatten_device_tree - create tree of device_nodes from flat blob
897 : : *
898 : : * unflattens the device-tree passed by the firmware, creating the
899 : : * tree of struct device_node. It also fills the "name" and "type"
900 : : * pointers of the nodes so the normal device-tree walking functions
901 : : * can be used.
902 : : */
903 : 0 : void __init unflatten_device_tree(void)
904 : : {
905 : 0 : __unflatten_device_tree(initial_boot_params, &of_allnodes,
906 : : early_init_dt_alloc_memory_arch);
907 : :
908 : : /* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */
909 : 0 : of_alias_scan(early_init_dt_alloc_memory_arch);
910 : 0 : }
911 : :
912 : : /**
913 : : * unflatten_and_copy_device_tree - copy and create tree of device_nodes from flat blob
914 : : *
915 : : * Copies and unflattens the device-tree passed by the firmware, creating the
916 : : * tree of struct device_node. It also fills the "name" and "type"
917 : : * pointers of the nodes so the normal device-tree walking functions
918 : : * can be used. This should only be used when the FDT memory has not been
919 : : * reserved such is the case when the FDT is built-in to the kernel init
920 : : * section. If the FDT memory is reserved already then unflatten_device_tree
921 : : * should be used instead.
922 : : */
923 : 0 : void __init unflatten_and_copy_device_tree(void)
924 : : {
925 : : int size;
926 : : void *dt;
927 : :
928 [ # # ]: 0 : if (!initial_boot_params) {
929 : 0 : pr_warn("No valid device tree found, continuing without\n");
930 : 0 : return;
931 : : }
932 : :
933 [ # # ]: 0 : size = __be32_to_cpu(initial_boot_params->totalsize);
934 : 0 : dt = early_init_dt_alloc_memory_arch(size,
935 : : __alignof__(struct boot_param_header));
936 : :
937 [ # # ]: 0 : if (dt) {
938 : 0 : memcpy(dt, initial_boot_params, size);
939 : 0 : initial_boot_params = dt;
940 : : }
941 : 0 : unflatten_device_tree();
942 : : }
943 : :
944 : : #endif /* CONFIG_OF_EARLY_FLATTREE */
|