[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