linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* libfdt: Several new functions
@ 2007-08-30  4:52 David Gibson
  2007-08-30  4:54 ` [PATCH 2/3] libfdt: Add fdt_get_path() function David Gibson
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: David Gibson @ 2007-08-30  4:52 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-dev

This series of patches adds several new functions to libfdt.  These
are all read-only functions related to determining a given nodes node
and ancestry.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] libfdt: Add fdt_get_name() to retrieve a node's name
  2007-08-30  4:52 libfdt: Several new functions David Gibson
  2007-08-30  4:54 ` [PATCH 2/3] libfdt: Add fdt_get_path() function David Gibson
  2007-08-30  4:54 ` [PATCH 3/3] libfdt: Add fdt_parent_offset() and supporting functions David Gibson
@ 2007-08-30  4:54 ` David Gibson
  2007-08-30 13:52 ` libfdt: Several new functions Jon Loeliger
  3 siblings, 0 replies; 5+ messages in thread
From: David Gibson @ 2007-08-30  4:54 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-dev

This patch adds a new fdt_get_name() function to libfdt which will
return a node's name string (including unit address, if any).

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

---
 libfdt/fdt_ro.c      |   24 ++++++++++++++
 libfdt/libfdt.h      |    2 +
 tests/Makefile.tests |    3 +
 tests/get_name.c     |   83 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/run_tests.sh   |    1 
 5 files changed, 112 insertions(+), 1 deletion(-)

Index: dtc/libfdt/fdt_ro.c
===================================================================
--- dtc.orig/libfdt/fdt_ro.c	2007-08-29 13:14:06.000000000 +1000
+++ dtc/libfdt/fdt_ro.c	2007-08-29 14:09:29.000000000 +1000
@@ -169,6 +169,30 @@
 	return offset;	
 }
 
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
+{
+	const struct fdt_node_header *nh;
+	int err;
+
+	if ((err = _fdt_check_header(fdt)) != 0)
+		goto fail;
+
+	err = -FDT_ERR_BADOFFSET;
+	nh = fdt_offset_ptr(fdt, nodeoffset, sizeof(*nh));
+	if (!nh || (fdt32_to_cpu(nh->tag) != FDT_BEGIN_NODE))
+		goto fail;
+
+	if (len)
+		*len = strlen(nh->name);
+
+	return nh->name;
+
+ fail:
+	if (len)
+		*len = err;
+	return NULL;
+}
+
 const struct fdt_property *fdt_get_property(const void *fdt,
 					    int nodeoffset,
 					    const char *name, int *lenp)
Index: dtc/libfdt/libfdt.h
===================================================================
--- dtc.orig/libfdt/libfdt.h	2007-08-29 13:14:06.000000000 +1000
+++ dtc/libfdt/libfdt.h	2007-08-29 14:09:29.000000000 +1000
@@ -115,6 +115,8 @@
 
 int fdt_path_offset(const void *fdt, const char *path);
 
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *baselen);
+
 const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
 					    const char *name, int *lenp);
 
Index: dtc/tests/Makefile.tests
===================================================================
--- dtc.orig/tests/Makefile.tests	2007-08-29 13:14:06.000000000 +1000
+++ dtc/tests/Makefile.tests	2007-08-29 14:09:29.000000000 +1000
@@ -1,4 +1,5 @@
-LIB_TESTS_L = root_node find_property subnode_offset path_offset getprop \
+LIB_TESTS_L = root_node find_property subnode_offset path_offset \
+	get_name getprop \
 	notfound \
 	setprop_inplace nop_property nop_node \
 	sw_tree1 \
Index: dtc/tests/run_tests.sh
===================================================================
--- dtc.orig/tests/run_tests.sh	2007-08-29 13:14:06.000000000 +1000
+++ dtc/tests/run_tests.sh	2007-08-29 14:09:29.000000000 +1000
@@ -35,6 +35,7 @@
     run_test find_property $TREE
     run_test subnode_offset $TREE
     run_test path_offset $TREE
+    run_test get_name $TREE
     run_test getprop $TREE
     run_test notfound $TREE
 
Index: dtc/tests/get_name.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ dtc/tests/get_name.c	2007-08-29 13:14:50.000000000 +1000
@@ -0,0 +1,83 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ *	Testcase for fdt_get_name()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+void check_name(void *fdt, const char *path)
+{
+	int offset;
+	const char *getname, *getname2, *checkname;
+	int len;
+
+	checkname = strrchr(path, '/');
+	if (!checkname)
+		TEST_BUG();
+	checkname += 1;
+
+	offset = fdt_path_offset(fdt, path);
+	if (offset < 0)
+		FAIL("Couldn't find %s", path);
+
+	getname = fdt_get_name(fdt, offset, &len);
+	verbose_printf("fdt_get_name(%d) returns \"%s\" (len=%d)\n",
+		       offset, getname, len);
+	if (!getname)
+		FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len));
+
+	if (strcmp(getname, checkname) != 0)
+		FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"",
+		     path, getname, checkname);
+
+	if (len != strlen(getname))
+		FAIL("fdt_get_name(%s) returned length %d instead of %d",
+		     path, len, strlen(getname));
+
+	/* Now check that it doesn't break if we omit len */
+	getname2 = fdt_get_name(fdt, offset, NULL);
+	if (!getname2)
+		FAIL("fdt_get_name(%d, NULL) failed", offset);
+	if (strcmp(getname2, getname) != 0)
+		FAIL("fdt_get_name(%d, NULL) returned \"%s\" instead of \"%s\"",
+		     offset, getname2, getname);
+}
+
+int main(int argc, char *argv[])
+{
+	void *fdt;
+
+	test_init(argc, argv);
+	fdt = load_blob_arg(argc, argv);
+
+	check_name(fdt, "/");
+	check_name(fdt, "/subnode1");
+	check_name(fdt, "/subnode2");
+	check_name(fdt, "/subnode1/subsubnode");
+	check_name(fdt, "/subnode2/subsubnode");
+
+	PASS();
+}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 2/3] libfdt: Add fdt_get_path() function
  2007-08-30  4:52 libfdt: Several new functions David Gibson
@ 2007-08-30  4:54 ` David Gibson
  2007-08-30  4:54 ` [PATCH 3/3] libfdt: Add fdt_parent_offset() and supporting functions David Gibson
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: David Gibson @ 2007-08-30  4:54 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-dev

This patch adds an fdt_get_path() function to libfdt, which returns
the full path of a given node in a caller supplied buffer.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

---
 libfdt/fdt_ro.c      |   66 ++++++++++++++++++++++++++++++++++++
 libfdt/libfdt.h      |    2 +
 tests/Makefile.tests |    2 -
 tests/get_path.c     |   91 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/run_tests.sh   |    1 
 5 files changed, 161 insertions(+), 1 deletion(-)

Index: dtc/libfdt/fdt_ro.c
===================================================================
--- dtc.orig/libfdt/fdt_ro.c	2007-08-29 14:09:52.000000000 +1000
+++ dtc/libfdt/fdt_ro.c	2007-08-29 14:28:32.000000000 +1000
@@ -283,3 +283,69 @@
 
 	return prop->data;
 }
+
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
+{
+	uint32_t tag;
+	int p = 0, overflow = 0;
+	int offset, nextoffset, namelen;
+	const char *name;
+
+	CHECK_HEADER(fdt);
+
+	tag = _fdt_next_tag(fdt, 0, &nextoffset);
+	if (tag != FDT_BEGIN_NODE)
+		return -FDT_ERR_BADSTRUCTURE;
+
+	if (buflen < 2)
+		return -FDT_ERR_NOSPACE;
+	buf[0] = '/';
+	p = 1;
+
+	while (offset < nodeoffset) {
+		offset = nextoffset;
+		tag = _fdt_next_tag(fdt, offset, &nextoffset);
+		switch (tag) {
+		case FDT_END:
+			return -FDT_ERR_BADOFFSET;
+
+		case FDT_BEGIN_NODE:
+			name = fdt_get_name(fdt, offset, &namelen);
+			if (!name)
+				return namelen;
+			if (overflow || ((p + namelen + 1) > buflen)) {
+				overflow++;
+				break;
+			}
+			memcpy(buf + p, name, namelen);
+			p += namelen;
+			buf[p++] = '/';
+			break;
+
+		case FDT_END_NODE:
+			if (overflow) {
+				overflow--;
+				break;
+			}
+			do {
+				p--;
+			} while  (buf[p-1] != '/');
+			break;
+
+		case FDT_PROP:
+		case FDT_NOP:
+			break;
+
+		default:
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+	}
+
+	if (overflow)
+		return -FDT_ERR_NOSPACE;
+
+	if (p > 1) /* special case so that root path is "/", not "" */
+		p--;
+	buf[p] = '\0';
+	return p;
+}
Index: dtc/tests/get_path.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ dtc/tests/get_path.c	2007-08-29 14:09:53.000000000 +1000
@@ -0,0 +1,91 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ *	Testcase for fdt_get_path()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define POISON	('\xff')
+
+void check_path_buf(void *fdt, const char *path, int pathlen, int buflen)
+{
+	int offset;
+	char buf[buflen+1];
+	int len;
+
+	offset = fdt_path_offset(fdt, path);
+	if (offset < 0)
+		FAIL("Couldn't find path \"%s\": %s", path, fdt_strerror(offset));
+
+	memset(buf, POISON, sizeof(buf)); /* poison the buffer */
+
+	len = fdt_get_path(fdt, offset, buf, buflen);
+	if (buflen <= pathlen) {
+		if (len != -FDT_ERR_NOSPACE)
+			FAIL("fdt_get_path([%d bytes]) returns %d with "
+			     "insufficient buffer space", buflen, len);
+	} else {
+		if (len < 0)
+			FAIL("fdt_get_path([%d bytes]): %s", buflen,
+			     fdt_strerror(len));
+		if (len != pathlen)
+			FAIL("fdt_get_path([%d bytes]) reports length %d "
+			     "instead of %d", buflen, len, pathlen);
+		if (strcmp(buf, path) != 0)
+			FAIL("fdt_get_path([%d bytes]) returns \"%s\" "
+			     "instead of \"%s\"", buflen, buf, path);
+	}
+
+	if (buf[buflen] != POISON)
+		FAIL("fdt_get_path([%d bytes]) overran buffer", buflen);
+}
+
+void check_path(void *fdt, const char *path)
+{
+	int pathlen = strlen(path);
+
+	check_path_buf(fdt, path, pathlen, 1024);
+	check_path_buf(fdt, path, pathlen, pathlen+1);
+	check_path_buf(fdt, path, pathlen, pathlen);
+}
+
+int main(int argc, char *argv[])
+{
+	void *fdt;
+
+	test_init(argc, argv);
+	fdt = load_blob_arg(argc, argv);
+
+	check_path(fdt, "/");
+	check_path(fdt, "/subnode1");
+	check_path(fdt, "/subnode2");
+	check_path(fdt, "/subnode1/subsubnode");
+	check_path(fdt, "/subnode2/subsubnode");
+
+	PASS();
+}
Index: dtc/tests/Makefile.tests
===================================================================
--- dtc.orig/tests/Makefile.tests	2007-08-29 14:09:52.000000000 +1000
+++ dtc/tests/Makefile.tests	2007-08-29 14:09:53.000000000 +1000
@@ -1,5 +1,5 @@
 LIB_TESTS_L = root_node find_property subnode_offset path_offset \
-	get_name getprop \
+	get_name getprop get_path \
 	notfound \
 	setprop_inplace nop_property nop_node \
 	sw_tree1 \
Index: dtc/tests/run_tests.sh
===================================================================
--- dtc.orig/tests/run_tests.sh	2007-08-29 14:09:52.000000000 +1000
+++ dtc/tests/run_tests.sh	2007-08-29 14:09:53.000000000 +1000
@@ -37,6 +37,7 @@
     run_test path_offset $TREE
     run_test get_name $TREE
     run_test getprop $TREE
+    run_test get_path $TREE
     run_test notfound $TREE
 
     # Write-in-place tests
Index: dtc/libfdt/libfdt.h
===================================================================
--- dtc.orig/libfdt/libfdt.h	2007-08-29 14:09:52.000000000 +1000
+++ dtc/libfdt/libfdt.h	2007-08-29 14:10:28.000000000 +1000
@@ -136,6 +136,8 @@
 	return (void *)fdt_getprop(fdt, nodeoffset, name, lenp);
 }
 
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
+
 /* Write-in-place functions */
 int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
 			const void *val, int len);

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 3/3] libfdt: Add fdt_parent_offset() and supporting functions
  2007-08-30  4:52 libfdt: Several new functions David Gibson
  2007-08-30  4:54 ` [PATCH 2/3] libfdt: Add fdt_get_path() function David Gibson
