* [PATCH 1/2] libfdt: Add helpers to read #address-cells and #size-cells @ 2014-05-12 6:06 David Gibson [not found] ` <1399874771-23089-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> 0 siblings, 1 reply; 4+ messages in thread From: David Gibson @ 2014-05-12 6:06 UTC (permalink / raw) To: devicetree-compiler-u79uwXL29TY76Z2rM5mHXA Cc: jdl-ClAdetSTwOo, grant.likely-s3s/WqlpOiPyB63q8FvJNQ, robherring2-Re5JQEeQqe8AvxtiuMwx3w, scottwood-KZfg59tc24xl57MIdRCFDg, kim.phillips-KZfg59tc24xl57MIdRCFDg, galak-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, David Gibson This patch makes a small start on libfdt functions which actually help to parse the contents of device trees, rather than purely manipulating the tree's structure. We add simple helpers to read and sanity check the #address-cells and #size-cells values for a given node. Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> --- libfdt/Makefile.libfdt | 3 +- libfdt/fdt_addresses.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++ libfdt/libfdt.h | 62 +++++++++++++++++++++++++++++++- tests/.gitignore | 1 + tests/Makefile.tests | 1 + tests/addr_size_cells.c | 64 +++++++++++++++++++++++++++++++++ tests/addresses.dts | 15 ++++++++ tests/run_tests.sh | 3 ++ 8 files changed, 243 insertions(+), 2 deletions(-) create mode 100644 libfdt/fdt_addresses.c create mode 100644 tests/addr_size_cells.c create mode 100644 tests/addresses.dts diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt index 91126c0..09c322e 100644 --- a/libfdt/Makefile.libfdt +++ b/libfdt/Makefile.libfdt @@ -6,5 +6,6 @@ LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1 LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h LIBFDT_VERSION = version.lds -LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c +LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \ + fdt_addresses.c LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) diff --git a/libfdt/fdt_addresses.c b/libfdt/fdt_addresses.c new file mode 100644 index 0000000..eff4dbc --- /dev/null +++ b/libfdt/fdt_addresses.c @@ -0,0 +1,96 @@ +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2014 David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU 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 + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include <fdt.h> +#include <libfdt.h> + +#include "libfdt_internal.h" + +int fdt_address_cells(const void *fdt, int nodeoffset) +{ + const fdt32_t *ac; + int val; + int len; + + ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len); + if (!ac) + return 2; + + if (len != sizeof(*ac)) + return -FDT_ERR_BADNCELLS; + + val = fdt32_to_cpu(*ac); + if ((val <= 0) || (val > FDT_MAX_NCELLS)) + return -FDT_ERR_BADNCELLS; + + return val; +} + +int fdt_size_cells(const void *fdt, int nodeoffset) +{ + const fdt32_t *sc; + int val; + int len; + + sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len); + if (!sc) + return 2; + + if (len != sizeof(*sc)) + return -FDT_ERR_BADNCELLS; + + val = fdt32_to_cpu(*sc); + if ((val < 0) || (val > FDT_MAX_NCELLS)) + return -FDT_ERR_BADNCELLS; + + return val; +} diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index c4d5a91..32d5227 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -116,7 +116,12 @@ * Should never be returned, if it is, it indicates a bug in * libfdt itself. */ -#define FDT_ERR_MAX 13 +/* Errors in device tree content */ +#define FDT_ERR_BADNCELLS 14 + /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells + * or similar property with a bad format or value */ + +#define FDT_ERR_MAX 14 /**********************************************************************/ /* Low-level functions (you probably don't need these) */ @@ -853,6 +858,61 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); /**********************************************************************/ +/* Read-only functions (addressing related) */ +/**********************************************************************/ + +/** + * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells + * + * This is the maximum value for #address-cells, #size-cells and + * similar properties that will be processed by libfdt. IEE1275 + * requires that OF implementations handle values up to 4. + * Implementations may support larger values, but in practice higher + * values aren't used. + */ +#define FDT_MAX_NCELLS 4 + +/** + * fdt_address_cells - retrieve address size for a bus represented in the tree + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to find the address size for + * + * When the node has a valid #address-cells property, returns its value. + * + * returns: + * 0 <= n < FDT_MAX_NCELLS, on success + * 2, if the node has no #address-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid #address-cells property + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_address_cells(const void *fdt, int nodeoffset); + +/** + * fdt_size_cells - retrieve address range size for a bus represented in the + * tree + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to find the address range size for + * + * When the node has a valid #size-cells property, returns its value. + * + * returns: + * 0 <= n < FDT_MAX_NCELLS, on success + * 2, if the node has no #address-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid #size-cells property + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_size_cells(const void *fdt, int nodeoffset); + + +/**********************************************************************/ /* Write-in-place functions */ /**********************************************************************/ diff --git a/tests/.gitignore b/tests/.gitignore index bb5e33a..5656555 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -3,6 +3,7 @@ *.test.dts tmp.* /add_subnode_with_nops +/addr_size_cells /appendprop[12] /asm_tree_dump /boot-cpuid diff --git a/tests/Makefile.tests b/tests/Makefile.tests index dafb618..9adedec 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -8,6 +8,7 @@ LIB_TESTS_L = get_mem_rsv \ char_literal \ sized_cells \ notfound \ + addr_size_cells \ setprop_inplace nop_property nop_node \ sw_tree1 \ move_and_save mangle-layout nopulate \ diff --git a/tests/addr_size_cells.c b/tests/addr_size_cells.c new file mode 100644 index 0000000..6090d93 --- /dev/null +++ b/tests/addr_size_cells.c @@ -0,0 +1,64 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for #address-cells and #size-cells handling + * Copyright (C) 2014 David Gibson, <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> + * + * 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 <libfdt.h> + +#include "tests.h" +#include "testdata.h" + +static void check_node(const void *fdt, const char *path, int ac, int sc) +{ + int offset; + int xac, xsc; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) + FAIL("Couldn't find path %s", path); + + xac = fdt_address_cells(fdt, offset); + xsc = fdt_size_cells(fdt, offset); + + if (xac != ac) + FAIL("Address cells for %s is %d instead of %d\n", + path, xac, ac); + if (xsc != sc) + FAIL("Size cells for %s is %d instead of %d\n", + path, xsc, sc); +} + +int main(int argc, char *argv[]) +{ + void *fdt; + + if (argc != 2) + CONFIG("Usage: %s <dtb file>\n", argv[0]); + + test_init(argc, argv); + fdt = load_blob(argv[1]); + + check_node(fdt, "/", 2, 2); + check_node(fdt, "/identity-bus@0", 2, 2); + check_node(fdt, "/simple-bus@1000000", 2, 1); + PASS(); +} diff --git a/tests/addresses.dts b/tests/addresses.dts new file mode 100644 index 0000000..a2faaf5 --- /dev/null +++ b/tests/addresses.dts @@ -0,0 +1,15 @@ +/dts-v1/; + +/ { + compatible = "test_addresses"; + #address-cells = <2>; + #size-cells = <2>; + + identity-bus@0 { + }; + + simple-bus@1000000 { + #address-cells = <2>; + #size-cells = <1>; + }; +}; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 97e016b..f205ce6 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -188,6 +188,9 @@ ALL_LAYOUTS="mts mst tms tsm smt stm" libfdt_tests () { tree1_tests test_tree1.dtb + run_dtc_test -I dts -O dtb -o addresses.test.dtb addresses.dts + run_test addr_size_cells addresses.test.dtb + # Sequential write tests run_test sw_tree1 tree1_tests sw_tree1.test.dtb -- 1.9.0 -- To unsubscribe from this list: send the line "unsubscribe devicetree-compiler" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply related [flat|nested] 4+ messages in thread
[parent not found: <1399874771-23089-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>]
* [PATCH 2/2] libfdt: Add address translation functions [not found] ` <1399874771-23089-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> @ 2014-05-12 6:06 ` David Gibson [not found] ` <1399874771-23089-2-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> 0 siblings, 1 reply; 4+ messages in thread From: David Gibson @ 2014-05-12 6:06 UTC (permalink / raw) To: devicetree-compiler-u79uwXL29TY76Z2rM5mHXA Cc: jdl-ClAdetSTwOo, grant.likely-s3s/WqlpOiPyB63q8FvJNQ, robherring2-Re5JQEeQqe8AvxtiuMwx3w, scottwood-KZfg59tc24xl57MIdRCFDg, kim.phillips-KZfg59tc24xl57MIdRCFDg, galak-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, David Gibson Add the fdt_address_translate() function to process 'ranges' properties to translate addresses from one bus to another. Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> --- libfdt/fdt_addresses.c | 164 ++++++++++++++++++++++++++++++++++++++++++++ libfdt/libfdt.h | 46 ++++++++++++- tests/.gitignore | 1 + tests/Makefile.tests | 2 +- tests/addr_size_cells.c | 2 +- tests/address_translation.c | 121 ++++++++++++++++++++++++++++++++ tests/addresses.dts | 30 +++++++- tests/run_tests.sh | 1 + 8 files changed, 363 insertions(+), 4 deletions(-) create mode 100644 tests/address_translation.c diff --git a/libfdt/fdt_addresses.c b/libfdt/fdt_addresses.c index eff4dbc..78a641a 100644 --- a/libfdt/fdt_addresses.c +++ b/libfdt/fdt_addresses.c @@ -94,3 +94,167 @@ int fdt_size_cells(const void *fdt, int nodeoffset) return val; } + +static int _fdt_address_cmp(int sizea, const fdt32_t *a, + int sizeb, const fdt32_t *b) +{ + int n, i; + + if (sizea < sizeb) { + for (i = 0; i < (sizeb - sizea); i++) + if (b[i] != 0) + return -1; + + b += sizeb - sizea; + n = sizea; + } else if (sizeb < sizea) { + for (i = 0; i < (sizea - sizeb); i++) + if (a[i] != 0) + return 1; + a += sizea - sizeb; + n = sizeb; + } else { + n = sizea; + } + + for (i = 0; i < n; i++) { + fdt32_t ai = fdt32_to_cpu(a[i]); + fdt32_t bi = fdt32_to_cpu(b[i]); + + if (ai < bi) + return -1; + else if (bi < ai) + return 1; + } + + return 0; +} + +static int _fdt_address_diff(int size, const fdt32_t *a, const fdt32_t *b, + fdt32_t *diff) +{ + int i; + int borrow = 0; + + for (i = 0; i < size; i++) { + fdt32_t ai = fdt32_to_cpu(a[size - i - 1]); + fdt32_t bi = fdt32_to_cpu(b[size - i - 1]); + + diff[size - i - 1] = cpu_to_fdt32(ai - bi - borrow); + borrow = ai < (bi + borrow); + } + + return borrow ? -1 : 0; /* Negative result */ +} + +static int _fdt_address_add(int sizea, const fdt32_t *a, + int sizeb, const fdt32_t *b, + int size, fdt32_t *sum) +{ + int i; + int carry = 0; + + for (i = 0; i < (sizea - size); i++) + if (a[i]) + return -1; /* overflow */ + for (i = 0; i < (sizeb - size); i++) + if (b[i]) + return -1; /* overflow */ + + for (i = 0; i < size; i++) { + fdt32_t ai = (i < sizea) ? fdt32_to_cpu(a[sizea - i - 1]) : 0; + fdt32_t bi = (i < sizeb) ? fdt32_to_cpu(b[sizeb - i - 1]) : 0; + + sum[size - i - 1] = cpu_to_fdt32(ai + bi + carry); + carry = ((ai + bi) < ai) || ((ai + bi) < bi); + } + + if (carry) + return -1; /* overflow */ + + return 0; +} + +static int _fdt_address_apply_ranges(int ac, int sc, int pac, + const fdt32_t *ranges, int rlen, + const fdt32_t *addr, fdt32_t *paddr) +{ + int wcells = ac + sc + pac; + int i; + + /* No translation */ + if (!ranges) + return -FDT_ERR_NOTFOUND; /* No translation */ + + /* Identity translation */ + if (rlen == 0) { + if (ac != pac) + return -FDT_ERR_BADRANGES; + + memcpy(paddr, addr, sizeof(fdt32_t) * pac); + return 0; + } + + if (rlen % (wcells * sizeof(fdt32_t))) + return -FDT_ERR_BADRANGES; + + for (i = 0; i < (rlen / sizeof(fdt32_t) / wcells); i++) { + const fdt32_t *waddr = ranges + i * wcells; + const fdt32_t *wpaddr = waddr + ac; + const fdt32_t *wsize = wpaddr + pac; + fdt32_t offset[FDT_MAX_NCELLS]; + + if (_fdt_address_diff(ac, addr, waddr, offset) < 0) + continue; + + if (_fdt_address_cmp(ac, offset, sc, wsize) >= 0) + continue; + + if (_fdt_address_add(ac, offset, pac, wpaddr, + pac, paddr) < 0) + return -FDT_ERR_BADRANGES; + + return 0; + } + + return -FDT_ERR_NOTFOUND; +} + +int fdt_address_translate(const void *fdt, + int inbusoffset, const fdt32_t *inaddr, + int outbusoffset, fdt32_t *outaddr) +{ + int ac = fdt_address_cells(fdt, inbusoffset); + int sc = fdt_size_cells(fdt, inbusoffset); + fdt32_t tmpaddr[FDT_MAX_NCELLS]; + + while (inbusoffset != outbusoffset) { + int parent = fdt_parent_offset(fdt, inbusoffset); + int pac, rlen; + const fdt32_t *ranges; + int rc; + + if (parent == -FDT_ERR_NOTFOUND) + /* Reached the root, meaning outbus wasn't an + * ancestor of inbus */ + return -FDT_ERR_BADOFFSET; + else if (parent < 0) + return parent; + + pac = fdt_address_cells(fdt, parent); + ranges = fdt_getprop(fdt, inbusoffset, "ranges", &rlen); + + rc = _fdt_address_apply_ranges(ac, sc, pac, ranges, rlen, + inaddr, tmpaddr); + if (rc < 0) + return rc; + + inaddr = tmpaddr; + ac = pac; + sc = fdt_size_cells(fdt, parent); + inbusoffset = parent; + } + + memcpy(outaddr, inaddr, ac * sizeof(fdt32_t)); + return 0; +} diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h index 32d5227..dc321c3 100644 --- a/libfdt/libfdt.h +++ b/libfdt/libfdt.h @@ -120,8 +120,10 @@ #define FDT_ERR_BADNCELLS 14 /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells * or similar property with a bad format or value */ +#define FDT_ERR_BADRANGES 15 + /* FDT_ERR_BADRANGES: Device tree has a bad ranges property */ -#define FDT_ERR_MAX 14 +#define FDT_ERR_MAX 15 /**********************************************************************/ /* Low-level functions (you probably don't need these) */ @@ -911,6 +913,48 @@ int fdt_address_cells(const void *fdt, int nodeoffset); */ int fdt_size_cells(const void *fdt, int nodeoffset); +/** + * fdt_address_translate - Translate OF addresses + * @fdt: pointer to the device tree blob + * @inbusoffset: offset of node which defines the address space of the input + * address + * @inaddr: input address, must point to N contiguous cells of data + * where N is the #address-cells of the node at inbusoffset + * @outbusoffset: offset of the node into whose address space to + * translate the address + * @outaddr: buffer to store the translated address, must point to N + * contiguous cells of space (which will be overwritten), + * where N is the #address-cells of the node at outbusoffset + * + * Given an address within the address space of one node, translate it + * to an address in the address space of an ancestor node. + * + * NOTE: This function is very expensive, as it scans the device tree + * structure from the start to the start of node for every level of + * translation, making it roughly O(n^2) in the size of the flattened + * tree. FIXME: improve this + * + * returns: + * 0, on success outaddr will contain the translated address + * -FDT_ERR_NOTFOUND, if the address is not mapped into the bus at + * outbusoffset + * -FDT_ERR_BADOFFEST, of inbusoffset or outbusoffset don't point to + * nodes, or if outbusoffset is not an ancestor of + * inbusoffset + * -FDT_ERR_BADNCELLS, if any intermediate node has a badly formatted or + * invalid #size-cells property + * -FDT_ERR_BADRANGES, if any intermediate node has an invalid ranges + * property + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_address_translate(const void *fdt, + int inbusoffset, const fdt32_t *inaddr, + int outbusoffset, fdt32_t *outaddr); + /**********************************************************************/ /* Write-in-place functions */ diff --git a/tests/.gitignore b/tests/.gitignore index 5656555..a99e109 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -4,6 +4,7 @@ tmp.* /add_subnode_with_nops /addr_size_cells +/address_translation /appendprop[12] /asm_tree_dump /boot-cpuid diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 9adedec..2a7f347 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -8,7 +8,7 @@ LIB_TESTS_L = get_mem_rsv \ char_literal \ sized_cells \ notfound \ - addr_size_cells \ + addr_size_cells address_translation \ setprop_inplace nop_property nop_node \ sw_tree1 \ move_and_save mangle-layout nopulate \ diff --git a/tests/addr_size_cells.c b/tests/addr_size_cells.c index 6090d93..6e737f4 100644 --- a/tests/addr_size_cells.c +++ b/tests/addr_size_cells.c @@ -59,6 +59,6 @@ int main(int argc, char *argv[]) check_node(fdt, "/", 2, 2); check_node(fdt, "/identity-bus@0", 2, 2); - check_node(fdt, "/simple-bus@1000000", 2, 1); + check_node(fdt, "/offset-bus@1000000", 2, 2); PASS(); } diff --git a/tests/address_translation.c b/tests/address_translation.c new file mode 100644 index 0000000..c205598 --- /dev/null +++ b/tests/address_translation.c @@ -0,0 +1,121 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for #address-cells and #size-cells handling + * Copyright (C) 2014 David Gibson, <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> + * + * 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 <libfdt.h> + +#include "tests.h" +#include "testdata.h" + +static void verbose_print_addr(int cells, const fdt32_t *addr) +{ + int i; + + for (i = 0; i < cells; i++) + verbose_printf("%08x ", fdt32_to_cpu(addr[i])); +} + +static void check_node(const void *fdt, int offset) +{ + char path[1024]; + const fdt32_t *tests; + int testlen, rc, i; + int ac; + + rc = fdt_get_path(fdt, offset, path, sizeof(path)); + if (rc < 0) + FAIL("fdt_get_path(): %s\n", fdt_strerror(rc)); + + ac = fdt_address_cells(fdt, offset); + + verbose_printf("Checking node %s [#address-cells = %d]\n", path, ac); + + tests = fdt_getprop(fdt, offset, "libfdt,test-translation", &testlen); + if (!tests) + return; + + i = 0; + while (i < (testlen / sizeof(fdt32_t))) { + int phandle = fdt32_to_cpu(tests[i++]); + int toffset; + const fdt32_t *inaddr, *checkaddr; + fdt32_t *outaddr; + int tac; + char tpath[1024]; + + toffset = fdt_node_offset_by_phandle(fdt, phandle); + + tac = fdt_address_cells(fdt, toffset); + rc = fdt_get_path(fdt, toffset, tpath, sizeof(tpath)); + if (rc < 0) + FAIL("fdt_get_path(): %s\n", fdt_strerror(rc)); + + inaddr = tests + i; + i += ac; + checkaddr = tests + i; + i += tac; + + verbose_printf("Translating address "); + verbose_print_addr(ac, inaddr); + verbose_printf("to bus %s [#address-cells = %d]\n", + tpath, tac); + + verbose_printf("Expecting: "); + verbose_print_addr(tac, checkaddr); + verbose_printf("\n"); + + outaddr = alloca(tac * sizeof(fdt32_t)); + rc = fdt_address_translate(fdt, offset, inaddr, toffset, outaddr); + if (rc < 0) + FAIL("fdt_address_translate(): %s\n", fdt_strerror(rc)); + + verbose_printf("Got: "); + verbose_print_addr(tac, outaddr); + verbose_printf("\n"); + + if (memcmp(outaddr, checkaddr, tac * sizeof(fdt32_t)) != 0) + FAIL("Incorrect translated address"); + } +} + +int main(int argc, char *argv[]) +{ + void *fdt; + int offset = 0; + + if (argc != 2) + CONFIG("Usage: %s <dtb file>\n", argv[0]); + + test_init(argc, argv); + fdt = load_blob(argv[1]); + + do { + check_node(fdt, offset); + offset = fdt_next_node(fdt, offset, NULL); + } while (offset >= 0); + + if (offset != -FDT_ERR_NOTFOUND) + FAIL("fdt_next_node(): %s\n", fdt_strerror(offset)); + + PASS(); +} diff --git a/tests/addresses.dts b/tests/addresses.dts index a2faaf5..2ee2be7 100644 --- a/tests/addresses.dts +++ b/tests/addresses.dts @@ -6,10 +6,38 @@ #size-cells = <2>; identity-bus@0 { + ranges; + + libfdt,test-translation = < + &{/} 0 0 0 0 + &{/} 0xabcd 0x1234 0xabcd 0x1234 + >; }; - simple-bus@1000000 { + offset-bus@1000000 { #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x0 0x1000000 0x0 0x1000000>; + + libfdt,test-translation = < + &{/} 0 0 0 0x1000000 + &{/} 0 0x1234 0 0x1001234 + &{/} 0 0xffffff 0 0x1ffffff + >; + }; + + embed-bus@100000000 { + #address-cells = <1>; #size-cells = <1>; + ranges = <0x0 0x1 0x0 0x80000000 + 0x80000000 0x1 0x80000000 0x80000000>; + + libfdt,test-translation = < + &{/} 0x0 0x1 0x0 + &{/} 0xabcd 0x1 0xabcd + &{/} 0x7fffffff 0x1 0x7fffffff + &{/} 0x80000000 0x1 0x80000000 + &{/} 0xffffffff 0x1 0xffffffff + >; }; }; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index f205ce6..68d4360 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -190,6 +190,7 @@ libfdt_tests () { run_dtc_test -I dts -O dtb -o addresses.test.dtb addresses.dts run_test addr_size_cells addresses.test.dtb + run_test address_translation addresses.test.dtb # Sequential write tests run_test sw_tree1 -- 1.9.0 -- To unsubscribe from this list: send the line "unsubscribe devicetree-compiler" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply related [flat|nested] 4+ messages in thread
[parent not found: <1399874771-23089-2-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>]
* Re: [PATCH 2/2] libfdt: Add address translation functions [not found] ` <1399874771-23089-2-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> @ 2014-05-12 19:01 ` Rob Herring [not found] ` <CAL_Jsq+Lppxf7OHO1ekqpc7E+P8cMJcTOftZSd2TrN8kb4PQuQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 4+ messages in thread From: Rob Herring @ 2014-05-12 19:01 UTC (permalink / raw) To: David Gibson Cc: devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, jdl-ClAdetSTwOo, Grant Likely, Scott Wood, Kim Phillips, Kumar Gala, Benjamin Herrenschmidt On Mon, May 12, 2014 at 1:06 AM, David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote: > Add the fdt_address_translate() function to process 'ranges' properties > to translate addresses from one bus to another. Some trailing whitespace errors: Applying: libfdt: Add address translation functions dtc/.git/rebase-apply/patch:87: trailing whitespace. dtc/.git/rebase-apply/patch:208: trailing whitespace. * @inbusoffset: offset of node which defines the address space of the input dtc/.git/rebase-apply/patch:342: trailing whitespace. warning: 3 lines add whitespace errors. [...] > +int fdt_address_translate(const void *fdt, > + int inbusoffset, const fdt32_t *inaddr, > + int outbusoffset, fdt32_t *outaddr) The translated address in native endian would be more useful, but more importantly how does one determine the translated address size needed to convert it? I don't see any reason for the caller to have the outaddr in be32. While in theory you could need something larger than a uint64_t, the reality is any >2 cell case is broken anyway. Rob -- To unsubscribe from this list: send the line "unsubscribe devicetree-compiler" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 4+ messages in thread
[parent not found: <CAL_Jsq+Lppxf7OHO1ekqpc7E+P8cMJcTOftZSd2TrN8kb4PQuQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: [PATCH 2/2] libfdt: Add address translation functions [not found] ` <CAL_Jsq+Lppxf7OHO1ekqpc7E+P8cMJcTOftZSd2TrN8kb4PQuQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2014-05-14 4:22 ` David Gibson 0 siblings, 0 replies; 4+ messages in thread From: David Gibson @ 2014-05-14 4:22 UTC (permalink / raw) To: Rob Herring Cc: devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, jdl-ClAdetSTwOo, Grant Likely, Scott Wood, Kim Phillips, Kumar Gala, Benjamin Herrenschmidt [-- Attachment #1: Type: text/plain, Size: 1906 bytes --] On Mon, May 12, 2014 at 02:01:14PM -0500, Rob Herring wrote: > On Mon, May 12, 2014 at 1:06 AM, David Gibson > <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote: > > Add the fdt_address_translate() function to process 'ranges' properties > > to translate addresses from one bus to another. > > Some trailing whitespace errors: > > Applying: libfdt: Add address translation functions > dtc/.git/rebase-apply/patch:87: trailing whitespace. > > dtc/.git/rebase-apply/patch:208: trailing whitespace. > * @inbusoffset: offset of node which defines the address space of the input > dtc/.git/rebase-apply/patch:342: trailing whitespace. > > warning: 3 lines add whitespace errors. Oops. Not sure how I missed those. > [...] > > > > +int fdt_address_translate(const void *fdt, > > + int inbusoffset, const fdt32_t *inaddr, > > + int outbusoffset, fdt32_t *outaddr) > > The translated address in native endian would be more useful, but more > importantly how does one determine the translated address size needed > to convert it? I don't see any reason for the caller to have the > outaddr in be32. While in theory you could need something larger than > a uint64_t, the reality is any >2 cell case is broken anyway. The output isn't necessarily representable in any simple type (e.g. translating from an ISA bus to a parent PCI bus - output is 3 cells). I'm certainly thinking helper functions to translate simple 1 and 2 cell addresses to native integers, but this function is intended to strictly translate between one device tree address representation and another device tree address representation. -- 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 [-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-05-14 4:22 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-05-12 6:06 [PATCH 1/2] libfdt: Add helpers to read #address-cells and #size-cells David Gibson [not found] ` <1399874771-23089-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> 2014-05-12 6:06 ` [PATCH 2/2] libfdt: Add address translation functions David Gibson [not found] ` <1399874771-23089-2-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> 2014-05-12 19:01 ` Rob Herring [not found] ` <CAL_Jsq+Lppxf7OHO1ekqpc7E+P8cMJcTOftZSd2TrN8kb4PQuQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2014-05-14 4:22 ` David Gibson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).