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

Herve Codina
2026-04-09T11:54:52Z

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 <herve.codina@bootlin.com>
---
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