All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: Ruslan Ruslichenko <ruslichenko.r@gmail.com>
Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org,
	alex.bennee@linaro.org, peter.maydell@linaro.org,
	artem_mygaiev@epam.com, volodymyr_babchuk@epam.com,
	takahiro.nakata.wr@renesas.com,
	"Edgar E . Iglesias" <edgar.iglesias@gmail.com>,
	Ruslan_Ruslichenko@epam.com, balaton@eik.bme.hu,
	Alistair Francis <alistair.francis@wdc.com>
Subject: Re: [PATCH v3 02/33] system/device_tree: add few parsing and traversal helpers
Date: Fri, 3 Apr 2026 11:52:11 +1100	[thread overview]
Message-ID: <ac8PO_EpAiWxczDy@zatzit> (raw)
In-Reply-To: <20260402215629.745866-3-ruslichenko.r@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 8830 bytes --]

On Thu, Apr 02, 2026 at 11:55:47PM +0200, Ruslan Ruslichenko wrote:
> From: Ruslan Ruslichenko <Ruslan_Ruslichenko@epam.com>
> 
> The patch adds few utility functions for parsing FDT nodes.
> The helpers are required for upcoming Hardware device tree
> feature.

If you're building an entire fdt based machine type, it really seems
like you might want a "live" dt representation - the flattened format
is great for communicating between things, but it's not a good data
structure if you're actively consulting it.

