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