[PATCH v2 1/4] lib: utils: fdt: add generic domain and property parsing helpers
Raymond Mao <[email protected]> Fri, 24 Jul 2026 22:38:18 -0400
| Newsgroups | org.infradead.lists.opensbi |
|---|---|
| Message-ID | <[email protected]> |
From: Raymond Mao <[email protected]> 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 <[email protected]> --- 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 -- opensbi mailing list [email protected] http://lists.infradead.org/mailman/listinfo/opensbi