Thu Jun 8 17:24:10 2017 UTC ()
s/ALIGN/FDTALIGN2/


(skrll)
diff -r1.3 -r1.4 src/external/gpl2/dtc/dist/flattree.c

cvs diff -r1.3 -r1.4 src/external/gpl2/dtc/dist/flattree.c (switch to unified diff)

--- src/external/gpl2/dtc/dist/flattree.c 2017/06/08 16:00:40 1.3
+++ src/external/gpl2/dtc/dist/flattree.c 2017/06/08 17:24:10 1.4
@@ -1,942 +1,942 @@ @@ -1,942 +1,942 @@
1/* $NetBSD: flattree.c,v 1.3 2017/06/08 16:00:40 skrll Exp $ */ 1/* $NetBSD: flattree.c,v 1.4 2017/06/08 17:24:10 skrll Exp $ */
2 2
3/* 3/*
4 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 4 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
5 * 5 *
6 * 6 *
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as 8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the 9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version. 10 * License, or (at your option) any later version.
11 * 11 *
12 * This program is distributed in the hope that it will be useful, 12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details. 15 * General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU General Public License 17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software 18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA 20 * USA
21 */ 21 */
22 22
23#include "dtc.h" 23#include "dtc.h"
24#include "srcpos.h" 24#include "srcpos.h"
25 25
26#define FTF_FULLPATH 0x1 26#define FTF_FULLPATH 0x1
27#define FTF_VARALIGN 0x2 27#define FTF_VARALIGN 0x2
28#define FTF_NAMEPROPS 0x4 28#define FTF_NAMEPROPS 0x4
29#define FTF_BOOTCPUID 0x8 29#define FTF_BOOTCPUID 0x8
30#define FTF_STRTABSIZE 0x10 30#define FTF_STRTABSIZE 0x10
31#define FTF_STRUCTSIZE 0x20 31#define FTF_STRUCTSIZE 0x20
32#define FTF_NOPS 0x40 32#define FTF_NOPS 0x40
33 33
34static struct version_info { 34static struct version_info {
35 int version; 35 int version;
36 int last_comp_version; 36 int last_comp_version;
37 int hdr_size; 37 int hdr_size;
38 int flags; 38 int flags;
39} version_table[] = { 39} version_table[] = {
40 {1, 1, FDT_V1_SIZE, 40 {1, 1, FDT_V1_SIZE,
41 FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS}, 41 FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS},
42 {2, 1, FDT_V2_SIZE, 42 {2, 1, FDT_V2_SIZE,
43 FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID}, 43 FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID},
44 {3, 1, FDT_V3_SIZE, 44 {3, 1, FDT_V3_SIZE,
45 FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID|FTF_STRTABSIZE}, 45 FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID|FTF_STRTABSIZE},
46 {16, 16, FDT_V3_SIZE, 46 {16, 16, FDT_V3_SIZE,
47 FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_NOPS}, 47 FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_NOPS},
48 {17, 16, FDT_V17_SIZE, 48 {17, 16, FDT_V17_SIZE,
49 FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE|FTF_NOPS}, 49 FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE|FTF_NOPS},
50}; 50};
51 51
52struct emitter { 52struct emitter {
53 void (*cell)(void *, cell_t); 53 void (*cell)(void *, cell_t);
54 void (*string)(void *, const char *, int); 54 void (*string)(void *, const char *, int);
55 void (*align)(void *, int); 55 void (*align)(void *, int);
56 void (*data)(void *, struct data); 56 void (*data)(void *, struct data);
57 void (*beginnode)(void *, struct label *labels); 57 void (*beginnode)(void *, struct label *labels);
58 void (*endnode)(void *, struct label *labels); 58 void (*endnode)(void *, struct label *labels);
59 void (*property)(void *, struct label *labels); 59 void (*property)(void *, struct label *labels);
60}; 60};
61 61
62static void bin_emit_cell(void *e, cell_t val) 62static void bin_emit_cell(void *e, cell_t val)
63{ 63{
64 struct data *dtbuf = e; 64 struct data *dtbuf = e;
65 65
66 *dtbuf = data_append_cell(*dtbuf, val); 66 *dtbuf = data_append_cell(*dtbuf, val);
67} 67}
68 68
69static void bin_emit_string(void *e, const char *str, int len) 69static void bin_emit_string(void *e, const char *str, int len)
70{ 70{
71 struct data *dtbuf = e; 71 struct data *dtbuf = e;
72 72
73 if (len == 0) 73 if (len == 0)
74 len = strlen(str); 74 len = strlen(str);
75 75
76 *dtbuf = data_append_data(*dtbuf, str, len); 76 *dtbuf = data_append_data(*dtbuf, str, len);
77 *dtbuf = data_append_byte(*dtbuf, '\0'); 77 *dtbuf = data_append_byte(*dtbuf, '\0');
78} 78}
79 79
80static void bin_emit_align(void *e, int a) 80static void bin_emit_align(void *e, int a)
81{ 81{
82 struct data *dtbuf = e; 82 struct data *dtbuf = e;
83 83
84 *dtbuf = data_append_align(*dtbuf, a); 84 *dtbuf = data_append_align(*dtbuf, a);
85} 85}
86 86
87static void bin_emit_data(void *e, struct data d) 87static void bin_emit_data(void *e, struct data d)
88{ 88{
89 struct data *dtbuf = e; 89 struct data *dtbuf = e;
90 90
91 *dtbuf = data_append_data(*dtbuf, d.val, d.len); 91 *dtbuf = data_append_data(*dtbuf, d.val, d.len);
92} 92}
93 93
94static void bin_emit_beginnode(void *e, struct label *labels) 94static void bin_emit_beginnode(void *e, struct label *labels)
95{ 95{
96 bin_emit_cell(e, FDT_BEGIN_NODE); 96 bin_emit_cell(e, FDT_BEGIN_NODE);
97} 97}
98 98
99static void bin_emit_endnode(void *e, struct label *labels) 99static void bin_emit_endnode(void *e, struct label *labels)
100{ 100{
101 bin_emit_cell(e, FDT_END_NODE); 101 bin_emit_cell(e, FDT_END_NODE);
102} 102}
103 103
104static void bin_emit_property(void *e, struct label *labels) 104static void bin_emit_property(void *e, struct label *labels)
105{ 105{
106 bin_emit_cell(e, FDT_PROP); 106 bin_emit_cell(e, FDT_PROP);
107} 107}
108 108
109static struct emitter bin_emitter = { 109static struct emitter bin_emitter = {
110 .cell = bin_emit_cell, 110 .cell = bin_emit_cell,
111 .string = bin_emit_string, 111 .string = bin_emit_string,
112 .align = bin_emit_align, 112 .align = bin_emit_align,
113 .data = bin_emit_data, 113 .data = bin_emit_data,
114 .beginnode = bin_emit_beginnode, 114 .beginnode = bin_emit_beginnode,
115 .endnode = bin_emit_endnode, 115 .endnode = bin_emit_endnode,
116 .property = bin_emit_property, 116 .property = bin_emit_property,
117}; 117};
118 118
119static void emit_label(FILE *f, const char *prefix, const char *label) 119static void emit_label(FILE *f, const char *prefix, const char *label)
120{ 120{
121 fprintf(f, "\t.globl\t%s_%s\n", prefix, label); 121 fprintf(f, "\t.globl\t%s_%s\n", prefix, label);
122 fprintf(f, "%s_%s:\n", prefix, label); 122 fprintf(f, "%s_%s:\n", prefix, label);
123 fprintf(f, "_%s_%s:\n", prefix, label); 123 fprintf(f, "_%s_%s:\n", prefix, label);
124} 124}
125 125
126static void emit_offset_label(FILE *f, const char *label, int offset) 126static void emit_offset_label(FILE *f, const char *label, int offset)
127{ 127{
128 fprintf(f, "\t.globl\t%s\n", label); 128 fprintf(f, "\t.globl\t%s\n", label);
129 fprintf(f, "%s\t= . + %d\n", label, offset); 129 fprintf(f, "%s\t= . + %d\n", label, offset);
130} 130}
131 131
132#define ASM_EMIT_BELONG(f, fmt, ...) \ 132#define ASM_EMIT_BELONG(f, fmt, ...) \
133 { \ 133 { \
134 fprintf((f), "\t.byte\t((" fmt ") >> 24) & 0xff\n", __VA_ARGS__); \ 134 fprintf((f), "\t.byte\t((" fmt ") >> 24) & 0xff\n", __VA_ARGS__); \
135 fprintf((f), "\t.byte\t((" fmt ") >> 16) & 0xff\n", __VA_ARGS__); \ 135 fprintf((f), "\t.byte\t((" fmt ") >> 16) & 0xff\n", __VA_ARGS__); \
136 fprintf((f), "\t.byte\t((" fmt ") >> 8) & 0xff\n", __VA_ARGS__); \ 136 fprintf((f), "\t.byte\t((" fmt ") >> 8) & 0xff\n", __VA_ARGS__); \
137 fprintf((f), "\t.byte\t(" fmt ") & 0xff\n", __VA_ARGS__); \ 137 fprintf((f), "\t.byte\t(" fmt ") & 0xff\n", __VA_ARGS__); \
138 } 138 }
139 139
140static void asm_emit_cell(void *e, cell_t val) 140static void asm_emit_cell(void *e, cell_t val)
141{ 141{
142 FILE *f = e; 142 FILE *f = e;
143 143
144 fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n", 144 fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n",
145 (val >> 24) & 0xff, (val >> 16) & 0xff, 145 (val >> 24) & 0xff, (val >> 16) & 0xff,
146 (val >> 8) & 0xff, val & 0xff); 146 (val >> 8) & 0xff, val & 0xff);
147} 147}
148 148
149static void asm_emit_string(void *e, const char *str, int len) 149static void asm_emit_string(void *e, const char *str, int len)
150{ 150{
151 FILE *f = e; 151 FILE *f = e;
152 152
153 if (len != 0) 153 if (len != 0)
154 fprintf(f, "\t.string\t\"%.*s\"\n", len, str); 154 fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
155 else 155 else
156 fprintf(f, "\t.string\t\"%s\"\n", str); 156 fprintf(f, "\t.string\t\"%s\"\n", str);
157} 157}
158 158
159static void asm_emit_align(void *e, int a) 159static void asm_emit_align(void *e, int a)
160{ 160{
161 FILE *f = e; 161 FILE *f = e;
162 162
163 fprintf(f, "\t.balign\t%d, 0\n", a); 163 fprintf(f, "\t.balign\t%d, 0\n", a);
164} 164}
165 165
166static void asm_emit_data(void *e, struct data d) 166static void asm_emit_data(void *e, struct data d)
167{ 167{
168 FILE *f = e; 168 FILE *f = e;
169 int off = 0; 169 int off = 0;
170 struct marker *m = d.markers; 170 struct marker *m = d.markers;
171 171
172 for_each_marker_of_type(m, LABEL) 172 for_each_marker_of_type(m, LABEL)
173 emit_offset_label(f, m->ref, m->offset); 173 emit_offset_label(f, m->ref, m->offset);
174 174
175 while ((d.len - off) >= sizeof(uint32_t)) { 175 while ((d.len - off) >= sizeof(uint32_t)) {
176 asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off)))); 176 asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off))));
177 off += sizeof(uint32_t); 177 off += sizeof(uint32_t);
178 } 178 }
179 179
180 while ((d.len - off) >= 1) { 180 while ((d.len - off) >= 1) {
181 fprintf(f, "\t.byte\t0x%hhx\n", d.val[off]); 181 fprintf(f, "\t.byte\t0x%hhx\n", d.val[off]);
182 off += 1; 182 off += 1;
183 } 183 }
184 184
185 assert(off == d.len); 185 assert(off == d.len);
186} 186}
187 187
188static void asm_emit_beginnode(void *e, struct label *labels) 188static void asm_emit_beginnode(void *e, struct label *labels)
189{ 189{
190 FILE *f = e; 190 FILE *f = e;
191 struct label *l; 191 struct label *l;
192 192
193 for_each_label(labels, l) { 193 for_each_label(labels, l) {
194 fprintf(f, "\t.globl\t%s\n", l->label); 194 fprintf(f, "\t.globl\t%s\n", l->label);
195 fprintf(f, "%s:\n", l->label); 195 fprintf(f, "%s:\n", l->label);
196 } 196 }
197 fprintf(f, "\t/* FDT_BEGIN_NODE */\n"); 197 fprintf(f, "\t/* FDT_BEGIN_NODE */\n");
198 asm_emit_cell(e, FDT_BEGIN_NODE); 198 asm_emit_cell(e, FDT_BEGIN_NODE);
199} 199}
200 200
201static void asm_emit_endnode(void *e, struct label *labels) 201static void asm_emit_endnode(void *e, struct label *labels)
202{ 202{
203 FILE *f = e; 203 FILE *f = e;
204 struct label *l; 204 struct label *l;
205 205
206 fprintf(f, "\t/* FDT_END_NODE */\n"); 206 fprintf(f, "\t/* FDT_END_NODE */\n");
207 asm_emit_cell(e, FDT_END_NODE); 207 asm_emit_cell(e, FDT_END_NODE);
208 for_each_label(labels, l) { 208 for_each_label(labels, l) {
209 fprintf(f, "\t.globl\t%s_end\n", l->label); 209 fprintf(f, "\t.globl\t%s_end\n", l->label);
210 fprintf(f, "%s_end:\n", l->label); 210 fprintf(f, "%s_end:\n", l->label);
211 } 211 }
212} 212}
213 213
214static void asm_emit_property(void *e, struct label *labels) 214static void asm_emit_property(void *e, struct label *labels)
215{ 215{
216 FILE *f = e; 216 FILE *f = e;
217 struct label *l; 217 struct label *l;
218 218
219 for_each_label(labels, l) { 219 for_each_label(labels, l) {
220 fprintf(f, "\t.globl\t%s\n", l->label); 220 fprintf(f, "\t.globl\t%s\n", l->label);
221 fprintf(f, "%s:\n", l->label); 221 fprintf(f, "%s:\n", l->label);
222 } 222 }
223 fprintf(f, "\t/* FDT_PROP */\n"); 223 fprintf(f, "\t/* FDT_PROP */\n");
224 asm_emit_cell(e, FDT_PROP); 224 asm_emit_cell(e, FDT_PROP);
225} 225}
226 226
227static struct emitter asm_emitter = { 227static struct emitter asm_emitter = {
228 .cell = asm_emit_cell, 228 .cell = asm_emit_cell,
229 .string = asm_emit_string, 229 .string = asm_emit_string,
230 .align = asm_emit_align, 230 .align = asm_emit_align,
231 .data = asm_emit_data, 231 .data = asm_emit_data,
232 .beginnode = asm_emit_beginnode, 232 .beginnode = asm_emit_beginnode,
233 .endnode = asm_emit_endnode, 233 .endnode = asm_emit_endnode,
234 .property = asm_emit_property, 234 .property = asm_emit_property,
235}; 235};
236 236
237static int stringtable_insert(struct data *d, const char *str) 237static int stringtable_insert(struct data *d, const char *str)
238{ 238{
239 int i; 239 int i;
240 240
241 /* FIXME: do this more efficiently? */ 241 /* FIXME: do this more efficiently? */
242 242
243 for (i = 0; i < d->len; i++) { 243 for (i = 0; i < d->len; i++) {
244 if (streq(str, d->val + i)) 244 if (streq(str, d->val + i))
245 return i; 245 return i;
246 } 246 }
247 247
248 *d = data_append_data(*d, str, strlen(str)+1); 248 *d = data_append_data(*d, str, strlen(str)+1);
249 return i; 249 return i;
250} 250}
251 251
252static void flatten_tree(struct node *tree, struct emitter *emit, 252static void flatten_tree(struct node *tree, struct emitter *emit,
253 void *etarget, struct data *strbuf, 253 void *etarget, struct data *strbuf,
254 struct version_info *vi) 254 struct version_info *vi)
255{ 255{
256 struct property *prop; 256 struct property *prop;
257 struct node *child; 257 struct node *child;
258 bool seen_name_prop = false; 258 bool seen_name_prop = false;
259 259
260 if (tree->deleted) 260 if (tree->deleted)
261 return; 261 return;
262 262
263 emit->beginnode(etarget, tree->labels); 263 emit->beginnode(etarget, tree->labels);
264 264
265 if (vi->flags & FTF_FULLPATH) 265 if (vi->flags & FTF_FULLPATH)
266 emit->string(etarget, tree->fullpath, 0); 266 emit->string(etarget, tree->fullpath, 0);
267 else 267 else
268 emit->string(etarget, tree->name, 0); 268 emit->string(etarget, tree->name, 0);
269 269
270 emit->align(etarget, sizeof(cell_t)); 270 emit->align(etarget, sizeof(cell_t));
271 271
272 for_each_property(tree, prop) { 272 for_each_property(tree, prop) {
273 int nameoff; 273 int nameoff;
274 274
275 if (streq(prop->name, "name")) 275 if (streq(prop->name, "name"))
276 seen_name_prop = true; 276 seen_name_prop = true;
277 277
278 nameoff = stringtable_insert(strbuf, prop->name); 278 nameoff = stringtable_insert(strbuf, prop->name);
279 279
280 emit->property(etarget, prop->labels); 280 emit->property(etarget, prop->labels);
281 emit->cell(etarget, prop->val.len); 281 emit->cell(etarget, prop->val.len);
282 emit->cell(etarget, nameoff); 282 emit->cell(etarget, nameoff);
283 283
284 if ((vi->flags & FTF_VARALIGN) && (prop->val.len >= 8)) 284 if ((vi->flags & FTF_VARALIGN) && (prop->val.len >= 8))
285 emit->align(etarget, 8); 285 emit->align(etarget, 8);
286 286
287 emit->data(etarget, prop->val); 287 emit->data(etarget, prop->val);
288 emit->align(etarget, sizeof(cell_t)); 288 emit->align(etarget, sizeof(cell_t));
289 } 289 }
290 290
291 if ((vi->flags & FTF_NAMEPROPS) && !seen_name_prop) { 291 if ((vi->flags & FTF_NAMEPROPS) && !seen_name_prop) {
292 emit->property(etarget, NULL); 292 emit->property(etarget, NULL);
293 emit->cell(etarget, tree->basenamelen+1); 293 emit->cell(etarget, tree->basenamelen+1);
294 emit->cell(etarget, stringtable_insert(strbuf, "name")); 294 emit->cell(etarget, stringtable_insert(strbuf, "name"));
295 295
296 if ((vi->flags & FTF_VARALIGN) && ((tree->basenamelen+1) >= 8)) 296 if ((vi->flags & FTF_VARALIGN) && ((tree->basenamelen+1) >= 8))
297 emit->align(etarget, 8); 297 emit->align(etarget, 8);
298 298
299 emit->string(etarget, tree->name, tree->basenamelen); 299 emit->string(etarget, tree->name, tree->basenamelen);
300 emit->align(etarget, sizeof(cell_t)); 300 emit->align(etarget, sizeof(cell_t));
301 } 301 }
302 302
303 for_each_child(tree, child) { 303 for_each_child(tree, child) {
304 flatten_tree(child, emit, etarget, strbuf, vi); 304 flatten_tree(child, emit, etarget, strbuf, vi);
305 } 305 }
306 306
307 emit->endnode(etarget, tree->labels); 307 emit->endnode(etarget, tree->labels);
308} 308}
309 309
310static struct data flatten_reserve_list(struct reserve_info *reservelist, 310static struct data flatten_reserve_list(struct reserve_info *reservelist,
311 struct version_info *vi) 311 struct version_info *vi)
312{ 312{
313 struct reserve_info *re; 313 struct reserve_info *re;
314 struct data d = empty_data; 314 struct data d = empty_data;
315 int j; 315 int j;
316 316
317 for (re = reservelist; re; re = re->next) { 317 for (re = reservelist; re; re = re->next) {
318 d = data_append_re(d, re->address, re->size); 318 d = data_append_re(d, re->address, re->size);
319 } 319 }
320 /* 320 /*
321 * Add additional reserved slots if the user asked for them. 321 * Add additional reserved slots if the user asked for them.
322 */ 322 */
323 for (j = 0; j < reservenum; j++) { 323 for (j = 0; j < reservenum; j++) {
324 d = data_append_re(d, 0, 0); 324 d = data_append_re(d, 0, 0);
325 } 325 }
326 326
327 return d; 327 return d;
328} 328}
329 329
330static void make_fdt_header(struct fdt_header *fdt, 330static void make_fdt_header(struct fdt_header *fdt,
331 struct version_info *vi, 331 struct version_info *vi,
332 int reservesize, int dtsize, int strsize, 332 int reservesize, int dtsize, int strsize,
333 int boot_cpuid_phys) 333 int boot_cpuid_phys)
334{ 334{
335 int reserve_off; 335 int reserve_off;
336 336
337 reservesize += sizeof(struct fdt_reserve_entry); 337 reservesize += sizeof(struct fdt_reserve_entry);
338 338
339 memset(fdt, 0xff, sizeof(*fdt)); 339 memset(fdt, 0xff, sizeof(*fdt));
340 340
341 fdt->magic = cpu_to_fdt32(FDT_MAGIC); 341 fdt->magic = cpu_to_fdt32(FDT_MAGIC);
342 fdt->version = cpu_to_fdt32(vi->version); 342 fdt->version = cpu_to_fdt32(vi->version);
343 fdt->last_comp_version = cpu_to_fdt32(vi->last_comp_version); 343 fdt->last_comp_version = cpu_to_fdt32(vi->last_comp_version);
344 344
345 /* Reserve map should be doubleword aligned */ 345 /* Reserve map should be doubleword aligned */
346 reserve_off = FDTALIGN2(vi->hdr_size, 8); 346 reserve_off = FDTALIGN2(vi->hdr_size, 8);
347 347
348 fdt->off_mem_rsvmap = cpu_to_fdt32(reserve_off); 348 fdt->off_mem_rsvmap = cpu_to_fdt32(reserve_off);
349 fdt->off_dt_struct = cpu_to_fdt32(reserve_off + reservesize); 349 fdt->off_dt_struct = cpu_to_fdt32(reserve_off + reservesize);
350 fdt->off_dt_strings = cpu_to_fdt32(reserve_off + reservesize 350 fdt->off_dt_strings = cpu_to_fdt32(reserve_off + reservesize
351 + dtsize); 351 + dtsize);
352 fdt->totalsize = cpu_to_fdt32(reserve_off + reservesize + dtsize + strsize); 352 fdt->totalsize = cpu_to_fdt32(reserve_off + reservesize + dtsize + strsize);
353 353
354 if (vi->flags & FTF_BOOTCPUID) 354 if (vi->flags & FTF_BOOTCPUID)
355 fdt->boot_cpuid_phys = cpu_to_fdt32(boot_cpuid_phys); 355 fdt->boot_cpuid_phys = cpu_to_fdt32(boot_cpuid_phys);
356 if (vi->flags & FTF_STRTABSIZE) 356 if (vi->flags & FTF_STRTABSIZE)
357 fdt->size_dt_strings = cpu_to_fdt32(strsize); 357 fdt->size_dt_strings = cpu_to_fdt32(strsize);
358 if (vi->flags & FTF_STRUCTSIZE) 358 if (vi->flags & FTF_STRUCTSIZE)
359 fdt->size_dt_struct = cpu_to_fdt32(dtsize); 359 fdt->size_dt_struct = cpu_to_fdt32(dtsize);
360} 360}
361 361
362void dt_to_blob(FILE *f, struct dt_info *dti, int version) 362void dt_to_blob(FILE *f, struct dt_info *dti, int version)
363{ 363{
364 struct version_info *vi = NULL; 364 struct version_info *vi = NULL;
365 int i; 365 int i;
366 struct data blob = empty_data; 366 struct data blob = empty_data;
367 struct data reservebuf = empty_data; 367 struct data reservebuf = empty_data;
368 struct data dtbuf = empty_data; 368 struct data dtbuf = empty_data;
369 struct data strbuf = empty_data; 369 struct data strbuf = empty_data;
370 struct fdt_header fdt; 370 struct fdt_header fdt;
371 int padlen = 0; 371 int padlen = 0;
372 372
373 for (i = 0; i < ARRAY_SIZE(version_table); i++) { 373 for (i = 0; i < ARRAY_SIZE(version_table); i++) {
374 if (version_table[i].version == version) 374 if (version_table[i].version == version)
375 vi = &version_table[i]; 375 vi = &version_table[i];
376 } 376 }
377 if (!vi) 377 if (!vi)
378 die("Unknown device tree blob version %d\n", version); 378 die("Unknown device tree blob version %d\n", version);
379 379
380 flatten_tree(dti->dt, &bin_emitter, &dtbuf, &strbuf, vi); 380 flatten_tree(dti->dt, &bin_emitter, &dtbuf, &strbuf, vi);
381 bin_emit_cell(&dtbuf, FDT_END); 381 bin_emit_cell(&dtbuf, FDT_END);
382 382
383 reservebuf = flatten_reserve_list(dti->reservelist, vi); 383 reservebuf = flatten_reserve_list(dti->reservelist, vi);
384 384
385 /* Make header */ 385 /* Make header */
386 make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len, 386 make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
387 dti->boot_cpuid_phys); 387 dti->boot_cpuid_phys);
388 388
389 /* 389 /*
390 * If the user asked for more space than is used, adjust the totalsize. 390 * If the user asked for more space than is used, adjust the totalsize.
391 */ 391 */
392 if (minsize > 0) { 392 if (minsize > 0) {
393 padlen = minsize - fdt32_to_cpu(fdt.totalsize); 393 padlen = minsize - fdt32_to_cpu(fdt.totalsize);
394 if (padlen < 0) { 394 if (padlen < 0) {
395 padlen = 0; 395 padlen = 0;
396 if (quiet < 1) 396 if (quiet < 1)
397 fprintf(stderr, 397 fprintf(stderr,
398 "Warning: blob size %d >= minimum size %d\n", 398 "Warning: blob size %d >= minimum size %d\n",
399 fdt32_to_cpu(fdt.totalsize), minsize); 399 fdt32_to_cpu(fdt.totalsize), minsize);
400 } 400 }
401 } 401 }
402 402
403 if (padsize > 0) 403 if (padsize > 0)
404 padlen = padsize; 404 padlen = padsize;
405 405
406 if (alignsize > 0) 406 if (alignsize > 0)
407 padlen = ALIGN(fdt32_to_cpu(fdt.totalsize) + padlen, alignsize) 407 padlen = FDTALIGN2(fdt32_to_cpu(fdt.totalsize) + padlen, alignsize)
408 - fdt32_to_cpu(fdt.totalsize); 408 - fdt32_to_cpu(fdt.totalsize);
409 409
410 if (padlen > 0) { 410 if (padlen > 0) {
411 int tsize = fdt32_to_cpu(fdt.totalsize); 411 int tsize = fdt32_to_cpu(fdt.totalsize);
412 tsize += padlen; 412 tsize += padlen;
413 fdt.totalsize = cpu_to_fdt32(tsize); 413 fdt.totalsize = cpu_to_fdt32(tsize);
414 } 414 }
415 415
416 /* 416 /*
417 * Assemble the blob: start with the header, add with alignment 417 * Assemble the blob: start with the header, add with alignment
418 * the reserve buffer, add the reserve map terminating zeroes, 418 * the reserve buffer, add the reserve map terminating zeroes,
419 * the device tree itself, and finally the strings. 419 * the device tree itself, and finally the strings.
420 */ 420 */
421 blob = data_append_data(blob, &fdt, vi->hdr_size); 421 blob = data_append_data(blob, &fdt, vi->hdr_size);
422 blob = data_append_align(blob, 8); 422 blob = data_append_align(blob, 8);
423 blob = data_merge(blob, reservebuf); 423 blob = data_merge(blob, reservebuf);
424 blob = data_append_zeroes(blob, sizeof(struct fdt_reserve_entry)); 424 blob = data_append_zeroes(blob, sizeof(struct fdt_reserve_entry));
425 blob = data_merge(blob, dtbuf); 425 blob = data_merge(blob, dtbuf);
426 blob = data_merge(blob, strbuf); 426 blob = data_merge(blob, strbuf);
427 427
428 /* 428 /*
429 * If the user asked for more space than is used, pad out the blob. 429 * If the user asked for more space than is used, pad out the blob.
430 */ 430 */
431 if (padlen > 0) 431 if (padlen > 0)
432 blob = data_append_zeroes(blob, padlen); 432 blob = data_append_zeroes(blob, padlen);
433 433
434 if (fwrite(blob.val, blob.len, 1, f) != 1) { 434 if (fwrite(blob.val, blob.len, 1, f) != 1) {
435 if (ferror(f)) 435 if (ferror(f))
436 die("Error writing device tree blob: %s\n", 436 die("Error writing device tree blob: %s\n",
437 strerror(errno)); 437 strerror(errno));
438 else 438 else
439 die("Short write on device tree blob\n"); 439 die("Short write on device tree blob\n");
440 } 440 }
441 441
442 /* 442 /*
443 * data_merge() frees the right-hand element so only the blob 443 * data_merge() frees the right-hand element so only the blob
444 * remains to be freed. 444 * remains to be freed.
445 */ 445 */
446 data_free(blob); 446 data_free(blob);
447} 447}
448 448
449static void dump_stringtable_asm(FILE *f, struct data strbuf) 449static void dump_stringtable_asm(FILE *f, struct data strbuf)
450{ 450{
451 const char *p; 451 const char *p;
452 int len; 452 int len;
453 453
454 p = strbuf.val; 454 p = strbuf.val;
455 455
456 while (p < (strbuf.val + strbuf.len)) { 456 while (p < (strbuf.val + strbuf.len)) {
457 len = strlen(p); 457 len = strlen(p);
458 fprintf(f, "\t.string \"%s\"\n", p); 458 fprintf(f, "\t.string \"%s\"\n", p);
459 p += len+1; 459 p += len+1;
460 } 460 }
461} 461}
462 462
463void dt_to_asm(FILE *f, struct dt_info *dti, int version) 463void dt_to_asm(FILE *f, struct dt_info *dti, int version)
464{ 464{
465 struct version_info *vi = NULL; 465 struct version_info *vi = NULL;
466 int i; 466 int i;
467 struct data strbuf = empty_data; 467 struct data strbuf = empty_data;
468 struct reserve_info *re; 468 struct reserve_info *re;
469 const char *symprefix = "dt"; 469 const char *symprefix = "dt";
470 470
471 for (i = 0; i < ARRAY_SIZE(version_table); i++) { 471 for (i = 0; i < ARRAY_SIZE(version_table); i++) {
472 if (version_table[i].version == version) 472 if (version_table[i].version == version)
473 vi = &version_table[i]; 473 vi = &version_table[i];
474 } 474 }
475 if (!vi) 475 if (!vi)
476 die("Unknown device tree blob version %d\n", version); 476 die("Unknown device tree blob version %d\n", version);
477 477
478 fprintf(f, "/* autogenerated by dtc, do not edit */\n\n"); 478 fprintf(f, "/* autogenerated by dtc, do not edit */\n\n");
479 479
480 emit_label(f, symprefix, "blob_start"); 480 emit_label(f, symprefix, "blob_start");
481 emit_label(f, symprefix, "header"); 481 emit_label(f, symprefix, "header");
482 fprintf(f, "\t/* magic */\n"); 482 fprintf(f, "\t/* magic */\n");
483 asm_emit_cell(f, FDT_MAGIC); 483 asm_emit_cell(f, FDT_MAGIC);
484 fprintf(f, "\t/* totalsize */\n"); 484 fprintf(f, "\t/* totalsize */\n");
485 ASM_EMIT_BELONG(f, "_%s_blob_abs_end - _%s_blob_start", 485 ASM_EMIT_BELONG(f, "_%s_blob_abs_end - _%s_blob_start",
486 symprefix, symprefix); 486 symprefix, symprefix);
487 fprintf(f, "\t/* off_dt_struct */\n"); 487 fprintf(f, "\t/* off_dt_struct */\n");
488 ASM_EMIT_BELONG(f, "_%s_struct_start - _%s_blob_start", 488 ASM_EMIT_BELONG(f, "_%s_struct_start - _%s_blob_start",
489 symprefix, symprefix); 489 symprefix, symprefix);
490 fprintf(f, "\t/* off_dt_strings */\n"); 490 fprintf(f, "\t/* off_dt_strings */\n");
491 ASM_EMIT_BELONG(f, "_%s_strings_start - _%s_blob_start", 491 ASM_EMIT_BELONG(f, "_%s_strings_start - _%s_blob_start",
492 symprefix, symprefix); 492 symprefix, symprefix);
493 fprintf(f, "\t/* off_mem_rsvmap */\n"); 493 fprintf(f, "\t/* off_mem_rsvmap */\n");
494 ASM_EMIT_BELONG(f, "_%s_reserve_map - _%s_blob_start", 494 ASM_EMIT_BELONG(f, "_%s_reserve_map - _%s_blob_start",
495 symprefix, symprefix); 495 symprefix, symprefix);
496 fprintf(f, "\t/* version */\n"); 496 fprintf(f, "\t/* version */\n");
497 asm_emit_cell(f, vi->version); 497 asm_emit_cell(f, vi->version);
498 fprintf(f, "\t/* last_comp_version */\n"); 498 fprintf(f, "\t/* last_comp_version */\n");
499 asm_emit_cell(f, vi->last_comp_version); 499 asm_emit_cell(f, vi->last_comp_version);
500 500
501 if (vi->flags & FTF_BOOTCPUID) { 501 if (vi->flags & FTF_BOOTCPUID) {
502 fprintf(f, "\t/* boot_cpuid_phys */\n"); 502 fprintf(f, "\t/* boot_cpuid_phys */\n");
503 asm_emit_cell(f, dti->boot_cpuid_phys); 503 asm_emit_cell(f, dti->boot_cpuid_phys);
504 } 504 }
505 505
506 if (vi->flags & FTF_STRTABSIZE) { 506 if (vi->flags & FTF_STRTABSIZE) {
507 fprintf(f, "\t/* size_dt_strings */\n"); 507 fprintf(f, "\t/* size_dt_strings */\n");
508 ASM_EMIT_BELONG(f, "_%s_strings_end - _%s_strings_start", 508 ASM_EMIT_BELONG(f, "_%s_strings_end - _%s_strings_start",
509 symprefix, symprefix); 509 symprefix, symprefix);
510 } 510 }
511 511
512 if (vi->flags & FTF_STRUCTSIZE) { 512 if (vi->flags & FTF_STRUCTSIZE) {
513 fprintf(f, "\t/* size_dt_struct */\n"); 513 fprintf(f, "\t/* size_dt_struct */\n");
514 ASM_EMIT_BELONG(f, "_%s_struct_end - _%s_struct_start", 514 ASM_EMIT_BELONG(f, "_%s_struct_end - _%s_struct_start",
515 symprefix, symprefix); 515 symprefix, symprefix);
516 } 516 }
517 517
518 /* 518 /*
519 * Reserve map entries. 519 * Reserve map entries.
520 * Align the reserve map to a doubleword boundary. 520 * Align the reserve map to a doubleword boundary.
521 * Each entry is an (address, size) pair of u64 values. 521 * Each entry is an (address, size) pair of u64 values.
522 * Always supply a zero-sized temination entry. 522 * Always supply a zero-sized temination entry.
523 */ 523 */
524 asm_emit_align(f, 8); 524 asm_emit_align(f, 8);
525 emit_label(f, symprefix, "reserve_map"); 525 emit_label(f, symprefix, "reserve_map");
526 526
527 fprintf(f, "/* Memory reserve map from source file */\n"); 527 fprintf(f, "/* Memory reserve map from source file */\n");
528 528
529 /* 529 /*
530 * Use .long on high and low halfs of u64s to avoid .quad 530 * Use .long on high and low halfs of u64s to avoid .quad
531 * as it appears .quad isn't available in some assemblers. 531 * as it appears .quad isn't available in some assemblers.
532 */ 532 */
533 for (re = dti->reservelist; re; re = re->next) { 533 for (re = dti->reservelist; re; re = re->next) {
534 struct label *l; 534 struct label *l;
535 535
536 for_each_label(re->labels, l) { 536 for_each_label(re->labels, l) {
537 fprintf(f, "\t.globl\t%s\n", l->label); 537 fprintf(f, "\t.globl\t%s\n", l->label);
538 fprintf(f, "%s:\n", l->label); 538 fprintf(f, "%s:\n", l->label);
539 } 539 }
540 ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->address >> 32)); 540 ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->address >> 32));
541 ASM_EMIT_BELONG(f, "0x%08x", 541 ASM_EMIT_BELONG(f, "0x%08x",
542 (unsigned int)(re->address & 0xffffffff)); 542 (unsigned int)(re->address & 0xffffffff));
543 ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size >> 32)); 543 ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size >> 32));
544 ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size & 0xffffffff)); 544 ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size & 0xffffffff));
545 } 545 }
546 for (i = 0; i < reservenum; i++) { 546 for (i = 0; i < reservenum; i++) {
547 fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); 547 fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
548 } 548 }
549 549
550 fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); 550 fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
551 551
552 emit_label(f, symprefix, "struct_start"); 552 emit_label(f, symprefix, "struct_start");
553 flatten_tree(dti->dt, &asm_emitter, f, &strbuf, vi); 553 flatten_tree(dti->dt, &asm_emitter, f, &strbuf, vi);
554 554
555 fprintf(f, "\t/* FDT_END */\n"); 555 fprintf(f, "\t/* FDT_END */\n");
556 asm_emit_cell(f, FDT_END); 556 asm_emit_cell(f, FDT_END);
557 emit_label(f, symprefix, "struct_end"); 557 emit_label(f, symprefix, "struct_end");
558 558
559 emit_label(f, symprefix, "strings_start"); 559 emit_label(f, symprefix, "strings_start");
560 dump_stringtable_asm(f, strbuf); 560 dump_stringtable_asm(f, strbuf);
561 emit_label(f, symprefix, "strings_end"); 561 emit_label(f, symprefix, "strings_end");
562 562
563 emit_label(f, symprefix, "blob_end"); 563 emit_label(f, symprefix, "blob_end");
564 564
565 /* 565 /*
566 * If the user asked for more space than is used, pad it out. 566 * If the user asked for more space than is used, pad it out.
567 */ 567 */
568 if (minsize > 0) { 568 if (minsize > 0) {
569 fprintf(f, "\t.space\t%d - (_%s_blob_end - _%s_blob_start), 0\n", 569 fprintf(f, "\t.space\t%d - (_%s_blob_end - _%s_blob_start), 0\n",
570 minsize, symprefix, symprefix); 570 minsize, symprefix, symprefix);
571 } 571 }
572 if (padsize > 0) { 572 if (padsize > 0) {
573 fprintf(f, "\t.space\t%d, 0\n", padsize); 573 fprintf(f, "\t.space\t%d, 0\n", padsize);
574 } 574 }
575 if (alignsize > 0) 575 if (alignsize > 0)
576 asm_emit_align(f, alignsize); 576 asm_emit_align(f, alignsize);
577 emit_label(f, symprefix, "blob_abs_end"); 577 emit_label(f, symprefix, "blob_abs_end");
578 578
579 data_free(strbuf); 579 data_free(strbuf);
580} 580}
581 581
582struct inbuf { 582struct inbuf {
583 char *base, *limit, *ptr; 583 char *base, *limit, *ptr;
584}; 584};
585 585
586static void inbuf_init(struct inbuf *inb, void *base, void *limit) 586static void inbuf_init(struct inbuf *inb, void *base, void *limit)
587{ 587{
588 inb->base = base; 588 inb->base = base;
589 inb->limit = limit; 589 inb->limit = limit;
590 inb->ptr = inb->base; 590 inb->ptr = inb->base;
591} 591}
592 592
593static void flat_read_chunk(struct inbuf *inb, void *p, int len) 593static void flat_read_chunk(struct inbuf *inb, void *p, int len)
594{ 594{
595 if ((inb->ptr + len) > inb->limit) 595 if ((inb->ptr + len) > inb->limit)
596 die("Premature end of data parsing flat device tree\n"); 596 die("Premature end of data parsing flat device tree\n");
597 597
598 memcpy(p, inb->ptr, len); 598 memcpy(p, inb->ptr, len);
599 599
600 inb->ptr += len; 600 inb->ptr += len;
601} 601}
602 602
603static uint32_t flat_read_word(struct inbuf *inb) 603static uint32_t flat_read_word(struct inbuf *inb)
604{ 604{
605 fdt32_t val; 605 fdt32_t val;
606 606
607 assert(((inb->ptr - inb->base) % sizeof(val)) == 0); 607 assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
608 608
609 flat_read_chunk(inb, &val, sizeof(val)); 609 flat_read_chunk(inb, &val, sizeof(val));
610 610
611 return fdt32_to_cpu(val); 611 return fdt32_to_cpu(val);
612} 612}
613 613
614static void flat_realign(struct inbuf *inb, int align) 614static void flat_realign(struct inbuf *inb, int align)
615{ 615{
616 int off = inb->ptr - inb->base; 616 int off = inb->ptr - inb->base;
617 617
618 inb->ptr = inb->base + FDTALIGN2(off, align); 618 inb->ptr = inb->base + FDTALIGN2(off, align);
619 if (inb->ptr > inb->limit) 619 if (inb->ptr > inb->limit)
620 die("Premature end of data parsing flat device tree\n"); 620 die("Premature end of data parsing flat device tree\n");
621} 621}
622 622
623static char *flat_read_string(struct inbuf *inb) 623static char *flat_read_string(struct inbuf *inb)
624{ 624{
625 int len = 0; 625 int len = 0;
626 const char *p = inb->ptr; 626 const char *p = inb->ptr;
627 char *str; 627 char *str;
628 628
629 do { 629 do {
630 if (p >= inb->limit) 630 if (p >= inb->limit)
631 die("Premature end of data parsing flat device tree\n"); 631 die("Premature end of data parsing flat device tree\n");
632 len++; 632 len++;
633 } while ((*p++) != '\0'); 633 } while ((*p++) != '\0');
634 634
635 str = xstrdup(inb->ptr); 635 str = xstrdup(inb->ptr);
636 636
637 inb->ptr += len; 637 inb->ptr += len;
638 638
639 flat_realign(inb, sizeof(uint32_t)); 639 flat_realign(inb, sizeof(uint32_t));
640 640
641 return str; 641 return str;
642} 642}
643 643
644static struct data flat_read_data(struct inbuf *inb, int len) 644static struct data flat_read_data(struct inbuf *inb, int len)
645{ 645{
646 struct data d = empty_data; 646 struct data d = empty_data;
647 647
648 if (len == 0) 648 if (len == 0)
649 return empty_data; 649 return empty_data;
650 650
651 d = data_grow_for(d, len); 651 d = data_grow_for(d, len);
652 d.len = len; 652 d.len = len;
653 653
654 flat_read_chunk(inb, d.val, len); 654 flat_read_chunk(inb, d.val, len);
655 655
656 flat_realign(inb, sizeof(uint32_t)); 656 flat_realign(inb, sizeof(uint32_t));
657 657
658 return d; 658 return d;
659} 659}
660 660
661static char *flat_read_stringtable(struct inbuf *inb, int offset) 661static char *flat_read_stringtable(struct inbuf *inb, int offset)
662{ 662{
663 const char *p; 663 const char *p;
664 664
665 p = inb->base + offset; 665 p = inb->base + offset;
666 while (1) { 666 while (1) {
667 if (p >= inb->limit || p < inb->base) 667 if (p >= inb->limit || p < inb->base)
668 die("String offset %d overruns string table\n", 668 die("String offset %d overruns string table\n",
669 offset); 669 offset);
670 670
671 if (*p == '\0') 671 if (*p == '\0')
672 break; 672 break;
673 673
674 p++; 674 p++;
675 } 675 }
676 676
677 return xstrdup(inb->base + offset); 677 return xstrdup(inb->base + offset);
678} 678}
679 679
680static struct property *flat_read_property(struct inbuf *dtbuf, 680static struct property *flat_read_property(struct inbuf *dtbuf,
681 struct inbuf *strbuf, int flags) 681 struct inbuf *strbuf, int flags)
682{ 682{
683 uint32_t proplen, stroff; 683 uint32_t proplen, stroff;
684 char *name; 684 char *name;
685 struct data val; 685 struct data val;
686 686
687 proplen = flat_read_word(dtbuf); 687 proplen = flat_read_word(dtbuf);
688 stroff = flat_read_word(dtbuf); 688 stroff = flat_read_word(dtbuf);
689 689
690 name = flat_read_stringtable(strbuf, stroff); 690 name = flat_read_stringtable(strbuf, stroff);
691 691
692 if ((flags & FTF_VARALIGN) && (proplen >= 8)) 692 if ((flags & FTF_VARALIGN) && (proplen >= 8))
693 flat_realign(dtbuf, 8); 693 flat_realign(dtbuf, 8);
694 694
695 val = flat_read_data(dtbuf, proplen); 695 val = flat_read_data(dtbuf, proplen);
696 696
697 return build_property(name, val); 697 return build_property(name, val);
698} 698}
699 699
700 700
701static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) 701static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
702{ 702{
703 struct reserve_info *reservelist = NULL; 703 struct reserve_info *reservelist = NULL;
704 struct reserve_info *new; 704 struct reserve_info *new;
705 struct fdt_reserve_entry re; 705 struct fdt_reserve_entry re;
706 706
707 /* 707 /*
708 * Each entry is a pair of u64 (addr, size) values for 4 cell_t's. 708 * Each entry is a pair of u64 (addr, size) values for 4 cell_t's.
709 * List terminates at an entry with size equal to zero. 709 * List terminates at an entry with size equal to zero.
710 * 710 *
711 * First pass, count entries. 711 * First pass, count entries.
712 */ 712 */
713 while (1) { 713 while (1) {
714 uint64_t address, size; 714 uint64_t address, size;
715 715
716 flat_read_chunk(inb, &re, sizeof(re)); 716 flat_read_chunk(inb, &re, sizeof(re));
717 address = fdt64_to_cpu(re.address); 717 address = fdt64_to_cpu(re.address);
718 size = fdt64_to_cpu(re.size); 718 size = fdt64_to_cpu(re.size);
719 if (size == 0) 719 if (size == 0)
720 break; 720 break;
721 721
722 new = build_reserve_entry(address, size); 722 new = build_reserve_entry(address, size);
723 reservelist = add_reserve_entry(reservelist, new); 723 reservelist = add_reserve_entry(reservelist, new);
724 } 724 }
725 725
726 return reservelist; 726 return reservelist;
727} 727}
728 728
729 729
730static char *nodename_from_path(const char *ppath, const char *cpath) 730static char *nodename_from_path(const char *ppath, const char *cpath)
731{ 731{
732 int plen; 732 int plen;
733 733
734 plen = strlen(ppath); 734 plen = strlen(ppath);
735 735
736 if (!strneq(ppath, cpath, plen)) 736 if (!strneq(ppath, cpath, plen))
737 die("Path \"%s\" is not valid as a child of \"%s\"\n", 737 die("Path \"%s\" is not valid as a child of \"%s\"\n",
738 cpath, ppath); 738 cpath, ppath);
739 739
740 /* root node is a special case */ 740 /* root node is a special case */
741 if (!streq(ppath, "/")) 741 if (!streq(ppath, "/"))
742 plen++; 742 plen++;
743 743
744 return xstrdup(cpath + plen); 744 return xstrdup(cpath + plen);
745} 745}
746 746
747static struct node *unflatten_tree(struct inbuf *dtbuf, 747static struct node *unflatten_tree(struct inbuf *dtbuf,
748 struct inbuf *strbuf, 748 struct inbuf *strbuf,
749 const char *parent_flatname, int flags) 749 const char *parent_flatname, int flags)
750{ 750{
751 struct node *node; 751 struct node *node;
752 char *flatname; 752 char *flatname;
753 uint32_t val; 753 uint32_t val;
754 754
755 node = build_node(NULL, NULL); 755 node = build_node(NULL, NULL);
756 756
757 flatname = flat_read_string(dtbuf); 757 flatname = flat_read_string(dtbuf);
758 758
759 if (flags & FTF_FULLPATH) 759 if (flags & FTF_FULLPATH)
760 node->name = nodename_from_path(parent_flatname, flatname); 760 node->name = nodename_from_path(parent_flatname, flatname);
761 else 761 else
762 node->name = flatname; 762 node->name = flatname;
763 763
764 do { 764 do {
765 struct property *prop; 765 struct property *prop;
766 struct node *child; 766 struct node *child;
767 767
768 val = flat_read_word(dtbuf); 768 val = flat_read_word(dtbuf);
769 switch (val) { 769 switch (val) {
770 case FDT_PROP: 770 case FDT_PROP:
771 if (node->children) 771 if (node->children)
772 fprintf(stderr, "Warning: Flat tree input has " 772 fprintf(stderr, "Warning: Flat tree input has "
773 "subnodes preceding a property.\n"); 773 "subnodes preceding a property.\n");
774 prop = flat_read_property(dtbuf, strbuf, flags); 774 prop = flat_read_property(dtbuf, strbuf, flags);
775 add_property(node, prop); 775 add_property(node, prop);
776 break; 776 break;
777 777
778 case FDT_BEGIN_NODE: 778 case FDT_BEGIN_NODE:
779 child = unflatten_tree(dtbuf,strbuf, flatname, flags); 779 child = unflatten_tree(dtbuf,strbuf, flatname, flags);
780 add_child(node, child); 780 add_child(node, child);
781 break; 781 break;
782 782
783 case FDT_END_NODE: 783 case FDT_END_NODE:
784 break; 784 break;
785 785
786 case FDT_END: 786 case FDT_END:
787 die("Premature FDT_END in device tree blob\n"); 787 die("Premature FDT_END in device tree blob\n");
788 break; 788 break;
789 789
790 case FDT_NOP: 790 case FDT_NOP:
791 if (!(flags & FTF_NOPS)) 791 if (!(flags & FTF_NOPS))
792 fprintf(stderr, "Warning: NOP tag found in flat tree" 792 fprintf(stderr, "Warning: NOP tag found in flat tree"
793 " version <16\n"); 793 " version <16\n");
794 794
795 /* Ignore */ 795 /* Ignore */
796 break; 796 break;
797 797
798 default: 798 default:
799 die("Invalid opcode word %08x in device tree blob\n", 799 die("Invalid opcode word %08x in device tree blob\n",
800 val); 800 val);
801 } 801 }
802 } while (val != FDT_END_NODE); 802 } while (val != FDT_END_NODE);
803 803
804 if (node->name != flatname) { 804 if (node->name != flatname) {
805 free(flatname); 805 free(flatname);
806 } 806 }
807 807
808 return node; 808 return node;
809} 809}
810 810
811 811
812struct dt_info *dt_from_blob(const char *fname) 812struct dt_info *dt_from_blob(const char *fname)
813{ 813{
814 FILE *f; 814 FILE *f;
815 fdt32_t magic_buf, totalsize_buf; 815 fdt32_t magic_buf, totalsize_buf;
816 uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys; 816 uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
817 uint32_t off_dt, off_str, off_mem_rsvmap; 817 uint32_t off_dt, off_str, off_mem_rsvmap;
818 int rc; 818 int rc;
819 char *blob; 819 char *blob;
820 struct fdt_header *fdt; 820 struct fdt_header *fdt;
821 char *p; 821 char *p;
822 struct inbuf dtbuf, strbuf; 822 struct inbuf dtbuf, strbuf;
823 struct inbuf memresvbuf; 823 struct inbuf memresvbuf;
824 int sizeleft; 824 int sizeleft;
825 struct reserve_info *reservelist; 825 struct reserve_info *reservelist;
826 struct node *tree; 826 struct node *tree;
827 uint32_t val; 827 uint32_t val;
828 int flags = 0; 828 int flags = 0;
829 829
830 f = srcfile_relative_open(fname, NULL); 830 f = srcfile_relative_open(fname, NULL);
831 831
832 rc = fread(&magic_buf, sizeof(magic_buf), 1, f); 832 rc = fread(&magic_buf, sizeof(magic_buf), 1, f);
833 if (ferror(f)) 833 if (ferror(f))
834 die("Error reading DT blob magic number: %s\n", 834 die("Error reading DT blob magic number: %s\n",
835 strerror(errno)); 835 strerror(errno));
836 if (rc < 1) { 836 if (rc < 1) {
837 if (feof(f)) 837 if (feof(f))
838 die("EOF reading DT blob magic number\n"); 838 die("EOF reading DT blob magic number\n");
839 else 839 else
840 die("Mysterious short read reading magic number\n"); 840 die("Mysterious short read reading magic number\n");
841 } 841 }
842 842
843 magic = fdt32_to_cpu(magic_buf); 843 magic = fdt32_to_cpu(magic_buf);
844 if (magic != FDT_MAGIC) 844 if (magic != FDT_MAGIC)
845 die("Blob has incorrect magic number\n"); 845 die("Blob has incorrect magic number\n");
846 846
847 rc = fread(&totalsize_buf, sizeof(totalsize_buf), 1, f); 847 rc = fread(&totalsize_buf, sizeof(totalsize_buf), 1, f);
848 if (ferror(f)) 848 if (ferror(f))
849 die("Error reading DT blob size: %s\n", strerror(errno)); 849 die("Error reading DT blob size: %s\n", strerror(errno));
850 if (rc < 1) { 850 if (rc < 1) {
851 if (feof(f)) 851 if (feof(f))
852 die("EOF reading DT blob size\n"); 852 die("EOF reading DT blob size\n");
853 else 853 else
854 die("Mysterious short read reading blob size\n"); 854 die("Mysterious short read reading blob size\n");
855 } 855 }
856 856
857 totalsize = fdt32_to_cpu(totalsize_buf); 857 totalsize = fdt32_to_cpu(totalsize_buf);
858 if (totalsize < FDT_V1_SIZE) 858 if (totalsize < FDT_V1_SIZE)
859 die("DT blob size (%d) is too small\n", totalsize); 859 die("DT blob size (%d) is too small\n", totalsize);
860 860
861 blob = xmalloc(totalsize); 861 blob = xmalloc(totalsize);
862 862
863 fdt = (struct fdt_header *)blob; 863 fdt = (struct fdt_header *)blob;
864 fdt->magic = cpu_to_fdt32(magic); 864 fdt->magic = cpu_to_fdt32(magic);
865 fdt->totalsize = cpu_to_fdt32(totalsize); 865 fdt->totalsize = cpu_to_fdt32(totalsize);
866 866
867 sizeleft = totalsize - sizeof(magic) - sizeof(totalsize); 867 sizeleft = totalsize - sizeof(magic) - sizeof(totalsize);
868 p = blob + sizeof(magic) + sizeof(totalsize); 868 p = blob + sizeof(magic) + sizeof(totalsize);
869 869
870 while (sizeleft) { 870 while (sizeleft) {
871 if (feof(f)) 871 if (feof(f))
872 die("EOF before reading %d bytes of DT blob\n", 872 die("EOF before reading %d bytes of DT blob\n",
873 totalsize); 873 totalsize);
874 874
875 rc = fread(p, 1, sizeleft, f); 875 rc = fread(p, 1, sizeleft, f);
876 if (ferror(f)) 876 if (ferror(f))
877 die("Error reading DT blob: %s\n", 877 die("Error reading DT blob: %s\n",
878 strerror(errno)); 878 strerror(errno));
879 879
880 sizeleft -= rc; 880 sizeleft -= rc;
881 p += rc; 881 p += rc;
882 } 882 }
883 883
884 off_dt = fdt32_to_cpu(fdt->off_dt_struct); 884 off_dt = fdt32_to_cpu(fdt->off_dt_struct);
885 off_str = fdt32_to_cpu(fdt->off_dt_strings); 885 off_str = fdt32_to_cpu(fdt->off_dt_strings);
886 off_mem_rsvmap = fdt32_to_cpu(fdt->off_mem_rsvmap); 886 off_mem_rsvmap = fdt32_to_cpu(fdt->off_mem_rsvmap);
887 version = fdt32_to_cpu(fdt->version); 887 version = fdt32_to_cpu(fdt->version);
888 boot_cpuid_phys = fdt32_to_cpu(fdt->boot_cpuid_phys); 888 boot_cpuid_phys = fdt32_to_cpu(fdt->boot_cpuid_phys);
889 889
890 if (off_mem_rsvmap >= totalsize) 890 if (off_mem_rsvmap >= totalsize)
891 die("Mem Reserve structure offset exceeds total size\n"); 891 die("Mem Reserve structure offset exceeds total size\n");
892 892
893 if (off_dt >= totalsize) 893 if (off_dt >= totalsize)
894 die("DT structure offset exceeds total size\n"); 894 die("DT structure offset exceeds total size\n");
895 895
896 if (off_str > totalsize) 896 if (off_str > totalsize)
897 die("String table offset exceeds total size\n"); 897 die("String table offset exceeds total size\n");
898 898
899 if (version >= 3) { 899 if (version >= 3) {
900 uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings); 900 uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings);
901 if ((off_str+size_str < off_str) || (off_str+size_str > totalsize)) 901 if ((off_str+size_str < off_str) || (off_str+size_str > totalsize))
902 die("String table extends past total size\n"); 902 die("String table extends past total size\n");
903 inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str); 903 inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
904 } else { 904 } else {
905 inbuf_init(&strbuf, blob + off_str, blob + totalsize); 905 inbuf_init(&strbuf, blob + off_str, blob + totalsize);
906 } 906 }
907 907
908 if (version >= 17) { 908 if (version >= 17) {
909 size_dt = fdt32_to_cpu(fdt->size_dt_struct); 909 size_dt = fdt32_to_cpu(fdt->size_dt_struct);
910 if ((off_dt+size_dt < off_dt) || (off_dt+size_dt > totalsize)) 910 if ((off_dt+size_dt < off_dt) || (off_dt+size_dt > totalsize))
911 die("Structure block extends past total size\n"); 911 die("Structure block extends past total size\n");
912 } 912 }
913 913
914 if (version < 16) { 914 if (version < 16) {
915 flags |= FTF_FULLPATH | FTF_NAMEPROPS | FTF_VARALIGN; 915 flags |= FTF_FULLPATH | FTF_NAMEPROPS | FTF_VARALIGN;
916 } else { 916 } else {
917 flags |= FTF_NOPS; 917 flags |= FTF_NOPS;
918 } 918 }
919 919
920 inbuf_init(&memresvbuf, 920 inbuf_init(&memresvbuf,
921 blob + off_mem_rsvmap, blob + totalsize); 921 blob + off_mem_rsvmap, blob + totalsize);
922 inbuf_init(&dtbuf, blob + off_dt, blob + totalsize); 922 inbuf_init(&dtbuf, blob + off_dt, blob + totalsize);
923 923
924 reservelist = flat_read_mem_reserve(&memresvbuf); 924 reservelist = flat_read_mem_reserve(&memresvbuf);
925 925
926 val = flat_read_word(&dtbuf); 926 val = flat_read_word(&dtbuf);
927 927
928 if (val != FDT_BEGIN_NODE) 928 if (val != FDT_BEGIN_NODE)
929 die("Device tree blob doesn't begin with FDT_BEGIN_NODE (begins with 0x%08x)\n", val); 929 die("Device tree blob doesn't begin with FDT_BEGIN_NODE (begins with 0x%08x)\n", val);
930 930
931 tree = unflatten_tree(&dtbuf, &strbuf, "", flags); 931 tree = unflatten_tree(&dtbuf, &strbuf, "", flags);
932 932
933 val = flat_read_word(&dtbuf); 933 val = flat_read_word(&dtbuf);
934 if (val != FDT_END) 934 if (val != FDT_END)
935 die("Device tree blob doesn't end with FDT_END\n"); 935 die("Device tree blob doesn't end with FDT_END\n");
936 936
937 free(blob); 937 free(blob);
938 938
939 fclose(f); 939 fclose(f);
940 940
941 return build_dt_info(DTSF_V1, reservelist, tree, boot_cpuid_phys); 941 return build_dt_info(DTSF_V1, reservelist, tree, boot_cpuid_phys);
942} 942}