Browse Source

libfdt: Add phandle related functions

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 <david@gibson.dropbear.id.au>
main
David Gibson 17 years ago committed by Jon Loeliger
parent
commit
7346858f81
  1. 21
      libfdt/fdt_ro.c
  2. 54
      libfdt/libfdt.h
  3. 5
      tests/Makefile.tests
  4. 58
      tests/get_phandle.c
  5. 64
      tests/node_offset_by_phandle.c
  6. 6
      tests/run_tests.sh
  7. 4
      tests/rw_tree1.c
  8. 2
      tests/sw_tree1.c
  9. 2
      tests/test_tree1.dts
  10. 2
      tests/test_tree1_dts0.dts
  11. 3
      tests/testdata.h
  12. 3
      tests/trees.S

21
libfdt/fdt_ro.c

@ -293,6 +293,18 @@ const void *fdt_getprop(const void *fdt, int nodeoffset, @@ -293,6 +293,18 @@ const void *fdt_getprop(const void *fdt, int nodeoffset,
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 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, @@ -478,6 +490,15 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
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);

54
libfdt/libfdt.h

@ -78,29 +78,32 @@ @@ -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 @@ @@ -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) */
@ -411,6 +414,20 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset, @@ -411,6 +414,20 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
return (void *)fdt_getprop(fdt, nodeoffset, name, lenp);
}

/**
* 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
@ -557,6 +574,27 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, @@ -557,6 +574,27 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
const char *propname,
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

5
tests/Makefile.tests

@ -1,7 +1,8 @@ @@ -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 \

58
tests/get_phandle.c

@ -0,0 +1,58 @@ @@ -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, "/subnode@2", PHANDLE_1);
check_phandle(fdt, "/subnode@2/subsubnode@0", PHANDLE_2);

PASS();
}

64
tests/node_offset_by_phandle.c

@ -0,0 +1,64 @@ @@ -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, "/subnode@2");
subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode@0");

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();
}

6
tests/run_tests.sh

@ -38,10 +38,12 @@ tree1_tests () { @@ -38,10 +38,12 @@ tree1_tests () {
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
@ -130,12 +132,16 @@ dtc_tests () { @@ -130,12 +132,16 @@ dtc_tests () {
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

4
tests/rw_tree1.c

@ -85,8 +85,12 @@ int main(int argc, char *argv[]) @@ -85,8 +85,12 @@ int main(int argc, char *argv[])
CHECK(fdt_setprop_typed(fdt, offset, "prop-int", TEST_VALUE_1));

OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@2"));
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, "subsubnode@0"));
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));

2
tests/sw_tree1.c

@ -69,8 +69,10 @@ int main(int argc, char *argv[]) @@ -69,8 +69,10 @@ int main(int argc, char *argv[])
CHECK(fdt_end_node(fdt));

CHECK(fdt_begin_node(fdt, "subnode@2"));
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, "subsubnode@0"));
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));

2
tests/test_tree1.dts

@ -19,9 +19,11 @@ @@ -19,9 +19,11 @@
};

subnode@2 {
linux,phandle = <0x2000>;
prop-int = <123456789>;

subsubnode@0 {
linux,phandle = <0x2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <0726746425>;
};

2
tests/test_tree1_dts0.dts

@ -17,9 +17,11 @@ @@ -17,9 +17,11 @@
};

subnode@2 {
linux,phandle = <2000>;
prop-int = <d# 123456789>;

subsubnode@0 {
linux,phandle = <2001>;
compatible = "subsubnode2", "subsubnode";
prop-int = <o# 0726746425>;
};

3
tests/testdata.h

@ -23,6 +23,9 @@ @@ -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"

3
tests/trees.S

@ -100,9 +100,11 @@ test_tree1_struct: @@ -100,9 +100,11 @@ test_tree1_struct:
END_NODE

BEGIN_NODE("subnode@2")
PROP_INT(test_tree1, phandle, cell_to_fdt(PHANDLE_1))
PROP_INT(test_tree1, prop_int, TEST_VALUE_2)

BEGIN_NODE("subsubnode@0")
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 @@ test_tree1_strings: @@ -116,6 +118,7 @@ test_tree1_strings:
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:


Loading…
Cancel
Save