From: Chali Anis <[email protected]> of_state_fixup() was static, callable only via of_register_fixup(). Export it so other subsystems can invoke it directly to render a state instance's devicetree representation on demand, without going through the global fixup-registration/of_fix_tree() machinery.
While exporting it, teach it to resolve backend nodes that are top-level "barebox,fixed-partitions" subnodes carrying a partuuid property instead of being tied to a real, already-probed storage device node in the tree - the same globally-resolvable-by-UUID binding drivers/of/of_path.c's of_cdev_find() already supports for EFI, where devices aren't instantiated from devicetree. Without this, of_state_fixup() could only find a backend reachable by walking real hardware nodes already present in root, which such a partuuid-only declaration never is. Assisted-by: Claude Sonnet 5 Signed-off-by: Chali Anis <[email protected]> --- common/state/state.c | 72 ++++++++++++++++++++++++++++++++++++-------- include/state.h | 5 +++ 2 files changed, 64 insertions(+), 13 deletions(-) diff --git a/common/state/state.c b/common/state/state.c index b421b43da539..5de806b954e9 100644 --- a/common/state/state.c +++ b/common/state/state.c @@ -433,14 +433,69 @@ int state_from_node(struct state *state, struct device_node *node, bool create) return ret; } -static int of_state_fixup(struct device_node *root, void *ctx) +static int state_get_backend(struct state *state, struct device_node *root, struct device_node *n) +{ + struct device_node *backend_node, *part, *state_root, *np; + const char *compatible = "fixed-partitions"; + struct property *prop; + phandle phandle; + int ret; + + state_root = of_find_node_by_path(state->of_path); + if (!state_root) + return -ENODEV; + + backend_node = of_parse_phandle(state_root, "backend", 0); + if (!backend_node) + return -ENODEV; + + if (of_node_is_fixed_partitions(of_get_parent(backend_node)) && + of_property_present(backend_node, "partuuid")) { + part = of_create_node(root, "/partitions"); + if (!part) + return -ENOMEM; + + prop = of_new_property(part, "compatible", compatible, + strlen(compatible) + 1); + if (!prop) + return -ENOMEM; + + np = of_copy_node(part, backend_node); + if (!np) + return -ENOMEM; + + /* + * of_copy_node() carries over backend_node's phandle as-is, + * but that phandle was allocated in barebox's own live + * devicetree, a namespace independent of @root's. Assign a + * fresh one scoped to @root instead, so it can't collide + * with an unrelated node already using that value there. + */ + phandle = of_get_tree_max_phandle(root) + 1; + np->phandle = phandle; + ret = of_property_write_u32(np, "phandle", phandle); + if (ret) + return ret; + + return of_property_write_u32(n, "backend", phandle); + } + + backend_node = of_find_node_by_reproducible_name(root, state->backend_reproducible_name); + if (!backend_node) + return -ENODEV; + + phandle = of_node_create_phandle(backend_node); + + return of_property_write_u32(n, "backend", phandle); +} + +int of_state_fixup(struct device_node *root, void *ctx) { struct state *state = ctx; const char *compatible = "barebox,state"; - struct device_node *new_node, *node, *parent, *backend_node, *aliases; + struct device_node *new_node, *node, *parent, *aliases; struct property *p; int ret; - phandle phandle; node = of_find_node_by_path_from(root, state->of_path); if (node) { @@ -498,16 +553,7 @@ static int of_state_fixup(struct device_node *root, void *ctx) goto out; } - /* backend phandle */ - backend_node = of_find_node_by_reproducible_name(root, - state->backend_reproducible_name); - if (!backend_node) { - ret = -ENODEV; - goto out; - } - - phandle = of_node_create_phandle(backend_node); - ret = of_property_write_u32(new_node, "backend", phandle); + ret = state_get_backend(state, root, new_node); if (ret) goto out; diff --git a/include/state.h b/include/state.h index 3daf82c0735f..d0034506f6e3 100644 --- a/include/state.h +++ b/include/state.h @@ -22,6 +22,7 @@ void state_info(void); int state_read_mac(struct state *state, const char *name, u8 *buf); +int of_state_fixup(struct device_node *root, void *ctx); #else /* #if IS_ENABLED(CONFIG_STATE) */ static inline struct state *state_new_from_node(struct device_node *node, @@ -60,6 +61,10 @@ static inline int state_read_mac(struct state *state, const char *name, u8 *buf) return -ENOSYS; } +static inline int of_state_fixup(struct device_node *root, void *ctx) +{ + return -ENOSYS; +} #endif /* #if IS_ENABLED(CONFIG_STATE) / #else */ #define BAREBOX_STATE_PARTITION_GUID \
