* 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.