On Tue, Apr 13, 2021 at 04:07:40PM +0800, Yanan Wang wrote: > From: Andrew Jones > > qemu_fdt_add_path() works like qemu_fdt_add_subnode(), except > it also adds any missing subnodes in the path. We also tweak > an error message of qemu_fdt_add_subnode(). > > We'll make use of this new function in a coming patch. > > Signed-off-by: Andrew Jones > Signed-off-by: Yanan Wang > --- > include/sysemu/device_tree.h | 1 + > softmmu/device_tree.c | 45 ++++++++++++++++++++++++++++++++++-- > 2 files changed, 44 insertions(+), 2 deletions(-) > > diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h > index 8a2fe55622..ef060a9759 100644 > --- a/include/sysemu/device_tree.h > +++ b/include/sysemu/device_tree.h > @@ -121,6 +121,7 @@ uint32_t qemu_fdt_get_phandle(void *fdt, const char *path); > uint32_t qemu_fdt_alloc_phandle(void *fdt); > int qemu_fdt_nop_node(void *fdt, const char *node_path); > int qemu_fdt_add_subnode(void *fdt, const char *name); > +int qemu_fdt_add_path(void *fdt, const char *path); > > #define qemu_fdt_setprop_cells(fdt, node_path, property, ...) \ > do { \ > diff --git a/softmmu/device_tree.c b/softmmu/device_tree.c > index 2691c58cf6..8592c7aa1b 100644 > --- a/softmmu/device_tree.c > +++ b/softmmu/device_tree.c > @@ -541,8 +541,8 @@ int qemu_fdt_add_subnode(void *fdt, const char *name) > > retval = fdt_add_subnode(fdt, parent, basename); > if (retval < 0) { > - error_report("FDT: Failed to create subnode %s: %s", name, > - fdt_strerror(retval)); > + error_report("%s: Failed to create subnode %s: %s", > + __func__, name, fdt_strerror(retval)); > exit(1); > } > > @@ -550,6 +550,47 @@ int qemu_fdt_add_subnode(void *fdt, const char *name) > return retval; > } > > +/* > + * Like qemu_fdt_add_subnode(), but will add all missing > + * subnodes in the path. > + */ > +int qemu_fdt_add_path(void *fdt, const char *path) > +{ > + char *dupname, *basename, *p; > + int parent, retval = -1; > + > + if (path[0] != '/') { > + return retval; > + } > + > + parent = fdt_path_offset(fdt, "/"); Getting the offset for "/" is never needed - it's always 0. > + p = dupname = g_strdup(path); You shouldn't need the strdup(), see below. > + > + while (p) { > + *p = '/'; > + basename = p + 1; > + p = strchr(p + 1, '/'); > + if (p) { > + *p = '\0'; > + } > + retval = fdt_path_offset(fdt, dupname); The fdt_path_offset_namelen() function exists *exactly* so that you can look up partial parths without having to mangle your input string. Just set the namelen right, and it will ignore anything to the right of that. > + if (retval < 0 && retval != -FDT_ERR_NOTFOUND) { > + error_report("%s: Invalid path %s: %s", > + __func__, path, fdt_strerror(retval)); If you're getting an error other than FDT_ERR_NOTFOUND here, chances are it's not an invalid path, but a corrupted fdt blob or something else. > + exit(1); > + } else if (retval == -FDT_ERR_NOTFOUND) { > + retval = fdt_add_subnode(fdt, parent, basename); > + if (retval < 0) { > + break; > + } > + } > + parent = retval; > + } > + > + g_free(dupname); > + return retval; > +} > + > void qemu_fdt_dumpdtb(void *fdt, int size) > { > const char *dumpdtb = current_machine->dumpdtb; -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson