On Sun, May 16, 2021 at 06:28:53PM +0800, Yanan Wang wrote: > From: Andrew Jones > > qemu_fdt_add_path() works like qemu_fdt_add_subnode(), except it > also adds all missing subnodes from the given path. We'll use it > in a coming patch where we will add cpu-map to the device tree. > > And we also tweak an error message of qemu_fdt_add_subnode(). > > Cc: David Gibson > Cc: Alistair Francis > Signed-off-by: Andrew Jones > Co-developed-by: Yanan Wang > Signed-off-by: Yanan Wang Reviewed-by: David Gibson Wonder if I should integrate a function like this into libfdt. > --- > include/sysemu/device_tree.h | 1 + > softmmu/device_tree.c | 44 ++++++++++++++++++++++++++++++++++-- > 2 files changed, 43 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 b621f63fba..3965c834ca 100644 > --- a/softmmu/device_tree.c > +++ b/softmmu/device_tree.c > @@ -540,8 +540,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); > } > > @@ -549,6 +549,46 @@ int qemu_fdt_add_subnode(void *fdt, const char *name) > return retval; > } > > +/* > + * qemu_fdt_add_path: Like qemu_fdt_add_subnode(), but will add > + * all missing subnodes from the given path. > + */ > +int qemu_fdt_add_path(void *fdt, const char *path) > +{ > + const char *name; > + const char *p = path; > + int namelen, retval; > + int parent = 0; > + > + if (path[0] != '/') { > + return -1; > + } > + > + while (p) { > + name = p + 1; > + p = strchr(name, '/'); > + namelen = p != NULL ? p - name : strlen(name); > + > + retval = fdt_subnode_offset_namelen(fdt, parent, name, namelen); > + if (retval < 0 && retval != -FDT_ERR_NOTFOUND) { > + error_report("%s: Unexpected error in finding subnode %.*s: %s", > + __func__, namelen, name, fdt_strerror(retval)); > + exit(1); > + } else if (retval == -FDT_ERR_NOTFOUND) { > + retval = fdt_add_subnode_namelen(fdt, parent, name, namelen); > + if (retval < 0) { > + error_report("%s: Failed to create subnode %.*s: %s", > + __func__, namelen, name, fdt_strerror(retval)); > + exit(1); > + } > + } > + > + parent = retval; > + } > + > + 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