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