mirror of https://gitlab.com/qemu-project/dtc.git
Rework tracking of reserve entries during processing. This is initial work
to allow more powerful handling of reserve entries.
This commit is contained in:
parent
fccb194a14
commit
f040d95b84
10
data.c
10
data.c
|
@ -222,6 +222,16 @@ 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_re(struct data d, struct reserve_entry *re)
|
||||||
|
{
|
||||||
|
struct reserve_entry bere;
|
||||||
|
|
||||||
|
bere.address = cpu_to_be64(re->address);
|
||||||
|
bere.size = cpu_to_be64(re->size);
|
||||||
|
|
||||||
|
return data_append_data(d, &bere, sizeof(bere));
|
||||||
|
}
|
||||||
|
|
||||||
struct data data_append_addr(struct data d, u64 addr)
|
struct data data_append_addr(struct data d, u64 addr)
|
||||||
{
|
{
|
||||||
u64 beaddr = cpu_to_be64(addr);
|
u64 beaddr = cpu_to_be64(addr);
|
||||||
|
|
17
dtc-parser.y
17
dtc-parser.y
|
@ -43,7 +43,7 @@ extern struct boot_info *the_boot_info;
|
||||||
int datalen;
|
int datalen;
|
||||||
int hexlen;
|
int hexlen;
|
||||||
u64 addr;
|
u64 addr;
|
||||||
struct reserve_entry re;
|
struct reserve_info *re;
|
||||||
}
|
}
|
||||||
|
|
||||||
%token DT_MEMRESERVE
|
%token DT_MEMRESERVE
|
||||||
|
@ -59,7 +59,7 @@ extern struct boot_info *the_boot_info;
|
||||||
|
|
||||||
%type <data> propdata
|
%type <data> propdata
|
||||||
%type <re> memreserve
|
%type <re> memreserve
|
||||||
%type <data> memreserves
|
%type <re> memreserves
|
||||||
%type <data> celllist
|
%type <data> celllist
|
||||||
%type <data> bytestring
|
%type <data> bytestring
|
||||||
%type <prop> propdef
|
%type <prop> propdef
|
||||||
|
@ -79,22 +79,19 @@ sourcefile: memreserves devicetree {
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
memreserves: memreserves memreserve {
|
memreserves: memreserve memreserves {
|
||||||
$$ = data_append_addr(data_append_addr($1, $2.address),
|
$$ = chain_reserve_entry($1, $2);
|
||||||
$2.size);
|
|
||||||
}
|
}
|
||||||
| /* empty */ {
|
| /* empty */ {
|
||||||
$$ = empty_data;
|
$$ = NULL;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
memreserve: DT_MEMRESERVE DT_ADDR DT_ADDR ';' {
|
memreserve: DT_MEMRESERVE DT_ADDR DT_ADDR ';' {
|
||||||
$$.address = $2;
|
$$ = build_reserve_entry($2, $3, NULL);
|
||||||
$$.size = $3;
|
|
||||||
}
|
}
|
||||||
| DT_MEMRESERVE DT_ADDR '-' DT_ADDR ';' {
|
| DT_MEMRESERVE DT_ADDR '-' DT_ADDR ';' {
|
||||||
$$.address = $2;
|
$$ = build_reserve_entry($2, $4 - $2 + 1, NULL);
|
||||||
$$.size = $4 - $2 + 1;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
23
dtc.h
23
dtc.h
|
@ -120,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_re(struct data d, struct reserve_entry *re);
|
||||||
struct data data_append_addr(struct data d, u64 addr);
|
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);
|
||||||
|
@ -129,8 +130,6 @@ 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
|
||||||
|
@ -183,12 +182,28 @@ int check_device_tree(struct node *dt);
|
||||||
|
|
||||||
/* Boot info (tree plus memreserve information */
|
/* Boot info (tree plus memreserve information */
|
||||||
|
|
||||||
|
struct reserve_info {
|
||||||
|
struct reserve_entry re;
|
||||||
|
|
||||||
|
struct reserve_info *next;
|
||||||
|
|
||||||
|
char *label;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct reserve_info *build_reserve_entry(u64 start, u64 len, char *label);
|
||||||
|
struct reserve_info *chain_reserve_entry(struct reserve_info *first,
|
||||||
|
struct reserve_info *list);
|
||||||
|
struct reserve_info *add_reserve_entry(struct reserve_info *list,
|
||||||
|
struct reserve_info *new);
|
||||||
|
|
||||||
|
|
||||||
struct boot_info {
|
struct boot_info {
|
||||||
struct data mem_reserve_data; /* mem reserve from header */
|
struct reserve_info *reservelist;
|
||||||
|
/* struct data mem_reserve_data; /\* mem reserve from header *\/ */
|
||||||
struct node *dt; /* the device tree */
|
struct node *dt; /* the device tree */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct boot_info *build_boot_info(struct data mem_reserve_data,
|
struct boot_info *build_boot_info(struct reserve_info *reservelist,
|
||||||
struct node *tree);
|
struct node *tree);
|
||||||
|
|
||||||
/* Flattened trees */
|
/* Flattened trees */
|
||||||
|
|
52
flattree.c
52
flattree.c
|
@ -287,14 +287,25 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
|
||||||
emit->endnode(etarget, tree->label);
|
emit->endnode(etarget, tree->label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct data flatten_reserve_list(struct reserve_info *reservelist,
|
||||||
|
struct version_info *vi)
|
||||||
|
{
|
||||||
|
struct reserve_info *re;
|
||||||
|
struct data d = empty_data;
|
||||||
|
|
||||||
|
for (re = reservelist; re; re = re->next) {
|
||||||
|
d = data_append_re(d, &re->re);
|
||||||
|
}
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
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,
|
||||||
struct data *mem_reserve_data,
|
int reservesize, 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);
|
reservesize += sizeof(struct reserve_entry);
|
||||||
|
|
||||||
memset(bph, 0xff, sizeof(*bph));
|
memset(bph, 0xff, sizeof(*bph));
|
||||||
|
|
||||||
|
@ -324,6 +335,7 @@ void write_dt_blob(FILE *f, struct boot_info *bi, int version)
|
||||||
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 data reservebuf;
|
||||||
struct boot_param_header bph;
|
struct boot_param_header bph;
|
||||||
struct reserve_entry termre = {.address = 0, .size = 0};
|
struct reserve_entry termre = {.address = 0, .size = 0};
|
||||||
|
|
||||||
|
@ -340,8 +352,10 @@ void write_dt_blob(FILE *f, struct boot_info *bi, int version)
|
||||||
flatten_tree(bi->dt, &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);
|
||||||
|
|
||||||
|
reservebuf = flatten_reserve_list(bi->reservelist, vi);
|
||||||
|
|
||||||
/* Make header */
|
/* Make header */
|
||||||
make_bph(&bph, vi, &bi->mem_reserve_data, dtbuf.len, strbuf.len);
|
make_bph(&bph, vi, reservebuf.len, dtbuf.len, strbuf.len);
|
||||||
|
|
||||||
fwrite(&bph, vi->hdr_size, 1, f);
|
fwrite(&bph, vi->hdr_size, 1, f);
|
||||||
|
|
||||||
|
@ -356,7 +370,7 @@ void write_dt_blob(FILE *f, struct boot_info *bi, int version)
|
||||||
* Each entry is an (address, size) pair of u64 values.
|
* Each entry is an (address, size) pair of u64 values.
|
||||||
* Always supply a zero-sized temination entry.
|
* Always supply a zero-sized temination entry.
|
||||||
*/
|
*/
|
||||||
fwrite(bi->mem_reserve_data.val, bi->mem_reserve_data.len, 1, f);
|
fwrite(reservebuf.val, reservebuf.len, 1, f);
|
||||||
fwrite(&termre, sizeof(termre), 1, f);
|
fwrite(&termre, sizeof(termre), 1, f);
|
||||||
|
|
||||||
fwrite(dtbuf.val, dtbuf.len, 1, f);
|
fwrite(dtbuf.val, dtbuf.len, 1, f);
|
||||||
|
@ -388,6 +402,7 @@ 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;
|
||||||
struct data strbuf = empty_data;
|
struct data strbuf = empty_data;
|
||||||
|
struct reserve_info *re;
|
||||||
char *symprefix = "dt";
|
char *symprefix = "dt";
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(version_table); i++) {
|
for (i = 0; i < ARRAY_SIZE(version_table); i++) {
|
||||||
|
@ -441,13 +456,14 @@ void write_dt_asm(FILE *f, struct boot_info *bi, int version)
|
||||||
fprintf(f, "\t.quad\t0, _%s_blob_end - _%s_blob_start\n",
|
fprintf(f, "\t.quad\t0, _%s_blob_end - _%s_blob_start\n",
|
||||||
symprefix, symprefix);
|
symprefix, symprefix);
|
||||||
|
|
||||||
if (bi->mem_reserve_data.len > 0) {
|
|
||||||
fprintf(f, "/* Memory reserve map from source file */\n");
|
fprintf(f, "/* Memory reserve map from source file */\n");
|
||||||
asm_emit_data(f, bi->mem_reserve_data);
|
for (re = bi->reservelist; re; re = re->next) {
|
||||||
|
fprintf(f, "\t.quad\t0x%016llx\n\t.quad\t0x%016llx\n",
|
||||||
|
(unsigned long long)re->re.address,
|
||||||
|
(unsigned long long)re->re.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(f, "\t.quad\t0\n");
|
fprintf(f, "\t.quad\t0\n\t.quad\t0\n");
|
||||||
fprintf(f, "\t.quad\t0\n");
|
|
||||||
|
|
||||||
emit_label(f, symprefix, "struct_start");
|
emit_label(f, symprefix, "struct_start");
|
||||||
flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi);
|
flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi);
|
||||||
|
@ -582,11 +598,12 @@ static struct property *flat_read_property(struct inbuf *dtbuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct data flat_read_mem_reserve(struct inbuf *inb)
|
static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
|
||||||
{
|
{
|
||||||
|
struct reserve_info *reservelist = NULL;
|
||||||
|
struct reserve_info *new;
|
||||||
char *p;
|
char *p;
|
||||||
struct reserve_entry re;
|
struct reserve_entry re;
|
||||||
struct data d = empty_data;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Each entry is a pair of u64 (addr, size) values for 4 cell_t's.
|
* Each entry is a pair of u64 (addr, size) values for 4 cell_t's.
|
||||||
|
@ -600,10 +617,11 @@ static struct data flat_read_mem_reserve(struct inbuf *inb)
|
||||||
if (re.size == 0)
|
if (re.size == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
d = data_append_data(d, &re, sizeof(re));
|
new = build_reserve_entry(re.address, re.size, NULL);
|
||||||
|
reservelist = add_reserve_entry(reservelist, new);
|
||||||
}
|
}
|
||||||
|
|
||||||
return d;
|
return reservelist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -726,7 +744,7 @@ struct boot_info *dt_from_blob(FILE *f)
|
||||||
struct inbuf dtbuf, strbuf;
|
struct inbuf dtbuf, strbuf;
|
||||||
struct inbuf memresvbuf;
|
struct inbuf memresvbuf;
|
||||||
int sizeleft;
|
int sizeleft;
|
||||||
struct data mem_reserve_data;
|
struct reserve_info *reservelist;
|
||||||
struct node *tree;
|
struct node *tree;
|
||||||
u32 val;
|
u32 val;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
@ -829,7 +847,7 @@ struct boot_info *dt_from_blob(FILE *f)
|
||||||
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);
|
reservelist = flat_read_mem_reserve(&memresvbuf);
|
||||||
|
|
||||||
val = flat_read_word(&dtbuf);
|
val = flat_read_word(&dtbuf);
|
||||||
|
|
||||||
|
@ -844,5 +862,5 @@ struct boot_info *dt_from_blob(FILE *f)
|
||||||
|
|
||||||
free(blob);
|
free(blob);
|
||||||
|
|
||||||
return build_boot_info(mem_reserve_data, tree);
|
return build_boot_info(reservelist, tree);
|
||||||
}
|
}
|
||||||
|
|
2
fstree.c
2
fstree.c
|
@ -89,6 +89,6 @@ struct boot_info *dt_from_fs(char *dirname)
|
||||||
|
|
||||||
fill_fullpaths(tree, "");
|
fill_fullpaths(tree, "");
|
||||||
|
|
||||||
return build_boot_info(empty_data, tree);
|
return build_boot_info(NULL, tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
44
livetree.c
44
livetree.c
|
@ -108,6 +108,46 @@ void add_child(struct node *parent, struct node *child)
|
||||||
*p = child;
|
*p = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct reserve_info *build_reserve_entry(u64 address, u64 size, char *label)
|
||||||
|
{
|
||||||
|
struct reserve_info *new = xmalloc(sizeof(*new));
|
||||||
|
|
||||||
|
new->re.address = address;
|
||||||
|
new->re.size = size;
|
||||||
|
|
||||||
|
new->next = NULL;
|
||||||
|
|
||||||
|
new->label = label;
|
||||||
|
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct reserve_info *chain_reserve_entry(struct reserve_info *first,
|
||||||
|
struct reserve_info *list)
|
||||||
|
{
|
||||||
|
assert(first->next == NULL);
|
||||||
|
|
||||||
|
first->next = list;
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct reserve_info *add_reserve_entry(struct reserve_info *list,
|
||||||
|
struct reserve_info *new)
|
||||||
|
{
|
||||||
|
struct reserve_info *last;
|
||||||
|
|
||||||
|
new->next = NULL;
|
||||||
|
|
||||||
|
if (! list)
|
||||||
|
return new;
|
||||||
|
|
||||||
|
for (last = list; last->next; last = last->next)
|
||||||
|
;
|
||||||
|
|
||||||
|
last->next = new;
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tree accessor functions
|
* Tree accessor functions
|
||||||
|
@ -682,13 +722,13 @@ int check_device_tree(struct node *dt)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct boot_info *build_boot_info(struct data mem_reserve_data,
|
struct boot_info *build_boot_info(struct reserve_info *reservelist,
|
||||||
struct node *tree)
|
struct node *tree)
|
||||||
{
|
{
|
||||||
struct boot_info *bi;
|
struct boot_info *bi;
|
||||||
|
|
||||||
bi = xmalloc(sizeof(*bi));
|
bi = xmalloc(sizeof(*bi));
|
||||||
bi->mem_reserve_data = mem_reserve_data;
|
bi->reservelist = reservelist;
|
||||||
bi->dt = tree;
|
bi->dt = tree;
|
||||||
|
|
||||||
return bi;
|
return bi;
|
||||||
|
|
27
treesource.c
27
treesource.c
|
@ -26,18 +26,6 @@ extern void yyerror(char const *);
|
||||||
|
|
||||||
struct boot_info *the_boot_info;
|
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)
|
struct boot_info *dt_from_source(FILE *f)
|
||||||
{
|
{
|
||||||
the_boot_info = NULL;
|
the_boot_info = NULL;
|
||||||
|
@ -158,19 +146,12 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level)
|
||||||
|
|
||||||
void write_tree_source(FILE *f, struct boot_info *bi)
|
void write_tree_source(FILE *f, struct boot_info *bi)
|
||||||
{
|
{
|
||||||
int i;
|
struct reserve_info *re;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
for (re = bi->reservelist; re; re = re->next) {
|
||||||
fprintf(f, "/memreserve/\t%016llx-%016llx;\n",
|
fprintf(f, "/memreserve/\t%016llx-%016llx;\n",
|
||||||
(unsigned long long)be64_to_cpu(re->address),
|
(unsigned long long)re->re.address,
|
||||||
(unsigned long long)(be64_to_cpu(re->address)
|
(unsigned long long)(re->re.address + re->re.size - 1));
|
||||||
+ be64_to_cpu(re->size) - 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
write_tree_source_node(f, bi->dt, 0);
|
write_tree_source_node(f, bi->dt, 0);
|
||||||
|
|
Loading…
Reference in New Issue