Support for specifying memreserve ranges in the source format, based on
a patch by Jon Loeliger <jdl AT freescale.com>, although tweaked substantially.main
parent
586606e35d
commit
f0517db250
2
Makefile
2
Makefile
|
@ -14,7 +14,7 @@ dtc: $(OBJS)
|
||||||
$(LINK.c) -o $@ $^
|
$(LINK.c) -o $@ $^
|
||||||
|
|
||||||
dtc-parser.tab.c dtc-parser.tab.h dtc-parser.output: dtc-parser.y
|
dtc-parser.tab.c dtc-parser.tab.h dtc-parser.output: dtc-parser.y
|
||||||
$(BISON) -d -v $<
|
$(BISON) -d $<
|
||||||
|
|
||||||
lex.yy.c: dtc-lexer.l
|
lex.yy.c: dtc-lexer.l
|
||||||
$(LEX) $<
|
$(LEX) $<
|
||||||
|
|
7
data.c
7
data.c
|
@ -229,6 +229,13 @@ struct data data_append_cell(struct data d, cell_t word)
|
||||||
return data_append_data(d, &beword, sizeof(beword));
|
return data_append_data(d, &beword, sizeof(beword));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct data data_append_addr(struct data d, u64 addr)
|
||||||
|
{
|
||||||
|
u64 beaddr = cpu_to_be64(addr);
|
||||||
|
|
||||||
|
return data_append_data(d, &beaddr, sizeof(beaddr));
|
||||||
|
}
|
||||||
|
|
||||||
struct data data_append_byte(struct data d, uint8_t byte)
|
struct data data_append_byte(struct data d, uint8_t byte)
|
||||||
{
|
{
|
||||||
return data_append_data(d, &byte, 1);
|
return data_append_data(d, &byte, 1);
|
||||||
|
|
26
dtc-lexer.l
26
dtc-lexer.l
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
%x CELLDATA
|
%x CELLDATA
|
||||||
%x BYTESTRING
|
%x BYTESTRING
|
||||||
|
%x MEMRESERVE
|
||||||
|
|
||||||
PROPCHAR [a-zA-Z0-9,._+*#?-]
|
PROPCHAR [a-zA-Z0-9,._+*#?-]
|
||||||
UNITCHAR [0-9a-f,]
|
UNITCHAR [0-9a-f,]
|
||||||
|
@ -53,6 +54,29 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@])
|
||||||
return DT_STRING;
|
return DT_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"/memreserve/" {
|
||||||
|
DPRINT("Keyword: /memreserve/\n");
|
||||||
|
BEGIN(MEMRESERVE);
|
||||||
|
return DT_MEMRESERVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
<MEMRESERVE>[0-9a-fA-F]+ {
|
||||||
|
if (yyleng > 2*sizeof(yylval.addr)) {
|
||||||
|
fprintf(stderr, "Address value %s too large\n",
|
||||||
|
yytext);
|
||||||
|
}
|
||||||
|
yylval.addr = (u64) strtoull(yytext, NULL, 16);
|
||||||
|
DPRINT("Addr: %llx\n",
|
||||||
|
(unsigned long long)yylval.addr);
|
||||||
|
return DT_ADDR;
|
||||||
|
}
|
||||||
|
|
||||||
|
<MEMRESERVE>";" {
|
||||||
|
DPRINT("/MEMRESERVE\n");
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
return ';';
|
||||||
|
}
|
||||||
|
|
||||||
<CELLDATA>[0-9a-fA-F]+ {
|
<CELLDATA>[0-9a-fA-F]+ {
|
||||||
if (yyleng > 2*sizeof(yylval.cval)) {
|
if (yyleng > 2*sizeof(yylval.cval)) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
@ -116,7 +140,7 @@ REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@])
|
||||||
|
|
||||||
<*>"//".*\n /* eat line comments */
|
<*>"//".*\n /* eat line comments */
|
||||||
|
|
||||||
. {
|
<*>. {
|
||||||
switch (yytext[0]) {
|
switch (yytext[0]) {
|
||||||
case '<':
|
case '<':
|
||||||
DPRINT("CELLDATA\n");
|
DPRINT("CELLDATA\n");
|
||||||
|
|
39
dtc-parser.y
39
dtc-parser.y
|
@ -24,7 +24,7 @@
|
||||||
int yylex (void);
|
int yylex (void);
|
||||||
void yyerror (char const *);
|
void yyerror (char const *);
|
||||||
|
|
||||||
extern struct node *device_tree;
|
extern struct boot_info *the_boot_info;
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
@ -39,8 +39,12 @@ extern struct node *device_tree;
|
||||||
struct node *nodelist;
|
struct node *nodelist;
|
||||||
int datalen;
|
int datalen;
|
||||||
int hexlen;
|
int hexlen;
|
||||||
|
u64 addr;
|
||||||
|
struct reserve_entry re;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%token DT_MEMRESERVE
|
||||||
|
%token <addr> DT_ADDR
|
||||||
%token <str> DT_PROPNAME
|
%token <str> DT_PROPNAME
|
||||||
%token <str> DT_NODENAME
|
%token <str> DT_NODENAME
|
||||||
%token <cval> DT_CELL
|
%token <cval> DT_CELL
|
||||||
|
@ -51,11 +55,14 @@ extern struct node *device_tree;
|
||||||
%token <str> DT_REF
|
%token <str> DT_REF
|
||||||
|
|
||||||
%type <data> propdata
|
%type <data> propdata
|
||||||
|
%type <re> memreserve
|
||||||
|
%type <data> memreserves
|
||||||
%type <data> celllist
|
%type <data> celllist
|
||||||
%type <data> bytestring
|
%type <data> bytestring
|
||||||
%type <prop> propdef
|
%type <prop> propdef
|
||||||
%type <proplist> proplist
|
%type <proplist> proplist
|
||||||
|
|
||||||
|
%type <node> devicetree
|
||||||
%type <node> nodedef
|
%type <node> nodedef
|
||||||
%type <node> subnode
|
%type <node> subnode
|
||||||
%type <nodelist> subnodes
|
%type <nodelist> subnodes
|
||||||
|
@ -66,9 +73,33 @@ extern struct node *device_tree;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
devicetree: {
|
sourcefile: memreserves devicetree {
|
||||||
assert(device_tree == NULL);
|
the_boot_info = build_boot_info($1, $2);
|
||||||
} '/' nodedef { device_tree = name_node($3, "", NULL); }
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
memreserves: memreserves memreserve {
|
||||||
|
$$ = data_append_addr(data_append_addr($1, $2.address),
|
||||||
|
$2.size);
|
||||||
|
}
|
||||||
|
| /* empty */ {
|
||||||
|
$$ = empty_data;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
memreserve: DT_MEMRESERVE DT_ADDR DT_ADDR ';' {
|
||||||
|
$$.address = $2;
|
||||||
|
$$.size = $3;
|
||||||
|
}
|
||||||
|
| DT_MEMRESERVE DT_ADDR '-' DT_ADDR ';' {
|
||||||
|
$$.address = $2;
|
||||||
|
$$.size = $4 - $2 + 1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
devicetree: '/' nodedef {
|
||||||
|
$$ = name_node($2, "", NULL);
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
nodedef: '{' proplist subnodes '}' ';' {
|
nodedef: '{' proplist subnodes '}' ';' {
|
||||||
|
|
18
dtc.c
18
dtc.c
|
@ -102,7 +102,7 @@ static void usage(void)
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct node *dt;
|
struct boot_info *bi;
|
||||||
char *inform = "dts";
|
char *inform = "dts";
|
||||||
char *outform = "dts";
|
char *outform = "dts";
|
||||||
char *outname = "-";
|
char *outname = "-";
|
||||||
|
@ -151,12 +151,12 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
if (streq(inform, "dts")) {
|
if (streq(inform, "dts")) {
|
||||||
inf = dtc_open_file(arg);
|
inf = dtc_open_file(arg);
|
||||||
dt = dt_from_source(inf);
|
bi = dt_from_source(inf);
|
||||||
} else if (streq(inform, "fs")) {
|
} else if (streq(inform, "fs")) {
|
||||||
dt = dt_from_fs(arg);
|
bi = dt_from_fs(arg);
|
||||||
} else if(streq(inform, "dtb")) {
|
} else if(streq(inform, "dtb")) {
|
||||||
inf = dtc_open_file(arg);
|
inf = dtc_open_file(arg);
|
||||||
dt = dt_from_blob(inf);
|
bi = dt_from_blob(inf);
|
||||||
} else {
|
} else {
|
||||||
die("Unknown input format \"%s\"\n", inform);
|
die("Unknown input format \"%s\"\n", inform);
|
||||||
}
|
}
|
||||||
|
@ -164,10 +164,10 @@ int main(int argc, char *argv[])
|
||||||
if (inf && (inf != stdin))
|
if (inf && (inf != stdin))
|
||||||
fclose(inf);
|
fclose(inf);
|
||||||
|
|
||||||
if (! dt)
|
if (! bi || ! bi->dt)
|
||||||
die("Couldn't read input tree\n");
|
die("Couldn't read input tree\n");
|
||||||
|
|
||||||
if (! check_device_tree(dt)) {
|
if (! check_device_tree(bi->dt)) {
|
||||||
fprintf(stderr, "Input tree has errors\n");
|
fprintf(stderr, "Input tree has errors\n");
|
||||||
if (! force)
|
if (! force)
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -183,11 +183,11 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (streq(outform, "dts")) {
|
if (streq(outform, "dts")) {
|
||||||
write_tree_source(outf, dt, 0);
|
write_tree_source(outf, bi);
|
||||||
} else if (streq(outform, "dtb")) {
|
} else if (streq(outform, "dtb")) {
|
||||||
write_dt_blob(outf, dt, outversion, reservenum);
|
write_dt_blob(outf, bi, outversion);
|
||||||
} else if (streq(outform, "asm")) {
|
} else if (streq(outform, "asm")) {
|
||||||
write_dt_asm(outf, dt, outversion, reservenum);
|
write_dt_asm(outf, bi, outversion);
|
||||||
} else if (streq(outform, "null")) {
|
} else if (streq(outform, "null")) {
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
} else {
|
} else {
|
||||||
|
|
38
dtc.h
38
dtc.h
|
@ -31,6 +31,10 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <endian.h>
|
||||||
|
#include <byteswap.h>
|
||||||
|
|
||||||
|
#include "flat_dt.h"
|
||||||
|
|
||||||
static inline void die(char * str, ...)
|
static inline void die(char * str, ...)
|
||||||
{
|
{
|
||||||
|
@ -74,7 +78,13 @@ typedef u32 cell_t;
|
||||||
#define cpu_to_be32(x) htonl(x)
|
#define cpu_to_be32(x) htonl(x)
|
||||||
#define be32_to_cpu(x) ntohl(x)
|
#define be32_to_cpu(x) ntohl(x)
|
||||||
|
|
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
|
#define cpu_to_be64(x) (x)
|
||||||
|
#define be64_to_cpu(x) (x)
|
||||||
|
#else
|
||||||
|
#define cpu_to_be64(x) bswap_64(x)
|
||||||
|
#define be64_to_cpu(x) bswap_64(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define streq(a, b) (strcmp((a), (b)) == 0)
|
#define streq(a, b) (strcmp((a), (b)) == 0)
|
||||||
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
|
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
|
||||||
|
@ -110,6 +120,7 @@ struct data data_copy_file(FILE *f, size_t len);
|
||||||
|
|
||||||
struct data data_append_data(struct data d, void *p, int len);
|
struct data data_append_data(struct data d, void *p, int len);
|
||||||
struct data data_append_cell(struct data d, cell_t word);
|
struct data data_append_cell(struct data d, cell_t word);
|
||||||
|
struct data data_append_addr(struct data d, u64 addr);
|
||||||
struct data data_append_byte(struct data d, uint8_t byte);
|
struct data data_append_byte(struct data d, uint8_t byte);
|
||||||
struct data data_append_zeroes(struct data d, int len);
|
struct data data_append_zeroes(struct data d, int len);
|
||||||
struct data data_append_align(struct data d, int align);
|
struct data data_append_align(struct data d, int align);
|
||||||
|
@ -118,6 +129,8 @@ struct data data_add_fixup(struct data d, char *ref);
|
||||||
|
|
||||||
int data_is_one_string(struct data d);
|
int data_is_one_string(struct data d);
|
||||||
|
|
||||||
|
struct data build_mem_reserve(struct data d);
|
||||||
|
|
||||||
/* DT constraints */
|
/* DT constraints */
|
||||||
|
|
||||||
#define MAX_PROPNAME_LEN 31
|
#define MAX_PROPNAME_LEN 31
|
||||||
|
@ -168,6 +181,16 @@ void add_child(struct node *parent, struct node *child);
|
||||||
|
|
||||||
int check_device_tree(struct node *dt);
|
int check_device_tree(struct node *dt);
|
||||||
|
|
||||||
|
/* Boot info (tree plus memreserve information */
|
||||||
|
|
||||||
|
struct boot_info {
|
||||||
|
struct data mem_reserve_data; /* mem reserve from header */
|
||||||
|
struct node *dt; /* the device tree */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct boot_info *build_boot_info(struct data mem_reserve_data,
|
||||||
|
struct node *tree);
|
||||||
|
|
||||||
/* Flattened trees */
|
/* Flattened trees */
|
||||||
|
|
||||||
enum flat_dt_format {
|
enum flat_dt_format {
|
||||||
|
@ -175,20 +198,19 @@ enum flat_dt_format {
|
||||||
FFMT_ASM,
|
FFMT_ASM,
|
||||||
};
|
};
|
||||||
|
|
||||||
void write_dt_blob(FILE *f, struct node *tree, int version, int reservenum);
|
void write_dt_blob(FILE *f, struct boot_info *bi, int version);
|
||||||
void write_dt_asm(FILE *f, struct node *tree, int version, int reservenum);
|
void write_dt_asm(FILE *f, struct boot_info *bi, int version);
|
||||||
|
|
||||||
struct node *dt_from_blob(FILE *f);
|
struct boot_info *dt_from_blob(FILE *f);
|
||||||
|
|
||||||
/* Tree source */
|
/* Tree source */
|
||||||
|
|
||||||
void write_tree_source(FILE *f, struct node *tree, int level);
|
void write_tree_source(FILE *f, struct boot_info *bi);
|
||||||
|
struct boot_info *dt_from_source(FILE *f);
|
||||||
struct node *dt_from_source(FILE *f);
|
|
||||||
|
|
||||||
/* FS trees */
|
/* FS trees */
|
||||||
|
|
||||||
struct node *dt_from_fs(char *dirname);
|
struct boot_info *dt_from_fs(char *dirname);
|
||||||
|
|
||||||
/* misc */
|
/* misc */
|
||||||
|
|
||||||
|
|
105
flattree.c
105
flattree.c
|
@ -288,10 +288,11 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
|
||||||
|
|
||||||
static void make_bph(struct boot_param_header *bph,
|
static void make_bph(struct boot_param_header *bph,
|
||||||
struct version_info *vi,
|
struct version_info *vi,
|
||||||
int reservenum,
|
struct data *mem_reserve_data,
|
||||||
int dtsize, int strsize)
|
int dtsize, int strsize)
|
||||||
{
|
{
|
||||||
int reserve_off;
|
int reserve_off;
|
||||||
|
int reservenum = mem_reserve_data->len / sizeof(struct reserve_entry);
|
||||||
int reservesize = (reservenum+1) * sizeof(struct reserve_entry);
|
int reservesize = (reservenum+1) * sizeof(struct reserve_entry);
|
||||||
|
|
||||||
memset(bph, 0xff, sizeof(*bph));
|
memset(bph, 0xff, sizeof(*bph));
|
||||||
|
@ -316,14 +317,14 @@ static void make_bph(struct boot_param_header *bph,
|
||||||
bph->size_dt_strings = cpu_to_be32(strsize);
|
bph->size_dt_strings = cpu_to_be32(strsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_dt_blob(FILE *f, struct node *tree, int version, int reservenum)
|
void write_dt_blob(FILE *f, struct boot_info *bi, int version)
|
||||||
{
|
{
|
||||||
struct version_info *vi = NULL;
|
struct version_info *vi = NULL;
|
||||||
int i;
|
int i;
|
||||||
struct data dtbuf = empty_data;
|
struct data dtbuf = empty_data;
|
||||||
struct data strbuf = empty_data;
|
struct data strbuf = empty_data;
|
||||||
struct boot_param_header bph;
|
struct boot_param_header bph;
|
||||||
struct reserve_entry re = {.address = 0, .size = 0};
|
struct reserve_entry termre = {.address = 0, .size = 0};
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(version_table); i++) {
|
for (i = 0; i < ARRAY_SIZE(version_table); i++) {
|
||||||
if (version_table[i].version == version)
|
if (version_table[i].version == version)
|
||||||
|
@ -335,10 +336,11 @@ void write_dt_blob(FILE *f, struct node *tree, int version, int reservenum)
|
||||||
dtbuf = empty_data;
|
dtbuf = empty_data;
|
||||||
strbuf = empty_data;
|
strbuf = empty_data;
|
||||||
|
|
||||||
flatten_tree(tree, &bin_emitter, &dtbuf, &strbuf, vi);
|
flatten_tree(bi->dt, &bin_emitter, &dtbuf, &strbuf, vi);
|
||||||
bin_emit_cell(&dtbuf, OF_DT_END);
|
bin_emit_cell(&dtbuf, OF_DT_END);
|
||||||
|
|
||||||
make_bph(&bph, vi, reservenum, dtbuf.len, strbuf.len);
|
/* Make header */
|
||||||
|
make_bph(&bph, vi, &bi->mem_reserve_data, dtbuf.len, strbuf.len);
|
||||||
|
|
||||||
fwrite(&bph, vi->hdr_size, 1, f);
|
fwrite(&bph, vi->hdr_size, 1, f);
|
||||||
|
|
||||||
|
@ -346,8 +348,15 @@ void write_dt_blob(FILE *f, struct node *tree, int version, int reservenum)
|
||||||
for (i = vi->hdr_size; i < be32_to_cpu(bph.off_mem_rsvmap); i++)
|
for (i = vi->hdr_size; i < be32_to_cpu(bph.off_mem_rsvmap); i++)
|
||||||
fputc(0, f);
|
fputc(0, f);
|
||||||
|
|
||||||
for (i = 0; i < reservenum+1; i++)
|
/*
|
||||||
fwrite(&re, sizeof(re), 1, f);
|
* Reserve map entries.
|
||||||
|
* Since the blob is relocatable, the address of the map is not
|
||||||
|
* determinable here, so no entry is made for the DT itself.
|
||||||
|
* Each entry is an (address, size) pair of u64 values.
|
||||||
|
* Always supply a zero-sized temination entry.
|
||||||
|
*/
|
||||||
|
fwrite(bi->mem_reserve_data.val, bi->mem_reserve_data.len, 1, f);
|
||||||
|
fwrite(&termre, sizeof(termre), 1, f);
|
||||||
|
|
||||||
fwrite(dtbuf.val, dtbuf.len, 1, f);
|
fwrite(dtbuf.val, dtbuf.len, 1, f);
|
||||||
fwrite(strbuf.val, strbuf.len, 1, f);
|
fwrite(strbuf.val, strbuf.len, 1, f);
|
||||||
|
@ -373,7 +382,7 @@ void dump_stringtable_asm(FILE *f, struct data strbuf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_dt_asm(FILE *f, struct node *tree, int version, int reservenum)
|
void write_dt_asm(FILE *f, struct boot_info *bi, int version)
|
||||||
{
|
{
|
||||||
struct version_info *vi = NULL;
|
struct version_info *vi = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
@ -417,20 +426,30 @@ void write_dt_asm(FILE *f, struct node *tree, int version, int reservenum)
|
||||||
fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n",
|
fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n",
|
||||||
symprefix, symprefix);
|
symprefix, symprefix);
|
||||||
|
|
||||||
/* align the reserve map to a doubleword boundary */
|
/*
|
||||||
|
* Reserve map entries.
|
||||||
|
* Align the reserve map to a doubleword boundary.
|
||||||
|
* Each entry is an (address, size) pair of u64 values.
|
||||||
|
* Since the ASM file variant can relocate and compute the address
|
||||||
|
* and size of the the device tree itself, and an entry for it.
|
||||||
|
* Always supply a zero-sized temination entry.
|
||||||
|
*/
|
||||||
asm_emit_align(f, 8);
|
asm_emit_align(f, 8);
|
||||||
emit_label(f, symprefix, "reserve_map");
|
emit_label(f, symprefix, "reserve_map");
|
||||||
/* reserve map entry for the device tree itself */
|
|
||||||
fprintf(f, "\t.long\t0, _%s_blob_start\n", symprefix);
|
fprintf(f, "\t.long\t0, _%s_blob_start\n", symprefix);
|
||||||
fprintf(f, "\t.long\t0, _%s_blob_end - _%s_blob_start\n",
|
fprintf(f, "\t.long\t0, _%s_blob_end - _%s_blob_start\n",
|
||||||
symprefix, symprefix);
|
symprefix, symprefix);
|
||||||
for (i = 0; i < reservenum+1; i++) {
|
|
||||||
fprintf(f, "\t.llong\t0\n");
|
if (bi->mem_reserve_data.len > 0) {
|
||||||
fprintf(f, "\t.llong\t0\n");
|
fprintf(f, "/* Memory reserve map from source file */\n");
|
||||||
|
asm_emit_data(f, bi->mem_reserve_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(f, "\t.llong\t0\n");
|
||||||
|
fprintf(f, "\t.llong\t0\n");
|
||||||
|
|
||||||
emit_label(f, symprefix, "struct_start");
|
emit_label(f, symprefix, "struct_start");
|
||||||
flatten_tree(tree, &asm_emitter, f, &strbuf, vi);
|
flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi);
|
||||||
fprintf(f, "\t.long\tOF_DT_END\n");
|
fprintf(f, "\t.long\tOF_DT_END\n");
|
||||||
emit_label(f, symprefix, "struct_end");
|
emit_label(f, symprefix, "struct_end");
|
||||||
|
|
||||||
|
@ -561,6 +580,43 @@ struct property *flat_read_property(struct inbuf *dtbuf, struct inbuf *strbuf,
|
||||||
return build_property(name, val, NULL);
|
return build_property(name, val, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct data flat_read_mem_reserve(struct inbuf *inb)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
int len = 0;
|
||||||
|
int done = 0;
|
||||||
|
cell_t cells[4];
|
||||||
|
struct data d;
|
||||||
|
|
||||||
|
d = empty_data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each entry is a pair of u64 (addr, size) values for 4 cell_t's.
|
||||||
|
* List terminates at an entry with size equal to zero.
|
||||||
|
*
|
||||||
|
* First pass, count entries.
|
||||||
|
*/
|
||||||
|
p = inb->ptr;
|
||||||
|
do {
|
||||||
|
flat_read_chunk(inb, &cells[0], 4 * sizeof(cell_t));
|
||||||
|
if (cells[2] == 0 && cells[3] == 0) {
|
||||||
|
done = 1;
|
||||||
|
} else {
|
||||||
|
++len;
|
||||||
|
}
|
||||||
|
} while (!done);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Back up for pass two, reading the whole data value.
|
||||||
|
*/
|
||||||
|
inb->ptr = p;
|
||||||
|
d = flat_read_data(inb, len * 4 * sizeof(cell_t));
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *nodename_from_path(char *ppath, char *cpath)
|
static char *nodename_from_path(char *ppath, char *cpath)
|
||||||
{
|
{
|
||||||
char *lslash;
|
char *lslash;
|
||||||
|
@ -668,15 +724,19 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node *dt_from_blob(FILE *f)
|
|
||||||
|
struct boot_info *dt_from_blob(FILE *f)
|
||||||
{
|
{
|
||||||
u32 magic, totalsize, off_dt, off_str, version, size_str;
|
u32 magic, totalsize, version, size_str;
|
||||||
|
u32 off_dt, off_str, off_mem_rsvmap;
|
||||||
int rc;
|
int rc;
|
||||||
char *blob;
|
char *blob;
|
||||||
struct boot_param_header *bph;
|
struct boot_param_header *bph;
|
||||||
char *p;
|
char *p;
|
||||||
struct inbuf dtbuf, strbuf;
|
struct inbuf dtbuf, strbuf;
|
||||||
|
struct inbuf memresvbuf;
|
||||||
int sizeleft;
|
int sizeleft;
|
||||||
|
struct data mem_reserve_data;
|
||||||
struct node *tree;
|
struct node *tree;
|
||||||
u32 val;
|
u32 val;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
@ -735,18 +795,21 @@ struct node *dt_from_blob(FILE *f)
|
||||||
|
|
||||||
off_dt = be32_to_cpu(bph->off_dt_struct);
|
off_dt = be32_to_cpu(bph->off_dt_struct);
|
||||||
off_str = be32_to_cpu(bph->off_dt_strings);
|
off_str = be32_to_cpu(bph->off_dt_strings);
|
||||||
|
off_mem_rsvmap = be32_to_cpu(bph->off_mem_rsvmap);
|
||||||
version = be32_to_cpu(bph->version);
|
version = be32_to_cpu(bph->version);
|
||||||
|
|
||||||
fprintf(stderr, "\tmagic:\t\t\t0x%x\n", magic);
|
fprintf(stderr, "\tmagic:\t\t\t0x%x\n", magic);
|
||||||
fprintf(stderr, "\ttotalsize:\t\t%d\n", totalsize);
|
fprintf(stderr, "\ttotalsize:\t\t%d\n", totalsize);
|
||||||
fprintf(stderr, "\toff_dt_struct:\t\t0x%x\n", off_dt);
|
fprintf(stderr, "\toff_dt_struct:\t\t0x%x\n", off_dt);
|
||||||
fprintf(stderr, "\toff_dt_strings:\t\t0x%x\n", off_str);
|
fprintf(stderr, "\toff_dt_strings:\t\t0x%x\n", off_str);
|
||||||
fprintf(stderr, "\toff_mem_rsvmap:\t\t0x%x\n",
|
fprintf(stderr, "\toff_mem_rsvmap:\t\t0x%x\n", off_mem_rsvmap);
|
||||||
be32_to_cpu(bph->off_mem_rsvmap));
|
|
||||||
fprintf(stderr, "\tversion:\t\t0x%x\n", version );
|
fprintf(stderr, "\tversion:\t\t0x%x\n", version );
|
||||||
fprintf(stderr, "\tlast_comp_version:\t0x%x\n",
|
fprintf(stderr, "\tlast_comp_version:\t0x%x\n",
|
||||||
be32_to_cpu(bph->last_comp_version));
|
be32_to_cpu(bph->last_comp_version));
|
||||||
|
|
||||||
|
if (off_mem_rsvmap >= totalsize)
|
||||||
|
die("Mem Reserve structure offset exceeds total size\n");
|
||||||
|
|
||||||
if (off_dt >= totalsize)
|
if (off_dt >= totalsize)
|
||||||
die("DT structure offset exceeds total size\n");
|
die("DT structure offset exceeds total size\n");
|
||||||
|
|
||||||
|
@ -768,12 +831,16 @@ struct node *dt_from_blob(FILE *f)
|
||||||
flags |= FTF_FULLPATH | FTF_NAMEPROPS | FTF_VARALIGN;
|
flags |= FTF_FULLPATH | FTF_NAMEPROPS | FTF_VARALIGN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inbuf_init(&memresvbuf,
|
||||||
|
blob + off_mem_rsvmap, blob + totalsize);
|
||||||
inbuf_init(&dtbuf, blob + off_dt, blob + totalsize);
|
inbuf_init(&dtbuf, blob + off_dt, blob + totalsize);
|
||||||
inbuf_init(&strbuf, blob + off_str, blob + totalsize);
|
inbuf_init(&strbuf, blob + off_str, blob + totalsize);
|
||||||
|
|
||||||
if (version >= 3)
|
if (version >= 3)
|
||||||
strbuf.limit = strbuf.base + size_str;
|
strbuf.limit = strbuf.base + size_str;
|
||||||
|
|
||||||
|
mem_reserve_data = flat_read_mem_reserve(&memresvbuf);
|
||||||
|
|
||||||
val = flat_read_word(&dtbuf);
|
val = flat_read_word(&dtbuf);
|
||||||
|
|
||||||
if (val != OF_DT_BEGIN_NODE)
|
if (val != OF_DT_BEGIN_NODE)
|
||||||
|
@ -787,5 +854,5 @@ struct node *dt_from_blob(FILE *f)
|
||||||
|
|
||||||
free(blob);
|
free(blob);
|
||||||
|
|
||||||
return tree;
|
return build_boot_info(mem_reserve_data, tree);
|
||||||
}
|
}
|
||||||
|
|
4
fstree.c
4
fstree.c
|
@ -80,7 +80,7 @@ static struct node *read_fstree(char *dirname)
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node *dt_from_fs(char *dirname)
|
struct boot_info *dt_from_fs(char *dirname)
|
||||||
{
|
{
|
||||||
struct node *tree;
|
struct node *tree;
|
||||||
|
|
||||||
|
@ -89,6 +89,6 @@ struct node *dt_from_fs(char *dirname)
|
||||||
|
|
||||||
fill_fullpaths(tree, "");
|
fill_fullpaths(tree, "");
|
||||||
|
|
||||||
return tree;
|
return build_boot_info(empty_data, tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
livetree.c
12
livetree.c
|
@ -665,3 +665,15 @@ int check_device_tree(struct node *dt)
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct boot_info *build_boot_info(struct data mem_reserve_data,
|
||||||
|
struct node *tree)
|
||||||
|
{
|
||||||
|
struct boot_info *bi;
|
||||||
|
|
||||||
|
bi = xmalloc(sizeof(*bi));
|
||||||
|
bi->mem_reserve_data = mem_reserve_data;
|
||||||
|
bi->dt = tree;
|
||||||
|
|
||||||
|
return bi;
|
||||||
|
}
|
||||||
|
|
4
test.dts
4
test.dts
|
@ -1,3 +1,7 @@
|
||||||
|
/memreserve/ 1000000000000000 0000000002000000;
|
||||||
|
/memreserve/ 2000000000000000-20ffffffffffffff;
|
||||||
|
/memreserve/ 0-13;
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "MyBoardName";
|
model = "MyBoardName";
|
||||||
compatible = "MyBoardFamilyName";
|
compatible = "MyBoardFamilyName";
|
||||||
|
|
51
treesource.c
51
treesource.c
|
@ -20,20 +20,35 @@
|
||||||
|
|
||||||
#include "dtc.h"
|
#include "dtc.h"
|
||||||
|
|
||||||
struct node *device_tree;
|
|
||||||
|
|
||||||
extern FILE *yyin;
|
extern FILE *yyin;
|
||||||
extern int yyparse(void);
|
extern int yyparse(void);
|
||||||
|
extern void yyerror(char const *);
|
||||||
|
|
||||||
struct node *dt_from_source(FILE *f)
|
struct boot_info *the_boot_info;
|
||||||
|
|
||||||
|
struct data build_mem_reserve(struct data d)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* FIXME: Should reconcile the -R parameter here now?
|
||||||
|
*/
|
||||||
|
if (d.len % 16 != 0) {
|
||||||
|
yyerror("Memory Reserve entries are <u64 addr, u64 size>\n");
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct boot_info *dt_from_source(FILE *f)
|
||||||
|
{
|
||||||
|
the_boot_info = NULL;
|
||||||
|
|
||||||
yyin = f;
|
yyin = f;
|
||||||
if (yyparse() != 0)
|
if (yyparse() != 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fill_fullpaths(device_tree, "");
|
fill_fullpaths(the_boot_info->dt, "");
|
||||||
|
|
||||||
return device_tree;
|
return the_boot_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_prefix(FILE *f, int level)
|
static void write_prefix(FILE *f, int level)
|
||||||
|
@ -75,7 +90,8 @@ static enum proptype guess_type(struct property *prop)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_tree_source(FILE *f, struct node *tree, int level)
|
|
||||||
|
void write_tree_source_node(FILE *f, struct node *tree, int level)
|
||||||
{
|
{
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
struct node *child;
|
struct node *child;
|
||||||
|
@ -133,8 +149,29 @@ void write_tree_source(FILE *f, struct node *tree, int level)
|
||||||
}
|
}
|
||||||
for_each_child(tree, child) {
|
for_each_child(tree, child) {
|
||||||
fprintf(f, "\n");
|
fprintf(f, "\n");
|
||||||
write_tree_source(f, child, level+1);
|
write_tree_source_node(f, child, level+1);
|
||||||
}
|
}
|
||||||
write_prefix(f, level);
|
write_prefix(f, level);
|
||||||
fprintf(f, "};\n");
|
fprintf(f, "};\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void write_tree_source(FILE *f, struct boot_info *bi)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert((bi->mem_reserve_data.len % sizeof(struct reserve_entry)) == 0);
|
||||||
|
for (i = 0;
|
||||||
|
i < (bi->mem_reserve_data.len / sizeof(struct reserve_entry));
|
||||||
|
i++) {
|
||||||
|
struct reserve_entry *re = ((struct reserve_entry *)
|
||||||
|
bi->mem_reserve_data.val) + i;
|
||||||
|
|
||||||
|
fprintf(f, "/memreserve/\t%016llx-%016llx;\n",
|
||||||
|
(unsigned long long)re->address,
|
||||||
|
(unsigned long long)re->address + re->size - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
write_tree_source_node(f, bi->dt, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue