diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2008-01-11 14:55:05 +1100 |
---|---|---|
committer | Jon Loeliger <jdl@freescale.com> | 2008-01-11 07:40:40 -0600 |
commit | 82b327d38062cdb4e5628856f9b440ad6c96e7f8 (patch) | |
tree | 010dc350ff10ddf0a85494acbde229c0bc405548 | |
parent | 7364cc79b5fa11e416dce01802139bc87d690118 (diff) | |
download | dtc-82b327d38062cdb4e5628856f9b440ad6c96e7f8.tar.gz |
libfdt: Add fdt_set_name() function
This patch adds an fdt_set_name() function to libfdt, mirroring
fdt_get_name(). This is a r/w function which alters the name of a
given device tree node.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
-rw-r--r-- | libfdt/fdt_rw.c | 24 | ||||
-rw-r--r-- | libfdt/libfdt.h | 26 | ||||
-rw-r--r-- | tests/Makefile.tests | 2 | ||||
-rwxr-xr-x | tests/run_tests.sh | 1 | ||||
-rw-r--r-- | tests/set_name.c | 91 |
5 files changed, 143 insertions, 1 deletions
diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 6673f8e..a1c70ff 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -252,6 +252,30 @@ static int _add_property(void *fdt, int nodeoffset, const char *name, int len, return 0; } +int fdt_set_name(void *fdt, int nodeoffset, const char *name) +{ + char *namep; + int oldlen, newlen; + int err; + + if ((err = rw_check_header(fdt))) + return err; + + namep = (char *)fdt_get_name(fdt, nodeoffset, &oldlen); + if (!namep) + return oldlen; + + newlen = strlen(name); + + err = _blob_splice_struct(fdt, namep, ALIGN(oldlen+1, FDT_TAGSIZE), + ALIGN(newlen+1, FDT_TAGSIZE)); + if (err) + return err; + + memcpy(namep, name, newlen+1); + return 0; +} + int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len) { diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index ac0f5c3..d053689 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -846,6 +846,32 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); int fdt_del_mem_rsv(void *fdt, int n); /** + * fdt_set_name - change the name of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of a node + * @name: name to give the node + * + * fdt_set_name() replaces the name (including unit address, if any) + * of the given node with the given string. NOTE: this function can't + * efficiently check if the new name is unique amongst the given + * node's siblings; results are undefined if this function is invoked + * with a name equal to one of the given node's siblings. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob + * to contain the new name + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_set_name(void *fdt, int nodeoffset, const char *name); + +/** * fdt_setprop - create or change a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 8d17b89..0f4d342 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -8,7 +8,7 @@ LIB_TESTS_L = get_mem_rsv \ setprop_inplace nop_property nop_node \ sw_tree1 \ move_and_save mangle-layout \ - open_pack rw_tree1 setprop del_property del_node \ + open_pack rw_tree1 set_name setprop del_property del_node \ string_escapes references path-references \ dtbs_equal_ordered LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 83e8d62..d04bfbe 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -68,6 +68,7 @@ tree1_tests_rw () { TREE=$1 # Read-write tests + run_test set_name $TREE run_test setprop $TREE run_test del_property $TREE run_test del_node $TREE diff --git a/tests/set_name.c b/tests/set_name.c new file mode 100644 index 0000000..49817a9 --- /dev/null +++ b/tests/set_name.c @@ -0,0 +1,91 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_set_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_set_name(void *fdt, const char *path, const char *newname) +{ + int offset; + const char *getname, *oldname; + int len, err; + + oldname = strrchr(path, '/'); + if (!oldname) + TEST_BUG(); + oldname += 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, oldname) != 0) + FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"", + path, getname, oldname); + + if (len != strlen(getname)) + FAIL("fdt_get_name(%s) returned length %d instead of %zd", + path, len, strlen(getname)); + + err = fdt_set_name(fdt, offset, newname); + if (err) + FAIL("fdt_set_name(%d, \"%s\"): %s", offset, newname, + fdt_strerror(err)); + + getname = fdt_get_name(fdt, offset, &len); + if (!getname) + FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len)); + + if (strcmp(getname, newname) != 0) + FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"", + path, getname, newname); + + if (len != strlen(getname)) + FAIL("fdt_get_name(%s) returned length %d instead of %zd", + path, len, strlen(getname)); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + test_init(argc, argv); + fdt = load_blob_arg(argc, argv); + fdt = open_blob_rw(fdt); + + check_set_name(fdt, "/subnode@1", "subnode@17"); + check_set_name(fdt, "/subnode@2/subsubnode@0", "fred@0"); + check_set_name(fdt, "/subnode@17/subsubnode", "something@0"); + + PASS(); +} |