@ 2007-08-30  4:54 ` David Gibson
  2007-08-30  4:54 ` [PATCH 1/3] libfdt: Add fdt_get_name() to retrieve a node's name David Gibson
  2007-08-30 13:52 ` libfdt: Several new functions Jon Loeliger
  3 siblings, 0 replies; 5+ messages in thread
From: David Gibson @ 2007-08-30  4:54 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-dev

This patch adds an fdt_parent_offset() function which returns an
offset to the parent node of a given node.  It also adds two helper
functions which are used to implement fdt_parent_offset() but are also
exported: fdt_supernode_atdepth_offset() which returns the ancestor of
a given node at a specified depth from the root of the tree, and
fdt_node_depth() which returns the depth of a given node.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

---
 libfdt/fdt_ro.c                  |   68 ++++++++++++++++++
 libfdt/libfdt.h                  |   10 ++
 tests/Makefile.tests             |    2 
 tests/parent_offset.c            |   90 ++++++++++++++++++++++++
 tests/run_tests.sh               |    2 
 tests/supernode_atdepth_offset.c |  144 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 314 insertions(+), 2 deletions(-)

Index: dtc/libfdt/fdt_ro.c
===================================================================
--- dtc.orig/libfdt/fdt_ro.c	2007-08-29 14:28:32.000000000 +1000
+++ dtc/libfdt/fdt_ro.c	2007-08-30 14:28:35.000000000 +1000
@@ -349,3 +349,71 @@ int fdt_get_path(const void *fdt, int no
 	buf[p] = '\0';
 	return p;
 }
+
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+				 int supernodedepth, int *nodedepth)
+{
+	int level = -1;
+	uint32_t tag;
+	int offset, nextoffset = 0;
+	int supernodeoffset = -FDT_ERR_INTERNAL;
+
+	CHECK_HEADER(fdt);
+
+	if (supernodedepth < 0)
+		return -FDT_ERR_NOTFOUND;
+
+	do {
+		offset = nextoffset;
+		tag = _fdt_next_tag(fdt, offset, &nextoffset);
+		switch (tag) {
+		case FDT_END:
+			return -FDT_ERR_BADOFFSET;
+
+		case FDT_BEGIN_NODE:
+			level++;
+			if (level == supernodedepth)
+				supernodeoffset = offset;
+			break;
+
+		case FDT_END_NODE:
+			level--;
+			break;
+
+		case FDT_PROP:
+		case FDT_NOP:
+			break;
+
+		default:
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+	} while (offset < nodeoffset);
+
+	if (nodedepth)
+		*nodedepth = level;
+
+	if (supernodedepth > level)
+		return -FDT_ERR_NOTFOUND;
+	return supernodeoffset;
+}
+
+int fdt_node_depth(const void *fdt, int nodeoffset)
+{
+	int nodedepth;
+	int err;
+
+	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
+	if (err)
+		return (err < 0) ? err : -FDT_ERR_INTERNAL;
+	return nodedepth;
+}
+
+int fdt_parent_offset(const void *fdt, int nodeoffset)
+{
+	int nodedepth = fdt_node_depth(fdt, nodeoffset);
+
+	if (nodedepth < 0)
+		return nodedepth;
+	return fdt_supernode_atdepth_offset(fdt, nodeoffset,
+					    nodedepth - 1, NULL);
+}
Index: dtc/libfdt/libfdt.h
===================================================================
--- dtc.orig/libfdt/libfdt.h	2007-08-30 13:26:56.000000000 +1000
+++ dtc/libfdt/libfdt.h	2007-08-30 14:26:40.000000000 +1000
@@ -74,7 +74,10 @@
 #define FDT_ERR_BADSTRUCTURE	10
 #define FDT_ERR_BADLAYOUT	11
 
-#define FDT_ERR_MAX		11
+/* "Can't happen" error indicating a bug in libfdt */
+#define FDT_ERR_INTERNAL	12
+
+#define FDT_ERR_MAX		12
 
 #define fdt_get_header(fdt, field) \
 	(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
@@ -138,6 +141,11 @@ static inline void *fdt_getprop_w(void *
 
 int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
 
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+				 int supernodedepth, int *nodedepth);
+int fdt_node_depth(const void *fdt, int nodeoffset);
+int fdt_parent_offset(const void *fdt, int nodeoffset);
+
 /* Write-in-place functions */
 int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
 			const void *val, int len);
Index: dtc/tests/Makefile.tests
===================================================================
--- dtc.orig/tests/Makefile.tests	2007-08-30 13:43:53.000000000 +1000
+++ dtc/tests/Makefile.tests	2007-08-30 14:17:07.000000000 +1000
@@ -1,5 +1,5 @@
 LIB_TESTS_L = root_node find_property subnode_offset path_offset \
-	get_name getprop get_path \
+	get_name getprop get_path supernode_atdepth_offset parent_offset \
 	notfound \
 	setprop_inplace nop_property nop_node \
 	sw_tree1 \
Index: dtc/tests/run_tests.sh
===================================================================
--- dtc.orig/tests/run_tests.sh	2007-08-30 13:44:15.000000000 +1000
+++ dtc/tests/run_tests.sh	2007-08-30 14:17:14.000000000 +1000
@@ -38,6 +38,8 @@ tree1_tests () {
     run_test get_name $TREE
     run_test getprop $TREE
     run_test get_path $TREE
+    run_test supernode_atdepth_offset $TREE
+    run_test parent_offset $TREE
     run_test notfound $TREE
 
     # Write-in-place tests
Index: dtc/tests/supernode_atdepth_offset.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ dtc/tests/supernode_atdepth_offset.c	2007-08-30 13:51:45.000000000 +1000
@@ -0,0 +1,144 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ *	Testcase for fdt_supernode_atdepth_offset()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int path_depth(const char *path)
+{
+	const char *p;
+	int depth = 0;
+
+	if (path[0] != '/')
+		TEST_BUG();
+
+	if (strcmp(path, "/") == 0)
+		return 0;
+	for (p = path; *p; p++)
+		if (*p == '/')
+			depth++;
+
+	/* Special case for path == "/" */
+	if (p == (path + 1))
+		return 0;
+	else
+		return depth;
+}
+
+int path_prefix(const char *path, int depth)
+{
+	const char *p;
+	int i;
+
+	if (path[0] != '/')
+		TEST_BUG();
+
+	if (depth == 0)
+		return 1;
+
+	p = path;
+	for (i = 0; i < depth; i++)
+		p = strchrnul(p+1, '/');
+
+	return p - path;
+}
+
+void check_supernode_atdepth(struct fdt_header *fdt, const char *path,
+			     int depth)
+{
+	int pdepth = path_depth(path);
+	char *superpath;
+	int nodeoffset, supernodeoffset, superpathoffset;
+	int nodedepth;
+
+	superpath = strndupa(path, path_prefix(path, depth));
+	verbose_printf("Path %s (%d), depth %d, supernode is %s\n",
+		       path, pdepth, depth, superpath);
+
+	nodeoffset = fdt_path_offset(fdt, path);
+	if (nodeoffset < 0)
+		FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(nodeoffset));
+	superpathoffset = fdt_path_offset(fdt, superpath);
+	if (superpathoffset < 0)
+		FAIL("fdt_path_offset(%s): %s", superpath,
+		     fdt_strerror(superpathoffset));
+
+	supernodeoffset = fdt_supernode_atdepth_offset(fdt, nodeoffset,
+						       depth, &nodedepth);
+	if (supernodeoffset < 0)
+		FAIL("fdt_supernode_atdepth_offset(): %s",
+		     fdt_strerror(supernodeoffset));
+
+	if (supernodeoffset != superpathoffset)
+		FAIL("fdt_supernode_atdepth_offset() returns %d instead of %d",
+		     supernodeoffset, superpathoffset);
+
+	if (nodedepth != pdepth)
+		FAIL("fdt_supernode_atdept_offset() returns node depth %d "
+		     "instead of %d", nodedepth, pdepth);
+}
+
+void check_supernode_overdepth(struct fdt_header *fdt, const char *path)
+{
+	int pdepth = path_depth(path);
+	int nodeoffset, err;
+
+	nodeoffset = fdt_path_offset(fdt, path);
+	if (nodeoffset < 0)
+		FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(nodeoffset));
+
+	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, pdepth + 1, NULL);
+	if (err != -FDT_ERR_NOTFOUND)
+		FAIL("fdt_supernode_atdept_offset(%s, %d) returns %d instead "
+		     "of FDT_ERR_NOTFOUND", path, pdepth+1, err);
+}
+
+void check_path(struct fdt_header *fdt, const char *path)
+{
+	int i;
+
+	for (i = 0; i <= path_depth(path); i++)
+		check_supernode_atdepth(fdt, path, i);
+	check_supernode_overdepth(fdt, path);
+}
+int main(int argc, char *argv[])
+{
+	void *fdt;
+
+	test_init(argc, argv);
+	fdt = load_blob_arg(argc, argv);
+
+	check_path(fdt, "/");
+	check_path(fdt, "/subnode1");
+	check_path(fdt, "/subnode2");
+	check_path(fdt, "/subnode1/subsubnode");
+	check_path(fdt, "/subnode2/subsubnode");
+
+	PASS();
+}
Index: dtc/tests/parent_offset.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ dtc/tests/parent_offset.c	2007-08-30 14:21:10.000000000 +1000
@@ -0,0 +1,90 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ *	Testcase for fdt_parent_offset()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int path_parent_len(const char *path)
+{
+	const char *p = strrchr(path, '/');
+
+	if (!p)
+		TEST_BUG();
+	if (p == path)
+		return 1;
+	else
+		return p - path;
+}
+
+void check_path(struct fdt_header *fdt, const char *path)
+{
+	char *parentpath;
+	int nodeoffset, parentoffset, parentpathoffset;
+
+	parentpath = strndupa(path, path_parent_len(path));
+
+	verbose_printf("Path: \"%s\"\tParent: \"%s\"\n", path, parentpath);
+
+	nodeoffset = fdt_path_offset(fdt, path);
+	if (nodeoffset < 0)
+		FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(nodeoffset));
+
+	parentpathoffset = fdt_path_offset(fdt, parentpath);
+	if (parentpathoffset < 0)
+		FAIL("fdt_path_offset(%s): %s", parentpath,
+		     fdt_strerror(parentpathoffset));
+
+	parentoffset = fdt_parent_offset(fdt, nodeoffset);
+	if (parentoffset < 0)
+		FAIL("fdt_parent_offset(): %s", fdt_strerror(parentoffset));
+
+	if (parentoffset != parentpathoffset)
+		FAIL("fdt_parent_offset() returns %d instead of %d",
+		     parentoffset, parentpathoffset);
+}
+
+int main(int argc, char *argv[])
+{
+	void *fdt;
+	int err;
+
+	test_init(argc, argv);
+	fdt = load_blob_arg(argc, argv);
+
+	check_path(fdt, "/subnode1");
+	check_path(fdt, "/subnode2");
+	check_path(fdt, "/subnode1/subsubnode");
+	check_path(fdt, "/subnode2/subsubnode");
+	err = fdt_parent_offset(fdt, 0);
+	if (err != -FDT_ERR_NOTFOUND)
+		FAIL("fdt_parent_offset(/) returns %d instead of "
+		     "-FDT_ERR_NOTFOUND", err);
+
+	PASS();
+}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: libfdt: Several new functions
  2007-08-30  4:52 libfdt: Several new functions David Gibson
                   ` (2 preceding siblings ...)
  2007-08-30  4:54 ` [PATCH 1/3] libfdt: Add fdt_get_name() to retrieve a node's name David Gibson
@ 2007-08-30 13:52 ` Jon Loeliger
  3 siblings, 0 replies; 5+ messages in thread
From: Jon Loeliger @ 2007-08-30 13:52 UTC (permalink / raw)
  To: David Gibson; +Cc: linuxppc-dev

So, like, the other day David Gibson mumbled:
> This series of patches adds several new functions to libfdt.  These
> are all read-only functions related to determining a given nodes node
> and ancestry.

All three pplied.

Thanks,
jdl

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2007-08-30 13:52 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-08-30  4:52 libfdt: Several new functions David Gibson
2007-08-30  4:54 ` [PATCH 2/3] libfdt: Add fdt_get_path() function David Gibson
2007-08-30  4:54 ` [PATCH 3/3] libfdt: Add fdt_parent_offset() and supporting functions David Gibson
2007-08-30  4:54 ` [PATCH 1/3] libfdt: Add fdt_get_name() to retrieve a node's name David Gibson
2007-08-30 13:52 ` libfdt: Several new functions Jon Loeliger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).