mirror of
https://github.com/dgibson/dtc.git
synced 2025-10-14 00:37:41 -04:00
dtc: Allow multiple labels on nodes and properties
At present, both the grammar and our internal data structures mean that there can be only one label on a node or property. This is a fairly arbitrary constraint, given that any number of value labels can appear at the same point, and that in C you can have any number of labels on the same statement. This is pretty much a non-issue now, but it may become important with some of the extensions that Grant and I have in mind. It's not that hard to change, so this patch does so, allowing an arbitrary number of labels on any given node or property. As usual a testcase is added too. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Acked-by: Grant Likely <grant.likely@secretlab.ca>
This commit is contained in:
parent
49c2da3085
commit
05898c67c1
9 changed files with 157 additions and 89 deletions
11
checks.c
11
checks.c
|
@ -314,16 +314,19 @@ static void check_duplicate_label(struct check *c, struct node *dt,
|
||||||
static void check_duplicate_label_node(struct check *c, struct node *dt,
|
static void check_duplicate_label_node(struct check *c, struct node *dt,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
{
|
{
|
||||||
if (node->label)
|
struct label *l;
|
||||||
check_duplicate_label(c, dt, node->label, node, NULL, NULL);
|
|
||||||
|
for_each_label(node->labels, l)
|
||||||
|
check_duplicate_label(c, dt, l->label, node, NULL, NULL);
|
||||||
}
|
}
|
||||||
static void check_duplicate_label_prop(struct check *c, struct node *dt,
|
static void check_duplicate_label_prop(struct check *c, struct node *dt,
|
||||||
struct node *node, struct property *prop)
|
struct node *node, struct property *prop)
|
||||||
{
|
{
|
||||||
struct marker *m = prop->val.markers;
|
struct marker *m = prop->val.markers;
|
||||||
|
struct label *l;
|
||||||
|
|
||||||
if (prop->label)
|
for_each_label(prop->labels, l)
|
||||||
check_duplicate_label(c, dt, prop->label, node, prop, NULL);
|
check_duplicate_label(c, dt, l->label, node, prop, NULL);
|
||||||
|
|
||||||
for_each_marker_of_type(m, LABEL)
|
for_each_marker_of_type(m, LABEL)
|
||||||
check_duplicate_label(c, dt, m->ref, node, prop, m);
|
check_duplicate_label(c, dt, m->ref, node, prop, m);
|
||||||
|
|
41
dtc-parser.y
41
dtc-parser.y
|
@ -78,7 +78,6 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
|
||||||
%type <node> nodedef
|
%type <node> nodedef
|
||||||
%type <node> subnode
|
%type <node> subnode
|
||||||
%type <nodelist> subnodes
|
%type <nodelist> subnodes
|
||||||
%type <labelref> label
|
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
@ -102,9 +101,14 @@ memreserves:
|
||||||
;
|
;
|
||||||
|
|
||||||
memreserve:
|
memreserve:
|
||||||
label DT_MEMRESERVE addr addr ';'
|
DT_MEMRESERVE addr addr ';'
|
||||||
{
|
{
|
||||||
$$ = build_reserve_entry($3, $4, $1);
|
$$ = build_reserve_entry($2, $3);
|
||||||
|
}
|
||||||
|
| DT_LABEL memreserve
|
||||||
|
{
|
||||||
|
add_label(&$2->labels, $1);
|
||||||
|
$$ = $2;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -118,7 +122,7 @@ addr:
|
||||||
devicetree:
|
devicetree:
|
||||||
'/' nodedef
|
'/' nodedef
|
||||||
{
|
{
|
||||||
$$ = name_node($2, "", NULL);
|
$$ = name_node($2, "");
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -141,13 +145,18 @@ proplist:
|
||||||
;
|
;
|
||||||
|
|
||||||
propdef:
|
propdef:
|
||||||
label DT_PROPNODENAME '=' propdata ';'
|
DT_PROPNODENAME '=' propdata ';'
|
||||||
{
|
{
|
||||||
$$ = build_property($2, $4, $1);
|
$$ = build_property($1, $3);
|
||||||
}
|
}
|
||||||
| label DT_PROPNODENAME ';'
|
| DT_PROPNODENAME ';'
|
||||||
{
|
{
|
||||||
$$ = build_property($2, empty_data, $1);
|
$$ = build_property($1, empty_data);
|
||||||
|
}
|
||||||
|
| DT_LABEL propdef
|
||||||
|
{
|
||||||
|
add_label(&$2->labels, $1);
|
||||||
|
$$ = $2;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -276,20 +285,14 @@ subnodes:
|
||||||
;
|
;
|
||||||
|
|
||||||
subnode:
|
subnode:
|
||||||
label DT_PROPNODENAME nodedef
|
DT_PROPNODENAME nodedef
|
||||||
{
|
{
|
||||||
$$ = name_node($3, $2, $1);
|
$$ = name_node($2, $1);
|
||||||
}
|
}
|
||||||
;
|
| DT_LABEL subnode
|
||||||
|
|
||||||
label:
|
|
||||||
/* empty */
|
|
||||||
{
|
{
|
||||||
$$ = NULL;
|
add_label(&$2->labels, $1);
|
||||||
}
|
$$ = $2;
|
||||||
| DT_LABEL
|
|
||||||
{
|
|
||||||
$$ = $1;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
22
dtc.h
22
dtc.h
|
@ -125,13 +125,18 @@ int data_is_one_string(struct data d);
|
||||||
#define MAX_NODENAME_LEN 31
|
#define MAX_NODENAME_LEN 31
|
||||||
|
|
||||||
/* Live trees */
|
/* Live trees */
|
||||||
|
struct label {
|
||||||
|
char *label;
|
||||||
|
struct label *next;
|
||||||
|
};
|
||||||
|
|
||||||
struct property {
|
struct property {
|
||||||
char *name;
|
char *name;
|
||||||
struct data val;
|
struct data val;
|
||||||
|
|
||||||
struct property *next;
|
struct property *next;
|
||||||
|
|
||||||
char *label;
|
struct label *labels;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct node {
|
struct node {
|
||||||
|
@ -148,21 +153,26 @@ struct node {
|
||||||
cell_t phandle;
|
cell_t phandle;
|
||||||
int addr_cells, size_cells;
|
int addr_cells, size_cells;
|
||||||
|
|
||||||
char *label;
|
struct label *labels;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define for_each_label(l0, l) \
|
||||||
|
for ((l) = (l0); (l); (l) = (l)->next)
|
||||||
|
|
||||||
#define for_each_property(n, p) \
|
#define for_each_property(n, p) \
|
||||||
for ((p) = (n)->proplist; (p); (p) = (p)->next)
|
for ((p) = (n)->proplist; (p); (p) = (p)->next)
|
||||||
|
|
||||||
#define for_each_child(n, c) \
|
#define for_each_child(n, c) \
|
||||||
for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
|
for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
|
||||||
|
|
||||||
struct property *build_property(char *name, struct data val, char *label);
|
void add_label(struct label **labels, char *label);
|
||||||
|
|
||||||
|
struct property *build_property(char *name, struct data val);
|
||||||
struct property *chain_property(struct property *first, struct property *list);
|
struct property *chain_property(struct property *first, struct property *list);
|
||||||
struct property *reverse_properties(struct property *first);
|
struct property *reverse_properties(struct property *first);
|
||||||
|
|
||||||
struct node *build_node(struct property *proplist, struct node *children);
|
struct node *build_node(struct property *proplist, struct node *children);
|
||||||
struct node *name_node(struct node *node, char *name, char *label);
|
struct node *name_node(struct node *node, char *name);
|
||||||
struct node *chain_node(struct node *first, struct node *list);
|
struct node *chain_node(struct node *first, struct node *list);
|
||||||
|
|
||||||
void add_property(struct node *node, struct property *prop);
|
void add_property(struct node *node, struct property *prop);
|
||||||
|
@ -191,10 +201,10 @@ struct reserve_info {
|
||||||
|
|
||||||
struct reserve_info *next;
|
struct reserve_info *next;
|
||||||
|
|
||||||
char *label;
|
struct label *labels;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len, char *label);
|
struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len);
|
||||||
struct reserve_info *chain_reserve_entry(struct reserve_info *first,
|
struct reserve_info *chain_reserve_entry(struct reserve_info *first,
|
||||||
struct reserve_info *list);
|
struct reserve_info *list);
|
||||||
struct reserve_info *add_reserve_entry(struct reserve_info *list,
|
struct reserve_info *add_reserve_entry(struct reserve_info *list,
|
||||||
|
|
57
flattree.c
57
flattree.c
|
@ -52,9 +52,9 @@ struct emitter {
|
||||||
void (*string)(void *, char *, int);
|
void (*string)(void *, char *, int);
|
||||||
void (*align)(void *, int);
|
void (*align)(void *, int);
|
||||||
void (*data)(void *, struct data);
|
void (*data)(void *, struct data);
|
||||||
void (*beginnode)(void *, const char *);
|
void (*beginnode)(void *, struct label *labels);
|
||||||
void (*endnode)(void *, const char *);
|
void (*endnode)(void *, struct label *labels);
|
||||||
void (*property)(void *, const char *);
|
void (*property)(void *, struct label *labels);
|
||||||
};
|
};
|
||||||
|
|
||||||
static void bin_emit_cell(void *e, cell_t val)
|
static void bin_emit_cell(void *e, cell_t val)
|
||||||
|
@ -89,17 +89,17 @@ static void bin_emit_data(void *e, struct data d)
|
||||||
*dtbuf = data_append_data(*dtbuf, d.val, d.len);
|
*dtbuf = data_append_data(*dtbuf, d.val, d.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bin_emit_beginnode(void *e, const char *label)
|
static void bin_emit_beginnode(void *e, struct label *labels)
|
||||||
{
|
{
|
||||||
bin_emit_cell(e, FDT_BEGIN_NODE);
|
bin_emit_cell(e, FDT_BEGIN_NODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bin_emit_endnode(void *e, const char *label)
|
static void bin_emit_endnode(void *e, struct label *labels)
|
||||||
{
|
{
|
||||||
bin_emit_cell(e, FDT_END_NODE);
|
bin_emit_cell(e, FDT_END_NODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bin_emit_property(void *e, const char *label)
|
static void bin_emit_property(void *e, struct label *labels)
|
||||||
{
|
{
|
||||||
bin_emit_cell(e, FDT_PROP);
|
bin_emit_cell(e, FDT_PROP);
|
||||||
}
|
}
|
||||||
|
@ -191,37 +191,40 @@ static void asm_emit_data(void *e, struct data d)
|
||||||
assert(off == d.len);
|
assert(off == d.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_emit_beginnode(void *e, const char *label)
|
static void asm_emit_beginnode(void *e, struct label *labels)
|
||||||
{
|
{
|
||||||
FILE *f = e;
|
FILE *f = e;
|
||||||
|
struct label *l;
|
||||||
|
|
||||||
if (label) {
|
for_each_label(labels, l) {
|
||||||
fprintf(f, "\t.globl\t%s\n", label);
|
fprintf(f, "\t.globl\t%s\n", l->label);
|
||||||
fprintf(f, "%s:\n", label);
|
fprintf(f, "%s:\n", l->label);
|
||||||
}
|
}
|
||||||
fprintf(f, "\t/* FDT_BEGIN_NODE */\n");
|
fprintf(f, "\t/* FDT_BEGIN_NODE */\n");
|
||||||
asm_emit_cell(e, FDT_BEGIN_NODE);
|
asm_emit_cell(e, FDT_BEGIN_NODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_emit_endnode(void *e, const char *label)
|
static void asm_emit_endnode(void *e, struct label *labels)
|
||||||
{
|
{
|
||||||
FILE *f = e;
|
FILE *f = e;
|
||||||
|
struct label *l;
|
||||||
|
|
||||||
fprintf(f, "\t/* FDT_END_NODE */\n");
|
fprintf(f, "\t/* FDT_END_NODE */\n");
|
||||||
asm_emit_cell(e, FDT_END_NODE);
|
asm_emit_cell(e, FDT_END_NODE);
|
||||||
if (label) {
|
for_each_label(labels, l) {
|
||||||
fprintf(f, "\t.globl\t%s_end\n", label);
|
fprintf(f, "\t.globl\t%s_end\n", l->label);
|
||||||
fprintf(f, "%s_end:\n", label);
|
fprintf(f, "%s_end:\n", l->label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_emit_property(void *e, const char *label)
|
static void asm_emit_property(void *e, struct label *labels)
|
||||||
{
|
{
|
||||||
FILE *f = e;
|
FILE *f = e;
|
||||||
|
struct label *l;
|
||||||
|
|
||||||
if (label) {
|
for_each_label(labels, l) {
|
||||||
fprintf(f, "\t.globl\t%s\n", label);
|
fprintf(f, "\t.globl\t%s\n", l->label);
|
||||||
fprintf(f, "%s:\n", label);
|
fprintf(f, "%s:\n", l->label);
|
||||||
}
|
}
|
||||||
fprintf(f, "\t/* FDT_PROP */\n");
|
fprintf(f, "\t/* FDT_PROP */\n");
|
||||||
asm_emit_cell(e, FDT_PROP);
|
asm_emit_cell(e, FDT_PROP);
|
||||||
|
@ -260,7 +263,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
|
||||||
struct node *child;
|
struct node *child;
|
||||||
int seen_name_prop = 0;
|
int seen_name_prop = 0;
|
||||||
|
|
||||||
emit->beginnode(etarget, tree->label);
|
emit->beginnode(etarget, tree->labels);
|
||||||
|
|
||||||
if (vi->flags & FTF_FULLPATH)
|
if (vi->flags & FTF_FULLPATH)
|
||||||
emit->string(etarget, tree->fullpath, 0);
|
emit->string(etarget, tree->fullpath, 0);
|
||||||
|
@ -277,7 +280,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
|
||||||
|
|
||||||
nameoff = stringtable_insert(strbuf, prop->name);
|
nameoff = stringtable_insert(strbuf, prop->name);
|
||||||
|
|
||||||
emit->property(etarget, prop->label);
|
emit->property(etarget, prop->labels);
|
||||||
emit->cell(etarget, prop->val.len);
|
emit->cell(etarget, prop->val.len);
|
||||||
emit->cell(etarget, nameoff);
|
emit->cell(etarget, nameoff);
|
||||||
|
|
||||||
|
@ -304,7 +307,7 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
|
||||||
flatten_tree(child, emit, etarget, strbuf, vi);
|
flatten_tree(child, emit, etarget, strbuf, vi);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit->endnode(etarget, tree->label);
|
emit->endnode(etarget, tree->labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct data flatten_reserve_list(struct reserve_info *reservelist,
|
static struct data flatten_reserve_list(struct reserve_info *reservelist,
|
||||||
|
@ -525,9 +528,11 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
|
||||||
* as it appears .quad isn't available in some assemblers.
|
* as it appears .quad isn't available in some assemblers.
|
||||||
*/
|
*/
|
||||||
for (re = bi->reservelist; re; re = re->next) {
|
for (re = bi->reservelist; re; re = re->next) {
|
||||||
if (re->label) {
|
struct label *l;
|
||||||
fprintf(f, "\t.globl\t%s\n", re->label);
|
|
||||||
fprintf(f, "%s:\n", re->label);
|
for_each_label(re->labels, l) {
|
||||||
|
fprintf(f, "\t.globl\t%s\n", l->label);
|
||||||
|
fprintf(f, "%s:\n", l->label);
|
||||||
}
|
}
|
||||||
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32));
|
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32));
|
||||||
ASM_EMIT_BELONG(f, "0x%08x",
|
ASM_EMIT_BELONG(f, "0x%08x",
|
||||||
|
@ -684,7 +689,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf,
|
||||||
|
|
||||||
val = flat_read_data(dtbuf, proplen);
|
val = flat_read_data(dtbuf, proplen);
|
||||||
|
|
||||||
return build_property(name, val, NULL);
|
return build_property(name, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -709,7 +714,7 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
|
||||||
if (re.size == 0)
|
if (re.size == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
new = build_reserve_entry(re.address, re.size, NULL);
|
new = build_reserve_entry(re.address, re.size);
|
||||||
reservelist = add_reserve_entry(reservelist, new);
|
reservelist = add_reserve_entry(reservelist, new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
8
fstree.c
8
fstree.c
|
@ -60,8 +60,7 @@ static struct node *read_fstree(const char *dirname)
|
||||||
} else {
|
} else {
|
||||||
prop = build_property(xstrdup(de->d_name),
|
prop = build_property(xstrdup(de->d_name),
|
||||||
data_copy_file(pfile,
|
data_copy_file(pfile,
|
||||||
st.st_size),
|
st.st_size));
|
||||||
NULL);
|
|
||||||
add_property(tree, prop);
|
add_property(tree, prop);
|
||||||
fclose(pfile);
|
fclose(pfile);
|
||||||
}
|
}
|
||||||
|
@ -69,8 +68,7 @@ static struct node *read_fstree(const char *dirname)
|
||||||
struct node *newchild;
|
struct node *newchild;
|
||||||
|
|
||||||
newchild = read_fstree(tmpnam);
|
newchild = read_fstree(tmpnam);
|
||||||
newchild = name_node(newchild, xstrdup(de->d_name),
|
newchild = name_node(newchild, xstrdup(de->d_name));
|
||||||
NULL);
|
|
||||||
add_child(tree, newchild);
|
add_child(tree, newchild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +83,7 @@ struct boot_info *dt_from_fs(const char *dirname)
|
||||||
struct node *tree;
|
struct node *tree;
|
||||||
|
|
||||||
tree = read_fstree(dirname);
|
tree = read_fstree(dirname);
|
||||||
tree = name_node(tree, "", NULL);
|
tree = name_node(tree, "");
|
||||||
|
|
||||||
return build_boot_info(NULL, tree, guess_boot_cpuid(tree));
|
return build_boot_info(NULL, tree, guess_boot_cpuid(tree));
|
||||||
}
|
}
|
||||||
|
|
45
livetree.c
45
livetree.c
|
@ -24,17 +24,24 @@
|
||||||
* Tree building functions
|
* Tree building functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct property *build_property(char *name, struct data val, char *label)
|
void add_label(struct label **labels, char *label)
|
||||||
|
{
|
||||||
|
struct label *new = xmalloc(sizeof(*new));
|
||||||
|
|
||||||
|
new->label = label;
|
||||||
|
new->next = *labels;
|
||||||
|
*labels = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct property *build_property(char *name, struct data val)
|
||||||
{
|
{
|
||||||
struct property *new = xmalloc(sizeof(*new));
|
struct property *new = xmalloc(sizeof(*new));
|
||||||
|
|
||||||
|
memset(new, 0, sizeof(*new));
|
||||||
|
|
||||||
new->name = name;
|
new->name = name;
|
||||||
new->val = val;
|
new->val = val;
|
||||||
|
|
||||||
new->next = NULL;
|
|
||||||
|
|
||||||
new->label = label;
|
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,14 +85,12 @@ struct node *build_node(struct property *proplist, struct node *children)
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node *name_node(struct node *node, char *name, char * label)
|
struct node *name_node(struct node *node, char *name)
|
||||||
{
|
{
|
||||||
assert(node->name == NULL);
|
assert(node->name == NULL);
|
||||||
|
|
||||||
node->name = name;
|
node->name = name;
|
||||||
|
|
||||||
node->label = label;
|
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,18 +129,15 @@ void add_child(struct node *parent, struct node *child)
|
||||||
*p = child;
|
*p = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size,
|
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
|
||||||
char *label)
|
|
||||||
{
|
{
|
||||||
struct reserve_info *new = xmalloc(sizeof(*new));
|
struct reserve_info *new = xmalloc(sizeof(*new));
|
||||||
|
|
||||||
|
memset(new, 0, sizeof(*new));
|
||||||
|
|
||||||
new->re.address = address;
|
new->re.address = address;
|
||||||
new->re.size = size;
|
new->re.size = size;
|
||||||
|
|
||||||
new->next = NULL;
|
|
||||||
|
|
||||||
new->label = label;
|
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +219,10 @@ struct property *get_property_by_label(struct node *tree, const char *label,
|
||||||
*node = tree;
|
*node = tree;
|
||||||
|
|
||||||
for_each_property(tree, prop) {
|
for_each_property(tree, prop) {
|
||||||
if (prop->label && streq(prop->label, label))
|
struct label *l;
|
||||||
|
|
||||||
|
for_each_label(prop->labels, l)
|
||||||
|
if (streq(l->label, label))
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,10 +301,12 @@ struct node *get_node_by_path(struct node *tree, const char *path)
|
||||||
struct node *get_node_by_label(struct node *tree, const char *label)
|
struct node *get_node_by_label(struct node *tree, const char *label)
|
||||||
{
|
{
|
||||||
struct node *child, *node;
|
struct node *child, *node;
|
||||||
|
struct label *l;
|
||||||
|
|
||||||
assert(label && (strlen(label) > 0));
|
assert(label && (strlen(label) > 0));
|
||||||
|
|
||||||
if (tree->label && streq(tree->label, label))
|
for_each_label(tree->labels, l)
|
||||||
|
if (streq(l->label, label))
|
||||||
return tree;
|
return tree;
|
||||||
|
|
||||||
for_each_child(tree, child) {
|
for_each_child(tree, child) {
|
||||||
|
@ -353,15 +360,13 @@ cell_t get_node_phandle(struct node *root, struct node *node)
|
||||||
&& (phandle_format & PHANDLE_LEGACY))
|
&& (phandle_format & PHANDLE_LEGACY))
|
||||||
add_property(node,
|
add_property(node,
|
||||||
build_property("linux,phandle",
|
build_property("linux,phandle",
|
||||||
data_append_cell(empty_data, phandle),
|
data_append_cell(empty_data, phandle)));
|
||||||
NULL));
|
|
||||||
|
|
||||||
if (!get_property(node, "phandle")
|
if (!get_property(node, "phandle")
|
||||||
&& (phandle_format & PHANDLE_EPAPR))
|
&& (phandle_format & PHANDLE_EPAPR))
|
||||||
add_property(node,
|
add_property(node,
|
||||||
build_property("phandle",
|
build_property("phandle",
|
||||||
data_append_cell(empty_data, phandle),
|
data_append_cell(empty_data, phandle)));
|
||||||
NULL));
|
|
||||||
|
|
||||||
/* If the node *does* have a phandle property, we must
|
/* If the node *does* have a phandle property, we must
|
||||||
* be dealing with a self-referencing phandle, which will be
|
* be dealing with a self-referencing phandle, which will be
|
||||||
|
|
38
tests/multilabel.dts
Normal file
38
tests/multilabel.dts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
m1: mq: /memreserve/ 0 0x1000;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
p1: px: prop = "foo";
|
||||||
|
|
||||||
|
/* Explicit phandles */
|
||||||
|
n1: nx: node1 {
|
||||||
|
linux,phandle = <0x2000>;
|
||||||
|
ref = <&{/node2}>; /* reference precedes target */
|
||||||
|
lref = <&ny>;
|
||||||
|
};
|
||||||
|
ny: n2: node2 {
|
||||||
|
phandle = <0x1>;
|
||||||
|
ref = <&{/node1}>; /* reference after target */
|
||||||
|
lref = <&nx>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Implicit phandles */
|
||||||
|
n3: node3 {
|
||||||
|
ref = <&{/node4}>;
|
||||||
|
lref = <&n4>;
|
||||||
|
};
|
||||||
|
n4: node4 {
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Explicit phandle with implicit value */
|
||||||
|
/* This self-reference is the standard way to tag a node as requiring
|
||||||
|
* a phandle (perhaps for reference by nodes that will be dynamically
|
||||||
|
* added) without explicitly allocating it a phandle.
|
||||||
|
* The self-reference requires some special internal handling, though
|
||||||
|
* so check it actually works */
|
||||||
|
n5: nz: node5 {
|
||||||
|
linux,phandle = <&n5>;
|
||||||
|
phandle = <&nz>;
|
||||||
|
};
|
||||||
|
};
|
|
@ -221,6 +221,9 @@ dtc_tests () {
|
||||||
run_test phandle_format dtc_references.test.$f.dtb $f
|
run_test phandle_format dtc_references.test.$f.dtb $f
|
||||||
done
|
done
|
||||||
|
|
||||||
|
run_dtc_test -I dts -O dtb -o multilabel.test.dtb multilabel.dts
|
||||||
|
run_test references multilabel.test.dtb
|
||||||
|
|
||||||
run_dtc_test -I dts -O dtb -o dtc_comments.test.dtb comments.dts
|
run_dtc_test -I dts -O dtb -o dtc_comments.test.dtb comments.dts
|
||||||
run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts
|
run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts
|
||||||
run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb
|
run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb
|
||||||
|
|
15
treesource.c
15
treesource.c
|
@ -235,10 +235,11 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level)
|
||||||
{
|
{
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
struct node *child;
|
struct node *child;
|
||||||
|
struct label *l;
|
||||||
|
|
||||||
write_prefix(f, level);
|
write_prefix(f, level);
|
||||||
if (tree->label)
|
for_each_label(tree->labels, l)
|
||||||
fprintf(f, "%s: ", tree->label);
|
fprintf(f, "%s: ", l->label);
|
||||||
if (tree->name && (*tree->name))
|
if (tree->name && (*tree->name))
|
||||||
fprintf(f, "%s {\n", tree->name);
|
fprintf(f, "%s {\n", tree->name);
|
||||||
else
|
else
|
||||||
|
@ -246,8 +247,8 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level)
|
||||||
|
|
||||||
for_each_property(tree, prop) {
|
for_each_property(tree, prop) {
|
||||||
write_prefix(f, level+1);
|
write_prefix(f, level+1);
|
||||||
if (prop->label)
|
for_each_label(prop->labels, l)
|
||||||
fprintf(f, "%s: ", prop->label);
|
fprintf(f, "%s: ", l->label);
|
||||||
fprintf(f, "%s", prop->name);
|
fprintf(f, "%s", prop->name);
|
||||||
write_propval(f, prop);
|
write_propval(f, prop);
|
||||||
}
|
}
|
||||||
|
@ -267,8 +268,10 @@ void dt_to_source(FILE *f, struct boot_info *bi)
|
||||||
fprintf(f, "/dts-v1/;\n\n");
|
fprintf(f, "/dts-v1/;\n\n");
|
||||||
|
|
||||||
for (re = bi->reservelist; re; re = re->next) {
|
for (re = bi->reservelist; re; re = re->next) {
|
||||||
if (re->label)
|
struct label *l;
|
||||||
fprintf(f, "%s: ", re->label);
|
|
||||||
|
for_each_label(re->labels, l)
|
||||||
|
fprintf(f, "%s: ", l->label);
|
||||||
fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
|
fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
|
||||||
(unsigned long long)re->re.address,
|
(unsigned long long)re->re.address,
|
||||||
(unsigned long long)re->re.size);
|
(unsigned long long)re->re.size);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue