While applying dt-overlays using libfdt code, the order of the applied properties and sub-nodes is reversed. This should not be a problem in ideal world (mainline), but this matters for some vendor specific/custom dtb files. This can be easily fixed by the little change to libfdt code: any new properties and sub-nodes should be added after the parent's node properties and subnodes. Signed-off-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> --- libfdt/fdt_rw.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 8795947..88c5930 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -189,19 +189,27 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, int len, struct fdt_property **prop) { int proplen; - int nextoffset; + int offset, nextoffset; int namestroff; int err; int allocated; + uint32_t tag; if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) return nextoffset; + /* Try to place the new property after the parent's properties */ + fdt_next_tag(fdt, nodeoffset, &nextoffset); /* skip the BEGIN_NODE */ + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + } while ((tag == FDT_PROP) || (tag == FDT_NOP)); + namestroff = fdt_find_add_string_(fdt, name, &allocated); if (namestroff < 0) return namestroff; - *prop = fdt_offset_ptr_w_(fdt, nextoffset); + *prop = fdt_offset_ptr_w_(fdt, offset); proplen = sizeof(**prop) + FDT_TAGALIGN(len); err = fdt_splice_struct_(fdt, *prop, 0, proplen); @@ -321,6 +329,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, struct fdt_node_header *nh; int offset, nextoffset; int nodelen; + int depth = 0; int err; uint32_t tag; fdt32_t *endtag; @@ -333,12 +342,21 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, else if (offset != -FDT_ERR_NOTFOUND) return offset; - /* Try to place the new node after the parent's properties */ + /* Try to place the new node after the parent's subnodes */ fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ do { +again: offset = nextoffset; tag = fdt_next_tag(fdt, offset, &nextoffset); - } while ((tag == FDT_PROP) || (tag == FDT_NOP)); + if (depth && tag == FDT_END_NODE) { + depth--; + goto again; + } + if (tag == FDT_BEGIN_NODE) { + depth++; + goto again; + } + } while (depth || (tag == FDT_PROP) || (tag == FDT_NOP)); nh = fdt_offset_ptr_w_(fdt, offset); nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; -- 2.17.1