lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260112142009.1006236-65-herve.codina@bootlin.com>
Date: Mon, 12 Jan 2026 15:19:54 +0100
From: Herve Codina <herve.codina@...tlin.com>
To: David Gibson <david@...son.dropbear.id.au>,
	Rob Herring <robh@...nel.org>,
	Krzysztof Kozlowski <krzk@...nel.org>,
	Conor Dooley <conor+dt@...nel.org>
Cc: 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>,
	Herve Codina <herve.codina@...tlin.com>
Subject: [RFC PATCH 64/77] dtc: Add support for references by path involving orphan nodes

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.

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


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