24 #define FTF_FULLPATH 0x1
25 #define FTF_VARALIGN 0x2
26 #define FTF_NAMEPROPS 0x4
27 #define FTF_BOOTCPUID 0x8
28 #define FTF_STRTABSIZE 0x10
29 #define FTF_STRUCTSIZE 0x20
62 struct data *dtbuf =
e;
67 static void bin_emit_string(
void *
e,
char *
str,
int len)
69 struct data *dtbuf =
e;
78 static void bin_emit_align(
void *e,
int a)
80 struct data *dtbuf =
e;
85 static void bin_emit_data(
void *e,
struct data d)
87 struct data *dtbuf =
e;
92 static void bin_emit_beginnode(
void *e,
struct label *labels)
97 static void bin_emit_endnode(
void *e,
struct label *labels)
102 static void bin_emit_property(
void *e,
struct label *labels)
107 static struct emitter bin_emitter = {
108 .cell = bin_emit_cell,
109 .string = bin_emit_string,
110 .align = bin_emit_align,
111 .data = bin_emit_data,
112 .beginnode = bin_emit_beginnode,
113 .endnode = bin_emit_endnode,
114 .property = bin_emit_property,
117 static void emit_label(FILE *
f,
const char *
prefix,
const char *
label)
119 fprintf(f,
"\t.globl\t%s_%s\n", prefix, label);
120 fprintf(f,
"%s_%s:\n", prefix, label);
121 fprintf(f,
"_%s_%s:\n", prefix, label);
124 static void emit_offset_label(FILE *
f,
const char *
label,
int offset)
126 fprintf(f,
"\t.globl\t%s\n", label);
127 fprintf(f,
"%s\t= . + %d\n", label, offset);
130 #define ASM_EMIT_BELONG(f, fmt, ...) \
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__); \
138 static void asm_emit_cell(
void *e,
cell_t 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);
147 static void asm_emit_string(
void *e,
char *str,
int len)
158 fprintf(f,
"\t.string\t\"%s\"\n", str);
165 static void asm_emit_align(
void *e,
int a)
169 fprintf(f,
"\t.balign\t%d, 0\n", a);
172 static void asm_emit_data(
void *e,
struct data d)
186 while ((d.
len - off) >= 1) {
194 static void asm_emit_beginnode(
void *e,
struct label *labels)
203 fprintf(f,
"\t/* FDT_BEGIN_NODE */\n");
207 static void asm_emit_endnode(
void *e,
struct label *labels)
212 fprintf(f,
"\t/* FDT_END_NODE */\n");
220 static void asm_emit_property(
void *e,
struct label *labels)
229 fprintf(f,
"\t/* FDT_PROP */\n");
233 static struct emitter asm_emitter = {
234 .cell = asm_emit_cell,
235 .string = asm_emit_string,
236 .align = asm_emit_align,
237 .data = asm_emit_data,
238 .beginnode = asm_emit_beginnode,
239 .endnode = asm_emit_endnode,
240 .property = asm_emit_property,
243 static int stringtable_insert(
struct data *d,
const char *str)
249 for (i = 0; i < d->
len; i++) {
264 int seen_name_prop = 0;
284 nameoff = stringtable_insert(strbuf, prop->
name);
287 emit->
cell(etarget, prop->
val.len);
288 emit->
cell(etarget, nameoff);
291 emit->
align(etarget, 8);
293 emit->
data(etarget, prop->
val);
300 emit->
cell(etarget, stringtable_insert(strbuf,
"name"));
303 emit->
align(etarget, 8);
310 flatten_tree(child, emit, etarget, strbuf, vi);
324 for (re = reservelist; re; re = re->
next) {
337 static void make_fdt_header(
struct fdt_header *fdt,
339 int reservesize,
int dtsize,
int strsize,
346 memset(fdt, 0xff,
sizeof(*fdt));
380 for (i = 0; i <
ARRAY_SIZE(version_table); i++) {
381 if (version_table[i].version == version)
382 vi = &version_table[
i];
385 die(
"Unknown device tree blob version %d\n", version);
387 flatten_tree(bi->
dt, &bin_emitter, &dtbuf, &strbuf, vi);
388 bin_emit_cell(&dtbuf,
FDT_END);
390 reservebuf = flatten_reserve_list(bi->
reservelist, vi);
393 make_fdt_header(&fdt, vi, reservebuf.
len, dtbuf.
len, strbuf.
len,
401 if ((padlen < 0) && (
quiet < 1))
403 "Warning: blob size %d >= minimum size %d\n",
434 if (fwrite(blob.
val, blob.
len, 1, f) != 1) {
436 die(
"Error writing device tree blob: %s\n",
439 die(
"Short write on device tree blob\n");
449 static void dump_stringtable_asm(FILE *f,
struct data strbuf)
456 while (p < (strbuf.
val + strbuf.
len)) {
458 fprintf(f,
"\t.string \"%s\"\n", p);
469 const char *symprefix =
"dt";
471 for (i = 0; i <
ARRAY_SIZE(version_table); i++) {
472 if (version_table[i].version == version)
473 vi = &version_table[
i];
476 die(
"Unknown device tree blob version %d\n", version);
478 fprintf(f,
"/* autogenerated by dtc, do not edit */\n\n");
480 emit_label(f, symprefix,
"blob_start");
481 emit_label(f, symprefix,
"header");
484 fprintf(f,
"\t/* totalsize */\n");
486 symprefix, symprefix);
487 fprintf(f,
"\t/* off_dt_struct */\n");
489 symprefix, symprefix);
490 fprintf(f,
"\t/* off_dt_strings */\n");
492 symprefix, symprefix);
493 fprintf(f,
"\t/* off_mem_rsvmap */\n");
495 symprefix, symprefix);
496 fprintf(f,
"\t/* version */\n");
498 fprintf(f,
"\t/* last_comp_version */\n");
502 fprintf(f,
"\t/* boot_cpuid_phys */\n");
507 fprintf(f,
"\t/* size_dt_strings */\n");
509 symprefix, symprefix);
513 fprintf(f,
"\t/* size_dt_struct */\n");
515 symprefix, symprefix);
524 asm_emit_align(f, 8);
525 emit_label(f, symprefix,
"reserve_map");
527 fprintf(f,
"/* Memory reserve map from source file */\n");
542 (
unsigned int)(re->
re.address & 0xffffffff));
547 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");
552 emit_label(f, symprefix,
"struct_start");
553 flatten_tree(bi->
dt, &asm_emitter, f, &strbuf, vi);
555 fprintf(f,
"\t/* FDT_END */\n");
557 emit_label(f, symprefix,
"struct_end");
559 emit_label(f, symprefix,
"strings_start");
560 dump_stringtable_asm(f, strbuf);
561 emit_label(f, symprefix,
"strings_end");
563 emit_label(f, symprefix,
"blob_end");
569 fprintf(f,
"\t.space\t%d - (_%s_blob_end - _%s_blob_start), 0\n",
570 minsize, symprefix, symprefix);
575 emit_label(f, symprefix,
"blob_abs_end");
584 static void inbuf_init(
struct inbuf *
inb,
void *base,
void *
limit)
591 static void flat_read_chunk(
struct inbuf *
inb,
void *p,
int len)
594 die(
"Premature end of data parsing flat device tree\n");
601 static uint32_t flat_read_word(
struct inbuf *inb)
607 flat_read_chunk(inb, &val,
sizeof(val));
612 static void flat_realign(
struct inbuf *inb,
int align)
614 int off = inb->
ptr - inb->
base;
618 die(
"Premature end of data parsing flat device tree\n");
621 static char *flat_read_string(
struct inbuf *inb)
624 const char *p = inb->
ptr;
629 die(
"Premature end of data parsing flat device tree\n");
631 }
while ((*p++) !=
'\0');
637 flat_realign(inb,
sizeof(uint32_t));
652 flat_read_chunk(inb, d.
val, len);
654 flat_realign(inb,
sizeof(uint32_t));
659 static char *flat_read_stringtable(
struct inbuf *inb,
int offset)
665 if (p >= inb->
limit || p < inb->base)
666 die(
"String offset %d overruns string table\n",
678 static struct property *flat_read_property(
struct inbuf *dtbuf,
681 uint32_t proplen, stroff;
685 proplen = flat_read_word(dtbuf);
686 stroff = flat_read_word(dtbuf);
688 name = flat_read_stringtable(strbuf, stroff);
691 flat_realign(dtbuf, 8);
693 val = flat_read_data(dtbuf, proplen);
712 flat_read_chunk(inb, &re,
sizeof(re));
726 static char *nodename_from_path(
const char *ppath,
const char *cpath)
732 if (!
strneq(ppath, cpath, plen))
733 die(
"Path \"%s\" is not valid as a child of \"%s\"\n",
737 if (!
streq(ppath,
"/"))
743 static struct node *unflatten_tree(
struct inbuf *dtbuf,
744 struct inbuf *strbuf,
745 const char *parent_flatname,
int flags)
753 flatname = flat_read_string(dtbuf);
756 node->
name = nodename_from_path(parent_flatname, flatname);
758 node->
name = flatname;
764 val = flat_read_word(dtbuf);
768 fprintf(stderr,
"Warning: Flat tree input has "
769 "subnodes preceding a property.\n");
770 prop = flat_read_property(dtbuf, strbuf, flags);
775 child = unflatten_tree(dtbuf,strbuf, flatname, flags);
783 die(
"Premature FDT_END in device tree blob\n");
788 fprintf(stderr,
"Warning: NOP tag found in flat tree"
795 die(
"Invalid opcode word %08x in device tree blob\n",
808 uint32_t off_dt, off_str, off_mem_rsvmap;
813 struct inbuf dtbuf, strbuf;
814 struct inbuf memresvbuf;
823 rc = fread(&magic,
sizeof(magic), 1, f);
825 die(
"Error reading DT blob magic number: %s\n",
829 die(
"EOF reading DT blob magic number\n");
831 die(
"Mysterious short read reading magic number\n");
836 die(
"Blob has incorrect magic number\n");
838 rc = fread(&totalsize,
sizeof(totalsize), 1, f);
843 die(
"EOF reading DT blob size\n");
845 die(
"Mysterious short read reading blob size\n");
850 die(
"DT blob size (%d) is too small\n", totalsize);
858 sizeleft = totalsize -
sizeof(
magic) -
sizeof(totalsize);
859 p = blob +
sizeof(
magic) +
sizeof(totalsize);
863 die(
"EOF before reading %d bytes of DT blob\n",
866 rc = fread(p, 1, sizeleft, f);
868 die(
"Error reading DT blob: %s\n",
881 if (off_mem_rsvmap >= totalsize)
882 die(
"Mem Reserve structure offset exceeds total size\n");
884 if (off_dt >= totalsize)
885 die(
"DT structure offset exceeds total size\n");
887 if (off_str > totalsize)
888 die(
"String table offset exceeds total size\n");
892 if (off_str+size_str > totalsize)
893 die(
"String table extends past total size\n");
894 inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
896 inbuf_init(&strbuf, blob + off_str, blob + totalsize);
901 if (off_dt+size_dt > totalsize)
902 die(
"Structure block extends past total size\n");
911 inbuf_init(&memresvbuf,
912 blob + off_mem_rsvmap, blob + totalsize);
913 inbuf_init(&dtbuf, blob + off_dt, blob + totalsize);
915 reservelist = flat_read_mem_reserve(&memresvbuf);
917 val = flat_read_word(&dtbuf);
920 die(
"Device tree blob doesn't begin with FDT_BEGIN_NODE (begins with 0x%08x)\n", val);
922 tree = unflatten_tree(&dtbuf, &strbuf,
"", flags);
924 val = flat_read_word(&dtbuf);
926 die(
"Device tree blob doesn't end with FDT_END\n");