> 
> Signed-off-by: Ruslan Ruslichenko <Ruslan_Ruslichenko@epam.com>
> ---
>  include/system/device_tree.h |  22 ++++
>  system/device_tree.c         | 194 +++++++++++++++++++++++++++++++++++
>  2 files changed, 216 insertions(+)
> 
> diff --git a/include/system/device_tree.h b/include/system/device_tree.h
> index 5667ff9538..bc378d38d0 100644
> --- a/include/system/device_tree.h
> +++ b/include/system/device_tree.h
> @@ -116,6 +116,11 @@ const void *qemu_fdt_getprop(void *fdt, const char *node_path,
>  uint32_t qemu_fdt_getprop_cell(void *fdt, const char *node_path,
>                                 const char *property, int cell_id,
>                                 Error **errp);
> +
> +const void *qemu_fdt_getprop_inherited(void *fdt, const char *node_path,
> +                             const char *property, int *lenp, Error **errp);
> +uint32_t qemu_fdt_getprop_cell_inherited(void *fdt, const char *node_path,
> +                               const char *property, int cell_id, Error **errp);
>  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);
> @@ -191,6 +196,23 @@ int qemu_fdt_setprop_sized_cells_from_array(void *fdt,
>                                                  qdt_tmp);                 \
>      })
>  
> +/* node queries */
> +
> +int qemu_devtree_get_num_children(void *fdt, const char *node_path);
> +int qemu_devtree_get_children(void *fdt, const char *node_path,
> +                                     int max_paths, char **returned_paths);
> +int qemu_devtree_num_props(void *fdt, const char *node_path);
> +
> +/* node getters */
> +
> +int qemu_devtree_get_node_by_phandle(void *fdt, char *node_path, int phandle);
> +char *qemu_devtree_getparent(void *fdt, const char *current);
> +
> +/* misc */
> +
> +int devtree_get_num_nodes(void *fdt);
> +
> +#define DT_PATH_LENGTH 1024
>  
>  /**
>   * qemu_fdt_randomize_seeds:
> diff --git a/system/device_tree.c b/system/device_tree.c
> index d2db7bd355..1a70223712 100644
> --- a/system/device_tree.c
> +++ b/system/device_tree.c
> @@ -464,6 +464,96 @@ uint32_t qemu_fdt_getprop_cell(void *fdt, const char *node_path,
>      return be32_to_cpu(p[cell_id]);
>  }
>  
> +const void *qemu_fdt_getprop_inherited(void *fdt, const char *node_path,
> +                             const char *property, int *lenp, Error **errp)
> +{
> +    const void *found_val = NULL;
> +    int found_len = 0;
> +    int curr_offset = 0;
> +    int temp_len;
> +    char **tokens;
> +    char **iter;
> +
> +    found_val = fdt_getprop(fdt, 0, property, &found_len);
> +
> +    tokens = g_strsplit(node_path + 1, "/", -1);
> +
> +    for (iter = tokens; *iter != NULL; iter++) {
> +        if (**iter == '\0') {
> +            continue;
> +        }
> +
> +        curr_offset = fdt_subnode_offset(fdt, curr_offset, *iter);
> +        if (curr_offset < 0) {
> +            error_setg(errp, "%s: Path '%s' not found",
> +                       __func__, *iter);
> +            g_strfreev(tokens);
> +            return NULL;
> +        }
> +
> +        const void *val = fdt_getprop(fdt, curr_offset, property, &temp_len);
> +        if (val) {
> +            found_val = val;
> +            found_len = temp_len;
> +        }
> +    }
> +    g_strfreev(tokens);
> +
> +    if (!found_val) {
> +        error_setg(errp, "%s: Property '%s' not found",
> +                   __func__, property);
> +        return NULL;
> +    }
> +
> +    if (lenp) {
> +        *lenp = found_len;
> +    }
> +
> +    return found_val;
> +}
> +
> +uint32_t qemu_fdt_getprop_cell_inherited(void *fdt, const char *node_path,
> +                               const char *property, int cell_id, Error **errp)
> +{
> +    int len;
> +    const uint32_t *p;
> +
> +    p = qemu_fdt_getprop_inherited(fdt, node_path, property, &len, errp);
> +    if (!p) {
> +        return 0;
> +    }
> +    if (len < (cell_id + 1) * 4) {
> +        error_setg(errp,
> +                   "%s: %s/%s is too short, need %d bytes for cell ind %d",
> +                   __func__, node_path, property, (cell_id + 1) * 4, cell_id);
> +        return 0;
> +    }
> +    return be32_to_cpu(p[cell_id]);
> +}
> +
> +char *qemu_devtree_getparent(void *fdt, const char *current)
> +{
> +    const char *sep;
> +    int len;
> +
> +    if (!current || !strcmp(current, "/")) {
> +        return NULL;
> +    }
> +
> +    sep = strrchr(current, '/');
> +    if (!sep) {
> +        return NULL;
> +    }
> +
> +    if (sep == current) {
> +        len = 1;
> +    } else {
> +        len = sep - current;
> +    }
> +
> +    return g_strndup(current, len);
> +}
> +
>  uint32_t qemu_fdt_get_phandle(void *fdt, const char *path)
>  {
>      uint32_t r;
> @@ -631,6 +721,110 @@ out:
>      return ret;
>  }
>  
> +int qemu_devtree_num_props(void *fdt, const char *node_path)
> +{
> +    int offset = fdt_path_offset(fdt, node_path);
> +    int ret = 0;
> +
> +    for (offset = fdt_first_property_offset(fdt, offset);
> +            offset != -FDT_ERR_NOTFOUND;
> +            offset = fdt_next_property_offset(fdt, offset)) {
> +        ret++;
> +    }
> +    return ret;
> +}
> +
> +int qemu_devtree_get_children(void *fdt, const char *node_path,
> +                                     int max_paths, char **returned_paths)
> +{
> +    int count = 0;
> +    int subnode;
> +    const char *name;
> +    int offset = fdt_path_offset(fdt, node_path);
> +
> +    if (offset < 0) {
> +        return offset;
> +    }
> +
> +    bool is_root = (strcmp(node_path, "/") == 0);
> +
> +    fdt_for_each_subnode(subnode, fdt, offset) {
> +        if (count >= max_paths) {
> +            break;
> +        }
> +        name = fdt_get_name(fdt, subnode, NULL);
> +        if (returned_paths) {
> +            returned_paths[count] = g_strdup_printf("%s/%s",
> +                                                is_root ? "" : node_path, name);
> +        }
> +
> +        ++count;
> +    }
> +
> +    return count;
> +}
> +
> +int qemu_devtree_get_num_children(void *fdt, const char *node_path)
> +{
> +    int count = 0;
> +    int subnode;
> +    int offset = fdt_path_offset(fdt, node_path);
> +
> +    if (offset < 0) {
> +        return offset;
> +    }
> +
> +    fdt_for_each_subnode(subnode, fdt, offset) {
> +        ++count;
> +    }
> +
> +    return count;
> +}
> +
> +int qemu_devtree_get_node_by_phandle(void *fdt, char *node_path, int phandle)
> +{
> +    int offset = 0, cur_depth = 0;
> +    int path_lens[64] = { 0 };
> +
> +    for (offset = 0; offset >= 0; offset = fdt_next_node(fdt, offset,
> +                                                         &cur_depth)) {
> +        if (cur_depth >= 64) {
> +            break;
> +        }
> +        const char *name = fdt_get_name(fdt, offset, NULL);
> +
> +        int parent_len = (cur_depth > 0) ? path_lens[cur_depth - 1] : 0;
> +        int len = snprintf(node_path + parent_len,
> +                             DT_PATH_LENGTH - parent_len,
> +                             "%s%s",
> +                             (parent_len > 1) ? "/" : "",
> +                             (cur_depth == 0) ? "/" : name);
> +
> +        path_lens[cur_depth] = parent_len + len;
> +
> +        if (fdt_get_phandle(fdt, offset) == phandle) {
> +            return 0;
> +        }
> +    }
> +
> +    return -FDT_ERR_NOTFOUND;
> +}
> +
> +int devtree_get_num_nodes(void *fdt)
> +{
> +    int num_nodes = 0;
> +    int depth = 0, offset = 0;
> +
> +    for (;;) {
> +        offset = fdt_next_node(fdt, offset, &depth);
> +        num_nodes++;
> +        if (offset <= 0 || depth <= 0) {
> +            break;
> +        }
> +    }
> +    return num_nodes;
> +}
> +
>  void qmp_dumpdtb(const char *filename, Error **errp)
>  {
>      ERRP_GUARD();
> -- 
> 2.43.0
> 

-- 
David Gibson (he or they)	| 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

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2026-04-03  0:52 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-02 21:55 [PATCH v3 00/33] hw/arm: Introduce generic FDT-driven machine Ruslan Ruslichenko
2026-04-02 21:55 ` [PATCH v3 01/33] system/device_tree: update qemu_fdt_getprop_cell Ruslan Ruslichenko
2026-04-02 21:55 ` [PATCH v3 02/33] system/device_tree: add few parsing and traversal helpers Ruslan Ruslichenko
2026-04-03  0:52   ` David Gibson [this message]
2026-04-03 17:25     ` Ruslan Ruslichenko
2026-04-02 21:55 ` [PATCH v3 03/33] util/log: add log entry for fdt generic utils Ruslan Ruslichenko
2026-04-02 21:55 ` [PATCH v3 04/33] hw/core: introduce generic FDT device model registry Ruslan Ruslichenko
2026-04-02 21:55 ` [PATCH v3 05/33] hw/core/fdt_generic: implement FDT machine creation helpers Ruslan Ruslichenko
2026-04-02 21:55 ` [PATCH v3 06/33] hw/core/fdt_generic: add cpu clusters management Ruslan Ruslichenko
2026-04-02 21:55 ` [PATCH v3 07/33] hw/core/fdt_generic_util: implement main fdt parse routine Ruslan Ruslichenko
2026-04-02 21:55 ` [PATCH v3 08/33] hw/core/fdt_generic_util: implement fdt_init_qdev Ruslan Ruslichenko
2026-04-02 21:55 ` [PATCH v3 09/33] qdev: Add qdev_prop_get_array_elem_type() helper Ruslan Ruslichenko
2026-04-02 21:55 ` [PATCH v3 10/33] qom/object: export object_resolve_link() Ruslan Ruslichenko
2026-04-02 21:55 ` [PATCH v3 11/33] hw/core/fdt_generic_util: initilize qdev properties from fdt Ruslan Ruslichenko
2026-04-02 21:55 ` [PATCH v3 12/33] hw/core/fdt_generic_util: actually realize device Ruslan Ruslichenko
2026-04-02 21:55 ` [PATCH v3 13/33] hw/core/fdt_generic_util: add TYPE_FDT_GENERIC_MMAP Ruslan Ruslichenko
2026-04-02 21:55 ` [PATCH v3 14/33] hw/core/fdt_generic_util: add TYPE_FDT_GENERIC_INTC Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 15/33] hw/core/fdt_generic_util: implement fdt_get_irq/_info API Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 16/33] hw/core/fdt_generic_util: map device memory regions Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 17/33] hw/core/fdt_generic_util: Connect device irqs Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 18/33] hw/core/fdt_generic_util: realize cpu clusters Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 19/33] hw/core: add fdt_generic to the build Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 20/33] hw/arm: add generic ARM machine initialized by FDT Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 21/33] hw/arm/arm_generic_fdt: Add support for host-backed RAM regions Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 22/33] hw/core/sysbus: implement FDT_GENERIC_MMAP_CLASS interface Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 23/33] hw/intc/arm_gic: implement FDT_GENERIC_INTC and fdt support Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 24/33] target/arm/cpu: add fdt support for armv8-timer Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 25/33] system/memory: add setters for MemoryRegion properties Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 26/33] system/memory: implement FDT_GENERIC_MMAP interface Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 27/33] hw/core/fdt_generic_util: initialize serial devices Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 28/33] system/memory: add QOM aliases for fdt support Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 29/33] hw/intc/arm_gicv3: Implement FDTGenericIntc interface Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 30/33] hw/core/fdt_generic_util: Add deferred device initialization support Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 31/33] hw/core/fdt_generic_util: Add blockdev binding support Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 32/33] hw/pci-host: add gsi-irqs property array Ruslan Ruslichenko
2026-04-02 21:56 ` [PATCH v3 33/33] tests/functional: Add functional tests for arm-generic-fdt machine Ruslan Ruslichenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ac8PO_EpAiWxczDy@zatzit \
    --to=david@gibson.dropbear.id.au \
    --cc=Ruslan_Ruslichenko@epam.com \
    --cc=alex.bennee@linaro.org \
    --cc=alistair.francis@wdc.com \
    --cc=artem_mygaiev@epam.com \
    --cc=balaton@eik.bme.hu \
    --cc=edgar.iglesias@gmail.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=ruslichenko.r@gmail.com \
    --cc=takahiro.nakata.wr@renesas.com \
    --cc=volodymyr_babchuk@epam.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.