diff mbox series

[v3,07/22] libpdbg: Create virtual nodes based on system-path property

Message ID 20190923084841.18057-8-amitay@ozlabs.org
State Superseded
Headers show
Series Add system device tree to libpdbg | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch success Successfully applied on branch master (1a147598c63a3db8e97c654fe1e46ef806515f4d)
snowpatch_ozlabs/build-multiarch success Test build-multiarch on branch master

Commit Message

Amitay Isaacs Sept. 23, 2019, 8:48 a.m. UTC
To create a virtual node, "system-path" property is used to denote the
attachment point in the system device tree view.

It's also possible to create virtual nodes from backend device tree as
nodes without compatible property.

All nodes without "compatible" property will be treated as virtual
nodes.

Signed-off-by: Amitay Isaacs <amitay@ozlabs.org>
---
 libpdbg/device.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)

Comments

Alistair Popple Sept. 26, 2019, 5:09 a.m. UTC | #1
Looks good now, thanks.

Reviewed-by: Alistair Popple <alistair@popple.id.au>

On Monday, 23 September 2019 6:48:26 PM AEST Amitay Isaacs wrote:
> To create a virtual node, "system-path" property is used to denote the
> attachment point in the system device tree view.
> 
> It's also possible to create virtual nodes from backend device tree as
> nodes without compatible property.
> 
> All nodes without "compatible" property will be treated as virtual
> nodes.
> 
> Signed-off-by: Amitay Isaacs <amitay@ozlabs.org>
> ---
>  libpdbg/device.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 92 insertions(+)
> 
> diff --git a/libpdbg/device.c b/libpdbg/device.c
> index 9cb2a0a..960d23a 100644
> --- a/libpdbg/device.c
> +++ b/libpdbg/device.c
> @@ -649,6 +649,97 @@ uint64_t pdbg_target_address(struct pdbg_target *target, uint64_t *out_size)
>  	return dt_get_number(p->prop, na);
>  }
>  
> +static struct pdbg_target *dt_new_virtual(struct pdbg_target *root, const char *system_path)
> +{
> +	char *parent_path, *sep;
> +	struct pdbg_target *parent, *vnode;
> +
> +	parent_path = strdup(system_path);
> +	assert(parent_path);
> +
> +	sep = strrchr(parent_path, '/');
> +	if (!sep || sep[1] == '\0') {
> +		PR_ERROR("Invalid path reference \"%s\"\n", system_path);
> +		free(parent_path);
> +		return NULL;
> +	}
> +
> +	*sep = '\0';
> +
> +	parent = dt_find_by_path(root, parent_path);
> +	if (!parent) {
> +		PR_ERROR("Invalid path reference \"%s\"\n", system_path);
> +		free(parent_path);
> +		return NULL;
> +	}
> +
> +	vnode = dt_new_node(sep+1, NULL, 0);
> +	assert(vnode);
> +
> +	free(parent_path);
> +
> +	if (!dt_attach_node(parent, vnode)) {
> +		free(vnode);
> +		return NULL;
> +	}
> +
> +	PR_DEBUG("Created virtual node %s\n", system_path);
> +	return vnode;
> +}
> +
> +static void dt_link_virtual(struct pdbg_target *node, struct pdbg_target *vnode)
> +{
> +	struct dt_property *prop;
> +
> +	node->vnode = vnode;
> +	vnode->vnode = node;
> +
> +	/* Move any properties on virtual node to real node */
> +	while ((prop = list_pop(&vnode->properties, struct dt_property, list)))
> +		list_add_tail(&node->properties, &prop->list);
> +}
> +
> +static void pdbg_targets_init_virtual(struct pdbg_target *node, struct pdbg_target *root)
> +{
> +	struct pdbg_target *vnode, *child = NULL;
> +	const char *system_path;
> +	size_t len;
> +
> +	system_path = (const char *)pdbg_target_property(node, "system-path", &len);
> +	if (!system_path)
> +		goto skip;
> +
> +	/*
> +	 * A virtual node identifies the attachment point of a node in the
> +	 * system tree.
> +	 */
> +	vnode = dt_find_by_path(root, system_path);
> +	if (!vnode)
> +		vnode = dt_new_virtual(root, system_path);
> +
> +	/* If virtual node does not exist, or cannot be created, skip */
> +	if (!vnode)
> +		goto skip;
> +
> +	/* A node is virtual if compatible is set to NULL.  */
> +	assert(!vnode->compatible);
> +
> +	/*
> +	 * If virtual node is not linked, then link with node;
> +	 * otherwise skip
> +	 */
> +	if (!vnode->vnode)
> +		dt_link_virtual(node, vnode);
> +
> +skip:
> +	list_for_each(&node->children, child, list) {
> +		if (child->vnode && !child->compatible)
> +			continue;
> +
> +		pdbg_targets_init_virtual(child, root);
> +	}
> +}
> +
>  void pdbg_targets_init(void *fdt)
>  {
>  	/* Root node needs to be valid when this function returns */
> @@ -663,6 +754,7 @@ void pdbg_targets_init(void *fdt)
>  	}
>  
>  	dt_expand(pdbg_dt_root, fdt);
> +	pdbg_targets_init_virtual(pdbg_dt_root, pdbg_dt_root);
>  }
>  
>  char *pdbg_target_path(struct pdbg_target *target)
>
diff mbox series

