Since introduction of OF_UPSTREAM flag, U-Boot's dtc must be able
to compile Kernel's device tree.

Since kernel commit 7de129f5389b ("ARM: dts: stm32: stm32mp151a-prtt1l:
Fix QSPI configuration"), label relative path references has been
introduced. These label relative path references is not supported
by current U-Boot dtc version 1.5.0: (see mailing list discussion [1]).

In order to support such label relative patch references
adds following commit from upstream DTC tree:

commit 651410e54cb9 ("util: introduce xstrndup helper")
commit ec7986e682cf ("dtc: introduce label relative path references")

[1] https://lore.kernel.org/all/20250115144428.GZ3476@bill-the-cat/T/

Signed-off-by: Patrice Chotard <patrice.chot...@foss.st.com>
Cc: Tom Rini <tr...@konsulko.com>
Cc: Simon Glass <s...@chromium.org>
---

 scripts/dtc/dtc-lexer.l  |  2 +-
 scripts/dtc/dtc-parser.y | 13 +++++++++++++
 scripts/dtc/livetree.c   | 33 ++++++++++++++++++++++++++++++---
 scripts/dtc/util.c       | 11 +++++++++++
 scripts/dtc/util.h       |  1 +
 5 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
index d3694d6cf20..d34e1b04220 100644
--- a/scripts/dtc/dtc-lexer.l
+++ b/scripts/dtc/dtc-lexer.l
@@ -215,7 +215,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, 
...);
                        return DT_REF;
                }
 
-<*>"&{/"{PATHCHAR}*\}  {       /* new-style path reference */
+<*>"&{"{PATHCHAR}*\}   {       /* new-style path reference */
                        yytext[yyleng-1] = '\0';
                        DPRINT("Ref: %s\n", yytext+2);
                        yylval.labelref = xstrdup(yytext+2);
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
index 011a5b25539..b3b9c83873d 100644
--- a/scripts/dtc/dtc-parser.y
+++ b/scripts/dtc/dtc-parser.y
@@ -34,6 +34,12 @@ extern void yyerror(char const *s);
 
 extern struct dt_info *parser_output;
 extern bool treesource_error;
+
+static bool is_ref_relative(const char *ref)
+{
+       return ref[0] != '/' && strchr(&ref[1], '/');
+}
+
 %}
 
 %union {
@@ -176,12 +182,17 @@ devicetree:
                         */
                        if (!($<flags>-1 & DTSF_PLUGIN))
                                ERROR(&@2, "Label or path %s not found", $1);
+                       else if (is_ref_relative($1))
+                               ERROR(&@2, "Label-relative reference %s not 
supported in plugin", $1);
                        $$ = add_orphan_node(name_node(build_node(NULL, NULL), 
""), $2, $1);
                }
        | devicetree DT_LABEL DT_REF nodedef
                {
                        struct node *target = get_node_by_ref($1, $3);
 
+                       if (($<flags>-1 & DTSF_PLUGIN) && is_ref_relative($3))
+                               ERROR(&@2, "Label-relative reference %s not 
supported in plugin", $3);
+
                        if (target) {
                                add_label(&target->labels, $2);
                                merge_nodes(target, $4);
@@ -197,6 +208,8 @@ devicetree:
                         * so $-1 is what we want (plugindecl)
                         */
                        if ($<flags>-1 & DTSF_PLUGIN) {
+                               if (is_ref_relative($2))
+                                       ERROR(&@2, "Label-relative reference %s 
not supported in plugin", $2);
                                add_orphan_node($1, $3, $2);
                        } else {
                                struct node *target = get_node_by_ref($1, $2);
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
index ba06ef348be..4cfc2adccdd 100644
--- a/scripts/dtc/livetree.c
+++ b/scripts/dtc/livetree.c
@@ -583,12 +583,39 @@ struct node *get_node_by_phandle(struct node *tree, 
cell_t phandle)
 
 struct node *get_node_by_ref(struct node *tree, const char *ref)
 {
+       struct node *target = tree;
+       const char *label = NULL, *path = NULL;
+
        if (streq(ref, "/"))
                return tree;
-       else if (ref[0] == '/')
-               return get_node_by_path(tree, ref);
+
+       if (ref[0] == '/')
+               path = ref;
        else
-               return get_node_by_label(tree, ref);
+               label = ref;
+
+       if (label) {
+               const char *slash = strchr(label, '/');
+               char *buf = NULL;
+
+               if (slash) {
+                       buf = xstrndup(label, slash - label);
+                       label = buf;
+                       path = slash + 1;
+               }
+
+               target = get_node_by_label(tree, label);
+
+               free(buf);
+
+               if (!target)
+                       return NULL;
+       }
+
+       if (path)
+               target = get_node_by_path(target, path);
+
+       return target;
 }
 
 cell_t get_node_phandle(struct node *root, struct node *node)
diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
index 23334d39bb6..25d4db1e8c2 100644
--- a/scripts/dtc/util.c
+++ b/scripts/dtc/util.c
@@ -46,6 +46,17 @@ char *xstrdup(const char *s)
        return d;
 }
 
+char *xstrndup(const char *s, size_t n)
+{
+       size_t len = strnlen(s, n) + 1;
+       char *d = xmalloc(len);
+
+       memcpy(d, s, len - 1);
+       d[len - 1] = '\0';
+
+       return d;
+}
+
 /* based in part from (3) vsnprintf */
 int xasprintf(char **strp, const char *fmt, ...)
 {
diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h
index 211d584435d..23e32962385 100644
--- a/scripts/dtc/util.h
+++ b/scripts/dtc/util.h
@@ -70,6 +70,7 @@ static inline void *xrealloc(void *p, size_t len)
 }
 
 extern char *xstrdup(const char *s);
+extern char *xstrndup(const char *s, size_t len);
 
 extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
 extern char *join_path(const char *path, const char *name);
-- 
2.25.1

Reply via email to