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 >