Patch

diff --git a/libpdbg/device.c b/libpdbg/device.c
index 9cb2a0a..960d23a 100644
--- a/libpdbg/device.c
+++ b/libpdbg/device.c
@@ -649,6 +649,97 @@  uint64_t pdbg_target_address(struct pdbg_target *target, uint64_t *out_size)
 	return dt_get_number(p->prop, na);
 }
 
+static struct pdbg_target *dt_new_virtual(struct pdbg_target *root, const char *system_path)
+{
+	char *parent_path, *sep;
+	struct pdbg_target *parent, *vnode;
+
+	parent_path = strdup(system_path);
+	assert(parent_path);
+
+	sep = strrchr(parent_path, '/');
+	if (!sep || sep[1] == '\0') {
+		PR_ERROR("Invalid path reference \"%s\"\n", system_path);
+		free(parent_path);
+		return NULL;
+	}
+
+	*sep = '\0';
+
+	parent = dt_find_by_path(root, parent_path);
+	if (!parent) {
+		PR_ERROR("Invalid path reference \"%s\"\n", system_path);
+		free(parent_path);
+		return NULL;
+	}
+
+	vnode = dt_new_node(sep+1, NULL, 0);
+	assert(vnode);
+
+	free(parent_path);
+
+	if (!dt_attach_node(parent, vnode)) {
+		free(vnode);
+		return NULL;
+	}
+
+	PR_DEBUG("Created virtual node %s\n", system_path);
+	return vnode;
+}
+
+static void dt_link_virtual(struct pdbg_target *node, struct pdbg_target *vnode)
+{
+	struct dt_property *prop;
+
+	node->vnode = vnode;
+	vnode->vnode = node;
+
+	/* Move any properties on virtual node to real node */
+	while ((prop = list_pop(&vnode->properties, struct dt_property, list)))
+		list_add_tail(&node->properties, &prop->list);
+}
+
+static void pdbg_targets_init_virtual(struct pdbg_target *node, struct pdbg_target *root)
+{
+	struct pdbg_target *vnode, *child = NULL;
+	const char *system_path;
+	size_t len;
+
+	system_path = (const char *)pdbg_target_property(node, "system-path", &len);
+	if (!system_path)
+		goto skip;
+
+	/*
+	 * A virtual node identifies the attachment point of a node in the
+	 * system tree.
+	 */
+	vnode = dt_find_by_path(root, system_path);
+	if (!vnode)
+		vnode = dt_new_virtual(root, system_path);
+
+	/* If virtual node does not exist, or cannot be created, skip */
+	if (!vnode)
+		goto skip;
+
+	/* A node is virtual if compatible is set to NULL.  */
+	assert(!vnode->compatible);
+
+	/*
+	 * If virtual node is not linked, then link with node;
+	 * otherwise skip
+	 */
+	if (!vnode->vnode)
+		dt_link_virtual(node, vnode);
+
+skip:
+	list_for_each(&node->children, child, list) {
+		if (child->vnode && !child->compatible)
+			continue;
+
+		pdbg_targets_init_virtual(child, root);
+	}
+}
+
 void pdbg_targets_init(void *fdt)
 {
 	/* Root node needs to be valid when this function returns */
@@ -663,6 +754,7 @@  void pdbg_targets_init(void *fdt)
 	}
 
 	dt_expand(pdbg_dt_root, fdt);
+	pdbg_targets_init_virtual(pdbg_dt_root, pdbg_dt_root);
 }
 
 char *pdbg_target_path(struct pdbg_target *target)