aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/dtc/treesource.c
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2009-04-30 01:25:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-05-02 19:52:26 -0400
commit9fffb55f66127b52c937ede5196ebfa0c0d50bce (patch)
tree11664fb82734ba8dcde9556b8d47e780451a740a /scripts/dtc/treesource.c
parentafc1e702e8e8355faa712d4e90d9afe26a4995a5 (diff)
Move dtc and libfdt sources from arch/powerpc/boot to scripts/dtc
The powerpc kernel always requires an Open Firmware like device tree to supply device information. On systems without OF, this comes from a flattened device tree blob. This blob is usually generated by dtc, a tool which compiles a text description of the device tree into the flattened format used by the kernel. Sometimes, the bootwrapper makes small changes to the pre-compiled device tree blob (e.g. filling in the size of RAM). To do this it uses the libfdt library. Because these are only used on powerpc, the code for both these tools is included under arch/powerpc/boot (these were imported and are periodically updated from the upstream dtc tree). However, the microblaze architecture, currently being prepared for merging to mainline also uses dtc to produce device tree blobs. A few other archs have also mentioned some interest in using dtc. Therefore, this patch moves dtc and libfdt from arch/powerpc into scripts, where it can be used by any architecture. The vast bulk of this patch is a literal move, the rest is adjusting the various Makefiles to use dtc and libfdt correctly from their new locations. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'scripts/dtc/treesource.c')
-rw-r--r--scripts/dtc/treesource.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c
new file mode 100644
index 000000000000..ebeb6eb27907
--- /dev/null
+++ b/scripts/dtc/treesource.c
@@ -0,0 +1,278 @@
1/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
3 *
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20
21#include "dtc.h"
22#include "srcpos.h"
23
24extern FILE *yyin;
25extern int yyparse(void);
26
27struct boot_info *the_boot_info;
28int treesource_error;
29
30struct boot_info *dt_from_source(const char *fname)
31{
32 the_boot_info = NULL;
33 treesource_error = 0;
34
35 srcpos_file = dtc_open_file(fname, NULL);
36 yyin = srcpos_file->file;
37
38 if (yyparse() != 0)
39 die("Unable to parse input tree\n");
40
41 if (treesource_error)
42 die("Syntax error parsing input tree\n");
43
44 return the_boot_info;
45}
46
47static void write_prefix(FILE *f, int level)
48{
49 int i;
50
51 for (i = 0; i < level; i++)
52 fputc('\t', f);
53}
54
55int isstring(char c)
56{
57 return (isprint(c)
58 || (c == '\0')
59 || strchr("\a\b\t\n\v\f\r", c));
60}
61
62static void write_propval_string(FILE *f, struct data val)
63{
64 const char *str = val.val;
65 int i;
66 int newchunk = 1;
67 struct marker *m = val.markers;
68
69 assert(str[val.len-1] == '\0');
70
71 for (i = 0; i < (val.len-1); i++) {
72 char c = str[i];
73
74 if (newchunk) {
75 while (m && (m->offset <= i)) {
76 if (m->type == LABEL) {
77 assert(m->offset == i);
78 fprintf(f, "%s: ", m->ref);
79 }
80 m = m->next;
81 }
82 fprintf(f, "\"");
83 newchunk = 0;
84 }
85
86 switch (c) {
87 case '\a':
88 fprintf(f, "\\a");
89 break;
90 case '\b':
91 fprintf(f, "\\b");
92 break;
93 case '\t':
94 fprintf(f, "\\t");
95 break;
96 case '\n':
97 fprintf(f, "\\n");
98 break;
99 case '\v':
100 fprintf(f, "\\v");
101 break;
102 case '\f':
103 fprintf(f, "\\f");
104 break;
105 case '\r':
106 fprintf(f, "\\r");
107 break;
108 case '\\':
109 fprintf(f, "\\\\");
110 break;
111 case '\"':
112 fprintf(f, "\\\"");
113 break;
114 case '\0':
115 fprintf(f, "\", ");
116 newchunk = 1;
117 break;
118 default:
119 if (isprint(c))
120 fprintf(f, "%c", c);
121 else
122 fprintf(f, "\\x%02hhx", c);
123 }
124 }
125 fprintf(f, "\"");
126
127 /* Wrap up any labels at the end of the value */
128 for_each_marker_of_type(m, LABEL) {
129 assert (m->offset == val.len);
130 fprintf(f, " %s:", m->ref);
131 }
132}
133
134static void write_propval_cells(FILE *f, struct data val)
135{
136 void *propend = val.val + val.len;
137 cell_t *cp = (cell_t *)val.val;
138 struct marker *m = val.markers;
139
140 fprintf(f, "<");
141 for (;;) {
142 while (m && (m->offset <= ((char *)cp - val.val))) {
143 if (m->type == LABEL) {
144 assert(m->offset == ((char *)cp - val.val));
145 fprintf(f, "%s: ", m->ref);
146 }
147 m = m->next;
148 }
149
150 fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
151 if ((void *)cp >= propend)
152 break;
153 fprintf(f, " ");
154 }
155
156 /* Wrap up any labels at the end of the value */
157 for_each_marker_of_type(m, LABEL) {
158 assert (m->offset == val.len);
159 fprintf(f, " %s:", m->ref);
160 }
161 fprintf(f, ">");
162}
163
164static void write_propval_bytes(FILE *f, struct data val)
165{
166 void *propend = val.val + val.len;
167 const char *bp = val.val;
168 struct marker *m = val.markers;
169
170 fprintf(f, "[");
171 for (;;) {
172 while (m && (m->offset == (bp-val.val))) {
173 if (m->type == LABEL)
174 fprintf(f, "%s: ", m->ref);
175 m = m->next;
176 }
177
178 fprintf(f, "%02hhx", *bp++);
179 if ((const void *)bp >= propend)
180 break;
181 fprintf(f, " ");
182 }
183
184 /* Wrap up any labels at the end of the value */
185 for_each_marker_of_type(m, LABEL) {
186 assert (m->offset == val.len);
187 fprintf(f, " %s:", m->ref);
188 }
189 fprintf(f, "]");
190}
191
192static void write_propval(FILE *f, struct property *prop)
193{
194 int len = prop->val.len;
195 const char *p = prop->val.val;
196 struct marker *m = prop->val.markers;
197 int nnotstring = 0, nnul = 0;
198 int nnotstringlbl = 0, nnotcelllbl = 0;
199 int i;
200
201 if (len == 0) {
202 fprintf(f, ";\n");
203 return;
204 }
205
206 for (i = 0; i < len; i++) {
207 if (! isstring(p[i]))
208 nnotstring++;
209 if (p[i] == '\0')
210 nnul++;
211 }
212
213 for_each_marker_of_type(m, LABEL) {
214 if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
215 nnotstringlbl++;
216 if ((m->offset % sizeof(cell_t)) != 0)
217 nnotcelllbl++;
218 }
219
220 fprintf(f, " = ");
221 if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
222 && (nnotstringlbl == 0)) {
223 write_propval_string(f, prop->val);
224 } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
225 write_propval_cells(f, prop->val);
226 } else {
227 write_propval_bytes(f, prop->val);
228 }
229
230 fprintf(f, ";\n");
231}
232
233static void write_tree_source_node(FILE *f, struct node *tree, int level)
234{
235 struct property *prop;
236 struct node *child;
237
238 write_prefix(f, level);
239 if (tree->label)
240 fprintf(f, "%s: ", tree->label);
241 if (tree->name && (*tree->name))
242 fprintf(f, "%s {\n", tree->name);
243 else
244 fprintf(f, "/ {\n");
245
246 for_each_property(tree, prop) {
247 write_prefix(f, level+1);
248 if (prop->label)
249 fprintf(f, "%s: ", prop->label);
250 fprintf(f, "%s", prop->name);
251 write_propval(f, prop);
252 }
253 for_each_child(tree, child) {
254 fprintf(f, "\n");
255 write_tree_source_node(f, child, level+1);
256 }
257 write_prefix(f, level);
258 fprintf(f, "};\n");
259}
260
261
262void dt_to_source(FILE *f, struct boot_info *bi)
263{
264 struct reserve_info *re;
265
266 fprintf(f, "/dts-v1/;\n\n");
267
268 for (re = bi->reservelist; re; re = re->next) {
269 if (re->label)
270 fprintf(f, "%s: ", re->label);
271 fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
272 (unsigned long long)re->re.address,
273 (unsigned long long)re->re.size);
274 }
275
276 write_tree_source_node(f, bi->dt, 0);
277}
278