[PATCH 4/4] Allow nodes at the root to be specified by path as well as by label.
John Bonesio
bones at secretlab.ca
Wed Nov 3 09:55:30 EST 2010
Changes to allow us to specify a node by it's path. A path can be used in
place of a label.
This is particularly useful when overriding existing nodes.
This way we don't have to label every possible node in a device tree we know
is a base device tree for a class of systems, and we know the tree will be
modified for the specific systems.
Signed-off-by: John Bonesio <bones at secretlab.ca>
---
dtc-lexer.l | 24 +++++++++++++++++++++++
dtc-parser.y | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
dtc.h | 2 ++
livetree.c | 48 +++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 133 insertions(+), 1 deletions(-)
diff --git a/dtc-lexer.l b/dtc-lexer.l
index 4b07236..087a51f 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -127,6 +127,23 @@ static int pop_input_file(void);
return DT_REF;
}
+<*>"&{"{LABEL}{PATHCHAR}*\} { /* label and/or path refererence with braces */
+ /*
+ * Possibly this could be parsed by the parser rather
+ * than as a lexical element.
+ *
+ * What is intended here is to support the following
+ * type of references:
+ * a) &{/path/to/the/node/reference}
+ * b) &{label}
+ * c) &{label/path/from/labeled/node/to/reference}
+ */
+ yytext[yyleng-1] = '\0';
+ DPRINT("Ref: %s\n", yytext+2);
+ yylval.labelref = xstrdup(yytext+2);
+ return DT_REF;
+ }
+
<*>"&{/"{PATHCHAR}+\} { /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
@@ -146,6 +163,13 @@ static int pop_input_file(void);
return ']';
}
+<PROPNODENAME>"aliases" {
+ DPRINT("Aliases: %s\n", yytext);
+ yylval.propnodename = xstrdup(yytext);
+ BEGIN_DEFAULT();
+ return DT_ALIASES;
+ }
+
<PROPNODENAME>{PROPNODECHAR}+ {
DPRINT("PropNodeName: %s\n", yytext);
yylval.propnodename = xstrdup(yytext);
diff --git a/dtc-parser.y b/dtc-parser.y
index 2a9736a..8718f07 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -60,6 +60,7 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
%token DT_REMOVENODE
%token <propnodename> DT_REMOVEPROP
%token <propnodename> DT_PROPNODENAME
+%token <propnodename> DT_ALIASES
%token <literal> DT_LITERAL
%token <cbase> DT_BASE
%token <byte> DT_BYTE
@@ -77,10 +78,13 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
%type <cell> cellval
%type <data> bytestring
%type <prop> propdef
+%type <prop> aliasespropdef
%type <proplist> proplist
+%type <proplist> aliasesproplist
%type <node> devicetree
%type <node> nodedef
+%type <node> aliasesnodedef
%type <node> subnode
%type <nodelist> subnodes
@@ -128,11 +132,33 @@ addr:
devicetree:
'/' nodedef
{
+ /*
+ * We need to wait until the whole tree is parsed so we
+ * can assign aliases as labels on forward reference
+ * nodes.
+ */
+ struct node *aliases_node = get_node_by_ref($2, "/aliases");
+
+ if (aliases_node) {
+ make_aliases_labels($2, aliases_node);
+ }
+
$$ = name_node($2, "");
}
| devicetree '/' nodedef
{
$$ = merge_nodes($1, $3);
+
+ /*
+ * We need to wait until the whole tree is parsed so we
+ * can assign aliases as labels on forward reference
+ * nodes.
+ */
+ struct node *aliases_node = get_node_by_ref($$, "/aliases");
+
+ if (aliases_node) {
+ make_aliases_labels($$, aliases_node);
+ }
}
| devicetree DT_REF nodedef
{
@@ -162,6 +188,13 @@ nodedef:
}
;
+aliasesnodedef:
+ '{' aliasesproplist '}' ';'
+ {
+ $$ = build_node($2, NULL);
+ }
+ ;
+
proplist:
/* empty */
{
@@ -173,6 +206,17 @@ proplist:
}
;
+aliasesproplist:
+ /* empty */
+ {
+ $$ = NULL;
+ }
+ | aliasesproplist aliasespropdef
+ {
+ $$ = chain_property($2, $1);
+ }
+ ;
+
propdef:
DT_PROPNODENAME '=' propdata ';'
{
@@ -195,6 +239,18 @@ propdef:
}
;
+aliasespropdef:
+ DT_PROPNODENAME '=' DT_REF ';'
+ {
+ struct data d = empty_data;
+
+ d = data_add_marker(d, REF_PATH, $3);
+ $$ = build_property($1, d);
+
+ strtbl_insert(&label_table, $1, srcpos_copy(&yylloc));
+ }
+ ;
+
propdata:
propdataprefix DT_STRING
{
@@ -323,6 +379,10 @@ subnode:
{
$$ = name_node($2, $1);
}
+ | DT_ALIASES aliasesnodedef
+ {
+ $$ = name_node($2, "aliases");
+ }
| DT_LABEL subnode
{
strtbl_insert(&label_table, $1, srcpos_copy(&yylloc));
diff --git a/dtc.h b/dtc.h
index 764b3a9..1c3632c 100644
--- a/dtc.h
+++ b/dtc.h
@@ -179,6 +179,8 @@ struct node *name_node(struct node *node, char *name);
struct node *chain_node(struct node *first, struct node *list);
struct node *merge_nodes(struct node *old_node, struct node *new_node);
+void make_aliases_labels(struct node *root, struct node *aliases);
+
void add_property(struct node *node, struct property *prop);
void remove_property(struct node *node, struct property *prop);
void add_child(struct node *parent, struct node *child);
diff --git a/livetree.c b/livetree.c
index f1b235c..357d762 100644
--- a/livetree.c
+++ b/livetree.c
@@ -473,8 +473,54 @@ struct node *get_node_by_ref(struct node *tree, const char *ref)
{
if (ref[0] == '/')
return get_node_by_path(tree, ref);
- else
+ else {
+ /*
+ * Support finding a node reference that is rooted by
+ * a label reference.
+ *
+ * References rooted by a label have a '/' in them.
+ */
+ char *ref_cpy = xstrdup(ref);
+ char *p = strchr(ref_cpy, '/');
+ struct node *node;
+
+ if (p) {
+ *p = '\0';
+ node = get_node_by_label(tree, ref_cpy);
+ *p = '/';
+ node = get_node_by_path(node, p+1);
+
+ free(ref_cpy);
+
+ return node;
+ }
+
return get_node_by_label(tree, ref);
+ }
+}
+
+void make_aliases_labels(struct node *root, struct node *aliases) {
+ struct property *prop;
+
+ for_each_property(aliases, prop) {
+ struct marker *m = prop->val.markers;
+ struct node *refnode;
+
+ for_each_marker_of_type(m, REF_PATH) {
+ refnode = get_node_by_ref(root, m->ref);
+ if (refnode)
+ /*
+ * Right here we might be insertting labels
+ * with illegal characters, but we won't be
+ * able to reference them in the dts file
+ * (sytnax error).
+ *
+ * We could possibly check for this and spit
+ * out a warning.
+ */
+ add_label(&refnode->labels, prop->name);
+ }
+ }
}
cell_t get_node_phandle(struct node *root, struct node *node)
More information about the devicetree-discuss
mailing list