From nobody Mon Sep 28 04:49:01 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 335DA3B71DB; Wed, 26 Aug 2026 08:32:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733158; cv=none; b=OtdXG9NzTi7BHrhNboGhkm3D8+SapdkviEXQTd2M9PId4r79gRvgjgMyxIXu8v3tp8QckqGKg32EAs33woPSVsd2DGt3o/XiCxpF+nPM7ONRG5Lua+N9xljWRL6wmiiBeGXqOmAMz0g+DeIIewqhHK/p8+srGrjU1fC3UYnLYUY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733158; c=relaxed/simple; bh=n2QIIBZjmbgnupjMVzE5oPOSGKv45iKI1Fovz/8xFxU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DcUjvhvEvm63ipZ7kKTtSt9sWUpNXW8SkjAitgPaMHPOlIrV9gNt9dR3dtPBYyd/WoD6cW3Pmc/JTbPHgL8g+lpl/6z1pcQl0H9igrz/xBOaCSzXEQfGethL9kITkbb1rTHdkaaqvOlFMf/I8ndconqPkstqcr/6aYCRwf6Uq1U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=yyFoxvW7; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="yyFoxvW7" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 7E3F71A183C; Wed, 26 Aug 2026 08:32:34 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 4FC8E604EC; Wed, 26 Aug 2026 08:32:34 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id B344C11C7AC4A; Wed, 26 Aug 2026 10:32:27 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1787733149; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=ijfJDCYjmaY3mHI9qGkrNyCnSe01wkhGYj63FXlvkY8=; b=yyFoxvW7Y+sFzLPJ39LN4/vqqyWGqjftk2Dva0MsKO7a7yI+xdGJ/lHTgDnhqJydKl5szz 3iojsG5tKCrzZbtC4Og6kj9xp61LMTGvQp0o2i7N6SjnO2IpAIU4ExXGyhlXWNJfM6fyRN c15O1qXC4g5jF9DHtFNpZwQ6G4uJ6I4cdjO7edh9e7QqnGslQSV8N4ubzTiI3FiLJEqQ1P rrsZzNN7Ldbjulu/xH23Bs9Rn2qWY6XRjxbVYcsplpYXObvK48v+8MrqcQNpBRBDT/aDWw CdpufzonS/vFOLUDAOFGIEMITCOqFfFzFknqMzRCfJhXcJ3+DAiNPdLv/7HdwQ== From: Herve Codina To: David Gibson , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Laurent Pinchart , David Lechner , Ayush Singh , Geert Uytterhoeven , devicetree-compiler@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree-spec@vger.kernel.org, Hui Pu , Ian Ray , Luca Ceresoli , Thomas Petazzoni , Herve Codina Subject: [PATCH v3 01/15] fdtget: Use libfdt iterators instead of open coded loops Date: Wed, 26 Aug 2026 10:31:32 +0200 Message-ID: <20260826083146.304291-2-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826083146.304291-1-herve.codina@bootlin.com> References: <20260826083146.304291-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" fdtget uses directly fdt_{first,next}_property_offset() with a while(1) loop to iterate over node properties. It also uses the low level primitive fdt_next_tag() with custom tags, level and depth handling to iterates over subnodes. It is worth noting that FDT_NOP can be returned by fdt_next_tag() and this tag is not taken into account in the fdtget open coded loop. This will lead to an incorrect error if a FDT_NOP tag is encountered. libfdt provides iterators to iterate over node properties and subnodes. The subnode iterator provided by libfdt is robust against FDT_NOP tags and will be robust in the future when new tags are introduced. Replace fdtget open coded loops by iterators provided by libfdt and designed to perform those operations. Signed-off-by: Herve Codina --- fdtget.c | 73 ++++++++++++++++++-------------------------------------- 1 file changed, 23 insertions(+), 50 deletions(-) diff --git a/fdtget.c b/fdtget.c index dd709854..c6169691 100644 --- a/fdtget.c +++ b/fdtget.c @@ -138,21 +138,20 @@ static int show_data(struct display_info *disp, const= char *data, int len) static int list_properties(const void *blob, int node) { const char *name; + const void *p; int prop; =20 - prop =3D fdt_first_property_offset(blob, node); - do { - /* Stop silently when there are no more properties */ - if (prop < 0) - return prop =3D=3D -FDT_ERR_NOTFOUND ? 0 : prop; - fdt_getprop_by_offset(blob, prop, &name, NULL); - if (name) + fdt_for_each_property_offset(prop, blob, node) { + p =3D fdt_getprop_by_offset(blob, prop, &name, NULL); + if (p && name) puts(name); - prop =3D fdt_next_property_offset(blob, prop); - } while (1); -} + } =20 -#define MAX_LEVEL 32 /* how deeply nested we will go */ + if ((prop < 0) && (prop !=3D -FDT_ERR_NOTFOUND)) + return prop; + + return 0; +} =20 /** * List all subnodes in a node, one per line @@ -163,47 +162,21 @@ static int list_properties(const void *blob, int node) */ static int list_subnodes(const void *blob, int node) { - int nextoffset; /* next node offset from libfdt */ - uint32_t tag; /* current tag */ - int level =3D 0; /* keep track of nesting level */ const char *pathp; - int depth =3D 1; /* the assumed depth of this node */ - - while (level >=3D 0) { - tag =3D fdt_next_tag(blob, node, &nextoffset); - switch (tag) { - case FDT_BEGIN_NODE: - pathp =3D fdt_get_name(blob, node, NULL); - if (level <=3D depth) { - if (pathp =3D=3D NULL) - pathp =3D "/* NULL pointer error */"; - if (*pathp =3D=3D '\0') - pathp =3D "/"; /* root is nameless */ - if (level =3D=3D 1) - puts(pathp); - } - level++; - if (level >=3D MAX_LEVEL) { - printf("Nested too deep, aborting.\n"); - return 1; - } - break; - case FDT_END_NODE: - level--; - if (level =3D=3D 0) - level =3D -1; /* exit the loop */ - break; - case FDT_END: - return 1; - case FDT_PROP: - break; - default: - if (level <=3D depth) - printf("Unknown tag 0x%08X\n", tag); - return 1; - } - node =3D nextoffset; + int subnode; + + fdt_for_each_subnode(subnode, blob, node) { + pathp =3D fdt_get_name(blob, subnode, NULL); + if (pathp =3D=3D NULL) + pathp =3D "/* NULL pointer error */"; + if (*pathp =3D=3D '\0') + pathp =3D "/"; /* root is nameless */ + puts(pathp); } + + if (subnode < 0 && (subnode !=3D -FDT_ERR_NOTFOUND)) + return subnode; + return 0; } =20 --=20 2.55.0 From nobody Mon Sep 28 04:49:01 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8078B3B71B8; Wed, 26 Aug 2026 08:32:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733165; cv=none; b=O+1rQ8xehUDplMWmr5NcV+cW+55L6w7h6+xA/43E2jUWvv2+b5mIa264OO6rprqWP+6p4O1+0OHjGsjtg2rkquc9v1X4CCrWsoBqImeIl6E5ZiLD9aZVh6peD/piA7qj1+NvsURMmmZHvZXgUleIBLgIfHy7yAZCa8EWdIUqIpQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733165; c=relaxed/simple; bh=0Ef+lXz7IkIPu46bk8IFoiO7dhr/2JMnSVJ4jZIoLls=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Tr9Jq9gGmbYzP5oWdM3e5IxRnwaY09qBl/y9OM8bMk0gkn97ynir2xWPJT5+y2l2PYwjycMTkgoztRsemUABH8iB369pNl/36XmSHLFPq7TASfahW1ZsAfFXv7OHZhDoF+PKi4wab+FaSvuJQ9uAkd076oxVyTzGUlXgnki33Jk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=FhRn+df8; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="FhRn+df8" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id C0DB91A183F; Wed, 26 Aug 2026 08:32:41 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 8DDFC604EC; Wed, 26 Aug 2026 08:32:41 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id AC4F711C7AC7C; Wed, 26 Aug 2026 10:32:33 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1787733156; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=z47qAnB4rUFVZ7n66ZHWLESpHAxKpy2FC2IRGf+1VRU=; b=FhRn+df8m62N4RNNxbtEkF05qgDYqgghzuQbmYJUnGJVNUv5cpjFx3M+CRZ3LY/l4/v1i5 oxcUTJoJnHiTa8avAqMXcwu3/3OqjPRQGZg/TUSr8xBAJTRfqGtO32yAZ4r1cQAOgDDHBJ 1BiwISvDtrpiYJWh/8+yeTVKudqdnAtCBwPwnTMjo2uZN1J4R/Hn4GrvJMTQFGQLeY+/6h VfQWyHqbrsUEwzbehd1//R/s34qY9dhTXvnAwyKIwvnJo0TcdfJEKEHCKlXHr7K2XsxGIr E2XsazqOkRfFFWkhipexCJ8Q8GyA6I1jSy0peV83Ek5xYXf9JPgYlHxbMpwDCQ== From: Herve Codina To: David Gibson , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Laurent Pinchart , David Lechner , Ayush Singh , Geert Uytterhoeven , devicetree-compiler@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree-spec@vger.kernel.org, Hui Pu , Ian Ray , Luca Ceresoli , Thomas Petazzoni , Herve Codina , Frank Li Subject: [PATCH v3 02/15] libfdt: Don't assume the root node is available at offset 0 Date: Wed, 26 Aug 2026 10:31:33 +0200 Message-ID: <20260826083146.304291-3-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826083146.304291-1-herve.codina@bootlin.com> References: <20260826083146.304291-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 In several places, libfdt assumes that the root offset (i.e. the first FDT_BEGIN_NODE tag) is present at the offset 0 of the structure block. This assumption is not correct. A FDT_NOP can be present at the offset 0 and this is a legit case. Indeed, the device-tree specification [0] defines the FDT_NOP tag as follow: The FDT_NOP token will be ignored by any program parsing the device tree. This token has no extra data; so it is followed immediately by the next token, which can be any valid token. A property or node definition in the tree can be overwritten with FDT_NOP tokens to remove it from the tree without needing to move other sections of the tree=E2=80=99s representation in the devicetree blob. Nothing refers to any location for this tag and it has to be simply ignored. Having this tag at offset 0 doesn't make an exception, the tag has to be ignored. Introduce fdt_root_offset() in order to get the offset of the root node (first FDT_BEGIN_NODE tag) available in a fdt blob taking care of FDT_NOP tags. Use this function to get the root node offset instead of looking for this node at offset 0. [0] https://github.com/devicetree-org/devicetree-specification/blob/main/so= urce/chapter5-flattened-format.rst?plain=3D1#L317 Signed-off-by: Herve Codina Reviewed-by: Frank Li --- libfdt/fdt.c | 39 +++++++++++++++++++++++++++++-- libfdt/fdt_ro.c | 57 ++++++++++++++++++++++++++++++++++++++-------- libfdt/fdt_rw.c | 12 ++++++++++ libfdt/libfdt.h | 15 +++++++++++- libfdt/version.lds | 1 + 5 files changed, 111 insertions(+), 13 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 56d4dcb2..eb803e8a 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -252,13 +252,48 @@ int fdt_check_prop_offset_(const void *fdt, int offse= t) return offset; } =20 -int fdt_next_node(const void *fdt, int offset, int *depth) +int fdt_root_offset(const void *fdt) { int nextoffset =3D 0; + int offset; + uint32_t tag; + + do { + offset =3D nextoffset; + tag =3D fdt_next_tag(fdt, offset, &nextoffset); + switch (tag) { + case FDT_END_NODE: + case FDT_PROP: + return -FDT_ERR_BADSTRUCTURE; + + case FDT_BEGIN_NODE: + return offset; + + default: + break; + } + } while (tag !=3D FDT_END); + + return (nextoffset < 0) ? nextoffset : -FDT_ERR_NOTFOUND; +} + +int fdt_next_node(const void *fdt, int offset, int *depth) +{ + int nextoffset =3D offset; uint32_t tag; =20 + /* + * Get the root node if asked for next node from the root node + * (offset =3D=3D 0) or if the given offset is not valid (negative). + */ + if (offset <=3D 0) { + nextoffset =3D fdt_root_offset(fdt); + if (nextoffset < 0) + return nextoffset; + } + if (offset >=3D 0) - if ((nextoffset =3D fdt_check_node_offset_(fdt, offset)) < 0) + if ((nextoffset =3D fdt_check_node_offset_(fdt, nextoffset)) < 0) return nextoffset; =20 do { diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 11f2e2ee..856c62f1 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -231,6 +231,12 @@ int fdt_subnode_offset_namelen(const void *fdt, int of= fset, =20 FDT_RO_PROBE(fdt); =20 + if (!offset) { + offset =3D fdt_root_offset(fdt); + if (offset < 0) + return offset; + } + for (depth =3D 0; (offset >=3D 0) && (depth >=3D 0); offset =3D fdt_next_node(fdt, offset, &depth)) @@ -253,13 +259,17 @@ int fdt_path_offset_namelen(const void *fdt, const ch= ar *path, int namelen) { const char *end =3D path + namelen; const char *p =3D path; - int offset =3D 0; + int offset; =20 FDT_RO_PROBE(fdt); =20 if (!can_assume(VALID_INPUT) && namelen <=3D 0) return -FDT_ERR_BADPATH; =20 + offset =3D fdt_root_offset(fdt); + if (offset < 0) + return offset; + /* see if we have an alias */ if (*path !=3D '/') { const char *q =3D memchr(path, '/', end - p); @@ -304,14 +314,24 @@ int fdt_path_offset(const void *fdt, const char *path) =20 const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) { - const struct fdt_node_header *nh =3D fdt_offset_ptr_(fdt, nodeoffset); + const struct fdt_node_header *nh; const char *nameptr; int err; =20 + if (!nodeoffset) { + nodeoffset =3D fdt_root_offset(fdt); + if (nodeoffset < 0) { + err =3D nodeoffset; + goto fail; + } + } + + if (!can_assume(VALID_DTB) && (((err =3D fdt_ro_probe_(fdt)) < 0) || ((err =3D fdt_check_node_offset_(fdt, nodeoffset)) < 0))) goto fail; =20 + nh =3D fdt_offset_ptr_(fdt, nodeoffset); nameptr =3D nh->name; =20 if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { @@ -344,6 +364,12 @@ int fdt_first_property_offset(const void *fdt, int nod= eoffset) { int offset; =20 + if (!nodeoffset) { + nodeoffset =3D fdt_root_offset(fdt); + if (nodeoffset < 0) + return nodeoffset; + } + if ((offset =3D fdt_check_node_offset_(fdt, nodeoffset)) < 0) return offset; =20 @@ -581,7 +607,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char = *buf, int buflen) if (buflen < 2) return -FDT_ERR_NOSPACE; =20 - for (offset =3D 0, depth =3D 0; + for (offset =3D fdt_root_offset(fdt), depth =3D 0; (offset >=3D 0) && (offset <=3D nodeoffset); offset =3D fdt_next_node(fdt, offset, &depth)) { while (pdepth > depth) { @@ -619,7 +645,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char = *buf, int buflen) else if (offset =3D=3D -FDT_ERR_BADOFFSET) return -FDT_ERR_BADSTRUCTURE; =20 - return offset; /* error from fdt_next_node() */ + return offset; /* error from fdt_next_node() or fdt_root_offset() */ } =20 int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, @@ -627,13 +653,21 @@ int fdt_supernode_atdepth_offset(const void *fdt, int= nodeoffset, { int offset, depth; int supernodeoffset =3D -FDT_ERR_INTERNAL; + int root_offset; =20 FDT_RO_PROBE(fdt); =20 if (supernodedepth < 0) return -FDT_ERR_NOTFOUND; =20 - for (offset =3D 0, depth =3D 0; + root_offset =3D fdt_root_offset(fdt); + if (root_offset < 0) + return root_offset; + + if (!nodeoffset) + nodeoffset =3D root_offset; + + for (offset =3D root_offset, depth =3D 0; (offset >=3D 0) && (offset <=3D nodeoffset); offset =3D fdt_next_node(fdt, offset, &depth)) { if (depth =3D=3D supernodedepth) @@ -663,12 +697,15 @@ int fdt_supernode_atdepth_offset(const void *fdt, int= nodeoffset, int fdt_node_depth(const void *fdt, int nodeoffset) { int nodedepth; - int err; + int offset; + + offset =3D fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); + if (offset < 0) + return offset; + + if (!can_assume(LIBFDT_FLAWLESS) && offset !=3D fdt_root_offset(fdt)) + return -FDT_ERR_INTERNAL; =20 - err =3D fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); - if (err) - return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err : - -FDT_ERR_INTERNAL; return nodedepth; } =20 diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 850aafe4..ceef49b8 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -226,6 +226,12 @@ static int fdt_add_property_(void *fdt, int nodeoffset= , const char *name, int err; int allocated; =20 + if (!nodeoffset) { + nodeoffset =3D fdt_root_offset(fdt); + if (nodeoffset < 0) + return nodeoffset; + } + if ((nextoffset =3D fdt_check_node_offset_(fdt, nodeoffset)) < 0) return nextoffset; =20 @@ -377,6 +383,12 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffse= t, =20 FDT_RW_PROBE(fdt); =20 + if (!parentoffset) { + parentoffset =3D fdt_root_offset(fdt); + if (parentoffset < 0) + return parentoffset; + } + offset =3D fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); if (offset >=3D 0) return -FDT_ERR_EXISTS; diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index c69a18ed..7a1915a5 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -503,6 +503,19 @@ int fdt_num_mem_rsv(const void *fdt); */ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *s= ize); =20 +/** + * fdt_root_offset - Get the offset of the root node + * @fdt: pointer to the device tree blob + * + * The root node can be located after the offset 0. Indeed FDT_NOP tags ca= n be + * present at offset 0. fdt_root_offset() takes care of those possible FDT= _NOP + * tags. + * + * returns: offset of the root node or negative libfdt error value otherwi= se + */ +int fdt_root_offset(const void *fdt); + + /** * fdt_subnode_offset_namelen - find a subnode based on substring * @fdt: pointer to the device tree blob @@ -1025,7 +1038,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, cha= r *buf, int buflen); * at a specific depth from the root (where the root itself has depth * 0, its immediate subnodes depth 1 and so forth). So * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL); - * will always return 0, the offset of the root node. If the node at + * will always return the offset of the root node. If the node at * nodeoffset has depth D, then: * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL); * will return nodeoffset itself. diff --git a/libfdt/version.lds b/libfdt/version.lds index cbfef546..d0b71669 100644 --- a/libfdt/version.lds +++ b/libfdt/version.lds @@ -7,6 +7,7 @@ LIBFDT_1.2 { fdt_string; fdt_num_mem_rsv; fdt_get_mem_rsv; + fdt_root_offset; fdt_subnode_offset_namelen; fdt_subnode_offset; fdt_path_offset_namelen; --=20 2.55.0 From nobody Mon Sep 28 04:49:01 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 155E2385D78; Wed, 26 Aug 2026 08:32:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733166; cv=none; b=QKJkYrYewPkPIK/hx68sIGy1QXV3Iey7NJFiVKBLNbZLukjd+qcgJ1O9Z2vJu3csq/9QEPq94sxG/x3sqlz7Jl1/xA37M3qRBtkQJJugWhxGck/2+LkUUy87SGajVhe/G+dQO9pODak6GYuDfkOYyXTqwSl1iUI983OdRikCSBY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733166; c=relaxed/simple; bh=nqqpXaFq+Xv9lq7FzU3oUbvr1L5YIu+wbJC9mghIqW8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Z74NvNtsretafqwlwH8Du+aHo8wu1u4WBvFb1sbHkgSZSNi9MBabT0jFpR1kMxxXh0rkt3e/UtiquEDCSAZTakag1IO+eKpkpzKdnR8PploMdNZBqKO1j3nMyj25rVpNVqK87HJrP4yLbqkJVmgC1oco6lIQ5uka27KOCI1aj1U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=Jn7RZI/j; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="Jn7RZI/j" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id B345B1A1840; Wed, 26 Aug 2026 08:32:43 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 871E4604EC; Wed, 26 Aug 2026 08:32:43 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id E31E311C7AC5A; Wed, 26 Aug 2026 10:32:40 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1787733162; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=SqdDH62okKjLJ49j/IFlkhZUgbK4ajA4xDkkDNp6AJU=; b=Jn7RZI/j6B7SXS+77gx3H8Pwt7iuJvYGdLM7dEUMgdkJnHA0I/9qPX6Ks02Py2vgizRP2O uy/2GXrYf+XptbUHdQkUZdF2nanndHjMrB/b7bj2xfGr8p/QIVwT7UXFO6UmSx1sd3mgAq mOiaxKi04ejUQtb2LWFSLjtrSvZhWFuRlU/ndKrwrVC98or3DHsIWeSUZ6xKyDVoekARDo V5FHZQpfTOllaDsVeAQB/riTbOa3JuWQNU0F3RW+0fxgKzj9KGRTJbanV/iYuccn+uBwzV gfnoy3+FpQBoOJiOEV2j85vNg8gclPsWk2+a1aPJ4IEKk2xHbhNYt9Xr1Y7GQw== From: Herve Codina To: David Gibson , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Laurent Pinchart , David Lechner , Ayush Singh , Geert Uytterhoeven , devicetree-compiler@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree-spec@vger.kernel.org, Hui Pu , Ian Ray , Luca Ceresoli , Thomas Petazzoni , Herve Codina Subject: [PATCH v3 03/15] tests: Don't assume the root node is available at offset 0 Date: Wed, 26 Aug 2026 10:31:34 +0200 Message-ID: <20260826083146.304291-4-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826083146.304291-1-herve.codina@bootlin.com> References: <20260826083146.304291-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" Several tests uses offset 0 as the offset of the root node. Either to check the offset returned by tested functions or to directly manipulate the root node retrieved using fdt_offset_ptr(fdt, 0, ...). The root node is not always at offset 0. Indeed, a FDT_NOP tag can be present at offset 0. fdt_root_offset() returns the offset of the root node taking care of possible FDT_NOP tag. Use fdt_root_offset() to get the offset of the root node and use this value whenever the offset of the root node is expected. Signed-off-by: Herve Codina --- tests/node_offset_by_compatible.c | 4 +++- tests/node_offset_by_prop_value.c | 11 +++++++---- tests/path_offset.c | 13 +++++++++---- tests/root_node.c | 6 +++++- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/tests/node_offset_by_compatible.c b/tests/node_offset_by_compa= tible.c index a9e67835..1278a562 100644 --- a/tests/node_offset_by_compatible.c +++ b/tests/node_offset_by_compatible.c @@ -39,12 +39,14 @@ static void check_search(void *fdt, const char *compat,= ...) int main(int argc, char *argv[]) { void *fdt; + int root_offset; int subnode1_offset, subnode2_offset; int subsubnode1_offset, subsubnode2_offset; =20 test_init(argc, argv); fdt =3D load_blob_arg(argc, argv); =20 + root_offset =3D fdt_root_offset(fdt); subnode1_offset =3D fdt_path_offset(fdt, "/subnode@1"); subnode2_offset =3D fdt_path_offset(fdt, "/subnode@2"); subsubnode1_offset =3D fdt_path_offset(fdt, "/subnode@1/subsubnode"); @@ -54,7 +56,7 @@ int main(int argc, char *argv[]) || (subsubnode1_offset < 0) || (subsubnode2_offset < 0)) FAIL("Can't find required nodes"); =20 - check_search(fdt, "test_tree1", 0, -FDT_ERR_NOTFOUND); + check_search(fdt, "test_tree1", root_offset, -FDT_ERR_NOTFOUND); check_search(fdt, "subnode1", subnode1_offset, -FDT_ERR_NOTFOUND); check_search(fdt, "subsubnode1", subsubnode1_offset, -FDT_ERR_NOTFOUND); check_search(fdt, "subsubnode2", subsubnode2_offset, -FDT_ERR_NOTFOUND); diff --git a/tests/node_offset_by_prop_value.c b/tests/node_offset_by_prop_= value.c index 48ab1d93..329409b9 100644 --- a/tests/node_offset_by_prop_value.c +++ b/tests/node_offset_by_prop_value.c @@ -64,12 +64,14 @@ static void check_search_str(void *fdt, const char *pro= pname, int main(int argc, char *argv[]) { void *fdt; + int root_offset; int subnode1_offset, subnode2_offset; int subsubnode1_offset, subsubnode2_offset; =20 test_init(argc, argv); fdt =3D load_blob_arg(argc, argv); =20 + root_offset =3D fdt_root_offset(fdt); subnode1_offset =3D fdt_path_offset(fdt, "/subnode@1"); subnode2_offset =3D fdt_path_offset(fdt, "/subnode@2"); subsubnode1_offset =3D fdt_path_offset(fdt, "/subnode@1/subsubnode"); @@ -79,19 +81,20 @@ int main(int argc, char *argv[]) || (subsubnode1_offset < 0) || (subsubnode2_offset < 0)) FAIL("Can't find required nodes"); =20 - check_search_cell(fdt, "prop-int", TEST_VALUE_1, 0, subnode1_offset, - subsubnode1_offset, -FDT_ERR_NOTFOUND); + check_search_cell(fdt, "prop-int", TEST_VALUE_1, root_offset, + subnode1_offset, subsubnode1_offset, -FDT_ERR_NOTFOUND); =20 check_search_cell(fdt, "prop-int", TEST_VALUE_2, subnode2_offset, subsubnode2_offset, -FDT_ERR_NOTFOUND); =20 - check_search_str(fdt, "prop-str", TEST_STRING_1, 0, -FDT_ERR_NOTFOUND); + check_search_str(fdt, "prop-str", TEST_STRING_1, root_offset, + -FDT_ERR_NOTFOUND); =20 check_search_str(fdt, "prop-str", "no such string", -FDT_ERR_NOTFOUND); =20 check_search_cell(fdt, "prop-int", TEST_VALUE_1+1, -FDT_ERR_NOTFOUND); =20 - check_search(fdt, "no-such-prop", NULL, 0, -FDT_ERR_NOTFOUND); + check_search(fdt, "no-such-prop", NULL, root_offset, -FDT_ERR_NOTFOUND); =20 PASS(); } diff --git a/tests/path_offset.c b/tests/path_offset.c index ad8db833..d4f6553b 100644 --- a/tests/path_offset.c +++ b/tests/path_offset.c @@ -84,11 +84,16 @@ int main(int argc, char *argv[]) void *fdt; int subnode1_offset, subnode2_offset; int subsubnode1_offset, subsubnode2_offset, subsubnode2_offset2; + int root_offset; =20 test_init(argc, argv); fdt =3D load_blob_arg(argc, argv); =20 - check_path_offset(fdt, "/", 0); + root_offset =3D fdt_root_offset(fdt); + if (root_offset < 0) + FAIL("fdt_root_offset()) failed: %s", fdt_strerror(root_offset)); + + check_path_offset(fdt, "/", root_offset); =20 subnode1_offset =3D check_subnode(fdt, 0, "subnode@1"); subnode2_offset =3D check_subnode(fdt, 0, "subnode@2"); @@ -106,8 +111,8 @@ int main(int argc, char *argv[]) =20 /* Test paths with extraneous separators */ check_path_offset(fdt, "", -FDT_ERR_BADPATH); - check_path_offset(fdt, "//", 0); - check_path_offset(fdt, "///", 0); + check_path_offset(fdt, "//", root_offset); + check_path_offset(fdt, "///", root_offset); check_path_offset(fdt, "//subnode@1", subnode1_offset); check_path_offset(fdt, "/subnode@1/", subnode1_offset); check_path_offset(fdt, "//subnode@1///", subnode1_offset); @@ -116,7 +121,7 @@ int main(int argc, char *argv[]) /* Test fdt_path_offset_namelen() */ check_path_offset_namelen(fdt, "/subnode@1", -1, -FDT_ERR_BADPATH); check_path_offset_namelen(fdt, "/subnode@1", 0, -FDT_ERR_BADPATH); - check_path_offset_namelen(fdt, "/subnode@1", 1, 0); + check_path_offset_namelen(fdt, "/subnode@1", 1, root_offset); check_path_offset_namelen(fdt, "/subnode@1/subsubnode", 10, subnode1_offs= et); check_path_offset_namelen(fdt, "/subnode@1/subsubnode", 11, subnode1_offs= et); check_path_offset_namelen(fdt, "/subnode@2TRAILINGGARBAGE", 10, subnode2_= offset); diff --git a/tests/root_node.c b/tests/root_node.c index 37e6f059..30903f2b 100644 --- a/tests/root_node.c +++ b/tests/root_node.c @@ -19,12 +19,16 @@ int main(int argc, char *argv[]) { void *fdt; const struct fdt_node_header *nh; + int root_offset; =20 test_init(argc, argv); fdt =3D load_blob_arg(argc, argv); =20 - nh =3D fdt_offset_ptr(fdt, 0, sizeof(*nh)); + root_offset =3D fdt_root_offset(fdt); + if (root_offset < 0) + FAIL("fdt_root_offset() returns %d", root_offset); =20 + nh =3D fdt_offset_ptr(fdt, root_offset, sizeof(*nh)); if (! nh) FAIL("NULL retrieving root node"); =20 --=20 2.55.0 From nobody Mon Sep 28 04:49:01 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DB5A23B893C; Wed, 26 Aug 2026 08:32:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733169; cv=none; b=jrZxfdR8onmdQWCvP2y6n/aEX9Mr2+HZfKW7Tb5e3KL7pxOeXw0D52iM9o909C3PXL2Pem/ulxUZgmEJjG7K/tGAXp5OU4pvB8Dh5zXJnXuF3z33dHCpMarXqnI8PBbN9CTo6BO2qdKi/BBhZLtruSrrYx5q/r81LgiolqHDjag= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733169; c=relaxed/simple; bh=SvnrI4XKbm69hwbW4FnPoNxrxxzQqWC9H7w6rqeDnEQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XBVjmR/ASuSui21OEAm676HT0KGeifMaH0GYlI1GoJ/TXHzNKaLbZfmhYZ7TJyOCQLuamjngM2xEwvtwD8j0s90PwbTq1YkMtOSSZ/S8ibCwOb3d+kYxlETtTKjjaimj5GH3Hn5NT1bvZTYYKYTxU8FnYZ9FI0cVglHfG7tCCgc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=tx5ywbf8; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="tx5ywbf8" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 54EF71A183F; Wed, 26 Aug 2026 08:32:46 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 226F5604EC; Wed, 26 Aug 2026 08:32:46 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 2CF4D11C7A96D; Wed, 26 Aug 2026 10:32:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1787733165; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=Vwooc4B3R0CfZKT2vciMVi7EI4eYpEP71MWHW1Bldss=; b=tx5ywbf84g6yN06AcxJog9iGIeBLUF4sRMoDYrmS+iNbHpISxkgj3m2fnZA9ZBrbP9w9+T JTw/kYAivh/yqOBZ3zpyqfJ41SRJJk6qcE0qAO1MxTgWv+7Wautaldj56+IegbGv09OEk7 FtfwF6+/hZ6hX02M+N1XacCZf8vd0LzGzLaAX1ZWoxofc4hAs3dm2BqSXf+UpYM5ZA9fhL ZdmkNeUbz013asKJSu+AXDzHtgGTIA1IQpHpmhxX2CTRuBTPS1Rgnh147KWGCDSsPp/t12 diTkQecX/9uNAUhJpfaIOOy7H6qyS8vjgxyHcvLqu4DYD+Lnd4NHPAR1+s6Tag== From: Herve Codina To: David Gibson , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Laurent Pinchart , David Lechner , Ayush Singh , Geert Uytterhoeven , devicetree-compiler@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree-spec@vger.kernel.org, Hui Pu , Ian Ray , Luca Ceresoli , Thomas Petazzoni , Herve Codina Subject: [PATCH v3 04/15] tests/nopulate: Add a FDT_NOP before the root node Date: Wed, 26 Aug 2026 10:31:35 +0200 Message-ID: <20260826083146.304291-5-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826083146.304291-1-herve.codina@bootlin.com> References: <20260826083146.304291-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" A FDT_NOP tag can be present at the offset 0 and so before the root node. This is a legit case. The nopulate tool adds FDT_NOP tag after each tag encountered but it doesn't add a FDT_NOP tag at offset 0. Improve nopulate to fix this lack and add a FDT_NOP tag at offset 0. Signed-off-by: Herve Codina Reviewed-by: David Gibson --- tests/nopulate.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/nopulate.c b/tests/nopulate.c index 06f8369a..050e69fb 100644 --- a/tests/nopulate.c +++ b/tests/nopulate.c @@ -22,7 +22,10 @@ static int nopulate_struct(char *buf, const char *fdt) uint32_t tag; char *p; =20 + /* Add a FDT_NOP before the root node (first node) */ p =3D buf; + *((fdt32_t *)p) =3D cpu_to_fdt32(FDT_NOP); + p +=3D FDT_TAGSIZE; =20 do { offset =3D nextoffset; --=20 2.55.0 From nobody Mon Sep 28 04:49:01 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6D1233B5314 for ; Wed, 26 Aug 2026 08:32:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733172; cv=none; b=PC+CwHOMGLVy8gNpQZZl996TMVBMnqwRAKaGquMaWtiPVV91KoihURG8A02ysas9NHXJib6bj72ixJhJ7L5T44WAX1M/OGoZJHHs6dbAHKWT6F7AK2DHwDyzA4h0oaZ1RUFwVk0X+zcEecoLoPniR05H9EAaFLFxDcGKX6tjfPw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733172; c=relaxed/simple; bh=aSuaLD5lGVPIQ5nEqA0ifxuQjZLrDQZvJUNjMVnDt6w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pWMKus1pru3z8hN8dqL0cbYXBjUdyYTuF0fikhUP1MYGWayE+dLHjF2z6Eoivk6iaI68KiDnicv/c+4hPu4+pzp1i28ViQSuXQF11yGsOWZaqRmRtUxdcobEkHpiZIoh5gBoTGIGXcFmRDpBbdoWrB8xNl1gAlO3t7569Xe75XI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=Hhgi/Uc2; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="Hhgi/Uc2" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id AF3011A1840; Wed, 26 Aug 2026 08:32:48 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 823F4604EC; Wed, 26 Aug 2026 08:32:48 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id CD66911C7AC7E; Wed, 26 Aug 2026 10:32:45 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1787733167; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=EVK9O7k92JFDWFYqEVYeBihhFb83QRpRZVBQqv6qGW8=; b=Hhgi/Uc2FrjTRVxGiekdd1OeiuQBg05VU8VHz7NatLn7XNQBST3UpxLXHq0yYSq8yPxYXt kbPAnPeJ6gq51Gqpkflz2K0KM55H5qtyh51JUIPrMM4S40FEJ7mZknzMAdq+/H6JDeT+YR QRzeAQz+a6SlOGXGUt2adfH8GGVsrUC5RmpbvL+8MkoP/b93R9OLB237TEs4L1+iZVV/n9 Fdb5z5JG7iwCv5NkHVUmV6QSA9QP1pWDlKgxY5+ghTl5ArSDUNwKc/Z+9Z7BlEinV6Z97b UQkbr2thxgl2qc+6k7oNslRRAPOHnOmgoIeii5Nzc4DmkW1bj2y3Of+Pd6nOAA== From: Herve Codina To: David Gibson , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Laurent Pinchart , David Lechner , Ayush Singh , Geert Uytterhoeven , devicetree-compiler@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree-spec@vger.kernel.org, Hui Pu , Ian Ray , Luca Ceresoli , Thomas Petazzoni , Herve Codina Subject: [PATCH v3 05/15] tests: treegen: Introduce emit_fdt_header_vers() Date: Wed, 26 Aug 2026 10:31:36 +0200 Message-ID: <20260826083146.304291-6-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826083146.304291-1-herve.codina@bootlin.com> References: <20260826083146.304291-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" treegen is used to generate custom dtbs. It uses emit_fdt_header() to generate the header part. The current definition of this function doesn't allow to set custom settings related to version fields. In order to easily generate some dtb with custom version values, introduce emit_fdt_header_vers(). The modification doesn't introduce any functional changes. Signed-off-by: Herve Codina Reviewed-by: David Gibson --- tests/treegen.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/treegen.c b/tests/treegen.c index 6891bfd6..28943d43 100644 --- a/tests/treegen.c +++ b/tests/treegen.c @@ -105,7 +105,8 @@ static void fill_prop_name(struct buf *b, size_t strs, = size_t prop, size_t strof =20 /* FDT structure helpers */ =20 -static size_t emit_fdt_header(struct buf *b) +static size_t emit_fdt_header_vers(struct buf *b, uint32_t version, + uint32_t last_comp_version) { size_t off =3D emit_u32(b, FDT_MAGIC); =20 @@ -113,14 +114,19 @@ static size_t emit_fdt_header(struct buf *b) emit_u32(b, 0); /* off_dt_struct */ emit_u32(b, 0); /* off_dt_strings */ emit_u32(b, 0); /* off_mem_rsvmap */ - emit_u32(b, 0x11); /* version */ - emit_u32(b, 0x10); /* last_comp_version */ + emit_u32(b, version); /* version */ + emit_u32(b, last_comp_version); /* last_comp_version */ emit_u32(b, 0); /* boot_cpuid_phys */ emit_u32(b, 0); /* size_dt_strings */ emit_u32(b, 0); /* size_dt_struct */ return off; } =20 +static size_t emit_fdt_header(struct buf *b) +{ + return emit_fdt_header_vers(b, 0x11, 0x10); +} + static void finish_rsvmap(struct buf *b, size_t hdr, size_t rsvmap) { struct fdt_header *fh =3D (struct fdt_header *)(b->data + hdr); --=20 2.55.0 From nobody Mon Sep 28 04:49:01 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AD6543B7747; Wed, 26 Aug 2026 08:32:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733175; cv=none; b=lrxzCZeYnm4Eesy6vtMwcqPP1dMrk6tV/8MDl0BY4evHPSQmqI5xCtz6SqUJ8t9cZ5H3oMX76Vjbm/ugNNxTPB4fj77ohLa2Wio6p6vwf9IoSbvZOIRcJo/6ECGZmL1GZppZO1PDs4xsR09OYyQA/6RXadiyw+UFEREWwzDmp1E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733175; c=relaxed/simple; bh=LyfoGBf+bozP8v8sfTfgbLFIPFn7OocWM5OCM5etkZQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=K1hsaZE7DlKwtIu4DOWnjCZ3Fb4HcPfp0/F66lSMQhqCWbHklMFDENUowJNfBEN2wXdlzJtU/paBjaEAsPUusLbzy3xQm4XWWOUlE/LEuoj+ji60A1z2IoVyNEzAx+oBVFJbJRiEourQX+OvsawmgJN/biDQNdOK5Cyp1CmLTF0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=C92s42Fh; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="C92s42Fh" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 3CAD04E413C1; Wed, 26 Aug 2026 08:32:52 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 0A086604EC; Wed, 26 Aug 2026 08:32:52 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 93CB211C7AC4A; Wed, 26 Aug 2026 10:32:48 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1787733170; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=BovFWMOtZhvJgX8p9K2wqIASV+yACJxR34EojkuuGFg=; b=C92s42FhPeU1E7dk/BRC2Z1LnPQdynoshACWbsbJO0mwg4zCBY6++NXGBDs7RHICas3iA8 fDC72b9iEFQeP7bnZyn0GuigNJRxplx8EnszI6odS++hxJQ9HO/rNdUv4M67+UxabXXAjj NzXVR2pARSr+ViiLxT40UhBkHpbh9qUKBJU5HTwgqutY268hfjkU9bNU8UiWuX+idt2UT0 P2pxVN50g3IaZ8OhsyBLCRzc7ROuOQmN4FBdo4eCi5rj7QOYtQfPFIdMLjj7JKbVHPddIU QLBa5kEKYKX8FPpBCQ+K5olQhilzPkXAR+gJ9o2PB1cMgxDcJoR9G8x8IlZGsw== From: Herve Codina To: David Gibson , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Laurent Pinchart , David Lechner , Ayush Singh , Geert Uytterhoeven , devicetree-compiler@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree-spec@vger.kernel.org, Hui Pu , Ian Ray , Luca Ceresoli , Thomas Petazzoni , Herve Codina , Frank Li Subject: [PATCH v3 06/15] Introduce structured tag value definition Date: Wed, 26 Aug 2026 10:31:37 +0200 Message-ID: <20260826083146.304291-7-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826083146.304291-1-herve.codina@bootlin.com> References: <20260826083146.304291-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" The goal of structured tag values is to ease the introduction of new tags in future releases with the capability for an already existing release to ignore those structured tags. In order to do that data length related to the unknown tag needs to be identified. Also add a flag to tell an old release if this tag can be simply skipped or must lead to an error. Structured tag value is defined on 32bit and is defined as follow: Bits | 31 | 30 | 29 28 | 27 0| ------+----+-----------+-------------------+--------+ Fields| 1 | SKIP_SAFE | DATA_LEN_ENCODING | TAG_ID | ------+----+-----------+-------------------+--------+ Bit 31 is always set to 1 to identify a structured tag value. Bit 30 (SKIP_SAFE) is set to 1 if the tag can be safely ignored when its TAG_ID value is not a known value (unknown tag). If the SKIP_SAFE bit is set to 0 this tag must not be ignored and an error should be reported when its TAG_ID value is not a known value (unknown tag). Bits 29..28 (DATA_LEN_ENCODING) indicates the length of the data related to the tag. Following values are possible: - 0b00: No data. The tag is followed by the next tag value. - 0b01: 1 cell data The tag is followed by a 1 cell (u32) data. The next tag is available after this cell. - 0b10: 2 cells data The tag is followed by a 2 cells (2 * u32) data. The next tag is available after those two cells. - 0b11: Data length encoding The tag is followed by a cell (u32) indicating the size of the data. This size is given in bytes. Data are available right after this cell. The next tag is available after the data. Padding is present after the data in order to have the next tag aligned on 32bits. This padding is not included in the size of the data. Bits 27..0 (TAG_ID) is the tag identifier defining a specific tag. Introduce the structured tag values definition and some specific tags reserved for tests based on this structure definition. Signed-off-by: Herve Codina Reviewed-by: Frank Li --- libfdt/fdt.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/libfdt/fdt.h b/libfdt/fdt.h index a07abfcc..f41a355f 100644 --- a/libfdt/fdt.h +++ b/libfdt/fdt.h @@ -49,6 +49,7 @@ struct fdt_property { =20 #define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ #define FDT_TAGSIZE sizeof(fdt32_t) +#define FDT_CELLSIZE sizeof(fdt32_t) =20 #define FDT_BEGIN_NODE 0x1 /* Start node: full name */ #define FDT_END_NODE 0x2 /* End node */ @@ -57,6 +58,28 @@ struct fdt_property { #define FDT_NOP 0x4 /* nop */ #define FDT_END 0x9 =20 +/* Tag values flags */ +#define FDT_TAG_STRUCTURED (1U<<31) +#define FDT_TAG_SKIP_SAFE (1U<<30) +#define FDT_TAG_DATA_MASK (3U<<28) +#define FDT_TAG_DATA_NONE (0U<<28) +#define FDT_TAG_DATA_1CELL (1U<<28) +#define FDT_TAG_DATA_2CELLS (2U<<28) +#define FDT_TAG_DATA_VARLEN (3U<<28) + +#define FDT_TAG_NO_SKIP(tag_data, tag_id) \ + (FDT_TAG_STRUCTURED | tag_data | tag_id) + +#define FDT_TAG_CAN_SKIP(tag_data, tag_id) \ + (FDT_TAG_STRUCTURED | FDT_TAG_SKIP_SAFE | tag_data | tag_id) + +/* Tests reserved tags */ +#define FDT_TEST_NONE_CAN_SKIP FDT_TAG_CAN_SKIP(FDT_TAG_DATA_NONE, 0) +#define FDT_TEST_1CELL_CAN_SKIP FDT_TAG_CAN_SKIP(FDT_TAG_DATA_1CELL, 0) +#define FDT_TEST_2CELLS_CAN_SKIP FDT_TAG_CAN_SKIP(FDT_TAG_DATA_2CELLS, 0) +#define FDT_TEST_VARLEN_CAN_SKIP FDT_TAG_CAN_SKIP(FDT_TAG_DATA_VARLEN, 0) +#define FDT_TEST_NONE_NO_SKIP FDT_TAG_NO_SKIP(FDT_TAG_DATA_NONE, 0) + #define FDT_V1_SIZE (7*sizeof(fdt32_t)) #define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t)) #define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t)) --=20 2.55.0 From nobody Mon Sep 28 04:49:01 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 689573BB104 for ; Wed, 26 Aug 2026 08:32:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733177; cv=none; b=iGHzQc6lEhozdvoxMu+OYqHIMv1ivvSpAW4p8ySeU9W9IDHNgcGlbmApq+WdT268Fz6obzPQE5kwUZgQN9zn3I8I9enTcGNOB7L9FqA1O/BmRKn5M/uOCTlCVafXjJ4/dlWEcwTMdip/LkwpjDWXTIGRKKlBotcOr3gEx+Zy+O8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733177; c=relaxed/simple; bh=mWWP/Mq0dmFdgdQKWf3OHgWJSShbhrYNhKhwhXn55+4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=P7oRIyxH02KkwTMN8CJ1JAf++GklNMD275jmJy5hq50RFAx2YKIOJDRQxdIy7O0HKQrCH8CRA9S/Rdpks4EpzmaefVZgS94NCkS6N+TInOZgyK5ai8uddOxhFp7AUxrgGEKigMf7H+ITPBx04YrcCy9BtMfF+BYeUFg0eP+PO2g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=LE9od/ZQ; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="LE9od/ZQ" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id F15814E413C4; Wed, 26 Aug 2026 08:32:53 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id BDB99604EC; Wed, 26 Aug 2026 08:32:53 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 31EDA11C7AB70; Wed, 26 Aug 2026 10:32:51 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1787733172; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=yf3H7SVuVcK0WphDMYA5ife05YxHxK0TfuE9N0nAOHA=; b=LE9od/ZQYf70EGAzsm3LuS4UK4FRmS1yeUkQezXZDF/kZ9Uahwe9b0pl4Uj7FtDM/XrcNk 27E1QHj7d+75RgDYSE5ZJsg8At0bDe5UqjLZAYIzeGousaSu8tgmC3Oo6CTjkOSjr0/STZ BESXVeAT/jKa5GoQ6Fu2Elux4Gw8vgGzzJ0vQLvuxAE3UZ57zwtizuc/JbbyQjM0wnzwpe WeWUk3RSg9qXkSQhc80lOvP2LmdeUzPABDO9eCZf9MqSlvC0nv094h9X2Hw8ou6aGXV9aP voSO4Lp4POEtq608a8dNWNPP2nbTFa7SZhDkyZvt1v41e+ZuAiHUK3EA9QFjZA== From: Herve Codina To: David Gibson , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Laurent Pinchart , David Lechner , Ayush Singh , Geert Uytterhoeven , devicetree-compiler@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree-spec@vger.kernel.org, Hui Pu , Ian Ray , Luca Ceresoli , Thomas Petazzoni , Herve Codina , Frank Li Subject: [PATCH v3 07/15] fdtdump: Handle unknown tags Date: Wed, 26 Aug 2026 10:31:38 +0200 Message-ID: <20260826083146.304291-8-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826083146.304291-1-herve.codina@bootlin.com> References: <20260826083146.304291-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" The structured tag value definition introduced recently gives the ability to ignore unknown tags without any error when they are read. Add support for those structured tags in fdtdump and introduce a command line option to dump unknown tags that should be ignored. Signed-off-by: Herve Codina Reviewed-by: Frank Li --- fdtdump.c | 45 ++++++- tests/Makefile.tests | 3 +- tests/meson.build | 2 + tests/run_tests.sh | 41 +++++++ tests/treegen.c | 162 +++++++++++++++++++++++++ tests/unknown_tags_can_skip.dtb.expect | 29 +++++ 6 files changed, 278 insertions(+), 4 deletions(-) create mode 100644 tests/unknown_tags_can_skip.dtb.expect diff --git a/fdtdump.c b/fdtdump.c index 0e7a2659..7a8b2784 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -44,7 +44,7 @@ static const char *tagname(uint32_t tag) #define dumpf(fmt, args...) \ do { if (debug) printf("// " fmt, ## args); } while (0) =20 -static void dump_blob(void *blob, bool debug) +static void dump_blob(void *blob, bool debug, int dump_unknown) { uintptr_t blob_off =3D (uintptr_t)blob; struct fdt_header *bph =3D blob; @@ -146,20 +146,55 @@ static void dump_blob(void *blob, bool debug) continue; } =20 + if ((tag & FDT_TAG_STRUCTURED) && (tag & FDT_TAG_SKIP_SAFE)) { + sz =3D 0; + switch (tag & FDT_TAG_DATA_MASK) { + case FDT_TAG_DATA_NONE: + break; + case FDT_TAG_DATA_1CELL: + sz =3D FDT_CELLSIZE; + break; + case FDT_TAG_DATA_2CELLS: + sz =3D 2 * FDT_CELLSIZE; + break; + case FDT_TAG_DATA_VARLEN: + /* Get the length */ + sz =3D fdt32_to_cpu(GET_CELL(p)); + break; + } + + if (dump_unknown) { + printf("%*s// Unknown tag ignored: 0x%08"PRIx32", data len %d", + depth * shift, "", tag, sz); + if (dump_unknown > 1 && sz !=3D 0) { + printf(" "); + for (i =3D 0; i < sz; i++) + printf("%02hhx", *(p + i)); + } + printf("\n"); + } + + /* Skip the data bytes */ + p =3D PALIGN(p + sz, 4); + continue; + } + die("** Unknown tag 0x%08"PRIx32"\n", tag); } } =20 /* Usage related data. */ static const char usage_synopsis[] =3D "fdtdump [options] "; -static const char usage_short_opts[] =3D "ds" USAGE_COMMON_SHORT_OPTS; +static const char usage_short_opts[] =3D "dus" USAGE_COMMON_SHORT_OPTS; static struct option const usage_long_opts[] =3D { {"debug", no_argument, NULL, 'd'}, + {"unknown", no_argument, NULL, 'u'}, {"scan", no_argument, NULL, 's'}, USAGE_COMMON_LONG_OPTS }; static const char * const usage_opts_help[] =3D { "Dump debug information while decoding the file", + "Dump unknown tags information while decoding the file (-uu to dump data)= ", "Scan for an embedded fdt in file", USAGE_COMMON_OPTS_HELP }; @@ -183,6 +218,7 @@ int main(int argc, char *argv[]) const char *file; char *buf; bool debug =3D false; + int dump_unknown =3D 0; bool scan =3D false; size_t len; =20 @@ -198,6 +234,9 @@ int main(int argc, char *argv[]) case 'd': debug =3D true; break; + case 'u': + dump_unknown++; + break; case 's': scan =3D true; break; @@ -242,7 +281,7 @@ int main(int argc, char *argv[]) } else if (!valid_header(buf, len)) die("%s: header is not valid\n", file); =20 - dump_blob(buf, debug); + dump_blob(buf, debug, dump_unknown); =20 return 0; } diff --git a/tests/Makefile.tests b/tests/Makefile.tests index af5d309c..63e201ae 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -44,7 +44,8 @@ TESTS =3D $(LIB_TESTS) $(DL_LIB_TESTS) TESTS_TREES_L =3D test_tree1.dtb bad_node_char.dtb bad_node_format.dtb \ bad_prop_char.dtb ovf_size_strings.dtb truncated_property.dtb \ truncated_string.dtb truncated_memrsv.dtb unterminated_memrsv.dtb \ - two_roots.dtb named_root.dtb + two_roots.dtb named_root.dtb unknown_tags_can_skip.dtb \ + unknown_tags_no_skip.dtb TESTS_TREES =3D $(TESTS_TREES_L:%=3D$(TESTS_PREFIX)%) =20 TESTS_TARGETS =3D $(TESTS) $(TESTS_TREES) diff --git a/tests/meson.build b/tests/meson.build index c6ac2d7f..779e6bc7 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -17,6 +17,8 @@ treegen_dtb =3D custom_target( 'unterminated_memrsv.dtb', 'two_roots.dtb', 'named_root.dtb', + 'unknown_tags_can_skip.dtb', + 'unknown_tags_no_skip.dtb', ] ) =20 diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 842b5430..f3647e63 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -196,6 +196,40 @@ check_align () { ) } =20 +# $1: generated file +# $2: expected file +check_diff () { + printf "check_diff $1 $2: " + local fgen=3D"$1" + local fref=3D"$2" + ( + if diff $fref $fgen >/dev/null; then + PASS + else + if [ -z "$QUIET_TEST" ]; then + echo "DIFF :-:" + diff -u $fref $fgen + fi + FAIL "Results differ from expected" + fi + ) +} + +# $1: dtb file +# $2: out file +wrap_fdtdump () { + printf "wrap_fdtdump -uu $1: " + local dtb=3D"$1" + local out=3D"$2" + ( + if $FDTDUMP -uu ${dtb} 2>/dev/null >${out}; then + PASS + else + FAIL + fi + ) +} + run_dtc_test () { printf "dtc $*: " base_run_test wrap_test $VALGRIND $DTC "$@" @@ -1008,6 +1042,13 @@ utilfdt_tests () { =20 fdtdump_tests () { run_fdtdump_test "$SRCDIR/fdtdump.dts" + + base_run_test wrap_fdtdump unknown_tags_can_skip.dtb unknown_tags_can_= skip.dtb.out + # Remove unneeded comments + sed -i '/^\/\/ [^U]/d' unknown_tags_can_skip.dtb.out + base_run_test check_diff unknown_tags_can_skip.dtb.out "$SRCDIR/unknow= n_tags_can_skip.dtb.expect" + + run_wrap_error_test $FDTDUMP unknown_tags_no_skip.dtb } =20 fdtoverlay_tests() { diff --git a/tests/treegen.c b/tests/treegen.c index 28943d43..f07c8963 100644 --- a/tests/treegen.c +++ b/tests/treegen.c @@ -707,6 +707,166 @@ static struct buf make_named_root(void) return b; } =20 +/* Tree with "unknown" tags that can be skipped + * Use a really future dtb version to check version downgrade on + * modification. + */ +static struct buf make_unknown_tags_can_skip(void) +{ + struct buf b =3D buf_init(); + size_t hdr; + size_t p_int, p_str; + size_t p_sn1_int; + size_t p_sn2_int1, p_sn2_int2; + size_t p_sn2ssn_bool; + + hdr =3D emit_fdt_header_vers(&b, 0xffffffff, 0x10); + emit_align(&b, 8); + + emit_rsvmap_empty(&b, hdr); + + { + size_t ss =3D start_block(&b); + + emit_u32(&b, FDT_TEST_1CELL_CAN_SKIP); + emit_u32(&b, 0x1); + + emit_begin_node(&b, ""); + emit_u32(&b, FDT_TEST_NONE_CAN_SKIP); + + p_int =3D emit_prop_u32(&b, 0, 0x3201); + + emit_u32(&b, FDT_TEST_1CELL_CAN_SKIP); + emit_u32(&b, 0x110); + + p_str =3D emit_prop_str(&b, 0, "abcd"); + + emit_u32(&b, FDT_TEST_2CELLS_CAN_SKIP); + emit_u32(&b, 0x120); + emit_u32(&b, 0x121); + + emit_u32(&b, FDT_TEST_VARLEN_CAN_SKIP); + emit_u32(&b, 3); + emit_bytes(&b, (const uint8_t []){0x10, 0x11, 0x12}, 3); + emit_align(&b, FDT_TAGSIZE); + + emit_begin_node(&b, "subnode1"); + p_sn1_int =3D emit_prop_u64(&b, 0, 0x640100006402); + emit_u32(&b, FDT_TEST_NONE_CAN_SKIP); + emit_end_node(&b); + + emit_begin_node(&b, "subnode2"); + emit_u32(&b, FDT_TEST_1CELL_CAN_SKIP); + emit_u32(&b, 0x121); + + p_sn2_int1 =3D emit_prop_u64(&b, 0, 0x6402000064021); + + emit_u32(&b, FDT_TEST_2CELLS_CAN_SKIP); + emit_u32(&b, 0x1220); + emit_u32(&b, 0x1221); + + p_sn2_int2 =3D emit_prop_u32(&b, 0, 0x32022); + + emit_begin_node(&b, "subsubnode"); + emit_u32(&b, FDT_TEST_2CELLS_CAN_SKIP); + emit_u32(&b, 0x1230); + emit_u32(&b, 0x1231); + p_sn2ssn_bool =3D emit_prop_nil(&b, 0); + emit_end_node(&b); + + emit_u32(&b, FDT_TEST_VARLEN_CAN_SKIP); + emit_u32(&b, 3); + emit_bytes(&b, (const uint8_t []){0x21, 0x22, 0x23}, 3); + emit_align(&b, FDT_TAGSIZE); + emit_end_node(&b); + + emit_u32(&b, FDT_TEST_VARLEN_CAN_SKIP); + emit_u32(&b, 4); + emit_bytes(&b, (const uint8_t []){0x31, 0x32, 0x33, 0x34}, 4); + emit_align(&b, FDT_TAGSIZE); + emit_end_node(&b); + + emit_u32(&b, FDT_TEST_1CELL_CAN_SKIP); + emit_u32(&b, 0x2); + + emit_u32(&b, FDT_TEST_VARLEN_CAN_SKIP); + emit_u32(&b, 2); + emit_bytes(&b, (const uint8_t []){0x40, 0x41}, 2); + emit_align(&b, FDT_TAGSIZE); + + emit_fdt_end(&b); + finish_struct_block(&b, hdr, ss); + } + + { + size_t strs =3D start_block(&b); + size_t s; + + s =3D emit_string(&b, "prop-int"); + fill_prop_name(&b, strs, p_int, s); + fill_prop_name(&b, strs, p_sn1_int, s); + + s =3D emit_string(&b, "prop-str"); + fill_prop_name(&b, strs, p_str, s); + + s =3D emit_string(&b, "prop-int1"); + fill_prop_name(&b, strs, p_sn2_int1, s); + + s =3D emit_string(&b, "prop-int2"); + fill_prop_name(&b, strs, p_sn2_int2, s); + + s =3D emit_string(&b, "prop-bool"); + fill_prop_name(&b, strs, p_sn2ssn_bool, s); + + finish_strings_block(&b, hdr, strs); + } + + finish_totalsize(&b, hdr); + + return b; +} + +/* Tree with "unknown" tags that cannot be skipped */ +static struct buf make_unknown_tags_no_skip(void) +{ + struct buf b =3D buf_init(); + size_t hdr; + size_t p_prop_u64; + + hdr =3D emit_fdt_header_vers(&b, 0xffffffff, 0x10); + emit_align(&b, 8); + + emit_rsvmap_empty(&b, hdr); + + { + size_t ss =3D start_block(&b); + + emit_begin_node(&b, ""); + emit_u32(&b, FDT_TEST_NONE_NO_SKIP); + + emit_begin_node(&b, "subnode1"); + p_prop_u64 =3D emit_prop_u64(&b, 0, 0x100000002); + emit_end_node(&b); + emit_end_node(&b); + emit_fdt_end(&b); + finish_struct_block(&b, hdr, ss); + } + + { + size_t strs =3D start_block(&b); + size_t s; + + s =3D emit_string(&b, "prop-int"); + fill_prop_name(&b, strs, p_prop_u64, s); + + finish_strings_block(&b, hdr, strs); + } + + finish_totalsize(&b, hdr); + + return b; +} + /* Tree table and main */ =20 static struct { @@ -722,6 +882,8 @@ static struct { TREE(unterminated_memrsv), TREE(two_roots), TREE(named_root), + TREE(unknown_tags_can_skip), + TREE(unknown_tags_no_skip), }; =20 int main(int argc, char *argv[]) diff --git a/tests/unknown_tags_can_skip.dtb.expect b/tests/unknown_tags_ca= n_skip.dtb.expect new file mode 100644 index 00000000..5ad9964e --- /dev/null +++ b/tests/unknown_tags_can_skip.dtb.expect @@ -0,0 +1,29 @@ +/dts-v1/; + +// Unknown tag ignored: 0xd0000000, data len 4 00000001 +/ { + // Unknown tag ignored: 0xc0000000, data len 0 + prop-int =3D <0x00003201>; + // Unknown tag ignored: 0xd0000000, data len 4 00000110 + prop-str =3D "abcd"; + // Unknown tag ignored: 0xe0000000, data len 8 0000012000000121 + // Unknown tag ignored: 0xf0000000, data len 3 101112 + subnode1 { + prop-int =3D <0x00006401 0x00006402>; + // Unknown tag ignored: 0xc0000000, data len 0 + }; + subnode2 { + // Unknown tag ignored: 0xd0000000, data len 4 00000121 + prop-int1 =3D <0x00064020 0x00064021>; + // Unknown tag ignored: 0xe0000000, data len 8 0000122000001221 + prop-int2 =3D <0x00032022>; + subsubnode { + // Unknown tag ignored: 0xe0000000, data len 8 0000123000001231 + prop-bool; + }; + // Unknown tag ignored: 0xf0000000, data len 3 212223 + }; + // Unknown tag ignored: 0xf0000000, data len 4 31323334 +}; +// Unknown tag ignored: 0xd0000000, data len 4 00000002 +// Unknown tag ignored: 0xf0000000, data len 2 4041 --=20 2.55.0 From nobody Mon Sep 28 04:49:01 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E14B03B71B8; Wed, 26 Aug 2026 08:32:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733179; cv=none; b=EWzmLTB6b2vOIU8CFdTc+1hZRGHt4tyk4CBKRQ8BOf7SJCHaXg1UUbZ1kv1M1MyYiOedbEfLELi+9g/lV4ed57bG3XEfVg4YVaWcT3Oxd+3xASAdB9lc/TFGp0b7A09LPcqadwpRX1gT9iFWfg6lrdqfqNhkeQBrDbnpm+BMEgU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733179; c=relaxed/simple; bh=QpN4qCEt7hYwfnpdO4a5K03B/9xVWyqMhVF9158lw10=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Nwo+SDlXv0KWvwoXafSY0T/FRHrBNCsBIyUqZ99CPmnMNKmJAffeUnZjvIBBYs0QY6kxp918t4q9De0US78UEma/NBNhXevIhREjduznwk2RicGwufkErI39YcNb6I8ME8SPHnweLUmytWjxDheRZxIZr9wYAzrV3YbacSRpbNs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=gsqEE0Sn; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="gsqEE0Sn" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 7A9CB4E413C1; Wed, 26 Aug 2026 08:32:56 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 4E78F604EC; Wed, 26 Aug 2026 08:32:56 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 655C511C7AC5A; Wed, 26 Aug 2026 10:32:53 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1787733175; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=D7Zzba+aoynELITCEBt8J/Zswm9vFahDLREpmOs5caI=; b=gsqEE0Snv8tqiXD49byCdDSB/UMboSB2y+I9kDtXFJSMuOwchg0LUAs9O1t5CQMHZ2DRSH VpictovkXdMDS1WJdsRCupfQDrAlHSaZ52qHlbByE+RgJ4eku8v8DEYGXjrfmb0u+q29Tp u1Hh41TYaIntguvuOEkafs9bbD6U90aOMib4QdYG+HSEePh3PBKLz8WjYC9XKDIbMH27Cs MaxIjnPraGNawRaK+io8O6SF0jqwDrBCZ/hAgb5TR/gYOg76jnPJgBx62ouaXFxnRGqcGY rR6hp9Ot2q5oTadF0+PDCTo9HBqwfydJHE9GDmmKfx1HAvMhzHr1xR/Jo1AxLQ== From: Herve Codina To: David Gibson , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Laurent Pinchart , David Lechner , Ayush Singh , Geert Uytterhoeven , devicetree-compiler@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree-spec@vger.kernel.org, Hui Pu , Ian Ray , Luca Ceresoli , Thomas Petazzoni , Herve Codina , Frank Li Subject: [PATCH v3 08/15] flattree: Handle unknown tags Date: Wed, 26 Aug 2026 10:31:39 +0200 Message-ID: <20260826083146.304291-9-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826083146.304291-1-herve.codina@bootlin.com> References: <20260826083146.304291-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" The structured tag value definition introduced recently gives the ability to ignore unknown tags without any error when they are read. Handle those structured tag. Signed-off-by: Herve Codina Reviewed-by: Luca Ceresoli Reviewed-by: Frank Li --- flattree.c | 65 ++++++++++++++++++++-- tests/run_tests.sh | 5 ++ tests/unknown_tags_can_skip.dtb.dts.expect | 19 +++++++ 3 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 tests/unknown_tags_can_skip.dtb.dts.expect diff --git a/flattree.c b/flattree.c index f3b698c1..88dbfa7e 100644 --- a/flattree.c +++ b/flattree.c @@ -579,7 +579,8 @@ static void flat_read_chunk(struct inbuf *inb, void *p,= int len) if ((inb->ptr + len) > inb->limit) die("Premature end of data parsing flat device tree\n"); =20 - memcpy(p, inb->ptr, len); + if (p) + memcpy(p, inb->ptr, len); =20 inb->ptr +=3D len; } @@ -604,6 +605,61 @@ static void flat_realign(struct inbuf *inb, int align) die("Premature end of data parsing flat device tree\n"); } =20 +static bool flat_skip_unknown_tag(struct inbuf *inb, uint32_t tag) +{ + uint32_t lng; + + if (!(tag & FDT_TAG_STRUCTURED) || !(tag & FDT_TAG_SKIP_SAFE)) + return false; + + switch (tag & FDT_TAG_DATA_MASK) { + case FDT_TAG_DATA_NONE: + break; + + case FDT_TAG_DATA_1CELL: + flat_read_word(inb); + break; + + case FDT_TAG_DATA_2CELLS: + flat_read_word(inb); + flat_read_word(inb); + break; + + case FDT_TAG_DATA_VARLEN: + /* Get the length */ + lng =3D flat_read_word(inb); + + /* Skip the following length bytes */ + flat_read_chunk(inb, NULL, lng); + + flat_realign(inb, sizeof(uint32_t)); + break; + } + + return true; +} + +static uint32_t flat_read_tag(struct inbuf *inb) +{ + uint32_t tag; + + do { + tag =3D flat_read_word(inb); + switch (tag) { + case FDT_BEGIN_NODE: + case FDT_END_NODE: + case FDT_PROP: + case FDT_NOP: + case FDT_END: + return tag; + default: + break; + } + } while (flat_skip_unknown_tag(inb, tag)); + + die("Cannot skip unknown tag 0x%08x\n", tag); +} + static const char *flat_read_string(struct inbuf *inb) { int len =3D 0; @@ -750,7 +806,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, struct property *prop; struct node *child; =20 - val =3D flat_read_word(dtbuf); + val =3D flat_read_tag(dtbuf); switch (val) { case FDT_PROP: if (node->children) @@ -905,14 +961,13 @@ struct dt_info *dt_from_blob(const char *fname) =20 reservelist =3D flat_read_mem_reserve(&memresvbuf); =20 - val =3D flat_read_word(&dtbuf); - + val =3D flat_read_tag(&dtbuf); if (val !=3D FDT_BEGIN_NODE) die("Device tree blob doesn't begin with FDT_BEGIN_NODE (begins with 0x%= 08x)\n", val); =20 tree =3D unflatten_tree(&dtbuf, &strbuf, "", flags); =20 - val =3D flat_read_word(&dtbuf); + val =3D flat_read_tag(&dtbuf); if (val !=3D FDT_END) die("Device tree blob doesn't end with FDT_END\n"); =20 diff --git a/tests/run_tests.sh b/tests/run_tests.sh index f3647e63..8fc23cb7 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -882,6 +882,11 @@ dtc_tests () { =20 # Tests for overlay/plugin generation dtc_overlay_tests + + # Tests with "unknown tags" + run_dtc_test -I dtb -O dts -o unknown_tags_can_skip.dtb.dts unknown_ta= gs_can_skip.dtb + base_run_test check_diff unknown_tags_can_skip.dtb.dts "$SRCDIR/unknow= n_tags_can_skip.dtb.dts.expect" + run_wrap_error_test $DTC -I dtb -O dts -o unknown_tags_no_skip.dtb.dts= unknown_tags_no_skip.dtb } =20 cmp_tests () { diff --git a/tests/unknown_tags_can_skip.dtb.dts.expect b/tests/unknown_tag= s_can_skip.dtb.dts.expect new file mode 100644 index 00000000..2194025b --- /dev/null +++ b/tests/unknown_tags_can_skip.dtb.dts.expect @@ -0,0 +1,19 @@ +/dts-v1/; + +/ { + prop-int =3D <0x3201>; + prop-str =3D "abcd"; + + subnode1 { + prop-int =3D <0x6401 0x6402>; + }; + + subnode2 { + prop-int1 =3D <0x64020 0x64021>; + prop-int2 =3D <0x32022>; + + subsubnode { + prop-bool; + }; + }; +}; --=20 2.55.0 From nobody Mon Sep 28 04:49:01 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E3D283B71CE; Wed, 26 Aug 2026 08:32:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733181; cv=none; b=Jvn/EcohLloC0g0T1jy7iAksaDRgsarIbnz/np5RMdw+ii8JJGJkJIAJU6xwlSMsNfdVrtiFeI+oE66bvyz0U96OS4ElM2s448VMCT8vzItQaPXdGD1Io9Yvo3g2opLKJcKJUsZ/ax1Wvj+pz0TIS8RAzm4oxSwm2Mcv7C/nY40= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733181; c=relaxed/simple; bh=ryj6qtC+rieClZ3/ur+Ak/VqTR1urmgK0jCffZjuyz8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZBQp3C2Z6CQeWsesrJQtMkGn+zPpnGdP++kKzliWoKMfIOnfomC0iLx2RyMQs4lHvUyR7RJvFaabEaL1BQLmP/aBVhkVfHsLKs+P4jb1Utr/gn+XsO2JlwDawV9NhBKg4zaGG1KaLcG//QtDg6JCNfpI7ydwPY/XrqtPjxh2gMo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=boas6wea; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="boas6wea" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 92FBE1A1844; Wed, 26 Aug 2026 08:32:58 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 67BBA604EC; Wed, 26 Aug 2026 08:32:58 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id D8C6811C7AC4A; Wed, 26 Aug 2026 10:32:55 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1787733177; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=t87Xr7v6Qr55Y1xfzRrTbV4rvY3L3qyedBD8I8H65Hc=; b=boas6weaJXVkiMVNkq0z/TXWKJyq9tROa07RhEVafPtuejLCPiFrQffJLu1GA/74A7l1yq mrBagvnPKrZR6wMFnOy80kPzN48oCfkoNkkaTpXuiOc3QLH1NcMRI+JrhUZxp7BXmF4bew YK4StO4XvfdYzFeWWCXlX7tI3BBCP5FaroXvnxQo5oz/DtKHkAXWJX6KPq4ujgGdO2KrYS 9twPPBqCcIN1tCfx8ZZcL16IV8aL2tzlguL+pUwtJiVWyrUpUSrMQT49WuoBrUgqJOfIED FDopYgfR97BDcphz+B9Ap8gozi2TV2eBQiEDRpGpMNucnwNCQEuxZFafaM/84A== From: Herve Codina To: David Gibson , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Laurent Pinchart , David Lechner , Ayush Singh , Geert Uytterhoeven , devicetree-compiler@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree-spec@vger.kernel.org, Hui Pu , Ian Ray , Luca Ceresoli , Thomas Petazzoni , Herve Codina , Frank Li Subject: [PATCH v3 09/15] libfdt: Handle unknown tags in fdt_next_tag() Date: Wed, 26 Aug 2026 10:31:40 +0200 Message-ID: <20260826083146.304291-10-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826083146.304291-1-herve.codina@bootlin.com> References: <20260826083146.304291-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" The structured tag value definition introduced recently gives the ability to ignore unknown tags without any error when they are read. libfdt uses fdt_next_tag() to get a tag. Filtering out tags that should be ignored in fdt_next_tag() allows to have the filtering done globally and allows, in future releases, to have a central place to add new known tags that should not be filtered out. An already known tag exists with the meaning of "just ignore". This tag is FDT_NOP. fdt_next_tag() callers already handle the FDT_NOP tag. Avoid unneeded modification at callers side and use a fake FDT_NOP tag when an unknown tag that should be ignored is encountered. Add also fdt_next_tag_() internal function for callers who need to know if the FDT_NOP tag returned is a real FDT_NOP or a fake FDT_NOP due to an unknown tag. Signed-off-by: Herve Codina Reviewed-by: Luca Ceresoli Reviewed-by: Frank Li --- libfdt/fdt.c | 75 ++++++++++++++++++++++++++++++++++++++-- libfdt/libfdt_internal.h | 3 ++ tests/run_tests.sh | 9 +++-- 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index eb803e8a..506e0dd3 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -167,7 +167,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset,= unsigned int len) return fdt_offset_ptr_(fdt, offset); } =20 -uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) +static uint32_t fdt_next_tag_all(const void *fdt, int startoffset, int *ne= xtoffset) { const fdt32_t *tagp, *lenp; uint32_t tag, len, sum; @@ -218,7 +218,37 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset= , int *nextoffset) break; =20 default: - return FDT_END; + if (!(tag & FDT_TAG_STRUCTURED) || !(tag & FDT_TAG_SKIP_SAFE)) + return FDT_END; + + switch (tag & FDT_TAG_DATA_MASK) { + case FDT_TAG_DATA_NONE: + break; + case FDT_TAG_DATA_1CELL: + offset +=3D FDT_CELLSIZE; + break; + case FDT_TAG_DATA_2CELLS: + offset +=3D 2 * FDT_CELLSIZE; + break; + case FDT_TAG_DATA_VARLEN: + /* Get the length */ + lenp =3D fdt_offset_ptr(fdt, offset, sizeof(*lenp)); + if (!can_assume(VALID_DTB) && !lenp) + return FDT_END; /* premature end */ + len =3D fdt32_to_cpu(*lenp); + /* + * Skip the cell encoding the length and the + * following length bytes + */ + len +=3D sizeof(*lenp); + sum =3D len + offset; + if (!can_assume(VALID_DTB) && + (sum >=3D INT_MAX || sum < (uint32_t) offset)) + return FDT_END; /* premature end */ + + offset +=3D len; + break; + } } =20 if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) @@ -228,6 +258,47 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset= , int *nextoffset) return tag; } =20 +static bool fdt_tag_is_unknown(uint32_t tag) +{ + switch (tag) { + case FDT_BEGIN_NODE: + case FDT_END_NODE: + case FDT_PROP: + case FDT_NOP: + case FDT_END: + return false; + default: + break; + } + return true; +} + +uint32_t fdt_next_tag_(const void *fdt, int startoffset, int *nextoffset, = bool *is_unknown) +{ + uint32_t tag; + bool unknown =3D false; + + /* Retrieve next tag */ + tag =3D fdt_next_tag_all(fdt, startoffset, nextoffset); + if (tag =3D=3D FDT_END) + goto end; + + if (fdt_tag_is_unknown(tag)) { + unknown =3D true; + /* Use a known tag that should be skipped by the caller */ + tag =3D FDT_NOP; + } +end: + if (is_unknown) + *is_unknown =3D unknown; + return tag; +} + +uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) +{ + return fdt_next_tag_(fdt, startoffset, nextoffset, NULL); +} + int fdt_check_node_offset_(const void *fdt, int offset) { if (!can_assume(VALID_INPUT) diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 0e103caf..f2e30ce8 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -20,6 +20,9 @@ int32_t fdt_ro_probe_(const void *fdt); } \ } =20 +uint32_t fdt_next_tag_(const void *fdt, int startoffset, int *nextoffset, + bool *is_unknown); + int fdt_check_node_offset_(const void *fdt, int offset); int fdt_check_prop_offset_(const void *fdt, int offset); =20 diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 8fc23cb7..225c22f8 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -577,11 +577,12 @@ libfdt_tests () { run_test dtbs_equal_ordered cell-overflow.test.dtb cell-overflow-resul= ts.test.dtb =20 # check full tests - for good in test_tree1.dtb; do + for good in test_tree1.dtb unknown_tags_can_skip.dtb; do run_test check_full $good done for bad in truncated_property.dtb truncated_string.dtb \ - truncated_memrsv.dtb two_roots.dtb named_root.dtb; do + truncated_memrsv.dtb two_roots.dtb named_root.dtb \ + unknown_tags_no_skip.dtb; do run_test check_full -n $bad done } @@ -962,6 +963,10 @@ fdtget_tests () { run_fdtget_test "" -tx \ -d "" $dtb /randomnode doctor-who run_fdtget_test "" -tx -d "" $dtb /memory doctor-who + + # test with unknown tags involved + run_fdtget_test "25601 25602" unknown_tags_can_skip.dtb /subnode1 prop= -int + run_wrap_error_test $DTGET unknown_tags_no_skip.dtb /subnode1 prop-int } =20 fdtput_tests () { --=20 2.55.0 From nobody Mon Sep 28 04:49:01 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EC2E33BBFC9; Wed, 26 Aug 2026 08:33:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733183; cv=none; b=AP5OdqiAWkU8K3LAmx0rDDkxjShhV/K8xiiyDtacI2tek/eA+K4T7oa8zPqNILVZ/sTIanV2/7L7aKx8bphaa+1KB1ClHRugt6Pue0J2WOYj6146S5Ikzs5zfENFKU/EQXiQZjVg4q+aogARYNCU32WvhJIRr42V4Sf8BcgoInk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733183; c=relaxed/simple; bh=P+chBaix+UggPJ8LbDsepISCksiwwTbW55SAZCgR8oU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rHlbSLoO69np4uMNrXzOyB91EfrhqbvIUfNXe6UakWSFyOR/Xc1p7RSFAKbE9EoJZykeaKuXzE4yj7WXLU5laC0rH0/hm8bCpZZQwxhAoS5S96FzV83ww6DWaSLrUIUZfmFFdb/99qj/cOaVkae16z5I25frlT6VAmNQBl5q3kg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=byKANWwQ; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="byKANWwQ" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id A50E74E413C1; Wed, 26 Aug 2026 08:33:00 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 77886604EC; Wed, 26 Aug 2026 08:33:00 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 06E0211C7AC7C; Wed, 26 Aug 2026 10:32:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1787733179; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=mU6cOuGSCvhMuDVdjXkVf3OutlhHj+8iM1DPGXph9Lc=; b=byKANWwQfgQKvHLLTgf7iO6sG2Lq+eys3hpUS9xb172vDMXk9THOvEjQpFR48ShjReYT/M cjXQcdQnjgXy6DZesfsuPdnzajTdIft/EH/lKUdZ9DVLPwXw88PfHdbef6aJ/DohN0W0Mw giWaOvqQeOiW3w5PrbkQRwo4Z+u01dxY/uM2KcQdurW2FEZQNNyh5nqRFEKD379cXoD8lw QiGRiB3/dRxcV8fL/dbICRhffMBbTiine1yzpzS/Hr4TQpyjJNBv+iOigxDgu8Au010VWu bX+ur0FIPCTWTd08pp03+/au0rC/V+mibpm1DKr7VuZ4AIqVVCBGjM7/zPLYCw== From: Herve Codina To: David Gibson , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Laurent Pinchart , David Lechner , Ayush Singh , Geert Uytterhoeven , devicetree-compiler@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree-spec@vger.kernel.org, Hui Pu , Ian Ray , Luca Ceresoli , Thomas Petazzoni , Herve Codina , Frank Li Subject: [PATCH v3 10/15] libfdt: Introduce fdt_ptr_offset_() Date: Wed, 26 Aug 2026 10:31:41 +0200 Message-ID: <20260826083146.304291-11-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826083146.304291-1-herve.codina@bootlin.com> References: <20260826083146.304291-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" libfdt provides internal helpers to convert an offset to a pointer but nothing to do the reverse operation. Introduce the fdt_ptr_offset_() internal helper to convert a pointer to an offset. Signed-off-by: Herve Codina Reviewed-by: Luca Ceresoli Reviewed-by: Frank Li --- libfdt/libfdt_internal.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index f2e30ce8..3c83d9a7 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -46,6 +46,11 @@ static inline void *fdt_offset_ptr_w_(void *fdt, int off= set) return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset); } =20 +static inline int fdt_ptr_offset_(const void *fdt, const void *ptr) +{ + return (const char *)ptr - (const char *)fdt_offset_ptr_(fdt, 0); +} + static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt= , int n) { const struct fdt_reserve_entry *rsv_table =3D --=20 2.55.0 From nobody Mon Sep 28 04:49:01 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AC56B3BCD17; Wed, 26 Aug 2026 08:33:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733185; cv=none; b=bBcHe57UXjksFlPkM+GPXVd8+DcRl9oZECeVNUzHHbpJt+YoKIlG8Gxmb91g4wFPkNOJ7Fo64zyA9SxiQvQF6+tTjXO00oSS/TIN4e+MMwfMRhIyZO0oShw3YMrQ0iN0oFZyPuAbQpzyMvzsMA+5V4vHnGrg+KgpXYxmbTGR7q4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733185; c=relaxed/simple; bh=Xw+lLkeHOdNK/RVttK7odw2ffNcux/6YzZuNE+EPAxY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YxME01qrL9FeiRtLdU3xcYVyxJ2f9eQ4G4lH1C/I0knlT5jroc4fo+XiUAO5lVg3vwnC8UmqIiFkoWc3vrOuj0QjKadZ/5WDW16nFrCVE3VzF5Um9DFlGDuCdPfr72sdvQhtMikBGhneZdl3FLmTWSE3Jbo3hLfnDXrWIqxgSwk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=dZlTQO5F; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="dZlTQO5F" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 582A21A183B; Wed, 26 Aug 2026 08:33:02 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 2C33E604EC; Wed, 26 Aug 2026 08:33:02 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id C078411C7AC7E; Wed, 26 Aug 2026 10:32:59 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1787733181; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=6vGE5JHlVYso6AMZWaa842fc1ufJ/3MtKzaefu5tSXI=; b=dZlTQO5FolvC82YRcRRYZQXn8nIZ1jivHBjx8dV+hindmX7G0mU+4LMzggv4cwzsh/gQAl cTY+ySIVJuaUTp1B/oMDpNHMleNzW6E3vdlBdOsIdMeXxcQaI9ja4vTCy4Jed/Z0wgDYk2 oOyggECfj/iALr+2liHCnFh1Ae0r/GEqeUwAtWW+coE2oCWZ3gH6dARE5ZS0Y1X/PkQMaj EDKirwcY5oJD6waZJ5q3EyozwXDd0rm/jaGALdic79zemGZ7PsZ4U97JSNlpbm0THSmBUH m22OHHcBdkTNU+3bdSYCjmVY6/B3O6l0h//sxjhcvjHJMc1ij92qdr2NbigvZg== From: Herve Codina To: David Gibson , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Laurent Pinchart , David Lechner , Ayush Singh , Geert Uytterhoeven , devicetree-compiler@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree-spec@vger.kernel.org, Hui Pu , Ian Ray , Luca Ceresoli , Thomas Petazzoni , Herve Codina Subject: [PATCH v3 11/15] libfdt: Introduce fdt_getprop_by_offset_w() Date: Wed, 26 Aug 2026 10:31:42 +0200 Message-ID: <20260826083146.304291-12-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826083146.304291-1-herve.codina@bootlin.com> References: <20260826083146.304291-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" Future operations, such as handling unknown tags on dtb modifications, need to modify properties retrieved by their offset. fdt_getprop_by_offset() already exists to get a preperty by its offset but the property returned is read-only. A writable returned property is needed. Fill the lack and introduce fdt_getprop_by_offset_w(), the write enabled variant of fdt_getprop_by_offset(). Add also its related test. Signed-off-by: Herve Codina --- libfdt/libfdt.h | 6 +++ tests/.gitignore | 1 + tests/Makefile.tests | 2 +- tests/get_prop_offset_w.c | 84 +++++++++++++++++++++++++++++++++++++++ tests/meson.build | 1 + tests/run_tests.sh | 1 + tests/tests.h | 1 + tests/testutils.c | 18 +++++++++ 8 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 tests/get_prop_offset_w.c diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 7a1915a5..82965e32 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -856,6 +856,12 @@ static inline struct fdt_property *fdt_get_property_w(= void *fdt, int nodeoffset, #ifndef SWIG /* This function is not useful in Python */ const void *fdt_getprop_by_offset(const void *fdt, int offset, const char **namep, int *lenp); +static inline void *fdt_getprop_by_offset_w(const void *fdt, int offset, + const char **namep, int *lenp) +{ + return (void *)(uintptr_t)fdt_getprop_by_offset(fdt, offset, namep, + lenp); +} #endif =20 /** diff --git a/tests/.gitignore b/tests/.gitignore index 69693129..1091174a 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -30,6 +30,7 @@ tmp.* /get_phandle /getprop /get_prop_offset +/get_prop_offset_w /incbin /integer-expressions /fs_tree1 diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 63e201ae..0d4d399f 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -16,7 +16,7 @@ LIB_TESTS_L =3D get_mem_rsv \ sw_tree1 sw_states \ move_and_save mangle-layout nopulate \ open_pack rw_tree1 rw_oom set_name setprop del_property del_node \ - appendprop1 appendprop2 propname_escapes \ + appendprop1 appendprop2 propname_escapes get_prop_offset_w \ string_escapes references path-references phandle_format \ boot-cpuid incbin relref_merge \ extra-terminating-null \ diff --git a/tests/get_prop_offset_w.c b/tests/get_prop_offset_w.c new file mode 100644 index 00000000..dbfa5dd7 --- /dev/null +++ b/tests/get_prop_offset_w.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_getprop_by_offset_w() + * Copyright (C) 2026 Bootlin. + */ + +#include +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +#define SPACE 65536 + +int main(int argc, char *argv[]) +{ + const void *exp_val; + const char *name; + char *modif_val; + void *propval; + int proplen; + int exp_len; + int poffset; + void *fdt; + void *buf; + int err; + + test_init(argc, argv); + fdt =3D load_blob_arg(argc, argv); + + buf =3D xmalloc(SPACE); + + err =3D fdt_open_into(fdt, buf, SPACE); + if (err) + FAIL("fdt_open_into(): %s", fdt_strerror(err)); + + free(fdt); + fdt =3D buf; + + /* Retrieve the offset of the 'prop-str' property */ + poffset =3D get_poffset(fdt, 0, "prop-str"); + if (poffset < 0) + FAIL("Property 'prop-str' not found"); + + /* Get the property value for modification */ + propval =3D fdt_getprop_by_offset_w(fdt, poffset, &name, &proplen); + if (!propval) + FAIL("fdt_getprop_by_offset_w(%d): %s", poffset, + fdt_strerror(proplen)); + + /* Check original values */ + if (strcmp(name, "prop-str")) + FAIL("Name mismatch : %s instead of prop-str", name); + + exp_len =3D strlen(TEST_STRING_1) + 1; + if (proplen !=3D exp_len) + FAIL("Original size mismatch on property \"%s\": %d instead of %d", + name, proplen, exp_len); + + exp_val =3D TEST_STRING_1; + if (memcmp(exp_val, propval, exp_len)) + FAIL("Original data mismatch on property \"%s\"", name); + + if (exp_len < 4) + CONFIG("Property \"%s\" should be at least 4 bytes", name); + + /* Modify the property value */ + modif_val =3D xmalloc(proplen); + memcpy(modif_val, propval, proplen); + modif_val[1] =3D (modif_val[1] !=3D 'A') ? 'A' : 'a'; + modif_val[3] =3D (modif_val[3] !=3D 'B') ? 'B' : 'b'; + memcpy(propval, modif_val, exp_len); + + /* Check that the modified value is taken into account */ + if (!check_get_prop_offset(fdt, poffset, "prop-str", exp_len, modif_val)) + FAIL("Modified property 'prop-str' not found"); + + PASS(); +} diff --git a/tests/meson.build b/tests/meson.build index 779e6bc7..dae6a941 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -50,6 +50,7 @@ tests =3D [ 'get_path', 'get_phandle', 'get_prop_offset', + 'get_prop_offset_w', 'get_next_tag_invalid_prop_len', 'getprop', 'incbin', diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 225c22f8..419a24d8 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -419,6 +419,7 @@ tree1_tests_rw () { run_test setprop $TREE run_test del_property $TREE run_test del_node $TREE + run_test get_prop_offset_w $TREE } =20 check_tests () { diff --git a/tests/tests.h b/tests/tests.h index 578d8c1a..37ed3394 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -109,6 +109,7 @@ const void *check_get_prop_offset(void *fdt, int poffse= t, const char *in_name, const void *check_getprop_addrrange(void *fdt, int parent, int nodeoffset, const char *name, int num); =20 +int get_poffset(void *fdt, int nodeoffset, const char *propname); int nodename_eq(const char *s1, const char *s2); void vg_prepare_blob(void *fdt, size_t bufsize); void *load_blob(const char *filename); diff --git a/tests/testutils.c b/tests/testutils.c index 6d69e872..d35a1978 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -230,6 +230,24 @@ const void *check_getprop_addrrange(void *fdt, int par= ent, int nodeoffset, return propval; } =20 +int get_poffset(void *fdt, int nodeoffset, const char *propname) +{ + const char *name; + int poffset; + + fdt_for_each_property_offset(poffset, fdt, nodeoffset) { + if (fdt_getprop_by_offset(fdt, poffset, &name, NULL)) { + if (!strcmp(name, propname)) + return poffset; + } + } + + if (poffset < 0) + return poffset; + + return -FDT_ERR_NOTFOUND; +} + int nodename_eq(const char *s1, const char *s2) { int len =3D strlen(s2); --=20 2.55.0 From nobody Mon Sep 28 04:49:01 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 056B23BD651; Wed, 26 Aug 2026 08:33:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733187; cv=none; b=CE3uxMLCjqyUKu7bbZPZbR+j53AY3qFLb3jRpBqA9kas591QYxImoPYNMUi30G5dRik5+imK+0bIvb2v7dtFPXfMZyrEYZqKhPFva3Z9kQmSaTsOycPR96U3lmyjQY2ImRBLkH6NmvolgZMWjOIVFdhoFnXidROojs38XQpTu3U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733187; c=relaxed/simple; bh=W9mg9jyRvlVpHVLF9f2CJrNNCtoo1iqZVPGSzFepCow=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZCtZCoPbV3VPhZB6EvhrCN3TGlAzbu7or5GYW/h/eLKEBBv4osAtFlrsKIeViYEwSdZp5i9Yv4ZkfqOFGaD5Yak4VALhzp/IZDH8mGxSFkBXho3MJbpqvFCbCDVT/+4ib+sFJPw97BoiOCCOGOuF3shtJNguST3jb+lVDxccJpU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=YrNRMr9C; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="YrNRMr9C" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 72F364E413C1; Wed, 26 Aug 2026 08:33:04 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 4697F604EC; Wed, 26 Aug 2026 08:33:04 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id C722611C7AC80; Wed, 26 Aug 2026 10:33:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1787733183; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=JRzxNI/yZN/r4qaoRVBp6jb+DAZQ50f2Ttu1ACcCaw4=; b=YrNRMr9C2sPO/1j2CjLdZPdhXAmb9vXhmPP73VxhyuzPN0Ry/vAsCqoSscuFKJWFkZogbx wU9wFsZMn4G1azxnmfHgSRk0CWbU4eSojJI1KPiXi7ByfgA4cuvBIDBu0TeS1GAEivZj8K idvmM3xpvH9onJ1Sn+3epBmra6jkgdZV/AiqlXkb0YqaTsJsK40tTMrp5tHEu8/rxkUdnw qMHqnXU+tDi81h89ZgBHdkuSBJ4GUWaejtJhDavpy7oIdRxGLLzkyrWIXsmfgPuni2FXP7 J0xzr/VG5fMdwZoKWISxoqsiAFQAZEexB7bZzZEVk7GTeKVUzRq17N8DnEHJrw== From: Herve Codina To: David Gibson , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Laurent Pinchart , David Lechner , Ayush Singh , Geert Uytterhoeven , devicetree-compiler@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree-spec@vger.kernel.org, Hui Pu , Ian Ray , Luca Ceresoli , Thomas Petazzoni , Herve Codina Subject: [PATCH v3 12/15] libfdt: Introduce fdt_getprop_offset_namelen() Date: Wed, 26 Aug 2026 10:31:43 +0200 Message-ID: <20260826083146.304291-13-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826083146.304291-1-herve.codina@bootlin.com> References: <20260826083146.304291-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" Future operations, such as handling unknown tags on dtb modifications, need to get an offset to a property based on the node offset and the property name. Several function exists to get a property based on the node offset and the property name but none of them allows to get the property offset. Fill the lack and introduce fdt_getprop_offset_namelen() and its simple variant fdt_getprop_offset(). Signed-off-by: Herve Codina --- libfdt/fdt_ro.c | 13 +++++++++++++ libfdt/libfdt_internal.h | 8 ++++++++ 2 files changed, 21 insertions(+) diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 856c62f1..50c0a8bc 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -536,6 +536,19 @@ const void *fdt_getprop(const void *fdt, int nodeoffse= t, return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); } =20 +int fdt_getprop_offset_namelen(const void *fdt, int nodeoffset, + const char *name, int namelen) +{ + const struct fdt_property *prop; + int lenp, offset; + + prop =3D fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, + &lenp, &offset); + if (!prop) + return lenp; + return offset; +} + uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) { const fdt32_t *php; diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 3c83d9a7..e3923629 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -26,6 +26,14 @@ uint32_t fdt_next_tag_(const void *fdt, int startoffset,= int *nextoffset, int fdt_check_node_offset_(const void *fdt, int offset); int fdt_check_prop_offset_(const void *fdt, int offset); =20 +int fdt_getprop_offset_namelen(const void *fdt, int nodeoffset, + const char *name, int namelen); +static inline int fdt_getprop_offset(const void *fdt, int nodeoffset, + const char *name) +{ + return fdt_getprop_offset_namelen(fdt, nodeoffset, name, strlen(name)); +} + const char *fdt_find_string_len_(const char *strtab, int tabsize, const ch= ar *s, int s_len); static inline const char *fdt_find_string_(const char *strtab, int tabsize, --=20 2.55.0 From nobody Mon Sep 28 04:49:01 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ED1233B7776; Wed, 26 Aug 2026 08:33:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733189; cv=none; b=YObUEHR8mZps2w960WTbncmXTzeEuJihiayqqWmaVmoDRZOYiPv/A4ox56MLDHqcliaxMc27QLQX5aY0pKcxngOiBIJX/OnreWTZFRn5yplW7t1PwFKh3NeW+VL6cteGXdQLXpQnEn/3CgGnMw354i2dJ5NriaAdORepwaPdlHI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733189; c=relaxed/simple; bh=l5aizd0aNPlQXbHAGyKGkXH/oCilS0i0zb3Qqb0JRBU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XOgF5Y0D1A9gNf6ORkx41FwnRuq9bwzNw7sWElLZNnY3Hf/gfC28NO0IIFqToO/Oo7nNBcWM3U/avI6Se83Q8XMxj7zL6PJMJIX2EvUvfjN0Kvk3fjAdLTB0kRuW4x7TPoU/OTbLI0ovBulTPvg31giThlsNrgI2WQCljK3bpC8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=vczcrhIR; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="vczcrhIR" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 9EDF74E413C6; Wed, 26 Aug 2026 08:33:06 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 72842604EC; Wed, 26 Aug 2026 08:33:06 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id D222411C7AC82; Wed, 26 Aug 2026 10:33:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1787733185; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=Pb7tD7MCAsE6s+ppctJ9MSYDTHi603VmMwnW5c1tQJk=; b=vczcrhIR/oux8dWgctN6CQQwHni80XqH4l8jE/DgZ/+WnwvzqPPrlCzSM9sDjnhRYBp7wb zxcnjEd5dg4eqU4zJCtc6gYHwtqkdz1q9vdJAEjGx5ZtALUw/f4tNQckR/b4dL7ggVZtjY rT5PVZ1JmZqjMuve4BEJdDic/EVkb+YJIk9PSFeULJE3DLEhIQoR5DngT/Aoes28r8RK1B 5zKrrr1IBhXWMyDBxyc8C+/njpcenkYMHHz3zHSHZT5vfmoaqjnTSlDkXiaW7xWfRoE9ie QOFL8Daa+pDKGNMuvaLPGVimY92oKqBlJPq/sYLZn0dqa2Dzck8V2Ak1mpvHww== From: Herve Codina To: David Gibson , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Laurent Pinchart , David Lechner , Ayush Singh , Geert Uytterhoeven , devicetree-compiler@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree-spec@vger.kernel.org, Hui Pu , Ian Ray , Luca Ceresoli , Thomas Petazzoni , Herve Codina Subject: [PATCH v3 13/15] tests: Add wip_func utility Date: Wed, 26 Aug 2026 10:31:44 +0200 Message-ID: <20260826083146.304291-14-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826083146.304291-1-herve.codina@bootlin.com> References: <20260826083146.304291-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" wip_func is a test utility allowing to wrap the write inplace functions. It allows to create tests with custom wip write sequence. Also the modified dtb is saved allowing to perform later checks on this modified dtb. Signed-off-by: Herve Codina --- tests/Makefile.tests | 3 +- tests/meson.build | 1 + tests/wip_func.c | 127 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 tests/wip_func.c diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 0d4d399f..a71c4cbf 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -31,7 +31,8 @@ LIB_TESTS_L =3D get_mem_rsv \ check_path check_header check_full \ fs_tree1 \ truncated_property truncated_string \ - truncated_memrsv unterminated_memrsv + truncated_memrsv unterminated_memrsv \ + wip_func LIB_TESTS =3D $(LIB_TESTS_L:%=3D$(TESTS_PREFIX)%) =20 ifneq ($(STATIC_BUILD),1) diff --git a/tests/meson.build b/tests/meson.build index dae6a941..e7a88936 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -96,6 +96,7 @@ tests =3D [ 'truncated_string', 'unterminated_memrsv', 'utilfdt_test', + 'wip_func', ] =20 test_deps =3D [testutil_dep, util_dep, libfdt_dep] diff --git a/tests/wip_func.c b/tests/wip_func.c new file mode 100644 index 00000000..3becc4f1 --- /dev/null +++ b/tests/wip_func.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * libfdt - Flat Device Tree manipulation + * Wrapper wip functions family + * Copyright (C) 2026 Herve Codina, Bootlin. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "tests.h" + +struct args { + char *dtb_path; + enum { + NOP_NODE, + NOP_PROP, + SET_PROP, + } op; + char *node_path; + char *prop_name; + int index; + char *value; +}; + +const char *usage_txt =3D "Usage:\n" + " - wip_func nop_node \n" + " - wip_func nop_prop \n" + " - wip_func set_prop \n" + ; + +static void parse_args(struct args *args, int argc, char *argv[]) +{ + char *endptr; + + memset(args, 0, sizeof(*args)); + + if (argc < 3) + goto fail; + + args->dtb_path =3D argv[1]; + + if (!strcmp(argv[2], "nop_node")) { + args->op =3D NOP_NODE; + if (argc !=3D 4) + goto fail; + args->node_path =3D argv[3]; + } else if (!strcmp(argv[2], "nop_prop")) { + args->op =3D NOP_PROP; + if (argc !=3D 5) + goto fail; + args->node_path =3D argv[3]; + args->prop_name =3D argv[4]; + } else if (!strcmp(argv[2], "set_prop")) { + args->op =3D SET_PROP; + if (argc !=3D 7) + goto fail; + args->node_path =3D argv[3]; + args->prop_name =3D argv[4]; + errno =3D 0; + args->index =3D strtol(argv[5], &endptr, 0); + if (*endptr !=3D '\0' || errno) + goto fail; + args->value =3D argv[6]; + } else { + goto fail; + } + + return; + +fail: + CONFIG("%s\n", usage_txt); +} + +int main(int argc, char *argv[]) +{ + struct args args; + void *fdt; + int node; + int err; + + test_init(argc, argv); + + parse_args(&args, argc, argv); + + fdt =3D load_blob(args.dtb_path); + + node =3D fdt_path_offset(fdt, args.node_path); + if (node < 0) + FAIL("Fail to get '%s': %s", args.node_path, fdt_strerror(node)); + + switch (args.op) { + case NOP_NODE: + err =3D fdt_nop_node(fdt, node); + if (err) + FAIL("fdt_nop_node('%s'): %s", args.node_path, fdt_strerror(err)); + break; + + case NOP_PROP: + err =3D fdt_nop_property(fdt, node, args.prop_name); + if (err) + FAIL("fdt_nop_node('%s', '%s'): %s", args.node_path, + args.prop_name, fdt_strerror(err)); + break; + + case SET_PROP: + err =3D fdt_setprop_inplace_namelen_partial(fdt, node, + args.prop_name, strlen(args.prop_name), args.index, + args.value, strlen(args.value) + 1); + if (err) + FAIL("fdt_setprop_inplace_namelen_partial('%s', '%s', %d, \"%s\"): %s", + args.node_path, args.prop_name, args.index, + args.value, fdt_strerror(err)); + break; + } + + save_blob(args.dtb_path, fdt); + + PASS(); +} --=20 2.55.0 From nobody Mon Sep 28 04:49:01 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2E8923BED06; Wed, 26 Aug 2026 08:33:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733192; cv=none; b=G6kzwomEybtcZg+3zalbpbGotaGotxPDg8uuUzjm7zPTuPg9HtKzqgSqjXoCCQtWie1LkWZKxgCTpJetNTlE8LdsF1WD4788/FQjDAQUjnLqoclFss8WxpYZL3csCTIfA7dXS2nCo/1lfR8s/J9Hh3TbnY7fTnnZYsNIFKv2TNw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733192; c=relaxed/simple; bh=Y45M0QfxTOT6Od7P03ZxgLhowajbdMXNWUmNq65PXtM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=smnJaa2fdCiFYmEmdo2oYa/CKXY/7FnaOIPw9CsFXXbEBNPFjSBCmAb4vCrq9V12LQj53J/n1FV1bFlwV/ofzUFLEHOQfD/vZ2RZcZsgHg8t4Y75YUkR9qQIpMh7zxTZ9q+pRGLtAt8VmnjzbiBusnRVdgKsU76cOJ8ZxBk7PfI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=pNRNZ0HS; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="pNRNZ0HS" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id B04254E413C1; Wed, 26 Aug 2026 08:33:08 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 840B1604EC; Wed, 26 Aug 2026 08:33:08 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id D022711C7AC83; Wed, 26 Aug 2026 10:33:05 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1787733187; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=df6wW/P50wnQy16r3BTZ8VpoEcM/jXRMcu40sgw4tww=; b=pNRNZ0HSmpKB5UYtayvFIo4jPh9f90aqbxuslWrYFYZVYe0g1L44ARvgpDl5zB8WuN+Y9H x/tQ3gotyMfqzpKZj0O3jP37JAuY2+tsedxJkRmCzOADPZKgh77RZe/ZmQBPOBWlEvmTGh nPYjf8enSggZP47TvK94WNu9InJtnjEvVYM8ZJyB+YHOty09jr1NZuL9Z257Je7CYsUee9 2xeYSkepHhPs5AV+jxzdpt3dTxbuI4n7aaOw1PjZTjTZwHF0Q4lwVBU5/rcy8Fv2Zw5YZN iouuWiJhC/4y7YPwqFEP8f2EYaG/iNvgPuM2xkPUojBJN58ZTl50nBGunux4CQ== From: Herve Codina To: David Gibson , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Laurent Pinchart , David Lechner , Ayush Singh , Geert Uytterhoeven , devicetree-compiler@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree-spec@vger.kernel.org, Hui Pu , Ian Ray , Luca Ceresoli , Thomas Petazzoni , Herve Codina Subject: [PATCH v3 14/15] libfdt: Handle unknown tags on dtb modifications Date: Wed, 26 Aug 2026 10:31:45 +0200 Message-ID: <20260826083146.304291-15-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826083146.304291-1-herve.codina@bootlin.com> References: <20260826083146.304291-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" The structured tag value definition introduced recently gives the ability to ignore unknown tags without any error. When the dtb is modified those unknown tags have to be taken into account. First, depending on the unknown tag location, the item associated with the tag is identified: - An unknown tag located just after a FDT_BEGIN_NODE is related to the node. - An unknown tag located just after a FDT_PROP is related to the property. - An unknown tag out of any node (i.e located before the first FDT_BEGIN_NODE or after the last FDT_END_NODE) is a global tag related to the dtb itself. Then, if we are allowed to write a dtb containing unknown tags, the following rules are used: - When a property is modified, tags related to this property are removed and the dtb version is downgraded. - When a property is removed, tags related to this property are obviously removed. The dtb version is kept unchanged. - When a property or a node is added, obviously no unknown tags are added and the dtb version is kept unchanged. - When a node is removed, tags related to this node are obviously removed. The dtb version is kept unchanged. - Adding, removing or modifying a property is not considered as a node modification and so, those operations have no impacts on unknown tags related to the node. Those node related tags are kept unchanged. - The only modification considered as a node modification is setting its name. We consider that this operation has no impact on tags related to the node. Here also, those node related tags and the dtb version are kept unchanged. - Global (dtb related) unknown tags are kept unchanged regardless the modification done. Implement those rules when a dtb is modified. Signed-off-by: Herve Codina Reviewed-by: Luca Ceresoli --- libfdt/fdt_rw.c | 129 +++++++++++++++++- libfdt/fdt_wip.c | 28 +++- libfdt/libfdt_internal.h | 3 + tests/run_tests.sh | 78 +++++++++++ ...own_tags_can_skip.fdtput.test.dtb.0.expect | 31 +++++ ...own_tags_can_skip.fdtput.test.dtb.1.expect | 35 +++++ ...own_tags_can_skip.fdtput.test.dtb.2.expect | 33 +++++ ...own_tags_can_skip.fdtput.test.dtb.3.expect | 35 +++++ ...own_tags_can_skip.fdtput.test.dtb.4.expect | 34 +++++ ...own_tags_can_skip.fdtput.test.dtb.5.expect | 32 +++++ ...own_tags_can_skip.fdtput.test.dtb.6.expect | 27 ++++ ...nknown_tags_can_skip.wip.test.dtb.0.expect | 31 +++++ ...nknown_tags_can_skip.wip.test.dtb.1.expect | 35 +++++ ...nknown_tags_can_skip.wip.test.dtb.2.expect | 37 +++++ ...nknown_tags_can_skip.wip.test.dtb.3.expect | 38 ++++++ 15 files changed, 603 insertions(+), 3 deletions(-) create mode 100644 tests/unknown_tags_can_skip.fdtput.test.dtb.0.expect create mode 100644 tests/unknown_tags_can_skip.fdtput.test.dtb.1.expect create mode 100644 tests/unknown_tags_can_skip.fdtput.test.dtb.2.expect create mode 100644 tests/unknown_tags_can_skip.fdtput.test.dtb.3.expect create mode 100644 tests/unknown_tags_can_skip.fdtput.test.dtb.4.expect create mode 100644 tests/unknown_tags_can_skip.fdtput.test.dtb.5.expect create mode 100644 tests/unknown_tags_can_skip.fdtput.test.dtb.6.expect create mode 100644 tests/unknown_tags_can_skip.wip.test.dtb.0.expect create mode 100644 tests/unknown_tags_can_skip.wip.test.dtb.1.expect create mode 100644 tests/unknown_tags_can_skip.wip.test.dtb.2.expect create mode 100644 tests/unknown_tags_can_skip.wip.test.dtb.3.expect diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index ceef49b8..87776609 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -197,10 +197,69 @@ int fdt_del_mem_rsv(void *fdt, int n) return fdt_splice_mem_rsv_(fdt, re, 1, 0); } =20 +static void fdt_nopify_area(void *fdt, int start_offset, int next_offset) +{ + int count =3D (next_offset - start_offset) / sizeof(fdt32_t); + fdt32_t fdt32_nop =3D cpu_to_fdt32(FDT_NOP); + fdt32_t *ptr; + + ptr =3D fdt_offset_ptr_w_(fdt, start_offset); + while (count--) + *(ptr++) =3D fdt32_nop; +}; + +int fdt_prop_remove_unknown_tags(void *fdt, bool force_inplace, + int prop_offset, bool downgrade_version) +{ + int nextoffset, offset; + bool is_unknown; + uint32_t tag; + + /* + * Only inplace using nopify is supported even if we could use an other + * method involving splices if force_inplace is set to false. + */ + + tag =3D fdt_next_tag(fdt, prop_offset, &nextoffset); + if (tag =3D=3D FDT_END) + return nextoffset; + + /* + * Look at all tags related to the current property. I.e. tags after the + * current property and before either the next property, a sub-node or + * the end of current node + */ + do { + offset =3D nextoffset; + tag =3D fdt_next_tag_(fdt, offset, &nextoffset, &is_unknown); + if (tag =3D=3D FDT_END) + return nextoffset; + + /* + * Unknown tags are returned as NOP. Force FDT_NOP to be really + * present in the area to remove the unknown tag and its related + * data. Also, as a tag is removed, downgrade the dtb version + * if asked for. + */ + if (tag =3D=3D FDT_NOP) { + if (is_unknown) { + if (downgrade_version) + fdt_downgrade_version(fdt); + fdt_nopify_area(fdt, offset, nextoffset); + } + } + + } while ((tag !=3D FDT_PROP) && (tag !=3D FDT_BEGIN_NODE) && + (tag !=3D FDT_END_NODE)); + + return 0; +} + static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name, int namelen, int len, struct fdt_property **prop) { + int prop_offset; int oldlen; int err; =20 @@ -209,6 +268,15 @@ static int fdt_resize_property_(void *fdt, int nodeoff= set, if (!*prop) return oldlen; =20 + /* + * The property is resized. Remove possible unknown tags related to the + * property downgrading the dtb version. + */ + prop_offset =3D fdt_ptr_offset_(fdt, *prop); + err =3D fdt_prop_remove_unknown_tags(fdt, false, prop_offset, true); + if (err) + return err; + if ((err =3D fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), FDT_TAGALIGN(len)))) return err; @@ -217,6 +285,29 @@ static int fdt_resize_property_(void *fdt, int nodeoff= set, return 0; } =20 +static int fdt_node_skip_unknown_tags(void *fdt, int next) +{ + int nextoffset =3D next; + int offset; + uint32_t tag; + + /* + * Skip all tags related to the current node. I.e. tags after the + * current node and before either the next property, a sub-node or the + * end of current node. + */ + do { + offset =3D nextoffset; + tag =3D fdt_next_tag(fdt, offset, &nextoffset); + if (tag =3D=3D FDT_END) + return nextoffset; + + } while ((tag !=3D FDT_PROP) && (tag !=3D FDT_BEGIN_NODE) && + (tag !=3D FDT_END_NODE)); + + return offset; +} + static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, int namelen, int len, struct fdt_property **prop) { @@ -235,6 +326,15 @@ static int fdt_add_property_(void *fdt, int nodeoffset= , const char *name, if ((nextoffset =3D fdt_check_node_offset_(fdt, nodeoffset)) < 0) return nextoffset; =20 + /* + * nextoffset it at the first tag after the node. + * Skip possible unknown tags related to the node in order to add the + * property after those tags. + */ + nextoffset =3D fdt_node_skip_unknown_tags(fdt, nextoffset); + if (nextoffset < 0) + return nextoffset; + namestroff =3D fdt_find_add_string_(fdt, name, namelen, &allocated); if (namestroff < 0) return namestroff; @@ -333,11 +433,22 @@ int fdt_appendprop(void *fdt, int nodeoffset, const c= har *name, { struct fdt_property *prop; int err, oldlen, newlen; + int prop_offset; =20 FDT_RW_PROBE(fdt); =20 prop =3D fdt_get_property_w(fdt, nodeoffset, name, &oldlen); if (prop) { + /* + * The property is going to be modified. Remove possible unknown + * tags related to this property downgrading the dtb version. + */ + prop_offset =3D fdt_ptr_offset_(fdt, prop); + err =3D fdt_prop_remove_unknown_tags(fdt, false, prop_offset, + true); + if (err) + return err; + newlen =3D len + oldlen; err =3D fdt_splice_struct_(fdt, prop->data, FDT_TAGALIGN(oldlen), @@ -360,6 +471,8 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *= name) { struct fdt_property *prop; int len, proplen; + int prop_offset; + int err; =20 FDT_RW_PROBE(fdt); =20 @@ -367,6 +480,15 @@ int fdt_delprop(void *fdt, int nodeoffset, const char = *name) if (!prop) return len; =20 + /* + * The property is going to be removed. Remove also possible unknown + * tags related to this property. Keep the dtb version unchanged. + */ + prop_offset =3D fdt_ptr_offset_(fdt, prop); + err =3D fdt_prop_remove_unknown_tags(fdt, false, prop_offset, false); + if (err) + return err; + proplen =3D sizeof(*prop) + FDT_TAGALIGN(len); return fdt_splice_struct_(fdt, prop, proplen, 0); } @@ -395,7 +517,12 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffse= t, else if (offset !=3D -FDT_ERR_NOTFOUND) return offset; =20 - /* Try to place the new node after the parent's properties */ + /* + * Try to place the new node after the parent's properties and unknown + * tags related to those properties. + * Unknown tags are reported as FDT_NOP tags by fdt_next_tag. + * Skipping FDT_NOP tags will correctly skip unknown tags. + */ tag =3D fdt_next_tag(fdt, parentoffset, &nextoffset); /* the fdt_subnode_offset_namelen() should ensure this never hits */ if (!can_assume(LIBFDT_FLAWLESS) && (tag !=3D FDT_BEGIN_NODE)) diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c index c2d7566a..7ca3ffbc 100644 --- a/libfdt/fdt_wip.c +++ b/libfdt/fdt_wip.c @@ -15,17 +15,30 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int = nodeoffset, uint32_t idx, const void *val, int len) { + int prop_offset; void *propval; int proplen; + int err; =20 - propval =3D fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen, - &proplen); + prop_offset =3D fdt_getprop_offset_namelen(fdt, nodeoffset, name, namelen= ); + if (prop_offset < 0) + return prop_offset; + + propval =3D fdt_getprop_by_offset_w(fdt, prop_offset, NULL, &proplen); if (!propval) return proplen; =20 if ((unsigned)proplen < (len + idx)) return -FDT_ERR_NOSPACE; =20 + /* + * Remove unknown tags related to the property downgrading the dtb + * version. + */ + err =3D fdt_prop_remove_unknown_tags(fdt, true, prop_offset, true); + if (err) + return err; + memcpy((char *)propval + idx, val, len); return 0; } @@ -59,12 +72,23 @@ static void fdt_nop_region_(void *start, int len) int fdt_nop_property(void *fdt, int nodeoffset, const char *name) { struct fdt_property *prop; + int prop_offset; int len; + int err; =20 prop =3D fdt_get_property_w(fdt, nodeoffset, name, &len); if (!prop) return len; =20 + /* + * The property is going to be removed (nopified). Remove unknown tags + * related to this property. Keep the dtb version unchanged. + */ + prop_offset =3D fdt_ptr_offset_(fdt, prop); + err =3D fdt_prop_remove_unknown_tags(fdt, true, prop_offset, false); + if (err) + return err; + fdt_nop_region_(prop, len + sizeof(*prop)); =20 return 0; diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index e3923629..ce128fda 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -26,6 +26,9 @@ uint32_t fdt_next_tag_(const void *fdt, int startoffset, = int *nextoffset, int fdt_check_node_offset_(const void *fdt, int offset); int fdt_check_prop_offset_(const void *fdt, int offset); =20 +int fdt_prop_remove_unknown_tags(void *fdt, bool force_inplace, + int prop_offset, bool downgrade_version); + int fdt_getprop_offset_namelen(const void *fdt, int nodeoffset, const char *name, int namelen); static inline int fdt_getprop_offset(const void *fdt, int nodeoffset, diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 419a24d8..980ed6a0 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -586,6 +586,34 @@ libfdt_tests () { unknown_tags_no_skip.dtb; do run_test check_full -n $bad done + + # Check inplace modification with "unknown" tags that can be skipped + dtb=3Dunknown_tags_can_skip.wip.test.dtb + cp unknown_tags_can_skip.dtb $dtb + base_run_test wrap_fdtdump $dtb $dtb.0.out + # Remove unneeded header fields (keep those related to versions) + sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.0.out + base_run_test check_diff $dtb.0.out "$SRCDIR/$dtb.0.expect" + + run_test wip_func $dtb set_prop / prop-str 0 "vwxy" + base_run_test wrap_fdtdump $dtb $dtb.1.out + # Remove unneeded header fields (keep those related to versions) + sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.1.out + base_run_test check_diff $dtb.1.out "$SRCDIR/$dtb.1.expect" + + cp unknown_tags_can_skip.dtb $dtb + run_test wip_func $dtb nop_prop /subnode2 prop-int1 + base_run_test wrap_fdtdump $dtb $dtb.2.out + # Remove unneeded header fields (keep those related to versions) + sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.2.out + base_run_test check_diff $dtb.2.out "$SRCDIR/$dtb.2.expect" + + cp unknown_tags_can_skip.dtb $dtb + run_test wip_func $dtb nop_node /subnode2/subsubnode + base_run_test wrap_fdtdump $dtb $dtb.3.out + # Remove unneeded header fields (keep those related to versions) + sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.3.out + base_run_test check_diff $dtb.3.out "$SRCDIR/$dtb.3.expect" } =20 dtc_tests () { @@ -1045,6 +1073,56 @@ fdtput_tests () { run_wrap_error_test $DTPUT $dtb -d /chosen non-existent-prop =20 # TODO: Add tests for verbose mode? + + # Modify a dtb containing some "unknown" tags that can be skipped + dtb=3Dunknown_tags_can_skip.fdtput.test.dtb + cp unknown_tags_can_skip.dtb $dtb + base_run_test wrap_fdtdump $dtb $dtb.0.out + # Remove unneeded header fields (keep those related to versions) + sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.0.out + base_run_test check_diff $dtb.0.out "$SRCDIR/$dtb.0.expect" + + run_fdtput_test "vwxyz" $dtb / prop-str -ts "vwxyz" + base_run_test wrap_fdtdump $dtb $dtb.1.out + # Remove unneeded header fields (keep those related to versions) + sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.1.out + base_run_test check_diff $dtb.1.out "$SRCDIR/$dtb.1.expect" + + cp unknown_tags_can_skip.dtb $dtb + run_wrap_test $DTPUT $dtb -c /tst-fdtput + base_run_test wrap_fdtdump $dtb $dtb.2.out + # Remove unneeded header fields (keep those related to versions) + sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.2.out + base_run_test check_diff $dtb.2.out "$SRCDIR/$dtb.2.expect" + run_wrap_test $DTPUT $dtb -c /tst-fdtput/n1 /tst-fdtput/n2 /tst-fdtput= /n3 + run_wrap_test $DTPUT $dtb -r /tst-fdtput/n1 /tst-fdtput/n3 + run_fdtget_test "n2" $dtb -l /tst-fdtput + base_run_test wrap_fdtdump $dtb $dtb.3.out + # Remove unneeded header fields (keep those related to versions) + sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.3.out + base_run_test check_diff $dtb.3.out "$SRCDIR/$dtb.3.expect" + + cp unknown_tags_can_skip.dtb $dtb + run_wrap_test $DTPUT $dtb -d / prop-str + run_fdtget_test "prop-int" $dtb -p / + base_run_test wrap_fdtdump $dtb $dtb.4.out + # Remove unneeded header fields (keep those related to versions) + sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.4.out + base_run_test check_diff $dtb.4.out "$SRCDIR/$dtb.4.expect" + + cp unknown_tags_can_skip.dtb $dtb + run_wrap_test $DTPUT $dtb /subnode2 prop-tst-fdtput -ts "Test fdtput" + base_run_test wrap_fdtdump $dtb $dtb.5.out + # Remove unneeded header fields (keep those related to versions) + sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.5.out + base_run_test check_diff $dtb.5.out "$SRCDIR/$dtb.5.expect" + + cp unknown_tags_can_skip.dtb $dtb + run_wrap_test $DTPUT $dtb -r /subnode2/subsubnode + base_run_test wrap_fdtdump $dtb $dtb.6.out + # Remove unneeded header fields (keep those related to versions) + sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.6.out + base_run_test check_diff $dtb.6.out "$SRCDIR/$dtb.6.expect" } =20 utilfdt_tests () { diff --git a/tests/unknown_tags_can_skip.fdtput.test.dtb.0.expect b/tests/u= nknown_tags_can_skip.fdtput.test.dtb.0.expect new file mode 100644 index 00000000..75883593 --- /dev/null +++ b/tests/unknown_tags_can_skip.fdtput.test.dtb.0.expect @@ -0,0 +1,31 @@ +/dts-v1/; +// version: 4294967295 +// last_comp_version: 16 + +// Unknown tag ignored: 0xd0000000, data len 4 00000001 +/ { + // Unknown tag ignored: 0xc0000000, data len 0 + prop-int =3D <0x00003201>; + // Unknown tag ignored: 0xd0000000, data len 4 00000110 + prop-str =3D "abcd"; + // Unknown tag ignored: 0xe0000000, data len 8 0000012000000121 + // Unknown tag ignored: 0xf0000000, data len 3 101112 + subnode1 { + prop-int =3D <0x00006401 0x00006402>; + // Unknown tag ignored: 0xc0000000, data len 0 + }; + subnode2 { + // Unknown tag ignored: 0xd0000000, data len 4 00000121 + prop-int1 =3D <0x00064020 0x00064021>; + // Unknown tag ignored: 0xe0000000, data len 8 0000122000001221 + prop-int2 =3D <0x00032022>; + subsubnode { + // Unknown tag ignored: 0xe0000000, data len 8 0000123000001231 + prop-bool; + }; + // Unknown tag ignored: 0xf0000000, data len 3 212223 + }; + // Unknown tag ignored: 0xf0000000, data len 4 31323334 +}; +// Unknown tag ignored: 0xd0000000, data len 4 00000002 +// Unknown tag ignored: 0xf0000000, data len 2 4041 diff --git a/tests/unknown_tags_can_skip.fdtput.test.dtb.1.expect b/tests/u= nknown_tags_can_skip.fdtput.test.dtb.1.expect new file mode 100644 index 00000000..b4d3ae29 --- /dev/null +++ b/tests/unknown_tags_can_skip.fdtput.test.dtb.1.expect @@ -0,0 +1,35 @@ +/dts-v1/; +// version: 17 +// last_comp_version: 16 + +// Unknown tag ignored: 0xd0000000, data len 4 00000001 +/ { + // Unknown tag ignored: 0xc0000000, data len 0 + prop-int =3D <0x00003201>; + // Unknown tag ignored: 0xd0000000, data len 4 00000110 + prop-str =3D "vwxyz"; + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + subnode1 { + prop-int =3D <0x00006401 0x00006402>; + // Unknown tag ignored: 0xc0000000, data len 0 + }; + subnode2 { + // Unknown tag ignored: 0xd0000000, data len 4 00000121 + prop-int1 =3D <0x00064020 0x00064021>; + // Unknown tag ignored: 0xe0000000, data len 8 0000122000001221 + prop-int2 =3D <0x00032022>; + subsubnode { + // Unknown tag ignored: 0xe0000000, data len 8 0000123000001231 + prop-bool; + }; + // Unknown tag ignored: 0xf0000000, data len 3 212223 + }; + // Unknown tag ignored: 0xf0000000, data len 4 31323334 +}; +// Unknown tag ignored: 0xd0000000, data len 4 00000002 +// Unknown tag ignored: 0xf0000000, data len 2 4041 diff --git a/tests/unknown_tags_can_skip.fdtput.test.dtb.2.expect b/tests/u= nknown_tags_can_skip.fdtput.test.dtb.2.expect new file mode 100644 index 00000000..a196bed3 --- /dev/null +++ b/tests/unknown_tags_can_skip.fdtput.test.dtb.2.expect @@ -0,0 +1,33 @@ +/dts-v1/; +// version: 17 +// last_comp_version: 16 + +// Unknown tag ignored: 0xd0000000, data len 4 00000001 +/ { + // Unknown tag ignored: 0xc0000000, data len 0 + prop-int =3D <0x00003201>; + // Unknown tag ignored: 0xd0000000, data len 4 00000110 + prop-str =3D "abcd"; + // Unknown tag ignored: 0xe0000000, data len 8 0000012000000121 + // Unknown tag ignored: 0xf0000000, data len 3 101112 + tst-fdtput { + }; + subnode1 { + prop-int =3D <0x00006401 0x00006402>; + // Unknown tag ignored: 0xc0000000, data len 0 + }; + subnode2 { + // Unknown tag ignored: 0xd0000000, data len 4 00000121 + prop-int1 =3D <0x00064020 0x00064021>; + // Unknown tag ignored: 0xe0000000, data len 8 0000122000001221 + prop-int2 =3D <0x00032022>; + subsubnode { + // Unknown tag ignored: 0xe0000000, data len 8 0000123000001231 + prop-bool; + }; + // Unknown tag ignored: 0xf0000000, data len 3 212223 + }; + // Unknown tag ignored: 0xf0000000, data len 4 31323334 +}; +// Unknown tag ignored: 0xd0000000, data len 4 00000002 +// Unknown tag ignored: 0xf0000000, data len 2 4041 diff --git a/tests/unknown_tags_can_skip.fdtput.test.dtb.3.expect b/tests/u= nknown_tags_can_skip.fdtput.test.dtb.3.expect new file mode 100644 index 00000000..52faa1dd --- /dev/null +++ b/tests/unknown_tags_can_skip.fdtput.test.dtb.3.expect @@ -0,0 +1,35 @@ +/dts-v1/; +// version: 17 +// last_comp_version: 16 + +// Unknown tag ignored: 0xd0000000, data len 4 00000001 +/ { + // Unknown tag ignored: 0xc0000000, data len 0 + prop-int =3D <0x00003201>; + // Unknown tag ignored: 0xd0000000, data len 4 00000110 + prop-str =3D "abcd"; + // Unknown tag ignored: 0xe0000000, data len 8 0000012000000121 + // Unknown tag ignored: 0xf0000000, data len 3 101112 + tst-fdtput { + n2 { + }; + }; + subnode1 { + prop-int =3D <0x00006401 0x00006402>; + // Unknown tag ignored: 0xc0000000, data len 0 + }; + subnode2 { + // Unknown tag ignored: 0xd0000000, data len 4 00000121 + prop-int1 =3D <0x00064020 0x00064021>; + // Unknown tag ignored: 0xe0000000, data len 8 0000122000001221 + prop-int2 =3D <0x00032022>; + subsubnode { + // Unknown tag ignored: 0xe0000000, data len 8 0000123000001231 + prop-bool; + }; + // Unknown tag ignored: 0xf0000000, data len 3 212223 + }; + // Unknown tag ignored: 0xf0000000, data len 4 31323334 +}; +// Unknown tag ignored: 0xd0000000, data len 4 00000002 +// Unknown tag ignored: 0xf0000000, data len 2 4041 diff --git a/tests/unknown_tags_can_skip.fdtput.test.dtb.4.expect b/tests/u= nknown_tags_can_skip.fdtput.test.dtb.4.expect new file mode 100644 index 00000000..1ddc694b --- /dev/null +++ b/tests/unknown_tags_can_skip.fdtput.test.dtb.4.expect @@ -0,0 +1,34 @@ +/dts-v1/; +// version: 17 +// last_comp_version: 16 + +// Unknown tag ignored: 0xd0000000, data len 4 00000001 +/ { + // Unknown tag ignored: 0xc0000000, data len 0 + prop-int =3D <0x00003201>; + // Unknown tag ignored: 0xd0000000, data len 4 00000110 + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + subnode1 { + prop-int =3D <0x00006401 0x00006402>; + // Unknown tag ignored: 0xc0000000, data len 0 + }; + subnode2 { + // Unknown tag ignored: 0xd0000000, data len 4 00000121 + prop-int1 =3D <0x00064020 0x00064021>; + // Unknown tag ignored: 0xe0000000, data len 8 0000122000001221 + prop-int2 =3D <0x00032022>; + subsubnode { + // Unknown tag ignored: 0xe0000000, data len 8 0000123000001231 + prop-bool; + }; + // Unknown tag ignored: 0xf0000000, data len 3 212223 + }; + // Unknown tag ignored: 0xf0000000, data len 4 31323334 +}; +// Unknown tag ignored: 0xd0000000, data len 4 00000002 +// Unknown tag ignored: 0xf0000000, data len 2 4041 diff --git a/tests/unknown_tags_can_skip.fdtput.test.dtb.5.expect b/tests/u= nknown_tags_can_skip.fdtput.test.dtb.5.expect new file mode 100644 index 00000000..f955ac1c --- /dev/null +++ b/tests/unknown_tags_can_skip.fdtput.test.dtb.5.expect @@ -0,0 +1,32 @@ +/dts-v1/; +// version: 17 +// last_comp_version: 16 + +// Unknown tag ignored: 0xd0000000, data len 4 00000001 +/ { + // Unknown tag ignored: 0xc0000000, data len 0 + prop-int =3D <0x00003201>; + // Unknown tag ignored: 0xd0000000, data len 4 00000110 + prop-str =3D "abcd"; + // Unknown tag ignored: 0xe0000000, data len 8 0000012000000121 + // Unknown tag ignored: 0xf0000000, data len 3 101112 + subnode1 { + prop-int =3D <0x00006401 0x00006402>; + // Unknown tag ignored: 0xc0000000, data len 0 + }; + subnode2 { + // Unknown tag ignored: 0xd0000000, data len 4 00000121 + prop-tst-fdtput =3D "Test fdtput"; + prop-int1 =3D <0x00064020 0x00064021>; + // Unknown tag ignored: 0xe0000000, data len 8 0000122000001221 + prop-int2 =3D <0x00032022>; + subsubnode { + // Unknown tag ignored: 0xe0000000, data len 8 0000123000001231 + prop-bool; + }; + // Unknown tag ignored: 0xf0000000, data len 3 212223 + }; + // Unknown tag ignored: 0xf0000000, data len 4 31323334 +}; +// Unknown tag ignored: 0xd0000000, data len 4 00000002 +// Unknown tag ignored: 0xf0000000, data len 2 4041 diff --git a/tests/unknown_tags_can_skip.fdtput.test.dtb.6.expect b/tests/u= nknown_tags_can_skip.fdtput.test.dtb.6.expect new file mode 100644 index 00000000..59247478 --- /dev/null +++ b/tests/unknown_tags_can_skip.fdtput.test.dtb.6.expect @@ -0,0 +1,27 @@ +/dts-v1/; +// version: 17 +// last_comp_version: 16 + +// Unknown tag ignored: 0xd0000000, data len 4 00000001 +/ { + // Unknown tag ignored: 0xc0000000, data len 0 + prop-int =3D <0x00003201>; + // Unknown tag ignored: 0xd0000000, data len 4 00000110 + prop-str =3D "abcd"; + // Unknown tag ignored: 0xe0000000, data len 8 0000012000000121 + // Unknown tag ignored: 0xf0000000, data len 3 101112 + subnode1 { + prop-int =3D <0x00006401 0x00006402>; + // Unknown tag ignored: 0xc0000000, data len 0 + }; + subnode2 { + // Unknown tag ignored: 0xd0000000, data len 4 00000121 + prop-int1 =3D <0x00064020 0x00064021>; + // Unknown tag ignored: 0xe0000000, data len 8 0000122000001221 + prop-int2 =3D <0x00032022>; + // Unknown tag ignored: 0xf0000000, data len 3 212223 + }; + // Unknown tag ignored: 0xf0000000, data len 4 31323334 +}; +// Unknown tag ignored: 0xd0000000, data len 4 00000002 +// Unknown tag ignored: 0xf0000000, data len 2 4041 diff --git a/tests/unknown_tags_can_skip.wip.test.dtb.0.expect b/tests/unkn= own_tags_can_skip.wip.test.dtb.0.expect new file mode 100644 index 00000000..75883593 --- /dev/null +++ b/tests/unknown_tags_can_skip.wip.test.dtb.0.expect @@ -0,0 +1,31 @@ +/dts-v1/; +// version: 4294967295 +// last_comp_version: 16 + +// Unknown tag ignored: 0xd0000000, data len 4 00000001 +/ { + // Unknown tag ignored: 0xc0000000, data len 0 + prop-int =3D <0x00003201>; + // Unknown tag ignored: 0xd0000000, data len 4 00000110 + prop-str =3D "abcd"; + // Unknown tag ignored: 0xe0000000, data len 8 0000012000000121 + // Unknown tag ignored: 0xf0000000, data len 3 101112 + subnode1 { + prop-int =3D <0x00006401 0x00006402>; + // Unknown tag ignored: 0xc0000000, data len 0 + }; + subnode2 { + // Unknown tag ignored: 0xd0000000, data len 4 00000121 + prop-int1 =3D <0x00064020 0x00064021>; + // Unknown tag ignored: 0xe0000000, data len 8 0000122000001221 + prop-int2 =3D <0x00032022>; + subsubnode { + // Unknown tag ignored: 0xe0000000, data len 8 0000123000001231 + prop-bool; + }; + // Unknown tag ignored: 0xf0000000, data len 3 212223 + }; + // Unknown tag ignored: 0xf0000000, data len 4 31323334 +}; +// Unknown tag ignored: 0xd0000000, data len 4 00000002 +// Unknown tag ignored: 0xf0000000, data len 2 4041 diff --git a/tests/unknown_tags_can_skip.wip.test.dtb.1.expect b/tests/unkn= own_tags_can_skip.wip.test.dtb.1.expect new file mode 100644 index 00000000..2a0dd4a0 --- /dev/null +++ b/tests/unknown_tags_can_skip.wip.test.dtb.1.expect @@ -0,0 +1,35 @@ +/dts-v1/; +// version: 17 +// last_comp_version: 16 + +// Unknown tag ignored: 0xd0000000, data len 4 00000001 +/ { + // Unknown tag ignored: 0xc0000000, data len 0 + prop-int =3D <0x00003201>; + // Unknown tag ignored: 0xd0000000, data len 4 00000110 + prop-str =3D "vwxy"; + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + subnode1 { + prop-int =3D <0x00006401 0x00006402>; + // Unknown tag ignored: 0xc0000000, data len 0 + }; + subnode2 { + // Unknown tag ignored: 0xd0000000, data len 4 00000121 + prop-int1 =3D <0x00064020 0x00064021>; + // Unknown tag ignored: 0xe0000000, data len 8 0000122000001221 + prop-int2 =3D <0x00032022>; + subsubnode { + // Unknown tag ignored: 0xe0000000, data len 8 0000123000001231 + prop-bool; + }; + // Unknown tag ignored: 0xf0000000, data len 3 212223 + }; + // Unknown tag ignored: 0xf0000000, data len 4 31323334 +}; +// Unknown tag ignored: 0xd0000000, data len 4 00000002 +// Unknown tag ignored: 0xf0000000, data len 2 4041 diff --git a/tests/unknown_tags_can_skip.wip.test.dtb.2.expect b/tests/unkn= own_tags_can_skip.wip.test.dtb.2.expect new file mode 100644 index 00000000..bc08885b --- /dev/null +++ b/tests/unknown_tags_can_skip.wip.test.dtb.2.expect @@ -0,0 +1,37 @@ +/dts-v1/; +// version: 4294967295 +// last_comp_version: 16 + +// Unknown tag ignored: 0xd0000000, data len 4 00000001 +/ { + // Unknown tag ignored: 0xc0000000, data len 0 + prop-int =3D <0x00003201>; + // Unknown tag ignored: 0xd0000000, data len 4 00000110 + prop-str =3D "abcd"; + // Unknown tag ignored: 0xe0000000, data len 8 0000012000000121 + // Unknown tag ignored: 0xf0000000, data len 3 101112 + subnode1 { + prop-int =3D <0x00006401 0x00006402>; + // Unknown tag ignored: 0xc0000000, data len 0 + }; + subnode2 { + // Unknown tag ignored: 0xd0000000, data len 4 00000121 + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + prop-int2 =3D <0x00032022>; + subsubnode { + // Unknown tag ignored: 0xe0000000, data len 8 0000123000001231 + prop-bool; + }; + // Unknown tag ignored: 0xf0000000, data len 3 212223 + }; + // Unknown tag ignored: 0xf0000000, data len 4 31323334 +}; +// Unknown tag ignored: 0xd0000000, data len 4 00000002 +// Unknown tag ignored: 0xf0000000, data len 2 4041 diff --git a/tests/unknown_tags_can_skip.wip.test.dtb.3.expect b/tests/unkn= own_tags_can_skip.wip.test.dtb.3.expect new file mode 100644 index 00000000..aa6e9394 --- /dev/null +++ b/tests/unknown_tags_can_skip.wip.test.dtb.3.expect @@ -0,0 +1,38 @@ +/dts-v1/; +// version: 4294967295 +// last_comp_version: 16 + +// Unknown tag ignored: 0xd0000000, data len 4 00000001 +/ { + // Unknown tag ignored: 0xc0000000, data len 0 + prop-int =3D <0x00003201>; + // Unknown tag ignored: 0xd0000000, data len 4 00000110 + prop-str =3D "abcd"; + // Unknown tag ignored: 0xe0000000, data len 8 0000012000000121 + // Unknown tag ignored: 0xf0000000, data len 3 101112 + subnode1 { + prop-int =3D <0x00006401 0x00006402>; + // Unknown tag ignored: 0xc0000000, data len 0 + }; + subnode2 { + // Unknown tag ignored: 0xd0000000, data len 4 00000121 + prop-int1 =3D <0x00064020 0x00064021>; + // Unknown tag ignored: 0xe0000000, data len 8 0000122000001221 + prop-int2 =3D <0x00032022>; + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // [NOP] + // Unknown tag ignored: 0xf0000000, data len 3 212223 + }; + // Unknown tag ignored: 0xf0000000, data len 4 31323334 +}; +// Unknown tag ignored: 0xd0000000, data len 4 00000002 +// Unknown tag ignored: 0xf0000000, data len 2 4041 --=20 2.55.0 From nobody Mon Sep 28 04:49:01 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E936E3BFE2D; Wed, 26 Aug 2026 08:33:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733195; cv=none; b=d3rt05BJmF9jVjh3sjieqVhswPBJolg6C4SsBo3Z17/wMZp9XrxWMij4wZ9K3IhqCoF7B3ysn/JKebznm0jO7VsSrq0QzA9rkAup3Psca4NsSXhwNCBX4Z9ItDrdFkA9FxKnk8ii2YKm5wbSamVPRhjOMLayIysbe1bYQb3lFqc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787733195; c=relaxed/simple; bh=fzKus03/R6an1aUgEbZpIoehd/VWSsiJqTbcTz/gBs4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aIM6tQhVydslPe0onPXa1kTOQuaArYHyNhobF2V+EDKaAQF7iDGEBn6BvTaktMGCWVeTy6ng/XmKgEErzfX6cNhdJ0fv2mv+7Qt0EBnTCILV4042vQR/u/qgd9TnptGle50yaTNesLTnVyZKlUkvNE/EbKkqZEcGrDg07LVyxBg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=axJpFO2V; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="axJpFO2V" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 6E46E4E413C7; Wed, 26 Aug 2026 08:33:11 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 3BED9604EC; Wed, 26 Aug 2026 08:33:11 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 2A70E11C7AC84; Wed, 26 Aug 2026 10:33:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1787733190; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=ACDhV2FLapSdIgl3Vk7h551zsr4ybIlem53jcJy/8jQ=; b=axJpFO2Vg33dCE6oSD3PEXAC8Y4clqjND8tUhilP3o6p3RYT5nSkfUupGoxHjTsGPY59JR JqTMJM8CtuDWAR6rVoVoxjqNiKsZozPpTSJO/fEoUXl7I+/PcoV+cecVdAn0MgEIkaQzOB BlkY/SXc6i2eXe7n8TjN55LSee8FaecF+Jc2//JgTKqF4/98EvQdRNiPmkDZHK++Qhutrq QADYyMyoK+x8mSPX2Lq3UeYejpERXeBhIseiWePRhVEtNdrbda6TmeyUsiC3bfx/LpP0gq VRK61pRUwNNu+WKQbUSuPa/UaisyoqqxQJz16cucmOvdoBNSaszqX1q8KwHxsw== From: Herve Codina To: David Gibson , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Laurent Pinchart , David Lechner , Ayush Singh , Geert Uytterhoeven , devicetree-compiler@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree-spec@vger.kernel.org, Hui Pu , Ian Ray , Luca Ceresoli , Thomas Petazzoni , Herve Codina , Frank Li Subject: [PATCH v3 15/15] Introduce v18 dtb version Date: Wed, 26 Aug 2026 10:31:46 +0200 Message-ID: <20260826083146.304291-16-herve.codina@bootlin.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260826083146.304291-1-herve.codina@bootlin.com> References: <20260826083146.304291-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" This v18 version will add support for - Structured tags. Those tags value definition will allow "old" libfdt, dtc and other tools to skip unknown tags if encountered in future dtb version. libfdt, dtc and other tools implementing version v18 will be able to skip unknown tags available in dtbd generated with later version of dtc. - dt_flags header field. For now this flag field is set to 0. It is a placeholder for future dtb version and could be used to store some dtb related information such as the kind of dtb. For instance, the future addons format will use this field to clearly identify that the dtb is an addon dtb. - last_comp_version_w header field. This field is similar to last_comp_version but for writing. It contains the lowest version of the devicetree data structure with which the version used can safely perform modifications (taking into account following rules related to unknown tags). If this lowest version is greater than the last known supported version, modification are simply forbidden and lead to a FDT_ERR_BADVERSION error. For modification, when an unknown tag that can be skipped is involved and last_comp_version_w allows modifications, the following rules apply: - When a property is modified, tags related to this property are removed and the dtb version is downgraded. - When a property is removed, tags related to this property are obviously removed. The dtb version is kept unchanged. - When a property or a node is added, obviously no unknown tags are added and the dtb version is kept unchanged. - When a node is removed, tags related to this node are obviously removed. The dtb version is kept unchanged. - Adding, removing or modifying a property is not considered as a node modification and so, those operations have no impacts on unknown tags related to the node. Those node related tags are kept unchanged. - The only modification considered as a node modification is setting its name. We consider that this operation has no impact on tags related to the node. Here also, those node related tags and the dtb version are kept unchanged. - Global (dtb related) unknown tags are kept unchanged regardless the modification done. In all cases, if unknown tags are not involved in a modification, the dtb version is not downgraded when the modification is made. It is worth noting that with this v18 version, the dtb version is not downgraded for any modification but only when unknown tags are removed due to a property modification. In v17 or older version any modification led to a dtb version downgrade. Signed-off-by: Herve Codina Reviewed-by: Frank Li --- dtc.h | 2 +- fdtdump.c | 8 ++- flattree.c | 37 ++++++++++--- libfdt/fdt.h | 5 ++ libfdt/fdt_rw.c | 20 +++++-- libfdt/fdt_sw.c | 3 ++ libfdt/libfdt.h | 7 ++- pylibfdt/libfdt.i | 18 +++++++ tests/Makefile.tests | 2 +- tests/dtflags_default.dtb.expect | 1 + tests/dtflags_default.dts | 10 ++++ tests/meson.build | 1 + tests/pylibfdt_tests.py | 10 ++-- tests/run_tests.sh | 42 ++++++++++----- tests/testutils.c | 2 +- tests/treegen.c | 53 +++++++++++++++++-- ...own_tags_can_skip.fdtput.test.dtb.0.expect | 1 + ...own_tags_can_skip.fdtput.test.dtb.1.expect | 3 +- ...own_tags_can_skip.fdtput.test.dtb.2.expect | 3 +- ...own_tags_can_skip.fdtput.test.dtb.3.expect | 3 +- ...own_tags_can_skip.fdtput.test.dtb.4.expect | 3 +- ...own_tags_can_skip.fdtput.test.dtb.5.expect | 3 +- ...own_tags_can_skip.fdtput.test.dtb.6.expect | 3 +- ...nknown_tags_can_skip.wip.test.dtb.0.expect | 1 + ...nknown_tags_can_skip.wip.test.dtb.1.expect | 3 +- ...nknown_tags_can_skip.wip.test.dtb.2.expect | 1 + ...nknown_tags_can_skip.wip.test.dtb.3.expect | 1 + 27 files changed, 202 insertions(+), 44 deletions(-) create mode 100644 tests/dtflags_default.dtb.expect create mode 100644 tests/dtflags_default.dts diff --git a/dtc.h b/dtc.h index 473552eb..f0c2cde6 100644 --- a/dtc.h +++ b/dtc.h @@ -29,7 +29,7 @@ #define debug(...) #endif =20 -#define DEFAULT_FDT_VERSION 17 +#define DEFAULT_FDT_VERSION 18 =20 /* * Command line options diff --git a/fdtdump.c b/fdtdump.c index 7a8b2784..5994e1d7 100644 --- a/fdtdump.c +++ b/fdtdump.c @@ -18,7 +18,7 @@ #include "util.h" =20 #define FDT_MAGIC_SIZE 4 -#define MAX_VERSION 17U +#define MAX_VERSION 18U =20 #define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) #define PALIGN(p, a) ((void *)(ALIGN((uintptr_t)(p), (a)))) @@ -86,6 +86,12 @@ static void dump_blob(void *blob, bool debug, int dump_u= nknown) if (version >=3D 17) printf("// size_dt_struct:\t0x%"PRIx32"\n", fdt32_to_cpu(bph->size_dt_struct)); + if (version >=3D 18) { + printf("// dt_flags:\t\t0x%"PRIx32"\n", + fdt32_to_cpu(bph->dt_flags)); + printf("// last_comp_version_w:\t%"PRIu32"\n", + fdt32_to_cpu(bph->last_comp_version_w)); + } printf("\n"); =20 for (i =3D 0; ; i++) { diff --git a/flattree.c b/flattree.c index 88dbfa7e..ff57fc5d 100644 --- a/flattree.c +++ b/flattree.c @@ -13,23 +13,29 @@ #define FTF_STRTABSIZE 0x10 #define FTF_STRUCTSIZE 0x20 #define FTF_NOPS 0x40 +#define FTF_DTFLAGS 0x80 +#define FTF_LCVERSW 0x100 =20 static struct version_info { int version; int last_comp_version; + int last_comp_version_w; int hdr_size; int flags; } version_table[] =3D { - {1, 1, FDT_V1_SIZE, + {1, 1, 0, FDT_V1_SIZE, FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS}, - {2, 1, FDT_V2_SIZE, + {2, 1, 0, FDT_V2_SIZE, FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID}, - {3, 1, FDT_V3_SIZE, + {3, 1, 0, FDT_V3_SIZE, FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID|FTF_STRTABSIZE}, - {16, 16, FDT_V3_SIZE, + {16, 16, 0, FDT_V3_SIZE, FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_NOPS}, - {17, 16, FDT_V17_SIZE, + {17, 16, 0, FDT_V17_SIZE, FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE|FTF_NOPS}, + {18, 16, 17, FDT_V18_SIZE, + FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE|FTF_NOPS|FTF_DTFLAGS| + FTF_LCVERSW}, }; =20 struct emitter { @@ -314,7 +320,7 @@ static struct data flatten_reserve_list(struct reserve_= info *reservelist, static void make_fdt_header(struct fdt_header *fdt, struct version_info *vi, int reservesize, int dtsize, int strsize, - int boot_cpuid_phys) + int boot_cpuid_phys, uint32_t dt_flags) { int reserve_off; =20 @@ -341,6 +347,10 @@ static void make_fdt_header(struct fdt_header *fdt, fdt->size_dt_strings =3D cpu_to_fdt32(strsize); if (vi->flags & FTF_STRUCTSIZE) fdt->size_dt_struct =3D cpu_to_fdt32(dtsize); + if (vi->flags & FTF_DTFLAGS) + fdt->dt_flags =3D cpu_to_fdt32(dt_flags); + if (vi->flags & FTF_LCVERSW) + fdt->last_comp_version_w =3D cpu_to_fdt32(vi->last_comp_version_w); } =20 void dt_to_blob(FILE *f, struct dt_info *dti, int version) @@ -368,7 +378,7 @@ void dt_to_blob(FILE *f, struct dt_info *dti, int versi= on) =20 /* Make header */ make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len, - dti->boot_cpuid_phys); + dti->boot_cpuid_phys, 0); =20 /* * If the user asked for more space than is used, adjust the totalsize. @@ -499,6 +509,16 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int versi= on) symprefix, symprefix); } =20 + if (vi->flags & FTF_DTFLAGS) { + fprintf(f, "\t/* dt_flags */\n"); + asm_emit_cell(f, 0); + } + + if (vi->flags & FTF_LCVERSW) { + fprintf(f, "\t/* last_comp_version_w */\n"); + asm_emit_cell(f, vi->last_comp_version_w); + } + /* * Reserve map entries. * Align the reserve map to a doubleword boundary. @@ -955,6 +975,9 @@ struct dt_info *dt_from_blob(const char *fname) flags |=3D FTF_NOPS; } =20 + if (version >=3D 18) + flags |=3D FTF_DTFLAGS | FTF_LCVERSW; + inbuf_init(&memresvbuf, blob + off_mem_rsvmap, blob + totalsize); inbuf_init(&dtbuf, blob + off_dt, blob + totalsize); diff --git a/libfdt/fdt.h b/libfdt/fdt.h index f41a355f..a43b85c1 100644 --- a/libfdt/fdt.h +++ b/libfdt/fdt.h @@ -26,6 +26,10 @@ struct fdt_header { =20 /* version 17 fields below */ fdt32_t size_dt_struct; /* size of the structure block */ + + /* version 18 fields below */ + fdt32_t dt_flags; /* Ored value of FDT_FLAG_XXXX */ + fdt32_t last_comp_version_w; /* last compatible version for writing */ }; =20 struct fdt_reserve_entry { @@ -85,5 +89,6 @@ struct fdt_property { #define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t)) #define FDT_V16_SIZE FDT_V3_SIZE #define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t)) +#define FDT_V18_SIZE (FDT_V17_SIZE + 2 * sizeof(fdt32_t)) =20 #endif /* FDT_H */ diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 87776609..005efde8 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -34,13 +34,17 @@ static int fdt_rw_probe_(void *fdt) return 0; FDT_RO_PROBE(fdt); =20 - if (!can_assume(LATEST) && fdt_version(fdt) < 17) - return -FDT_ERR_BADVERSION; + if (!can_assume(LATEST)) { + if (fdt_version(fdt) < 17) + return -FDT_ERR_BADVERSION; + else if (fdt_version(fdt) >=3D 18 && + fdt_last_comp_version_w(fdt) > FDT_LAST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + } if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry), fdt_size_dt_struct(fdt))) return -FDT_ERR_BADLAYOUT; =20 - fdt_downgrade_version(fdt); return 0; } =20 @@ -624,7 +628,11 @@ int fdt_open_into(const void *fdt, void *buf, int bufs= ize) err =3D fdt_move(fdt, buf, bufsize); if (err) return err; - fdt_set_version(buf, 17); + if (can_assume(LATEST) || fdt_version(fdt) < 18) { + fdt_set_version(buf, 18); + fdt_set_dt_flags(buf, 0); + fdt_set_last_comp_version_w(buf, 17); + } fdt_set_size_dt_struct(buf, struct_size); fdt_set_totalsize(buf, bufsize); return 0; @@ -653,8 +661,10 @@ int fdt_open_into(const void *fdt, void *buf, int bufs= ize) =20 fdt_set_magic(buf, FDT_MAGIC); fdt_set_totalsize(buf, bufsize); - fdt_set_version(buf, 17); + fdt_set_version(buf, 18); fdt_set_last_comp_version(buf, 16); + fdt_set_dt_flags(buf, 0); + fdt_set_last_comp_version_w(buf, 17); fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); =20 return 0; diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 96d4cf57..caafd60a 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -137,6 +137,9 @@ int fdt_create_with_flags(void *buf, int bufsize, uint3= 2_t flags) fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); fdt_set_off_dt_strings(fdt, 0); =20 + fdt_set_dt_flags(fdt, 0); + fdt_set_last_comp_version_w(fdt, FDT_LAST_COMPATIBLE_VERSION_W); + return 0; } =20 diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 82965e32..8e99e644 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -15,7 +15,8 @@ extern "C" { =20 #define FDT_FIRST_SUPPORTED_VERSION 0x02 #define FDT_LAST_COMPATIBLE_VERSION 0x10 -#define FDT_LAST_SUPPORTED_VERSION 0x11 +#define FDT_LAST_COMPATIBLE_VERSION_W 0x11 +#define FDT_LAST_SUPPORTED_VERSION 0x12 =20 /* Error codes: informative error codes */ #define FDT_ERR_NOTFOUND 1 @@ -284,6 +285,8 @@ int fdt_next_subnode(const void *fdt, int offset); #define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) #define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) #define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) +#define fdt_dt_flags(fdt) (fdt_get_header(fdt, dt_flags)) +#define fdt_last_comp_version_w(fdt) (fdt_get_header(fdt, last_comp_versio= n_w)) =20 #define fdt_set_hdr_(name) \ static inline void fdt_set_##name(void *fdt, uint32_t val) \ @@ -301,6 +304,8 @@ fdt_set_hdr_(last_comp_version) fdt_set_hdr_(boot_cpuid_phys) fdt_set_hdr_(size_dt_strings) fdt_set_hdr_(size_dt_struct) +fdt_set_hdr_(dt_flags) +fdt_set_hdr_(last_comp_version_w) #undef fdt_set_hdr_ =20 /** diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i index b41c03f4..462fe28a 100644 --- a/pylibfdt/libfdt.i +++ b/pylibfdt/libfdt.i @@ -281,6 +281,22 @@ class FdtRo(object): """ return fdt_size_dt_struct(self._fdt) =20 + def dt_flags(self): + """Return flags from the header + + Returns: + flags value from the header + """ + return fdt_dt_flags(self._fdt) + + def last_comp_version_w(self): + """Return the last compatible version for writing of the device tr= ee + + Returns: + Last compatible version number for writing of the device tree + """ + return fdt_last_comp_version_w(self._fdt) + def num_mem_rsv(self, quiet=3D()): """Return the number of memory reserve-map records =20 @@ -1287,6 +1303,8 @@ uint32_t fdt_last_comp_version(const void *fdt); uint32_t fdt_boot_cpuid_phys(const void *fdt); uint32_t fdt_size_dt_strings(const void *fdt); uint32_t fdt_size_dt_struct(const void *fdt); +uint32_t fdt_dt_flags(const void *fdt); +uint32_t fdt_last_comp_version_w(const void *fdt); =20 int fdt_property_string(void *fdt, const char *name, const char *val); int fdt_property_cell(void *fdt, const char *name, uint32_t val); diff --git a/tests/Makefile.tests b/tests/Makefile.tests index a71c4cbf..857e4899 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -46,7 +46,7 @@ TESTS_TREES_L =3D test_tree1.dtb bad_node_char.dtb bad_no= de_format.dtb \ bad_prop_char.dtb ovf_size_strings.dtb truncated_property.dtb \ truncated_string.dtb truncated_memrsv.dtb unterminated_memrsv.dtb \ two_roots.dtb named_root.dtb unknown_tags_can_skip.dtb \ - unknown_tags_no_skip.dtb + unknown_tags_no_skip.dtb last_comp_version_w_future.dtb TESTS_TREES =3D $(TESTS_TREES_L:%=3D$(TESTS_PREFIX)%) =20 TESTS_TARGETS =3D $(TESTS) $(TESTS_TREES) diff --git a/tests/dtflags_default.dtb.expect b/tests/dtflags_default.dtb.e= xpect new file mode 100644 index 00000000..cefed4d6 --- /dev/null +++ b/tests/dtflags_default.dtb.expect @@ -0,0 +1 @@ +// dt_flags: 0x0 diff --git a/tests/dtflags_default.dts b/tests/dtflags_default.dts new file mode 100644 index 00000000..3ef867e8 --- /dev/null +++ b/tests/dtflags_default.dts @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * Copyright (C) 2026 Bootlin + */ + +/dts-v1/; + +/ { + prop =3D <1>; +}; diff --git a/tests/meson.build b/tests/meson.build index e7a88936..fcc73982 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -19,6 +19,7 @@ treegen_dtb =3D custom_target( 'named_root.dtb', 'unknown_tags_can_skip.dtb', 'unknown_tags_no_skip.dtb', + 'last_comp_version_w_future.dtb', ] ) =20 diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py index 0e166075..c3aaf00f 100644 --- a/tests/pylibfdt_tests.py +++ b/tests/pylibfdt_tests.py @@ -274,14 +274,16 @@ class PyLibfdtBasicTests(unittest.TestCase): """Test that we can access the header values""" self.assertEqual(self.fdt.magic(), 0xd00dfeed) self.assertEqual(self.fdt.totalsize(), len(self.fdt._fdt)) - self.assertEqual(self.fdt.off_dt_struct(), 88) - self.assertEqual(self.fdt.off_dt_strings(), 652) - self.assertEqual(self.fdt.off_mem_rsvmap(), 40) - self.assertEqual(self.fdt.version(), 17) + self.assertEqual(self.fdt.off_dt_struct(), 96) + self.assertEqual(self.fdt.off_dt_strings(), 660) + self.assertEqual(self.fdt.off_mem_rsvmap(), 48) + self.assertEqual(self.fdt.version(), 18) self.assertEqual(self.fdt.last_comp_version(), 16) self.assertEqual(self.fdt.boot_cpuid_phys(), 0) self.assertEqual(self.fdt.size_dt_strings(), 105) self.assertEqual(self.fdt.size_dt_struct(), 564) + self.assertEqual(self.fdt.dt_flags(), 0) + self.assertEqual(self.fdt.last_comp_version_w(), 17) =20 def testPack(self): """Test that we can pack the tree after deleting something""" diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 980ed6a0..42b74e05 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -578,7 +578,8 @@ libfdt_tests () { run_test dtbs_equal_ordered cell-overflow.test.dtb cell-overflow-resul= ts.test.dtb =20 # check full tests - for good in test_tree1.dtb unknown_tags_can_skip.dtb; do + for good in test_tree1.dtb unknown_tags_can_skip.dtb \ + last_comp_version_w_future.dtb; do run_test check_full $good done for bad in truncated_property.dtb truncated_string.dtb \ @@ -592,27 +593,27 @@ libfdt_tests () { cp unknown_tags_can_skip.dtb $dtb base_run_test wrap_fdtdump $dtb $dtb.0.out # Remove unneeded header fields (keep those related to versions) - sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.0.out + sed -i '/^\/.*\(magic\|off\|size\|cpu\|flags\)/d' $dtb.0.out base_run_test check_diff $dtb.0.out "$SRCDIR/$dtb.0.expect" =20 run_test wip_func $dtb set_prop / prop-str 0 "vwxy" base_run_test wrap_fdtdump $dtb $dtb.1.out # Remove unneeded header fields (keep those related to versions) - sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.1.out + sed -i '/^\/.*\(magic\|off\|size\|cpu\|flags\)/d' $dtb.1.out base_run_test check_diff $dtb.1.out "$SRCDIR/$dtb.1.expect" =20 cp unknown_tags_can_skip.dtb $dtb run_test wip_func $dtb nop_prop /subnode2 prop-int1 base_run_test wrap_fdtdump $dtb $dtb.2.out # Remove unneeded header fields (keep those related to versions) - sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.2.out + sed -i '/^\/.*\(magic\|off\|size\|cpu\|flags\)/d' $dtb.2.out base_run_test check_diff $dtb.2.out "$SRCDIR/$dtb.2.expect" =20 cp unknown_tags_can_skip.dtb $dtb run_test wip_func $dtb nop_node /subnode2/subsubnode base_run_test wrap_fdtdump $dtb $dtb.3.out # Remove unneeded header fields (keep those related to versions) - sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.3.out + sed -i '/^\/.*\(magic\|off\|size\|cpu\|flags\)/d' $dtb.3.out base_run_test check_diff $dtb.3.out "$SRCDIR/$dtb.3.expect" } =20 @@ -917,6 +918,14 @@ dtc_tests () { run_dtc_test -I dtb -O dts -o unknown_tags_can_skip.dtb.dts unknown_ta= gs_can_skip.dtb base_run_test check_diff unknown_tags_can_skip.dtb.dts "$SRCDIR/unknow= n_tags_can_skip.dtb.dts.expect" run_wrap_error_test $DTC -I dtb -O dts -o unknown_tags_no_skip.dtb.dts= unknown_tags_no_skip.dtb + + # Tests dt_flags header field (default value) + run_dtc_test -I dts -O dtb -o dtflags_default.dtb "$SRCDIR/dtflags_def= ault.dts" + base_run_test wrap_fdtdump dtflags_default.dtb dtflags_default.dtb.out + # Keep only lines containing 'dt_flags' + sed -i '/dt_flags/!d' dtflags_default.dtb.out + base_run_test check_diff dtflags_default.dtb.out "$SRCDIR/dtflags_defa= ult.dtb.expect" + run_test check_full dtflags_default.dtb } =20 cmp_tests () { @@ -1074,32 +1083,41 @@ fdtput_tests () { =20 # TODO: Add tests for verbose mode? =20 + # Not allowed to modify a dtb due to last_comp_version_w + # FDT_ERR_BADVERSION error code is returned + dtb=3Dlast_comp_version_w_future.fdtput.test.dtb + cp last_comp_version_w_future.dtb $dtb + run_wrap_error_test $DTPUT $dtb /subnode prop-int -tu 123 + run_wrap_error_test $DTPUT $dtb -d /subnode prop-int + run_wrap_error_test $DTPUT $dtb -c /new-node + run_wrap_error_test $DTPUT $dtb -r /subnode + # Modify a dtb containing some "unknown" tags that can be skipped dtb=3Dunknown_tags_can_skip.fdtput.test.dtb cp unknown_tags_can_skip.dtb $dtb base_run_test wrap_fdtdump $dtb $dtb.0.out # Remove unneeded header fields (keep those related to versions) - sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.0.out + sed -i '/^\/.*\(magic\|off\|size\|cpu\|flags\)/d' $dtb.0.out base_run_test check_diff $dtb.0.out "$SRCDIR/$dtb.0.expect" =20 run_fdtput_test "vwxyz" $dtb / prop-str -ts "vwxyz" base_run_test wrap_fdtdump $dtb $dtb.1.out # Remove unneeded header fields (keep those related to versions) - sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.1.out + sed -i '/^\/.*\(magic\|off\|size\|cpu\|flags\)/d' $dtb.1.out base_run_test check_diff $dtb.1.out "$SRCDIR/$dtb.1.expect" =20 cp unknown_tags_can_skip.dtb $dtb run_wrap_test $DTPUT $dtb -c /tst-fdtput base_run_test wrap_fdtdump $dtb $dtb.2.out # Remove unneeded header fields (keep those related to versions) - sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.2.out + sed -i '/^\/.*\(magic\|off\|size\|cpu\|flags\)/d' $dtb.2.out base_run_test check_diff $dtb.2.out "$SRCDIR/$dtb.2.expect" run_wrap_test $DTPUT $dtb -c /tst-fdtput/n1 /tst-fdtput/n2 /tst-fdtput= /n3 run_wrap_test $DTPUT $dtb -r /tst-fdtput/n1 /tst-fdtput/n3 run_fdtget_test "n2" $dtb -l /tst-fdtput base_run_test wrap_fdtdump $dtb $dtb.3.out # Remove unneeded header fields (keep those related to versions) - sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.3.out + sed -i '/^\/.*\(magic\|off\|size\|cpu\|flags\)/d' $dtb.3.out base_run_test check_diff $dtb.3.out "$SRCDIR/$dtb.3.expect" =20 cp unknown_tags_can_skip.dtb $dtb @@ -1107,21 +1125,21 @@ fdtput_tests () { run_fdtget_test "prop-int" $dtb -p / base_run_test wrap_fdtdump $dtb $dtb.4.out # Remove unneeded header fields (keep those related to versions) - sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.4.out + sed -i '/^\/.*\(magic\|off\|size\|cpu\|flags\)/d' $dtb.4.out base_run_test check_diff $dtb.4.out "$SRCDIR/$dtb.4.expect" =20 cp unknown_tags_can_skip.dtb $dtb run_wrap_test $DTPUT $dtb /subnode2 prop-tst-fdtput -ts "Test fdtput" base_run_test wrap_fdtdump $dtb $dtb.5.out # Remove unneeded header fields (keep those related to versions) - sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.5.out + sed -i '/^\/.*\(magic\|off\|size\|cpu\|flags\)/d' $dtb.5.out base_run_test check_diff $dtb.5.out "$SRCDIR/$dtb.5.expect" =20 cp unknown_tags_can_skip.dtb $dtb run_wrap_test $DTPUT $dtb -r /subnode2/subsubnode base_run_test wrap_fdtdump $dtb $dtb.6.out # Remove unneeded header fields (keep those related to versions) - sed -i '/^\/.*\(magic\|off\|size\|cpu\)/d' $dtb.6.out + sed -i '/^\/.*\(magic\|off\|size\|cpu\|flags\)/d' $dtb.6.out base_run_test check_diff $dtb.6.out "$SRCDIR/$dtb.6.expect" } =20 diff --git a/tests/testutils.c b/tests/testutils.c index d35a1978..7df80f7c 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -354,7 +354,7 @@ void *open_blob_rw(const void *blob) { int err; void *buf; - int newsize =3D fdt_totalsize(blob) + 8; + int newsize =3D fdt_totalsize(blob) + 8 + 2 * 4; =20 buf =3D xmalloc(newsize); err =3D fdt_open_into(blob, buf, newsize); diff --git a/tests/treegen.c b/tests/treegen.c index f07c8963..b0730ef6 100644 --- a/tests/treegen.c +++ b/tests/treegen.c @@ -106,7 +106,8 @@ static void fill_prop_name(struct buf *b, size_t strs, = size_t prop, size_t strof /* FDT structure helpers */ =20 static size_t emit_fdt_header_vers(struct buf *b, uint32_t version, - uint32_t last_comp_version) + uint32_t last_comp_version, + uint32_t last_comp_version_w) { size_t off =3D emit_u32(b, FDT_MAGIC); =20 @@ -119,12 +120,14 @@ static size_t emit_fdt_header_vers(struct buf *b, uin= t32_t version, emit_u32(b, 0); /* boot_cpuid_phys */ emit_u32(b, 0); /* size_dt_strings */ emit_u32(b, 0); /* size_dt_struct */ + emit_u32(b, 0); /* dt_flags */ + emit_u32(b, last_comp_version_w); /* last_comp_version_w */ return off; } =20 static size_t emit_fdt_header(struct buf *b) { - return emit_fdt_header_vers(b, 0x11, 0x10); + return emit_fdt_header_vers(b, 0x12, 0x10, 0x11); } =20 static void finish_rsvmap(struct buf *b, size_t hdr, size_t rsvmap) @@ -720,7 +723,7 @@ static struct buf make_unknown_tags_can_skip(void) size_t p_sn2_int1, p_sn2_int2; size_t p_sn2ssn_bool; =20 - hdr =3D emit_fdt_header_vers(&b, 0xffffffff, 0x10); + hdr =3D emit_fdt_header_vers(&b, 0xffffffff, 0x10, 0x11); emit_align(&b, 8); =20 emit_rsvmap_empty(&b, hdr); @@ -833,7 +836,7 @@ static struct buf make_unknown_tags_no_skip(void) size_t hdr; size_t p_prop_u64; =20 - hdr =3D emit_fdt_header_vers(&b, 0xffffffff, 0x10); + hdr =3D emit_fdt_header_vers(&b, 0xffffffff, 0x10, 0x11); emit_align(&b, 8); =20 emit_rsvmap_empty(&b, hdr); @@ -867,6 +870,47 @@ static struct buf make_unknown_tags_no_skip(void) return b; } =20 +/* Tree with "unknown" tags that can be skipped + * Use a really future dtb version to check version downgrade on + * modification. + */ +static struct buf make_last_comp_version_w_future(void) +{ + struct buf b =3D buf_init(); + size_t hdr; + size_t p_int; + + hdr =3D emit_fdt_header_vers(&b, 0xffffffff, 0x10, 0xffffffff); + emit_align(&b, 8); + + emit_rsvmap_empty(&b, hdr); + + { + size_t ss =3D start_block(&b); + + emit_begin_node(&b, ""); + p_int =3D emit_prop_u64(&b, 0, 0x100000002); + emit_end_node(&b); + emit_fdt_end(&b); + + finish_struct_block(&b, hdr, ss); + } + + { + size_t strs =3D start_block(&b); + size_t s; + + s =3D emit_string(&b, "prop-int"); + fill_prop_name(&b, strs, p_int, s); + + finish_strings_block(&b, hdr, strs); + } + + finish_totalsize(&b, hdr); + + return b; +} + /* Tree table and main */ =20 static struct { @@ -884,6 +928,7 @@ static struct { TREE(named_root), TREE(unknown_tags_can_skip), TREE(unknown_tags_no_skip), + TREE(last_comp_version_w_future), }; =20 int main(int argc, char *argv[]) diff --git a/tests/unknown_tags_can_skip.fdtput.test.dtb.0.expect b/tests/u= nknown_tags_can_skip.fdtput.test.dtb.0.expect index 75883593..42167271 100644 --- a/tests/unknown_tags_can_skip.fdtput.test.dtb.0.expect +++ b/tests/unknown_tags_can_skip.fdtput.test.dtb.0.expect @@ -1,6 +1,7 @@ /dts-v1/; // version: 4294967295 // last_comp_version: 16 +// last_comp_version_w: 17 =20 // Unknown tag ignored: 0xd0000000, data len 4 00000001 / { diff --git a/tests/unknown_tags_can_skip.fdtput.test.dtb.1.expect b/tests/u= nknown_tags_can_skip.fdtput.test.dtb.1.expect index b4d3ae29..6d750f88 100644 --- a/tests/unknown_tags_can_skip.fdtput.test.dtb.1.expect +++ b/tests/unknown_tags_can_skip.fdtput.test.dtb.1.expect @@ -1,6 +1,7 @@ /dts-v1/; -// version: 17 +// version: 18 // last_comp_version: 16 +// last_comp_version_w: 17 =20 // Unknown tag ignored: 0xd0000000, data len 4 00000001 / { diff --git a/tests/unknown_tags_can_skip.fdtput.test.dtb.2.expect b/tests/u= nknown_tags_can_skip.fdtput.test.dtb.2.expect index a196bed3..83bbfd1f 100644 --- a/tests/unknown_tags_can_skip.fdtput.test.dtb.2.expect +++ b/tests/unknown_tags_can_skip.fdtput.test.dtb.2.expect @@ -1,6 +1,7 @@ /dts-v1/; -// version: 17 +// version: 4294967295 // last_comp_version: 16 +// last_comp_version_w: 17 =20 // Unknown tag ignored: 0xd0000000, data len 4 00000001 / { diff --git a/tests/unknown_tags_can_skip.fdtput.test.dtb.3.expect b/tests/u= nknown_tags_can_skip.fdtput.test.dtb.3.expect index 52faa1dd..77b00d1d 100644 --- a/tests/unknown_tags_can_skip.fdtput.test.dtb.3.expect +++ b/tests/unknown_tags_can_skip.fdtput.test.dtb.3.expect @@ -1,6 +1,7 @@ /dts-v1/; -// version: 17 +// version: 4294967295 // last_comp_version: 16 +// last_comp_version_w: 17 =20 // Unknown tag ignored: 0xd0000000, data len 4 00000001 / { diff --git a/tests/unknown_tags_can_skip.fdtput.test.dtb.4.expect b/tests/u= nknown_tags_can_skip.fdtput.test.dtb.4.expect index 1ddc694b..93c7b750 100644 --- a/tests/unknown_tags_can_skip.fdtput.test.dtb.4.expect +++ b/tests/unknown_tags_can_skip.fdtput.test.dtb.4.expect @@ -1,6 +1,7 @@ /dts-v1/; -// version: 17 +// version: 4294967295 // last_comp_version: 16 +// last_comp_version_w: 17 =20 // Unknown tag ignored: 0xd0000000, data len 4 00000001 / { diff --git a/tests/unknown_tags_can_skip.fdtput.test.dtb.5.expect b/tests/u= nknown_tags_can_skip.fdtput.test.dtb.5.expect index f955ac1c..7ee385aa 100644 --- a/tests/unknown_tags_can_skip.fdtput.test.dtb.5.expect +++ b/tests/unknown_tags_can_skip.fdtput.test.dtb.5.expect @@ -1,6 +1,7 @@ /dts-v1/; -// version: 17 +// version: 4294967295 // last_comp_version: 16 +// last_comp_version_w: 17 =20 // Unknown tag ignored: 0xd0000000, data len 4 00000001 / { diff --git a/tests/unknown_tags_can_skip.fdtput.test.dtb.6.expect b/tests/u= nknown_tags_can_skip.fdtput.test.dtb.6.expect index 59247478..777443f3 100644 --- a/tests/unknown_tags_can_skip.fdtput.test.dtb.6.expect +++ b/tests/unknown_tags_can_skip.fdtput.test.dtb.6.expect @@ -1,6 +1,7 @@ /dts-v1/; -// version: 17 +// version: 4294967295 // last_comp_version: 16 +// last_comp_version_w: 17 =20 // Unknown tag ignored: 0xd0000000, data len 4 00000001 / { diff --git a/tests/unknown_tags_can_skip.wip.test.dtb.0.expect b/tests/unkn= own_tags_can_skip.wip.test.dtb.0.expect index 75883593..42167271 100644 --- a/tests/unknown_tags_can_skip.wip.test.dtb.0.expect +++ b/tests/unknown_tags_can_skip.wip.test.dtb.0.expect @@ -1,6 +1,7 @@ /dts-v1/; // version: 4294967295 // last_comp_version: 16 +// last_comp_version_w: 17 =20 // Unknown tag ignored: 0xd0000000, data len 4 00000001 / { diff --git a/tests/unknown_tags_can_skip.wip.test.dtb.1.expect b/tests/unkn= own_tags_can_skip.wip.test.dtb.1.expect index 2a0dd4a0..afd8a4af 100644 --- a/tests/unknown_tags_can_skip.wip.test.dtb.1.expect +++ b/tests/unknown_tags_can_skip.wip.test.dtb.1.expect @@ -1,6 +1,7 @@ /dts-v1/; -// version: 17 +// version: 18 // last_comp_version: 16 +// last_comp_version_w: 17 =20 // Unknown tag ignored: 0xd0000000, data len 4 00000001 / { diff --git a/tests/unknown_tags_can_skip.wip.test.dtb.2.expect b/tests/unkn= own_tags_can_skip.wip.test.dtb.2.expect index bc08885b..53403228 100644 --- a/tests/unknown_tags_can_skip.wip.test.dtb.2.expect +++ b/tests/unknown_tags_can_skip.wip.test.dtb.2.expect @@ -1,6 +1,7 @@ /dts-v1/; // version: 4294967295 // last_comp_version: 16 +// last_comp_version_w: 17 =20 // Unknown tag ignored: 0xd0000000, data len 4 00000001 / { diff --git a/tests/unknown_tags_can_skip.wip.test.dtb.3.expect b/tests/unkn= own_tags_can_skip.wip.test.dtb.3.expect index aa6e9394..89fde625 100644 --- a/tests/unknown_tags_can_skip.wip.test.dtb.3.expect +++ b/tests/unknown_tags_can_skip.wip.test.dtb.3.expect @@ -1,6 +1,7 @@ /dts-v1/; // version: 4294967295 // last_comp_version: 16 +// last_comp_version_w: 17 =20 // Unknown tag ignored: 0xd0000000, data len 4 00000001 / { --=20 2.55.0