aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/dtc/flattree.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/dtc/flattree.c')
-rw-r--r--scripts/dtc/flattree.c192
1 files changed, 109 insertions, 83 deletions
diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
index 76acd28c068..ead0332c87e 100644
--- a/scripts/dtc/flattree.c
+++ b/scripts/dtc/flattree.c
@@ -52,9 +52,9 @@ struct emitter {
52 void (*string)(void *, char *, int); 52 void (*string)(void *, char *, int);
53 void (*align)(void *, int); 53 void (*align)(void *, int);
54 void (*data)(void *, struct data); 54 void (*data)(void *, struct data);
55 void (*beginnode)(void *, const char *); 55 void (*beginnode)(void *, struct label *labels);
56 void (*endnode)(void *, const char *); 56 void (*endnode)(void *, struct label *labels);
57 void (*property)(void *, const char *); 57 void (*property)(void *, struct label *labels);
58}; 58};
59 59
60static void bin_emit_cell(void *e, cell_t val) 60static void bin_emit_cell(void *e, cell_t val)
@@ -89,17 +89,17 @@ static void bin_emit_data(void *e, struct data d)
89 *dtbuf = data_append_data(*dtbuf, d.val, d.len); 89 *dtbuf = data_append_data(*dtbuf, d.val, d.len);
90} 90}
91 91
92static void bin_emit_beginnode(void *e, const char *label) 92static void bin_emit_beginnode(void *e, struct label *labels)
93{ 93{
94 bin_emit_cell(e, FDT_BEGIN_NODE); 94 bin_emit_cell(e, FDT_BEGIN_NODE);
95} 95}
96 96
97static void bin_emit_endnode(void *e, const char *label) 97static void bin_emit_endnode(void *e, struct label *labels)
98{ 98{
99 bin_emit_cell(e, FDT_END_NODE); 99 bin_emit_cell(e, FDT_END_NODE);
100} 100}
101 101
102static void bin_emit_property(void *e, const char *label) 102static void bin_emit_property(void *e, struct label *labels)
103{ 103{
104 bin_emit_cell(e, FDT_PROP); 104 bin_emit_cell(e, FDT_PROP);
105} 105}
@@ -127,11 +127,21 @@ static void emit_offset_label(FILE *f, const char *label, int offset)
127 fprintf(f, "%s\t= . + %d\n", label, offset); 127 fprintf(f, "%s\t= . + %d\n", label, offset);
128} 128}
129 129
130#define ASM_EMIT_BELONG(f, fmt, ...) \
131 { \
132 fprintf((f), "\t.byte\t((" fmt ") >> 24) & 0xff\n", __VA_ARGS__); \
133 fprintf((f), "\t.byte\t((" fmt ") >> 16) & 0xff\n", __VA_ARGS__); \
134 fprintf((f), "\t.byte\t((" fmt ") >> 8) & 0xff\n", __VA_ARGS__); \
135 fprintf((f), "\t.byte\t(" fmt ") & 0xff\n", __VA_ARGS__); \
136 }
137
130static void asm_emit_cell(void *e, cell_t val) 138static void asm_emit_cell(void *e, cell_t val)
131{ 139{
132 FILE *f = e; 140 FILE *f = e;
133 141
134 fprintf(f, "\t.long\t0x%x\n", val); 142 fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n",
143 (val >> 24) & 0xff, (val >> 16) & 0xff,
144 (val >> 8) & 0xff, val & 0xff);
135} 145}
136 146
137static void asm_emit_string(void *e, char *str, int len) 147static void asm_emit_string(void *e, char *str, int len)
@@ -156,7 +166,7 @@ static void asm_emit_align(void *e, int a)
156{ 166{
157 FILE *f = e; 167 FILE *f = e;
158 168
159 fprintf(f, "\t.balign\t%d\n", a); 169 fprintf(f, "\t.balign\t%d, 0\n", a);
160} 170}
161 171
162static void asm_emit_data(void *e, struct data d) 172static void asm_emit_data(void *e, struct data d)
@@ -169,8 +179,7 @@ static void asm_emit_data(void *e, struct data d)
169 emit_offset_label(f, m->ref, m->offset); 179 emit_offset_label(f, m->ref, m->offset);
170 180
171 while ((d.len - off) >= sizeof(uint32_t)) { 181 while ((d.len - off) >= sizeof(uint32_t)) {
172 fprintf(f, "\t.long\t0x%x\n", 182 asm_emit_cell(e, fdt32_to_cpu(*((uint32_t *)(d.val+off))));
173 fdt32_to_cpu(*((uint32_t *)(d.val+off))));
174 off += sizeof(uint32_t); 183 off += sizeof(uint32_t);
175 } 184 }
176 185
@@ -182,37 +191,43 @@ static void asm_emit_data(void *e, struct data d)
182 assert(off == d.len); 191 assert(off == d.len);
183} 192}
184 193
185static void asm_emit_beginnode(void *e, const char *label) 194static void asm_emit_beginnode(void *e, struct label *labels)
186{ 195{
187 FILE *f = e; 196 FILE *f = e;
197 struct label *l;
188 198
189 if (label) { 199 for_each_label(labels, l) {
190 fprintf(f, "\t.globl\t%s\n", label); 200 fprintf(f, "\t.globl\t%s\n", l->label);
191 fprintf(f, "%s:\n", label); 201 fprintf(f, "%s:\n", l->label);
192 } 202 }
193 fprintf(f, "\t.long\tFDT_BEGIN_NODE\n"); 203 fprintf(f, "\t/* FDT_BEGIN_NODE */\n");
204 asm_emit_cell(e, FDT_BEGIN_NODE);
194} 205}
195 206
196static void asm_emit_endnode(void *e, const char *label) 207static void asm_emit_endnode(void *e, struct label *labels)
197{ 208{
198 FILE *f = e; 209 FILE *f = e;
210 struct label *l;
199 211
200 fprintf(f, "\t.long\tFDT_END_NODE\n"); 212 fprintf(f, "\t/* FDT_END_NODE */\n");
201 if (label) { 213 asm_emit_cell(e, FDT_END_NODE);
202 fprintf(f, "\t.globl\t%s_end\n", label); 214 for_each_label(labels, l) {
203 fprintf(f, "%s_end:\n", label); 215 fprintf(f, "\t.globl\t%s_end\n", l->label);
216 fprintf(f, "%s_end:\n", l->label);
204 } 217 }
205} 218}
206 219
207static void asm_emit_property(void *e, const char *label) 220static void asm_emit_property(void *e, struct label *labels)
208{ 221{
209 FILE *f = e; 222 FILE *f = e;
223 struct label *l;
210 224
211 if (label) { 225 for_each_label(labels, l) {
212 fprintf(f, "\t.globl\t%s\n", label); 226 fprintf(f, "\t.globl\t%s\n", l->label);
213 fprintf(f, "%s:\n", label); 227 fprintf(f, "%s:\n", l->label);
214 } 228 }
215 fprintf(f, "\t.long\tFDT_PROP\n"); 229 fprintf(f, "\t/* FDT_PROP */\n");
230 asm_emit_cell(e, FDT_PROP);
216} 231}
217 232
218static struct emitter asm_emitter = { 233static struct emitter asm_emitter = {
@@ -248,7 +263,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
248 struct node *child; 263 struct node *child;
249 int seen_name_prop = 0; 264 int seen_name_prop = 0;
250 265
251 emit->beginnode(etarget, tree->label); 266 emit->beginnode(etarget, tree->labels);
252 267
253 if (vi->flags & FTF_FULLPATH) 268 if (vi->flags & FTF_FULLPATH)
254 emit->string(etarget, tree->fullpath, 0); 269 emit->string(etarget, tree->fullpath, 0);
@@ -265,7 +280,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
265 280
266 nameoff = stringtable_insert(strbuf, prop->name); 281 nameoff = stringtable_insert(strbuf, prop->name);
267 282
268 emit->property(etarget, prop->label); 283 emit->property(etarget, prop->labels);
269 emit->cell(etarget, prop->val.len); 284 emit->cell(etarget, prop->val.len);
270 emit->cell(etarget, nameoff); 285 emit->cell(etarget, nameoff);
271 286
@@ -292,7 +307,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
292 flatten_tree(child, emit, etarget, strbuf, vi); 307 flatten_tree(child, emit, etarget, strbuf, vi);
293 } 308 }
294 309
295 emit->endnode(etarget, tree->label); 310 emit->endnode(etarget, tree->labels);
296} 311}
297 312
298static struct data flatten_reserve_list(struct reserve_info *reservelist, 313static struct data flatten_reserve_list(struct reserve_info *reservelist,
@@ -413,10 +428,13 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version)
413 if (padlen > 0) 428 if (padlen > 0)
414 blob = data_append_zeroes(blob, padlen); 429 blob = data_append_zeroes(blob, padlen);
415 430
416 fwrite(blob.val, blob.len, 1, f); 431 if (fwrite(blob.val, blob.len, 1, f) != 1) {
417 432 if (ferror(f))
418 if (ferror(f)) 433 die("Error writing device tree blob: %s\n",
419 die("Error writing device tree blob: %s\n", strerror(errno)); 434 strerror(errno));
435 else
436 die("Short write on device tree blob\n");
437 }
420 438
421 /* 439 /*
422 * data_merge() frees the right-hand element so only the blob 440 * data_merge() frees the right-hand element so only the blob
@@ -455,39 +473,44 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
455 die("Unknown device tree blob version %d\n", version); 473 die("Unknown device tree blob version %d\n", version);
456 474
457 fprintf(f, "/* autogenerated by dtc, do not edit */\n\n"); 475 fprintf(f, "/* autogenerated by dtc, do not edit */\n\n");
458 fprintf(f, "#define FDT_MAGIC 0x%x\n", FDT_MAGIC);
459 fprintf(f, "#define FDT_BEGIN_NODE 0x%x\n", FDT_BEGIN_NODE);
460 fprintf(f, "#define FDT_END_NODE 0x%x\n", FDT_END_NODE);
461 fprintf(f, "#define FDT_PROP 0x%x\n", FDT_PROP);
462 fprintf(f, "#define FDT_END 0x%x\n", FDT_END);
463 fprintf(f, "\n");
464 476
465 emit_label(f, symprefix, "blob_start"); 477 emit_label(f, symprefix, "blob_start");
466 emit_label(f, symprefix, "header"); 478 emit_label(f, symprefix, "header");
467 fprintf(f, "\t.long\tFDT_MAGIC\t\t\t\t/* magic */\n"); 479 fprintf(f, "\t/* magic */\n");
468 fprintf(f, "\t.long\t_%s_blob_abs_end - _%s_blob_start\t/* totalsize */\n", 480 asm_emit_cell(f, FDT_MAGIC);
469 symprefix, symprefix); 481 fprintf(f, "\t/* totalsize */\n");
470 fprintf(f, "\t.long\t_%s_struct_start - _%s_blob_start\t/* off_dt_struct */\n", 482 ASM_EMIT_BELONG(f, "_%s_blob_abs_end - _%s_blob_start",
483 symprefix, symprefix);
484 fprintf(f, "\t/* off_dt_struct */\n");
485 ASM_EMIT_BELONG(f, "_%s_struct_start - _%s_blob_start",
471 symprefix, symprefix); 486 symprefix, symprefix);
472 fprintf(f, "\t.long\t_%s_strings_start - _%s_blob_start\t/* off_dt_strings */\n", 487 fprintf(f, "\t/* off_dt_strings */\n");
488 ASM_EMIT_BELONG(f, "_%s_strings_start - _%s_blob_start",
473 symprefix, symprefix); 489 symprefix, symprefix);
474 fprintf(f, "\t.long\t_%s_reserve_map - _%s_blob_start\t/* off_dt_strings */\n", 490 fprintf(f, "\t/* off_mem_rsvmap */\n");
491 ASM_EMIT_BELONG(f, "_%s_reserve_map - _%s_blob_start",
475 symprefix, symprefix); 492 symprefix, symprefix);
476 fprintf(f, "\t.long\t%d\t\t\t\t\t/* version */\n", vi->version); 493 fprintf(f, "\t/* version */\n");
477 fprintf(f, "\t.long\t%d\t\t\t\t\t/* last_comp_version */\n", 494 asm_emit_cell(f, vi->version);
478 vi->last_comp_version); 495 fprintf(f, "\t/* last_comp_version */\n");
479 496 asm_emit_cell(f, vi->last_comp_version);
480 if (vi->flags & FTF_BOOTCPUID) 497
481 fprintf(f, "\t.long\t%i\t\t\t\t\t/* boot_cpuid_phys */\n", 498 if (vi->flags & FTF_BOOTCPUID) {
482 bi->boot_cpuid_phys); 499 fprintf(f, "\t/* boot_cpuid_phys */\n");
500 asm_emit_cell(f, bi->boot_cpuid_phys);
501 }
483 502
484 if (vi->flags & FTF_STRTABSIZE) 503 if (vi->flags & FTF_STRTABSIZE) {
485 fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n", 504 fprintf(f, "\t/* size_dt_strings */\n");
486 symprefix, symprefix); 505 ASM_EMIT_BELONG(f, "_%s_strings_end - _%s_strings_start",
506 symprefix, symprefix);
507 }
487 508
488 if (vi->flags & FTF_STRUCTSIZE) 509 if (vi->flags & FTF_STRUCTSIZE) {
489 fprintf(f, "\t.long\t_%s_struct_end - _%s_struct_start\t/* size_dt_struct */\n", 510 fprintf(f, "\t/* size_dt_struct */\n");
511 ASM_EMIT_BELONG(f, "_%s_struct_end - _%s_struct_start",
490 symprefix, symprefix); 512 symprefix, symprefix);
513 }
491 514
492 /* 515 /*
493 * Reserve map entries. 516 * Reserve map entries.
@@ -505,16 +528,17 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
505 * as it appears .quad isn't available in some assemblers. 528 * as it appears .quad isn't available in some assemblers.
506 */ 529 */
507 for (re = bi->reservelist; re; re = re->next) { 530 for (re = bi->reservelist; re; re = re->next) {
508 if (re->label) { 531 struct label *l;
509 fprintf(f, "\t.globl\t%s\n", re->label); 532
510 fprintf(f, "%s:\n", re->label); 533 for_each_label(re->labels, l) {
534 fprintf(f, "\t.globl\t%s\n", l->label);
535 fprintf(f, "%s:\n", l->label);
511 } 536 }
512 fprintf(f, "\t.long\t0x%08x, 0x%08x\n", 537 ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32));
513 (unsigned int)(re->re.address >> 32), 538 ASM_EMIT_BELONG(f, "0x%08x",
514 (unsigned int)(re->re.address & 0xffffffff)); 539 (unsigned int)(re->re.address & 0xffffffff));
515 fprintf(f, "\t.long\t0x%08x, 0x%08x\n", 540 ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32));
516 (unsigned int)(re->re.size >> 32), 541 ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff));
517 (unsigned int)(re->re.size & 0xffffffff));
518 } 542 }
519 for (i = 0; i < reservenum; i++) { 543 for (i = 0; i < reservenum; i++) {
520 fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); 544 fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
@@ -524,7 +548,9 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
524 548
525 emit_label(f, symprefix, "struct_start"); 549 emit_label(f, symprefix, "struct_start");
526 flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi); 550 flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi);
527 fprintf(f, "\t.long\tFDT_END\n"); 551
552 fprintf(f, "\t/* FDT_END */\n");
553 asm_emit_cell(f, FDT_END);
528 emit_label(f, symprefix, "struct_end"); 554 emit_label(f, symprefix, "struct_end");
529 555
530 emit_label(f, symprefix, "strings_start"); 556 emit_label(f, symprefix, "strings_start");
@@ -601,7 +627,7 @@ static char *flat_read_string(struct inbuf *inb)
601 len++; 627 len++;
602 } while ((*p++) != '\0'); 628 } while ((*p++) != '\0');
603 629
604 str = strdup(inb->ptr); 630 str = xstrdup(inb->ptr);
605 631
606 inb->ptr += len; 632 inb->ptr += len;
607 633
@@ -643,7 +669,7 @@ static char *flat_read_stringtable(struct inbuf *inb, int offset)
643 p++; 669 p++;
644 } 670 }
645 671
646 return strdup(inb->base + offset); 672 return xstrdup(inb->base + offset);
647} 673}
648 674
649static struct property *flat_read_property(struct inbuf *dtbuf, 675static struct property *flat_read_property(struct inbuf *dtbuf,
@@ -663,7 +689,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf,
663 689
664 val = flat_read_data(dtbuf, proplen); 690 val = flat_read_data(dtbuf, proplen);
665 691
666 return build_property(name, val, NULL); 692 return build_property(name, val);
667} 693}
668 694
669 695
@@ -688,7 +714,7 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
688 if (re.size == 0) 714 if (re.size == 0)
689 break; 715 break;
690 716
691 new = build_reserve_entry(re.address, re.size, NULL); 717 new = build_reserve_entry(re.address, re.size);
692 reservelist = add_reserve_entry(reservelist, new); 718 reservelist = add_reserve_entry(reservelist, new);
693 } 719 }
694 720
@@ -710,7 +736,7 @@ static char *nodename_from_path(const char *ppath, const char *cpath)
710 if (!streq(ppath, "/")) 736 if (!streq(ppath, "/"))
711 plen++; 737 plen++;
712 738
713 return strdup(cpath + plen); 739 return xstrdup(cpath + plen);
714} 740}
715 741
716static struct node *unflatten_tree(struct inbuf *dtbuf, 742static struct node *unflatten_tree(struct inbuf *dtbuf,
@@ -776,7 +802,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
776 802
777struct boot_info *dt_from_blob(const char *fname) 803struct boot_info *dt_from_blob(const char *fname)
778{ 804{
779 struct dtc_file *dtcf; 805 FILE *f;
780 uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys; 806 uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
781 uint32_t off_dt, off_str, off_mem_rsvmap; 807 uint32_t off_dt, off_str, off_mem_rsvmap;
782 int rc; 808 int rc;
@@ -791,14 +817,14 @@ struct boot_info *dt_from_blob(const char *fname)
791 uint32_t val; 817 uint32_t val;
792 int flags = 0; 818 int flags = 0;
793 819
794 dtcf = dtc_open_file(fname, NULL); 820 f = srcfile_relative_open(fname, NULL);
795 821
796 rc = fread(&magic, sizeof(magic), 1, dtcf->file); 822 rc = fread(&magic, sizeof(magic), 1, f);
797 if (ferror(dtcf->file)) 823 if (ferror(f))
798 die("Error reading DT blob magic number: %s\n", 824 die("Error reading DT blob magic number: %s\n",
799 strerror(errno)); 825 strerror(errno));
800 if (rc < 1) { 826 if (rc < 1) {
801 if (feof(dtcf->file)) 827 if (feof(f))
802 die("EOF reading DT blob magic number\n"); 828 die("EOF reading DT blob magic number\n");
803 else 829 else
804 die("Mysterious short read reading magic number\n"); 830 die("Mysterious short read reading magic number\n");
@@ -808,11 +834,11 @@ struct boot_info *dt_from_blob(const char *fname)
808 if (magic != FDT_MAGIC) 834 if (magic != FDT_MAGIC)
809 die("Blob has incorrect magic number\n"); 835 die("Blob has incorrect magic number\n");
810 836
811 rc = fread(&totalsize, sizeof(totalsize), 1, dtcf->file); 837 rc = fread(&totalsize, sizeof(totalsize), 1, f);
812 if (ferror(dtcf->file)) 838 if (ferror(f))
813 die("Error reading DT blob size: %s\n", strerror(errno)); 839 die("Error reading DT blob size: %s\n", strerror(errno));
814 if (rc < 1) { 840 if (rc < 1) {
815 if (feof(dtcf->file)) 841 if (feof(f))
816 die("EOF reading DT blob size\n"); 842 die("EOF reading DT blob size\n");
817 else 843 else
818 die("Mysterious short read reading blob size\n"); 844 die("Mysterious short read reading blob size\n");
@@ -832,12 +858,12 @@ struct boot_info *dt_from_blob(const char *fname)
832 p = blob + sizeof(magic) + sizeof(totalsize); 858 p = blob + sizeof(magic) + sizeof(totalsize);
833 859
834 while (sizeleft) { 860 while (sizeleft) {
835 if (feof(dtcf->file)) 861 if (feof(f))
836 die("EOF before reading %d bytes of DT blob\n", 862 die("EOF before reading %d bytes of DT blob\n",
837 totalsize); 863 totalsize);
838 864
839 rc = fread(p, 1, sizeleft, dtcf->file); 865 rc = fread(p, 1, sizeleft, f);
840 if (ferror(dtcf->file)) 866 if (ferror(f))
841 die("Error reading DT blob: %s\n", 867 die("Error reading DT blob: %s\n",
842 strerror(errno)); 868 strerror(errno));
843 869
@@ -900,7 +926,7 @@ struct boot_info *dt_from_blob(const char *fname)
900 926
901 free(blob); 927 free(blob);
902 928
903 dtc_close_file(dtcf); 929 fclose(f);
904 930
905 return build_boot_info(reservelist, tree, boot_cpuid_phys); 931 return build_boot_info(reservelist, tree, boot_cpuid_phys);
906} 932}