From 7fcf8208b8a98f65ce938a64fab674add3656f27 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Wed, 27 Mar 2019 15:15:52 +0900 Subject: libfdt: add fdt_append_addrrange() This function will append an address range property using parent node's "#address-cells" and "#size-cells" properties. It will be used in implementing kdump with kexec_file_load system call at linux kernel for arm64 once it is merged into kernel tree. Signed-off-by: AKASHI Takahiro Message-Id: <20190327061552.17170-2-takahiro.akashi@linaro.org> [dwg: Correct a SEGV error in the testcase] Signed-off-by: David Gibson --- tests/.gitignore | 1 + tests/Makefile.tests | 1 + tests/appendprop_addrrange.c | 108 +++++++++++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 5 ++ tests/testdata.h | 6 +++ tests/tests.h | 3 ++ tests/testutils.c | 58 +++++++++++++++++++++++ 7 files changed, 182 insertions(+) create mode 100644 tests/appendprop_addrrange.c (limited to 'tests') diff --git a/tests/.gitignore b/tests/.gitignore index 12af438..0bc78aa 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -8,6 +8,7 @@ tmp.* /addr_size_cells /addr_size_cells2 /appendprop[12] +/appendprop_addrrange /asm_tree_dump /boot-cpuid /char_literal diff --git a/tests/Makefile.tests b/tests/Makefile.tests index b02d8bf..b77f121 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -10,6 +10,7 @@ LIB_TESTS_L = get_mem_rsv \ notfound \ addr_size_cells \ addr_size_cells2 \ + appendprop_addrrange \ stringlist \ setprop_inplace nop_property nop_node \ sw_tree1 sw_states \ diff --git a/tests/appendprop_addrrange.c b/tests/appendprop_addrrange.c new file mode 100644 index 0000000..b079fba --- /dev/null +++ b/tests/appendprop_addrrange.c @@ -0,0 +1,108 @@ +/* + * libfdt - Flat Device Tree manipulation + * Testcase for fdt_appendprop_addrrange() + * Copyright (C) 2018 AKASHI Takahiro, Linaro Limited + * + * 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 +#include +#include +#include + +#include + +#include "tests.h" +#include "testdata.h" + +int main(int argc, char *argv[]) +{ + void *fdt, *buf; + int offset, xac, xsc, num, i, err; + uint64_t addr, size; + + if (argc != 5) + CONFIG("Usage: %s \n", + argv[0]); + + test_init(argc, argv); + fdt = load_blob(argv[1]); + xac = strtol(argv[2], NULL, 10); + xsc = strtol(argv[3], NULL, 10); + num = strtol(argv[4], NULL, 10); + + buf = xmalloc(0x1000); + if (!buf) + FAIL("Couldn't allocate temporary buffer"); + err = fdt_open_into(fdt, buf, 0x1000); + if (err) + FAIL("fdt_open_into(): %s", fdt_strerror(err)); + + fdt = buf; + + /* Set up */ + err = fdt_setprop_cell(fdt, 0, "#address-cells", xac); + if (err) + FAIL("fdt_setprop_cell(\"#address-cells\"): %s", + fdt_strerror(err)); + err = fdt_setprop_cell(fdt, 0, "#size-cells", xsc); + if (err) + FAIL("fdt_setprop_cell(\"#size-cells\"): %s", + fdt_strerror(err)); + + offset = fdt_path_offset(fdt, "/node@1"); + if (offset < 0) + FAIL("Couldn't find path %s", "/node@1"); + + addr = TEST_MEMREGION_ADDR; + if (xac > 1) + addr += TEST_MEMREGION_ADDR_HI; + size = TEST_MEMREGION_SIZE; + if (xsc > 1) + size += TEST_MEMREGION_SIZE_HI; + + /* + * Do test + */ + /* 1. repeat append's */ + for (i = 0; i < num; i++) { + err = fdt_appendprop_addrrange(fdt, 0, offset, + "prop-memregion", addr, size); + if (err) + FAIL("Failed to append[%d] \"prop-memregion\": %s", + i, fdt_strerror(err)); + + check_getprop_addrrange(fdt, 0, offset, "prop-memregion", + i + 1); + + addr += size; + size += TEST_MEMREGION_SIZE_INC; + } + + /* 2. default property name */ + addr = TEST_MEMREGION_ADDR; + if (xac > 1) + addr += TEST_MEMREGION_ADDR_HI; + size = TEST_MEMREGION_SIZE; + if (xsc > 1) + size += TEST_MEMREGION_SIZE_HI; + + err = fdt_appendprop_addrrange(fdt, 0, offset, "reg", addr, size); + if (err) + FAIL("Failed to set \"reg\": %s", fdt_strerror(err)); + check_getprop_addrrange(fdt, 0, offset, "reg", 1); + + PASS(); +} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 04fc1e8..f6b308f 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -424,6 +424,11 @@ libfdt_tests () { run_dtc_test -I dts -O dtb -o property_iterate.dtb property_iterate.dts run_test property_iterate property_iterate.dtb + run_dtc_test -I dts -O dtb -o unit-addr-without-reg.dtb unit-addr-without-reg.dts + run_test appendprop_addrrange unit-addr-without-reg.dtb 1 1 1 + run_test appendprop_addrrange unit-addr-without-reg.dtb 2 2 2 + run_test appendprop_addrrange unit-addr-without-reg.dtb 2 1 3 + # Tests for behaviour on various sorts of corrupted trees run_test truncated_property run_test truncated_string diff --git a/tests/testdata.h b/tests/testdata.h index 68dcbac..0d08efb 100644 --- a/tests/testdata.h +++ b/tests/testdata.h @@ -40,6 +40,12 @@ #define TEST_CHAR4 '\'' #define TEST_CHAR5 '\xff' +#define TEST_MEMREGION_ADDR 0x12345678 +#define TEST_MEMREGION_ADDR_HI 0x8765432100000000 +#define TEST_MEMREGION_SIZE 0x9abcdef0 +#define TEST_MEMREGION_SIZE_HI 0x0fedcba900000000 +#define TEST_MEMREGION_SIZE_INC 0x1000 + #ifndef __ASSEMBLY__ extern struct fdt_header test_tree1; extern struct fdt_header truncated_property; diff --git a/tests/tests.h b/tests/tests.h index dc8120e..75735d6 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -128,6 +128,9 @@ const void *check_get_prop_offset(void *fdt, int poffset, const char *in_name, check_get_prop_offset(fdt, poffset, name, sizeof(x), &x); \ }) +const void *check_getprop_addrrange(void *fdt, int parent, int nodeoffset, + const char *name, int num); + int nodename_eq(const char *s1, const char *s2); void vg_prepare_blob(void *fdt, size_t bufsize); void *load_blob(const char *filename); diff --git a/tests/testutils.c b/tests/testutils.c index bbfda90..a250d5a 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -45,6 +45,7 @@ static inline void VALGRIND_MAKE_MEM_DEFINED(void *p, size_t len) #include #include "tests.h" +#include "testdata.h" /* For FDT_SW_MAGIC */ #include "libfdt_internal.h" @@ -184,6 +185,63 @@ const void *check_get_prop_offset(void *fdt, int poffset, const char *exp_name, return propval; } +const void *check_getprop_addrrange(void *fdt, int parent, int nodeoffset, + const char *name, int num) +{ + const void *propval; + int xac, xsc, buf_size, cells, i; + char *buf, *p; + uint64_t addr, size; + fdt32_t val; + + xac = fdt_address_cells(fdt, parent); + xsc = fdt_size_cells(fdt, parent); + + if (xac <= 0) + FAIL("Couldn't identify #address-cells: %s", + fdt_strerror(xac)); + if (xsc <= 0) + FAIL("Couldn't identify #size-cells: %s", + fdt_strerror(xsc)); + + buf_size = (xac + xsc) * sizeof(fdt32_t) * num; + buf = malloc(buf_size); + if (!buf) + FAIL("Couldn't allocate temporary buffer"); + + /* expected value */ + addr = TEST_MEMREGION_ADDR; + if (xac > 1) + addr += TEST_MEMREGION_ADDR_HI; + size = TEST_MEMREGION_SIZE; + if (xsc > 1) + size += TEST_MEMREGION_SIZE_HI; + for (p = buf, i = 0; i < num; i++) { + cells = xac; + while (cells) { + val = cpu_to_fdt32(addr >> (32 * (--cells))); + memcpy(p, &val, sizeof(val)); + p += sizeof(val); + } + cells = xsc; + while (cells) { + val = cpu_to_fdt32(size >> (32 * (--cells))); + memcpy(p, &val, sizeof(val)); + p += sizeof(val); + } + + addr += size; + size += TEST_MEMREGION_SIZE_INC; + } + + /* check */ + propval = check_getprop(fdt, nodeoffset, name, buf_size, + (const void *)buf); + + free(buf); + + return propval; +} int nodename_eq(const char *s1, const char *s2) { -- cgit v1.1