[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <aWiQ05zlfPfcIaZk@zatzit>
Date: Thu, 15 Jan 2026 18:01:39 +1100
From: David Gibson <david@...son.dropbear.id.au>
To: Herve Codina <herve.codina@...tlin.com>
Cc: Rob Herring <robh@...nel.org>, Krzysztof Kozlowski <krzk@...nel.org>,
Conor Dooley <conor+dt@...nel.org>,
Ayush Singh <ayush@...gleboard.org>,
Geert Uytterhoeven <geert@...ux-m68k.org>,
devicetree-compiler@...r.kernel.org, devicetree@...r.kernel.org,
linux-kernel@...r.kernel.org, devicetree-spec@...r.kernel.org,
Hui Pu <hui.pu@...ealthcare.com>,
Ian Ray <ian.ray@...ealthcare.com>,
Luca Ceresoli <luca.ceresoli@...tlin.com>,
Thomas Petazzoni <thomas.petazzoni@...tlin.com>
Subject: Re: [RFC PATCH 64/77] dtc: Add support for references by path
involving orphan nodes
On Mon, Jan 12, 2026 at 03:19:54PM +0100, Herve Codina wrote:
> Referencing a sub-node from an orphan node using a path is needed.
>
> Indeed, using the following snippet:
> --- 8< ---
> /addon/;
>
> &node1 {
> subnode {
> foo-phandle = <&foo_label>;
> };
> };
>
> &node2 {
> foo_label: foo {
> prop = <1>;
> };
> };
> --- 8< ---
>
> Even if node2 is an orphan node, foo is a local node. foo-phandle
> references the foo node using a label.
Another option would be to eliminate the idea of local references, and
require a symbol be attached to things that you want to reference by
label.
>
> Once converted to a dtb, the label is lost. Only the phandle of the foo
> node is used in the foo-phandle property and this property is marked
> FDT_REF_LOCAL.
>
> Converting back this dtb to a dts, the marked local phandle should be
> translated to a path to the related local node.
>
> The issue is that this local node is not in a root device tree. We need
> to identify the orphan node the foo node belongs to.
>
> We cannot use a path starting by '/'. This kind of path identify node in
> the root tree.
>
> This new syntax allows to identify the orphan node in a path:
> $<orphan_name>/<path>
>
> This leads to a reference by path in the form &{$<orphan_name>/<path>}.
>
> Using the previous example, those both phandles points to the same node:
> foo-phandle1 = <&foo_label>; /* Reference by label */
> foo-phandle2 = <&{$node2/foo}>; /* Reference by path */
>
> When the dtb is converted back to a dts, the marked local phandle
> involving subnode available from orphan nodes can be translated to a
> reference by path thanks to the new syntax.
>
> Add support for this &{$<orphan_name>/<path>} syntax to reference by
> path a local node from an orphan node.
>
> Signed-off-by: Herve Codina <herve.codina@...tlin.com>
> ---
> dtc-lexer.l | 7 +++++++
> dtc-parser.y | 19 +++++++++++++++++++
> dtc.c | 22 ++++++++++++++++++++--
> livetree.c | 14 +++++++++++++-
> treesource.c | 3 ++-
> 5 files changed, 61 insertions(+), 4 deletions(-)
>
> diff --git a/dtc-lexer.l b/dtc-lexer.l
> index cb616f9..540bfdf 100644
> --- a/dtc-lexer.l
> +++ b/dtc-lexer.l
> @@ -239,6 +239,13 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
> return DT_PATH_REF;
> }
>
> +<*>"&{\$"{LABEL}([/]{PATHCHAR}*)?\} { /* orphan path reference */
> + yytext[yyleng-1] = '\0';
> + DPRINT("Ref orphan path: %s\n", yytext+1);
> + yylval.labelref = xstrdup(yytext+2);
> + return DT_ORPHAN_PATH_REF;
> + }
> +
> <BYTESTRING>[0-9a-fA-F]{2} {
> yylval.byte = strtol(yytext, NULL, 16);
> DPRINT("Byte: %02x\n", (int)yylval.byte);
> diff --git a/dtc-parser.y b/dtc-parser.y
> index 7f8c294..9d619cd 100644
> --- a/dtc-parser.y
> +++ b/dtc-parser.y
> @@ -111,6 +111,7 @@ static struct node *parser_get_node_by_ref(struct node *dt, struct node *orphanl
> %token <labelref> DT_LABEL
> %token <labelref> DT_LABEL_REF
> %token <labelref> DT_PATH_REF
> +%token <labelref> DT_ORPHAN_PATH_REF
> %token DT_INCBIN
>
> %type <data> propdata
> @@ -589,6 +590,24 @@ arrayprefix:
> ERROR(&@2, "References are only allowed in "
> "arrays with 32-bit elements.");
>
> + $$.data = data_append_integer($1.data, val, $1.bits);
> + }
> + | arrayprefix DT_ORPHAN_PATH_REF
> + {
> + uint64_t val = ~0ULL >> (64 - $1.bits);
> +
> + if ($1.bits == 32) {
> + if (!(last_header_flags & DTSF_ADDON))
> + ERROR(&@2, "Orphan path reference %s supported only in addon", $2);
> +
> + $1.data = data_add_marker($1.data,
> + REF_PHANDLE,
> + $2);
> + } else {
> + ERROR(&@2, "References are only allowed in "
> + "arrays with 32-bit elements.");
> + }
> +
> $$.data = data_append_integer($1.data, val, $1.bits);
> }
> | arrayprefix DT_LABEL
> diff --git a/dtc.c b/dtc.c
> index 63725bf..72d85e4 100644
> --- a/dtc.c
> +++ b/dtc.c
> @@ -48,13 +48,31 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
> static void dti_fill_fullpaths(struct dt_info *dti)
> {
> struct node *orphan;
> + struct node *child;
>
> /* Fill fullpaths for the root node */
> if (dti->dt)
> fill_fullpaths(dti->dt, "");
>
> - for_each_orphan(dti->orphanlist, orphan)
> - fill_fullpaths(orphan, "__orphan__/");
> + /* Fill fullpaths for orphan nodes */
> + for_each_orphan(dti->orphanlist, orphan) {
> + if (orphan->name[0] == '\0')
> + die("orphan node has an empty name\n");
> +
> + /*
> + * An orphan node name is set with its reference.
> + * Its name is in the form "&xxxxxx".
> + * For its full path, we use "$xxxxx" to make a clear
> + * distinction between a reference (&xxxx) where a resolution
> + * could be involved vs a "simple" path where we just need to
> + * identified the orphan ($xxxx).
> + */
> + xasprintf(&orphan->fullpath, "$%s", orphan->name + 1);
> + orphan->basenamelen = strlen(orphan->name);
> +
> + for_each_child(orphan, child)
> + fill_fullpaths(child, orphan->fullpath);
> + }
> }
>
> /* Usage related data. */
> diff --git a/livetree.c b/livetree.c
> index 59b912d..263da1f 100644
> --- a/livetree.c
> +++ b/livetree.c
> @@ -804,7 +804,19 @@ static struct node *get_node_by_ref(struct node *tree, const char *ref)
> path = slash + 1;
> }
>
> - target = get_node_by_label(tree, label);
> + if (label[0] == '$' && tree->name[0] == '&') {
> + /*
> + * We search for an orphan and the given tree is an
> + * orphan. Use the given tree only if it matches the
> + * expected orphan.
> + */
> + if (streq(label + 1, tree->name + 1))
> + target = tree;
> + else
> + target = NULL;
> + } else {
> + target = get_node_by_label(tree, label);
> + }
>
> free(buf);
>
> diff --git a/treesource.c b/treesource.c
> index 71dbd5f..44de0db 100644
> --- a/treesource.c
> +++ b/treesource.c
> @@ -278,7 +278,8 @@ static void write_propval(FILE *f, struct property *prop)
> break;
>
> if (m_phandle) {
> - if (m_phandle->ref[0] == '/')
> + if (m_phandle->ref[0] == '/' /* Root node */ ||
> + m_phandle->ref[0] == '$' /* Orphan node */)
> fprintf(f, "&{%s}", m_phandle->ref);
> else
> fprintf(f, "&%s", m_phandle->ref);
> --
> 2.52.0
>
>
--
David Gibson (he or they) | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you, not the other way
| around.
http://www.ozlabs.org/~dgibson
Download attachment "signature.asc" of type "application/pgp-signature" (834 bytes)
Powered by blists - more mailing lists