Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fdt.c
Go to the documentation of this file.
1 /*
2  * Functions for working with the Flattened Device Tree data format
3  *
4  * Copyright 2009 Benjamin Herrenschmidt, IBM Corp
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/module.h>
15 #include <linux/of.h>
16 #include <linux/of_fdt.h>
17 #include <linux/string.h>
18 #include <linux/errno.h>
19 #include <linux/slab.h>
20 
21 #include <asm/setup.h> /* for COMMAND_LINE_SIZE */
22 #ifdef CONFIG_PPC
23 #include <asm/machdep.h>
24 #endif /* CONFIG_PPC */
25 
26 #include <asm/page.h>
27 
29 {
30  return ((char *)blob) +
32 }
33 
39  unsigned long node, const char *name,
40  unsigned long *size)
41 {
42  unsigned long p = node;
43 
44  do {
45  u32 tag = be32_to_cpup((__be32 *)p);
46  u32 sz, noff;
47  const char *nstr;
48 
49  p += 4;
50  if (tag == OF_DT_NOP)
51  continue;
52  if (tag != OF_DT_PROP)
53  return NULL;
54 
55  sz = be32_to_cpup((__be32 *)p);
56  noff = be32_to_cpup((__be32 *)(p + 4));
57  p += 8;
58  if (be32_to_cpu(blob->version) < 0x10)
59  p = ALIGN(p, sz >= 8 ? 8 : 4);
60 
61  nstr = of_fdt_get_string(blob, noff);
62  if (nstr == NULL) {
63  pr_warning("Can't find property index name !\n");
64  return NULL;
65  }
66  if (strcmp(name, nstr) == 0) {
67  if (size)
68  *size = sz;
69  return (void *)p;
70  }
71  p += sz;
72  p = ALIGN(p, 4);
73  } while (1);
74 }
75 
87  unsigned long node, const char *compat)
88 {
89  const char *cp;
90  unsigned long cplen, l, score = 0;
91 
92  cp = of_fdt_get_property(blob, node, "compatible", &cplen);
93  if (cp == NULL)
94  return 0;
95  while (cplen > 0) {
96  score++;
97  if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
98  return score;
99  l = strlen(cp) + 1;
100  cp += l;
101  cplen -= l;
102  }
103 
104  return 0;
105 }
106 
110 int of_fdt_match(struct boot_param_header *blob, unsigned long node,
111  const char *const *compat)
112 {
113  unsigned int tmp, score = 0;
114 
115  if (!compat)
116  return 0;
117 
118  while (*compat) {
119  tmp = of_fdt_is_compatible(blob, node, *compat);
120  if (tmp && (score == 0 || (tmp < score)))
121  score = tmp;
122  compat++;
123  }
124 
125  return score;
126 }
127 
128 static void *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
129  unsigned long align)
130 {
131  void *res;
132 
133  *mem = ALIGN(*mem, align);
134  res = (void *)*mem;
135  *mem += size;
136 
137  return res;
138 }
139 
149 static unsigned long unflatten_dt_node(struct boot_param_header *blob,
150  unsigned long mem,
151  unsigned long *p,
152  struct device_node *dad,
153  struct device_node ***allnextpp,
154  unsigned long fpsize)
155 {
156  struct device_node *np;
157  struct property *pp, **prev_pp = NULL;
158  char *pathp;
159  u32 tag;
160  unsigned int l, allocl;
161  int has_name = 0;
162  int new_format = 0;
163 
164  tag = be32_to_cpup((__be32 *)(*p));
165  if (tag != OF_DT_BEGIN_NODE) {
166  pr_err("Weird tag at start of node: %x\n", tag);
167  return mem;
168  }
169  *p += 4;
170  pathp = (char *)*p;
171  l = allocl = strlen(pathp) + 1;
172  *p = ALIGN(*p + l, 4);
173 
174  /* version 0x10 has a more compact unit name here instead of the full
175  * path. we accumulate the full path size using "fpsize", we'll rebuild
176  * it later. We detect this because the first character of the name is
177  * not '/'.
178  */
179  if ((*pathp) != '/') {
180  new_format = 1;
181  if (fpsize == 0) {
182  /* root node: special case. fpsize accounts for path
183  * plus terminating zero. root node only has '/', so
184  * fpsize should be 2, but we want to avoid the first
185  * level nodes to have two '/' so we use fpsize 1 here
186  */
187  fpsize = 1;
188  allocl = 2;
189  } else {
190  /* account for '/' and path size minus terminal 0
191  * already in 'l'
192  */
193  fpsize += l;
194  allocl = fpsize;
195  }
196  }
197 
198  np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
199  __alignof__(struct device_node));
200  if (allnextpp) {
201  memset(np, 0, sizeof(*np));
202  np->full_name = ((char *)np) + sizeof(struct device_node);
203  if (new_format) {
204  char *fn = np->full_name;
205  /* rebuild full path for new format */
206  if (dad && dad->parent) {
207  strcpy(fn, dad->full_name);
208 #ifdef DEBUG
209  if ((strlen(fn) + l + 1) != allocl) {
210  pr_debug("%s: p: %d, l: %d, a: %d\n",
211  pathp, (int)strlen(fn),
212  l, allocl);
213  }
214 #endif
215  fn += strlen(fn);
216  }
217  *(fn++) = '/';
218  memcpy(fn, pathp, l);
219  } else
220  memcpy(np->full_name, pathp, l);
221  prev_pp = &np->properties;
222  **allnextpp = np;
223  *allnextpp = &np->allnext;
224  if (dad != NULL) {
225  np->parent = dad;
226  /* we temporarily use the next field as `last_child'*/
227  if (dad->next == NULL)
228  dad->child = np;
229  else
230  dad->next->sibling = np;
231  dad->next = np;
232  }
233  kref_init(&np->kref);
234  }
235  /* process properties */
236  while (1) {
237  u32 sz, noff;
238  char *pname;
239 
240  tag = be32_to_cpup((__be32 *)(*p));
241  if (tag == OF_DT_NOP) {
242  *p += 4;
243  continue;
244  }
245  if (tag != OF_DT_PROP)
246  break;
247  *p += 4;
248  sz = be32_to_cpup((__be32 *)(*p));
249  noff = be32_to_cpup((__be32 *)((*p) + 4));
250  *p += 8;
251  if (be32_to_cpu(blob->version) < 0x10)
252  *p = ALIGN(*p, sz >= 8 ? 8 : 4);
253 
254  pname = of_fdt_get_string(blob, noff);
255  if (pname == NULL) {
256  pr_info("Can't find property name in list !\n");
257  break;
258  }
259  if (strcmp(pname, "name") == 0)
260  has_name = 1;
261  l = strlen(pname) + 1;
262  pp = unflatten_dt_alloc(&mem, sizeof(struct property),
263  __alignof__(struct property));
264  if (allnextpp) {
265  /* We accept flattened tree phandles either in
266  * ePAPR-style "phandle" properties, or the
267  * legacy "linux,phandle" properties. If both
268  * appear and have different values, things
269  * will get weird. Don't do that. */
270  if ((strcmp(pname, "phandle") == 0) ||
271  (strcmp(pname, "linux,phandle") == 0)) {
272  if (np->phandle == 0)
273  np->phandle = be32_to_cpup((__be32*)*p);
274  }
275  /* And we process the "ibm,phandle" property
276  * used in pSeries dynamic device tree
277  * stuff */
278  if (strcmp(pname, "ibm,phandle") == 0)
279  np->phandle = be32_to_cpup((__be32 *)*p);
280  pp->name = pname;
281  pp->length = sz;
282  pp->value = (void *)*p;
283  *prev_pp = pp;
284  prev_pp = &pp->next;
285  }
286  *p = ALIGN((*p) + sz, 4);
287  }
288  /* with version 0x10 we may not have the name property, recreate
289  * it here from the unit name if absent
290  */
291  if (!has_name) {
292  char *p1 = pathp, *ps = pathp, *pa = NULL;
293  int sz;
294 
295  while (*p1) {
296  if ((*p1) == '@')
297  pa = p1;
298  if ((*p1) == '/')
299  ps = p1 + 1;
300  p1++;
301  }
302  if (pa < ps)
303  pa = p1;
304  sz = (pa - ps) + 1;
305  pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
306  __alignof__(struct property));
307  if (allnextpp) {
308  pp->name = "name";
309  pp->length = sz;
310  pp->value = pp + 1;
311  *prev_pp = pp;
312  prev_pp = &pp->next;
313  memcpy(pp->value, ps, sz - 1);
314  ((char *)pp->value)[sz - 1] = 0;
315  pr_debug("fixed up name for %s -> %s\n", pathp,
316  (char *)pp->value);
317  }
318  }
319  if (allnextpp) {
320  *prev_pp = NULL;
321  np->name = of_get_property(np, "name", NULL);
322  np->type = of_get_property(np, "device_type", NULL);
323 
324  if (!np->name)
325  np->name = "<NULL>";
326  if (!np->type)
327  np->type = "<NULL>";
328  }
329  while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) {
330  if (tag == OF_DT_NOP)
331  *p += 4;
332  else
333  mem = unflatten_dt_node(blob, mem, p, np, allnextpp,
334  fpsize);
335  tag = be32_to_cpup((__be32 *)(*p));
336  }
337  if (tag != OF_DT_END_NODE) {
338  pr_err("Weird tag at end of node: %x\n", tag);
339  return mem;
340  }
341  *p += 4;
342  return mem;
343 }
344 
357 static void __unflatten_device_tree(struct boot_param_header *blob,
358  struct device_node **mynodes,
359  void * (*dt_alloc)(u64 size, u64 align))
360 {
361  unsigned long start, mem, size;
362  struct device_node **allnextp = mynodes;
363 
364  pr_debug(" -> unflatten_device_tree()\n");
365 
366  if (!blob) {
367  pr_debug("No device tree pointer\n");
368  return;
369  }
370 
371  pr_debug("Unflattening device tree:\n");
372  pr_debug("magic: %08x\n", be32_to_cpu(blob->magic));
373  pr_debug("size: %08x\n", be32_to_cpu(blob->totalsize));
374  pr_debug("version: %08x\n", be32_to_cpu(blob->version));
375 
376  if (be32_to_cpu(blob->magic) != OF_DT_HEADER) {
377  pr_err("Invalid device tree blob header\n");
378  return;
379  }
380 
381  /* First pass, scan for size */
382  start = ((unsigned long)blob) +
383  be32_to_cpu(blob->off_dt_struct);
384  size = unflatten_dt_node(blob, 0, &start, NULL, NULL, 0);
385  size = (size | 3) + 1;
386 
387  pr_debug(" size is %lx, allocating...\n", size);
388 
389  /* Allocate memory for the expanded device tree */
390  mem = (unsigned long)
391  dt_alloc(size + 4, __alignof__(struct device_node));
392 
393  ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef);
394 
395  pr_debug(" unflattening %lx...\n", mem);
396 
397  /* Second pass, do actual unflattening */
398  start = ((unsigned long)blob) +
399  be32_to_cpu(blob->off_dt_struct);
400  unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0);
401  if (be32_to_cpup((__be32 *)start) != OF_DT_END)
402  pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start));
403  if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef)
404  pr_warning("End of tree marker overwritten: %08x\n",
405  be32_to_cpu(((__be32 *)mem)[size / 4]));
406  *allnextp = NULL;
407 
408  pr_debug(" <- unflatten_device_tree()\n");
409 }
410 
411 static void *kernel_tree_alloc(u64 size, u64 align)
412 {
413  return kzalloc(size, GFP_KERNEL);
414 }
415 
424 void of_fdt_unflatten_tree(unsigned long *blob,
425  struct device_node **mynodes)
426 {
427  struct boot_param_header *device_tree =
428  (struct boot_param_header *)blob;
429  __unflatten_device_tree(device_tree, mynodes, &kernel_tree_alloc);
430 }
432 
433 /* Everything below here references initial_boot_params directly. */
436 
438 
439 #ifdef CONFIG_OF_EARLY_FLATTREE
440 
450 int __init of_scan_flat_dt(int (*it)(unsigned long node,
451  const char *uname, int depth,
452  void *data),
453  void *data)
454 {
455  unsigned long p = ((unsigned long)initial_boot_params) +
456  be32_to_cpu(initial_boot_params->off_dt_struct);
457  int rc = 0;
458  int depth = -1;
459 
460  do {
461  u32 tag = be32_to_cpup((__be32 *)p);
462  char *pathp;
463 
464  p += 4;
465  if (tag == OF_DT_END_NODE) {
466  depth--;
467  continue;
468  }
469  if (tag == OF_DT_NOP)
470  continue;
471  if (tag == OF_DT_END)
472  break;
473  if (tag == OF_DT_PROP) {
474  u32 sz = be32_to_cpup((__be32 *)p);
475  p += 8;
476  if (be32_to_cpu(initial_boot_params->version) < 0x10)
477  p = ALIGN(p, sz >= 8 ? 8 : 4);
478  p += sz;
479  p = ALIGN(p, 4);
480  continue;
481  }
482  if (tag != OF_DT_BEGIN_NODE) {
483  pr_err("Invalid tag %x in flat device tree!\n", tag);
484  return -EINVAL;
485  }
486  depth++;
487  pathp = (char *)p;
488  p = ALIGN(p + strlen(pathp) + 1, 4);
489  if ((*pathp) == '/') {
490  char *lp, *np;
491  for (lp = NULL, np = pathp; *np; np++)
492  if ((*np) == '/')
493  lp = np+1;
494  if (lp != NULL)
495  pathp = lp;
496  }
497  rc = it(p, pathp, depth, data);
498  if (rc != 0)
499  break;
500  } while (1);
501 
502  return rc;
503 }
504 
508 unsigned long __init of_get_flat_dt_root(void)
509 {
510  unsigned long p = ((unsigned long)initial_boot_params) +
511  be32_to_cpu(initial_boot_params->off_dt_struct);
512 
513  while (be32_to_cpup((__be32 *)p) == OF_DT_NOP)
514  p += 4;
516  p += 4;
517  return ALIGN(p + strlen((char *)p) + 1, 4);
518 }
519 
526 void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
527  unsigned long *size)
528 {
529  return of_fdt_get_property(initial_boot_params, node, name, size);
530 }
531 
537 int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
538 {
539  return of_fdt_is_compatible(initial_boot_params, node, compat);
540 }
541 
545 int __init of_flat_dt_match(unsigned long node, const char *const *compat)
546 {
547  return of_fdt_match(initial_boot_params, node, compat);
548 }
549 
550 #ifdef CONFIG_BLK_DEV_INITRD
551 
555 void __init early_init_dt_check_for_initrd(unsigned long node)
556 {
557  unsigned long start, end, len;
558  __be32 *prop;
559 
560  pr_debug("Looking for initrd properties... ");
561 
562  prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len);
563  if (!prop)
564  return;
565  start = of_read_ulong(prop, len/4);
566 
567  prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len);
568  if (!prop)
569  return;
570  end = of_read_ulong(prop, len/4);
571 
573  pr_debug("initrd_start=0x%lx initrd_end=0x%lx\n", start, end);
574 }
575 #else
576 inline void early_init_dt_check_for_initrd(unsigned long node)
577 {
578 }
579 #endif /* CONFIG_BLK_DEV_INITRD */
580 
584 int __init early_init_dt_scan_root(unsigned long node, const char *uname,
585  int depth, void *data)
586 {
587  __be32 *prop;
588 
589  if (depth != 0)
590  return 0;
591 
592  dt_root_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
593  dt_root_addr_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
594 
595  prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
596  if (prop)
597  dt_root_size_cells = be32_to_cpup(prop);
598  pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells);
599 
600  prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
601  if (prop)
602  dt_root_addr_cells = be32_to_cpup(prop);
603  pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);
604 
605  /* break now */
606  return 1;
607 }
608 
609 u64 __init dt_mem_next_cell(int s, __be32 **cellp)
610 {
611  __be32 *p = *cellp;
612 
613  *cellp = p + s;
614  return of_read_number(p, s);
615 }
616 
620 int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
621  int depth, void *data)
622 {
623  char *type = of_get_flat_dt_prop(node, "device_type", NULL);
624  __be32 *reg, *endp;
625  unsigned long l;
626 
627  /* We are scanning "memory" nodes only */
628  if (type == NULL) {
629  /*
630  * The longtrail doesn't have a device_type on the
631  * /memory node, so look for the node called /memory@0.
632  */
633  if (depth != 1 || strcmp(uname, "memory@0") != 0)
634  return 0;
635  } else if (strcmp(type, "memory") != 0)
636  return 0;
637 
638  reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
639  if (reg == NULL)
640  reg = of_get_flat_dt_prop(node, "reg", &l);
641  if (reg == NULL)
642  return 0;
643 
644  endp = reg + (l / sizeof(__be32));
645 
646  pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",
647  uname, l, reg[0], reg[1], reg[2], reg[3]);
648 
649  while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
650  u64 base, size;
651 
652  base = dt_mem_next_cell(dt_root_addr_cells, &reg);
653  size = dt_mem_next_cell(dt_root_size_cells, &reg);
654 
655  if (size == 0)
656  continue;
657  pr_debug(" - %llx , %llx\n", (unsigned long long)base,
658  (unsigned long long)size);
659 
660  early_init_dt_add_memory_arch(base, size);
661  }
662 
663  return 0;
664 }
665 
666 int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
667  int depth, void *data)
668 {
669  unsigned long l;
670  char *p;
671 
672  pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
673 
674  if (depth != 1 || !data ||
675  (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
676  return 0;
677 
678  early_init_dt_check_for_initrd(node);
679 
680  /* Retrieve command line */
681  p = of_get_flat_dt_prop(node, "bootargs", &l);
682  if (p != NULL && l > 0)
683  strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));
684 
685  /*
686  * CONFIG_CMDLINE is meant to be a default in case nothing else
687  * managed to set the command line, unless CONFIG_CMDLINE_FORCE
688  * is set in which case we override whatever was found earlier.
689  */
690 #ifdef CONFIG_CMDLINE
691 #ifndef CONFIG_CMDLINE_FORCE
692  if (!((char *)data)[0])
693 #endif
694  strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
695 #endif /* CONFIG_CMDLINE */
696 
697  pr_debug("Command line is: %s\n", (char*)data);
698 
699  /* break now */
700  return 1;
701 }
702 
711 void __init unflatten_device_tree(void)
712 {
713  __unflatten_device_tree(initial_boot_params, &allnodes,
715 
716  /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
718 }
719 
720 #endif /* CONFIG_OF_EARLY_FLATTREE */