Merge branch 'next-devicetree' of git://git.secretlab.ca/git/linux-2.6
[pandora-kernel.git] / scripts / dtc / treesource.c
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
24 extern FILE *yyin;
25 extern int yyparse(void);
26
27 struct boot_info *the_boot_info;
28 int treesource_error;
29
30 struct boot_info *dt_from_source(const char *fname)
31 {
32         the_boot_info = NULL;
33         treesource_error = 0;
34
35         srcfile_push(fname);
36         yyin = current_srcfile->f;
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
47 static 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
55 static int isstring(char c)
56 {
57         return (isprint(c)
58                 || (c == '\0')
59                 || strchr("\a\b\t\n\v\f\r", c));
60 }
61
62 static void write_propval_string(FILE *f, struct data val)
63 {
64         const char *str = val.val;
65         int i;
66         struct marker *m = val.markers;
67
68         assert(str[val.len-1] == '\0');
69
70         while (m && (m->offset == 0)) {
71                 if (m->type == LABEL)
72                         fprintf(f, "%s: ", m->ref);
73                 m = m->next;
74         }
75         fprintf(f, "\"");
76
77         for (i = 0; i < (val.len-1); i++) {
78                 char c = str[i];
79
80                 switch (c) {
81                 case '\a':
82                         fprintf(f, "\\a");
83                         break;
84                 case '\b':
85                         fprintf(f, "\\b");
86                         break;
87                 case '\t':
88                         fprintf(f, "\\t");
89                         break;
90                 case '\n':
91                         fprintf(f, "\\n");
92                         break;
93                 case '\v':
94                         fprintf(f, "\\v");
95                         break;
96                 case '\f':
97                         fprintf(f, "\\f");
98                         break;
99                 case '\r':
100                         fprintf(f, "\\r");
101                         break;
102                 case '\\':
103                         fprintf(f, "\\\\");
104                         break;
105                 case '\"':
106                         fprintf(f, "\\\"");
107                         break;
108                 case '\0':
109                         fprintf(f, "\", ");
110                         while (m && (m->offset < i)) {
111                                 if (m->type == LABEL) {
112                                         assert(m->offset == (i+1));
113                                         fprintf(f, "%s: ", m->ref);
114                                 }
115                                 m = m->next;
116                         }
117                         fprintf(f, "\"");
118                         break;
119                 default:
120                         if (isprint(c))
121                                 fprintf(f, "%c", c);
122                         else
123                                 fprintf(f, "\\x%02hhx", c);
124                 }
125         }
126         fprintf(f, "\"");
127
128         /* Wrap up any labels at the end of the value */
129         for_each_marker_of_type(m, LABEL) {
130                 assert (m->offset == val.len);
131                 fprintf(f, " %s:", m->ref);
132         }
133 }
134
135 static void write_propval_cells(FILE *f, struct data val)
136 {
137         void *propend = val.val + val.len;
138         cell_t *cp = (cell_t *)val.val;
139         struct marker *m = val.markers;
140
141         fprintf(f, "<");
142         for (;;) {
143                 while (m && (m->offset <= ((char *)cp - val.val))) {
144                         if (m->type == LABEL) {
145                                 assert(m->offset == ((char *)cp - val.val));
146                                 fprintf(f, "%s: ", m->ref);
147                         }
148                         m = m->next;
149                 }
150
151                 fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
152                 if ((void *)cp >= propend)
153                         break;
154                 fprintf(f, " ");
155         }
156
157         /* Wrap up any labels at the end of the value */
158         for_each_marker_of_type(m, LABEL) {
159                 assert (m->offset == val.len);
160                 fprintf(f, " %s:", m->ref);
161         }
162         fprintf(f, ">");
163 }
164
165 static void write_propval_bytes(FILE *f, struct data val)
166 {
167         void *propend = val.val + val.len;
168         const char *bp = val.val;
169         struct marker *m = val.markers;
170
171         fprintf(f, "[");
172         for (;;) {
173                 while (m && (m->offset == (bp-val.val))) {
174                         if (m->type == LABEL)
175                                 fprintf(f, "%s: ", m->ref);
176                         m = m->next;
177                 }
178
179                 fprintf(f, "%02hhx", *bp++);
180                 if ((const void *)bp >= propend)
181                         break;
182                 fprintf(f, " ");
183         }
184
185         /* Wrap up any labels at the end of the value */
186         for_each_marker_of_type(m, LABEL) {
187                 assert (m->offset == val.len);
188                 fprintf(f, " %s:", m->ref);
189         }
190         fprintf(f, "]");
191 }
192
193 static void write_propval(FILE *f, struct property *prop)
194 {
195         int len = prop->val.len;
196         const char *p = prop->val.val;
197         struct marker *m = prop->val.markers;
198         int nnotstring = 0, nnul = 0;
199         int nnotstringlbl = 0, nnotcelllbl = 0;
200         int i;
201
202         if (len == 0) {
203                 fprintf(f, ";\n");
204                 return;
205         }
206
207         for (i = 0; i < len; i++) {
208                 if (! isstring(p[i]))
209                         nnotstring++;
210                 if (p[i] == '\0')
211                         nnul++;
212         }
213
214         for_each_marker_of_type(m, LABEL) {
215                 if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
216                         nnotstringlbl++;
217                 if ((m->offset % sizeof(cell_t)) != 0)
218                         nnotcelllbl++;
219         }
220
221         fprintf(f, " = ");
222         if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
223             && (nnotstringlbl == 0)) {
224                 write_propval_string(f, prop->val);
225         } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
226                 write_propval_cells(f, prop->val);
227         } else {
228                 write_propval_bytes(f, prop->val);
229         }
230
231         fprintf(f, ";\n");
232 }
233
234 static void write_tree_source_node(FILE *f, struct node *tree, int level)
235 {
236         struct property *prop;
237         struct node *child;
238         struct label *l;
239
240         write_prefix(f, level);
241         for_each_label(tree->labels, l)
242                 fprintf(f, "%s: ", l->label);
243         if (tree->name && (*tree->name))
244                 fprintf(f, "%s {\n", tree->name);
245         else
246                 fprintf(f, "/ {\n");
247
248         for_each_property(tree, prop) {
249                 write_prefix(f, level+1);
250                 for_each_label(prop->labels, l)
251                         fprintf(f, "%s: ", l->label);
252                 fprintf(f, "%s", prop->name);
253                 write_propval(f, prop);
254         }
255         for_each_child(tree, child) {
256                 fprintf(f, "\n");
257                 write_tree_source_node(f, child, level+1);
258         }
259         write_prefix(f, level);
260         fprintf(f, "};\n");
261 }
262
263
264 void dt_to_source(FILE *f, struct boot_info *bi)
265 {
266         struct reserve_info *re;
267
268         fprintf(f, "/dts-v1/;\n\n");
269
270         for (re = bi->reservelist; re; re = re->next) {
271                 struct label *l;
272
273                 for_each_label(re->labels, l)
274                         fprintf(f, "%s: ", l->label);
275                 fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
276                         (unsigned long long)re->re.address,
277                         (unsigned long long)re->re.size);
278         }
279
280         write_tree_source_node(f, bi->dt, 0);
281 }
282