[PATCH v2 1/4] lib: utils: fdt: add generic domain and property parsing helpers
Raymond Mao
raymondmaoca at gmail.com
Fri Jul 24 19:38:18 PDT 2026
From: Raymond Mao <raymond.mao at riscstar.com>
Add reusable FDT helpers for domain-oriented and other FDT-based
consumers.
This adds helpers to:
- find a domain instance DT node by exact name match
- parse a single u32 property
- parse a single u64 property
- parse a u32 property list into a bitmask
Also tighten the internal domain-name matching to use exact node-name
matching.
Signed-off-by: Raymond Mao <raymond.mao at riscstar.com>
---
include/sbi_utils/fdt/fdt_domain.h | 13 +++++
include/sbi_utils/fdt/fdt_helper.h | 10 ++++
lib/utils/fdt/fdt_domain.c | 46 +++++++++++++++++-
lib/utils/fdt/fdt_helper.c | 76 ++++++++++++++++++++++++++++++
4 files changed, 144 insertions(+), 1 deletion(-)
diff --git a/include/sbi_utils/fdt/fdt_domain.h b/include/sbi_utils/fdt/fdt_domain.h
index 8c2dee09..60d51d6c 100644
--- a/include/sbi_utils/fdt/fdt_domain.h
+++ b/include/sbi_utils/fdt/fdt_domain.h
@@ -11,12 +11,18 @@
#ifndef __FDT_DOMAIN_H__
#define __FDT_DOMAIN_H__
+#include <sbi/sbi_error.h>
#include <sbi/sbi_types.h>
#ifdef CONFIG_FDT_DOMAIN
struct sbi_domain;
+struct fdt_find_domain_offset_info {
+ const char *name;
+ int domain_offset;
+};
+
/**
* Iterate over each domains in device tree
*
@@ -45,6 +51,8 @@ int fdt_iterate_each_memregion(void *fdt, int domain_offset, void *opaque,
int region_offset, u32 region_access,
void *opaque));
+int fdt_find_domain_offset(const void *fdt, const struct sbi_domain *dom);
+
/**
* Fix up the domain configuration in the device tree
*
@@ -76,6 +84,11 @@ int fdt_domains_populate(const void *fdt);
static inline void fdt_domain_fixup(void *fdt) { }
static inline int fdt_domains_populate(const void *fdt) { return 0; }
+static inline int fdt_find_domain_offset(const void *fdt,
+ const struct sbi_domain *dom)
+{
+ return SBI_ENOENT;
+}
#endif
diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
index 75a564d1..05ca9f79 100644
--- a/include/sbi_utils/fdt/fdt_helper.h
+++ b/include/sbi_utils/fdt/fdt_helper.h
@@ -50,6 +50,16 @@ int fdt_parse_hart_id(const void *fdt, int cpu_offset, u32 *hartid);
int fdt_parse_max_enabled_hart_id(const void *fdt, u32 *max_hartid);
+int fdt_parse_u32(const void *fdt, int nodeoff, const char *prop_name,
+ u32 *out_val);
+
+int fdt_parse_u64(const void *fdt, int nodeoff, const char *prop_name,
+ u64 *out_val);
+
+int fdt_parse_u32_array_bitmask(const void *fdt, int nodeoff,
+ const char *prop_name, u32 max_bits,
+ u32 *out_mask);
+
int fdt_parse_cbom_block_size(const void *fdt, int cpu_offset, unsigned long *cbom_block_size);
int fdt_parse_timebase_frequency(const void *fdt, unsigned long *freq);
diff --git a/lib/utils/fdt/fdt_domain.c b/lib/utils/fdt/fdt_domain.c
index 61627db3..af653505 100644
--- a/lib/utils/fdt/fdt_domain.c
+++ b/lib/utils/fdt/fdt_domain.c
@@ -97,6 +97,49 @@ int fdt_iterate_each_memregion(void *fdt, int domain_offset, void *opaque,
return 0;
}
+static bool fdt_find_domain_offset_match(void *fdt, int domain_offset,
+ void *opaque)
+{
+ struct fdt_find_domain_offset_info *info = opaque;
+ const char *name;
+
+ name = fdt_get_name(fdt, domain_offset, NULL);
+ if (name && !strcmp(info->name, name)) {
+ info->domain_offset = domain_offset;
+ return true;
+ }
+
+ return false;
+}
+
+static int fdt_find_domain_offset_iter(void *fdt, int domain_offset,
+ void *opaque)
+{
+ return fdt_find_domain_offset_match(fdt, domain_offset, opaque) ? 1 : 0;
+}
+
+int fdt_find_domain_offset(const void *fdt, const struct sbi_domain *dom)
+{
+ struct fdt_find_domain_offset_info info;
+ int rc;
+
+ if (!fdt || !dom)
+ return SBI_EINVAL;
+ if (dom == &root)
+ return -1;
+
+ info.name = dom->name;
+ info.domain_offset = -1;
+ rc = fdt_iterate_each_domain((void *)fdt, &info,
+ fdt_find_domain_offset_iter);
+ if (rc < 0)
+ return rc;
+ if (info.domain_offset >= 0)
+ return info.domain_offset;
+
+ return SBI_ENOENT;
+}
+
static int fdt_iterate_each_memregion_ro(const void *fdt, int domain_offset, void *opaque,
int (*fn)(const void *fdt, int domain_offset,
int region_offset, u32 region_access,
@@ -114,8 +157,9 @@ struct __fixup_find_domain_offset_info {
static int __fixup_find_domain_offset(void *fdt, int doff, void *p)
{
struct __fixup_find_domain_offset_info *fdo = p;
+ const char *name = fdt_get_name(fdt, doff, NULL);
- if (!strncmp(fdo->name, fdt_get_name(fdt, doff, NULL), strlen(fdo->name)))
+ if (name && !strcmp(fdo->name, name))
*fdo->doffset = doff;
return 0;
diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
index ad4efaaf..39c3f3aa 100644
--- a/lib/utils/fdt/fdt_helper.c
+++ b/lib/utils/fdt/fdt_helper.c
@@ -250,6 +250,82 @@ int fdt_parse_hart_id(const void *fdt, int cpu_offset, u32 *hartid)
return 0;
}
+int fdt_parse_u32(const void *fdt, int nodeoff, const char *prop_name,
+ u32 *out_val)
+{
+ const fdt32_t *prop;
+ int len;
+
+ if (!fdt || nodeoff < 0 || !prop_name || !out_val)
+ return SBI_EINVAL;
+
+ prop = fdt_getprop(fdt, nodeoff, prop_name, &len);
+ if (!prop)
+ return SBI_ENOENT;
+ if (len != (int)sizeof(fdt32_t))
+ return SBI_EINVAL;
+
+ *out_val = fdt32_to_cpu(prop[0]);
+ return 0;
+}
+
+int fdt_parse_u64(const void *fdt, int nodeoff, const char *prop_name,
+ u64 *out_val)
+{
+ const fdt32_t *prop;
+ int len;
+
+ if (!fdt || nodeoff < 0 || !prop_name || !out_val)
+ return SBI_EINVAL;
+
+ prop = fdt_getprop(fdt, nodeoff, prop_name, &len);
+ if (!prop)
+ return SBI_ENOENT;
+ if (len != (int)(2 * sizeof(fdt32_t)))
+ return SBI_EINVAL;
+
+ *out_val = ((u64)fdt32_to_cpu(prop[0]) << 32) | fdt32_to_cpu(prop[1]);
+ return 0;
+}
+
+int fdt_parse_u32_array_bitmask(const void *fdt, int nodeoff,
+ const char *prop_name, u32 max_bits,
+ u32 *out_mask)
+{
+ const fdt32_t *prop;
+ u32 mask = 0, count, val;
+ int len, i;
+
+ if (!fdt || nodeoff < 0 || !prop_name || !out_mask || !max_bits ||
+ max_bits > 32)
+ return SBI_EINVAL;
+
+ *out_mask = 0;
+
+ prop = fdt_getprop(fdt, nodeoff, prop_name, &len);
+ if (!prop)
+ return 0;
+ if (len < 0 || (len % (int)sizeof(fdt32_t)))
+ return SBI_EINVAL;
+
+ count = len / sizeof(fdt32_t);
+ if (count > max_bits)
+ return SBI_EINVAL;
+
+ for (i = 0; i < (int)count; i++) {
+ val = fdt32_to_cpu(prop[i]);
+ if (val >= max_bits)
+ return SBI_EINVAL;
+ if (mask & (1U << val))
+ return SBI_EINVAL;
+
+ mask |= 1U << val;
+ }
+
+ *out_mask = mask;
+ return 0;
+}
+
int fdt_parse_cbom_block_size(const void *fdt, int cpu_offset, unsigned long *cbom_block_size)
{
int len;
--
2.25.1
More information about the opensbi
mailing list