All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.