diff options
-rw-r--r-- | .clang-format | 2 | ||||
-rw-r--r-- | src/vppinfra/devicetree.c | 17 | ||||
-rw-r--r-- | src/vppinfra/devicetree.h | 50 |
3 files changed, 63 insertions, 6 deletions
diff --git a/.clang-format b/.clang-format index 798a8c39a35..e4855fce047 100644 --- a/.clang-format +++ b/.clang-format @@ -35,6 +35,8 @@ ForEachMacros: - 'foreach_vnet_dev_port' - 'foreach_vnet_dev_args' - 'foreach_vnet_dev_port_args' + - 'foreach_clib_dt_tree_node' + - 'foreach_clib_dt_child_node' StatementMacros: - 'CLIB_MULTIARCH_FN' diff --git a/src/vppinfra/devicetree.c b/src/vppinfra/devicetree.c index b725d5a0aed..df5a24f198e 100644 --- a/src/vppinfra/devicetree.c +++ b/src/vppinfra/devicetree.c @@ -192,9 +192,16 @@ done: } #endif -clib_dt_node_t * -clib_dt_get_child_node (clib_dt_node_t *n, char *name) +__clib_export clib_dt_node_t * +clib_dt_get_child_node (clib_dt_node_t *n, char *fmt, ...) { + u8 *s; + va_list va; + va_start (va, fmt); + s = va_format (0, fmt, &va); + va_end (va); + vec_add1 (s, 0); + vec_foreach_pointer (cn, n->child_nodes) { u8 *p = cn->path + vec_len (cn->path) - 1; @@ -206,15 +213,17 @@ clib_dt_get_child_node (clib_dt_node_t *n, char *name) if (p[-1] != '/') continue; - while (p[i] == name[i] && name[i] != 0) + while (p[i] == s[i] && s[i] != 0) i++; - if (name[i] != 0) + if (s[i] != 0) continue; + vec_free (s); return cn; } + vec_free (s); return 0; } diff --git a/src/vppinfra/devicetree.h b/src/vppinfra/devicetree.h index 21c2e0f7006..db7d8411a11 100644 --- a/src/vppinfra/devicetree.h +++ b/src/vppinfra/devicetree.h @@ -42,6 +42,8 @@ typedef struct clib_dt_main uword *node_by_phandle; } clib_dt_main_t; +__clib_export clib_dt_node_t *clib_dt_get_child_node (clib_dt_node_t *n, + char *fmt, ...); clib_dt_node_t *clib_dt_get_node_with_path (clib_dt_main_t *dm, char *fmt, ...); clib_dt_property_t *clib_dt_get_node_property_by_name (clib_dt_node_t *, @@ -56,7 +58,7 @@ format_function_t format_clib_dt_desc; format_function_t format_clib_dt_property_data; static_always_inline int -clib_dt_proprerty_is_u32 (clib_dt_property_t *p) +clib_dt_property_is_u32 (clib_dt_property_t *p) { if (p == 0 || p->size != 4) return 0; @@ -64,9 +66,53 @@ clib_dt_proprerty_is_u32 (clib_dt_property_t *p) } static_always_inline u32 -clib_dt_proprerty_get_u32 (clib_dt_property_t *p) +clib_dt_property_get_u32 (clib_dt_property_t *p) { return clib_net_to_host_u32 (*(u32u *) p->data); } +static_always_inline char * +clib_dt_property_get_string (clib_dt_property_t *p) +{ + return (char *) p->data; +} + +static_always_inline clib_dt_node_t * +clib_dt_get_root_node (clib_dt_node_t *n) +{ + return n->dt_main->root; +} + +static_always_inline clib_dt_node_t * +foreach_clib_dt_tree_node_helper (clib_dt_node_t *first, clib_dt_node_t **prev, + clib_dt_node_t *n) +{ + clib_dt_node_t *next; + +again: + if ((!*prev || (*prev)->parent != n) && vec_len (n->child_nodes) > 0) + next = n->child_nodes[0]; + else if (n->next) + next = n->next; + else + { + next = n->parent; + *prev = n; + n = next; + if (n == first) + return 0; + goto again; + } + + *prev = n; + return next == first ? 0 : next; +} + +#define foreach_clib_dt_child_node(_cn, _n) \ + vec_foreach_pointer (_cn, (_n)->child_nodes) + +#define foreach_clib_dt_tree_node(_n, _first) \ + for (clib_dt_node_t *__last = 0, *(_n) = _first; _n; \ + _n = foreach_clib_dt_tree_node_helper (_first, &__last, _n)) + #endif /* CLIB_DEVICETREE_H_ */ |