This patch adds fdt_get_phandle() and fdt_node_offset_by_phandle() functions to libfdt. fdt_get_phandle() will retreive the phandle value of a given node, and fdt_node_offset_by_phandle() will locate a node given a phandle.
Signed-off-by: David Gibson <[EMAIL PROTECTED]> Index: dtc/libfdt/libfdt.h =================================================================== --- dtc.orig/libfdt/libfdt.h 2007-11-12 19:11:55.000000000 +1100 +++ dtc/libfdt/libfdt.h 2007-11-12 20:11:12.000000000 +1100 @@ -78,29 +78,32 @@ /* FDT_ERR_BADPATH: Function was passed a badly formatted path * (e.g. missing a leading / for a function which requires an * absolute path) */ -#define FDT_ERR_BADSTATE 6 +#define FDT_ERR_BADPHANDLE 6 + /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle + * value. phandle values of 0 and -1 are not permitted. */ +#define FDT_ERR_BADSTATE 7 /* FDT_ERR_BADSTATE: Function was passed an incomplete device * tree created by the sequential-write functions, which is * not sufficiently complete for the requested operation. */ /* Error codes: codes for bad device tree blobs */ -#define FDT_ERR_TRUNCATED 7 +#define FDT_ERR_TRUNCATED 8 /* FDT_ERR_TRUNCATED: Structure block of the given device tree * ends without an FDT_END tag. */ -#define FDT_ERR_BADMAGIC 8 +#define FDT_ERR_BADMAGIC 9 /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a * device tree at all - it is missing the flattened device * tree magic number. */ -#define FDT_ERR_BADVERSION 9 +#define FDT_ERR_BADVERSION 10 /* FDT_ERR_BADVERSION: Given device tree has a version which * can't be handled by the requested operation. For * read-write functions, this may mean that fdt_open_into() is * required to convert the tree to the expected version. */ -#define FDT_ERR_BADSTRUCTURE 10 +#define FDT_ERR_BADSTRUCTURE 11 /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt * structure block or other serious error (e.g. misnested * nodes, or subnodes preceding properties). */ -#define FDT_ERR_BADLAYOUT 11 +#define FDT_ERR_BADLAYOUT 12 /* FDT_ERR_BADLAYOUT: For read-write functions, the given * device tree has it's sub-blocks in an order that the * function can't handle (memory reserve map, then structure, @@ -108,12 +111,12 @@ * into a form suitable for the read-write operations. */ /* "Can't happen" error indicating a bug in libfdt */ -#define FDT_ERR_INTERNAL 12 +#define FDT_ERR_INTERNAL 13 /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. * Should never be returned, if it is, it indicates a bug in * libfdt itself. */ -#define FDT_ERR_MAX 12 +#define FDT_ERR_MAX 13 /**********************************************************************/ /* Low-level functions (you probably don't need these) */ @@ -412,6 +415,20 @@ } /** + * fdt_get_phandle - retreive the phandle of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of the node + * + * fdt_get_phandle() retrieves the phandle of the device tree node at + * structure block offset nodeoffset. + * + * returns: + * the phandle of the node at nodeoffset, on succes (!= 0, != -1) + * 0, if the node has no phandle, or another error occurs + */ +uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); + +/** * fdt_get_path - determine the full path of a node * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose path to find @@ -558,6 +575,27 @@ const void *propval, int proplen); /** + * fdt_node_offset_by_phandle - find the node with a given phandle + * @fdt: pointer to the device tree blob + * @phandle: phandle value + * + * fdt_node_offset_by_prop_value() returns the offset of the node + * which has the given phandle value. If there is more than one node + * in the tree with the given phandle (an invalid tree), results are + * undefined. + * + * returns: + * structure block offset of the located node (>= 0), on success + * -FDT_ERR_NOTFOUND, no node with that phandle exists + * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1) + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); + +/** * fdt_node_check_compatible: check a node's compatible property * @fdt: pointer to the device tree blob * @nodeoffset: offset of a tree node Index: dtc/tests/testdata.h =================================================================== --- dtc.orig/tests/testdata.h 2007-11-12 19:11:55.000000000 +1100 +++ dtc/tests/testdata.h 2007-11-12 19:52:35.000000000 +1100 @@ -23,6 +23,9 @@ #define TEST_VALUE_1 cell_to_fdt(0xdeadbeef) #define TEST_VALUE_2 cell_to_fdt(123456789) +#define PHANDLE_1 0x2000 +#define PHANDLE_2 0x2001 + #define TEST_STRING_1 "hello world" #define TEST_STRING_2 "nastystring: \a\b\t\n\v\f\r\\\"" #define TEST_STRING_3 "\xde\xad\xbe\xef" Index: dtc/tests/trees.S =================================================================== --- dtc.orig/tests/trees.S 2007-11-12 19:11:55.000000000 +1100 +++ dtc/tests/trees.S 2007-11-12 19:52:49.000000000 +1100 @@ -100,9 +100,11 @@ END_NODE BEGIN_NODE("[EMAIL PROTECTED]") + PROP_INT(test_tree1, phandle, cell_to_fdt(PHANDLE_1)) PROP_INT(test_tree1, prop_int, TEST_VALUE_2) BEGIN_NODE("[EMAIL PROTECTED]") + PROP_INT(test_tree1, phandle, cell_to_fdt(PHANDLE_2)) PROP_STR(test_tree1, compatible, "subsubnode2\0subsubnode") PROP_INT(test_tree1, prop_int, TEST_VALUE_2) END_NODE @@ -116,6 +118,7 @@ STRING(test_tree1, compatible, "compatible") STRING(test_tree1, prop_int, "prop-int") STRING(test_tree1, prop_str, "prop-str") + STRING(test_tree1, phandle, "linux,phandle") test_tree1_strings_end: test_tree1_end: Index: dtc/tests/sw_tree1.c =================================================================== --- dtc.orig/tests/sw_tree1.c 2007-11-12 19:11:55.000000000 +1100 +++ dtc/tests/sw_tree1.c 2007-11-12 19:56:39.000000000 +1100 @@ -69,8 +69,10 @@ CHECK(fdt_end_node(fdt)); CHECK(fdt_begin_node(fdt, "[EMAIL PROTECTED]")); + CHECK(fdt_property_typed(fdt, "linux,phandle", cpu_to_fdt32(PHANDLE_1))); CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_2)); CHECK(fdt_begin_node(fdt, "[EMAIL PROTECTED]")); + CHECK(fdt_property_typed(fdt, "linux,phandle", cpu_to_fdt32(PHANDLE_2))); CHECK(fdt_property(fdt, "compatible", "subsubnode2\0subsubnode", 23)); CHECK(fdt_property_typed(fdt, "prop-int", TEST_VALUE_2)); Index: dtc/tests/test_tree1.dts =================================================================== --- dtc.orig/tests/test_tree1.dts 2007-11-12 19:42:00.000000000 +1100 +++ dtc/tests/test_tree1.dts 2007-11-12 19:42:02.000000000 +1100 @@ -19,9 +19,11 @@ }; [EMAIL PROTECTED] { + linux,phandle = <0x2000>; prop-int = <123456789>; [EMAIL PROTECTED] { + linux,phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; }; Index: dtc/tests/Makefile.tests =================================================================== --- dtc.orig/tests/Makefile.tests 2007-11-12 19:42:01.000000000 +1100 +++ dtc/tests/Makefile.tests 2007-11-13 09:34:30.000000000 +1100 @@ -1,7 +1,8 @@ LIB_TESTS_L = get_mem_rsv \ root_node find_property subnode_offset path_offset \ - get_name getprop get_path supernode_atdepth_offset parent_offset \ - node_offset_by_prop_value \ + get_name getprop get_phandle \ + get_path supernode_atdepth_offset parent_offset \ + node_offset_by_prop_value node_offset_by_phandle \ node_check_compatible node_offset_by_compatible \ notfound \ setprop_inplace nop_property nop_node \ Index: dtc/tests/get_phandle.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ dtc/tests/get_phandle.c 2007-11-12 19:53:11.000000000 +1100 @@ -0,0 +1,58 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_get_phandle() + * 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_phandle(void *fdt, const char *path, uint32_t checkhandle) +{ + int offset; + uint32_t phandle; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) + FAIL("Couldn't find %s", path); + + phandle = fdt_get_phandle(fdt, offset); + if (phandle != checkhandle) + FAIL("fdt_get_phandle(%s) returned 0x%x instead of 0x%x\n", + path, phandle, checkhandle); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + check_phandle(fdt, "/", 0); + check_phandle(fdt, "/[EMAIL PROTECTED]", PHANDLE_1); + check_phandle(fdt, "/[EMAIL PROTECTED]/[EMAIL PROTECTED]", PHANDLE_2); + + PASS(); +} Index: dtc/tests/run_tests.sh =================================================================== --- dtc.orig/tests/run_tests.sh 2007-11-12 19:42:00.000000000 +1100 +++ dtc/tests/run_tests.sh 2007-11-12 20:49:37.000000000 +1100 @@ -39,10 +39,12 @@ run_test path_offset $TREE run_test get_name $TREE run_test getprop $TREE + run_test get_phandle $TREE run_test get_path $TREE run_test supernode_atdepth_offset $TREE run_test parent_offset $TREE run_test node_offset_by_prop_value $TREE + run_test node_offset_by_phandle $TREE run_test node_check_compatible $TREE run_test node_offset_by_compatible $TREE run_test notfound $TREE @@ -131,12 +133,16 @@ run_test dtc.sh -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts run_test string_escapes dtc_escapes.test.dtb + run_test dtc.sh -I dts -O dtb -o dtc_references.test.dtb references.dts + run_test references dtc_references.test.dtb + # Check -Odts mode preserve all dtb information for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb ; do run_test dtc.sh -I dtb -O dts -o odts_$tree.test.dts $tree run_test dtc.sh -I dts -O dtb -o odts_$tree.test.dtb odts_$tree.test.dts run_test dtbs_equal_ordered $tree odts_$tree.test.dtb done + } while getopts "vdt:" ARG ; do Index: dtc/libfdt/fdt_ro.c =================================================================== --- dtc.orig/libfdt/fdt_ro.c 2007-11-12 19:11:55.000000000 +1100 +++ dtc/libfdt/fdt_ro.c 2007-11-12 20:08:39.000000000 +1100 @@ -293,6 +293,18 @@ return prop->data; } +uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) +{ + const uint32_t *php; + int len; + + php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); + if (!php || (len != sizeof(*php))) + return 0; + + return fdt32_to_cpu(*php); +} + int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) { uint32_t tag; @@ -478,6 +490,15 @@ return -FDT_ERR_NOTFOUND; } +int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) +{ + if ((phandle == 0) || (phandle == -1)) + return -FDT_ERR_BADPHANDLE; + phandle = cpu_to_fdt32(phandle); + return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle", + &phandle, sizeof(phandle)); +} + int _stringlist_contains(const void *strlist, int listlen, const char *str) { int len = strlen(str); Index: dtc/tests/rw_tree1.c =================================================================== --- dtc.orig/tests/rw_tree1.c 2007-11-12 19:11:55.000000000 +1100 +++ dtc/tests/rw_tree1.c 2007-11-12 19:57:10.000000000 +1100 @@ -85,8 +85,12 @@ CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_1)); OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "[EMAIL PROTECTED]")); + CHECK(fdt_setprop_typed(fdt, offset, "linux,phandle", + cpu_to_fdt32(PHANDLE_1))); CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_2)); OFF_CHECK(offset, fdt_add_subnode(fdt, offset, "[EMAIL PROTECTED]")); + CHECK(fdt_setprop_typed(fdt, offset, "linux,phandle", + cpu_to_fdt32(PHANDLE_2))); CHECK(fdt_setprop(fdt, offset, "compatible", "subsubnode2\0subsubnode", 23)); CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_2)); Index: dtc/tests/test_tree1_dts0.dts =================================================================== --- dtc.orig/tests/test_tree1_dts0.dts 2007-11-12 19:42:34.000000000 +1100 +++ dtc/tests/test_tree1_dts0.dts 2007-11-12 19:42:56.000000000 +1100 @@ -17,9 +17,11 @@ }; [EMAIL PROTECTED] { + linux,phandle = <2000>; prop-int = <d# 123456789>; [EMAIL PROTECTED] { + linux,phandle = <2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <o# 0726746425>; }; Index: dtc/tests/node_offset_by_phandle.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ dtc/tests/node_offset_by_phandle.c 2007-11-12 20:06:50.000000000 +1100 @@ -0,0 +1,64 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_node_offset_by_phandle() + * 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 <stdarg.h> + +#include <fdt.h> +#include <libfdt.h> + +#include "tests.h" +#include "testdata.h" + +void check_search(void *fdt, uint32_t phandle, int target) +{ + int offset; + + offset = fdt_node_offset_by_phandle(fdt, phandle); + + if (offset != target) + FAIL("fdt_node_offset_by_phandle(0x%x) returns %d " + "instead of %d", phandle, offset, target); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + int subnode2_offset, subsubnode2_offset; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + + subnode2_offset = fdt_path_offset(fdt, "/[EMAIL PROTECTED]"); + subsubnode2_offset = fdt_path_offset(fdt, "/[EMAIL PROTECTED]/[EMAIL PROTECTED]"); + + if ((subnode2_offset < 0) || (subsubnode2_offset < 0)) + FAIL("Can't find required nodes"); + + check_search(fdt, PHANDLE_1, subnode2_offset); + check_search(fdt, PHANDLE_2, subsubnode2_offset); + check_search(fdt, ~PHANDLE_1, -FDT_ERR_NOTFOUND); + check_search(fdt, 0, -FDT_ERR_BADPHANDLE); + check_search(fdt, -1, -FDT_ERR_BADPHANDLE); + + PASS(); +} -- 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 _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev