[PATCH v2] lib: utils: fdt: fix "ranges" translation

Anup Patel anup at brainfault.org
Tue Jul 22 22:20:04 PDT 2025


On Fri, Jul 11, 2025 at 12:02 AM Max Hsu <max.hsu at sifive.com> wrote:
>
> According to the Device Tree Spec, Chapter 2.3.8 "ranges" [1]:
> The parent address size will be determined from the #address-cells
> property of the node that defines the parent’s address space.
>
> In fdt_translate_address(), which considered the parent address size
> is the child address size, this commit fix the two address sizes
> and parsing the address independently.
>
> Signed-off-by: Max Hsu <max.hsu at sifive.com>

LGTM.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup

> ---
> v1 fix will introduce another bug in the following case.
>
> The node in DTS depth 1 if execute fdt_get_node_addr_size(), inside
> the function, the fdt_translate_address() will try to get the child
> "#address-cells" and "#size-cells" in DTS depth 0, and the parent
> "#address-cells" in DTS depth -1. which will cause early abort.
> With fdt_translate_address() early abort, the parameter "addr" didn't
> got any assignment of the address value. This let
> fdt_get_node_addr_size() return with unknown value of parameter "addr".
>
> For the v2 fix, which will check the "ranges" first, since the above
> case shouldn't happen in the DTS as the "ranges" should be existed in
> DTS depth more than 0. This fix also improve execution cycle.
> ---
> Changes in v2:
> - fix v1 bug mentioned in the cover letter.
> - Link to v1: https://lore.kernel.org/r/20250708-dev-maxh-master_fdt_helper-v1-1-866c165f1f85@sifive.com
> ---
>  lib/utils/fdt/fdt_helper.c | 26 +++++++++++++++-----------
>  1 file changed, 15 insertions(+), 11 deletions(-)
>
> diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> index 0f4859c1a721bc7c2871bacefe27caba7780f752..799fd48dc3abf0a3c1963f84dd6bde271e6c08d7 100644
> --- a/lib/utils/fdt/fdt_helper.c
> +++ b/lib/utils/fdt/fdt_helper.c
> @@ -84,23 +84,27 @@ static int fdt_translate_address(const void *fdt, uint64_t reg, int parent,
>                                  uint64_t *addr)
>  {
>         int i, rlen;
> -       int cell_addr, cell_size;
> +       int cell_parent_addr, cell_child_addr, cell_size;
>         const fdt32_t *ranges;
>         uint64_t offset, caddr = 0, paddr = 0, rsize = 0;
>
> -       cell_addr = fdt_address_cells(fdt, parent);
> -       if (cell_addr < 1)
> -               return SBI_ENODEV;
> -
> -       cell_size = fdt_size_cells(fdt, parent);
> -       if (cell_size < 0)
> -               return SBI_ENODEV;
> -
>         ranges = fdt_getprop(fdt, parent, "ranges", &rlen);
>         if (ranges && rlen > 0) {
> -               for (i = 0; i < cell_addr; i++)
> +               cell_child_addr = fdt_address_cells(fdt, parent);
> +               if (cell_child_addr < 1)
> +                       return SBI_ENODEV;
> +
> +               cell_parent_addr = fdt_address_cells(fdt, fdt_parent_offset(fdt, parent));
> +               if (cell_parent_addr < 1)
> +                       return SBI_ENODEV;
> +
> +               cell_size = fdt_size_cells(fdt, parent);
> +               if (cell_size < 0)
> +                       return SBI_ENODEV;
> +
> +               for (i = 0; i < cell_child_addr; i++)
>                         caddr = (caddr << 32) | fdt32_to_cpu(*ranges++);
> -               for (i = 0; i < cell_addr; i++)
> +               for (i = 0; i < cell_parent_addr; i++)
>                         paddr = (paddr << 32) | fdt32_to_cpu(*ranges++);
>                 for (i = 0; i < cell_size; i++)
>                         rsize = (rsize << 32) | fdt32_to_cpu(*ranges++);
>
> ---
> base-commit: a32a91069119e7a5aa31e6bc51d5e00860be3d80
> change-id: 20250708-dev-maxh-master_fdt_helper-46d2eeeb07cd
>
> Best regards,
> --
> Max Hsu <max.hsu at sifive.com>
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi



More information about the opensbi mailing list