Re: [PATCH v2 01/10] libfdt: Introduce fdt_first_node()

Frank Li <[email protected]> Thu, 4 Jun 2026 16:59:12 -0400
Newsgroups org.kernel.vger.devicetree-compiler,org.kernel.vger.devicetree-spec,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel
Message-ID <aiHnIE5uHYq4vcSX@lizhi-Precision-Tower-5810>
On Thu, Apr 09, 2026 at 01:54:17PM +0200, Herve Codina wrote:
> In several places, libfdt assumes that a FDT_BEGIN_NODE tag is present
> at the offset 0 of the structure block.
>
> This assumption is not correct. Indeed, 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’s 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_first_node() in order to get the offset of the first node
> (first FDT_BEGIN_NODE tag) available in a fdt blob taking care of
> FDT_NOP tags.
>
> [0] https://github.com/devicetree-org/devicetree-specification/blob/main/source/chapter5-flattened-format.rst?plain=1#L317
>
> Signed-off-by: Herve Codina <[email protected]>
> ---

Reviewed-by: Frank Li <[email protected]>

>  libfdt/fdt.c             | 25 +++++++++++++++++++++++++
>  libfdt/libfdt_internal.h |  1 +
>  2 files changed, 26 insertions(+)
>
> diff --git a/libfdt/fdt.c b/libfdt/fdt.c
> index 56d4dcb..676c7d7 100644
> --- a/libfdt/fdt.c
> +++ b/libfdt/fdt.c
> @@ -252,6 +252,31 @@ int fdt_check_prop_offset_(const void *fdt, int offset)
>  	return offset;
>  }
>
> +int fdt_first_node(const void *fdt)
> +{
> +	int nextoffset = 0;
> +	int offset;
> +	uint32_t tag;
> +
> +	do {
> +		offset = nextoffset;
> +		tag = 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 != FDT_END);
> +
> +	return (nextoffset < 0) ? nextoffset : -FDT_ERR_NOTFOUND;
> +}
> +
>  int fdt_next_node(const void *fdt, int offset, int *depth)
>  {
>  	int nextoffset = 0;
> diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h
> index 0e103ca..4c15264 100644
> --- a/libfdt/libfdt_internal.h
> +++ b/libfdt/libfdt_internal.h
> @@ -32,6 +32,7 @@ static inline const char *fdt_find_string_(const char *strtab, int tabsize,
>  }
>
>  int fdt_node_end_offset_(void *fdt, int nodeoffset);
> +int fdt_first_node(const void *fdt);
>
>  static inline const void *fdt_offset_ptr_(const void *fdt, int offset)
>  {
> --
> 2.53.0
>