aboutsummaryrefslogtreecommitdiffstats
path: root/dtc/tests
diff options
context:
space:
mode:
Diffstat (limited to 'dtc/tests')
-rw-r--r--dtc/tests/.gitignore75
-rw-r--r--dtc/tests/Makefile.tests102
-rw-r--r--dtc/tests/add_subnode_with_nops.c71
-rw-r--r--dtc/tests/addr_size_cells.c56
-rw-r--r--dtc/tests/addr_size_cells2.c49
-rw-r--r--dtc/tests/addresses.dts40
-rw-r--r--dtc/tests/aliases.dts25
-rw-r--r--dtc/tests/appendprop.dts8
-rw-r--r--dtc/tests/appendprop1.c57
-rw-r--r--dtc/tests/appendprop2.c51
-rw-r--r--dtc/tests/appendprop_addrrange.c95
-rw-r--r--dtc/tests/asm_tree_dump.c48
-rw-r--r--dtc/tests/bad-chosen.dts10
-rw-r--r--dtc/tests/bad-dma-ranges.dts12
-rw-r--r--dtc/tests/bad-empty-ranges.dts11
-rw-r--r--dtc/tests/bad-gpio.dts13
-rw-r--r--dtc/tests/bad-graph.dts24
-rw-r--r--dtc/tests/bad-interrupt-cells.dts12
-rw-r--r--dtc/tests/bad-interrupt-controller.dts7
-rw-r--r--dtc/tests/bad-name-property.dts7
-rw-r--r--dtc/tests/bad-ncells.dts7
-rw-r--r--dtc/tests/bad-octal-literal.dts5
-rw-r--r--dtc/tests/bad-phandle-cells.dts11
-rw-r--r--dtc/tests/bad-reg-ranges.dts12
-rw-r--r--dtc/tests/bad-size-cells.dts12
-rw-r--r--dtc/tests/bad-string-props.dts14
-rw-r--r--dtc/tests/base01.asm175
-rw-r--r--dtc/tests/base01.cmd1
-rw-r--r--dtc/tests/base01.dts33
-rw-r--r--dtc/tests/base01.stderr6
-rw-r--r--dtc/tests/boot-cpuid.c34
-rw-r--r--dtc/tests/boot-cpuid.dts16
-rw-r--r--dtc/tests/char_literal.c36
-rw-r--r--dtc/tests/char_literal.dts5
-rw-r--r--dtc/tests/check_full.c50
-rw-r--r--dtc/tests/check_header.c115
-rw-r--r--dtc/tests/check_path.c70
-rw-r--r--dtc/tests/comments-cmp.dts16
-rw-r--r--dtc/tests/comments.dts39
-rw-r--r--dtc/tests/data.S3
-rw-r--r--dtc/tests/default-addr-size.dts7
-rw-r--r--dtc/tests/del_node.c110
-rw-r--r--dtc/tests/del_property.c77
-rw-r--r--dtc/tests/delete_reinstate_multilabel.dts37
-rw-r--r--dtc/tests/delete_reinstate_multilabel_ref.dts9
-rw-r--r--dtc/tests/dependencies.cmp1
-rw-r--r--dtc/tests/dependencies.dts6
-rw-r--r--dtc/tests/deps_inc1.dtsi1
-rw-r--r--dtc/tests/deps_inc2.dtsi1
-rw-r--r--dtc/tests/division-by-zero.dts6
-rw-r--r--dtc/tests/dtb_reverse.c150
-rw-r--r--dtc/tests/dtbs_equal_ordered.c160
-rw-r--r--dtc/tests/dtbs_equal_unordered.c230
-rwxr-xr-xdtc/tests/dtc-checkfails.sh45
-rwxr-xr-xdtc/tests/dtc-fails.sh31
-rwxr-xr-xdtc/tests/dtc-fatal.sh15
-rw-r--r--dtc/tests/dumptrees.c69
-rw-r--r--dtc/tests/dup-nodename.dts8
-rw-r--r--dtc/tests/dup-phandle.dts10
-rw-r--r--dtc/tests/dup-propname.dts6
-rw-r--r--dtc/tests/embedded_nul.dtsbin0 -> 152 bytes
-rw-r--r--dtc/tests/embedded_nul_equiv.dts6
-rw-r--r--dtc/tests/empty.dts4
-rw-r--r--dtc/tests/escapes.dts7
-rw-r--r--dtc/tests/extra-terminating-null.c45
-rw-r--r--dtc/tests/extra-terminating-null.dts11
-rwxr-xr-xdtc/tests/fdtdump-runtest.sh31
-rw-r--r--dtc/tests/fdtdump.dts38
-rwxr-xr-xdtc/tests/fdtget-runtest.sh25
-rwxr-xr-xdtc/tests/fdtoverlay-runtest.sh41
-rwxr-xr-xdtc/tests/fdtput-runtest.sh40
-rw-r--r--dtc/tests/find_property.c28
-rw-r--r--dtc/tests/fs_tree1.c155
-rw-r--r--dtc/tests/get_alias.c44
-rw-r--r--dtc/tests/get_mem_rsv.c35
-rw-r--r--dtc/tests/get_name.c69
-rw-r--r--dtc/tests/get_path.c80
-rw-r--r--dtc/tests/get_phandle.c87
-rw-r--r--dtc/tests/get_prop_offset.c43
-rw-r--r--dtc/tests/getprop.c29
-rw-r--r--dtc/tests/good-gpio.dts12
-rw-r--r--dtc/tests/incbin.bin1
-rw-r--r--dtc/tests/incbin.c65
-rw-r--r--dtc/tests/incbin.dts6
-rw-r--r--dtc/tests/include0.dts1
-rw-r--r--dtc/tests/include1.dts32
-rw-r--r--dtc/tests/include2.dts1
-rw-r--r--dtc/tests/include3.dts1
-rw-r--r--dtc/tests/include4.dts1
-rw-r--r--dtc/tests/include5.dts1
-rw-r--r--dtc/tests/include5a.dts1
-rw-r--r--dtc/tests/include6.dts1
-rw-r--r--dtc/tests/include7.dts14
-rw-r--r--dtc/tests/include8.dts2
-rw-r--r--dtc/tests/integer-expressions.c103
-rw-r--r--dtc/tests/label01.dts63
-rw-r--r--dtc/tests/label_repeated.dts15
-rw-r--r--dtc/tests/line_directives.dts26
-rw-r--r--dtc/tests/lorem.txt35
-rw-r--r--dtc/tests/mangle-layout.c147
-rw-r--r--dtc/tests/meson.build131
-rw-r--r--dtc/tests/minusone-phandle.dts7
-rw-r--r--dtc/tests/move_and_save.c62
-rw-r--r--dtc/tests/multilabel.dts49
-rw-r--r--dtc/tests/multilabel_merge.dts75
-rw-r--r--dtc/tests/node_check_compatible.c68
-rw-r--r--dtc/tests/node_offset_by_compatible.c72
-rw-r--r--dtc/tests/node_offset_by_phandle.c50
-rw-r--r--dtc/tests/node_offset_by_prop_value.c97
-rw-r--r--dtc/tests/nonexist-label-ref.dts8
-rw-r--r--dtc/tests/nonexist-node-ref.dts8
-rw-r--r--dtc/tests/nonexist-node-ref2.dts10
-rw-r--r--dtc/tests/nop_node.c91
-rw-r--r--dtc/tests/nop_property.c57
-rw-r--r--dtc/tests/nopulate.c92
-rw-r--r--dtc/tests/notfound.c57
-rw-r--r--dtc/tests/nul-in-escape.dtsbin0 -> 36 bytes
-rw-r--r--dtc/tests/nul-in-line-info1.dtsbin0 -> 8 bytes
-rw-r--r--dtc/tests/nul-in-line-info2.dts1
-rw-r--r--dtc/tests/obsolete-chosen-interrupt-controller.dts13
-rw-r--r--dtc/tests/omit-no-ref.dts26
-rw-r--r--dtc/tests/open_pack.c58
-rw-r--r--dtc/tests/overlay.c220
-rw-r--r--dtc/tests/overlay_bad_fixup.c57
-rw-r--r--dtc/tests/overlay_bad_fixup_bad_index.dts14
-rw-r--r--dtc/tests/overlay_bad_fixup_base.dtsi18
-rw-r--r--dtc/tests/overlay_bad_fixup_empty.dts14
-rw-r--r--dtc/tests/overlay_bad_fixup_empty_index.dts14
-rw-r--r--dtc/tests/overlay_bad_fixup_index_trailing.dts14
-rw-r--r--dtc/tests/overlay_bad_fixup_path_empty_prop.dts14
-rw-r--r--dtc/tests/overlay_bad_fixup_path_only.dts14
-rw-r--r--dtc/tests/overlay_bad_fixup_path_only_sep.dts14
-rw-r--r--dtc/tests/overlay_bad_fixup_path_prop.dts14
-rw-r--r--dtc/tests/overlay_base.dts25
-rw-r--r--dtc/tests/overlay_base_manual_symbols.dts25
-rw-r--r--dtc/tests/overlay_overlay.dts52
-rw-r--r--dtc/tests/overlay_overlay_bypath.dts48
-rw-r--r--dtc/tests/overlay_overlay_local_merge.dts29
-rw-r--r--dtc/tests/overlay_overlay_long_path.dts32
-rw-r--r--dtc/tests/overlay_overlay_manual_fixups.dts112
-rw-r--r--dtc/tests/overlay_overlay_no_fixups.dts82
-rw-r--r--dtc/tests/overlay_overlay_nosugar.dts86
-rw-r--r--dtc/tests/overlay_overlay_simple.dts12
-rw-r--r--dtc/tests/parent_offset.c77
-rw-r--r--dtc/tests/path-references.c95
-rw-r--r--dtc/tests/path-references.dts28
-rw-r--r--dtc/tests/path_offset.c124
-rw-r--r--dtc/tests/path_offset_aliases.c45
-rw-r--r--dtc/tests/pci-bridge-bad1.dts16
-rw-r--r--dtc/tests/pci-bridge-bad2.dts16
-rw-r--r--dtc/tests/pci-bridge-ok.dts25
-rw-r--r--dtc/tests/phandle_format.c64
-rw-r--r--dtc/tests/prop-after-subnode.dts9
-rw-r--r--dtc/tests/property_iterate.c84
-rw-r--r--dtc/tests/property_iterate.dts23
-rw-r--r--dtc/tests/propname_escapes.c29
-rw-r--r--dtc/tests/propname_escapes.dts6
-rw-r--r--dtc/tests/pylibfdt_tests.py592
-rw-r--r--dtc/tests/references.c129
-rw-r--r--dtc/tests/references.dts41
-rw-r--r--dtc/tests/reg-ranges-root.dts8
-rw-r--r--dtc/tests/reg-without-unit-addr.dts10
-rw-r--r--dtc/tests/reuse-label.dts15
-rw-r--r--dtc/tests/reuse-label1.dts10
-rw-r--r--dtc/tests/reuse-label2.dts6
-rw-r--r--dtc/tests/reuse-label3.dts9
-rw-r--r--dtc/tests/reuse-label4.dts5
-rw-r--r--dtc/tests/reuse-label5.dts6
-rw-r--r--dtc/tests/reuse-label6.dts6
-rw-r--r--dtc/tests/root_node.c39
-rwxr-xr-xdtc/tests/run_tests.sh1104
-rw-r--r--dtc/tests/rw_oom.c83
-rw-r--r--dtc/tests/rw_tree1.c82
-rw-r--r--dtc/tests/search_dir/search_test.dtsi4
-rw-r--r--dtc/tests/search_dir/search_test2.dtsi3
-rw-r--r--dtc/tests/search_dir_b/search_paths_subdir.dts6
-rw-r--r--dtc/tests/search_dir_b/search_test_b.dtsi4
-rw-r--r--dtc/tests/search_dir_b/search_test_b2.dtsi5
-rw-r--r--dtc/tests/search_dir_b/search_test_c.dtsi2
-rw-r--r--dtc/tests/search_paths.dts6
-rw-r--r--dtc/tests/search_paths_b.dts6
-rw-r--r--dtc/tests/set_name.c77
-rw-r--r--dtc/tests/setprop.c82
-rw-r--r--dtc/tests/setprop_inplace.c84
-rw-r--r--dtc/tests/sized_cells.c70
-rw-r--r--dtc/tests/sized_cells.dts11
-rw-r--r--dtc/tests/sourceoutput.dts14
-rw-r--r--dtc/tests/stacked_overlay_addlabel.dts15
-rw-r--r--dtc/tests/stacked_overlay_bar.dts13
-rw-r--r--dtc/tests/stacked_overlay_base.dts6
-rw-r--r--dtc/tests/stacked_overlay_base_nolabel.dts6
-rw-r--r--dtc/tests/stacked_overlay_baz.dts13
-rw-r--r--dtc/tests/string_escapes.c30
-rw-r--r--dtc/tests/stringlist.c142
-rw-r--r--dtc/tests/stringlist.dts12
-rw-r--r--dtc/tests/subnode_iterate.c77
-rw-r--r--dtc/tests/subnode_iterate.dts44
-rw-r--r--dtc/tests/subnode_offset.c85
-rw-r--r--dtc/tests/supernode_atdepth_offset.c132
-rw-r--r--dtc/tests/sw_states.c127
-rw-r--r--dtc/tests/sw_tree1.c226
-rw-r--r--dtc/tests/test01.asm294
-rw-r--r--dtc/tests/test01.dts57
-rw-r--r--dtc/tests/test01.stderr4
-rwxr-xr-xdtc/tests/test_kernel_dts86
-rw-r--r--dtc/tests/test_label_ref.dts9
-rw-r--r--dtc/tests/test_props.dts11
-rw-r--r--dtc/tests/test_tree1.dts46
-rw-r--r--dtc/tests/test_tree1_delete.dts68
-rw-r--r--dtc/tests/test_tree1_label_noderef.dts56
-rw-r--r--dtc/tests/test_tree1_merge.dts51
-rw-r--r--dtc/tests/test_tree1_merge_labelled.dts49
-rw-r--r--dtc/tests/test_tree1_merge_path.dts49
-rw-r--r--dtc/tests/test_tree1_wrong1.dts43
-rw-r--r--dtc/tests/test_tree1_wrong2.dts43
-rw-r--r--dtc/tests/test_tree1_wrong3.dts43
-rw-r--r--dtc/tests/test_tree1_wrong4.dts41
-rw-r--r--dtc/tests/test_tree1_wrong5.dts44
-rw-r--r--dtc/tests/test_tree1_wrong6.dts45
-rw-r--r--dtc/tests/test_tree1_wrong7.dts46
-rw-r--r--dtc/tests/test_tree1_wrong8.dts44
-rw-r--r--dtc/tests/test_tree1_wrong9.dts45
-rw-r--r--dtc/tests/testdata.h60
-rw-r--r--dtc/tests/tests.h130
-rw-r--r--dtc/tests/testutils.c351
-rw-r--r--dtc/tests/testutils.sh67
-rw-r--r--dtc/tests/trees.S315
-rw-r--r--dtc/tests/truncated_memrsv.c50
-rw-r--r--dtc/tests/truncated_property.c36
-rw-r--r--dtc/tests/truncated_string.c68
-rw-r--r--dtc/tests/type-preservation.dt.yaml20
-rw-r--r--dtc/tests/type-preservation.dts28
-rw-r--r--dtc/tests/unit-addr-leading-0s.dts12
-rw-r--r--dtc/tests/unit-addr-leading-0x.dts12
-rw-r--r--dtc/tests/unit-addr-simple-bus-compatible.dts18
-rw-r--r--dtc/tests/unit-addr-simple-bus-reg-mismatch.dts18
-rw-r--r--dtc/tests/unit-addr-unique.dts14
-rw-r--r--dtc/tests/unit-addr-without-reg.dts9
-rw-r--r--dtc/tests/utilfdt_test.c114
-rw-r--r--dtc/tests/value-labels.c114
-rw-r--r--dtc/tests/value-labels.dts8
-rw-r--r--dtc/tests/zero-phandle.dts7
242 files changed, 12413 insertions, 0 deletions
diff --git a/dtc/tests/.gitignore b/dtc/tests/.gitignore
new file mode 100644
index 000000000..d3f143406
--- /dev/null
+++ b/dtc/tests/.gitignore
@@ -0,0 +1,75 @@
+*.dtb
+*.dts.test.s
+*.test.dts
+*.test.dt.yaml
+tmp.*
+/fs/
+/add_subnode_with_nops
+/addr_size_cells
+/addr_size_cells2
+/appendprop[12]
+/appendprop_addrrange
+/asm_tree_dump
+/boot-cpuid
+/char_literal
+/check_full
+/check_header
+/check_path
+/del_node
+/del_property
+/dtbs_equal_ordered
+/dtbs_equal_unordered
+/dtb_reverse
+/dumptrees
+/extra-terminating-null
+/find_property
+/get_alias
+/get_mem_rsv
+/get_name
+/get_path
+/get_phandle
+/getprop
+/get_prop_offset
+/incbin
+/integer-expressions
+/fs_tree1
+/mangle-layout
+/move_and_save
+/node_check_compatible
+/node_offset_by_compatible
+/node_offset_by_phandle
+/node_offset_by_prop_value
+/nop_node
+/nop_property
+/nopulate
+/notfound
+/open_pack
+/overlay
+/overlay_bad_fixup
+/parent_offset
+/path-references
+/path_offset
+/path_offset_aliases
+/phandle_format
+/property_iterate
+/propname_escapes
+/references
+/root_node
+/rw_tree1
+/rw_oom
+/set_name
+/setprop
+/setprop_inplace
+/sized_cells
+/string_escapes
+/stringlist
+/subnode_iterate
+/subnode_offset
+/supernode_atdepth_offset
+/sw_tree1
+/sw_states
+/truncated_property
+/truncated_string
+/truncated_memrsv
+/utilfdt_test
+/value-labels
diff --git a/dtc/tests/Makefile.tests b/dtc/tests/Makefile.tests
new file mode 100644
index 000000000..2b4762781
--- /dev/null
+++ b/dtc/tests/Makefile.tests
@@ -0,0 +1,102 @@
+LIB_TESTS_L = get_mem_rsv \
+ root_node find_property subnode_offset path_offset \
+ get_name getprop get_prop_offset 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 \
+ get_alias \
+ char_literal \
+ sized_cells \
+ notfound \
+ addr_size_cells \
+ addr_size_cells2 \
+ appendprop_addrrange \
+ stringlist \
+ setprop_inplace nop_property nop_node \
+ sw_tree1 sw_states \
+ move_and_save mangle-layout nopulate \
+ open_pack rw_tree1 rw_oom set_name setprop del_property del_node \
+ appendprop1 appendprop2 propname_escapes \
+ string_escapes references path-references phandle_format \
+ boot-cpuid incbin \
+ extra-terminating-null \
+ dtbs_equal_ordered \
+ dtb_reverse dtbs_equal_unordered \
+ add_subnode_with_nops path_offset_aliases \
+ utilfdt_test \
+ integer-expressions \
+ property_iterate \
+ subnode_iterate \
+ overlay overlay_bad_fixup \
+ check_path check_header check_full \
+ fs_tree1
+LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
+
+LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv \
+ two_roots named_root
+
+LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%)
+
+DL_LIB_TESTS_L = asm_tree_dump value-labels
+DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%)
+
+TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) $(DL_LIB_TESTS)
+
+TESTS_TREES_L = test_tree1.dtb
+TESTS_TREES = $(TESTS_TREES_L:%=$(TESTS_PREFIX)%)
+
+TESTS_TARGETS = $(TESTS) $(TESTS_TREES)
+
+TESTS_DEPFILES = $(TESTS:%=%.d) \
+ $(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d)
+
+TESTS_CLEANFILES_L = $(STD_CLEANFILES) \
+ *.dtb *.test.dts *.test.dt.yaml *.dtsv1 tmp.* *.bak \
+ dumptrees
+TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%)
+TESTS_CLEANDIRS_L = fs
+TESTS_CLEANDIRS = $(TESTS_CLEANDIRS_L:%=$(TESTS_PREFIX)%)
+
+.PHONY: tests
+tests: $(TESTS) $(TESTS_TREES)
+
+$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_lib)
+
+# Not necessary on all platforms; allow -ldl to be excluded instead of forcing
+# other platforms to patch it out.
+LIBDL = -ldl
+$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_lib)
+ @$(VECHO) LD [libdl] $@
+ $(LINK.c) -o $@ $^ $(LIBDL)
+
+$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \
+ util.o $(LIBFDT_lib)
+
+$(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o
+
+$(TESTS_TREES): $(TESTS_PREFIX)dumptrees
+ @$(VECHO) DUMPTREES
+ cd $(TESTS_PREFIX); ./dumptrees . >/dev/null
+
+tests_clean:
+ @$(VECHO) CLEAN "(tests)"
+ rm -f $(TESTS_CLEANFILES)
+ rm -rf $(TESTS_CLEANDIRS)
+
+check: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
+ cd $(TESTS_PREFIX); ./run_tests.sh
+
+ifeq ($(NO_VALGRIND),1)
+checkm:
+ @echo "make checkm requires valgrind, but NO_VALGRIND=1"
+else
+checkm: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
+ cd $(TESTS_PREFIX); ./run_tests.sh -m
+endif
+
+checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
+ cd $(TESTS_PREFIX); ./run_tests.sh -v
+
+ifneq ($(DEPTARGETS),)
+-include $(TESTS_DEPFILES)
+endif
diff --git a/dtc/tests/add_subnode_with_nops.c b/dtc/tests/add_subnode_with_nops.c
new file mode 100644
index 000000000..29bd34ba4
--- /dev/null
+++ b/dtc/tests/add_subnode_with_nops.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_nop_node()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define SPACE 65536
+
+#define CHECK(code) \
+ { \
+ err = (code); \
+ if (err) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ }
+
+#define OFF_CHECK(off, code) \
+ { \
+ (off) = (code); \
+ if (off < 0) \
+ FAIL(#code ": %s", fdt_strerror(off)); \
+ }
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int err;
+ int offset;
+
+ test_init(argc, argv);
+
+ fdt = xmalloc(SPACE);
+
+ CHECK(fdt_create(fdt, SPACE));
+
+ CHECK(fdt_finish_reservemap(fdt));
+ CHECK(fdt_begin_node(fdt, ""));
+ CHECK(fdt_property_cell(fdt, "prop1", TEST_VALUE_1));
+ CHECK(fdt_property_cell(fdt, "prop2", TEST_VALUE_2));
+ CHECK(fdt_end_node(fdt));
+ CHECK(fdt_finish(fdt));
+
+ verbose_printf("Built empty tree, totalsize = %d\n",
+ fdt_totalsize(fdt));
+
+ CHECK(fdt_open_into(fdt, fdt, SPACE));
+
+ check_getprop_cell(fdt, 0, "prop1", TEST_VALUE_1);
+ check_getprop_cell(fdt, 0, "prop2", TEST_VALUE_2);
+
+ CHECK(fdt_nop_property(fdt, 0, "prop1"));
+
+ check_getprop_cell(fdt, 0, "prop2", TEST_VALUE_2);
+
+ OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode"));
+
+ check_getprop_cell(fdt, 0, "prop2", TEST_VALUE_2);
+
+ PASS();
+}
diff --git a/dtc/tests/addr_size_cells.c b/dtc/tests/addr_size_cells.c
new file mode 100644
index 000000000..783574d68
--- /dev/null
+++ b/dtc/tests/addr_size_cells.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for #address-cells and #size-cells handling
+ * Copyright (C) 2014 David Gibson, <david@gibson.dropbear.id.au>
+ */
+#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, 1);
+ check_node(fdt, "/simple-bus@1000000", 2, 1);
+ check_node(fdt, "/discrete-bus@2000000", 1, 0);
+ check_node(fdt, "/c0", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS);
+ check_node(fdt, "/c1", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS);
+ check_node(fdt, "/c2", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS);
+ check_node(fdt, "/c3", -FDT_ERR_BADNCELLS, 0);
+ PASS();
+}
diff --git a/dtc/tests/addr_size_cells2.c b/dtc/tests/addr_size_cells2.c
new file mode 100644
index 000000000..d97541b42
--- /dev/null
+++ b/dtc/tests/addr_size_cells2.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for #address-cells and #size-cells handling
+ * Copyright (C) 2014 David Gibson, <david@gibson.dropbear.id.au>
+ */
+#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, 1);
+ PASS();
+}
diff --git a/dtc/tests/addresses.dts b/dtc/tests/addresses.dts
new file mode 100644
index 000000000..1b307ab53
--- /dev/null
+++ b/dtc/tests/addresses.dts
@@ -0,0 +1,40 @@
+/dts-v1/;
+
+/ {
+ compatible = "test_addresses";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ identity-bus@0 {
+ };
+
+ simple-bus@1000000 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ };
+
+ discrete-bus@2000000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ c0@0 {
+ #address-cells = <1 1>;
+ #size-cells = <1 1>;
+ };
+
+ c1@0 {
+ #address-cells = <0x80000000>;
+ #size-cells = <0x80000000>;
+ };
+
+ c2@0 {
+ #address-cells = <5>;
+ #size-cells = <5>;
+ };
+
+ c3@0 {
+ #address-cells = <0>;
+ #size-cells = <0>;
+ };
+};
diff --git a/dtc/tests/aliases.dts b/dtc/tests/aliases.dts
new file mode 100644
index 000000000..853479aee
--- /dev/null
+++ b/dtc/tests/aliases.dts
@@ -0,0 +1,25 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ aliases {
+ s1 = &sub1;
+ ss1 = &subsub1;
+ sss1 = &subsubsub1;
+ };
+
+ sub1: subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+
+ subsub1: subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+
+ subsubsub1: subsubsubnode {
+ compatible = "subsubsubnode1", "subsubsubnode";
+ };
+ };
+ };
+};
diff --git a/dtc/tests/appendprop.dts b/dtc/tests/appendprop.dts
new file mode 100644
index 000000000..f4bc730e5
--- /dev/null
+++ b/dtc/tests/appendprop.dts
@@ -0,0 +1,8 @@
+/dts-v1/;
+
+/ {
+ prop-str = "hello world", "nastystring: \a\b\t\n\v\f\r\\\"";
+ prop-int64 = /bits/ 64 <0xdeadbeef01abcdef 0xdeadbeef01abcdef>;
+ prop-int = <0xdeadbeef 123456789>;
+ prop-bytes = [00010203040001020304];
+};
diff --git a/dtc/tests/appendprop1.c b/dtc/tests/appendprop1.c
new file mode 100644
index 000000000..a7b502aac
--- /dev/null
+++ b/dtc/tests/appendprop1.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_appendprop()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define SPACE 65536
+
+#define CHECK(code) \
+ { \
+ err = (code); \
+ if (err) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ }
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int err;
+ uint8_t bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04};
+
+ test_init(argc, argv);
+
+ /* Create an empty tree first */
+ fdt = xmalloc(SPACE);
+ CHECK(fdt_create(fdt, SPACE));
+ CHECK(fdt_finish_reservemap(fdt));
+ CHECK(fdt_begin_node(fdt, ""));
+ CHECK(fdt_end_node(fdt));
+ CHECK(fdt_finish(fdt));
+
+ /* Now use appendprop to add properties */
+ CHECK(fdt_open_into(fdt, fdt, SPACE));
+
+ CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes)));
+ CHECK(fdt_appendprop_cell(fdt, 0, "prop-int", TEST_VALUE_1));
+ CHECK(fdt_appendprop_u64(fdt, 0, "prop-int64", TEST_VALUE64_1));
+ CHECK(fdt_appendprop_string(fdt, 0, "prop-str", TEST_STRING_1));
+
+ CHECK(fdt_pack(fdt));
+
+ save_blob("appendprop1.test.dtb", fdt);
+
+ PASS();
+}
diff --git a/dtc/tests/appendprop2.c b/dtc/tests/appendprop2.c
new file mode 100644
index 000000000..a0c1f6f43
--- /dev/null
+++ b/dtc/tests/appendprop2.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_appendprop()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define SPACE 65536
+
+#define CHECK(code) \
+ { \
+ err = (code); \
+ if (err) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ }
+
+int main(int argc, char *argv[])
+{
+ void *fdt, *buf;
+ int err;
+ uint8_t bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04};
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ buf = xmalloc(SPACE);
+ CHECK(fdt_open_into(fdt, buf, SPACE));
+ fdt = buf;
+
+ CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes)));
+ CHECK(fdt_appendprop_cell(fdt, 0, "prop-int", TEST_VALUE_2));
+ CHECK(fdt_appendprop_u64(fdt, 0, "prop-int64", TEST_VALUE64_1));
+ CHECK(fdt_appendprop_string(fdt, 0, "prop-str", TEST_STRING_2));
+
+ CHECK(fdt_pack(fdt));
+
+ save_blob("appendprop2.test.dtb", fdt);
+
+ PASS();
+}
diff --git a/dtc/tests/appendprop_addrrange.c b/dtc/tests/appendprop_addrrange.c
new file mode 100644
index 000000000..538afcf9a
--- /dev/null
+++ b/dtc/tests/appendprop_addrrange.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_appendprop_addrrange()
+ * Copyright (C) 2018 AKASHI Takahiro, Linaro Limited
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#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 <dtb file> <address-cells> <size-cells> <num>\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/dtc/tests/asm_tree_dump.c b/dtc/tests/asm_tree_dump.c
new file mode 100644
index 000000000..8236172d9
--- /dev/null
+++ b/dtc/tests/asm_tree_dump.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Tests if an asm tree built into a shared object matches a given dtb
+ * Copyright (C) 2008 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include <dlfcn.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *sohandle;
+ void *fdt;
+ int err;
+
+ test_init(argc, argv);
+ if (argc != 3)
+ CONFIG("Usage: %s <so file> <dtb file>", argv[0]);
+
+ sohandle = dlopen(argv[1], RTLD_NOW);
+ if (!sohandle)
+ FAIL("Couldn't dlopen() %s", argv[1]);
+
+ fdt = dlsym(sohandle, "dt_blob_start");
+ if (!fdt)
+ FAIL("Couldn't locate \"dt_blob_start\" symbol in %s",
+ argv[1]);
+
+ err = fdt_check_header(fdt);
+ if (err != 0)
+ FAIL("%s contains invalid tree: %s", argv[1],
+ fdt_strerror(err));
+
+ save_blob(argv[2], fdt);
+
+ PASS();
+}
diff --git a/dtc/tests/bad-chosen.dts b/dtc/tests/bad-chosen.dts
new file mode 100644
index 000000000..d6f53c68d
--- /dev/null
+++ b/dtc/tests/bad-chosen.dts
@@ -0,0 +1,10 @@
+/dts-v1/;
+
+/ {
+ node2 {
+ chosen {
+ bootargs = <0xdeadbeef>;
+ stdout-path = <1>;
+ };
+ };
+};
diff --git a/dtc/tests/bad-dma-ranges.dts b/dtc/tests/bad-dma-ranges.dts
new file mode 100644
index 000000000..fbe7ab82c
--- /dev/null
+++ b/dtc/tests/bad-dma-ranges.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ node {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ dma-ranges = <0 0 0 0 0>;
+ };
+};
diff --git a/dtc/tests/bad-empty-ranges.dts b/dtc/tests/bad-empty-ranges.dts
new file mode 100644
index 000000000..2be7bc858
--- /dev/null
+++ b/dtc/tests/bad-empty-ranges.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ node {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ };
+};
diff --git a/dtc/tests/bad-gpio.dts b/dtc/tests/bad-gpio.dts
new file mode 100644
index 000000000..6b77be447
--- /dev/null
+++ b/dtc/tests/bad-gpio.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+
+/ {
+ gpio: gpio-controller {
+ #gpio-cells = <3>;
+ };
+
+ node {
+ nr-gpios = <1>;
+ foo-gpios = <&gpio>;
+ bar-gpio = <&gpio 1 2 3>;
+ };
+};
diff --git a/dtc/tests/bad-graph.dts b/dtc/tests/bad-graph.dts
new file mode 100644
index 000000000..522da0edb
--- /dev/null
+++ b/dtc/tests/bad-graph.dts
@@ -0,0 +1,24 @@
+/dts-v1/;
+
+/ {
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ bad_endpoint: port-a@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ endpoint@d0 {
+ reg = <0>;
+ remote-endpoint = <0xdeadbeef>;
+ };
+
+ };
+
+ port@1 {
+ reg = <0>;
+ };
+ };
+};
diff --git a/dtc/tests/bad-interrupt-cells.dts b/dtc/tests/bad-interrupt-cells.dts
new file mode 100644
index 000000000..39fc78fdc
--- /dev/null
+++ b/dtc/tests/bad-interrupt-cells.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/ {
+ interrupt-parent = <&intc>;
+ intc: interrupt-controller {
+ #interrupt-cells = <3>;
+ };
+
+ node {
+ interrupts = <1>;
+ };
+};
diff --git a/dtc/tests/bad-interrupt-controller.dts b/dtc/tests/bad-interrupt-controller.dts
new file mode 100644
index 000000000..62fa11889
--- /dev/null
+++ b/dtc/tests/bad-interrupt-controller.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+ intc: interrupt-controller {
+ interrupt-controller;
+ };
+};
diff --git a/dtc/tests/bad-name-property.dts b/dtc/tests/bad-name-property.dts
new file mode 100644
index 000000000..4fde4bef1
--- /dev/null
+++ b/dtc/tests/bad-name-property.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+ node@0 {
+ name = "badthing";
+ };
+};
diff --git a/dtc/tests/bad-ncells.dts b/dtc/tests/bad-ncells.dts
new file mode 100644
index 000000000..636198cbf
--- /dev/null
+++ b/dtc/tests/bad-ncells.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+ #address-cells = "badthing";
+ #size-cells = "badthing";
+ #interrupt-cells = "badthing";
+};
diff --git a/dtc/tests/bad-octal-literal.dts b/dtc/tests/bad-octal-literal.dts
new file mode 100644
index 000000000..26558a274
--- /dev/null
+++ b/dtc/tests/bad-octal-literal.dts
@@ -0,0 +1,5 @@
+/dts-v1/;
+
+/ {
+ x = <09>;
+};
diff --git a/dtc/tests/bad-phandle-cells.dts b/dtc/tests/bad-phandle-cells.dts
new file mode 100644
index 000000000..7f7c6a25f
--- /dev/null
+++ b/dtc/tests/bad-phandle-cells.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/ {
+ intc: interrupt-controller {
+ #interrupt-cells = <3>;
+ };
+
+ node {
+ interrupts-extended = <&intc>;
+ };
+};
diff --git a/dtc/tests/bad-reg-ranges.dts b/dtc/tests/bad-reg-ranges.dts
new file mode 100644
index 000000000..77419f5bf
--- /dev/null
+++ b/dtc/tests/bad-reg-ranges.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ node {
+ reg = <0 0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0>;
+ };
+};
diff --git a/dtc/tests/bad-size-cells.dts b/dtc/tests/bad-size-cells.dts
new file mode 100644
index 000000000..515c0cc7b
--- /dev/null
+++ b/dtc/tests/bad-size-cells.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/ {
+ mangled {
+ #address-cells = <0x0>;
+ #size-cells = <0x0>;
+
+ valid {
+ reg = <0x0 0x4000000>;
+ };
+ };
+};
diff --git a/dtc/tests/bad-string-props.dts b/dtc/tests/bad-string-props.dts
new file mode 100644
index 000000000..6694704a5
--- /dev/null
+++ b/dtc/tests/bad-string-props.dts
@@ -0,0 +1,14 @@
+/dts-v1/;
+
+/ {
+ device_type = <0xdeadbeef>;
+ model = <0xdeadbeef>;
+ status = <0xdeadbeef>;
+ label = <0xdeadbeef>;
+
+ foobar-names = "foo", <1>;
+
+ node {
+ compatible = "good", <0xdeadbeef>;
+ };
+};
diff --git a/dtc/tests/base01.asm b/dtc/tests/base01.asm
new file mode 100644
index 000000000..266e44651
--- /dev/null
+++ b/dtc/tests/base01.asm
@@ -0,0 +1,175 @@
+/* autogenerated by dtc, do not edit */
+
+#define OF_DT_HEADER 0xd00dfeed
+#define OF_DT_BEGIN_NODE 0x1
+#define OF_DT_END_NODE 0x2
+#define OF_DT_PROP 0x3
+#define OF_DT_END 0x9
+
+ .globl dt_blob_start
+dt_blob_start:
+_dt_blob_start:
+ .globl dt_header
+dt_header:
+_dt_header:
+ .long OF_DT_HEADER /* magic */
+ .long _dt_blob_end - _dt_blob_start /* totalsize */
+ .long _dt_struct_start - _dt_blob_start /* off_dt_struct */
+ .long _dt_strings_start - _dt_blob_start /* off_dt_strings */
+ .long _dt_reserve_map - _dt_blob_start /* off_dt_strings */
+ .long 16 /* version */
+ .long 16 /* last_comp_version */
+ .long 0 /*boot_cpuid_phys*/
+ .long _dt_strings_end - _dt_strings_start /* size_dt_strings */
+ .balign 8
+ .globl dt_reserve_map
+dt_reserve_map:
+_dt_reserve_map:
+/* Memory reserve map from source file */
+ .long 0, 0
+ .long 0, 0
+ .globl dt_struct_start
+dt_struct_start:
+_dt_struct_start:
+ .long OF_DT_BEGIN_NODE
+ .string ""
+ .balign 4
+ .long OF_DT_PROP
+ .long 0xa
+ .long 0x0
+ .long 0x536f6d65
+ .long 0x4d6f6465
+ .short 0x6c00
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x8
+ .long 0x6
+ .long 0x4e6f7468
+ .long 0x696e6700
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x11
+ .long 0x2
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x20
+ .long 0x2
+ .balign 4
+ .long OF_DT_BEGIN_NODE
+ .string "memory@0"
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x7
+ .long 0x2c
+ .long 0x6d656d6f
+ .short 0x7279
+ .byte 0x0
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x10
+ .long 0x38
+ .long 0x0
+ .long 0x0
+ .long 0x0
+ .long 0x20000000
+ .balign 4
+ .long OF_DT_END_NODE
+ .long OF_DT_BEGIN_NODE
+ .string "cpus"
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x11
+ .long 0x1
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x20
+ .long 0x0
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x3c
+ .long 0xa
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x40
+ .long 0x17
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x44
+ .long 0x5
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x49
+ .long 0xf
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x4d
+ .long 0xd00d
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x10
+ .long 0x53
+ .long 0x4d2
+ .long 0x162e
+ .long 0x2334
+ .long 0xd80
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x59
+ .long 0x0
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x61
+ .long 0xffffffff
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x69
+ .long 0x0
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x71
+ .long 0xffffffff
+ .balign 4
+ .long OF_DT_END_NODE
+ .long OF_DT_END_NODE
+ .long OF_DT_END
+ .globl dt_struct_end
+dt_struct_end:
+_dt_struct_end:
+ .globl dt_strings_start
+dt_strings_start:
+_dt_strings_start:
+ .string "model"
+ .string "compatible"
+ .string "#address-cells"
+ .string "#size-cells"
+ .string "device_type"
+ .string "reg"
+ .string "d10"
+ .string "d23"
+ .string "b101"
+ .string "o17"
+ .string "hd00d"
+ .string "stuff"
+ .string "bad-d-1"
+ .string "bad-d-2"
+ .string "bad-o-1"
+ .string "bad-o-2"
+ .globl dt_strings_end
+dt_strings_end:
+_dt_strings_end:
+ .globl dt_blob_end
+dt_blob_end:
+_dt_blob_end:
diff --git a/dtc/tests/base01.cmd b/dtc/tests/base01.cmd
new file mode 100644
index 000000000..e1fce6c88
--- /dev/null
+++ b/dtc/tests/base01.cmd
@@ -0,0 +1 @@
+dtc -f -b 0 -V 16 -I dts -O asm
diff --git a/dtc/tests/base01.dts b/dtc/tests/base01.dts
new file mode 100644
index 000000000..97a5dd50b
--- /dev/null
+++ b/dtc/tests/base01.dts
@@ -0,0 +1,33 @@
+/dts-v1/;
+
+/ {
+ model = "SomeModel";
+ compatible = "Nothing";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ d10 = < 10>; // hex: 0xa
+ d23 = < 23>; // hex: 0x17
+ b101 = < 0x5>; // hex: 0x5
+ o17 = < 017>; // hex: 0xf
+ hd00d = < 0xd00d>; // hex: 0xd00d
+
+ // hex: 0x4d2 0x163e 0x2334 0xd80
+ stuff = < 1234 5678 9012 3456>;
+
+
+ bad-d-1 = < 0>; // Hrm. 0
+ bad-d-2 = < 123456789012345>;
+ bad-o-1 = < 00>;
+ bad-o-2 = < 0123456123456>;
+ };
+
+};
diff --git a/dtc/tests/base01.stderr b/dtc/tests/base01.stderr
new file mode 100644
index 000000000..0510b0fb4
--- /dev/null
+++ b/dtc/tests/base01.stderr
@@ -0,0 +1,6 @@
+DTC: dts->asm on file "tests/base01.dts"
+Line 26: Invalid cell value '123456789012345'; -1 assumed
+Line 27: Invalid cell value '891'; 0 assumed
+Line 28: Invalid cell value '123456123456'; -1 assumed
+ERROR: Missing /chosen node
+Input tree has errors
diff --git a/dtc/tests/boot-cpuid.c b/dtc/tests/boot-cpuid.c
new file mode 100644
index 000000000..5ed4f9af1
--- /dev/null
+++ b/dtc/tests/boot-cpuid.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * Copyright (C) 2008 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ uint32_t cpuid;
+
+ test_init(argc, argv);
+
+ if (argc != 3)
+ CONFIG("Usage: %s <dtb file> <cpuid>", argv[0]);
+
+ fdt = load_blob(argv[1]);
+ cpuid = strtoul(argv[2], NULL, 0);
+
+ if (fdt_boot_cpuid_phys(fdt) != cpuid)
+ FAIL("Incorrect boot_cpuid_phys (0x%x instead of 0x%x)",
+ fdt_boot_cpuid_phys(fdt), cpuid);
+
+ PASS();
+}
diff --git a/dtc/tests/boot-cpuid.dts b/dtc/tests/boot-cpuid.dts
new file mode 100644
index 000000000..7021a241f
--- /dev/null
+++ b/dtc/tests/boot-cpuid.dts
@@ -0,0 +1,16 @@
+/dts-v1/;
+
+/ {
+ cpus {
+ cpu@10 {
+ device_type = "cpu";
+ compatible = "fake-cpu";
+ reg = <0x10>;
+ };
+ cpu@11 {
+ device_type = "cpu";
+ compatible = "fake-cpu";
+ reg = <0x11>;
+ };
+ };
+};
diff --git a/dtc/tests/char_literal.c b/dtc/tests/char_literal.c
new file mode 100644
index 000000000..3a69e28a6
--- /dev/null
+++ b/dtc/tests/char_literal.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for character literals in dtc
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright (C) 2011 The Chromium Authors. All rights reserved.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ fdt32_t expected_cells[5];
+
+ expected_cells[0] = cpu_to_fdt32((unsigned char)TEST_CHAR1);
+ expected_cells[1] = cpu_to_fdt32((unsigned char)TEST_CHAR2);
+ expected_cells[2] = cpu_to_fdt32((unsigned char)TEST_CHAR3);
+ expected_cells[3] = cpu_to_fdt32((unsigned char)TEST_CHAR4);
+ expected_cells[4] = cpu_to_fdt32((unsigned char)TEST_CHAR5);
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_getprop(fdt, 0, "char-literal-cells",
+ sizeof(expected_cells), expected_cells);
+
+ PASS();
+}
diff --git a/dtc/tests/char_literal.dts b/dtc/tests/char_literal.dts
new file mode 100644
index 000000000..22e17edaf
--- /dev/null
+++ b/dtc/tests/char_literal.dts
@@ -0,0 +1,5 @@
+/dts-v1/;
+
+/ {
+ char-literal-cells = <'\r' 'b' '\0' '\'' '\xff'>;
+};
diff --git a/dtc/tests/check_full.c b/dtc/tests/check_full.c
new file mode 100644
index 000000000..b6d5fc3b1
--- /dev/null
+++ b/dtc/tests/check_full.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Tests if two given dtbs are structurally equal (including order)
+ * Copyright (C) 2007 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static int expect_bad; /* = 0 */
+
+int main(int argc, char *argv[])
+{
+ const char *filename;
+ char *fdt;
+ size_t len;
+ int err;
+
+ test_init(argc, argv);
+ if ((argc != 2)
+ && ((argc != 3) || !streq(argv[1], "-n")))
+ CONFIG("Usage: %s [-n] <dtb file>", argv[0]);
+ if (argc == 3)
+ expect_bad = 1;
+
+ filename = argv[argc-1];
+ err = utilfdt_read_err(filename, &fdt, &len);
+ if (err)
+ CONFIG("Couldn't open blob from \"%s\": %s",
+ filename, strerror(err));
+
+ vg_prepare_blob(fdt, len);
+
+ err = fdt_check_full(fdt, len);
+
+ if (expect_bad && (err == 0))
+ FAIL("fdt_check_full() succeeded unexpectedly");
+ else if (!expect_bad && (err != 0))
+ FAIL("fdt_check_full() failed: %s", fdt_strerror(err));
+
+ PASS();
+}
diff --git a/dtc/tests/check_header.c b/dtc/tests/check_header.c
new file mode 100644
index 000000000..ca26ec106
--- /dev/null
+++ b/dtc/tests/check_header.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_check_header
+ * Copyright (C) 2018 David Gibson
+ */
+
+#include <stdio.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+
+static void *dtdup(void *dt)
+{
+ size_t bufsize = fdt_totalsize(dt);
+ void *buf = xmalloc(bufsize);
+ fdt_move(dt, buf, bufsize);
+ return buf;
+}
+
+#define CHECK_MANGLE(exerr, code) \
+ do { \
+ void *fdt = dtdup(template); \
+ { code } \
+ err = fdt_check_header(fdt); \
+ verbose_printf("\"%s\" => %s\n", #code, fdt_strerror(err)); \
+ if (err != (exerr)) \
+ FAIL("fdt_check_header() didn't catch mangle %s", \
+ #code); \
+ free(fdt); \
+ } while (0)
+
+int main(int argc, char *argv[])
+{
+ void *template;
+ int err;
+
+ test_init(argc, argv);
+ template = load_blob(argv[1]);
+
+ /* Check that the base dt is valid before mangling it */
+ err = fdt_check_header(template);
+ if (err != 0)
+ FAIL("Base tree fails: %s", fdt_strerror(err));
+
+ /* Check a no-op mangle doesn't break things */
+ CHECK_MANGLE(0, ; );
+
+ /* Mess up the magic number */
+ CHECK_MANGLE(-FDT_ERR_BADMAGIC,
+ fdt_set_magic(fdt, fdt_magic(fdt) ^ 0x1);
+ );
+ CHECK_MANGLE(-FDT_ERR_BADMAGIC,
+ fdt_set_magic(fdt, fdt_magic(fdt) ^ 0x80000000);
+ );
+
+ /* Mess up the version */
+ CHECK_MANGLE(-FDT_ERR_BADVERSION,
+ fdt_set_version(fdt, FDT_FIRST_SUPPORTED_VERSION - 1);
+ fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION - 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_BADVERSION,
+ fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION + 1);
+ fdt_set_last_comp_version(fdt, FDT_LAST_SUPPORTED_VERSION + 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_BADVERSION,
+ fdt_set_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+ fdt_set_last_comp_version(fdt, FDT_LAST_SUPPORTED_VERSION);
+ );
+
+ /* Out of bounds sizes */
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, FDT_V1_SIZE - 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, (uint32_t)INT_MAX + 1);
+ );
+
+ /* Truncate within various blocks */
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, fdt_off_dt_struct(fdt) - 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, fdt_off_dt_strings(fdt) - 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, fdt_off_mem_rsvmap(fdt) - 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, fdt_off_dt_struct(fdt) + 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, fdt_off_dt_strings(fdt) + 1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_totalsize(fdt, fdt_off_mem_rsvmap(fdt) + 1);
+ );
+
+ /* Negative block sizes */
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_size_dt_struct(fdt, (uint32_t)-1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_size_dt_strings(fdt, (uint32_t)-1);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_size_dt_struct(fdt, (uint32_t)INT_MIN);
+ );
+ CHECK_MANGLE(-FDT_ERR_TRUNCATED,
+ fdt_set_size_dt_strings(fdt, (uint32_t)INT_MIN);
+ );
+
+ PASS();
+}
diff --git a/dtc/tests/check_path.c b/dtc/tests/check_path.c
new file mode 100644
index 000000000..cc9757a0a
--- /dev/null
+++ b/dtc/tests/check_path.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for node existence
+ * Copyright (C) 2016 Konsulko Inc.
+ */
+
+#include <stdio.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+
+#define CHECK(code) \
+ { \
+ int err = (code); \
+ if (err) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ }
+
+/* 4k ought to be enough for anybody */
+#define FDT_COPY_SIZE (4 * 1024)
+
+static void *open_dt(char *path)
+{
+ void *dt, *copy;
+
+ dt = load_blob(path);
+ copy = xmalloc(FDT_COPY_SIZE);
+
+ /*
+ * Resize our DTs to 4k so that we have room to operate on
+ */
+ CHECK(fdt_open_into(dt, copy, FDT_COPY_SIZE));
+
+ return copy;
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt_base;
+ int fail_config, exists, check_exists;
+
+ test_init(argc, argv);
+ fail_config = 0;
+
+ if (argc != 4)
+ fail_config = 1;
+
+ if (!fail_config) {
+ if (!strcmp(argv[2], "exists"))
+ check_exists = 1;
+ else if (!strcmp(argv[2], "not-exists"))
+ check_exists = 0;
+ else
+ fail_config = 1;
+ }
+
+ if (fail_config)
+ CONFIG("Usage: %s <base dtb> <[exists|not-exists]> <node-path>", argv[0]);
+
+ fdt_base = open_dt(argv[1]);
+
+ exists = fdt_path_offset(fdt_base, argv[3]) >= 0;
+
+ if (exists == check_exists)
+ PASS();
+ else
+ FAIL();
+}
diff --git a/dtc/tests/comments-cmp.dts b/dtc/tests/comments-cmp.dts
new file mode 100644
index 000000000..4ee9f52dc
--- /dev/null
+++ b/dtc/tests/comments-cmp.dts
@@ -0,0 +1,16 @@
+/dts-v1/;
+
+/ {
+ prop1;
+ prop2;
+ prop3;
+ prop4;
+ prop5;
+ prop6;
+ prop7;
+ prop8;
+ prop9;
+ prop10;
+ child {
+ };
+};
diff --git a/dtc/tests/comments.dts b/dtc/tests/comments.dts
new file mode 100644
index 000000000..0b04b6b88
--- /dev/null
+++ b/dtc/tests/comments.dts
@@ -0,0 +1,39 @@
+/* regexps for lexing comments are.. tricky. Check if we've actually
+ * got it right */
+/dts-v1/;
+
+/ {
+ // line comment
+ prop1;
+ /* comment */
+ prop2;
+ /* multiline
+
+ notaprop1;
+
+ comment */
+ prop3;
+ /**/
+ prop4;
+ /***/
+ prop5;
+ /****/
+ prop6;
+ /* another
+ * multiline
+ * comment */
+ prop7;
+ /* yet
+ * another
+ * multline
+ * comment
+ */
+ prop8;
+ /** try this */
+ prop9;
+ /* and this **/
+ prop10;
+ child /* finally */ {
+ };
+};
+/* final comment */
diff --git a/dtc/tests/data.S b/dtc/tests/data.S
new file mode 100644
index 000000000..86ad539f2
--- /dev/null
+++ b/dtc/tests/data.S
@@ -0,0 +1,3 @@
+/* Used in combination with dtc -Oasm output to embed
+ * a device tree in the data section of a .o */
+ .data
diff --git a/dtc/tests/default-addr-size.dts b/dtc/tests/default-addr-size.dts
new file mode 100644
index 000000000..e964a553f
--- /dev/null
+++ b/dtc/tests/default-addr-size.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+ node {
+ reg = <0 0 0>;
+ };
+};
diff --git a/dtc/tests/del_node.c b/dtc/tests/del_node.c
new file mode 100644
index 000000000..10846dfbe
--- /dev/null
+++ b/dtc/tests/del_node.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_nop_node()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int subnode1_offset, subnode2_offset, subsubnode2_offset;
+ int err;
+ int oldsize, delsize, newsize;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ fdt = open_blob_rw(fdt);
+
+ oldsize = fdt_totalsize(fdt);
+
+ subnode1_offset = fdt_path_offset(fdt, "/subnode@1");
+ if (subnode1_offset < 0)
+ FAIL("Couldn't find \"/subnode@1\": %s",
+ fdt_strerror(subnode1_offset));
+ check_getprop_cell(fdt, subnode1_offset, "prop-int", TEST_VALUE_1);
+
+ subnode2_offset = fdt_path_offset(fdt, "/subnode@2");
+ if (subnode2_offset < 0)
+ FAIL("Couldn't find \"/subnode@2\": %s",
+ fdt_strerror(subnode2_offset));
+ check_getprop_cell(fdt, subnode2_offset, "prop-int", TEST_VALUE_2);
+
+ subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode");
+ if (subsubnode2_offset < 0)
+ FAIL("Couldn't find \"/subnode@2/subsubnode\": %s",
+ fdt_strerror(subsubnode2_offset));
+ check_getprop_cell(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2);
+
+ err = fdt_del_node(fdt, subnode1_offset);
+ if (err)
+ FAIL("fdt_del_node(subnode1): %s", fdt_strerror(err));
+
+ subnode1_offset = fdt_path_offset(fdt, "/subnode@1");
+ if (subnode1_offset != -FDT_ERR_NOTFOUND)
+ FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"",
+ fdt_strerror(subnode1_offset),
+ fdt_strerror(-FDT_ERR_NOTFOUND));
+
+ subnode2_offset = fdt_path_offset(fdt, "/subnode@2");
+ if (subnode2_offset < 0)
+ FAIL("Couldn't find \"/subnode2\": %s",
+ fdt_strerror(subnode2_offset));
+ check_getprop_cell(fdt, subnode2_offset, "prop-int", TEST_VALUE_2);
+
+ subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode");
+ if (subsubnode2_offset < 0)
+ FAIL("Couldn't find \"/subnode@2/subsubnode\": %s",
+ fdt_strerror(subsubnode2_offset));
+ check_getprop_cell(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2);
+
+ err = fdt_del_node(fdt, subnode2_offset);
+ if (err)
+ FAIL("fdt_del_node(subnode2): %s", fdt_strerror(err));
+
+ subnode1_offset = fdt_path_offset(fdt, "/subnode@1");
+ if (subnode1_offset != -FDT_ERR_NOTFOUND)
+ FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"",
+ fdt_strerror(subnode1_offset),
+ fdt_strerror(-FDT_ERR_NOTFOUND));
+
+ subnode2_offset = fdt_path_offset(fdt, "/subnode@2");
+ if (subnode2_offset != -FDT_ERR_NOTFOUND)
+ FAIL("fdt_path_offset(subnode2) returned \"%s\" instead of \"%s\"",
+ fdt_strerror(subnode2_offset),
+ fdt_strerror(-FDT_ERR_NOTFOUND));
+
+ subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode");
+ if (subsubnode2_offset != -FDT_ERR_NOTFOUND)
+ FAIL("fdt_path_offset(subsubnode2) returned \"%s\" instead of \"%s\"",
+ fdt_strerror(subsubnode2_offset),
+ fdt_strerror(-FDT_ERR_NOTFOUND));
+
+ delsize = fdt_totalsize(fdt);
+
+ err = fdt_pack(fdt);
+ if (err)
+ FAIL("fdt_pack(): %s", fdt_strerror(err));
+
+ newsize = fdt_totalsize(fdt);
+
+ verbose_printf("oldsize = %d, delsize = %d, newsize = %d\n",
+ oldsize, delsize, newsize);
+
+ if (newsize >= oldsize)
+ FAIL("Tree failed to shrink after deletions");
+
+ PASS();
+}
diff --git a/dtc/tests/del_property.c b/dtc/tests/del_property.c
new file mode 100644
index 000000000..37e83034c
--- /dev/null
+++ b/dtc/tests/del_property.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_delprop()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ const uint32_t *intp;
+ const char *strp;
+ int err, lenerr;
+ int oldsize, delsize, newsize;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ fdt = open_blob_rw(fdt);
+
+ oldsize = fdt_totalsize(fdt);
+
+ intp = check_getprop_cell(fdt, 0, "prop-int", TEST_VALUE_1);
+ verbose_printf("int value was 0x%08x\n", *intp);
+
+ err = fdt_delprop(fdt, 0, "prop-int");
+ if (err)
+ FAIL("Failed to delete \"prop-int\": %s", fdt_strerror(err));
+
+ intp = fdt_getprop(fdt, 0, "prop-int", &lenerr);
+ if (intp)
+ FAIL("prop-int still present after deletion");
+ if (lenerr != -FDT_ERR_NOTFOUND)
+ FAIL("Unexpected error on second getprop: %s",
+ fdt_strerror(lenerr));
+
+ strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1,
+ TEST_STRING_1);
+ verbose_printf("string value was \"%s\"\n", strp);
+ err = fdt_delprop(fdt, 0, "prop-str");
+ if (err)
+ FAIL("Failed to delete \"prop-str\": %s", fdt_strerror(err));
+
+ strp = fdt_getprop(fdt, 0, "prop-str", &lenerr);
+ if (strp)
+ FAIL("prop-str still present after deletion");
+ if (lenerr != -FDT_ERR_NOTFOUND)
+ FAIL("Unexpected error on second getprop: %s",
+ fdt_strerror(lenerr));
+
+ delsize = fdt_totalsize(fdt);
+
+ err = fdt_pack(fdt);
+ if (err)
+ FAIL("fdt_pack(): %s\n", fdt_strerror(err));
+
+ newsize = fdt_totalsize(fdt);
+
+ verbose_printf("oldsize = %d, delsize = %d, newsize = %d\n",
+ oldsize, delsize, newsize);
+
+ if (newsize >= oldsize)
+ FAIL("Tree failed to shrink after deletions");
+
+ PASS();
+}
diff --git a/dtc/tests/delete_reinstate_multilabel.dts b/dtc/tests/delete_reinstate_multilabel.dts
new file mode 100644
index 000000000..281a6b289
--- /dev/null
+++ b/dtc/tests/delete_reinstate_multilabel.dts
@@ -0,0 +1,37 @@
+/dts-v1/;
+
+/* Create some nodes and properties with multiple labels */
+
+/ {
+ label1: label2: prop = "value";
+
+ label3: label4: node {
+ label5: label6: prop = "value";
+ };
+};
+
+/* Delete them, and everything that's part of them, i.e. the labels */
+
+/ {
+ /delete-property/ prop;
+ /delete-node/ node;
+};
+
+/*
+ * Re-instate them. None of the old labels should come back
+ *
+ * Note: Do not add any new/extra labels here. As of the time of writing,
+ * when dtc adds labels to an object, they are added to the head of the list
+ * of labels, and this test is specifically about ensuring the correct
+ * handling of lists of labels where the first label in the list is marked as
+ * deleted. Failure to observe this note may result in the test passing when
+ * it should not.
+ */
+
+/ {
+ prop = "value";
+
+ node {
+ prop = "value";
+ };
+};
diff --git a/dtc/tests/delete_reinstate_multilabel_ref.dts b/dtc/tests/delete_reinstate_multilabel_ref.dts
new file mode 100644
index 000000000..28fa1174f
--- /dev/null
+++ b/dtc/tests/delete_reinstate_multilabel_ref.dts
@@ -0,0 +1,9 @@
+/dts-v1/;
+
+/ {
+ prop = "value";
+
+ node {
+ prop = "value";
+ };
+};
diff --git a/dtc/tests/dependencies.cmp b/dtc/tests/dependencies.cmp
new file mode 100644
index 000000000..bcd94320b
--- /dev/null
+++ b/dtc/tests/dependencies.cmp
@@ -0,0 +1 @@
+dependencies.test.dtb: dependencies.dts deps_inc1.dtsi deps_inc2.dtsi
diff --git a/dtc/tests/dependencies.dts b/dtc/tests/dependencies.dts
new file mode 100644
index 000000000..2cfe31bd0
--- /dev/null
+++ b/dtc/tests/dependencies.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/include/ "deps_inc1.dtsi"
+
+/ {
+};
diff --git a/dtc/tests/deps_inc1.dtsi b/dtc/tests/deps_inc1.dtsi
new file mode 100644
index 000000000..5c607dcf0
--- /dev/null
+++ b/dtc/tests/deps_inc1.dtsi
@@ -0,0 +1 @@
+/include/ "deps_inc2.dtsi"
diff --git a/dtc/tests/deps_inc2.dtsi b/dtc/tests/deps_inc2.dtsi
new file mode 100644
index 000000000..710cecca9
--- /dev/null
+++ b/dtc/tests/deps_inc2.dtsi
@@ -0,0 +1 @@
+/* Empty */
diff --git a/dtc/tests/division-by-zero.dts b/dtc/tests/division-by-zero.dts
new file mode 100644
index 000000000..2984b29ff
--- /dev/null
+++ b/dtc/tests/division-by-zero.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/ {
+ prop-div = < (1/0) >;
+ prop-mod = < (1%0) >;
+};
diff --git a/dtc/tests/dtb_reverse.c b/dtc/tests/dtb_reverse.c
new file mode 100644
index 000000000..95b6c1c90
--- /dev/null
+++ b/dtc/tests/dtb_reverse.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Tests if two given dtbs are structurally equal (including order)
+ * Copyright (C) 2010 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <limits.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define CHECK(code) \
+ { \
+ err = (code); \
+ if (err) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ }
+
+static void reverse_reservemap(void *in, void *out, int n)
+{
+ int err;
+ uint64_t addr, size;
+
+ verbose_printf("reverse_reservemap(): %d/%d\n",
+ n, fdt_num_mem_rsv(in));
+
+ if (n < (fdt_num_mem_rsv(in)-1))
+ reverse_reservemap(in, out, n+1);
+
+ CHECK(fdt_get_mem_rsv(in, n, &addr, &size));
+ CHECK(fdt_add_reservemap_entry(out, addr, size));
+ verbose_printf("Added entry 0x%llx 0x%llx\n",
+ (unsigned long long)addr, (unsigned long long)size);
+}
+
+static void reverse_properties(void *in, void *out, int offset)
+{
+ int err;
+ int len;
+ const char *name;
+ const void *data;
+
+ data = fdt_getprop_by_offset(in, offset, &name, &len);
+ if (!data)
+ FAIL("fdt_getprop_by_offset(): %s\n", fdt_strerror(len));
+
+ verbose_printf("reverse_properties(): offset=%d name=%s\n",
+ offset, name);
+
+ offset = fdt_next_property_offset(in, offset);
+ if (offset >= 0)
+ reverse_properties(in, out, offset);
+ else if (offset != -FDT_ERR_NOTFOUND)
+ FAIL("fdt_next_property_offset(): %s\n", fdt_strerror(offset));
+
+ CHECK(fdt_property(out, name, data, len));
+ verbose_printf(" -> output property %s\n", name);
+}
+
+static void reverse_node(void *in, void *out, int nodeoffset);
+
+static void reverse_children(void *in, void *out, int offset)
+{
+ int err;
+ int nextoffset = offset;
+ int depth = 1;
+
+ do {
+ char path[PATH_MAX];
+
+ CHECK(fdt_get_path(in, nextoffset, path, sizeof(path)));
+ verbose_printf("reverse_children() offset=%d nextoffset=%d [%s]"
+ " depth=%d\n", offset, nextoffset, path, depth);
+
+ nextoffset = fdt_next_node(in, nextoffset, &depth);
+ } while ((depth >= 0) && (depth != 1));
+
+ if (depth == 1)
+ reverse_children(in, out, nextoffset);
+
+ reverse_node(in, out, offset);
+}
+
+static void reverse_node(void *in, void *out, int nodeoffset)
+{
+ const char *name = fdt_get_name(in, nodeoffset, NULL);
+ char path[PATH_MAX];
+ int err;
+ int offset;
+ int depth = 0;
+
+ CHECK(fdt_get_path(in, nodeoffset, path, sizeof(path)));
+ verbose_printf("reverse_node(): nodeoffset=%d [%s]\n",
+ nodeoffset, path);
+
+ CHECK(fdt_begin_node(out, name));
+
+ offset = fdt_first_property_offset(in, nodeoffset);
+ if (offset >= 0)
+ reverse_properties(in, out, offset);
+ else if (offset != -FDT_ERR_NOTFOUND)
+ FAIL("fdt_first_property(): %s\n", fdt_strerror(offset));
+
+ offset = fdt_next_node(in, nodeoffset, &depth);
+
+ if (depth == 1)
+ reverse_children(in, out, offset);
+
+ CHECK(fdt_end_node(out));
+}
+
+int main(int argc, char *argv[])
+{
+ void *in, *out;
+ char outname[PATH_MAX];
+ int bufsize;
+ int err;
+
+ test_init(argc, argv);
+ if (argc != 2)
+ CONFIG("Usage: %s <dtb file>", argv[0]);
+
+ in = load_blob(argv[1]);
+ sprintf(outname, "%s.reversed.test.dtb", argv[1]);
+
+ bufsize = fdt_totalsize(in);
+ out = xmalloc(bufsize);
+
+ CHECK(fdt_create(out, bufsize));
+
+ fdt_set_boot_cpuid_phys(out, fdt_boot_cpuid_phys(in));
+
+ reverse_reservemap(in, out, 0);
+ CHECK(fdt_finish_reservemap(out));
+
+ reverse_node(in, out, 0);
+
+ CHECK(fdt_finish(out));
+
+ save_blob(outname, out);
+
+ PASS();
+}
diff --git a/dtc/tests/dtbs_equal_ordered.c b/dtc/tests/dtbs_equal_ordered.c
new file mode 100644
index 000000000..90c7344d8
--- /dev/null
+++ b/dtc/tests/dtbs_equal_ordered.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Tests if two given dtbs are structurally equal (including order)
+ * Copyright (C) 2007 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static int notequal; /* = 0 */
+
+#define MISMATCH(fmt, ...) \
+ do { \
+ if (notequal) \
+ PASS(); \
+ else \
+ FAIL(fmt, ##__VA_ARGS__); \
+ } while (0)
+
+#define MATCH() \
+ do { \
+ if (!notequal) \
+ PASS(); \
+ else \
+ FAIL("Trees match which shouldn't"); \
+ } while (0)
+
+#define CHECK(code) \
+ { \
+ err = (code); \
+ if (err) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ }
+
+static void compare_mem_rsv(const void *fdt1, const void *fdt2)
+{
+ int i;
+ uint64_t addr1, size1, addr2, size2;
+ int err;
+
+ if (fdt_num_mem_rsv(fdt1) != fdt_num_mem_rsv(fdt2))
+ MISMATCH("Trees have different number of reserve entries");
+ for (i = 0; i < fdt_num_mem_rsv(fdt1); i++) {
+ CHECK(fdt_get_mem_rsv(fdt1, i, &addr1, &size1));
+ CHECK(fdt_get_mem_rsv(fdt2, i, &addr2, &size2));
+
+ if ((addr1 != addr2) || (size1 != size2))
+ MISMATCH("Mismatch in reserve entry %d: "
+ "(0x%llx, 0x%llx) != (0x%llx, 0x%llx)", i,
+ (unsigned long long)addr1,
+ (unsigned long long)size1,
+ (unsigned long long)addr2,
+ (unsigned long long)size2);
+ }
+}
+
+static void compare_structure(const void *fdt1, const void *fdt2)
+{
+ int nextoffset1 = 0, nextoffset2 = 0;
+ int offset1, offset2;
+ uint32_t tag1, tag2;
+ const char *name1, *name2;
+ int err;
+ const struct fdt_property *prop1, *prop2;
+ int len1, len2;
+
+ while (1) {
+ do {
+ offset1 = nextoffset1;
+ tag1 = fdt_next_tag(fdt1, offset1, &nextoffset1);
+ } while (tag1 == FDT_NOP);
+ do {
+ offset2 = nextoffset2;
+ tag2 = fdt_next_tag(fdt2, offset2, &nextoffset2);
+ } while (tag2 == FDT_NOP);
+
+ if (tag1 != tag2)
+ MISMATCH("Tag mismatch (%d != %d) at (%d, %d)",
+ tag1, tag2, offset1, offset2);
+
+ switch (tag1) {
+ case FDT_BEGIN_NODE:
+ name1 = fdt_get_name(fdt1, offset1, &err);
+ if (!name1)
+ FAIL("fdt_get_name(fdt1, %d, ..): %s",
+ offset1, fdt_strerror(err));
+ name2 = fdt_get_name(fdt2, offset2, NULL);
+ if (!name2)
+ FAIL("fdt_get_name(fdt2, %d, ..): %s",
+ offset2, fdt_strerror(err));
+
+ if (!streq(name1, name2))
+ MISMATCH("Name mismatch (\"%s\" != \"%s\") at (%d, %d)",
+ name1, name2, offset1, offset2);
+ break;
+
+ case FDT_PROP:
+ prop1 = fdt_offset_ptr(fdt1, offset1, sizeof(*prop1));
+ if (!prop1)
+ FAIL("Could get fdt1 property at %d", offset1);
+ prop2 = fdt_offset_ptr(fdt2, offset2, sizeof(*prop2));
+ if (!prop2)
+ FAIL("Could get fdt2 property at %d", offset2);
+
+ name1 = fdt_string(fdt1, fdt32_to_cpu(prop1->nameoff));
+ name2 = fdt_string(fdt2, fdt32_to_cpu(prop2->nameoff));
+ if (!streq(name1, name2))
+ MISMATCH("Property name mismatch \"%s\" != \"%s\" "
+ "at (%d, %d)", name1, name2, offset1, offset2);
+ len1 = fdt32_to_cpu(prop1->len);
+ len2 = fdt32_to_cpu(prop2->len);
+ if (len1 != len2)
+ MISMATCH("Property length mismatch %u != %u "
+ "at (%d, %d)", len1, len2, offset1, offset2);
+
+ if (memcmp(prop1->data, prop2->data, len1) != 0)
+ MISMATCH("Property value mismatch at (%d, %d)",
+ offset1, offset2);
+ break;
+
+ case FDT_END:
+ return;
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt1, *fdt2;
+ uint32_t cpuid1, cpuid2;
+
+ test_init(argc, argv);
+ if ((argc != 3)
+ && ((argc != 4) || !streq(argv[1], "-n")))
+ CONFIG("Usage: %s [-n] <dtb file> <dtb file>", argv[0]);
+ if (argc == 4)
+ notequal = 1;
+
+ fdt1 = load_blob(argv[argc-2]);
+ fdt2 = load_blob(argv[argc-1]);
+
+ compare_mem_rsv(fdt1, fdt2);
+ compare_structure(fdt1, fdt2);
+
+ cpuid1 = fdt_boot_cpuid_phys(fdt1);
+ cpuid2 = fdt_boot_cpuid_phys(fdt2);
+ if (cpuid1 != cpuid2)
+ MISMATCH("boot_cpuid_phys mismatch 0x%x != 0x%x",
+ cpuid1, cpuid2);
+
+ MATCH();
+}
diff --git a/dtc/tests/dtbs_equal_unordered.c b/dtc/tests/dtbs_equal_unordered.c
new file mode 100644
index 000000000..e5ff9e8b1
--- /dev/null
+++ b/dtc/tests/dtbs_equal_unordered.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Tests if two given dtbs are structurally equal (including order)
+ * Copyright (C) 2007 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <limits.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static int notequal; /* = 0 */
+static int ignore_memrsv; /* = 0 */
+
+#define MISMATCH(fmt, ...) \
+ do { \
+ if (notequal) \
+ PASS(); \
+ else \
+ FAIL(fmt, ##__VA_ARGS__); \
+ } while (0)
+
+#define MATCH() \
+ do { \
+ if (!notequal) \
+ PASS(); \
+ else \
+ FAIL("Trees match which shouldn't"); \
+ } while (0)
+
+#define CHECK(code) \
+ { \
+ err = (code); \
+ if (err) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ }
+
+static int mem_rsv_cmp(const void *p1, const void *p2)
+{
+ const struct fdt_reserve_entry *re1 = p1;
+ const struct fdt_reserve_entry *re2 = p2;
+
+ if (fdt64_to_cpu(re1->address) < fdt64_to_cpu(re2->address))
+ return -1;
+ else if (fdt64_to_cpu(re1->address) > fdt64_to_cpu(re2->address))
+ return 1;
+
+ if (fdt64_to_cpu(re1->size) < fdt64_to_cpu(re2->size))
+ return -1;
+ else if (fdt64_to_cpu(re1->size) > fdt64_to_cpu(re2->size))
+ return 1;
+
+ return 0;
+}
+
+static void compare_mem_rsv(void *fdt1, void *fdt2)
+{
+ int i;
+ uint64_t addr1, size1, addr2, size2;
+ int err;
+
+ if (fdt_num_mem_rsv(fdt1) != fdt_num_mem_rsv(fdt2))
+ MISMATCH("Trees have different number of reserve entries");
+
+ qsort((char *)fdt1 + fdt_off_mem_rsvmap(fdt1), fdt_num_mem_rsv(fdt1),
+ sizeof(struct fdt_reserve_entry), mem_rsv_cmp);
+ qsort((char *)fdt2 + fdt_off_mem_rsvmap(fdt2), fdt_num_mem_rsv(fdt2),
+ sizeof(struct fdt_reserve_entry), mem_rsv_cmp);
+
+ for (i = 0; i < fdt_num_mem_rsv(fdt1); i++) {
+ CHECK(fdt_get_mem_rsv(fdt1, i, &addr1, &size1));
+ CHECK(fdt_get_mem_rsv(fdt2, i, &addr2, &size2));
+
+ if ((addr1 != addr2) || (size1 != size2))
+ MISMATCH("Mismatch in reserve entry %d: "
+ "(0x%llx, 0x%llx) != (0x%llx, 0x%llx)", i,
+ (unsigned long long)addr1,
+ (unsigned long long)size1,
+ (unsigned long long)addr2,
+ (unsigned long long)size2);
+ }
+}
+
+static void compare_properties(const void *fdt1, int offset1,
+ const void *fdt2, int offset2)
+{
+ int offset = offset1;
+
+ /* Check the properties */
+ for (offset = fdt_first_property_offset(fdt1, offset1);
+ offset >= 0;
+ offset = fdt_next_property_offset(fdt1, offset)) {
+ const char *name;
+ int len1, len2;
+ const void *data1, *data2;
+ int i;
+
+ data1 = fdt_getprop_by_offset(fdt1, offset, &name, &len1);
+ if (!data1)
+ FAIL("fdt_getprop_by_offset(): %s\n",
+ fdt_strerror(len1));
+
+ verbose_printf("Property '%s'\n", name);
+
+ data2 = fdt_getprop(fdt2, offset2, name, &len2);
+ if (!data2) {
+ if (len2 == -FDT_ERR_NOTFOUND)
+ MISMATCH("Property '%s' missing\n", name);
+ else
+ FAIL("fdt_get_property(): %s\n",
+ fdt_strerror(len2));
+ }
+
+ verbose_printf("len1=%d data1=", len1);
+ for (i = 0; i < len1; i++)
+ verbose_printf(" %02x", ((const char *)data1)[i]);
+ verbose_printf("\nlen2=%d data2=", len2);
+ for (i = 0; i < len1; i++)
+ verbose_printf(" %02x", ((const char *)data2)[i]);
+ verbose_printf("\n");
+
+ if (len1 != len2)
+ MISMATCH("Property '%s' mismatched length %d vs. %d\n",
+ name, len1, len2);
+ else if (memcmp(data1, data2, len1) != 0)
+ MISMATCH("Property '%s' mismatched value\n", name);
+ }
+}
+
+static void compare_node(const void *fdt1, int offset1,
+ const void *fdt2, int offset2);
+
+static void compare_subnodes(const void *fdt1, int offset1,
+ const void *fdt2, int offset2,
+ int recurse)
+{
+ int coffset1, coffset2, depth;
+
+ for (depth = 0, coffset1 = offset1;
+ (coffset1 >= 0) && (depth >= 0);
+ coffset1 = fdt_next_node(fdt1, coffset1, &depth))
+ if (depth == 1) {
+ const char *name = fdt_get_name(fdt1, coffset1, NULL);
+
+ verbose_printf("Subnode %s\n", name);
+ coffset2 = fdt_subnode_offset(fdt2, offset2, name);
+ if (coffset2 == -FDT_ERR_NOTFOUND)
+ MISMATCH("Subnode %s missing\n", name);
+ else if (coffset2 < 0)
+ FAIL("fdt_subnode_offset(): %s\n",
+ fdt_strerror(coffset2));
+
+ if (recurse)
+ compare_node(fdt1, coffset1, fdt2, coffset2);
+ }
+}
+
+static void compare_node(const void *fdt1, int offset1,
+ const void *fdt2, int offset2)
+{
+ int err;
+ char path1[PATH_MAX], path2[PATH_MAX];
+
+ CHECK(fdt_get_path(fdt1, offset1, path1, sizeof(path1)));
+ CHECK(fdt_get_path(fdt2, offset2, path2, sizeof(path2)));
+
+ if (!streq(path1, path2))
+ TEST_BUG("Path mismatch %s vs. %s\n", path1, path2);
+
+ verbose_printf("Checking %s\n", path1);
+
+ compare_properties(fdt1, offset1, fdt2, offset2);
+ compare_properties(fdt2, offset2, fdt1, offset1);
+
+ compare_subnodes(fdt1, offset1, fdt2, offset2, 1);
+ compare_subnodes(fdt2, offset2, fdt1, offset1, 0);
+}
+
+static void badargs(char **argv)
+{
+ CONFIG("Usage: %s [-n] [-m] <dtb file> <dtb file>", argv[0]);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt1, *fdt2;
+ uint32_t cpuid1, cpuid2;
+ char **args;
+ int argsleft;
+
+ test_init(argc, argv);
+
+ args = &argv[1];
+ argsleft = argc - 1;
+
+ while (argsleft > 2) {
+ if (streq(args[0], "-n"))
+ notequal = 1;
+ else if (streq(args[0], "-m"))
+ ignore_memrsv = 1;
+ else
+ badargs(argv);
+ args++;
+ argsleft--;
+ }
+ if (argsleft != 2)
+ badargs(argv);
+
+ fdt1 = load_blob(args[0]);
+ fdt2 = load_blob(args[1]);
+
+ if (!ignore_memrsv)
+ compare_mem_rsv(fdt1, fdt2);
+ compare_node(fdt1, 0, fdt2, 0);
+
+ cpuid1 = fdt_boot_cpuid_phys(fdt1);
+ cpuid2 = fdt_boot_cpuid_phys(fdt2);
+ if (cpuid1 != cpuid2)
+ MISMATCH("boot_cpuid_phys mismatch 0x%x != 0x%x",
+ cpuid1, cpuid2);
+
+ MATCH();
+}
diff --git a/dtc/tests/dtc-checkfails.sh b/dtc/tests/dtc-checkfails.sh
new file mode 100755
index 000000000..4fd9691a2
--- /dev/null
+++ b/dtc/tests/dtc-checkfails.sh
@@ -0,0 +1,45 @@
+#! /bin/sh
+
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
+
+for x; do
+ shift
+ if [ "$x" = "-n" ]; then
+ for x; do
+ shift
+ if [ "$x" = "--" ]; then
+ break;
+ fi
+ NOCHECKS="$NOCHECKS $x"
+ done
+ break;
+ fi
+ if [ "$x" = "--" ]; then
+ break;
+ fi
+ YESCHECKS="$YESCHECKS $x"
+done
+
+LOG=tmp.log.$$
+rm -f $LOG
+trap "rm -f $LOG" 0
+
+verbose_run_log "$LOG" $VALGRIND "$DTC" -o /dev/null "$@"
+ret="$?"
+
+FAIL_IF_SIGNAL $ret
+
+for c in $YESCHECKS; do
+ if ! grep -E "(ERROR|Warning) \($c\):" $LOG > /dev/null; then
+ FAIL "Failed to trigger check \"$c\""
+ fi
+done
+
+for c in $NOCHECKS; do
+ if grep -E "(ERROR|Warning) \($c\):" $LOG > /dev/null; then
+ FAIL "Incorrectly triggered check \"$c\""
+ fi
+done
+
+PASS
diff --git a/dtc/tests/dtc-fails.sh b/dtc/tests/dtc-fails.sh
new file mode 100755
index 000000000..855b623a1
--- /dev/null
+++ b/dtc/tests/dtc-fails.sh
@@ -0,0 +1,31 @@
+#! /bin/sh
+
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
+
+if [ "$1" = "-n" ]; then
+ NEG="$1"
+ shift
+fi
+
+OUTPUT="$1"
+shift
+
+verbose_run $VALGRIND "$DTC" -o "$OUTPUT" "$@"
+ret="$?"
+
+FAIL_IF_SIGNAL $ret
+
+if [ -n "$NEG" ]; then
+ if [ ! -e "$OUTPUT" ]; then
+ FAIL "Produced no output"
+ fi
+else
+ if [ -e "$OUTPUT" ]; then
+ FAIL "Incorrectly produced output"
+ fi
+fi
+
+rm -f "$OUTPUT"
+
+PASS
diff --git a/dtc/tests/dtc-fatal.sh b/dtc/tests/dtc-fatal.sh
new file mode 100755
index 000000000..08a4d295a
--- /dev/null
+++ b/dtc/tests/dtc-fatal.sh
@@ -0,0 +1,15 @@
+#! /bin/sh
+
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
+
+verbose_run $VALGRIND "$DTC" -o/dev/null "$@"
+ret="$?"
+
+if [ "$ret" -gt 127 ]; then
+ FAIL "dtc killed by signal (ret=$ret)"
+elif [ "$ret" != "1" ]; then
+ FAIL "dtc returned incorrect status $ret instead of 1"
+fi
+
+PASS
diff --git a/dtc/tests/dumptrees.c b/dtc/tests/dumptrees.c
new file mode 100644
index 000000000..f1e0ea970
--- /dev/null
+++ b/dtc/tests/dumptrees.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * dumptrees - utility for libfdt testing
+ *
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2006.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "testdata.h"
+
+static struct {
+ void *blob;
+ const char *filename;
+} trees[] = {
+#define TREE(name) { &name, #name ".dtb" }
+ TREE(test_tree1),
+ TREE(bad_node_char), TREE(bad_node_format), TREE(bad_prop_char),
+ TREE(ovf_size_strings),
+ TREE(truncated_property), TREE(truncated_string),
+ TREE(truncated_memrsv),
+ TREE(two_roots),
+ TREE(named_root)
+};
+
+#define NUM_TREES (sizeof(trees) / sizeof(trees[0]))
+
+int main(int argc, char *argv[])
+{
+ int i;
+
+ if (argc != 2) {
+ fprintf(stderr, "Missing output directory argument\n");
+ return 1;
+ }
+
+ if (chdir(argv[1]) != 0) {
+ perror("chdir()");
+ return 1;
+ }
+
+ for (i = 0; i < NUM_TREES; i++) {
+ void *blob = trees[i].blob;
+ const char *filename = trees[i].filename;
+ int size;
+ int fd;
+ int ret;
+
+ size = fdt_totalsize(blob);
+
+ printf("Tree \"%s\", %d bytes\n", filename, size);
+
+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0)
+ perror("open()");
+
+ ret = write(fd, blob, size);
+ if (ret != size)
+ perror("write()");
+
+ close(fd);
+ }
+ exit(0);
+}
diff --git a/dtc/tests/dup-nodename.dts b/dtc/tests/dup-nodename.dts
new file mode 100644
index 000000000..2a3aa7596
--- /dev/null
+++ b/dtc/tests/dup-nodename.dts
@@ -0,0 +1,8 @@
+/dts-v1/;
+
+/ {
+ node {
+ };
+ node {
+ };
+};
diff --git a/dtc/tests/dup-phandle.dts b/dtc/tests/dup-phandle.dts
new file mode 100644
index 000000000..c266c6127
--- /dev/null
+++ b/dtc/tests/dup-phandle.dts
@@ -0,0 +1,10 @@
+/dts-v1/;
+
+/ {
+ node1 {
+ linux,phandle = <1>;
+ };
+ node2 {
+ linux,phandle = <1>;
+ };
+};
diff --git a/dtc/tests/dup-propname.dts b/dtc/tests/dup-propname.dts
new file mode 100644
index 000000000..8145f6e9d
--- /dev/null
+++ b/dtc/tests/dup-propname.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/ {
+ prop;
+ prop;
+};
diff --git a/dtc/tests/embedded_nul.dts b/dtc/tests/embedded_nul.dts
new file mode 100644
index 000000000..7b4993cc5
--- /dev/null
+++ b/dtc/tests/embedded_nul.dts
Binary files differ
diff --git a/dtc/tests/embedded_nul_equiv.dts b/dtc/tests/embedded_nul_equiv.dts
new file mode 100644
index 000000000..e978204f0
--- /dev/null
+++ b/dtc/tests/embedded_nul_equiv.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/ {
+ reserved-names = "aaaaaaaaaaaaaaaaaa\0bbbbbb\0ccccccccccccc";
+ reserved-ranges = < 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 >;
+};
diff --git a/dtc/tests/empty.dts b/dtc/tests/empty.dts
new file mode 100644
index 000000000..e160dad6a
--- /dev/null
+++ b/dtc/tests/empty.dts
@@ -0,0 +1,4 @@
+/dts-v1/;
+
+/ {
+};
diff --git a/dtc/tests/escapes.dts b/dtc/tests/escapes.dts
new file mode 100644
index 000000000..e05ab46bc
--- /dev/null
+++ b/dtc/tests/escapes.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+ compatible = "test_string_escapes";
+ escape-str = "nastystring: \a\b\t\n\v\f\r\\\"";
+ escape-str-2 = "\xde\xad\xbe\xef";
+};
diff --git a/dtc/tests/extra-terminating-null.c b/dtc/tests/extra-terminating-null.c
new file mode 100644
index 000000000..0fa2ca8e1
--- /dev/null
+++ b/dtc/tests/extra-terminating-null.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for properties with more than one terminating null
+ * Copyright (C) 2009 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check_extranull(void *fdt, const char *prop, const char *str, int numnulls)
+{
+ int len = strlen(str);
+ char checkbuf[len+numnulls];
+
+ memset(checkbuf, 0, sizeof(checkbuf));
+ memcpy(checkbuf, TEST_STRING_1, len);
+
+ check_getprop(fdt, 0, prop, len+numnulls, checkbuf);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+
+ fdt = load_blob_arg(argc, argv);
+
+ check_extranull(fdt, "extranull0", TEST_STRING_1, 1);
+ check_extranull(fdt, "extranull1,1", TEST_STRING_1, 2);
+ check_extranull(fdt, "extranull1,2", TEST_STRING_1, 2);
+ check_extranull(fdt, "extranull2,1", TEST_STRING_1, 3);
+ check_extranull(fdt, "extranull2,2", TEST_STRING_1, 3);
+ check_extranull(fdt, "extranull2,3", TEST_STRING_1, 3);
+ check_extranull(fdt, "extranull2,4", TEST_STRING_1, 3);
+
+ PASS();
+}
diff --git a/dtc/tests/extra-terminating-null.dts b/dtc/tests/extra-terminating-null.dts
new file mode 100644
index 000000000..b6cc19c18
--- /dev/null
+++ b/dtc/tests/extra-terminating-null.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/ {
+ extranull0 = "hello world";
+ extranull1,1 = "hello world\0";
+ extranull1,2 = "hello world", "";
+ extranull2,1 = "hello world\0\0";
+ extranull2,2 = "hello world", "", "";
+ extranull2,3 = "hello world\0", "";
+ extranull2,4 = "hello world", "\0";
+};
diff --git a/dtc/tests/fdtdump-runtest.sh b/dtc/tests/fdtdump-runtest.sh
new file mode 100755
index 000000000..71ac86147
--- /dev/null
+++ b/dtc/tests/fdtdump-runtest.sh
@@ -0,0 +1,31 @@
+#! /bin/sh
+
+# Arguments:
+# $1 - source file to compile and compare with fdtdump output of the
+# compiled file.
+
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
+
+dts="$1"
+dtb="${dts}.dtb"
+out="${dts}.out"
+LOG=tmp.log.$$
+
+files="$dtb $out $LOG"
+
+rm -f $files
+trap "rm -f $files" 0
+
+verbose_run_log_check "$LOG" $VALGRIND $DTC -O dtb $dts -o $dtb
+$FDTDUMP ${dtb} | grep -v "//" >${out}
+
+if diff -w $dts $out >/dev/null; then
+ PASS
+else
+ if [ -z "$QUIET_TEST" ]; then
+ echo "DIFF :-:"
+ diff -u -w $dts $out
+ fi
+ FAIL "Results differ from expected"
+fi
diff --git a/dtc/tests/fdtdump.dts b/dtc/tests/fdtdump.dts
new file mode 100644
index 000000000..b83b7dffa
--- /dev/null
+++ b/dtc/tests/fdtdump.dts
@@ -0,0 +1,38 @@
+/dts-v1/;
+
+/memreserve/ 0 0xe;
+/ {
+ model = "MyBoardName";
+ compatible = "MyBoardName", "MyBoardFamilyName";
+ #address-cells = <0x00000002>;
+ #size-cells = <0x00000002>;
+ cpus {
+ linux,phandle = <0x00000001>;
+ #address-cells = <0x00000001>;
+ #size-cells = <0x00000000>;
+ PowerPC,970@0 {
+ device_type = "cpu";
+ reg = <0x00000000>;
+ linux,boot-cpu;
+ };
+ PowerPC,970@1 {
+ device_type = "cpu";
+ reg = <0x00000001>;
+ };
+ };
+ randomnode {
+ string = "foo", "stuff";
+ bytes = [61 62 63 64 65];
+ nbytes = [80 ff];
+ child {
+ };
+ };
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x00000123 0x00000456 0x87654321>;
+ };
+ chosen {
+ bootargs = "root=/dev/sda2";
+ linux,platform = <0x00000600>;
+ };
+};
diff --git a/dtc/tests/fdtget-runtest.sh b/dtc/tests/fdtget-runtest.sh
new file mode 100755
index 000000000..18b7404a0
--- /dev/null
+++ b/dtc/tests/fdtget-runtest.sh
@@ -0,0 +1,25 @@
+#! /bin/sh
+
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
+
+LOG=tmp.log.$$
+EXPECT=tmp.expect.$$
+rm -f $LOG $EXPECT
+trap "rm -f $LOG $EXPECT" 0
+
+expect="$1"
+printf '%b\n' "$expect" > $EXPECT
+shift
+
+verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@"
+
+if cmp $EXPECT $LOG>/dev/null; then
+ PASS
+else
+ if [ -z "$QUIET_TEST" ]; then
+ echo "EXPECTED :-:"
+ cat $EXPECT
+ fi
+ FAIL "Results differ from expected"
+fi
diff --git a/dtc/tests/fdtoverlay-runtest.sh b/dtc/tests/fdtoverlay-runtest.sh
new file mode 100755
index 000000000..0c648f499
--- /dev/null
+++ b/dtc/tests/fdtoverlay-runtest.sh
@@ -0,0 +1,41 @@
+#! /bin/sh
+
+# Run script for fdtoverlay tests
+# We run fdtoverlay to generate a target device tree, then fdtget to check it
+
+# Usage
+# fdtoverlay-runtest.sh name expected_output dtb_file node property flags value
+
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
+
+LOG=tmp.log.$$
+EXPECT=tmp.expect.$$
+rm -f $LOG $EXPECT
+trap "rm -f $LOG $EXPECT" 0
+
+expect="$1"
+echo $expect >$EXPECT
+node="$2"
+property="$3"
+flags="$4"
+basedtb="$5"
+targetdtb="$6"
+shift 6
+overlays="$@"
+
+# First run fdtoverlay
+verbose_run_check $VALGRIND "$FDTOVERLAY" -i "$basedtb" -o "$targetdtb" $overlays
+
+# Now fdtget to read the value
+verbose_run_log_check "$LOG" $VALGRIND "$DTGET" "$targetdtb" "$node" "$property" $flags
+
+if cmp $EXPECT $LOG >/dev/null; then
+ PASS
+else
+ if [ -z "$QUIET_TEST" ]; then
+ echo "EXPECTED :-:"
+ cat $EXPECT
+ fi
+ FAIL "Results differ from expected"
+fi
diff --git a/dtc/tests/fdtput-runtest.sh b/dtc/tests/fdtput-runtest.sh
new file mode 100755
index 000000000..1210eabf4
--- /dev/null
+++ b/dtc/tests/fdtput-runtest.sh
@@ -0,0 +1,40 @@
+#! /bin/sh
+
+# Run script for fdtput tests
+# We run fdtput to update the device tree, then fdtget to check it
+
+# Usage
+# fdtput-runtest.sh name expected_output dtb_file node property flags value
+
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
+
+LOG=tmp.log.$$
+EXPECT=tmp.expect.$$
+rm -f $LOG $EXPECT
+trap "rm -f $LOG $EXPECT" 0
+
+expect="$1"
+echo $expect >$EXPECT
+dtb="$2"
+node="$3"
+property="$4"
+flags="$5"
+shift 5
+value="$@"
+
+# First run fdtput
+verbose_run_check $VALGRIND "$DTPUT" "$dtb" "$node" "$property" $value $flags
+
+# Now fdtget to read the value
+verbose_run_log_check "$LOG" $VALGRIND "$DTGET" "$dtb" "$node" "$property" $flags
+
+if cmp $EXPECT $LOG >/dev/null; then
+ PASS
+else
+ if [ -z "$QUIET_TEST" ]; then
+ echo "EXPECTED :-:"
+ cat $EXPECT
+ fi
+ FAIL "Results differ from expected"
+fi
diff --git a/dtc/tests/find_property.c b/dtc/tests/find_property.c
new file mode 100644
index 000000000..0404ea0bb
--- /dev/null
+++ b/dtc/tests/find_property.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_property_offset()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_property_cell(fdt, 0, "prop-int", TEST_VALUE_1);
+ check_property(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, TEST_STRING_1);
+
+ PASS();
+}
diff --git a/dtc/tests/fs_tree1.c b/dtc/tests/fs_tree1.c
new file mode 100644
index 000000000..dff388083
--- /dev/null
+++ b/dtc/tests/fs_tree1.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase/tool constructing an fs tree for further test
+ * Copyright (C) 2018 David Gibson, Red Hat Inc.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void start_dir(const char *name)
+{
+ int rc;
+
+ rc = mkdir(name, 0777);
+ if (rc != 0)
+ FAIL("mkdir(\"%s\"): %s", name, strerror(errno));
+
+ rc = chdir(name);
+ if (rc != 0)
+ FAIL("chdir(\"%s\"): %s", name, strerror(errno));
+}
+
+static void end_dir(void)
+{
+ int rc;
+
+ rc = chdir("..");
+ if (rc != 0)
+ FAIL("chdir(..): %s", strerror(errno));
+}
+
+static void mkfile(const char *name, void *data, size_t len)
+{
+ int fd;
+ int rc;
+
+ fd = open(name, O_WRONLY|O_CREAT, 0666);
+ if (fd < 0)
+ FAIL("open(\"%s\"): %s", name, strerror(errno));
+
+ rc = write(fd, data, len);
+ if (rc < 0)
+ FAIL("write(\"%s\"): %s", name, strerror(errno));
+ if (rc != len)
+ FAIL("write(\"%s\"): short write", name);
+
+ rc = close(fd);
+ if (rc != 0)
+ FAIL("close(\"%s\"): %s", name, strerror(errno));
+}
+
+#define mkfile_str(name, s) \
+ do { \
+ char str[] = s; \
+ mkfile((name), str, sizeof(str)); \
+ } while (0)
+
+static void mkfile_u32(const char *name, uint32_t val)
+{
+ val = cpu_to_fdt32(val);
+ mkfile(name, &val, sizeof(val));
+}
+
+static void mkfile_u64(const char *name, uint64_t val)
+{
+ val = cpu_to_fdt64(val);
+ mkfile(name, &val, sizeof(val));
+}
+
+int main(int argc, char *argv[])
+{
+ const char *base;
+
+ test_init(argc, argv);
+ if (argc != 2)
+ CONFIG("Usage: %s <path>", argv[0]);
+
+ base = argv[1];
+
+ start_dir(base);
+ mkfile_str("compatible", "test_tree1");
+ mkfile_u32("prop-int", TEST_VALUE_1);
+ mkfile_u64("prop-int64", 0xdeadbeef01abcdefULL);
+ mkfile_str("prop-str", "hello world");
+ mkfile_u32("#address-cells", 1);
+ mkfile_u32("#size-cells", 0);
+
+ {
+ start_dir("subnode@1");
+
+ mkfile_str("compatible", "subnode1");
+ mkfile_u32("reg", 1);
+ mkfile_u32("prop-int", TEST_VALUE_1);
+
+ {
+ start_dir("subsubnode");
+
+ mkfile_str("compatible", "subsubnode1\0subsubnode");
+ mkfile_str("placeholder", "this is a placeholder string\0string2");
+ mkfile_u32("prop-int", TEST_VALUE_1);
+
+ end_dir();
+ }
+
+ {
+ start_dir("ss1");
+ end_dir();
+ }
+
+ end_dir();
+ }
+
+ {
+ start_dir("subnode@2");
+
+ mkfile_u32("reg", 2);
+ mkfile_u32("linux,phandle", 0x2000);
+ mkfile_u32("prop-int", TEST_VALUE_2);
+ mkfile_u32("#address-cells", 1);
+ mkfile_u32("#size-cells", 0);
+
+ {
+ start_dir("subsubnode@0");
+
+ mkfile_u32("reg", 0);
+ mkfile_u32("phandle", 0x2001);
+ mkfile_str("compatible", "subsubnode2\0subsubnode");
+ mkfile_u32("prop-int", TEST_VALUE_2);
+
+ end_dir();
+ }
+
+ {
+ start_dir("ss2");
+ end_dir();
+ }
+
+ end_dir();
+ }
+
+ PASS();
+}
diff --git a/dtc/tests/get_alias.c b/dtc/tests/get_alias.c
new file mode 100644
index 000000000..fb2c38c07
--- /dev/null
+++ b/dtc/tests/get_alias.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_get_alias()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check_alias(void *fdt, const char *path, const char *alias)
+{
+ const char *aliaspath;
+
+ aliaspath = fdt_get_alias(fdt, alias);
+
+ if (path && !aliaspath)
+ FAIL("fdt_get_alias(%s) failed\n", alias);
+
+ if (strcmp(aliaspath, path) != 0)
+ FAIL("fdt_get_alias(%s) returned %s instead of %s\n",
+ alias, aliaspath, path);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_alias(fdt, "/subnode@1", "s1");
+ check_alias(fdt, "/subnode@1/subsubnode", "ss1");
+ check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "sss1");
+
+ PASS();
+}
diff --git a/dtc/tests/get_mem_rsv.c b/dtc/tests/get_mem_rsv.c
new file mode 100644
index 000000000..f977d19d9
--- /dev/null
+++ b/dtc/tests/get_mem_rsv.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_get_mem_rsv() and fdt_num_mem_rsv()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int rc;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ rc = fdt_num_mem_rsv(fdt);
+ if (rc < 0)
+ FAIL("fdt_num_mem_rsv(): %s", fdt_strerror(rc));
+ if (rc != 2)
+ FAIL("fdt_num_mem_rsv() returned %d instead of 2", rc);
+
+ check_mem_rsv(fdt, 0, TEST_ADDR_1, TEST_SIZE_1);
+ check_mem_rsv(fdt, 1, TEST_ADDR_2, TEST_SIZE_2);
+ PASS();
+}
diff --git a/dtc/tests/get_name.c b/dtc/tests/get_name.c
new file mode 100644
index 000000000..5a35103ff
--- /dev/null
+++ b/dtc/tests/get_name.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_get_name()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check_name(void *fdt, const char *path)
+{
+ int offset;
+ const char *getname, *getname2, *checkname;
+ int len;
+
+ checkname = strrchr(path, '/');
+ if (!checkname)
+ TEST_BUG();
+ checkname += 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, checkname) != 0)
+ FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"",
+ path, getname, checkname);
+
+ if (len != strlen(getname))
+ FAIL("fdt_get_name(%s) returned length %d instead of %zd",
+ path, len, strlen(getname));
+
+ /* Now check that it doesn't break if we omit len */
+ getname2 = fdt_get_name(fdt, offset, NULL);
+ if (!getname2)
+ FAIL("fdt_get_name(%d, NULL) failed", offset);
+ if (strcmp(getname2, getname) != 0)
+ FAIL("fdt_get_name(%d, NULL) returned \"%s\" instead of \"%s\"",
+ offset, getname2, getname);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_name(fdt, "/");
+ check_name(fdt, "/subnode@1");
+ check_name(fdt, "/subnode@2");
+ check_name(fdt, "/subnode@1/subsubnode");
+ check_name(fdt, "/subnode@2/subsubnode@0");
+
+ PASS();
+}
diff --git a/dtc/tests/get_path.c b/dtc/tests/get_path.c
new file mode 100644
index 000000000..734989874
--- /dev/null
+++ b/dtc/tests/get_path.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_get_path()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define POISON ('\xff')
+
+static void check_path_buf(void *fdt, const char *path, int pathlen, int buflen)
+{
+ int offset;
+ char buf[buflen+1];
+ int len;
+
+ offset = fdt_path_offset(fdt, path);
+ if (offset < 0)
+ FAIL("Couldn't find path \"%s\": %s", path, fdt_strerror(offset));
+
+ memset(buf, POISON, sizeof(buf)); /* poison the buffer */
+
+ len = fdt_get_path(fdt, offset, buf, buflen);
+ verbose_printf("get_path() %s -> %d -> %s\n", path, offset,
+ len >= 0 ? buf : "<error>");
+
+ if (buflen <= pathlen) {
+ if (len != -FDT_ERR_NOSPACE)
+ FAIL("fdt_get_path([%d bytes]) returns %d with "
+ "insufficient buffer space", buflen, len);
+ } else {
+ if (len < 0)
+ FAIL("fdt_get_path([%d bytes]): %s", buflen,
+ fdt_strerror(len));
+ if (len != 0)
+ FAIL("fdt_get_path([%d bytes]) returns %d "
+ "instead of 0", buflen, len);
+ if (strcmp(buf, path) != 0)
+ FAIL("fdt_get_path([%d bytes]) returns \"%s\" "
+ "instead of \"%s\"", buflen, buf, path);
+ }
+
+ if (buf[buflen] != POISON)
+ FAIL("fdt_get_path([%d bytes]) overran buffer", buflen);
+}
+
+static void check_path(void *fdt, const char *path)
+{
+ int pathlen = strlen(path);
+
+ check_path_buf(fdt, path, pathlen, 1024);
+ check_path_buf(fdt, path, pathlen, pathlen+1);
+ check_path_buf(fdt, path, pathlen, pathlen);
+ check_path_buf(fdt, path, pathlen, 0);
+ check_path_buf(fdt, path, pathlen, 2);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_path(fdt, "/");
+ check_path(fdt, "/subnode@1");
+ check_path(fdt, "/subnode@2");
+ check_path(fdt, "/subnode@1/subsubnode");
+ check_path(fdt, "/subnode@2/subsubnode@0");
+
+ PASS();
+}
diff --git a/dtc/tests/get_phandle.c b/dtc/tests/get_phandle.c
new file mode 100644
index 000000000..157b522d0
--- /dev/null
+++ b/dtc/tests/get_phandle.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_get_phandle()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static 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);
+}
+
+static void check_phandle_unique(const void *fdt, uint32_t checkhandle)
+{
+ uint32_t phandle;
+ int offset = -1;
+
+ while (true) {
+ offset = fdt_next_node(fdt, offset, NULL);
+ if (offset < 0) {
+ if (offset == -FDT_ERR_NOTFOUND)
+ break;
+
+ FAIL("error looking for phandle %#x", checkhandle);
+ }
+
+ phandle = fdt_get_phandle(fdt, offset);
+
+ if (phandle == checkhandle)
+ FAIL("generated phandle already exists");
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ uint32_t max, phandle;
+ void *fdt;
+ int err;
+
+ 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);
+
+ err = fdt_find_max_phandle(fdt, &max);
+ if (err < 0)
+ FAIL("fdt_find_max_phandle returned %d instead of 0\n", err);
+
+ if (max != PHANDLE_2)
+ FAIL("fdt_find_max_phandle found 0x%x instead of 0x%x", max,
+ PHANDLE_2);
+
+ max = fdt_get_max_phandle(fdt);
+ if (max != PHANDLE_2)
+ FAIL("fdt_get_max_phandle returned 0x%x instead of 0x%x\n",
+ max, PHANDLE_2);
+
+ err = fdt_generate_phandle(fdt, &phandle);
+ if (err < 0)
+ FAIL("failed to generate phandle: %d", err);
+
+ check_phandle_unique(fdt, phandle);
+
+ PASS();
+}
diff --git a/dtc/tests/get_prop_offset.c b/dtc/tests/get_prop_offset.c
new file mode 100644
index 000000000..cff3c18ca
--- /dev/null
+++ b/dtc/tests/get_prop_offset.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_getprop_by_offset()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ bool found_prop_int = false;
+ bool found_prop_str = false;
+ int poffset;
+ void *fdt;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ fdt_for_each_property_offset(poffset, fdt, 0) {
+ if (check_get_prop_offset_cell(fdt, poffset, "prop-int",
+ TEST_VALUE_1))
+ found_prop_int = true;
+ if (check_get_prop_offset(fdt, poffset, "prop-str",
+ strlen(TEST_STRING_1) + 1,
+ TEST_STRING_1))
+ found_prop_str = true;
+ }
+ if (!found_prop_int)
+ FAIL("Property 'prop-int' not found");
+ if (!found_prop_str)
+ FAIL("Property 'prop-str' not found");
+
+ PASS();
+}
diff --git a/dtc/tests/getprop.c b/dtc/tests/getprop.c
new file mode 100644
index 000000000..cccc8e2d3
--- /dev/null
+++ b/dtc/tests/getprop.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_getprop()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_getprop_cell(fdt, 0, "prop-int", TEST_VALUE_1);
+ check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1, TEST_STRING_1);
+
+ PASS();
+}
diff --git a/dtc/tests/good-gpio.dts b/dtc/tests/good-gpio.dts
new file mode 100644
index 000000000..65d1c177a
--- /dev/null
+++ b/dtc/tests/good-gpio.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/ {
+ gpio: gpio-controller {
+ #gpio-cells = <3>;
+ };
+
+ node {
+ foo,nr-gpios = <1>;
+ foo-gpios = <&gpio 1 2 3>;
+ };
+};
diff --git a/dtc/tests/incbin.bin b/dtc/tests/incbin.bin
new file mode 100644
index 000000000..e6e3e48d4
--- /dev/null
+++ b/dtc/tests/incbin.bin
@@ -0,0 +1 @@
+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ \ No newline at end of file
diff --git a/dtc/tests/incbin.c b/dtc/tests/incbin.c
new file mode 100644
index 000000000..36ff66984
--- /dev/null
+++ b/dtc/tests/incbin.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for string escapes in dtc
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define CHUNKSIZE 1024
+
+static char *load_file(const char *name, int *len)
+{
+ FILE *f;
+ char *buf = NULL;
+ int bufsize = 0, n;
+
+ *len = 0;
+
+ f = fopen(name, "r");
+ if (!f)
+ FAIL("Couldn't open \"%s\": %s", name, strerror(errno));
+
+ while (!feof(f)) {
+ if (bufsize < (*len + CHUNKSIZE)) {
+ buf = xrealloc(buf, *len + CHUNKSIZE);
+ bufsize = *len + CHUNKSIZE;
+ }
+
+ n = fread(buf + *len, 1, CHUNKSIZE, f);
+ if (ferror(f))
+ FAIL("Error reading \"%s\": %s", name, strerror(errno));
+ *len += n;
+ }
+
+ return buf;
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ char *incbin;
+ int len;
+
+ test_init(argc, argv);
+
+ if (argc != 3)
+ CONFIG("Usage: %s <incbin file> <dtb file>", argv[0]);
+
+ incbin = load_file(argv[1], &len);
+ fdt = load_blob(argv[2]);
+
+ check_getprop(fdt, 0, "incbin", len, incbin);
+ check_getprop(fdt, 0, "incbin-partial", 17, incbin + 13);
+
+ PASS();
+}
diff --git a/dtc/tests/incbin.dts b/dtc/tests/incbin.dts
new file mode 100644
index 000000000..7c30e0ec4
--- /dev/null
+++ b/dtc/tests/incbin.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/ {
+ incbin = /incbin/("incbin.bin");
+ incbin-partial = /incbin/("incbin.bin", 13, 17);
+};
diff --git a/dtc/tests/include0.dts b/dtc/tests/include0.dts
new file mode 100644
index 000000000..355ed6a92
--- /dev/null
+++ b/dtc/tests/include0.dts
@@ -0,0 +1 @@
+/include/ "include1.dts"
diff --git a/dtc/tests/include1.dts b/dtc/tests/include1.dts
new file mode 100644
index 000000000..0b4b773e6
--- /dev/null
+++ b/dtc/tests/include1.dts
@@ -0,0 +1,32 @@
+/dts-v1/;
+
+/include/ "include2.dts"
+/memreserve/ /include/ "include3.dts";
+
+/ {
+ /include/ "include4.dts"
+ /include/ "include5.dts" = <0xdeadbeef>;
+ prop-int64 /include/ "include5a.dts";
+ prop-str = /include/ "include6.dts";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /include/ "include7.dts"
+
+ subnode@2 {
+ reg = <2>;
+ linux,phandle = <0x2000>;
+ prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /include/ "include8.dts"
+ phandle = <0x2001>;
+ compatible = "subsubnode2", "subsubnode";
+ prop-int = <0726746425>;
+ };
+
+ ss2 {
+ };
+ };
+};
diff --git a/dtc/tests/include2.dts b/dtc/tests/include2.dts
new file mode 100644
index 000000000..7e189dd77
--- /dev/null
+++ b/dtc/tests/include2.dts
@@ -0,0 +1 @@
+/memreserve/ 0xdeadbeef00000000 0x100000;
diff --git a/dtc/tests/include3.dts b/dtc/tests/include3.dts
new file mode 100644
index 000000000..ee9d277aa
--- /dev/null
+++ b/dtc/tests/include3.dts
@@ -0,0 +1 @@
+123456789 010000
diff --git a/dtc/tests/include4.dts b/dtc/tests/include4.dts
new file mode 100644
index 000000000..b2ddbe5a0
--- /dev/null
+++ b/dtc/tests/include4.dts
@@ -0,0 +1 @@
+ compatible = "test_tree1";
diff --git a/dtc/tests/include5.dts b/dtc/tests/include5.dts
new file mode 100644
index 000000000..9a35dc54e
--- /dev/null
+++ b/dtc/tests/include5.dts
@@ -0,0 +1 @@
+prop-int
diff --git a/dtc/tests/include5a.dts b/dtc/tests/include5a.dts
new file mode 100644
index 000000000..39ddba4fb
--- /dev/null
+++ b/dtc/tests/include5a.dts
@@ -0,0 +1 @@
+= /bits/ 64 <0xdeadbeef01abcdef> \ No newline at end of file
diff --git a/dtc/tests/include6.dts b/dtc/tests/include6.dts
new file mode 100644
index 000000000..cd4bc1ab6
--- /dev/null
+++ b/dtc/tests/include6.dts
@@ -0,0 +1 @@
+"hello world"
diff --git a/dtc/tests/include7.dts b/dtc/tests/include7.dts
new file mode 100644
index 000000000..ab2c948f0
--- /dev/null
+++ b/dtc/tests/include7.dts
@@ -0,0 +1,14 @@
+ subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+ prop-int = [deadbeef];
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ placeholder = "this is a placeholder string", "string2";
+ prop-int = <0xdeadbeef>;
+ };
+
+ ss1 {
+ };
+ };
diff --git a/dtc/tests/include8.dts b/dtc/tests/include8.dts
new file mode 100644
index 000000000..7532ef51d
--- /dev/null
+++ b/dtc/tests/include8.dts
@@ -0,0 +1,2 @@
+subsubnode@0 {
+ reg = <0>;
diff --git a/dtc/tests/integer-expressions.c b/dtc/tests/integer-expressions.c
new file mode 100644
index 000000000..6f33d818e
--- /dev/null
+++ b/dtc/tests/integer-expressions.c
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * Testcase for dtc expression support
+ *
+ * Copyright (C) 2008 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static struct test_expr {
+ const char *expr;
+ uint32_t result;
+} expr_table[] = {
+#define TE(expr) { #expr, (expr) }
+ TE(0xdeadbeef),
+ TE(-0x21524111),
+ TE(1+1),
+ TE(2*3),
+ TE(4/2),
+ TE(10/3),
+ TE(19%4),
+ TE(1 << 13),
+ TE(0x1000 >> 4),
+ TE(3*2+1), TE(3*(2+1)),
+ TE(1+2*3), TE((1+2)*3),
+ TE(1 < 2), TE(2 < 1), TE(1 < 1),
+ TE(1 <= 2), TE(2 <= 1), TE(1 <= 1),
+ TE(1 > 2), TE(2 > 1), TE(1 > 1),
+ TE(1 >= 2), TE(2 >= 1), TE(1 >= 1),
+ TE(1 == 1), TE(1 == 2),
+ TE(1 != 1), TE(1 != 2),
+ TE(0xabcdabcd & 0xffff0000),
+ TE(0xdead4110 ^ 0xf0f0f0f0),
+ TE(0xabcd0000 | 0x0000abcd),
+ TE(~0x21524110),
+ TE(~~0xdeadbeef),
+ TE(0 && 0), TE(17 && 0), TE(0 && 17), TE(17 && 17),
+ TE(0 || 0), TE(17 || 0), TE(0 || 17), TE(17 || 17),
+ TE(!0), TE(!1), TE(!17), TE(!!0), TE(!!17),
+ TE(0 ? 17 : 39), TE(1 ? 17 : 39), TE(17 ? 0xdeadbeef : 0xabcd1234),
+ TE(11 * 257 * 1321517ULL),
+ TE(123456790 - 4/2 + 17%4),
+};
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ const fdt32_t *res;
+ int reslen;
+ int i;
+
+ test_init(argc, argv);
+
+ if ((argc == 3) && (strcmp(argv[1], "-g") == 0)) {
+ FILE *f = fopen(argv[2], "w");
+
+ if (!f)
+ FAIL("Couldn't open \"%s\" for output: %s\n",
+ argv[2], strerror(errno));
+
+ fprintf(f, "/dts-v1/;\n");
+ fprintf(f, "/ {\n");
+ fprintf(f, "\texpressions = <\n");
+ for (i = 0; i < ARRAY_SIZE(expr_table); i++)
+ fprintf(f, "\t\t(%s)\n", expr_table[i].expr);
+ fprintf(f, "\t>;\n");
+ fprintf(f, "};\n");
+ fclose(f);
+ } else {
+ fdt = load_blob_arg(argc, argv);
+
+ res = fdt_getprop(fdt, 0, "expressions", &reslen);
+
+ if (!res)
+ FAIL("Error retrieving expression results: %s\n",
+ fdt_strerror(reslen));
+
+ if (reslen != (ARRAY_SIZE(expr_table) * sizeof(uint32_t)))
+ FAIL("Unexpected length of results %d instead of %zd\n",
+ reslen, ARRAY_SIZE(expr_table) * sizeof(uint32_t));
+
+ for (i = 0; i < ARRAY_SIZE(expr_table); i++)
+ if (fdt32_to_cpu(res[i]) != expr_table[i].result)
+ FAIL("Incorrect result for expression \"%s\","
+ " 0x%x instead of 0x%x\n",
+ expr_table[i].expr, fdt32_to_cpu(res[i]),
+ expr_table[i].result);
+ }
+
+ PASS();
+}
diff --git a/dtc/tests/label01.dts b/dtc/tests/label01.dts
new file mode 100644
index 000000000..a8958034f
--- /dev/null
+++ b/dtc/tests/label01.dts
@@ -0,0 +1,63 @@
+/dts-v1/;
+
+/memreserve/ 0x1000000000000000 0x0000000002000000;
+memrsv2: /memreserve/ 0x2000000000000000 0x0100000000000000;
+/memreserve/ 0x0000000000000000 0x0000000000000014;
+
+/ {
+ model = "MyBoardName";
+ compatible = "MyBoardName", "MyBoardFamilyName";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ linux,phandle = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ PowerPC,970@0 {
+ name = "PowerPC,970";
+ device_type = "cpu";
+ reg = <0x00000000>;
+ clock-frequency = <1600000000>;
+ timebase-frequency = <33333333>;
+ linux,boot-cpu;
+ i-cache-size = <65536>;
+ d-cache-size = <32768>;
+ };
+
+ PowerPC,970@1 {
+ name = "PowerPC,970";
+ device_type = "cpu";
+ reg = <0x00000001>;
+ clock-frequency = <1600000000>;
+ timebase-frequency = <33333333>;
+ i-cache-size = <65536>;
+ d-cache-size = <32768>;
+ };
+
+ };
+
+ node: randomnode {
+ prop: string = str: "foo", str_mid: "stuffstuff\t\t\t\n\n\n" str_end: ;
+ blob = [byte: 0a 0b 0c 0d byte_mid: de ea ad be ef byte_end: ];
+ ref = < cell: &{/memory@0} 0x0 cell_mid: 0xffffffff cell_end: >;
+ mixed = "abc", pre: [1234] post: , gap: < aligned: 0xa 0xb 0xc>;
+ tricky1 = [61 lt1: 62 63 00];
+ subnode: child {
+ };
+ /* subnode_end: is auto-generated by node emit */
+ };
+ /* node_end: is auto-generated by node emit */
+
+ memory@0 {
+ device_type = "memory";
+ memreg: reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
+ };
+
+ chosen {
+ bootargs = "root=/dev/sda2";
+ linux,platform = <0x600>;
+ };
+
+};
+
diff --git a/dtc/tests/label_repeated.dts b/dtc/tests/label_repeated.dts
new file mode 100644
index 000000000..34225d331
--- /dev/null
+++ b/dtc/tests/label_repeated.dts
@@ -0,0 +1,15 @@
+/dts-v1/;
+
+/ {
+ l0: prop = "foo";
+
+ l1: node {
+ };
+};
+
+/ {
+ l0: prop = "foo";
+
+ l1: node {
+ };
+};
diff --git a/dtc/tests/line_directives.dts b/dtc/tests/line_directives.dts
new file mode 100644
index 000000000..67b5e084f
--- /dev/null
+++ b/dtc/tests/line_directives.dts
@@ -0,0 +1,26 @@
+/dts-v1/;
+
+/* common format */
+#line 3 "foo.dts"
+/* newer gcc format */
+# 9 "baz.dts" 1
+/* flags are optional */
+# 6 "bar.dts"
+
+/ {
+/*
+ * Make sure optional flags don't consume integer data on next line. The issue
+ * was that the {WS} in the trailing ({WS}+[0-9]+)? could cross the * line-
+ * break, and consume the leading "0" of the hex constant, leaving "x12345678"
+ * to be parsed as a number, which is invalid syntax.
+ */
+ prop1 = <
+# 10 "qux.dts"
+ 0x12345678
+ >;
+/*
+ * Check processing of escapes in filenames
+ */
+# 100 "\".dts"
+# 200 "\\.dts"
+};
diff --git a/dtc/tests/lorem.txt b/dtc/tests/lorem.txt
new file mode 100644
index 000000000..acff69837
--- /dev/null
+++ b/dtc/tests/lorem.txt
@@ -0,0 +1,35 @@
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris eros
+arcu, egestas non pellentesque non, euismod eu nibh. Proin arcu metus,
+dapibus vitae sodales rhoncus, suscipit vel nulla. Etiam lorem est,
+aliquam ut fringilla sit amet, condimentum et quam. Duis eu arcu odio,
+at pulvinar nisi. Morbi condimentum eros ut turpis rhoncus
+pharetra. Pellentesque habitant morbi tristique senectus et netus et
+malesuada fames ac turpis egestas. Nam et nulla enim. Etiam fringilla
+eleifend neque, at posuere ante lacinia a. Duis orci tortor, dictum ac
+gravida ac, euismod eu leo. Sed eget dolor tortor. Pellentesque
+venenatis, lectus eu vulputate porta, libero ipsum convallis mi, sit
+amet vehicula arcu elit sit amet odio.
+
+Fusce iaculis massa metus, id sagittis diam. Praesent molestie ante
+vel odio tincidunt auctor. Cum sociis natoque penatibus et magnis dis
+parturient montes, nascetur ridiculus mus. Duis rutrum vehicula nisl
+eget condimentum. In in justo nisl. Nullam id arcu at nisl eleifend
+pretium. Nulla interdum ligula id elit mollis dictum a sit amet
+quam. Nullam iaculis laoreet ipsum at tempus. Vestibulum in cursus
+dui. Curabitur porta lectus eget urna bibendum congue eget elementum
+nisi. Proin sit amet lectus ut neque iaculis consectetur eu sit amet
+nibh. Maecenas rhoncus dolor ac nunc gravida blandit. Fusce sem felis,
+aliquam a porttitor a, porta quis odio.
+
+Nunc purus lorem, sollicitudin non ultricies id, porta vitae
+enim. Nulla tristique gravida leo ut suscipit. Phasellus vitae turpis
+libero. Proin ac purus dolor, in suscipit magna. Sed et enim
+arcu. Morbi semper aliquet suscipit. Aenean laoreet condimentum massa,
+eu pharetra magna fermentum ut. Morbi euismod convallis tortor, eget
+fringilla lacus sagittis non. Nullam bibendum posuere feugiat.
+
+In at pulvinar massa. Mauris nunc lectus, mollis et malesuada
+pharetra, cursus sed lacus. Integer dolor urna, interdum a mollis at,
+vestibulum non nisl. Sed in urna tortor. Mauris arcu felis, volutpat
+quis euismod vel, congue sit amet ipsum. Morbi in aliquet purus. Duis
+cras amet.
diff --git a/dtc/tests/mangle-layout.c b/dtc/tests/mangle-layout.c
new file mode 100644
index 000000000..59b16049a
--- /dev/null
+++ b/dtc/tests/mangle-layout.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase/tool for rearranging blocks of a dtb
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+struct bufstate {
+ char *buf;
+ int size;
+};
+
+static void expand_buf(struct bufstate *buf, int newsize)
+{
+ buf->buf = realloc(buf->buf, newsize);
+ if (!buf->buf)
+ CONFIG("Allocation failure");
+ buf->size = newsize;
+}
+
+static void new_header(struct bufstate *buf, int version, const void *fdt)
+{
+ int hdrsize = fdt_header_size_(version);
+
+ if ((version != 16) && (version != 17))
+ CONFIG("Bad version %d", version);
+
+ expand_buf(buf, hdrsize);
+ memset(buf->buf, 0, hdrsize);
+
+ fdt_set_magic(buf->buf, FDT_MAGIC);
+ fdt_set_version(buf->buf, version);
+ fdt_set_last_comp_version(buf->buf, 16);
+ fdt_set_boot_cpuid_phys(buf->buf, fdt_boot_cpuid_phys(fdt));
+}
+
+static void add_block(struct bufstate *buf, int version, char block, const void *fdt)
+{
+ int align, size, oldsize;
+ const void *src;
+ int offset;
+
+ switch (block) {
+ case 'm':
+ /* Memory reserve map */
+ align = 8;
+ src = (const char *)fdt + fdt_off_mem_rsvmap(fdt);
+ size = (fdt_num_mem_rsv(fdt) + 1)
+ * sizeof(struct fdt_reserve_entry);
+ break;
+
+ case 't':
+ /* Structure block */
+ align = 4;
+ src = (const char *)fdt + fdt_off_dt_struct(fdt);
+ size = fdt_size_dt_struct(fdt);
+ break;
+
+ case 's':
+ /* Strings block */
+ align = 1;
+ src = (const char *)fdt + fdt_off_dt_strings(fdt);
+ size = fdt_size_dt_strings(fdt);
+ break;
+ default:
+ CONFIG("Bad block '%c'", block);
+ }
+
+ oldsize = buf->size;
+ offset = ALIGN(oldsize, align);
+ expand_buf(buf, offset+size);
+ memset(buf->buf + oldsize, 0, offset - oldsize);
+
+ memcpy(buf->buf + offset, src, size);
+
+ switch (block) {
+ case 'm':
+ fdt_set_off_mem_rsvmap(buf->buf, offset);
+ break;
+
+ case 't':
+ fdt_set_off_dt_struct(buf->buf, offset);
+ if (version >= 17)
+ fdt_set_size_dt_struct(buf->buf, size);
+ break;
+
+ case 's':
+ fdt_set_off_dt_strings(buf->buf, offset);
+ fdt_set_size_dt_strings(buf->buf, size);
+ break;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int version;
+ const char *blockorder;
+ struct bufstate buf = {NULL, 0};
+ int err;
+ const char *inname;
+ char outname[PATH_MAX];
+
+ test_init(argc, argv);
+ if (argc != 4)
+ CONFIG("Usage: %s <dtb file> <version> <block order>", argv[0]);
+
+ inname = argv[1];
+ fdt = load_blob(argv[1]);
+ version = atoi(argv[2]);
+ blockorder = argv[3];
+ sprintf(outname, "v%d.%s.%s", version, blockorder, inname);
+
+ if ((version != 16) && (version != 17))
+ CONFIG("Version must be 16 or 17");
+
+ if (fdt_version(fdt) < 17)
+ CONFIG("Input tree must be v17");
+
+ new_header(&buf, version, fdt);
+
+ while (*blockorder) {
+ add_block(&buf, version, *blockorder, fdt);
+ blockorder++;
+ }
+
+ fdt_set_totalsize(buf.buf, buf.size);
+
+ err = fdt_check_header(buf.buf);
+ if (err)
+ FAIL("Output tree fails check: %s", fdt_strerror(err));
+
+ save_blob(outname, buf.buf);
+
+ PASS();
+}
diff --git a/dtc/tests/meson.build b/dtc/tests/meson.build
new file mode 100644
index 000000000..fa068241b
--- /dev/null
+++ b/dtc/tests/meson.build
@@ -0,0 +1,131 @@
+trees = static_library('trees', files('trees.S'), c_args: '-D__ASSEMBLY__',
+ include_directories: libfdt_inc)
+
+dumptrees = executable('dumptrees', files('dumptrees.c'),
+ link_with: trees, dependencies: libfdt_dep)
+
+dumptrees_dtb = custom_target(
+ 'dumptrees',
+ command: [dumptrees, meson.current_build_dir()],
+ output: [
+ 'test_tree1.dtb',
+ 'bad_node_char.dtb',
+ 'bad_node_format.dtb',
+ 'bad_prop_char.dtb',
+ 'ovf_size_strings.dtb',
+ 'truncated_property.dtb',
+ 'truncated_string.dtb',
+ 'truncated_memrsv.dtb',
+ ]
+)
+
+testutil_dep = declare_dependency(sources: ['testutils.c'], link_with: trees)
+
+tests = [
+ 'add_subnode_with_nops',
+ 'addr_size_cells',
+ 'addr_size_cells2',
+ 'appendprop1',
+ 'appendprop2',
+ 'appendprop_addrrange',
+ 'boot-cpuid',
+ 'char_literal',
+ 'check_full',
+ 'check_header',
+ 'check_path',
+ 'del_node',
+ 'del_property',
+ 'dtb_reverse',
+ 'dtbs_equal_ordered',
+ 'dtbs_equal_unordered',
+ 'extra-terminating-null',
+ 'find_property',
+ 'fs_tree1',
+ 'get_alias',
+ 'get_mem_rsv',
+ 'get_name',
+ 'get_path',
+ 'get_phandle',
+ 'get_prop_offset',
+ 'getprop',
+ 'incbin',
+ 'integer-expressions',
+ 'mangle-layout',
+ 'move_and_save',
+ 'node_check_compatible',
+ 'node_offset_by_compatible',
+ 'node_offset_by_phandle',
+ 'node_offset_by_prop_value',
+ 'nop_node',
+ 'nop_property',
+ 'nopulate',
+ 'notfound',
+ 'open_pack',
+ 'overlay',
+ 'overlay_bad_fixup',
+ 'parent_offset',
+ 'path-references',
+ 'path_offset',
+ 'path_offset_aliases',
+ 'phandle_format',
+ 'property_iterate',
+ 'propname_escapes',
+ 'references',
+ 'root_node',
+ 'rw_oom',
+ 'rw_tree1',
+ 'set_name',
+ 'setprop',
+ 'setprop_inplace',
+ 'sized_cells',
+ 'string_escapes',
+ 'stringlist',
+ 'subnode_iterate',
+ 'subnode_offset',
+ 'supernode_atdepth_offset',
+ 'sw_states',
+ 'sw_tree1',
+ 'utilfdt_test',
+]
+
+tests += [
+ 'truncated_memrsv',
+ 'truncated_property',
+ 'truncated_string',
+]
+
+dl = cc.find_library('dl', required: false)
+if dl.found()
+ tests += [
+ 'asm_tree_dump',
+ 'value-labels',
+ ]
+endif
+
+foreach t: tests
+ executable(t, files(t + '.c'), dependencies: [testutil_dep, util_dep, libfdt_dep, dl])
+endforeach
+
+run_tests = find_program('run_tests.sh')
+
+env = []
+if not py.found()
+ env += 'NO_PYTHON=1'
+else
+ env += [
+ 'PYTHON=' + py.path(),
+ 'PYTHONPATH=' + meson.source_root() / 'pylibfdt',
+ ]
+endif
+if not yaml.found()
+ env += 'NO_YAML=1'
+endif
+
+test(
+ 'run-test',
+ run_tests,
+ workdir: meson.current_build_dir(),
+ depends: dumptrees_dtb,
+ env: env,
+ timeout: 1800, # mostly for valgrind
+)
diff --git a/dtc/tests/minusone-phandle.dts b/dtc/tests/minusone-phandle.dts
new file mode 100644
index 000000000..21d99867a
--- /dev/null
+++ b/dtc/tests/minusone-phandle.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+ node {
+ linux,phandle = <0xffffffff>;
+ };
+};
diff --git a/dtc/tests/move_and_save.c b/dtc/tests/move_and_save.c
new file mode 100644
index 000000000..a89f8dedd
--- /dev/null
+++ b/dtc/tests/move_and_save.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Basic testcase for read-only access
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt, *fdt1, *fdt2, *fdt3;
+ char *buf;
+ int shuntsize;
+ int bufsize;
+ int err;
+ const char *inname;
+ char outname[PATH_MAX];
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+ inname = argv[1];
+
+ shuntsize = ALIGN(fdt_totalsize(fdt) / 2, sizeof(uint64_t));
+ bufsize = fdt_totalsize(fdt) + shuntsize;
+ buf = xmalloc(bufsize);
+
+ fdt1 = buf;
+ err = fdt_move(fdt, fdt1, bufsize);
+ if (err)
+ FAIL("Failed to move tree into new buffer: %s",
+ fdt_strerror(err));
+ sprintf(outname, "moved.%s", inname);
+ save_blob(outname, fdt1);
+
+ fdt2 = buf + shuntsize;
+ err = fdt_move(fdt1, fdt2, bufsize-shuntsize);
+ if (err)
+ FAIL("Failed to shunt tree %d bytes: %s",
+ shuntsize, fdt_strerror(err));
+ sprintf(outname, "shunted.%s", inname);
+ save_blob(outname, fdt2);
+
+ fdt3 = buf;
+ err = fdt_move(fdt2, fdt3, bufsize);
+ if (err)
+ FAIL("Failed to deshunt tree %d bytes: %s",
+ shuntsize, fdt_strerror(err));
+ sprintf(outname, "deshunted.%s", inname);
+ save_blob(outname, fdt3);
+
+ PASS();
+}
diff --git a/dtc/tests/multilabel.dts b/dtc/tests/multilabel.dts
new file mode 100644
index 000000000..d80ebe1fb
--- /dev/null
+++ b/dtc/tests/multilabel.dts
@@ -0,0 +1,49 @@
+/dts-v1/;
+
+m1: mq: /memreserve/ 0 0x1000;
+
+/ {
+ p0: pw: prop = "foo";
+
+ rref = <&{/}>;
+
+ /* Explicit phandles */
+ n1: nx: node1 {
+ linux,phandle = <0x2000>;
+ ref = <&{/node2}>; /* reference precedes target */
+ p1: px: lref = <&ny>;
+ };
+ ny: n2: node2 {
+ p2: py: phandle = <0x1>;
+ ref = <&{/node1}>; /* reference after target */
+ lref = <&nx>;
+ };
+
+ /* Implicit phandles */
+ n3: node3 {
+ p3: ref = <&{/node4}>;
+ lref = <&n4>;
+ };
+ n4: node4 {
+ p4: prop;
+ };
+
+ /* Explicit phandle with implicit value */
+ /* This self-reference is the standard way to tag a node as requiring
+ * a phandle (perhaps for reference by nodes that will be dynamically
+ * added) without explicitly allocating it a phandle.
+ * The self-reference requires some special internal handling, though
+ * so check it actually works */
+ n5: nz: node5 {
+ linux,phandle = <&n5>;
+ phandle = <&nz>;
+ n1 = &n1;
+ n2 = &n2;
+ n3 = &n3;
+ };
+
+ node6 {
+ linux,phandle = <0xfffffffe>;
+ phandle = <0xfffffffe>;
+ };
+};
diff --git a/dtc/tests/multilabel_merge.dts b/dtc/tests/multilabel_merge.dts
new file mode 100644
index 000000000..a27d856f8
--- /dev/null
+++ b/dtc/tests/multilabel_merge.dts
@@ -0,0 +1,75 @@
+/dts-v1/;
+
+m1: mq: /memreserve/ 0 0x1000;
+
+/ {
+ p0: pw: prop = "foo";
+
+ /* Explicit phandles */
+ n1: node1 {
+ linux,phandle = <0x2000>;
+ ref = <&{/node2}>; /* reference precedes target */
+ p1: lref;
+ };
+ node2 {
+ phandle = <0x1>;
+ ref = <&{/node1}>; /* reference after target */
+ lref = <&nx>;
+ };
+
+ /* Implicit phandles */
+ n3: node3 {
+ p3: ref = <&{/node4}>;
+ lref = <&n4>;
+ };
+ n4: node4 {
+ p4: prop = "foo";
+ };
+
+ /* Explicit phandle with implicit value */
+ /* This self-reference is the standard way to tag a node as requiring
+ * a phandle (perhaps for reference by nodes that will be dynamically
+ * added) without explicitly allocating it a phandle.
+ * The self-reference requires some special internal handling, though
+ * so check it actually works */
+ n5: nz: node5 {
+ linux,phandle = <&n5>;
+ phandle = <&nz>;
+ n1 = &n1;
+ n2 = &n2;
+ n3 = &n3;
+ };
+
+ node6 {
+ linux,phandle = <0xfffffffe>;
+ phandle = <0xfffffffe>;
+ };
+};
+
+/ {
+ /* Append labels (also changes property content) */
+ nx: node1 {
+ px: lref = <&ny>;
+ };
+
+ /* Add multiple labels */
+ ny: n2: node2 {
+ /* Add a label to a property */
+ p2: py: phandle = <0x1>;
+ };
+
+ /* Reassigning the same label should be a no-op */
+ n3: node3 {
+ p3: ref = <&{/node4}>;
+ };
+
+ /* Redefining a node/property should not remove labels */
+ node4 {
+ prop;
+ };
+
+};
+
+/ {
+ rref = <&{/}>;
+};
diff --git a/dtc/tests/node_check_compatible.c b/dtc/tests/node_check_compatible.c
new file mode 100644
index 000000000..81efe6211
--- /dev/null
+++ b/dtc/tests/node_check_compatible.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_node_check_compatible()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check_compatible(const void *fdt, const char *path,
+ const char *compat)
+{
+ int offset, err;
+
+ offset = fdt_path_offset(fdt, path);
+ if (offset < 0)
+ FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(offset));
+
+ err = fdt_node_check_compatible(fdt, offset, compat);
+ if (err < 0)
+ FAIL("fdt_node_check_compatible(%s): %s", path,
+ fdt_strerror(err));
+ if (err != 0)
+ FAIL("%s is not compatible with \"%s\"", path, compat);
+}
+
+static void check_not_compatible(const void *fdt, const char *path,
+ const char *compat)
+{
+ int offset, err;
+
+ offset = fdt_path_offset(fdt, path);
+ if (offset < 0)
+ FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(offset));
+
+ err = fdt_node_check_compatible(fdt, offset, compat);
+ if (err < 0)
+ FAIL("fdt_node_check_compatible(%s): %s", path,
+ fdt_strerror(err));
+ if (err == 0)
+ FAIL("%s is incorrectly compatible with \"%s\"", path, compat);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_compatible(fdt, "/", "test_tree1");
+ check_compatible(fdt, "/subnode@1/subsubnode", "subsubnode1");
+ check_compatible(fdt, "/subnode@1/subsubnode", "subsubnode");
+ check_not_compatible(fdt, "/subnode@1/subsubnode", "subsubnode2");
+ check_compatible(fdt, "/subnode@2/subsubnode", "subsubnode2");
+ check_compatible(fdt, "/subnode@2/subsubnode", "subsubnode");
+ check_not_compatible(fdt, "/subnode@2/subsubnode", "subsubnode1");
+
+ PASS();
+}
diff --git a/dtc/tests/node_offset_by_compatible.c b/dtc/tests/node_offset_by_compatible.c
new file mode 100644
index 000000000..a9e678357
--- /dev/null
+++ b/dtc/tests/node_offset_by_compatible.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_node_offset_by_compatible()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdarg.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check_search(void *fdt, const char *compat, ...)
+{
+ va_list ap;
+ int offset = -1, target;
+
+ va_start(ap, compat);
+ do {
+ target = va_arg(ap, int);
+ verbose_printf("Searching (target = %d): %d ->",
+ target, offset);
+ offset = fdt_node_offset_by_compatible(fdt, offset, compat);
+ verbose_printf("%d\n", offset);
+
+ if (offset != target)
+ FAIL("fdt_node_offset_by_compatible(%s) returns %d "
+ "instead of %d", compat, offset, target);
+ } while (target >= 0);
+
+ va_end(ap);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int subnode1_offset, subnode2_offset;
+ int subsubnode1_offset, subsubnode2_offset;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ subnode1_offset = fdt_path_offset(fdt, "/subnode@1");
+ subnode2_offset = fdt_path_offset(fdt, "/subnode@2");
+ subsubnode1_offset = fdt_path_offset(fdt, "/subnode@1/subsubnode");
+ subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode@0");
+
+ if ((subnode1_offset < 0) || (subnode2_offset < 0)
+ || (subsubnode1_offset < 0) || (subsubnode2_offset < 0))
+ FAIL("Can't find required nodes");
+
+ check_search(fdt, "test_tree1", 0, -FDT_ERR_NOTFOUND);
+ check_search(fdt, "subnode1", subnode1_offset, -FDT_ERR_NOTFOUND);
+ check_search(fdt, "subsubnode1", subsubnode1_offset, -FDT_ERR_NOTFOUND);
+ check_search(fdt, "subsubnode2", subsubnode2_offset, -FDT_ERR_NOTFOUND);
+ /* Eek.. HACK to make this work whatever the order in the
+ * example tree */
+ if (subsubnode1_offset < subsubnode2_offset)
+ check_search(fdt, "subsubnode", subsubnode1_offset,
+ subsubnode2_offset, -FDT_ERR_NOTFOUND);
+ else
+ check_search(fdt, "subsubnode", subsubnode2_offset,
+ subsubnode1_offset, -FDT_ERR_NOTFOUND);
+ check_search(fdt, "nothing-like-this", -FDT_ERR_NOTFOUND);
+
+ PASS();
+}
diff --git a/dtc/tests/node_offset_by_phandle.c b/dtc/tests/node_offset_by_phandle.c
new file mode 100644
index 000000000..60af78a79
--- /dev/null
+++ b/dtc/tests/node_offset_by_phandle.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_node_offset_by_phandle()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdarg.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static 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();
+}
diff --git a/dtc/tests/node_offset_by_prop_value.c b/dtc/tests/node_offset_by_prop_value.c
new file mode 100644
index 000000000..48ab1d93a
--- /dev/null
+++ b/dtc/tests/node_offset_by_prop_value.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_path_offset()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdarg.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void vcheck_search(void *fdt, const char *propname, const void *propval,
+ int proplen, va_list ap)
+{
+ int offset = -1, target;
+
+ do {
+ target = va_arg(ap, int);
+ verbose_printf("Searching (target = %d): %d ->",
+ target, offset);
+ offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
+ propval, proplen);
+ verbose_printf("%d\n", offset);
+
+ if (offset != target)
+ FAIL("fdt_node_offset_by_prop_value() returns %d "
+ "instead of %d", offset, target);
+ } while (target >= 0);
+}
+
+static void check_search(void *fdt, const char *propname, const void *propval,
+ int proplen, ...)
+{
+ va_list ap;
+
+ va_start(ap, proplen);
+ vcheck_search(fdt, propname, propval, proplen, ap);
+ va_end(ap);
+}
+
+static void check_search_str(void *fdt, const char *propname,
+ const char *propval, ...)
+{
+ va_list ap;
+
+ va_start(ap, propval);
+ vcheck_search(fdt, propname, propval, strlen(propval)+1, ap);
+ va_end(ap);
+}
+
+#define check_search_cell(fdt, propname, propval, ...) \
+ { \
+ fdt32_t val = cpu_to_fdt32(propval); \
+ check_search((fdt), (propname), &val, sizeof(val), \
+ ##__VA_ARGS__); \
+ }
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int subnode1_offset, subnode2_offset;
+ int subsubnode1_offset, subsubnode2_offset;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ subnode1_offset = fdt_path_offset(fdt, "/subnode@1");
+ subnode2_offset = fdt_path_offset(fdt, "/subnode@2");
+ subsubnode1_offset = fdt_path_offset(fdt, "/subnode@1/subsubnode");
+ subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode@0");
+
+ if ((subnode1_offset < 0) || (subnode2_offset < 0)
+ || (subsubnode1_offset < 0) || (subsubnode2_offset < 0))
+ FAIL("Can't find required nodes");
+
+ check_search_cell(fdt, "prop-int", TEST_VALUE_1, 0, subnode1_offset,
+ subsubnode1_offset, -FDT_ERR_NOTFOUND);
+
+ check_search_cell(fdt, "prop-int", TEST_VALUE_2, subnode2_offset,
+ subsubnode2_offset, -FDT_ERR_NOTFOUND);
+
+ check_search_str(fdt, "prop-str", TEST_STRING_1, 0, -FDT_ERR_NOTFOUND);
+
+ check_search_str(fdt, "prop-str", "no such string", -FDT_ERR_NOTFOUND);
+
+ check_search_cell(fdt, "prop-int", TEST_VALUE_1+1, -FDT_ERR_NOTFOUND);
+
+ check_search(fdt, "no-such-prop", NULL, 0, -FDT_ERR_NOTFOUND);
+
+ PASS();
+}
diff --git a/dtc/tests/nonexist-label-ref.dts b/dtc/tests/nonexist-label-ref.dts
new file mode 100644
index 000000000..25927a109
--- /dev/null
+++ b/dtc/tests/nonexist-label-ref.dts
@@ -0,0 +1,8 @@
+/dts-v1/;
+
+/ {
+ ref = <&label>;
+ badref = <&nosuchlabel>;
+ label: node {
+ };
+};
diff --git a/dtc/tests/nonexist-node-ref.dts b/dtc/tests/nonexist-node-ref.dts
new file mode 100644
index 000000000..efd41404b
--- /dev/null
+++ b/dtc/tests/nonexist-node-ref.dts
@@ -0,0 +1,8 @@
+/dts-v1/;
+
+/ {
+ ref = < &{/node} >;
+ badref = < &{/nosuchnode} >;
+ label: node {
+ };
+};
diff --git a/dtc/tests/nonexist-node-ref2.dts b/dtc/tests/nonexist-node-ref2.dts
new file mode 100644
index 000000000..44b4ebeba
--- /dev/null
+++ b/dtc/tests/nonexist-node-ref2.dts
@@ -0,0 +1,10 @@
+/dts-v1/;
+
+/ {
+ label: node {
+ };
+};
+
+/* Try to redefine a node using a non-existent label */
+&nosuchnode {
+};
diff --git a/dtc/tests/nop_node.c b/dtc/tests/nop_node.c
new file mode 100644
index 000000000..ee972d2a3
--- /dev/null
+++ b/dtc/tests/nop_node.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_nop_node()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int subnode1_offset, subnode2_offset, subsubnode2_offset;
+ int err;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ subnode1_offset = fdt_path_offset(fdt, "/subnode@1");
+ if (subnode1_offset < 0)
+ FAIL("Couldn't find \"/subnode1\": %s",
+ fdt_strerror(subnode1_offset));
+ check_getprop_cell(fdt, subnode1_offset, "prop-int", TEST_VALUE_1);
+
+ subnode2_offset = fdt_path_offset(fdt, "/subnode@2");
+ if (subnode2_offset < 0)
+ FAIL("Couldn't find \"/subnode2\": %s",
+ fdt_strerror(subnode2_offset));
+ check_getprop_cell(fdt, subnode2_offset, "prop-int", TEST_VALUE_2);
+
+ subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode");
+ if (subsubnode2_offset < 0)
+ FAIL("Couldn't find \"/subnode@2/subsubnode\": %s",
+ fdt_strerror(subsubnode2_offset));
+ check_getprop_cell(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2);
+
+ err = fdt_nop_node(fdt, subnode1_offset);
+ if (err)
+ FAIL("fdt_nop_node(subnode1): %s", fdt_strerror(err));
+
+ subnode1_offset = fdt_path_offset(fdt, "/subnode@1");
+ if (subnode1_offset != -FDT_ERR_NOTFOUND)
+ FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"",
+ fdt_strerror(subnode1_offset),
+ fdt_strerror(-FDT_ERR_NOTFOUND));
+
+ subnode2_offset = fdt_path_offset(fdt, "/subnode@2");
+ if (subnode2_offset < 0)
+ FAIL("Couldn't find \"/subnode2\": %s",
+ fdt_strerror(subnode2_offset));
+ check_getprop_cell(fdt, subnode2_offset, "prop-int", TEST_VALUE_2);
+
+ subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode");
+ if (subsubnode2_offset < 0)
+ FAIL("Couldn't find \"/subnode@2/subsubnode\": %s",
+ fdt_strerror(subsubnode2_offset));
+ check_getprop_cell(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2);
+
+ err = fdt_nop_node(fdt, subnode2_offset);
+ if (err)
+ FAIL("fdt_nop_node(subnode2): %s", fdt_strerror(err));
+
+ subnode1_offset = fdt_path_offset(fdt, "/subnode@1");
+ if (subnode1_offset != -FDT_ERR_NOTFOUND)
+ FAIL("fdt_path_offset(subnode1) returned \"%s\" instead of \"%s\"",
+ fdt_strerror(subnode1_offset),
+ fdt_strerror(-FDT_ERR_NOTFOUND));
+
+ subnode2_offset = fdt_path_offset(fdt, "/subnode@2");
+ if (subnode2_offset != -FDT_ERR_NOTFOUND)
+ FAIL("fdt_path_offset(subnode2) returned \"%s\" instead of \"%s\"",
+ fdt_strerror(subnode2_offset),
+ fdt_strerror(-FDT_ERR_NOTFOUND));
+
+ subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode");
+ if (subsubnode2_offset != -FDT_ERR_NOTFOUND)
+ FAIL("fdt_path_offset(subsubnode2) returned \"%s\" instead of \"%s\"",
+ fdt_strerror(subsubnode2_offset),
+ fdt_strerror(-FDT_ERR_NOTFOUND));
+
+ PASS();
+}
diff --git a/dtc/tests/nop_property.c b/dtc/tests/nop_property.c
new file mode 100644
index 000000000..65938289e
--- /dev/null
+++ b/dtc/tests/nop_property.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_nop_property()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ const uint32_t *intp;
+ const char *strp;
+ int err;
+ int lenerr;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ intp = check_getprop_cell(fdt, 0, "prop-int", TEST_VALUE_1);
+ verbose_printf("int value was 0x%08x\n", *intp);
+
+ err = fdt_nop_property(fdt, 0, "prop-int");
+ if (err)
+ FAIL("Failed to nop \"prop-int\": %s", fdt_strerror(err));
+
+ intp = fdt_getprop(fdt, 0, "prop-int", &lenerr);
+ if (intp)
+ FAIL("prop-int still present after nopping");
+ if (lenerr != -FDT_ERR_NOTFOUND)
+ FAIL("Unexpected error on second getprop: %s", fdt_strerror(err));
+
+ strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1,
+ TEST_STRING_1);
+ verbose_printf("string value was \"%s\"\n", strp);
+ err = fdt_nop_property(fdt, 0, "prop-str");
+ if (err)
+ FAIL("Failed to nop \"prop-str\": %s", fdt_strerror(err));
+
+ strp = fdt_getprop(fdt, 0, "prop-str", &lenerr);
+ if (strp)
+ FAIL("prop-str still present after nopping");
+ if (lenerr != -FDT_ERR_NOTFOUND)
+ FAIL("Unexpected error on second getprop: %s", fdt_strerror(err));
+
+ PASS();
+}
diff --git a/dtc/tests/nopulate.c b/dtc/tests/nopulate.c
new file mode 100644
index 000000000..2ae175355
--- /dev/null
+++ b/dtc/tests/nopulate.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase/tool for rearranging blocks of a dtb
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static int nopulate_struct(char *buf, const char *fdt)
+{
+ int offset, nextoffset = 0;
+ uint32_t tag;
+ char *p;
+
+ p = buf;
+
+ do {
+ offset = nextoffset;
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+ memcpy(p, (const char *)fdt + fdt_off_dt_struct(fdt) + offset,
+ nextoffset - offset);
+ p += nextoffset - offset;
+
+ *((fdt32_t *)p) = cpu_to_fdt32(FDT_NOP);
+ p += FDT_TAGSIZE;
+
+ } while (tag != FDT_END);
+
+ return p - buf;
+}
+
+int main(int argc, char *argv[])
+{
+ char *fdt, *fdt2, *buf;
+ int newsize, struct_start, struct_end_old, struct_end_new, delta;
+ const char *inname;
+ char outname[PATH_MAX];
+
+ test_init(argc, argv);
+ if (argc != 2)
+ CONFIG("Usage: %s <dtb file>", argv[0]);
+
+ inname = argv[1];
+ fdt = load_blob(argv[1]);
+ sprintf(outname, "noppy.%s", inname);
+
+ if (fdt_version(fdt) < 17)
+ FAIL("Can't deal with version <17");
+
+ buf = xmalloc(2 * fdt_size_dt_struct(fdt));
+
+ newsize = nopulate_struct(buf, fdt);
+
+ verbose_printf("Nopulated structure block has new size %d\n", newsize);
+
+ /* Replace old strcutre block with the new */
+
+ fdt2 = xmalloc(fdt_totalsize(fdt) + newsize);
+
+ struct_start = fdt_off_dt_struct(fdt);
+ delta = newsize - fdt_size_dt_struct(fdt);
+ struct_end_old = struct_start + fdt_size_dt_struct(fdt);
+ struct_end_new = struct_start + newsize;
+
+ memcpy(fdt2, fdt, struct_start);
+ memcpy(fdt2 + struct_start, buf, newsize);
+ memcpy(fdt2 + struct_end_new, fdt + struct_end_old,
+ fdt_totalsize(fdt) - struct_end_old);
+
+ fdt_set_totalsize(fdt2, fdt_totalsize(fdt) + delta);
+ fdt_set_size_dt_struct(fdt2, newsize);
+
+ if (fdt_off_mem_rsvmap(fdt) > struct_start)
+ fdt_set_off_mem_rsvmap(fdt2, fdt_off_mem_rsvmap(fdt) + delta);
+ if (fdt_off_dt_strings(fdt) > struct_start)
+ fdt_set_off_dt_strings(fdt2, fdt_off_dt_strings(fdt) + delta);
+
+ save_blob(outname, fdt2);
+
+ PASS();
+}
diff --git a/dtc/tests/notfound.c b/dtc/tests/notfound.c
new file mode 100644
index 000000000..70acbcda3
--- /dev/null
+++ b/dtc/tests/notfound.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for behaviour on searching for a non-existent node
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check_error(const char *s, int err)
+{
+ if (err != -FDT_ERR_NOTFOUND)
+ FAIL("%s return error %s instead of -FDT_ERR_NOTFOUND", s,
+ fdt_strerror(err));
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int offset;
+ int subnode1_offset;
+ int lenerr;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ fdt_get_property(fdt, 0, "nonexistant-property", &lenerr);
+ check_error("fdt_get_property(\"nonexistant-property\")", lenerr);
+
+ fdt_getprop(fdt, 0, "nonexistant-property", &lenerr);
+ check_error("fdt_getprop(\"nonexistant-property\"", lenerr);
+
+ subnode1_offset = fdt_subnode_offset(fdt, 0, "subnode@1");
+ if (subnode1_offset < 0)
+ FAIL("Couldn't find subnode1: %s", fdt_strerror(subnode1_offset));
+
+ fdt_getprop(fdt, subnode1_offset, "prop-str", &lenerr);
+ check_error("fdt_getprop(\"prop-str\")", lenerr);
+
+ offset = fdt_subnode_offset(fdt, 0, "nonexistant-subnode");
+ check_error("fdt_subnode_offset(\"nonexistant-subnode\")", offset);
+
+ offset = fdt_subnode_offset(fdt, 0, "subsubnode");
+ check_error("fdt_subnode_offset(\"subsubnode\")", offset);
+
+ offset = fdt_path_offset(fdt, "/nonexistant-subnode");
+ check_error("fdt_path_offset(\"/nonexistant-subnode\")", offset);
+
+ PASS();
+}
diff --git a/dtc/tests/nul-in-escape.dts b/dtc/tests/nul-in-escape.dts
new file mode 100644
index 000000000..9bed351cf
--- /dev/null
+++ b/dtc/tests/nul-in-escape.dts
Binary files differ
diff --git a/dtc/tests/nul-in-line-info1.dts b/dtc/tests/nul-in-line-info1.dts
new file mode 100644
index 000000000..ceb7261b7
--- /dev/null
+++ b/dtc/tests/nul-in-line-info1.dts
Binary files differ
diff --git a/dtc/tests/nul-in-line-info2.dts b/dtc/tests/nul-in-line-info2.dts
new file mode 100644
index 000000000..1157d2324
--- /dev/null
+++ b/dtc/tests/nul-in-line-info2.dts
@@ -0,0 +1 @@
+# 0 "\0"
diff --git a/dtc/tests/obsolete-chosen-interrupt-controller.dts b/dtc/tests/obsolete-chosen-interrupt-controller.dts
new file mode 100644
index 000000000..36dd6e81d
--- /dev/null
+++ b/dtc/tests/obsolete-chosen-interrupt-controller.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ PIC: pic@0 {
+ reg = <0x0 0x10>;
+ interrupt-controller;
+ };
+ chosen {
+ interrupt-controller = <&PIC>;
+ };
+};
diff --git a/dtc/tests/omit-no-ref.dts b/dtc/tests/omit-no-ref.dts
new file mode 100644
index 000000000..8ace232ec
--- /dev/null
+++ b/dtc/tests/omit-no-ref.dts
@@ -0,0 +1,26 @@
+/dts-v1/;
+
+/ {
+ test-phandle = <&node3>;
+ test-path = &node4;
+
+ /omit-if-no-ref/ node1: node1 {
+ bar = <0xdeadbeef>;
+ };
+
+ node2: node2 {
+ foo = <0x42>;
+ };
+
+ node3: node3 {
+ test = "test";
+ };
+
+ node4: node4 {
+ test;
+ };
+};
+
+/omit-if-no-ref/ &node2;
+/omit-if-no-ref/ &node3;
+/omit-if-no-ref/ &node4;
diff --git a/dtc/tests/open_pack.c b/dtc/tests/open_pack.c
new file mode 100644
index 000000000..6ed4df7f6
--- /dev/null
+++ b/dtc/tests/open_pack.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Basic testcase for read-only access
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt, *fdt1;
+ void *buf;
+ int oldsize, bufsize, packsize;
+ int err;
+ const char *inname;
+ char outname[PATH_MAX];
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+ inname = argv[1];
+
+ oldsize = fdt_totalsize(fdt);
+
+ bufsize = oldsize * 2;
+
+ buf = xmalloc(bufsize);
+ /* don't leak uninitialized memory into our output */
+ memset(buf, 0, bufsize);
+
+ fdt1 = buf;
+ err = fdt_open_into(fdt, fdt1, bufsize);
+ if (err)
+ FAIL("fdt_open_into(): %s", fdt_strerror(err));
+ sprintf(outname, "opened.%s", inname);
+ save_blob(outname, fdt1);
+
+ err = fdt_pack(fdt1);
+ if (err)
+ FAIL("fdt_pack(): %s", fdt_strerror(err));
+ sprintf(outname, "repacked.%s", inname);
+ save_blob(outname, fdt1);
+
+ packsize = fdt_totalsize(fdt1);
+
+ verbose_printf("oldsize = %d, bufsize = %d, packsize = %d\n",
+ oldsize, bufsize, packsize);
+ PASS();
+}
diff --git a/dtc/tests/overlay.c b/dtc/tests/overlay.c
new file mode 100644
index 000000000..91afa72a6
--- /dev/null
+++ b/dtc/tests/overlay.c
@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for DT overlays()
+ * Copyright (C) 2016 Free Electrons
+ * Copyright (C) 2016 NextThing Co.
+ */
+
+#include <stdio.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+
+#define CHECK(code) \
+ { \
+ int err = (code); \
+ if (err) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ }
+
+/* 4k ought to be enough for anybody */
+#define FDT_COPY_SIZE (4 * 1024)
+
+static int fdt_getprop_u32_by_poffset(void *fdt, const char *path,
+ const char *name, int poffset,
+ unsigned long *out)
+{
+ const fdt32_t *val;
+ int node_off;
+ int len;
+
+ node_off = fdt_path_offset(fdt, path);
+ if (node_off < 0)
+ return node_off;
+
+ val = fdt_getprop(fdt, node_off, name, &len);
+ if (!val || (len < (sizeof(uint32_t) * (poffset + 1))))
+ return -FDT_ERR_NOTFOUND;
+
+ *out = fdt32_to_cpu(*(val + poffset));
+
+ return 0;
+}
+
+static int check_getprop_string_by_name(void *fdt, const char *path,
+ const char *name, const char *val)
+{
+ int node_off;
+
+ node_off = fdt_path_offset(fdt, path);
+ if (node_off < 0)
+ return node_off;
+
+ check_getprop_string(fdt, node_off, name, val);
+
+ return 0;
+}
+
+static int check_getprop_u32_by_name(void *fdt, const char *path,
+ const char *name, uint32_t val)
+{
+ int node_off;
+
+ node_off = fdt_path_offset(fdt, path);
+ CHECK(node_off < 0);
+
+ check_getprop_cell(fdt, node_off, name, val);
+
+ return 0;
+}
+
+static int check_getprop_null_by_name(void *fdt, const char *path,
+ const char *name)
+{
+ int node_off;
+
+ node_off = fdt_path_offset(fdt, path);
+ CHECK(node_off < 0);
+
+ check_property(fdt, node_off, name, 0, NULL);
+
+ return 0;
+}
+
+static int fdt_overlay_change_int_property(void *fdt)
+{
+ return check_getprop_u32_by_name(fdt, "/test-node", "test-int-property",
+ 43);
+}
+
+static int fdt_overlay_change_str_property(void *fdt)
+{
+ return check_getprop_string_by_name(fdt, "/test-node",
+ "test-str-property", "foobar");
+}
+
+static int fdt_overlay_add_str_property(void *fdt)
+{
+ return check_getprop_string_by_name(fdt, "/test-node",
+ "test-str-property-2", "foobar2");
+}
+
+static int fdt_overlay_add_node(void *fdt)
+{
+ return check_getprop_null_by_name(fdt, "/test-node/new-node",
+ "new-property");
+}
+
+static int fdt_overlay_add_subnode_property(void *fdt)
+{
+ check_getprop_null_by_name(fdt, "/test-node/sub-test-node",
+ "sub-test-property");
+ check_getprop_null_by_name(fdt, "/test-node/sub-test-node",
+ "new-sub-test-property");
+
+ return 0;
+}
+
+static int fdt_overlay_local_phandle(void *fdt)
+{
+ uint32_t local_phandle;
+ unsigned long val = 0;
+ int off;
+
+ off = fdt_path_offset(fdt, "/test-node/new-local-node");
+ CHECK(off < 0);
+
+ local_phandle = fdt_get_phandle(fdt, off);
+ CHECK(!local_phandle);
+
+ CHECK(fdt_getprop_u32_by_poffset(fdt, "/test-node",
+ "test-several-phandle",
+ 0, &val));
+ CHECK(val != local_phandle);
+
+ CHECK(fdt_getprop_u32_by_poffset(fdt, "/test-node",
+ "test-several-phandle",
+ 1, &val));
+ CHECK(val != local_phandle);
+
+ return 0;
+}
+
+static int fdt_overlay_local_phandles(void *fdt)
+{
+ uint32_t local_phandle, test_phandle;
+ unsigned long val = 0;
+ int off;
+
+ off = fdt_path_offset(fdt, "/test-node/new-local-node");
+ CHECK(off < 0);
+
+ local_phandle = fdt_get_phandle(fdt, off);
+ CHECK(!local_phandle);
+
+ off = fdt_path_offset(fdt, "/test-node");
+ CHECK(off < 0);
+
+ test_phandle = fdt_get_phandle(fdt, off);
+ CHECK(!test_phandle);
+
+ CHECK(fdt_getprop_u32_by_poffset(fdt, "/test-node",
+ "test-phandle", 0, &val));
+ CHECK(test_phandle != val);
+
+ CHECK(fdt_getprop_u32_by_poffset(fdt, "/test-node",
+ "test-phandle", 1, &val));
+ CHECK(local_phandle != val);
+
+ return 0;
+}
+
+static void *open_dt(char *path)
+{
+ void *dt, *copy;
+
+ dt = load_blob(path);
+ copy = xmalloc(FDT_COPY_SIZE);
+
+ /*
+ * Resize our DTs to 4k so that we have room to operate on
+ */
+ CHECK(fdt_open_into(dt, copy, FDT_COPY_SIZE));
+
+ return copy;
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt_base, *fdt_overlay;
+
+ test_init(argc, argv);
+ if (argc != 3)
+ CONFIG("Usage: %s <base dtb> <overlay dtb>", argv[0]);
+
+ fdt_base = open_dt(argv[1]);
+ fdt_overlay = open_dt(argv[2]);
+
+ /* Apply the overlay */
+ CHECK(fdt_overlay_apply(fdt_base, fdt_overlay));
+
+ fdt_overlay_change_int_property(fdt_base);
+ fdt_overlay_change_str_property(fdt_base);
+ fdt_overlay_add_str_property(fdt_base);
+ fdt_overlay_add_node(fdt_base);
+ fdt_overlay_add_subnode_property(fdt_base);
+
+ /*
+ * If the base tree has a __symbols__ node, do the tests that
+ * are only successful with a proper phandle support, and thus
+ * dtc -@
+ */
+ if (fdt_path_offset(fdt_base, "/__symbols__") >= 0) {
+ fdt_overlay_local_phandle(fdt_base);
+ fdt_overlay_local_phandles(fdt_base);
+ }
+
+ PASS();
+}
diff --git a/dtc/tests/overlay_bad_fixup.c b/dtc/tests/overlay_bad_fixup.c
new file mode 100644
index 000000000..029bc7982
--- /dev/null
+++ b/dtc/tests/overlay_bad_fixup.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for DT overlays()
+ * Copyright (C) 2016 Free Electrons
+ * Copyright (C) 2016 NextThing Co.
+ */
+
+#include <stdio.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+
+#define CHECK(code, expected) \
+ { \
+ err = (code); \
+ if (err != expected) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ }
+
+/* 4k ought to be enough for anybody */
+#define FDT_COPY_SIZE (4 * 1024)
+
+static void *open_dt(char *path)
+{
+ void *dt, *copy;
+ int err;
+
+ dt = load_blob(path);
+ copy = xmalloc(FDT_COPY_SIZE);
+
+ /*
+ * Resize our DTs to 4k so that we have room to operate on
+ */
+ CHECK(fdt_open_into(dt, copy, FDT_COPY_SIZE), 0);
+
+ return copy;
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt_base, *fdt_overlay;
+ int err;
+
+ test_init(argc, argv);
+ if (argc != 3)
+ CONFIG("Usage: %s <base dtb> <overlay dtb>", argv[0]);
+
+ fdt_base = open_dt(argv[1]);
+ fdt_overlay = open_dt(argv[2]);
+
+ /* Apply the overlay */
+ CHECK(fdt_overlay_apply(fdt_base, fdt_overlay), -FDT_ERR_BADOVERLAY);
+
+ PASS();
+}
diff --git a/dtc/tests/overlay_bad_fixup_bad_index.dts b/dtc/tests/overlay_bad_fixup_bad_index.dts
new file mode 100644
index 000000000..b5cf13137
--- /dev/null
+++ b/dtc/tests/overlay_bad_fixup_bad_index.dts
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/include/ "overlay_bad_fixup_base.dtsi"
+
+/ {
+ __fixups__ {
+ test = "/fragment@0:target:ab";
+ };
+};
diff --git a/dtc/tests/overlay_bad_fixup_base.dtsi b/dtc/tests/overlay_bad_fixup_base.dtsi
new file mode 100644
index 000000000..216bcab52
--- /dev/null
+++ b/dtc/tests/overlay_bad_fixup_base.dtsi
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+
+/ {
+ fragment@0 {
+ target = <0xffffffff>;
+
+ __overlay__ {
+ test-property;
+ };
+ };
+};
diff --git a/dtc/tests/overlay_bad_fixup_empty.dts b/dtc/tests/overlay_bad_fixup_empty.dts
new file mode 100644
index 000000000..e111db4c8
--- /dev/null
+++ b/dtc/tests/overlay_bad_fixup_empty.dts
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/include/ "overlay_bad_fixup_base.dtsi"
+
+/ {
+ __fixups__ {
+ test = "";
+ };
+};
diff --git a/dtc/tests/overlay_bad_fixup_empty_index.dts b/dtc/tests/overlay_bad_fixup_empty_index.dts
new file mode 100644
index 000000000..9e12e2177
--- /dev/null
+++ b/dtc/tests/overlay_bad_fixup_empty_index.dts
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/include/ "overlay_bad_fixup_base.dtsi"
+
+/ {
+ __fixups__ {
+ test = "/fragment@0:target:";
+ };
+};
diff --git a/dtc/tests/overlay_bad_fixup_index_trailing.dts b/dtc/tests/overlay_bad_fixup_index_trailing.dts
new file mode 100644
index 000000000..f586bef4d
--- /dev/null
+++ b/dtc/tests/overlay_bad_fixup_index_trailing.dts
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/include/ "overlay_bad_fixup_base.dtsi"
+
+/ {
+ __fixups__ {
+ test = "/fragment@0:target:0a";
+ };
+};
diff --git a/dtc/tests/overlay_bad_fixup_path_empty_prop.dts b/dtc/tests/overlay_bad_fixup_path_empty_prop.dts
new file mode 100644
index 000000000..608b5f924
--- /dev/null
+++ b/dtc/tests/overlay_bad_fixup_path_empty_prop.dts
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/include/ "overlay_bad_fixup_base.dtsi"
+
+/ {
+ __fixups__ {
+ test = "/fragment@0::";
+ };
+};
diff --git a/dtc/tests/overlay_bad_fixup_path_only.dts b/dtc/tests/overlay_bad_fixup_path_only.dts
new file mode 100644
index 000000000..2485dd965
--- /dev/null
+++ b/dtc/tests/overlay_bad_fixup_path_only.dts
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/include/ "overlay_bad_fixup_base.dtsi"
+
+/ {
+ __fixups__ {
+ test = "/fragment@0";
+ };
+};
diff --git a/dtc/tests/overlay_bad_fixup_path_only_sep.dts b/dtc/tests/overlay_bad_fixup_path_only_sep.dts
new file mode 100644
index 000000000..3cbf6c40f
--- /dev/null
+++ b/dtc/tests/overlay_bad_fixup_path_only_sep.dts
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/include/ "overlay_bad_fixup_base.dtsi"
+
+/ {
+ __fixups__ {
+ test = "/fragment@0:";
+ };
+};
diff --git a/dtc/tests/overlay_bad_fixup_path_prop.dts b/dtc/tests/overlay_bad_fixup_path_prop.dts
new file mode 100644
index 000000000..ca79b52bc
--- /dev/null
+++ b/dtc/tests/overlay_bad_fixup_path_prop.dts
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/include/ "overlay_bad_fixup_base.dtsi"
+
+/ {
+ __fixups__ {
+ test = "/fragment@0:target";
+ };
+};
diff --git a/dtc/tests/overlay_base.dts b/dtc/tests/overlay_base.dts
new file mode 100644
index 000000000..a5e55b2b2
--- /dev/null
+++ b/dtc/tests/overlay_base.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+
+/ {
+ test: test-node {
+ test-int-property = <42>;
+ test-str-property = "foo";
+
+ subtest: sub-test-node {
+ sub-test-property;
+
+ subtest_with_long_path: sub-test-node-with-very-long-target-path {
+ long-test-path-property;
+ };
+ };
+ };
+};
+
+
diff --git a/dtc/tests/overlay_base_manual_symbols.dts b/dtc/tests/overlay_base_manual_symbols.dts
new file mode 100644
index 000000000..7e4d17dcb
--- /dev/null
+++ b/dtc/tests/overlay_base_manual_symbols.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+
+/ {
+ test: test-node {
+ phandle = <&test>; /* Force phandle generation */
+ test-int-property = <42>;
+ test-str-property = "foo";
+
+ subtest: sub-test-node {
+ sub-test-property;
+ };
+ };
+ __symbols__ {
+ test = &test;
+ };
+};
+
+
diff --git a/dtc/tests/overlay_overlay.dts b/dtc/tests/overlay_overlay.dts
new file mode 100644
index 000000000..c4ef1d47f
--- /dev/null
+++ b/dtc/tests/overlay_overlay.dts
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ * Copyright (c) 2016 Konsulko Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+/plugin/;
+
+/* Test that we can change an int by another */
+&test {
+ test-int-property = <43>;
+};
+
+/* Test that we can replace a string by a longer one */
+&test {
+ test-str-property = "foobar";
+};
+
+/* Test that we add a new property */
+&test {
+ test-str-property-2 = "foobar2";
+};
+
+/* Test that we add a new node (by phandle) */
+&test {
+ new-node {
+ new-property;
+ };
+};
+
+&test {
+ local: new-local-node {
+ new-property;
+ };
+};
+
+&test {
+ test-phandle = <&test>, <&local>;
+};
+
+&test {
+ test-several-phandle = <&local>, <&local>;
+};
+
+&test {
+ sub-test-node {
+ new-sub-test-property;
+ };
+};
diff --git a/dtc/tests/overlay_overlay_bypath.dts b/dtc/tests/overlay_overlay_bypath.dts
new file mode 100644
index 000000000..f23e7b603
--- /dev/null
+++ b/dtc/tests/overlay_overlay_bypath.dts
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ * Copyright (c) 2016 Konsulko Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+/plugin/;
+
+/* Test that we can change an int by another */
+&{/test-node} {
+ test-int-property = <43>;
+};
+
+/* Test that we can replace a string by a longer one */
+&{/test-node} {
+ test-str-property = "foobar";
+};
+
+/* Test that we add a new property */
+&{/test-node} {
+ test-str-property-2 = "foobar2";
+};
+
+/* Test that we add a new node (by phandle) */
+&{/test-node} {
+ new-node {
+ new-property;
+ };
+};
+
+&{/} {
+ local: new-local-node {
+ new-property;
+ };
+};
+
+&{/} {
+ test-several-phandle = <&local>, <&local>;
+};
+
+&{/test-node} {
+ sub-test-node {
+ new-sub-test-property;
+ };
+};
diff --git a/dtc/tests/overlay_overlay_local_merge.dts b/dtc/tests/overlay_overlay_local_merge.dts
new file mode 100644
index 000000000..3ee622dfc
--- /dev/null
+++ b/dtc/tests/overlay_overlay_local_merge.dts
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ * Copyright (c) 2016 Konsulko Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+/plugin/;
+
+&test {
+ parent: new-node {
+ parent-property;
+ };
+};
+
+&parent {
+ new-merged-property;
+ new-merged-node {
+ new-property;
+ };
+};
+
+&{/} {
+ new-root-node {
+ new-root-node-property;
+ };
+};
diff --git a/dtc/tests/overlay_overlay_long_path.dts b/dtc/tests/overlay_overlay_long_path.dts
new file mode 100644
index 000000000..4f0d40b69
--- /dev/null
+++ b/dtc/tests/overlay_overlay_long_path.dts
@@ -0,0 +1,32 @@
+/dts-v1/;
+/plugin/;
+
+&subtest_with_long_path {
+ lpath_0: test-0 {
+ prop = "lpath";
+ };
+
+ lpath_1: test-1 {
+ prop = "lpath";
+ };
+
+ lpath_2: test-2 {
+ prop = "lpath";
+ };
+
+ lpath_3: test-3 {
+ prop = "lpath";
+ };
+
+ lpath_4: test-4 {
+ prop = "lpath";
+ };
+
+ lpath_5: test-5 {
+ prop = "lpath";
+ };
+
+ lpath_6: test-6 {
+ prop = "lpath";
+ };
+};
diff --git a/dtc/tests/overlay_overlay_manual_fixups.dts b/dtc/tests/overlay_overlay_manual_fixups.dts
new file mode 100644
index 000000000..a5715b604
--- /dev/null
+++ b/dtc/tests/overlay_overlay_manual_fixups.dts
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ * Copyright (c) 2016 Konsulko Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+
+/* Note no /plugin/ tag - we're manually generating the metadata for
+ testing purposes */
+
+/ {
+ /* Test that we can change an int by another */
+ fragment@0 {
+ target = <0xffffffff /*&test*/>;
+
+ __overlay__ {
+ test-int-property = <43>;
+ };
+ };
+
+ /* Test that we can replace a string by a longer one */
+ fragment@1 {
+ target = <0xffffffff /*&test*/>;
+
+ __overlay__ {
+ test-str-property = "foobar";
+ };
+ };
+
+ /* Test that we add a new property */
+ fragment@2 {
+ target = <0xffffffff /*&test*/>;
+
+ __overlay__ {
+ test-str-property-2 = "foobar2";
+ };
+ };
+
+ /* Test that we add a new node (by phandle) */
+ fragment@3 {
+ target = <0xffffffff /*&test*/>;
+
+ __overlay__ {
+ new-node {
+ new-property;
+ };
+ };
+ };
+
+ fragment@4 {
+ target = <0xffffffff /*&test*/>;
+
+ __overlay__ {
+ local: new-local-node {
+ new-property;
+ };
+ };
+ };
+
+ fragment@5 {
+ target = <0xffffffff /*&test*/>;
+
+ __overlay__ {
+ test-phandle = <0xffffffff /*&test*/>, <&local>;
+ };
+ };
+
+ fragment@6 {
+ target = <0xffffffff /*&test*/>;
+
+ __overlay__ {
+ test-several-phandle = <&local>, <&local>;
+ };
+ };
+
+ fragment@7 {
+ target = <0xffffffff /*&test*/>;
+
+ __overlay__ {
+ sub-test-node {
+ new-sub-test-property;
+ };
+ };
+ };
+
+ __fixups__ {
+ test = "/fragment@0:target:0",
+ "/fragment@1:target:0",
+ "/fragment@2:target:0",
+ "/fragment@3:target:0",
+ "/fragment@4:target:0",
+ "/fragment@5:target:0",
+ "/fragment@5/__overlay__:test-phandle:0",
+ "/fragment@6:target:0",
+ "/fragment@7:target:0";
+ };
+ __local_fixups__ {
+ fragment@5 {
+ __overlay__ {
+ test-phandle = <4>;
+ };
+ };
+ fragment@6 {
+ __overlay__ {
+ test-several-phandle = <0 4>;
+ };
+ };
+ };
+};
diff --git a/dtc/tests/overlay_overlay_no_fixups.dts b/dtc/tests/overlay_overlay_no_fixups.dts
new file mode 100644
index 000000000..e8d0f96d8
--- /dev/null
+++ b/dtc/tests/overlay_overlay_no_fixups.dts
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+
+/ {
+ fragment@0 {
+ target-path = "/test-node";
+
+ __overlay__ {
+ test-int-property = <43>;
+ };
+ };
+
+ /* Test that we can replace a string by a longer one */
+ fragment@1 {
+ target-path = "/test-node";
+
+ __overlay__ {
+ test-str-property = "foobar";
+ };
+ };
+
+ /* Test that we add a new property */
+ fragment@2 {
+ target-path = "/test-node";
+
+ __overlay__ {
+ test-str-property-2 = "foobar2";
+ };
+ };
+
+ fragment@3 {
+ target-path = "/test-node";
+
+ __overlay__ {
+ new-node {
+ new-property;
+ };
+ };
+ };
+
+ fragment@4 {
+ target-path = "/";
+
+ __overlay__ {
+ local: new-local-node {
+ new-property;
+ };
+ };
+ };
+
+ fragment@5 {
+ target-path = "/";
+
+ __overlay__ {
+ test-several-phandle = <&local>, <&local>;
+ };
+ };
+
+ fragment@6 {
+ target-path = "/test-node";
+
+ __overlay__ {
+ sub-test-node {
+ new-sub-test-property;
+ };
+ };
+ };
+
+ __local_fixups__ {
+ fragment@5 {
+ __overlay__ {
+ test-several-phandle = <0 4>;
+ };
+ };
+ };
+};
diff --git a/dtc/tests/overlay_overlay_nosugar.dts b/dtc/tests/overlay_overlay_nosugar.dts
new file mode 100644
index 000000000..b5947e96f
--- /dev/null
+++ b/dtc/tests/overlay_overlay_nosugar.dts
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ * Copyright (c) 2016 Konsulko Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+/plugin/;
+
+/ {
+ /* Test that we can change an int by another */
+ fragment@0 {
+ target = <&test>;
+
+ __overlay__ {
+ test-int-property = <43>;
+ };
+ };
+
+ /* Test that we can replace a string by a longer one */
+ fragment@1 {
+ target = <&test>;
+
+ __overlay__ {
+ test-str-property = "foobar";
+ };
+ };
+
+ /* Test that we add a new property */
+ fragment@2 {
+ target = <&test>;
+
+ __overlay__ {
+ test-str-property-2 = "foobar2";
+ };
+ };
+
+ /* Test that we add a new node (by phandle) */
+ fragment@3 {
+ target = <&test>;
+
+ __overlay__ {
+ new-node {
+ new-property;
+ };
+ };
+ };
+
+ fragment@4 {
+ target = <&test>;
+
+ __overlay__ {
+ local: new-local-node {
+ new-property;
+ };
+ };
+ };
+
+ fragment@5 {
+ target = <&test>;
+
+ __overlay__ {
+ test-phandle = <&test>, <&local>;
+ };
+ };
+
+ fragment@6 {
+ target = <&test>;
+
+ __overlay__ {
+ test-several-phandle = <&local>, <&local>;
+ };
+ };
+
+ fragment@7 {
+ target = <&test>;
+
+ __overlay__ {
+ sub-test-node {
+ new-sub-test-property;
+ };
+ };
+ };
+};
diff --git a/dtc/tests/overlay_overlay_simple.dts b/dtc/tests/overlay_overlay_simple.dts
new file mode 100644
index 000000000..8657e1e7a
--- /dev/null
+++ b/dtc/tests/overlay_overlay_simple.dts
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2016 Konsulko Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+/plugin/;
+
+&test {
+ test-int-property = <43>;
+};
diff --git a/dtc/tests/parent_offset.c b/dtc/tests/parent_offset.c
new file mode 100644
index 000000000..a935a5374
--- /dev/null
+++ b/dtc/tests/parent_offset.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_parent_offset()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static int path_parent_len(const char *path)
+{
+ const char *p = strrchr(path, '/');
+
+ if (!p)
+ TEST_BUG();
+ if (p == path)
+ return 1;
+ else
+ return p - path;
+}
+
+static void check_path(struct fdt_header *fdt, const char *path)
+{
+ char *parentpath;
+ int nodeoffset, parentoffset, parentpathoffset, pathparentlen;
+
+ pathparentlen = path_parent_len(path);
+ parentpath = alloca(pathparentlen + 1);
+ strncpy(parentpath, path, pathparentlen);
+ parentpath[pathparentlen] = '\0';
+
+ verbose_printf("Path: \"%s\"\tParent: \"%s\"\n", path, parentpath);
+
+ nodeoffset = fdt_path_offset(fdt, path);
+ if (nodeoffset < 0)
+ FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(nodeoffset));
+
+ parentpathoffset = fdt_path_offset(fdt, parentpath);
+ if (parentpathoffset < 0)
+ FAIL("fdt_path_offset(%s): %s", parentpath,
+ fdt_strerror(parentpathoffset));
+
+ parentoffset = fdt_parent_offset(fdt, nodeoffset);
+ if (parentoffset < 0)
+ FAIL("fdt_parent_offset(): %s", fdt_strerror(parentoffset));
+
+ if (parentoffset != parentpathoffset)
+ FAIL("fdt_parent_offset() returns %d instead of %d",
+ parentoffset, parentpathoffset);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int err;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_path(fdt, "/subnode@1");
+ check_path(fdt, "/subnode@2");
+ check_path(fdt, "/subnode@1/subsubnode");
+ check_path(fdt, "/subnode@2/subsubnode@0");
+ err = fdt_parent_offset(fdt, 0);
+ if (err != -FDT_ERR_NOTFOUND)
+ FAIL("fdt_parent_offset(/) returns %d instead of "
+ "-FDT_ERR_NOTFOUND", err);
+
+ PASS();
+}
diff --git a/dtc/tests/path-references.c b/dtc/tests/path-references.c
new file mode 100644
index 000000000..4db61a56d
--- /dev/null
+++ b/dtc/tests/path-references.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for string references in dtc
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check_ref(const void *fdt, int node, const char *checkpath)
+{
+ const char *p;
+ int len;
+
+ p = fdt_getprop(fdt, node, "ref", &len);
+ if (!p)
+ FAIL("fdt_getprop(%d, \"ref\"): %s", node, fdt_strerror(len));
+ if (!streq(p, checkpath))
+ FAIL("'ref' in node at %d has value \"%s\" instead of \"%s\"",
+ node, p, checkpath);
+
+ p = fdt_getprop(fdt, node, "lref", &len);
+ if (!p)
+ FAIL("fdt_getprop(%d, \"lref\"): %s", node, fdt_strerror(len));
+ if (!streq(p, checkpath))
+ FAIL("'lref' in node at %d has value \"%s\" instead of \"%s\"",
+ node, p, checkpath);
+}
+
+static void check_rref(const void *fdt)
+{
+ const char *p;
+ int len;
+
+ /* Check reference to root node */
+ p = fdt_getprop(fdt, 0, "rref", &len);
+ if (!p)
+ FAIL("fdt_getprop(0, \"rref\"): %s", fdt_strerror(len));
+ if (!streq(p, "/"))
+ FAIL("'rref' in root node has value \"%s\" instead of \"/\"",
+ p);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ const char *p;
+ int len, multilen;
+ int n1, n2, n3, n4;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ n1 = fdt_path_offset(fdt, "/node1");
+ if (n1 < 0)
+ FAIL("fdt_path_offset(/node1): %s", fdt_strerror(n1));
+ n2 = fdt_path_offset(fdt, "/node2");
+ if (n2 < 0)
+ FAIL("fdt_path_offset(/node2): %s", fdt_strerror(n2));
+
+ check_ref(fdt, n1, "/node2");
+ check_ref(fdt, n2, "/node1");
+
+ /* Check multiple reference */
+ multilen = strlen("/node1") + strlen("/node2") + 2;
+ p = fdt_getprop(fdt, 0, "multiref", &len);
+ if (!p)
+ FAIL("fdt_getprop(0, \"multiref\"): %s", fdt_strerror(len));
+ if (len != multilen)
+ FAIL("multiref has wrong length, %d instead of %d",
+ len, multilen);
+ if ((!streq(p, "/node1") || !streq(p + strlen("/node1") + 1, "/node2")))
+ FAIL("multiref has wrong value");
+
+ /* Check reference to nested nodes with common prefix */
+ n3 = fdt_path_offset(fdt, "/foo/baz");
+ if (n3 < 0)
+ FAIL("fdt_path_offset(/foo/baz): %s", fdt_strerror(n3));
+ n4 = fdt_path_offset(fdt, "/foobar/baz");
+ if (n4 < 0)
+ FAIL("fdt_path_offset(/foobar/baz): %s", fdt_strerror(n4));
+ check_ref(fdt, n3, "/foobar/baz");
+ check_ref(fdt, n4, "/foo/baz");
+
+ check_rref(fdt);
+
+ PASS();
+}
diff --git a/dtc/tests/path-references.dts b/dtc/tests/path-references.dts
new file mode 100644
index 000000000..1fb7d7045
--- /dev/null
+++ b/dtc/tests/path-references.dts
@@ -0,0 +1,28 @@
+/dts-v1/;
+
+/ {
+ rref = &{/};
+ /* Check multiple references case */
+ multiref = &n1 , &n2;
+ n1: node1 {
+ ref = &{/node2}; /* reference precedes target */
+ lref = &n2;
+ };
+ n2: node2 {
+ ref = &{/node1}; /* reference after target */
+ lref = &n1;
+ };
+ /* Check references to nested nodes with common prefix */
+ foobar {
+ n3: baz {
+ ref = &{/foo/baz};
+ lref = start: &n4 end:;
+ };
+ };
+ foo {
+ n4: baz {
+ ref = &{/foobar/baz};
+ lref = &n3;
+ };
+ };
+};
diff --git a/dtc/tests/path_offset.c b/dtc/tests/path_offset.c
new file mode 100644
index 000000000..82527d463
--- /dev/null
+++ b/dtc/tests/path_offset.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_path_offset()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static int check_subnode(void *fdt, int parent, const char *name)
+{
+ int offset;
+ const struct fdt_node_header *nh;
+ uint32_t tag;
+
+ verbose_printf("Checking subnode \"%s\" of %d...", name, parent);
+ offset = fdt_subnode_offset(fdt, parent, name);
+ verbose_printf("offset %d...", offset);
+ if (offset < 0)
+ FAIL("fdt_subnode_offset(\"%s\"): %s", name, fdt_strerror(offset));
+ nh = fdt_offset_ptr(fdt, offset, sizeof(*nh));
+ verbose_printf("pointer %p\n", nh);
+ if (! nh)
+ FAIL("NULL retrieving subnode \"%s\"", name);
+
+ tag = fdt32_to_cpu(nh->tag);
+
+ if (tag != FDT_BEGIN_NODE)
+ FAIL("Incorrect tag 0x%08x on property \"%s\"", tag, name);
+ if (!nodename_eq(nh->name, name))
+ FAIL("Subnode name mismatch \"%s\" instead of \"%s\"",
+ nh->name, name);
+
+ return offset;
+}
+
+static void check_path_offset(void *fdt, char *path, int offset)
+{
+ int rc;
+
+ verbose_printf("Checking offset of \"%s\" is %d...\n", path, offset);
+
+ rc = fdt_path_offset(fdt, path);
+ if (rc < 0)
+ FAIL("fdt_path_offset(\"%s\") failed: %s",
+ path, fdt_strerror(rc));
+ if (rc != offset)
+ FAIL("fdt_path_offset(\"%s\") returned incorrect offset"
+ " %d instead of %d", path, rc, offset);
+}
+
+static void check_path_offset_namelen(void *fdt, char *path, int namelen,
+ int offset)
+{
+ int rc;
+
+ verbose_printf("Checking offset of \"%s\" [first %d characters]"
+ " is %d...\n", path, namelen, offset);
+
+ rc = fdt_path_offset_namelen(fdt, path, namelen);
+ if (rc == offset)
+ return;
+
+ if (rc < 0)
+ FAIL("fdt_path_offset_namelen(\"%s\", %d) failed: %s",
+ path, namelen, fdt_strerror(rc));
+ else
+ FAIL("fdt_path_offset_namelen(\"%s\", %d) returned incorrect"
+ " offset %d instead of %d", path, namelen, rc, offset);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int subnode1_offset, subnode2_offset;
+ int subsubnode1_offset, subsubnode2_offset, subsubnode2_offset2;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_path_offset(fdt, "/", 0);
+
+ subnode1_offset = check_subnode(fdt, 0, "subnode@1");
+ subnode2_offset = check_subnode(fdt, 0, "subnode@2");
+
+ check_path_offset(fdt, "/subnode@1", subnode1_offset);
+ check_path_offset(fdt, "/subnode@2", subnode2_offset);
+
+ subsubnode1_offset = check_subnode(fdt, subnode1_offset, "subsubnode");
+ subsubnode2_offset = check_subnode(fdt, subnode2_offset, "subsubnode@0");
+ subsubnode2_offset2 = check_subnode(fdt, subnode2_offset, "subsubnode");
+
+ check_path_offset(fdt, "/subnode@1/subsubnode", subsubnode1_offset);
+ check_path_offset(fdt, "/subnode@2/subsubnode@0", subsubnode2_offset);
+ check_path_offset(fdt, "/subnode@2/subsubnode", subsubnode2_offset2);
+
+ /* Test paths with extraneous separators */
+ check_path_offset(fdt, "//", 0);
+ check_path_offset(fdt, "///", 0);
+ check_path_offset(fdt, "//subnode@1", subnode1_offset);
+ check_path_offset(fdt, "/subnode@1/", subnode1_offset);
+ check_path_offset(fdt, "//subnode@1///", subnode1_offset);
+ check_path_offset(fdt, "/subnode@2////subsubnode", subsubnode2_offset2);
+
+ /* Test fdt_path_offset_namelen() */
+ check_path_offset_namelen(fdt, "/subnode@1", 1, 0);
+ check_path_offset_namelen(fdt, "/subnode@1/subsubnode", 10, subnode1_offset);
+ check_path_offset_namelen(fdt, "/subnode@1/subsubnode", 11, subnode1_offset);
+ check_path_offset_namelen(fdt, "/subnode@2TRAILINGGARBAGE", 10, subnode2_offset);
+ check_path_offset_namelen(fdt, "/subnode@2TRAILINGGARBAGE", 11, -FDT_ERR_NOTFOUND);
+ check_path_offset_namelen(fdt, "/subnode@2/subsubnode@0/more", 23, subsubnode2_offset2);
+ check_path_offset_namelen(fdt, "/subnode@2/subsubnode@0/more", 22, -FDT_ERR_NOTFOUND);
+ check_path_offset_namelen(fdt, "/subnode@2/subsubnode@0/more", 24, subsubnode2_offset2);
+ check_path_offset_namelen(fdt, "/subnode@2/subsubnode@0/more", 25, -FDT_ERR_NOTFOUND);
+
+ PASS();
+}
diff --git a/dtc/tests/path_offset_aliases.c b/dtc/tests/path_offset_aliases.c
new file mode 100644
index 000000000..0112e7250
--- /dev/null
+++ b/dtc/tests/path_offset_aliases.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_path_offset()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright 2008 Kumar Gala, Freescale Semiconductor, Inc.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check_alias(void *fdt, const char *full_path, const char *alias_path)
+{
+ int offset, offset_a;
+
+ offset = fdt_path_offset(fdt, full_path);
+ offset_a = fdt_path_offset(fdt, alias_path);
+
+ if (offset != offset_a)
+ FAIL("Mismatch between %s path_offset (%d) and %s path_offset alias (%d)",
+ full_path, offset, alias_path, offset_a);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_alias(fdt, "/subnode@1", "s1");
+ check_alias(fdt, "/subnode@1/subsubnode", "ss1");
+ check_alias(fdt, "/subnode@1/subsubnode", "s1/subsubnode");
+ check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "sss1");
+ check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "ss1/subsubsubnode");
+ check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "s1/subsubnode/subsubsubnode");
+
+ PASS();
+}
diff --git a/dtc/tests/pci-bridge-bad1.dts b/dtc/tests/pci-bridge-bad1.dts
new file mode 100644
index 000000000..17aac04ae
--- /dev/null
+++ b/dtc/tests/pci-bridge-bad1.dts
@@ -0,0 +1,16 @@
+/dts-v1/;
+
+/ {
+ compatible = "example,pci-bridge-ok";
+ #address-cells = < 2 >;
+ #size-cells = < 2 >;
+ abadname@0 {
+ device_type = "pci";
+ compatible = "example,pci-bridge";
+ #address-cells = < 3 >;
+ #size-cells = < 2 >;
+ reg = <0 0 0 0x1000>;
+ bus-range = <0 0xff>;
+ ranges = <0 0 0 0 0 0 0x10000>;
+ };
+};
diff --git a/dtc/tests/pci-bridge-bad2.dts b/dtc/tests/pci-bridge-bad2.dts
new file mode 100644
index 000000000..a7e5c054a
--- /dev/null
+++ b/dtc/tests/pci-bridge-bad2.dts
@@ -0,0 +1,16 @@
+/dts-v1/;
+
+/ {
+ compatible = "example,pci-bridge-ok";
+ #address-cells = < 2 >;
+ #size-cells = < 2 >;
+ p@0 {
+ device_type = "pci";
+ compatible = "example,pci-bridge";
+ #address-cells = < 3 >;
+ #size-cells = < 2 >;
+ reg = <0 0 0 0x1000>;
+ bus-range = <0 0xff>;
+ ranges = <0 0 0 0 0 0 0x10000>;
+ };
+};
diff --git a/dtc/tests/pci-bridge-ok.dts b/dtc/tests/pci-bridge-ok.dts
new file mode 100644
index 000000000..02e32e01a
--- /dev/null
+++ b/dtc/tests/pci-bridge-ok.dts
@@ -0,0 +1,25 @@
+/dts-v1/;
+
+/ {
+ compatible = "example,pci-bridge-ok";
+ #address-cells = < 2 >;
+ #size-cells = < 2 >;
+ pci@0 {
+ device_type = "pci";
+ compatible = "example,pci-bridge";
+ #address-cells = < 3 >;
+ #size-cells = < 2 >;
+ reg = <0 0 0 0x1000>;
+ bus-range = <0 0xff>;
+ ranges = <0 0 0 0 0 0 0x10000>;
+ };
+ pcie@10000000000 {
+ device_type = "pci";
+ compatible = "example,pcie-bridge";
+ #address-cells = < 3 >;
+ #size-cells = < 2 >;
+ reg = <0x10 0x00000000 0 0x1000>;
+ bus-range = <0 0xff>;
+ ranges = <0 0 0 0 0 0 0x10000>;
+ };
+};
diff --git a/dtc/tests/phandle_format.c b/dtc/tests/phandle_format.c
new file mode 100644
index 000000000..d00618f3b
--- /dev/null
+++ b/dtc/tests/phandle_format.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for phandle format options
+ * Copyright (C) 2009 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define PHANDLE_LEGACY 0x1
+#define PHANDLE_EPAPR 0x2
+#define PHANDLE_BOTH 0x3
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int phandle_format;
+ int n4;
+ uint32_t h4;
+
+ if (argc != 3)
+ CONFIG("Usage: %s <dtb file> <legacy|epapr|both>\n", argv[0]);
+
+ test_init(argc, argv);
+ fdt = load_blob(argv[1]);
+
+ if (streq(argv[2], "legacy"))
+ phandle_format = PHANDLE_LEGACY;
+ else if (streq(argv[2], "epapr"))
+ phandle_format = PHANDLE_EPAPR;
+ else if (streq(argv[2], "both"))
+ phandle_format = PHANDLE_BOTH;
+ else
+ CONFIG("Usage: %s <dtb file> <legacy|epapr|both>\n", argv[0]);
+
+ n4 = fdt_path_offset(fdt, "/node4");
+ if (n4 < 0)
+ FAIL("fdt_path_offset(/node4): %s", fdt_strerror(n4));
+
+ h4 = fdt_get_phandle(fdt, n4);
+ if ((h4 == 0) || (h4 == -1))
+ FAIL("/node4 has bad phandle 0x%x\n", h4);
+
+ if (phandle_format & PHANDLE_LEGACY)
+ check_getprop_cell(fdt, n4, "linux,phandle", h4);
+ else
+ if (fdt_getprop(fdt, n4, "linux,phandle", NULL))
+ FAIL("linux,phandle property present in non-legacy mode");
+
+ if (phandle_format & PHANDLE_EPAPR)
+ check_getprop_cell(fdt, n4, "phandle", h4);
+ else
+ if (fdt_getprop(fdt, n4, "phandle", NULL))
+ FAIL("phandle property present in legacy-only mode");
+
+ PASS();
+}
diff --git a/dtc/tests/prop-after-subnode.dts b/dtc/tests/prop-after-subnode.dts
new file mode 100644
index 000000000..6dd0b660f
--- /dev/null
+++ b/dtc/tests/prop-after-subnode.dts
@@ -0,0 +1,9 @@
+/dts-v1/;
+
+/ {
+ node1 {
+ };
+ prop;
+ node2 {
+ };
+};
diff --git a/dtc/tests/property_iterate.c b/dtc/tests/property_iterate.c
new file mode 100644
index 000000000..9a67f4911
--- /dev/null
+++ b/dtc/tests/property_iterate.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Tests that fdt_next_subnode() works as expected
+ *
+ * Copyright (C) 2013 Google, Inc
+ *
+ * Copyright (C) 2007 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void test_node(void *fdt, int parent_offset)
+{
+ uint32_t properties;
+ const fdt32_t *prop;
+ int offset, property;
+ int count;
+ int len;
+
+ /*
+ * This property indicates the number of properties in our
+ * test node to expect
+ */
+ prop = fdt_getprop(fdt, parent_offset, "test-properties", &len);
+ if (!prop || len != sizeof(fdt32_t)) {
+ FAIL("Missing/invalid test-properties property at '%s'",
+ fdt_get_name(fdt, parent_offset, NULL));
+ }
+ properties = fdt32_to_cpu(*prop);
+
+ count = 0;
+ offset = fdt_first_subnode(fdt, parent_offset);
+ if (offset < 0)
+ FAIL("Missing test node\n");
+
+ fdt_for_each_property_offset(property, fdt, offset)
+ count++;
+
+ if (count != properties) {
+ FAIL("Node '%s': Expected %d properties, got %d\n",
+ fdt_get_name(fdt, parent_offset, NULL), properties,
+ count);
+ }
+}
+
+static void check_fdt_next_subnode(void *fdt)
+{
+ int offset;
+ int count = 0;
+
+ fdt_for_each_subnode(offset, fdt, 0) {
+ test_node(fdt, offset);
+ count++;
+ }
+
+ if (count != 2)
+ FAIL("Expected %d tests, got %d\n", 2, count);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+ if (argc != 2)
+ CONFIG("Usage: %s <dtb file>", argv[0]);
+
+ fdt = load_blob(argv[1]);
+ if (!fdt)
+ FAIL("No device tree available");
+
+ check_fdt_next_subnode(fdt);
+
+ PASS();
+}
diff --git a/dtc/tests/property_iterate.dts b/dtc/tests/property_iterate.dts
new file mode 100644
index 000000000..e8f5f8f4f
--- /dev/null
+++ b/dtc/tests/property_iterate.dts
@@ -0,0 +1,23 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ test1 {
+ test-properties = <3>;
+
+ test {
+ linux,phandle = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ test2 {
+ test-properties = <0>;
+
+ test {
+ };
+ };
+};
diff --git a/dtc/tests/propname_escapes.c b/dtc/tests/propname_escapes.c
new file mode 100644
index 000000000..3e41e63b2
--- /dev/null
+++ b/dtc/tests/propname_escapes.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_getprop()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_getprop_cell(fdt, 0, "#address-cells", 1);
+ check_getprop_cell(fdt, 0, "#gpio-cells", 2);
+
+ PASS();
+}
diff --git a/dtc/tests/propname_escapes.dts b/dtc/tests/propname_escapes.dts
new file mode 100644
index 000000000..9f70618b9
--- /dev/null
+++ b/dtc/tests/propname_escapes.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ \#gpio-cells = <2>;
+};
diff --git a/dtc/tests/pylibfdt_tests.py b/dtc/tests/pylibfdt_tests.py
new file mode 100644
index 000000000..64b5bd125
--- /dev/null
+++ b/dtc/tests/pylibfdt_tests.py
@@ -0,0 +1,592 @@
+# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
+# pylibfdt - Tests for Flat Device Tree manipulation in Python
+# Copyright (C) 2017 Google, Inc.
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+import struct
+import sys
+import types
+import unittest
+
+sys.path.insert(0, '../pylibfdt')
+import libfdt
+from libfdt import Fdt, FdtSw, FdtException, QUIET_NOTFOUND, QUIET_ALL
+
+TEST_ADDR_1H = 0xdeadbeef
+TEST_ADDR_1L = 0x00000000
+TEST_ADDR_1 = (TEST_ADDR_1H << 32) | TEST_ADDR_1L
+TEST_ADDR_1 = 0x8000000000000000
+TEST_SIZE_1H = 0x00000000
+TEST_SIZE_1L = 0x00100000
+TEST_SIZE_1 = (TEST_SIZE_1H << 32) | TEST_SIZE_1L
+TEST_ADDR_2H = 0
+TEST_ADDR_2L = 123456789
+TEST_ADDR_2 = (TEST_ADDR_2H << 32) | TEST_ADDR_2L
+TEST_SIZE_2H = 0
+TEST_SIZE_2L = 0o10000
+TEST_SIZE_2 = (TEST_SIZE_2H << 32) | TEST_SIZE_2L
+
+TEST_VALUE_1 = 0xdeadbeef
+TEST_VALUE_2 = 123456789
+
+TEST_VALUE64_1H = 0xdeadbeef
+TEST_VALUE64_1L = 0x01abcdef
+TEST_VALUE64_1 = (TEST_VALUE64_1H << 32) | TEST_VALUE64_1L
+
+PHANDLE_1 = 0x2000
+PHANDLE_2 = 0x2001
+
+TEST_BYTES_1 = b'hello world'
+
+TEST_STRING_1 = 'hello world'
+TEST_STRING_2 = 'hi world'
+TEST_STRING_3 = u'unicode \u01d3'
+
+
+def get_err(err_code):
+ """Convert an error code into an error message
+
+ Args:
+ err_code: Error code value (FDT_ERR_...)
+
+ Returns:
+ String error code
+ """
+ return 'pylibfdt error %d: %s' % (-err_code, libfdt.strerror(-err_code))
+
+def _ReadFdt(fname):
+ """Read a device tree file into an Fdt object, ready for use
+
+ Args:
+ fname: Filename to read from
+
+ Returns:
+ Fdt bytearray suitable for passing to libfdt functions
+ """
+ with open(fname, mode='rb') as f:
+ return libfdt.Fdt(f.read())
+
+class PyLibfdtBasicTests(unittest.TestCase):
+ """Test class for basic pylibfdt access functions
+
+ Properties:
+ fdt: Device tree file used for testing
+ """
+
+ def setUp(self):
+ """Read in the device tree we use for testing"""
+ self.fdt = _ReadFdt('test_tree1.dtb')
+ self.fdt2 = _ReadFdt('test_props.dtb')
+ self.fdt3 = _ReadFdt('aliases.dtb')
+
+ def GetPropList(self, node_path):
+ """Read a list of properties from a node
+
+ Args:
+ node_path: Full path to node, e.g. '/subnode@1/subsubnode'
+
+ Returns:
+ List of property names for that node, e.g. ['compatible', 'reg']
+ """
+ prop_list = []
+ node = self.fdt.path_offset(node_path)
+ poffset = self.fdt.first_property_offset(node, QUIET_NOTFOUND)
+ while poffset > 0:
+ prop = self.fdt.get_property_by_offset(poffset)
+ prop_list.append(prop.name)
+ poffset = self.fdt.next_property_offset(poffset, QUIET_NOTFOUND)
+ return prop_list
+
+ def GetSubnodes(self, node_path):
+ """Read a list of subnodes from a node
+
+ Args:
+ node_path: Full path to node, e.g. '/subnode@1/subsubnode'
+
+ Returns:
+ List of subnode names for that node, e.g. ['subsubnode', 'ss1']
+ """
+ subnode_list = []
+ node = self.fdt.path_offset(node_path)
+ offset = self.fdt.first_subnode(node, QUIET_NOTFOUND)
+ while offset > 0:
+ name = self.fdt.get_name(offset)
+ subnode_list.append(name)
+ offset = self.fdt.next_subnode(offset, QUIET_NOTFOUND)
+ return subnode_list
+
+ def testImport(self):
+ """Check that we can import the library correctly"""
+ self.assertEqual(type(libfdt), types.ModuleType)
+
+ def testBadFdt(self):
+ """Check that a filename provided accidentally is not accepted"""
+ with self.assertRaises(FdtException) as e:
+ fdt = libfdt.Fdt(b'a string')
+ self.assertEqual(e.exception.err, -libfdt.BADMAGIC)
+
+ def testSubnodeOffset(self):
+ """check that we can locate a subnode by name"""
+ node1 = self.fdt.path_offset('/subnode@1')
+ self.assertEqual(self.fdt.subnode_offset(0, 'subnode@1'), node1)
+
+ with self.assertRaises(FdtException) as e:
+ self.fdt.subnode_offset(0, 'missing')
+ self.assertEqual(e.exception.err, -libfdt.NOTFOUND)
+
+ node2 = self.fdt.path_offset('/subnode@1/subsubnode')
+ self.assertEqual(self.fdt.subnode_offset(node1, 'subsubnode'), node2)
+
+ def testPathOffset(self):
+ """Check that we can find the offset of a node"""
+ self.assertEqual(self.fdt.path_offset('/'), 0)
+ self.assertTrue(self.fdt.path_offset('/subnode@1') > 0)
+ with self.assertRaises(FdtException) as e:
+ self.fdt.path_offset('/wibble')
+ self.assertEqual(e.exception.err, -libfdt.NOTFOUND)
+ self.assertEqual(self.fdt.path_offset('/wibble', QUIET_NOTFOUND),
+ -libfdt.NOTFOUND)
+
+ def testPropertyOffset(self):
+ """Walk through all the properties in the root node"""
+ offset = self.fdt.first_property_offset(0)
+ self.assertTrue(offset > 0)
+ for i in range(5):
+ next_offset = self.fdt.next_property_offset(offset)
+ self.assertTrue(next_offset > offset)
+ offset = next_offset
+ self.assertEqual(self.fdt.next_property_offset(offset, QUIET_NOTFOUND),
+ -libfdt.NOTFOUND)
+
+ def testPropertyOffsetExceptions(self):
+ """Check that exceptions are raised as expected"""
+ with self.assertRaises(FdtException) as e:
+ self.fdt.first_property_offset(107)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
+
+ # Quieten the NOTFOUND exception and check that a BADOFFSET
+ # exception is still raised.
+ with self.assertRaises(FdtException) as e:
+ self.fdt.first_property_offset(107, QUIET_NOTFOUND)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
+ with self.assertRaises(FdtException) as e:
+ self.fdt.next_property_offset(107, QUIET_NOTFOUND)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
+
+ # Check that NOTFOUND can be quietened.
+ node = self.fdt.path_offset('/subnode@1/ss1')
+ self.assertEqual(self.fdt.first_property_offset(node, QUIET_NOTFOUND),
+ -libfdt.NOTFOUND)
+ with self.assertRaises(FdtException) as e:
+ self.fdt.first_property_offset(node)
+ self.assertEqual(e.exception.err, -libfdt.NOTFOUND)
+
+ def testGetName(self):
+ """Check that we can get the name of a node"""
+ self.assertEqual(self.fdt.get_name(0), '')
+ node = self.fdt.path_offset('/subnode@1/subsubnode')
+ self.assertEqual(self.fdt.get_name(node), 'subsubnode')
+
+ with self.assertRaises(FdtException) as e:
+ self.fdt.get_name(-2)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
+
+ def testGetPropertyByOffset(self):
+ """Check that we can read the name and contents of a property"""
+ root = 0
+ poffset = self.fdt.first_property_offset(root)
+ prop = self.fdt.get_property_by_offset(poffset)
+ self.assertEqual(prop.name, 'compatible')
+ self.assertEqual(prop, b'test_tree1\0')
+
+ with self.assertRaises(FdtException) as e:
+ self.fdt.get_property_by_offset(-2)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
+ self.assertEqual(
+ -libfdt.BADOFFSET,
+ self.fdt.get_property_by_offset(-2, [libfdt.BADOFFSET]))
+
+ def testGetProp(self):
+ """Check that we can read the contents of a property by name"""
+ root = self.fdt.path_offset('/')
+ value = self.fdt.getprop(root, "compatible")
+ self.assertEqual(value, b'test_tree1\0')
+ self.assertEqual(-libfdt.NOTFOUND, self.fdt.getprop(root, 'missing',
+ QUIET_NOTFOUND))
+
+ with self.assertRaises(FdtException) as e:
+ self.fdt.getprop(root, 'missing')
+ self.assertEqual(e.exception.err, -libfdt.NOTFOUND)
+
+ node = self.fdt.path_offset('/subnode@1/subsubnode')
+ value = self.fdt.getprop(node, "compatible")
+ self.assertEqual(value, b'subsubnode1\0subsubnode\0')
+
+ def testStrError(self):
+ """Check that we can get an error string"""
+ self.assertEqual(libfdt.strerror(-libfdt.NOTFOUND),
+ 'FDT_ERR_NOTFOUND')
+
+ def testNextNodeOffset(self):
+ """Check that we can walk through nodes"""
+ node_list = []
+ node = 0
+ depth = 0
+ while depth >= 0:
+ node_list.append([depth, self.fdt.get_name(node)])
+ node, depth = self.fdt.next_node(node, depth, (libfdt.BADOFFSET,))
+ self.assertEqual(node_list, [
+ [0, ''],
+ [1, 'subnode@1'],
+ [2, 'subsubnode'],
+ [2, 'ss1'],
+ [1, 'subnode@2'],
+ [2, 'subsubnode@0'],
+ [2, 'ss2'],
+ ])
+
+ def testFirstNextSubnodeOffset(self):
+ """Check that we can walk through subnodes"""
+ node_list = []
+ node = self.fdt.first_subnode(0, QUIET_NOTFOUND)
+ while node >= 0:
+ node_list.append(self.fdt.get_name(node))
+ node = self.fdt.next_subnode(node, QUIET_NOTFOUND)
+ self.assertEqual(node_list, ['subnode@1', 'subnode@2'])
+
+ def testFirstNextSubnodeOffsetExceptions(self):
+ """Check except handling for first/next subnode functions"""
+ node = self.fdt.path_offset('/subnode@1/subsubnode', QUIET_NOTFOUND)
+ self.assertEqual(self.fdt.first_subnode(node, QUIET_NOTFOUND),
+ -libfdt.NOTFOUND)
+ with self.assertRaises(FdtException) as e:
+ self.fdt.first_subnode(node)
+ self.assertEqual(e.exception.err, -libfdt.NOTFOUND)
+
+ node = self.fdt.path_offset('/subnode@1/ss1', QUIET_NOTFOUND)
+ self.assertEqual(self.fdt.next_subnode(node, QUIET_NOTFOUND),
+ -libfdt.NOTFOUND)
+ with self.assertRaises(FdtException) as e:
+ self.fdt.next_subnode(node)
+ self.assertEqual(e.exception.err, -libfdt.NOTFOUND)
+
+ def testDeleteProperty(self):
+ """Test that we can delete a property"""
+ node_name = '/subnode@1'
+ self.assertEqual(self.GetPropList(node_name),
+ ['compatible', 'reg', 'prop-int'])
+ node = self.fdt.path_offset('/%s' % node_name)
+ self.assertEqual(self.fdt.delprop(node, 'reg'), 0)
+ self.assertEqual(self.GetPropList(node_name),
+ ['compatible', 'prop-int'])
+
+ def testHeader(self):
+ """Test that we can access the header values"""
+ self.assertEqual(self.fdt.magic(), 0xd00dfeed)
+ self.assertEqual(self.fdt.totalsize(), len(self.fdt._fdt))
+ self.assertEqual(self.fdt.off_dt_struct(), 88)
+ self.assertEqual(self.fdt.off_dt_strings(), 652)
+ self.assertEqual(self.fdt.off_mem_rsvmap(), 40)
+ self.assertEqual(self.fdt.version(), 17)
+ self.assertEqual(self.fdt.last_comp_version(), 16)
+ self.assertEqual(self.fdt.boot_cpuid_phys(), 0)
+ self.assertEqual(self.fdt.size_dt_strings(), 105)
+ self.assertEqual(self.fdt.size_dt_struct(), 564)
+
+ def testPack(self):
+ """Test that we can pack the tree after deleting something"""
+ orig_size = self.fdt.totalsize()
+ node = self.fdt.path_offset('/subnode@2', QUIET_NOTFOUND)
+ self.assertEqual(self.fdt.delprop(node, 'prop-int'), 0)
+ self.assertEqual(orig_size, self.fdt.totalsize())
+ self.assertEqual(self.fdt.pack(), 0)
+ self.assertTrue(self.fdt.totalsize() < orig_size)
+ self.assertEqual(self.fdt.totalsize(), len(self.fdt.as_bytearray()))
+
+ def testBadPropertyOffset(self):
+ """Test that bad property offsets are detected"""
+ with self.assertRaises(FdtException) as e:
+ self.fdt.get_property_by_offset(13)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
+ with self.assertRaises(FdtException) as e:
+ self.fdt.first_property_offset(3)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
+ with self.assertRaises(FdtException) as e:
+ self.fdt.next_property_offset(3)
+ self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
+
+ def testBadPathOffset(self):
+ """Test that bad path names are detected"""
+ with self.assertRaisesRegex(FdtException, get_err(libfdt.BADPATH)):
+ self.fdt.path_offset('not-present')
+
+ def testQuietAll(self):
+ """Check that exceptions can be masked by QUIET_ALL"""
+ self.assertEqual(-libfdt.NOTFOUND,
+ self.fdt.path_offset('/missing', QUIET_ALL))
+ self.assertEqual(-libfdt.BADOFFSET,
+ self.fdt.get_property_by_offset(13, QUIET_ALL))
+ self.assertEqual(-libfdt.BADPATH,
+ self.fdt.path_offset('missing', QUIET_ALL))
+
+ def testIntegers(self):
+ """Check that integers can be passed and returned"""
+ self.assertEqual(0, libfdt.fdt_get_phandle(self.fdt._fdt, 0))
+ node2 = self.fdt.path_offset('/subnode@2')
+ self.assertEqual(0x2000, libfdt.fdt_get_phandle(self.fdt._fdt, node2))
+
+ def testGetPhandle(self):
+ """Test for the get_phandle() method"""
+ self.assertEqual(0, self.fdt.get_phandle(0))
+ node2 = self.fdt.path_offset('/subnode@2')
+ self.assertEqual(0x2000, self.fdt.get_phandle(node2))
+
+ def testGetAlias(self):
+ """Test for the get_alias() method"""
+ self.assertEqual("/subnode@1", self.fdt3.get_alias('s1'))
+ self.assertEqual("/subnode@1/subsubnode", self.fdt3.get_alias('ss1'))
+ self.assertEqual("/subnode@1/subsubnode/subsubsubnode", self.fdt3.get_alias('sss1'))
+
+ def testParentOffset(self):
+ """Test for the parent_offset() method"""
+ self.assertEqual(-libfdt.NOTFOUND,
+ self.fdt.parent_offset(0, QUIET_NOTFOUND))
+ with self.assertRaises(FdtException) as e:
+ self.fdt.parent_offset(0)
+ self.assertEqual(e.exception.err, -libfdt.NOTFOUND)
+
+ node1 = self.fdt.path_offset('/subnode@2')
+ self.assertEqual(0, self.fdt.parent_offset(node1))
+ node2 = self.fdt.path_offset('/subnode@2/subsubnode@0')
+ self.assertEqual(node1, self.fdt.parent_offset(node2))
+
+ def testNodeOffsetByPhandle(self):
+ """Test for the node_offset_by_phandle() method"""
+ self.assertEqual(-libfdt.NOTFOUND,
+ self.fdt.node_offset_by_phandle(1, QUIET_NOTFOUND))
+ node1 = self.fdt.path_offset('/subnode@2')
+ self.assertEqual(node1, self.fdt.node_offset_by_phandle(0x2000))
+ node2 = self.fdt.path_offset('/subnode@2/subsubnode@0')
+ self.assertEqual(node2, self.fdt.node_offset_by_phandle(0x2001))
+
+ def get_prop(self, name):
+ return self.fdt2.getprop(0, name)
+
+ def testGetIntProperties(self):
+ """Test that we can access properties as integers"""
+ self.assertEqual(0xdeadbeef, self.get_prop("prop-hex32").as_uint32())
+ self.assertEqual(123, self.get_prop("prop-uint32").as_uint32())
+ self.assertEqual(-2, self.get_prop("prop-int32").as_int32())
+ self.assertEqual(9223372036854775807,
+ self.get_prop("prop-uint64").as_uint64())
+ self.assertEqual(-2, self.get_prop("prop-int64").as_int64())
+
+ def testReserveMap(self):
+ """Test that we can access the memory reserve map"""
+ self.assertEqual(2, self.fdt.num_mem_rsv())
+ self.assertEqual([ 0xdeadbeef00000000, 0x100000],
+ self.fdt.get_mem_rsv(0))
+ self.assertEqual([123456789, 0o10000], self.fdt.get_mem_rsv(1))
+
+ def testEmpty(self):
+ """Test that we can create an empty tree"""
+ self.assertEqual(-libfdt.NOSPACE,
+ Fdt.create_empty_tree(1, (libfdt.NOSPACE,)))
+ fdt = Fdt.create_empty_tree(128)
+ self.assertEqual(128, fdt.totalsize())
+
+ def testOpenInto(self):
+ """Test that we can resize a tree"""
+ fdt = Fdt.create_empty_tree(128)
+ self.assertEqual(128, fdt.totalsize())
+ fdt.resize(256)
+ self.assertEqual(256, fdt.totalsize())
+ fdt.pack()
+ self.assertTrue(fdt.totalsize() < 128)
+
+ def testSetProp(self):
+ """Test that we can update and create properties"""
+ node = self.fdt.path_offset('/subnode@1')
+ self.fdt.setprop(node, 'compatible', TEST_BYTES_1)
+ self.assertEqual(TEST_BYTES_1, self.fdt.getprop(node, 'compatible'))
+
+ # Check that this property is missing, and that we don't have space to
+ # add it
+ self.assertEqual(-libfdt.NOTFOUND,
+ self.fdt.getprop(node, 'missing', QUIET_NOTFOUND))
+ self.assertEqual(-libfdt.NOSPACE,
+ self.fdt.setprop(node, 'missing', TEST_BYTES_1,
+ quiet=(libfdt.NOSPACE,)))
+
+ # Expand the device tree so we now have room
+ self.fdt.resize(self.fdt.totalsize() + 50)
+ self.fdt.setprop(node, 'missing', TEST_BYTES_1)
+ self.assertEqual(TEST_BYTES_1, self.fdt.getprop(node, 'missing'))
+
+ def testSetPropU32(self):
+ """Test that we can update and create integer properties"""
+ node = 0
+ prop = 'prop-int'
+ self.fdt.setprop_u32(node, prop, TEST_VALUE_1)
+ self.assertEqual(struct.pack('>I', TEST_VALUE_1),
+ self.fdt.getprop(node, prop))
+
+ def testSetPropU64(self):
+ """Test that we can update and create integer properties"""
+ node = 0
+ prop = 'prop-int64'
+ self.fdt.setprop_u64(node, prop, TEST_VALUE64_1)
+ self.assertEqual(struct.pack('>Q', TEST_VALUE64_1),
+ self.fdt.getprop(node, prop))
+
+ def testSetPropStr(self):
+ """Test that we can set a property to a particular string"""
+ node = 0
+ prop = 'prop-str'
+ self.assertEqual(TEST_STRING_1, self.fdt.getprop(node, prop).as_str())
+ self.fdt.setprop_str(node, prop, TEST_STRING_2)
+ self.assertEqual(TEST_STRING_2, self.fdt.getprop(node, prop).as_str())
+ with self.assertRaises(ValueError) as e:
+ self.fdt.getprop(node, 'prop-int').as_str()
+ self.assertIn('lacks nul termination', str(e.exception))
+
+ node2 = self.fdt.path_offset('/subnode@1/subsubnode')
+ with self.assertRaises(ValueError) as e:
+ self.fdt.getprop(node2, 'compatible').as_str()
+ self.assertIn('embedded nul', str(e.exception))
+
+ # Expand the device tree so we now have room
+ self.fdt.resize(self.fdt.totalsize() + 50)
+ prop = 'prop-unicode'
+ self.fdt.setprop_str(node, prop, TEST_STRING_3)
+ self.assertEqual(TEST_STRING_3,
+ self.fdt.getprop(node, prop).as_str())
+
+ def testSetName(self):
+ """Test that we can update a node name"""
+ node = self.fdt.path_offset('/subnode@1')
+ old_val = self.fdt.get_name(node)
+ self.fdt.set_name(node, 'test')
+ self.assertEqual('test', self.fdt.get_name(node))
+
+ with self.assertRaises(ValueError) as e:
+ self.fdt.set_name(node, 'some\0name')
+ self.assertIn('embedded nul', str(e.exception))
+
+ with self.assertRaises(ValueError) as e:
+ self.fdt.set_name(node, 'name\0')
+ self.assertIn('embedded nul', str(e.exception))
+
+ def testAddDeleteNodes(self):
+ """Test that we can add and delete nodes"""
+ node_name = '/subnode@1'
+ self.assertEqual(self.GetSubnodes(node_name), ['subsubnode', 'ss1'])
+ node = self.fdt.path_offset('%s/subsubnode' % node_name)
+ self.assertEqual(self.fdt.del_node(node, 'subsubnode'), 0)
+ self.assertEqual(self.GetSubnodes(node_name), ['ss1'])
+
+ node = self.fdt.path_offset(node_name)
+ offset = self.fdt.add_subnode(node, 'more')
+ self.assertTrue(offset > 0)
+ self.assertEqual(self.GetSubnodes(node_name), ['more', 'ss1'])
+
+
+class PyLibfdtSwTests(unittest.TestCase):
+ """Test class for pylibfdt sequential-write DT creation
+ """
+ def assertOk(self, err_code):
+ self.assertEqual(0, err_code)
+
+ def testCreate(self):
+ # First check the minimum size and also the FdtSw() constructor
+ with self.assertRaisesRegex(FdtException, get_err(libfdt.NOSPACE)):
+ self.assertEqual(-libfdt.NOSPACE, FdtSw(3))
+
+ sw = FdtSw()
+ sw.add_reservemap_entry(TEST_ADDR_1, TEST_SIZE_1)
+ sw.add_reservemap_entry(TEST_ADDR_2, TEST_SIZE_2)
+ sw.finish_reservemap()
+
+ sw.begin_node('')
+ sw.property_string('compatible', 'test_tree1')
+ sw.property_u32('prop-int', TEST_VALUE_1)
+
+ sw.property_u32('prop-int', TEST_VALUE_1)
+ sw.property_u64('prop-int64', TEST_VALUE64_1)
+ sw.property_string('prop-str', TEST_STRING_1)
+ sw.property_u32('#address-cells', 1)
+ sw.property_u32('#size-cells', 0)
+
+ sw.begin_node('subnode@1')
+ sw.property_string('compatible', 'subnode1')
+ sw.property_u32('reg', 1)
+ sw.property_cell('prop-int', TEST_VALUE_1)
+ sw.property('data', b'\x00data\x01')
+ sw.begin_node('subsubnode')
+ sw.property('compatible', b'subsubnode1\0subsubnode')
+ sw.property_cell('prop-int', TEST_VALUE_1)
+ sw.end_node()
+ sw.begin_node('ss1')
+ sw.end_node()
+ sw.end_node()
+
+ for i in range(2, 11):
+ with sw.add_node('subnode@%d' % i):
+ sw.property_u32('reg', 2)
+ sw.property_cell('linux,phandle', PHANDLE_1)
+ sw.property_cell('prop-int', TEST_VALUE_2)
+ sw.property_u32('#address-cells', 1)
+ sw.property_u32('#size-cells', 0)
+ with sw.add_node('subsubnode@0'):
+ sw.property_u32('reg', 0)
+ sw.property_cell('phandle', PHANDLE_2)
+ sw.property('compatible', b'subsubnode2\0subsubnode')
+ sw.property_cell('prop-int', TEST_VALUE_2)
+ with sw.add_node('ss2'):
+ pass
+ sw.end_node()
+
+ fdt = sw.as_fdt()
+ self.assertEqual(2, fdt.num_mem_rsv())
+ self.assertEqual([TEST_ADDR_1, TEST_SIZE_1], fdt.get_mem_rsv(0))
+
+ # Make sure we can add a few more things
+ with sw.add_node('another'):
+ sw.property_u32('reg', 3)
+
+ # Make sure we can read from the tree too
+ node = sw.path_offset('/subnode@1')
+ self.assertEqual(b'subnode1\0', sw.getprop(node, 'compatible'))
+
+ # Make sure we did at least two resizes
+ self.assertTrue(len(fdt.as_bytearray()) > FdtSw.INC_SIZE * 2)
+
+
+class PyLibfdtRoTests(unittest.TestCase):
+ """Test class for read-only pylibfdt access functions
+
+ This just tests a few simple cases. Most of the tests are in
+ PyLibfdtBasicTests.
+
+ Properties:
+ fdt: Device tree file used for testing
+ """
+
+ def setUp(self):
+ """Read in the device tree we use for testing"""
+ with open('test_tree1.dtb', mode='rb') as f:
+ self.fdt = libfdt.FdtRo(f.read())
+
+ def testAccess(self):
+ """Basic sanity check for the FdtRo class"""
+ node = self.fdt.path_offset('/subnode@1')
+ self.assertEqual(b'subnode1\0',
+ self.fdt.getprop(node, 'compatible'))
+ node = self.fdt.first_subnode(node)
+ self.assertEqual(b'this is a placeholder string\0string2\0',
+ self.fdt.getprop(node, 'placeholder'))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/dtc/tests/references.c b/dtc/tests/references.c
new file mode 100644
index 000000000..d18e72250
--- /dev/null
+++ b/dtc/tests/references.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for phandle references in dtc
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check_ref(const void *fdt, int node, uint32_t checkref)
+{
+ const fdt32_t *p;
+ uint32_t ref;
+ int len;
+
+ p = fdt_getprop(fdt, node, "ref", &len);
+ if (!p)
+ FAIL("fdt_getprop(%d, \"ref\"): %s", node, fdt_strerror(len));
+ if (len != sizeof(*p))
+ FAIL("'ref' in node at %d has wrong size (%d instead of %zd)",
+ node, len, sizeof(*p));
+ ref = fdt32_to_cpu(*p);
+ if (ref != checkref)
+ FAIL("'ref' in node at %d has value 0x%x instead of 0x%x",
+ node, ref, checkref);
+
+ p = fdt_getprop(fdt, node, "lref", &len);
+ if (!p)
+ FAIL("fdt_getprop(%d, \"lref\"): %s", node, fdt_strerror(len));
+ if (len != sizeof(*p))
+ FAIL("'lref' in node at %d has wrong size (%d instead of %zd)",
+ node, len, sizeof(*p));
+ ref = fdt32_to_cpu(*p);
+ if (ref != checkref)
+ FAIL("'lref' in node at %d has value 0x%x instead of 0x%x",
+ node, ref, checkref);
+}
+
+static void check_rref(const void *fdt)
+{
+ const fdt32_t *p;
+ uint32_t ref;
+ int len;
+
+ p = fdt_getprop(fdt, 0, "rref", &len);
+ if (!p)
+ FAIL("fdt_getprop(0, \"rref\"): %s", fdt_strerror(len));
+ if (len != sizeof(*p))
+ FAIL("'rref' in root node has wrong size (%d instead of %zd)",
+ len, sizeof(*p));
+ ref = fdt32_to_cpu(*p);
+ if (ref != fdt_get_phandle(fdt, 0))
+ FAIL("'rref' in root node has value 0x%x instead of 0x0", ref);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int n1, n2, n3, n4, n5, n6, err;
+ uint32_t h1, h2, h4, h5, h6, hn;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ n1 = fdt_path_offset(fdt, "/node1");
+ if (n1 < 0)
+ FAIL("fdt_path_offset(/node1): %s", fdt_strerror(n1));
+ n2 = fdt_path_offset(fdt, "/node2");
+ if (n2 < 0)
+ FAIL("fdt_path_offset(/node2): %s", fdt_strerror(n2));
+ n3 = fdt_path_offset(fdt, "/node3");
+ if (n3 < 0)
+ FAIL("fdt_path_offset(/node3): %s", fdt_strerror(n3));
+ n4 = fdt_path_offset(fdt, "/node4");
+ if (n4 < 0)
+ FAIL("fdt_path_offset(/node4): %s", fdt_strerror(n4));
+ n5 = fdt_path_offset(fdt, "/node5");
+ if (n5 < 0)
+ FAIL("fdt_path_offset(/node5): %s", fdt_strerror(n5));
+ n6 = fdt_path_offset(fdt, "/node6");
+ if (n6 < 0)
+ FAIL("fdt_path_offset(/node6): %s", fdt_strerror(n6));
+
+ h1 = fdt_get_phandle(fdt, n1);
+ h2 = fdt_get_phandle(fdt, n2);
+ h4 = fdt_get_phandle(fdt, n4);
+ h5 = fdt_get_phandle(fdt, n5);
+ h6 = fdt_get_phandle(fdt, n6);
+
+ if (h1 != 0x2000)
+ FAIL("/node1 has wrong phandle, 0x%x instead of 0x%x",
+ h1, 0x2000);
+ if (h2 != 0x1)
+ FAIL("/node2 has wrong phandle, 0x%x instead of 0x%x",
+ h2, 0x1);
+ if (h6 != FDT_MAX_PHANDLE)
+ FAIL("/node6 has wrong phandle, 0x%x instead of 0x%x",
+ h6, FDT_MAX_PHANDLE);
+ if ((h4 == 0x2000) || (h4 == 0x1) || (h4 == 0))
+ FAIL("/node4 has bad phandle, 0x%x", h4);
+
+ if ((h5 == 0) || (h5 == -1))
+ FAIL("/node5 has bad phandle, 0x%x", h5);
+ if ((h5 == h4) || (h5 == h2) || (h5 == h1))
+ FAIL("/node5 has duplicate phandle, 0x%x", h5);
+
+ /*
+ * /node6 has phandle FDT_MAX_PHANDLE, so fdt_generate_phandle() is
+ * expected to fail.
+ */
+ err = fdt_generate_phandle(fdt, &hn);
+ if (err != -FDT_ERR_NOPHANDLES)
+ FAIL("generated invalid phandle 0x%x\n", hn);
+
+ check_ref(fdt, n1, h2);
+ check_ref(fdt, n2, h1);
+ check_ref(fdt, n3, h4);
+
+ check_rref(fdt);
+
+ PASS();
+}
diff --git a/dtc/tests/references.dts b/dtc/tests/references.dts
new file mode 100644
index 000000000..b39063999
--- /dev/null
+++ b/dtc/tests/references.dts
@@ -0,0 +1,41 @@
+/dts-v1/;
+
+/ {
+ rref = <&{/}>;
+
+ /* Explicit phandles */
+ n1: node1 {
+ linux,phandle = <0x2000>;
+ ref = <&{/node2}>; /* reference precedes target */
+ lref = <&n2>;
+ };
+ n2: node2 {
+ phandle = <0x1>;
+ ref = <&{/node1}>; /* reference after target */
+ lref = <&n1>;
+ };
+
+ /* Implicit phandles */
+ n3: node3 {
+ ref = <&{/node4}>;
+ lref = <&n4>;
+ };
+ n4: node4 {
+ };
+
+ /* Explicit phandle with implicit value */
+ /* This self-reference is the standard way to tag a node as requiring
+ * a phandle (perhaps for reference by nodes that will be dynamically
+ * added) without explicitly allocating it a phandle.
+ * The self-reference requires some special internal handling, though
+ * so check it actually works */
+ n5: node5 {
+ linux,phandle = <&n5>;
+ phandle = <&n5>;
+ };
+
+ node6 {
+ linux,phandle = <0xfffffffe>;
+ phandle = <0xfffffffe>;
+ };
+};
diff --git a/dtc/tests/reg-ranges-root.dts b/dtc/tests/reg-ranges-root.dts
new file mode 100644
index 000000000..9935b415f
--- /dev/null
+++ b/dtc/tests/reg-ranges-root.dts
@@ -0,0 +1,8 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x1000 0x10>;
+ ranges = <0x1000 0x2000 0x1000>;
+};
diff --git a/dtc/tests/reg-without-unit-addr.dts b/dtc/tests/reg-without-unit-addr.dts
new file mode 100644
index 000000000..aaf8af7a8
--- /dev/null
+++ b/dtc/tests/reg-without-unit-addr.dts
@@ -0,0 +1,10 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ node {
+ reg = <0 1>;
+ };
+};
diff --git a/dtc/tests/reuse-label.dts b/dtc/tests/reuse-label.dts
new file mode 100644
index 000000000..98b5ca9dc
--- /dev/null
+++ b/dtc/tests/reuse-label.dts
@@ -0,0 +1,15 @@
+/dts-v1/;
+
+/ {
+ label: property1 = "foo";
+ label: property2 = "bar";
+
+ test1 = &label;
+
+ label: node1 {
+ prop = "foo";
+ };
+ label: node2 {
+ prop = "bar";
+ };
+};
diff --git a/dtc/tests/reuse-label1.dts b/dtc/tests/reuse-label1.dts
new file mode 100644
index 000000000..f22956932
--- /dev/null
+++ b/dtc/tests/reuse-label1.dts
@@ -0,0 +1,10 @@
+/dts-v1/;
+
+/ {
+ label: node1 {
+ prop = "foo";
+ };
+ label: node2 {
+ prop = "bar";
+ };
+};
diff --git a/dtc/tests/reuse-label2.dts b/dtc/tests/reuse-label2.dts
new file mode 100644
index 000000000..01ea6b27f
--- /dev/null
+++ b/dtc/tests/reuse-label2.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/ {
+ label: property1 = "foo";
+ label: property2 = "bar";
+};
diff --git a/dtc/tests/reuse-label3.dts b/dtc/tests/reuse-label3.dts
new file mode 100644
index 000000000..fa3d2c72a
--- /dev/null
+++ b/dtc/tests/reuse-label3.dts
@@ -0,0 +1,9 @@
+/dts-v1/;
+
+/ {
+ label: property = "foo";
+
+ label: node {
+ property = "foo";
+ };
+};
diff --git a/dtc/tests/reuse-label4.dts b/dtc/tests/reuse-label4.dts
new file mode 100644
index 000000000..6805de322
--- /dev/null
+++ b/dtc/tests/reuse-label4.dts
@@ -0,0 +1,5 @@
+/dts-v1/;
+
+/ {
+ property = label: "foo" label:;
+};
diff --git a/dtc/tests/reuse-label5.dts b/dtc/tests/reuse-label5.dts
new file mode 100644
index 000000000..b7238e64a
--- /dev/null
+++ b/dtc/tests/reuse-label5.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/ {
+ prop1 = label: "foo";
+ prop2 = "bar" label:;
+};
diff --git a/dtc/tests/reuse-label6.dts b/dtc/tests/reuse-label6.dts
new file mode 100644
index 000000000..f5d507c6d
--- /dev/null
+++ b/dtc/tests/reuse-label6.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/ {
+ label: prop1 = "foo";
+ prop2 = "bar" label:;
+};
diff --git a/dtc/tests/root_node.c b/dtc/tests/root_node.c
new file mode 100644
index 000000000..37e6f0590
--- /dev/null
+++ b/dtc/tests/root_node.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Basic testcase for read-only access
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ const struct fdt_node_header *nh;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ nh = fdt_offset_ptr(fdt, 0, sizeof(*nh));
+
+ if (! nh)
+ FAIL("NULL retrieving root node");
+
+ if (fdt32_to_cpu(nh->tag) != FDT_BEGIN_NODE)
+ FAIL("Wrong tag on root node");
+
+ if (strlen(nh->name) != 0)
+ FAIL("Wrong name for root node, \"%s\" instead of empty",
+ nh->name);
+
+ PASS();
+}
diff --git a/dtc/tests/run_tests.sh b/dtc/tests/run_tests.sh
new file mode 100755
index 000000000..0e270feb3
--- /dev/null
+++ b/dtc/tests/run_tests.sh
@@ -0,0 +1,1104 @@
+#! /bin/sh
+
+SRCDIR=`dirname "$0"`
+. "$SRCDIR/testutils.sh"
+
+if [ -z "$CC" ]; then
+ CC=cc
+fi
+
+if [ -z "$PYTHON" ]; then
+ PYTHON=python3
+fi
+
+if [ -n "$NO_PYTHON" ]; then
+ if [ "$NO_PYTHON" != "0" ]; then
+ no_python=true
+ else
+ no_python=false
+ fi
+else
+ if [ -f ../pylibfdt/_libfdt.so ] || [ -f ../pylibfdt/_libfdt.cpython-3*.so ]; then
+ no_python=false
+ else
+ no_python=true
+ fi
+fi
+
+if [ -n "$NO_YAML" ]; then
+ if [ "$NO_YAML" != "0" ]; then
+ no_yaml=true
+ else
+ no_yaml=false
+ fi
+else
+ if pkg-config --exists yaml-0.1; then
+ no_yaml=false
+ else
+ no_yaml=true
+ fi
+fi
+
+# stat differs between platforms
+if [ -z "$STATSZ" ]; then
+ stat --version 2>/dev/null | grep -q 'GNU'
+ GNUSTAT=$?
+ if [ "$GNUSTAT" -ne 0 ]; then
+ # Assume BSD stat if we can't detect as GNU stat
+ STATSZ="stat -f %Uz"
+ else
+ STATSZ="stat -c %s"
+ fi
+fi
+
+# Help things find the libfdt shared object
+if [ -z "$TEST_LIBDIR" ]; then
+ TEST_LIBDIR=../libfdt
+fi
+export LD_LIBRARY_PATH="$TEST_LIBDIR"
+
+export QUIET_TEST=1
+STOP_ON_FAIL=0
+
+export VALGRIND=
+VGCODE=126
+
+tot_tests=0
+tot_pass=0
+tot_fail=0
+tot_config=0
+tot_vg=0
+tot_strange=0
+
+base_run_test() {
+ tot_tests=$((tot_tests + 1))
+ if VALGRIND="$VALGRIND" "$@"; then
+ tot_pass=$((tot_pass + 1))
+ else
+ ret="$?"
+ if [ "$STOP_ON_FAIL" -eq 1 ]; then
+ exit 1
+ fi
+ if [ "$ret" -eq 1 ]; then
+ tot_config=$((tot_config + 1))
+ elif [ "$ret" -eq 2 ]; then
+ tot_fail=$((tot_fail + 1))
+ elif [ "$ret" -eq $VGCODE ]; then
+ tot_vg=$((tot_vg + 1))
+ else
+ tot_strange=$((tot_strange + 1))
+ fi
+ fi
+}
+
+shorten_echo () {
+ limit=32
+ printf "$1"
+ shift
+ for x; do
+ if [ ${#x} -le $limit ]; then
+ printf " $x"
+ else
+ short=$(echo "$x" | head -c$limit)
+ printf " \"$short\"...<${#x} bytes>"
+ fi
+ done
+}
+
+run_test () {
+ printf "$*: "
+ if [ -n "$VALGRIND" -a -f $1.supp ]; then
+ VGSUPP="--suppressions=$1.supp"
+ fi
+ base_run_test $VALGRIND $VGSUPP "./$@"
+}
+
+run_sh_test () {
+ printf "$*: "
+ base_run_test sh "$@"
+}
+
+wrap_test () {
+ (
+ if verbose_run "$@"; then
+ PASS
+ else
+ ret="$?"
+ if [ "$ret" -gt 127 ]; then
+ signame=$(kill -l $((ret - 128)))
+ FAIL "Killed by SIG$signame"
+ elif [ "$ret" -eq $VGCODE ]; then
+ echo "VALGRIND ERROR"
+ exit $VGCODE
+ else
+ FAIL "Returned error code $ret"
+ fi
+ fi
+ )
+}
+
+run_wrap_test () {
+ shorten_echo "$@: "
+ base_run_test wrap_test "$@"
+}
+
+wrap_error () {
+ (
+ if verbose_run "$@"; then
+ FAIL "Expected non-zero return code"
+ else
+ ret="$?"
+ if [ "$ret" -gt 127 ]; then
+ signame=$(kill -l $((ret - 128)))
+ FAIL "Killed by SIG$signame"
+ else
+ PASS
+ fi
+ fi
+ )
+}
+
+run_wrap_error_test () {
+ shorten_echo "$@"
+ printf " {!= 0}: "
+ base_run_test wrap_error "$@"
+}
+
+# $1: dtb file
+# $2: align base
+check_align () {
+ shorten_echo "check_align $@: "
+ local size=$($STATSZ "$1")
+ local align="$2"
+ (
+ if [ $(($size % $align)) -eq 0 ] ;then
+ PASS
+ else
+ FAIL "Output size $size is not $align-byte aligned"
+ fi
+ )
+}
+
+run_dtc_test () {
+ printf "dtc $*: "
+ base_run_test wrap_test $VALGRIND $DTC "$@"
+}
+
+asm_to_so () {
+ $CC -shared -o $1.test.so "$SRCDIR/data.S" $1.test.s
+}
+
+asm_to_so_test () {
+ run_wrap_test asm_to_so "$@"
+}
+
+run_fdtget_test () {
+ expect="$1"
+ shift
+ printf "fdtget-runtest.sh %s $*: " "$(echo $expect)"
+ base_run_test sh "$SRCDIR/fdtget-runtest.sh" "$expect" "$@"
+}
+
+run_fdtput_test () {
+ expect="$1"
+ shift
+ shorten_echo fdtput-runtest.sh "$expect" "$@"
+ printf ": "
+ base_run_test sh "$SRCDIR/fdtput-runtest.sh" "$expect" "$@"
+}
+
+run_fdtdump_test() {
+ file="$1"
+ shorten_echo fdtdump-runtest.sh "$file"
+ printf ": "
+ base_run_test sh "$SRCDIR/fdtdump-runtest.sh" "$file" 2>/dev/null
+}
+
+run_fdtoverlay_test() {
+ expect="$1"
+ shift
+ shorten_echo fdtoverlay-runtest.sh "$expect" "$@"
+ printf ": "
+ base_run_test sh "$SRCDIR/fdtoverlay-runtest.sh" "$expect" "$@"
+}
+
+BAD_FIXUP_TREES="bad_index \
+ empty \
+ empty_index \
+ index_trailing \
+ path_empty_prop \
+ path_only \
+ path_only_sep \
+ path_prop"
+
+# Test to exercise libfdt overlay application without dtc's overlay support
+libfdt_overlay_tests () {
+ # First test a doctored overlay which requires only local fixups
+ run_dtc_test -I dts -O dtb -o overlay_base_no_symbols.test.dtb "$SRCDIR/overlay_base.dts"
+ run_test check_path overlay_base_no_symbols.test.dtb not-exists "/__symbols__"
+ run_test check_path overlay_base_no_symbols.test.dtb not-exists "/__fixups__"
+ run_test check_path overlay_base_no_symbols.test.dtb not-exists "/__local_fixups__"
+
+ run_dtc_test -I dts -O dtb -o overlay_overlay_no_fixups.test.dtb "$SRCDIR/overlay_overlay_no_fixups.dts"
+ run_test check_path overlay_overlay_no_fixups.test.dtb not-exists "/__symbols__"
+ run_test check_path overlay_overlay_no_fixups.test.dtb not-exists "/__fixups__"
+ run_test check_path overlay_overlay_no_fixups.test.dtb exists "/__local_fixups__"
+
+ run_test overlay overlay_base_no_symbols.test.dtb overlay_overlay_no_fixups.test.dtb
+
+ # Then test with manually constructed fixups
+ run_dtc_test -I dts -O dtb -o overlay_base_manual_symbols.test.dtb "$SRCDIR/overlay_base_manual_symbols.dts"
+ run_test check_path overlay_base_manual_symbols.test.dtb exists "/__symbols__"
+ run_test check_path overlay_base_manual_symbols.test.dtb not-exists "/__fixups__"
+ run_test check_path overlay_base_manual_symbols.test.dtb not-exists "/__local_fixups__"
+
+ run_dtc_test -I dts -O dtb -o overlay_overlay_manual_fixups.test.dtb "$SRCDIR/overlay_overlay_manual_fixups.dts"
+ run_test check_path overlay_overlay_manual_fixups.test.dtb not-exists "/__symbols__"
+ run_test check_path overlay_overlay_manual_fixups.test.dtb exists "/__fixups__"
+ run_test check_path overlay_overlay_manual_fixups.test.dtb exists "/__local_fixups__"
+
+ run_test overlay overlay_base_manual_symbols.test.dtb overlay_overlay_manual_fixups.test.dtb
+
+ # test simplified plugin syntax
+ run_dtc_test -@ -I dts -O dtb -o overlay_overlay_simple.dtb "$SRCDIR/overlay_overlay_simple.dts"
+
+ # verify non-generation of local fixups
+ run_test check_path overlay_overlay_simple.dtb not-exists "/__local_fixups__"
+
+ # Bad fixup tests
+ for test in $BAD_FIXUP_TREES; do
+ tree="overlay_bad_fixup_$test"
+ run_dtc_test -I dts -O dtb -o $tree.test.dtb "$SRCDIR/$tree.dts"
+ run_test overlay_bad_fixup overlay_base_no_symbols.test.dtb $tree.test.dtb
+ done
+}
+
+# Tests to exercise dtc's overlay generation support
+dtc_overlay_tests () {
+ # Overlay tests for dtc
+ run_dtc_test -@ -I dts -O dtb -o overlay_base.test.dtb "$SRCDIR/overlay_base.dts"
+ run_test check_path overlay_base.test.dtb exists "/__symbols__"
+ run_test check_path overlay_base.test.dtb not-exists "/__fixups__"
+ run_test check_path overlay_base.test.dtb not-exists "/__local_fixups__"
+
+ # With syntactic sugar
+ run_dtc_test -I dts -O dtb -o overlay_overlay.test.dtb "$SRCDIR/overlay_overlay.dts"
+ run_test check_path overlay_overlay.test.dtb not-exists "/__symbols__"
+ run_test check_path overlay_overlay.test.dtb exists "/__fixups__"
+ run_test check_path overlay_overlay.test.dtb exists "/__local_fixups__"
+
+ # Without syntactic sugar
+ run_dtc_test -I dts -O dtb -o overlay_overlay_nosugar.test.dtb "$SRCDIR/overlay_overlay_nosugar.dts"
+ run_test check_path overlay_overlay_nosugar.test.dtb not-exists "/__symbols__"
+ run_test check_path overlay_overlay_nosugar.test.dtb exists "/__fixups__"
+ run_test check_path overlay_overlay_nosugar.test.dtb exists "/__local_fixups__"
+
+ # Using target-path
+ run_dtc_test -I dts -O dtb -o overlay_overlay_bypath.test.dtb "$SRCDIR/overlay_overlay_bypath.dts"
+ run_test check_path overlay_overlay_bypath.test.dtb not-exists "/__symbols__"
+ run_test check_path overlay_overlay_bypath.test.dtb not-exists "/__fixups__"
+ run_test check_path overlay_overlay_bypath.test.dtb exists "/__local_fixups__"
+
+ # Make sure local target references are resolved and nodes are merged and that path references are not
+ run_dtc_test -I dts -O dtb -o overlay_overlay_local_merge.test.dtb "$SRCDIR/overlay_overlay_local_merge.dts"
+ run_test check_path overlay_overlay_local_merge.test.dtb exists "/fragment@0/__overlay__/new-node/new-merged-node"
+ run_test check_path overlay_overlay_local_merge.test.dtb exists "/fragment@1/__overlay__/new-root-node"
+
+ # Check building works the same as manual constructions
+ run_test dtbs_equal_ordered overlay_overlay.test.dtb overlay_overlay_nosugar.test.dtb
+
+ run_dtc_test -I dts -O dtb -o overlay_overlay_manual_fixups.test.dtb "$SRCDIR/overlay_overlay_manual_fixups.dts"
+ run_test dtbs_equal_ordered overlay_overlay.test.dtb overlay_overlay_manual_fixups.test.dtb
+
+ run_dtc_test -I dts -O dtb -o overlay_overlay_no_fixups.test.dtb "$SRCDIR/overlay_overlay_no_fixups.dts"
+ run_test dtbs_equal_ordered overlay_overlay_bypath.test.dtb overlay_overlay_no_fixups.test.dtb
+
+ # Check we can actually apply the result
+ run_dtc_test -I dts -O dtb -o overlay_base_no_symbols.test.dtb "$SRCDIR/overlay_base.dts"
+ run_test overlay overlay_base.test.dtb overlay_overlay.test.dtb
+ run_test overlay overlay_base_no_symbols.test.dtb overlay_overlay_bypath.test.dtb
+
+ # test plugin source to dtb and back
+ run_dtc_test -I dtb -O dts -o overlay_overlay_decompile.test.dts overlay_overlay.test.dtb
+ run_dtc_test -I dts -O dtb -o overlay_overlay_decompile.test.dtb overlay_overlay_decompile.test.dts
+ run_test dtbs_equal_ordered overlay_overlay.test.dtb overlay_overlay_decompile.test.dtb
+
+ # Test generation of aliases instead of symbols
+ run_dtc_test -A -I dts -O dtb -o overlay_base_with_aliases.dtb "$SRCDIR/overlay_base.dts"
+ run_test check_path overlay_base_with_aliases.dtb exists "/aliases"
+ run_test check_path overlay_base_with_aliases.dtb not-exists "/__symbols__"
+ run_test check_path overlay_base_with_aliases.dtb not-exists "/__fixups__"
+ run_test check_path overlay_base_with_aliases.dtb not-exists "/__local_fixups__"
+}
+
+tree1_tests () {
+ TREE=$1
+
+ # Read-only tests
+ run_test get_mem_rsv $TREE
+ run_test root_node $TREE
+ run_test find_property $TREE
+ run_test subnode_offset $TREE
+ run_test path_offset $TREE
+ run_test get_name $TREE
+ run_test getprop $TREE
+ run_test get_prop_offset $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
+
+ # Write-in-place tests
+ run_test setprop_inplace $TREE
+ run_test nop_property $TREE
+ run_test nop_node $TREE
+}
+
+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
+}
+
+check_tests () {
+ tree="$1"
+ shift
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" "$@" -- -I dts -O dtb $tree
+ run_dtc_test -I dts -O dtb -o $tree.test.dtb -f $tree
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" "$@" -- -I dtb -O dtb $tree.test.dtb
+}
+
+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 "$SRCDIR/addresses.dts"
+ run_test addr_size_cells addresses.test.dtb
+ run_dtc_test -I dts -O dtb -o addresses2.test.dtb "$SRCDIR/empty.dts"
+ run_test addr_size_cells2 addresses2.test.dtb
+
+ run_dtc_test -I dts -O dtb -o stringlist.test.dtb "$SRCDIR/stringlist.dts"
+ run_test stringlist stringlist.test.dtb
+
+ for flags in default no_name_dedup; do
+ # Sequential write tests
+ run_test sw_tree1 fixed $flags
+ tree1_tests sw_tree1.test.dtb
+ tree1_tests unfinished_tree1.test.dtb
+ run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb
+ run_test sw_states
+
+ # Resizing tests
+ for mode in resize realloc newalloc; do
+ run_test sw_tree1 $mode $flags
+ tree1_tests sw_tree1.test.dtb
+ tree1_tests unfinished_tree1.test.dtb
+ run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb
+ done
+ done
+
+ # fdt_move tests
+ for tree in test_tree1.dtb sw_tree1.test.dtb unfinished_tree1.test.dtb; do
+ rm -f moved.$tree shunted.$tree deshunted.$tree
+ run_test move_and_save $tree
+ run_test dtbs_equal_ordered $tree moved.$tree
+ run_test dtbs_equal_ordered $tree shunted.$tree
+ run_test dtbs_equal_ordered $tree deshunted.$tree
+ done
+
+ # v16 and alternate layout tests
+ for tree in test_tree1.dtb; do
+ for version in 17 16; do
+ for layout in $ALL_LAYOUTS; do
+ run_test mangle-layout $tree $version $layout
+ tree1_tests v$version.$layout.$tree
+ run_test dtbs_equal_ordered $tree v$version.$layout.$tree
+ done
+ done
+ done
+
+ # Read-write tests
+ for basetree in test_tree1.dtb; do
+ for version in 17 16; do
+ for layout in $ALL_LAYOUTS; do
+ tree=v$version.$layout.$basetree
+ rm -f opened.$tree repacked.$tree
+ run_test open_pack $tree
+ tree1_tests opened.$tree
+ tree1_tests repacked.$tree
+
+ tree1_tests_rw $tree
+ tree1_tests_rw opened.$tree
+ tree1_tests_rw repacked.$tree
+ done
+ done
+ done
+ run_test rw_tree1
+ tree1_tests rw_tree1.test.dtb
+ tree1_tests_rw rw_tree1.test.dtb
+ run_test appendprop1
+ run_test appendprop2 appendprop1.test.dtb
+ run_dtc_test -I dts -O dtb -o appendprop.test.dtb "$SRCDIR/appendprop.dts"
+ run_test dtbs_equal_ordered appendprop2.test.dtb appendprop.test.dtb
+ libfdt_overlay_tests
+
+ for basetree in test_tree1.dtb sw_tree1.test.dtb rw_tree1.test.dtb; do
+ run_test nopulate $basetree
+ run_test dtbs_equal_ordered $basetree noppy.$basetree
+ tree1_tests noppy.$basetree
+ tree1_tests_rw noppy.$basetree
+ done
+
+ run_test rw_oom
+
+ run_dtc_test -I dts -O dtb -o subnode_iterate.dtb "$SRCDIR/subnode_iterate.dts"
+ run_test subnode_iterate subnode_iterate.dtb
+
+ run_dtc_test -I dts -O dtb -o property_iterate.dtb "$SRCDIR/property_iterate.dts"
+ run_test property_iterate property_iterate.dtb
+
+ run_dtc_test -I dts -O dtb -o unit-addr-without-reg.dtb "$SRCDIR/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
+ run_test truncated_memrsv
+
+ # Check aliases support in fdt_path_offset
+ run_dtc_test -I dts -O dtb -o aliases.dtb "$SRCDIR/aliases.dts"
+ run_test get_alias aliases.dtb
+ run_test path_offset_aliases aliases.dtb
+
+ # Specific bug tests
+ run_test add_subnode_with_nops
+ run_dtc_test -I dts -O dts -o sourceoutput.test.dts "$SRCDIR/sourceoutput.dts"
+ run_dtc_test -I dts -O dtb -o sourceoutput.test.dtb "$SRCDIR/sourceoutput.dts"
+ run_dtc_test -I dts -O dtb -o sourceoutput.test.dts.test.dtb sourceoutput.test.dts
+ run_test dtbs_equal_ordered sourceoutput.test.dtb sourceoutput.test.dts.test.dtb
+
+ run_dtc_test -I dts -O dtb -o embedded_nul.test.dtb "$SRCDIR/embedded_nul.dts"
+ run_dtc_test -I dts -O dtb -o embedded_nul_equiv.test.dtb "$SRCDIR/embedded_nul_equiv.dts"
+ run_test dtbs_equal_ordered embedded_nul.test.dtb embedded_nul_equiv.test.dtb
+
+ run_dtc_test -I dts -O dtb "$SRCDIR/bad-size-cells.dts"
+
+ run_wrap_error_test $DTC division-by-zero.dts
+ run_wrap_error_test $DTC bad-octal-literal.dts
+ run_dtc_test -I dts -O dtb "$SRCDIR/nul-in-escape.dts"
+ run_wrap_error_test $DTC nul-in-line-info1.dts
+ run_wrap_error_test $DTC nul-in-line-info2.dts
+
+ run_wrap_error_test $DTC -I dtb -O dts -o /dev/null ovf_size_strings.dtb
+
+ run_test check_header test_tree1.dtb
+
+ FSBASE=fs
+ rm -rf $FSBASE
+ mkdir -p $FSBASE
+ run_test fs_tree1 $FSBASE/test_tree1
+ run_dtc_test -I fs -O dts -o fs.test_tree1.test.dts $FSBASE/test_tree1
+ run_dtc_test -I fs -O dtb -o fs.test_tree1.test.dtb $FSBASE/test_tree1
+ run_test dtbs_equal_unordered -m fs.test_tree1.test.dtb test_tree1.dtb
+
+ # check full tests
+ for good in test_tree1.dtb; do
+ run_test check_full $good
+ done
+ for bad in truncated_property.dtb truncated_string.dtb \
+ truncated_memrsv.dtb two_roots.dtb named_root.dtb; do
+ run_test check_full -n $bad
+ done
+}
+
+dtc_tests () {
+ run_dtc_test -I dts -O dtb -o dtc_tree1.test.dtb "$SRCDIR/test_tree1.dts"
+ tree1_tests dtc_tree1.test.dtb
+ tree1_tests_rw dtc_tree1.test.dtb
+ run_test dtbs_equal_ordered dtc_tree1.test.dtb test_tree1.dtb
+
+ run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb "$SRCDIR/propname_escapes.dts"
+ run_test propname_escapes dtc_escapes.test.dtb
+
+ run_dtc_test -I dts -O dtb -o line_directives.test.dtb "$SRCDIR/line_directives.dts"
+
+ run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb "$SRCDIR/escapes.dts"
+ run_test string_escapes dtc_escapes.test.dtb
+
+ run_dtc_test -I dts -O dtb -o dtc_char_literal.test.dtb "$SRCDIR/char_literal.dts"
+ run_test char_literal dtc_char_literal.test.dtb
+
+ run_dtc_test -I dts -O dtb -o dtc_sized_cells.test.dtb "$SRCDIR/sized_cells.dts"
+ run_test sized_cells dtc_sized_cells.test.dtb
+
+ run_dtc_test -I dts -O dtb -o dtc_extra-terminating-null.test.dtb "$SRCDIR/extra-terminating-null.dts"
+ run_test extra-terminating-null dtc_extra-terminating-null.test.dtb
+
+ run_dtc_test -I dts -O dtb -o dtc_references.test.dtb "$SRCDIR/references.dts"
+ run_test references dtc_references.test.dtb
+
+ run_dtc_test -I dts -O dtb -o dtc_path-references.test.dtb "$SRCDIR/path-references.dts"
+ run_test path-references dtc_path-references.test.dtb
+
+ run_test phandle_format dtc_references.test.dtb epapr
+ for f in legacy epapr both; do
+ run_dtc_test -I dts -O dtb -H $f -o dtc_references.test.$f.dtb "$SRCDIR/references.dts"
+ run_test phandle_format dtc_references.test.$f.dtb $f
+ done
+
+ run_dtc_test -I dts -O dtb -o multilabel.test.dtb "$SRCDIR/multilabel.dts"
+ run_test references multilabel.test.dtb
+
+ run_dtc_test -I dts -O dtb -o label_repeated.test.dtb "$SRCDIR/label_repeated.dts"
+
+ run_dtc_test -I dts -O dtb -o dtc_comments.test.dtb "$SRCDIR/comments.dts"
+ run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb "$SRCDIR/comments-cmp.dts"
+ run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb
+
+ # Check /include/ directive
+ run_dtc_test -I dts -O dtb -o includes.test.dtb "$SRCDIR/include0.dts"
+ run_test dtbs_equal_ordered includes.test.dtb test_tree1.dtb
+
+ # Check /incbin/ directive
+ run_dtc_test -I dts -O dtb -o incbin.test.dtb "$SRCDIR/incbin.dts"
+ run_test incbin "$SRCDIR/incbin.bin" incbin.test.dtb
+
+ # Check boot_cpuid_phys handling
+ run_dtc_test -I dts -O dtb -o boot_cpuid.test.dtb "$SRCDIR/boot-cpuid.dts"
+ run_test boot-cpuid boot_cpuid.test.dtb 16
+
+ run_dtc_test -I dts -O dtb -b 17 -o boot_cpuid_17.test.dtb "$SRCDIR/boot-cpuid.dts"
+ run_test boot-cpuid boot_cpuid_17.test.dtb 17
+
+ run_dtc_test -I dtb -O dtb -o preserve_boot_cpuid.test.dtb boot_cpuid.test.dtb
+ run_test boot-cpuid preserve_boot_cpuid.test.dtb 16
+ run_test dtbs_equal_ordered preserve_boot_cpuid.test.dtb boot_cpuid.test.dtb
+
+ run_dtc_test -I dtb -O dtb -o preserve_boot_cpuid_17.test.dtb boot_cpuid_17.test.dtb
+ run_test boot-cpuid preserve_boot_cpuid_17.test.dtb 17
+ run_test dtbs_equal_ordered preserve_boot_cpuid_17.test.dtb boot_cpuid_17.test.dtb
+
+ run_dtc_test -I dtb -O dtb -b17 -o override17_boot_cpuid.test.dtb boot_cpuid.test.dtb
+ run_test boot-cpuid override17_boot_cpuid.test.dtb 17
+
+ run_dtc_test -I dtb -O dtb -b0 -o override0_boot_cpuid_17.test.dtb boot_cpuid_17.test.dtb
+ run_test boot-cpuid override0_boot_cpuid_17.test.dtb 0
+
+
+ # Check -Oasm mode
+ for tree in test_tree1.dts escapes.dts references.dts path-references.dts \
+ comments.dts aliases.dts include0.dts incbin.dts \
+ value-labels.dts ; do
+ run_dtc_test -I dts -O asm -o oasm_$tree.test.s "$SRCDIR/$tree"
+ asm_to_so_test oasm_$tree
+ run_dtc_test -I dts -O dtb -o $tree.test.dtb "$SRCDIR/$tree"
+ run_test asm_tree_dump ./oasm_$tree.test.so oasm_$tree.test.dtb
+ run_wrap_test cmp oasm_$tree.test.dtb $tree.test.dtb
+ done
+
+ run_test value-labels ./oasm_value-labels.dts.test.so
+
+ # Check -Odts mode preserve all dtb information
+ for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb \
+ dtc_extra-terminating-null.test.dtb dtc_references.test.dtb; do
+ run_dtc_test -I dtb -O dts -o odts_$tree.test.dts $tree
+ run_dtc_test -I dts -O dtb -o odts_$tree.test.dtb odts_$tree.test.dts
+ run_test dtbs_equal_ordered $tree odts_$tree.test.dtb
+ done
+
+ # Check -Odts preserving type information
+ for tree in type-preservation.dts; do
+ run_dtc_test -I dts -O dts -o $tree.test.dts "$SRCDIR/$tree"
+ run_dtc_test -I dts -O dts $tree.test.dts
+ run_wrap_test cmp "$SRCDIR/$tree" $tree.test.dts
+ done
+ for tree in path-references; do
+ run_dtc_test -I dts -O dtb -o $tree.test.dtb "$SRCDIR/$tree.dts"
+ run_dtc_test -I dts -O dts -o $tree.test.dts "$SRCDIR/$tree.dts"
+ run_dtc_test -I dts -O dtb -o $tree.test.dts.test.dtb $tree.test.dts
+ run_test dtbs_equal_ordered $tree.test.dtb $tree.test.dts.test.dtb
+ done
+
+ # Check -Oyaml output
+ if ! $no_yaml; then
+ for tree in type-preservation; do
+ run_dtc_test -I dts -O yaml -o $tree.test.dt.yaml "$SRCDIR/$tree.dts"
+ run_wrap_test cmp "$SRCDIR/$tree.dt.yaml" $tree.test.dt.yaml
+ done
+ fi
+
+ # Check version conversions
+ for tree in test_tree1.dtb ; do
+ for aver in 1 2 3 16 17; do
+ atree="ov${aver}_$tree.test.dtb"
+ run_dtc_test -I dtb -O dtb -V$aver -o $atree $tree
+ for bver in 16 17; do
+ btree="ov${bver}_$atree"
+ run_dtc_test -I dtb -O dtb -V$bver -o $btree $atree
+ run_test dtbs_equal_ordered $btree $tree
+ done
+ done
+ done
+
+ # Check merge/overlay functionality
+ run_dtc_test -I dts -O dtb -o dtc_tree1_merge.test.dtb "$SRCDIR/test_tree1_merge.dts"
+ tree1_tests dtc_tree1_merge.test.dtb test_tree1.dtb
+ run_dtc_test -I dts -O dtb -o dtc_tree1_merge_labelled.test.dtb "$SRCDIR/test_tree1_merge_labelled.dts"
+ tree1_tests dtc_tree1_merge_labelled.test.dtb test_tree1.dtb
+ run_dtc_test -I dts -O dtb -o dtc_tree1_label_noderef.test.dtb "$SRCDIR/test_tree1_label_noderef.dts"
+ run_test dtbs_equal_unordered dtc_tree1_label_noderef.test.dtb test_tree1.dtb
+ run_dtc_test -I dts -O dtb -o multilabel_merge.test.dtb "$SRCDIR/multilabel_merge.dts"
+ run_test references multilabel.test.dtb
+ run_test dtbs_equal_ordered multilabel.test.dtb multilabel_merge.test.dtb
+ run_dtc_test -I dts -O dtb -o dtc_tree1_merge_path.test.dtb "$SRCDIR/test_tree1_merge_path.dts"
+ tree1_tests dtc_tree1_merge_path.test.dtb test_tree1.dtb
+ run_wrap_error_test $DTC -I dts -O dtb -o /dev/null "$SRCDIR/test_label_ref.dts"
+
+ # Check prop/node delete functionality
+ run_dtc_test -I dts -O dtb -o dtc_tree1_delete.test.dtb "$SRCDIR/test_tree1_delete.dts"
+ tree1_tests dtc_tree1_delete.test.dtb
+
+ # Check omit-if-no-ref functionality
+ run_dtc_test -I dts -O dtb -o omit-no-ref.test.dtb "$SRCDIR/omit-no-ref.dts"
+ run_test check_path omit-no-ref.test.dtb not-exists "/node1"
+ run_test check_path omit-no-ref.test.dtb not-exists "/node2"
+ run_test check_path omit-no-ref.test.dtb exists "/node3"
+ run_test check_path omit-no-ref.test.dtb exists "/node4"
+
+ run_dtc_test -I dts -O dts -o delete_reinstate_multilabel.dts.test.dts "$SRCDIR/delete_reinstate_multilabel.dts"
+ run_wrap_test cmp delete_reinstate_multilabel.dts.test.dts "$SRCDIR/delete_reinstate_multilabel_ref.dts"
+
+ # Check some checks
+ check_tests "$SRCDIR/dup-nodename.dts" duplicate_node_names
+ check_tests "$SRCDIR/dup-propname.dts" duplicate_property_names
+ check_tests "$SRCDIR/dup-phandle.dts" explicit_phandles
+ check_tests "$SRCDIR/zero-phandle.dts" explicit_phandles
+ check_tests "$SRCDIR/minusone-phandle.dts" explicit_phandles
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" phandle_references -- -I dts -O dtb "$SRCDIR/nonexist-node-ref.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" phandle_references -- -I dts -O dtb "$SRCDIR/nonexist-label-ref.dts"
+ run_sh_test "$SRCDIR/dtc-fatal.sh" -I dts -O dtb "$SRCDIR/nonexist-node-ref2.dts"
+ check_tests "$SRCDIR/bad-name-property.dts" name_properties
+
+ check_tests "$SRCDIR/bad-ncells.dts" address_cells_is_cell size_cells_is_cell interrupts_extended_is_cell
+ check_tests "$SRCDIR/bad-string-props.dts" device_type_is_string model_is_string status_is_string label_is_string compatible_is_string_list names_is_string_list
+ check_tests "$SRCDIR/bad-chosen.dts" chosen_node_is_root
+ check_tests "$SRCDIR/bad-chosen.dts" chosen_node_bootargs
+ check_tests "$SRCDIR/bad-chosen.dts" chosen_node_stdout_path
+ check_tests "$SRCDIR/bad-reg-ranges.dts" reg_format ranges_format
+ check_tests "$SRCDIR/bad-empty-ranges.dts" ranges_format
+ check_tests "$SRCDIR/reg-ranges-root.dts" reg_format ranges_format
+ check_tests "$SRCDIR/bad-dma-ranges.dts" dma_ranges_format
+ check_tests "$SRCDIR/default-addr-size.dts" avoid_default_addr_size
+ check_tests "$SRCDIR/obsolete-chosen-interrupt-controller.dts" obsolete_chosen_interrupt_controller
+ check_tests "$SRCDIR/reg-without-unit-addr.dts" unit_address_vs_reg
+ check_tests "$SRCDIR/unit-addr-without-reg.dts" unit_address_vs_reg
+ check_tests "$SRCDIR/unit-addr-leading-0x.dts" unit_address_format
+ check_tests "$SRCDIR/unit-addr-leading-0s.dts" unit_address_format
+ check_tests "$SRCDIR/unit-addr-unique.dts" unique_unit_address
+ check_tests "$SRCDIR/bad-phandle-cells.dts" interrupts_extended_property
+ check_tests "$SRCDIR/bad-gpio.dts" gpios_property
+ check_tests "$SRCDIR/good-gpio.dts" -n gpios_property
+ check_tests "$SRCDIR/bad-graph.dts" graph_child_address
+ check_tests "$SRCDIR/bad-graph.dts" graph_port
+ check_tests "$SRCDIR/bad-graph.dts" graph_endpoint
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/bad-gpio.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" -n deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/good-gpio.dts"
+ check_tests "$SRCDIR/bad-interrupt-cells.dts" interrupts_property
+ check_tests "$SRCDIR/bad-interrupt-controller.dts" interrupt_provider
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" node_name_chars -- -I dtb -O dtb bad_node_char.dtb
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" node_name_format -- -I dtb -O dtb bad_node_format.dtb
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" property_name_chars -- -I dtb -O dtb bad_prop_char.dtb
+
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label1.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label2.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label3.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label4.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label5.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" duplicate_label -- -I dts -O dtb "$SRCDIR/reuse-label6.dts"
+
+ run_test check_path test_tree1.dtb exists "/subnode@1"
+ run_test check_path test_tree1.dtb not-exists "/subnode@10"
+
+ check_tests "$SRCDIR/pci-bridge-ok.dts" -n pci_bridge
+ check_tests "$SRCDIR/pci-bridge-bad1.dts" pci_bridge
+ check_tests "$SRCDIR/pci-bridge-bad2.dts" pci_bridge
+
+ check_tests "$SRCDIR/unit-addr-simple-bus-reg-mismatch.dts" simple_bus_reg
+ check_tests "$SRCDIR/unit-addr-simple-bus-compatible.dts" simple_bus_reg
+
+
+ # Check warning options
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" address_cells_is_cell interrupts_extended_is_cell -n size_cells_is_cell -- -Wno_size_cells_is_cell -I dts -O dtb "$SRCDIR/bad-ncells.dts"
+ run_sh_test "$SRCDIR/dtc-fails.sh" -n test-warn-output.test.dtb -I dts -O dtb "$SRCDIR/bad-ncells.dts"
+ run_sh_test "$SRCDIR/dtc-fails.sh" test-error-output.test.dtb -I dts -O dtb bad-ncells.dts -Esize_cells_is_cell
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" always_fail -- -Walways_fail -I dts -O dtb "$SRCDIR/test_tree1.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" -n always_fail -- -Walways_fail -Wno_always_fail -I dts -O dtb "$SRCDIR/test_tree1.dts"
+ run_sh_test "$SRCDIR/dtc-fails.sh" test-negation-1.test.dtb -Ealways_fail -I dts -O dtb "$SRCDIR/test_tree1.dts"
+ run_sh_test "$SRCDIR/dtc-fails.sh" -n test-negation-2.test.dtb -Ealways_fail -Eno_always_fail -I dts -O dtb "$SRCDIR/test_tree1.dts"
+ run_sh_test "$SRCDIR/dtc-fails.sh" test-negation-3.test.dtb -Ealways_fail -Wno_always_fail -I dts -O dtb "$SRCDIR/test_tree1.dts"
+ run_sh_test "$SRCDIR/dtc-fails.sh" -n test-negation-4.test.dtb -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb "$SRCDIR/bad-ncells.dts"
+ run_sh_test "$SRCDIR/dtc-checkfails.sh" size_cells_is_cell -- -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb "$SRCDIR/bad-ncells.dts"
+
+ # Check for proper behaviour reading from stdin
+ run_dtc_test -I dts -O dtb -o stdin_dtc_tree1.test.dtb - < "$SRCDIR/test_tree1.dts"
+ run_wrap_test cmp stdin_dtc_tree1.test.dtb dtc_tree1.test.dtb
+ run_dtc_test -I dtb -O dts -o stdin_odts_test_tree1.dtb.test.dts - < test_tree1.dtb
+ run_wrap_test cmp stdin_odts_test_tree1.dtb.test.dts odts_test_tree1.dtb.test.dts
+
+ # Check integer expresisons
+ run_test integer-expressions -g integer-expressions.test.dts
+ run_dtc_test -I dts -O dtb -o integer-expressions.test.dtb integer-expressions.test.dts
+ run_test integer-expressions integer-expressions.test.dtb
+
+ # Check for graceful failure in some error conditions
+ run_sh_test "$SRCDIR/dtc-fatal.sh" -I dts -O dtb nosuchfile.dts
+ run_sh_test "$SRCDIR/dtc-fatal.sh" -I dtb -O dtb nosuchfile.dtb
+ run_sh_test "$SRCDIR/dtc-fatal.sh" -I fs -O dtb nosuchfile
+
+ # Dependencies
+ run_dtc_test -I dts -O dtb -o dependencies.test.dtb -d dependencies.test.d "$SRCDIR/dependencies.dts"
+ sed -i.bak "s,$SRCDIR/,,g" dependencies.test.d
+ run_wrap_test cmp dependencies.test.d "$SRCDIR/dependencies.cmp"
+
+ # Search paths
+ run_wrap_error_test $DTC -I dts -O dtb -o search_paths.dtb "$SRCDIR/search_paths.dts"
+ run_dtc_test -i "$SRCDIR/search_dir" -I dts -O dtb -o search_paths.dtb \
+ "$SRCDIR/search_paths.dts"
+ run_wrap_error_test $DTC -i "$SRCDIR/search_dir_b" -I dts -O dtb \
+ -o search_paths_b.dtb "$SRCDIR/search_paths_b.dts"
+ run_dtc_test -i "$SRCDIR/search_dir_b" -i "$SRCDIR/search_dir" -I dts -O dtb \
+ -o search_paths_b.dtb "$SRCDIR/search_paths_b.dts"
+ run_dtc_test -I dts -O dtb -o search_paths_subdir.dtb \
+ "$SRCDIR/search_dir_b/search_paths_subdir.dts"
+
+ # Check -a option
+ for align in 2 4 8 16 32 64; do
+ # -p -a
+ run_dtc_test -O dtb -p 1000 -a $align -o align0.dtb "$SRCDIR/subnode_iterate.dts"
+ base_run_test check_align align0.dtb $align
+ # -S -a
+ run_dtc_test -O dtb -S 1999 -a $align -o align1.dtb "$SRCDIR/subnode_iterate.dts"
+ base_run_test check_align align1.dtb $align
+ done
+
+ # Tests for overlay/plugin generation
+ dtc_overlay_tests
+}
+
+cmp_tests () {
+ basetree="$1"
+ shift
+ wrongtrees="$@"
+
+ run_test dtb_reverse $basetree
+
+ # First dtbs_equal_ordered
+ run_test dtbs_equal_ordered $basetree $basetree
+ run_test dtbs_equal_ordered -n $basetree $basetree.reversed.test.dtb
+ for tree in $wrongtrees; do
+ run_test dtbs_equal_ordered -n $basetree $tree
+ done
+
+ # now unordered
+ run_test dtbs_equal_unordered $basetree $basetree
+ run_test dtbs_equal_unordered $basetree $basetree.reversed.test.dtb
+ run_test dtbs_equal_unordered $basetree.reversed.test.dtb $basetree
+ for tree in $wrongtrees; do
+ run_test dtbs_equal_unordered -n $basetree $tree
+ done
+
+ # now dtc --sort
+ run_dtc_test -I dtb -O dtb -s -o $basetree.sorted.test.dtb $basetree
+ run_test dtbs_equal_unordered $basetree $basetree.sorted.test.dtb
+ run_dtc_test -I dtb -O dtb -s -o $basetree.reversed.sorted.test.dtb $basetree.reversed.test.dtb
+ run_test dtbs_equal_unordered $basetree.reversed.test.dtb $basetree.reversed.sorted.test.dtb
+ run_test dtbs_equal_ordered $basetree.sorted.test.dtb $basetree.reversed.sorted.test.dtb
+}
+
+dtbs_equal_tests () {
+ WRONG_TREE1=""
+ for x in 1 2 3 4 5 6 7 8 9; do
+ run_dtc_test -I dts -O dtb -o test_tree1_wrong$x.test.dtb "$SRCDIR/test_tree1_wrong$x.dts"
+ WRONG_TREE1="$WRONG_TREE1 test_tree1_wrong$x.test.dtb"
+ done
+ cmp_tests test_tree1.dtb $WRONG_TREE1
+}
+
+fdtget_tests () {
+ dts=label01.dts
+ dtb=$dts.fdtget.test.dtb
+ run_dtc_test -O dtb -o $dtb "$SRCDIR/$dts"
+
+ # run_fdtget_test <expected-result> [<flags>] <file> <node> <property>
+ run_fdtget_test "MyBoardName" $dtb / model
+ run_fdtget_test "MyBoardName MyBoardFamilyName" $dtb / compatible
+ run_fdtget_test "77 121 66 111 \
+97 114 100 78 97 109 101 0 77 121 66 111 97 114 100 70 97 109 105 \
+108 121 78 97 109 101 0" -t bu $dtb / compatible
+ run_fdtget_test "MyBoardName MyBoardFamilyName" -t s $dtb / compatible
+ run_fdtget_test 32768 $dtb /cpus/PowerPC,970@1 d-cache-size
+ run_fdtget_test 8000 -tx $dtb /cpus/PowerPC,970@1 d-cache-size
+ run_fdtget_test "61 62 63 0" -tbx $dtb /randomnode tricky1
+ run_fdtget_test "a b c d de ea ad be ef" -tbx $dtb /randomnode blob
+
+ # Here the property size is not a multiple of 4 bytes, so it should fail
+ run_wrap_error_test $DTGET -tlx $dtb /randomnode mixed
+ run_fdtget_test "6162 6300 1234 0 a 0 b 0 c" -thx $dtb /randomnode mixed
+ run_fdtget_test "61 62 63 0 12 34 0 0 0 a 0 0 0 b 0 0 0 c" \
+ -thhx $dtb /randomnode mixed
+ run_wrap_error_test $DTGET -ts $dtb /randomnode doctor-who
+
+ # Test multiple arguments
+ run_fdtget_test "MyBoardName\nmemory" -ts $dtb / model /memory device_type
+
+ # Test defaults
+ run_wrap_error_test $DTGET -tx $dtb /randomnode doctor-who
+ run_fdtget_test "<the dead silence>" -tx \
+ -d "<the dead silence>" $dtb /randomnode doctor-who
+ run_fdtget_test "<blink>" -tx -d "<blink>" $dtb /memory doctor-who
+}
+
+fdtput_tests () {
+ dts=label01.dts
+ dtb=$dts.fdtput.test.dtb
+ text="$SRCDIR/lorem.txt"
+
+ # Allow just enough space for $text
+ run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb "$SRCDIR/$dts"
+
+ # run_fdtput_test <expected-result> <file> <node> <property> <flags> <value>
+ run_fdtput_test "a_model" $dtb / model -ts "a_model"
+ run_fdtput_test "board1 board2" $dtb / compatible -ts board1 board2
+ run_fdtput_test "board1 board2" $dtb / compatible -ts "board1 board2"
+ run_fdtput_test "32768" $dtb /cpus/PowerPC,970@1 d-cache-size "" "32768"
+ run_fdtput_test "8001" $dtb /cpus/PowerPC,970@1 d-cache-size -tx 0x8001
+ run_fdtput_test "2 3 12" $dtb /randomnode tricky1 -tbi "02 003 12"
+ run_fdtput_test "a b c ea ad be ef" $dtb /randomnode blob \
+ -tbx "a b c ea ad be ef"
+ run_fdtput_test "a0b0c0d deeaae ef000000" $dtb /randomnode blob \
+ -tx "a0b0c0d deeaae ef000000"
+ run_fdtput_test "$(cat $text)" $dtb /randomnode blob -ts "$(cat $text)"
+
+ # Test expansion of the blob when insufficient room for property
+ run_fdtput_test "$(cat $text $text)" $dtb /randomnode blob -ts "$(cat $text $text)"
+
+ # Start again with a fresh dtb
+ run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb "$SRCDIR/$dts"
+
+ # Node creation
+ run_wrap_error_test $DTPUT $dtb -c /baldrick sod
+ run_wrap_test $DTPUT $dtb -c /chosen/son /chosen/daughter
+ run_fdtput_test "eva" $dtb /chosen/daughter name "" -ts "eva"
+ run_fdtput_test "adam" $dtb /chosen/son name "" -ts "adam"
+
+ # Not allowed to create an existing node
+ run_wrap_error_test $DTPUT $dtb -c /chosen
+ run_wrap_error_test $DTPUT $dtb -c /chosen/son
+
+ # Automatic node creation
+ run_wrap_test $DTPUT $dtb -cp /blackadder/the-second/turnip \
+ /blackadder/the-second/potato
+ run_fdtput_test 1000 $dtb /blackadder/the-second/turnip cost "" 1000
+ run_fdtput_test "fine wine" $dtb /blackadder/the-second/potato drink \
+ "-ts" "fine wine"
+ run_wrap_test $DTPUT $dtb -p /you/are/drunk/sir/winston slurp -ts twice
+
+ # Test expansion of the blob when insufficient room for a new node
+ run_wrap_test $DTPUT $dtb -cp "$(cat $text $text)/longish"
+
+ # Allowed to create an existing node with -p
+ run_wrap_test $DTPUT $dtb -cp /chosen
+ run_wrap_test $DTPUT $dtb -cp /chosen/son
+
+ # Start again with a fresh dtb
+ run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb "$SRCDIR/$dts"
+
+ # Node delete
+ run_wrap_test $DTPUT $dtb -c /chosen/node1 /chosen/node2 /chosen/node3
+ run_fdtget_test "node3\nnode2\nnode1" $dtb -l /chosen
+ run_wrap_test $DTPUT $dtb -r /chosen/node1 /chosen/node2
+ run_fdtget_test "node3" $dtb -l /chosen
+
+ # Delete the non-existent node
+ run_wrap_error_test $DTPUT $dtb -r /non-existent/node
+
+ # Property delete
+ run_fdtput_test "eva" $dtb /chosen/ name "" -ts "eva"
+ run_fdtput_test "016" $dtb /chosen/ age "" -ts "016"
+ run_fdtget_test "age\nname\nbootargs\nlinux,platform" $dtb -p /chosen
+ run_wrap_test $DTPUT $dtb -d /chosen/ name age
+ run_fdtget_test "bootargs\nlinux,platform" $dtb -p /chosen
+
+ # Delete the non-existent property
+ run_wrap_error_test $DTPUT $dtb -d /chosen non-existent-prop
+
+ # TODO: Add tests for verbose mode?
+}
+
+utilfdt_tests () {
+ run_test utilfdt_test
+}
+
+fdtdump_tests () {
+ run_fdtdump_test "$SRCDIR/fdtdump.dts"
+}
+
+fdtoverlay_tests() {
+ base="$SRCDIR/overlay_base.dts"
+ basedtb=overlay_base.fdoverlay.test.dtb
+ overlay="$SRCDIR/overlay_overlay_manual_fixups.dts"
+ overlaydtb=overlay_overlay_manual_fixups.fdoverlay.test.dtb
+ targetdtb=target.fdoverlay.test.dtb
+
+ run_dtc_test -@ -I dts -O dtb -o $basedtb $base
+ run_dtc_test -@ -I dts -O dtb -o $overlaydtb $overlay
+
+ # test that the new property is installed
+ run_fdtoverlay_test foobar "/test-node" "test-str-property" "-ts" ${basedtb} ${targetdtb} ${overlaydtb}
+
+ stacked_base="$SRCDIR/stacked_overlay_base.dts"
+ stacked_basedtb=stacked_overlay_base.fdtoverlay.test.dtb
+ stacked_bar="$SRCDIR/stacked_overlay_bar.dts"
+ stacked_bardtb=stacked_overlay_bar.fdtoverlay.test.dtb
+ stacked_baz="$SRCDIR/stacked_overlay_baz.dts"
+ stacked_bazdtb=stacked_overlay_baz.fdtoverlay.test.dtb
+ stacked_targetdtb=stacked_overlay_target.fdtoverlay.test.dtb
+
+ run_dtc_test -@ -I dts -O dtb -o $stacked_basedtb $stacked_base
+ run_dtc_test -@ -I dts -O dtb -o $stacked_bardtb $stacked_bar
+ run_dtc_test -@ -I dts -O dtb -o $stacked_bazdtb $stacked_baz
+
+ # test that baz correctly inserted the property
+ run_fdtoverlay_test baz "/foonode/barnode/baznode" "baz-property" "-ts" ${stacked_basedtb} ${stacked_targetdtb} ${stacked_bardtb} ${stacked_bazdtb}
+
+ # test that bar and baz are correctly appended to __symbols__
+ run_fdtoverlay_test "/foonode/barnode" "/__symbols__" "bar" "-ts" ${stacked_basedtb} ${stacked_targetdtb} ${stacked_bardtb}
+ run_fdtoverlay_test "/foonode/barnode/baznode" "/__symbols__" "baz" "-ts" ${stacked_basedtb} ${stacked_targetdtb} ${stacked_bardtb} ${stacked_bazdtb}
+
+ overlay_long_path="$SRCDIR/overlay_overlay_long_path.dts"
+ overlay_long_pathdtb=overlay_overlay_long_path.fdoverlay.test.dtb
+ target_long_pathdtb=overlay_overlay_long_path_target.fdoverlay.test.dtb
+ run_dtc_test -@ -I dts -O dtb -o $overlay_long_pathdtb $overlay_long_path
+
+ # test that fdtoverlay manages to apply overlays with long target path
+ run_fdtoverlay_test lpath "/test-node/sub-test-node/sub-test-node-with-very-long-target-path/test-0" "prop" "-ts" ${basedtb} ${target_long_pathdtb} ${overlay_long_pathdtb}
+
+ # test adding a label to the root of a fragment
+ stacked_base_nolabel="$SRCDIR/stacked_overlay_base_nolabel.dts"
+ stacked_base_nolabeldtb=stacked_overlay_base_nolabel.test.dtb
+ stacked_addlabel="$SRCDIR/stacked_overlay_addlabel.dts"
+ stacked_addlabeldtb=stacked_overlay_addlabel.test.dtb
+ stacked_addlabel_targetdtb=stacked_overlay_target_nolabel.fdtoverlay.test.dtb
+
+ run_dtc_test -@ -I dts -O dtb -o $stacked_base_nolabeldtb $stacked_base_nolabel
+ run_dtc_test -@ -I dts -O dtb -o $stacked_addlabeldtb $stacked_addlabel
+
+ run_fdtoverlay_test baz "/foonode/barnode/baznode" "baz-property" "-ts" ${stacked_base_nolabeldtb} ${stacked_addlabel_targetdtb} ${stacked_addlabeldtb} ${stacked_bardtb} ${stacked_bazdtb}
+}
+
+pylibfdt_tests () {
+ run_dtc_test -I dts -O dtb -o test_props.dtb "$SRCDIR/test_props.dts"
+ TMP=/tmp/tests.stderr.$$
+ $PYTHON "$SRCDIR/pylibfdt_tests.py" -v 2> $TMP
+
+ # Use the 'ok' message meaning the test passed, 'ERROR' meaning it failed
+ # and the summary line for total tests (e.g. 'Ran 17 tests in 0.002s').
+ # We could add pass + fail to get total tests, but this provides a useful
+ # sanity check.
+ pass_count=$(grep "ok$" $TMP | wc -l)
+ fail_count=$(grep "^ERROR: " $TMP | wc -l)
+ total_tests=$(sed -n 's/^Ran \([0-9]*\) tests.*$/\1/p' $TMP)
+ cat $TMP
+ rm $TMP
+
+ # Extract the test results and add them to our totals
+ tot_fail=$((tot_fail + $fail_count))
+ tot_pass=$((tot_pass + $pass_count))
+ tot_tests=$((tot_tests + $total_tests))
+}
+
+while getopts "vt:me" ARG ; do
+ case $ARG in
+ "v")
+ unset QUIET_TEST
+ ;;
+ "t")
+ TESTSETS=$OPTARG
+ ;;
+ "m")
+ VALGRIND="valgrind --tool=memcheck -q --error-exitcode=$VGCODE"
+ ;;
+ "e")
+ STOP_ON_FAIL=1
+ ;;
+ esac
+done
+
+if [ -z "$TESTSETS" ]; then
+ TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget fdtput fdtdump fdtoverlay"
+
+ # Test pylibfdt if the libfdt Python module is available.
+ if ! $no_python; then
+ TESTSETS="$TESTSETS pylibfdt"
+ fi
+fi
+
+# Make sure we don't have stale blobs lying around
+rm -f *.test.dtb *.test.dts
+
+for set in $TESTSETS; do
+ case $set in
+ "libfdt")
+ libfdt_tests
+ ;;
+ "utilfdt")
+ utilfdt_tests
+ ;;
+ "dtc")
+ dtc_tests
+ ;;
+ "dtbs_equal")
+ dtbs_equal_tests
+ ;;
+ "fdtget")
+ fdtget_tests
+ ;;
+ "fdtput")
+ fdtput_tests
+ ;;
+ "fdtdump")
+ fdtdump_tests
+ ;;
+ "pylibfdt")
+ pylibfdt_tests
+ ;;
+ "fdtoverlay")
+ fdtoverlay_tests
+ ;;
+ esac
+done
+
+echo "********** TEST SUMMARY"
+echo "* Total testcases: $tot_tests"
+echo "* PASS: $tot_pass"
+echo "* FAIL: $tot_fail"
+echo "* Bad configuration: $tot_config"
+if [ -n "$VALGRIND" ]; then
+ echo "* valgrind errors: $tot_vg"
+fi
+echo "* Strange test result: $tot_strange"
+echo "**********"
+
+[ "$tot_tests" -eq "$tot_pass" ] || exit 1
diff --git a/dtc/tests/rw_oom.c b/dtc/tests/rw_oom.c
new file mode 100644
index 000000000..39fc312a6
--- /dev/null
+++ b/dtc/tests/rw_oom.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_nop_node()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+/* This is not derived programmatically. May require adjustment to changes. */
+#define SPACE 285
+
+#define CHECK(code) \
+ { \
+ err = (code); \
+ if (err) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ }
+
+#define OFF_CHECK(off, code) \
+ { \
+ (off) = (code); \
+ if (off < 0) \
+ FAIL(#code ": %s", fdt_strerror(off)); \
+ }
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int err;
+ int offset, s1;
+ int strsize1, strsize2;
+
+ /*
+ * Check OOM path, and check that property is cleaned up if it fails
+ * with OOM, rather than adding an orphan name.
+ *
+ * SW OOM is tested with the realloc/resize strategies.
+ */
+ test_init(argc, argv);
+
+ fdt = xmalloc(SPACE);
+
+ /* First create empty tree with SW */
+ CHECK(fdt_create_empty_tree(fdt, SPACE));
+
+ CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_1, TEST_SIZE_1));
+ CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_2, TEST_SIZE_2));
+
+ CHECK(fdt_setprop_string(fdt, 0, "compatible", "test_oom"));
+ CHECK(fdt_setprop_u32(fdt, 0, "prop-int", TEST_VALUE_1));
+ CHECK(fdt_setprop_u64(fdt, 0, "prop-int64", TEST_VALUE64_1));
+ CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1));
+
+ OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@1"));
+ s1 = offset;
+
+ strsize1 = fdt_size_dt_strings(fdt);
+ err = fdt_setprop_string(fdt, s1, "unique", "subnode1");
+ if (err != -FDT_ERR_NOSPACE)
+ FAIL("fdt_setprop_string(fdt, s1, \"compatible\", \"subnode1\"): %s", fdt_strerror(err));
+ strsize2 = fdt_size_dt_strings(fdt);
+
+ if (strsize1 != strsize2)
+ FAIL("fdt_setprop NOSPACE error failed to clean up allocated string\n");
+ err = 0;
+
+ /* Ensure we failed in the right place */
+ CHECK(fdt_setprop_string(fdt, s1, "unique", ""));
+
+ CHECK(fdt_pack(fdt));
+
+ PASS();
+}
diff --git a/dtc/tests/rw_tree1.c b/dtc/tests/rw_tree1.c
new file mode 100644
index 000000000..1fe2351fc
--- /dev/null
+++ b/dtc/tests/rw_tree1.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_nop_node()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define SPACE 65536
+
+#define CHECK(code) \
+ { \
+ err = (code); \
+ if (err) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ }
+
+#define OFF_CHECK(off, code) \
+ { \
+ (off) = (code); \
+ if (off < 0) \
+ FAIL(#code ": %s", fdt_strerror(off)); \
+ }
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int err;
+ int offset, s1, s2;
+
+ test_init(argc, argv);
+
+ fdt = xmalloc(SPACE);
+
+ /* First create empty tree with SW */
+ CHECK(fdt_create_empty_tree(fdt, SPACE));
+
+ CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_1, TEST_SIZE_1));
+ CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_2, TEST_SIZE_2));
+
+ CHECK(fdt_setprop_string(fdt, 0, "compatible", "test_tree1"));
+ CHECK(fdt_setprop_u32(fdt, 0, "prop-int", TEST_VALUE_1));
+ CHECK(fdt_setprop_u64(fdt, 0, "prop-int64", TEST_VALUE64_1));
+ CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1));
+
+ OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@1"));
+ s1 = offset;
+ CHECK(fdt_setprop_string(fdt, s1, "compatible", "subnode1"));
+ CHECK(fdt_setprop_cell(fdt, s1, "prop-int", TEST_VALUE_1));
+ OFF_CHECK(offset, fdt_add_subnode(fdt, s1, "subsubnode"));
+ CHECK(fdt_setprop(fdt, offset, "compatible",
+ "subsubnode1\0subsubnode", 23));
+ CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_1));
+ OFF_CHECK(offset, fdt_add_subnode(fdt, s1, "ss1"));
+
+ OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@2"));
+ s2 = offset;
+ CHECK(fdt_setprop_cell(fdt, s2, "linux,phandle", PHANDLE_1));
+ CHECK(fdt_setprop_cell(fdt, s2, "prop-int", TEST_VALUE_2));
+ OFF_CHECK(offset, fdt_add_subnode(fdt, s2, "subsubnode@0"));
+ CHECK(fdt_setprop_cell(fdt, offset, "linux,phandle", PHANDLE_2));
+ CHECK(fdt_setprop(fdt, offset, "compatible",
+ "subsubnode2\0subsubnode", 23));
+ CHECK(fdt_setprop_cell(fdt, offset, "prop-int", TEST_VALUE_2));
+ OFF_CHECK(offset, fdt_add_subnode(fdt, s2, "ss2"));
+
+ CHECK(fdt_pack(fdt));
+
+ save_blob("rw_tree1.test.dtb", fdt);
+
+ PASS();
+}
diff --git a/dtc/tests/search_dir/search_test.dtsi b/dtc/tests/search_dir/search_test.dtsi
new file mode 100644
index 000000000..217fb80a8
--- /dev/null
+++ b/dtc/tests/search_dir/search_test.dtsi
@@ -0,0 +1,4 @@
+/include/ "search_test2.dtsi"
+
+/ {
+};
diff --git a/dtc/tests/search_dir/search_test2.dtsi b/dtc/tests/search_dir/search_test2.dtsi
new file mode 100644
index 000000000..7b9099e5c
--- /dev/null
+++ b/dtc/tests/search_dir/search_test2.dtsi
@@ -0,0 +1,3 @@
+
+/ {
+};
diff --git a/dtc/tests/search_dir_b/search_paths_subdir.dts b/dtc/tests/search_dir_b/search_paths_subdir.dts
new file mode 100644
index 000000000..5c5c9622c
--- /dev/null
+++ b/dtc/tests/search_dir_b/search_paths_subdir.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/include/ "search_test_c.dtsi"
+
+/ {
+};
diff --git a/dtc/tests/search_dir_b/search_test_b.dtsi b/dtc/tests/search_dir_b/search_test_b.dtsi
new file mode 100644
index 000000000..b06a7d6ec
--- /dev/null
+++ b/dtc/tests/search_dir_b/search_test_b.dtsi
@@ -0,0 +1,4 @@
+/include/ "search_test_b2.dtsi"
+
+/ {
+};
diff --git a/dtc/tests/search_dir_b/search_test_b2.dtsi b/dtc/tests/search_dir_b/search_test_b2.dtsi
new file mode 100644
index 000000000..2526b43d6
--- /dev/null
+++ b/dtc/tests/search_dir_b/search_test_b2.dtsi
@@ -0,0 +1,5 @@
+
+/include/ "search_test.dtsi"
+
+/ {
+};
diff --git a/dtc/tests/search_dir_b/search_test_c.dtsi b/dtc/tests/search_dir_b/search_test_c.dtsi
new file mode 100644
index 000000000..336d7a250
--- /dev/null
+++ b/dtc/tests/search_dir_b/search_test_c.dtsi
@@ -0,0 +1,2 @@
+/ {
+};
diff --git a/dtc/tests/search_paths.dts b/dtc/tests/search_paths.dts
new file mode 100644
index 000000000..a2bf179e5
--- /dev/null
+++ b/dtc/tests/search_paths.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/include/ "search_test.dtsi"
+
+/ {
+};
diff --git a/dtc/tests/search_paths_b.dts b/dtc/tests/search_paths_b.dts
new file mode 100644
index 000000000..6ace6e24d
--- /dev/null
+++ b/dtc/tests/search_paths_b.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/include/ "search_test_b.dtsi"
+
+/ {
+};
diff --git a/dtc/tests/set_name.c b/dtc/tests/set_name.c
new file mode 100644
index 000000000..a62cb5874
--- /dev/null
+++ b/dtc/tests/set_name.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_set_name()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static 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();
+}
diff --git a/dtc/tests/setprop.c b/dtc/tests/setprop.c
new file mode 100644
index 000000000..fa3938da7
--- /dev/null
+++ b/dtc/tests/setprop.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_setprop()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define SPACE 65536
+#define NEW_STRING "here is quite a long test string, blah blah blah"
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ void *buf;
+ const uint32_t *intp;
+ const char *strp;
+ int err;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ buf = xmalloc(SPACE);
+
+ err = fdt_open_into(fdt, buf, SPACE);
+ if (err)
+ FAIL("fdt_open_into(): %s", fdt_strerror(err));
+
+ fdt = buf;
+
+ intp = check_getprop_cell(fdt, 0, "prop-int", TEST_VALUE_1);
+
+ verbose_printf("Old int value was 0x%08x\n", *intp);
+ err = fdt_setprop_string(fdt, 0, "prop-int", NEW_STRING);
+ if (err)
+ FAIL("Failed to set \"prop-int\" to \"%s\": %s",
+ NEW_STRING, fdt_strerror(err));
+
+ strp = check_getprop_string(fdt, 0, "prop-int", NEW_STRING);
+ verbose_printf("New value is \"%s\"\n", strp);
+
+ strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1,
+ TEST_STRING_1);
+
+ verbose_printf("Old string value was \"%s\"\n", strp);
+ err = fdt_setprop_empty(fdt, 0, "prop-str");
+ if (err)
+ FAIL("Failed to empty \"prop-str\": %s",
+ fdt_strerror(err));
+
+ check_getprop(fdt, 0, "prop-str", 0, NULL);
+
+ err = fdt_setprop_u32(fdt, 0, "prop-u32", TEST_VALUE_2);
+ if (err)
+ FAIL("Failed to set \"prop-u32\" to 0x%08x: %s",
+ TEST_VALUE_2, fdt_strerror(err));
+ check_getprop_cell(fdt, 0, "prop-u32", TEST_VALUE_2);
+
+ err = fdt_setprop_cell(fdt, 0, "prop-cell", TEST_VALUE_2);
+ if (err)
+ FAIL("Failed to set \"prop-cell\" to 0x%08x: %s",
+ TEST_VALUE_2, fdt_strerror(err));
+ check_getprop_cell(fdt, 0, "prop-cell", TEST_VALUE_2);
+
+ err = fdt_setprop_u64(fdt, 0, "prop-u64", TEST_VALUE64_1);
+ if (err)
+ FAIL("Failed to set \"prop-u64\" to 0x%016llx: %s",
+ TEST_VALUE64_1, fdt_strerror(err));
+ check_getprop_64(fdt, 0, "prop-u64", TEST_VALUE64_1);
+
+ PASS();
+}
diff --git a/dtc/tests/setprop_inplace.c b/dtc/tests/setprop_inplace.c
new file mode 100644
index 000000000..7e1198d3e
--- /dev/null
+++ b/dtc/tests/setprop_inplace.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_setprop_inplace()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ const uint32_t *intp;
+ const uint64_t *int64p;
+ const char *strp;
+ char *xstr;
+ int xlen, i;
+ int err;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ intp = check_getprop_cell(fdt, 0, "prop-int", TEST_VALUE_1);
+
+ verbose_printf("Old int value was 0x%08x\n", *intp);
+ err = fdt_setprop_inplace_cell(fdt, 0, "prop-int", ~TEST_VALUE_1);
+ if (err)
+ FAIL("Failed to set \"prop-int\" to 0x%08x: %s",
+ ~TEST_VALUE_1, fdt_strerror(err));
+ intp = check_getprop_cell(fdt, 0, "prop-int", ~TEST_VALUE_1);
+ verbose_printf("New int value is 0x%08x\n", *intp);
+
+ strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1,
+ TEST_STRING_1);
+
+
+ int64p = check_getprop_64(fdt, 0, "prop-int64", TEST_VALUE64_1);
+
+ verbose_printf("Old int64 value was 0x%016" PRIx64 "\n", *int64p);
+ err = fdt_setprop_inplace_u64(fdt, 0, "prop-int64", ~TEST_VALUE64_1);
+ if (err)
+ FAIL("Failed to set \"prop-int64\" to 0x%016llx: %s",
+ ~TEST_VALUE64_1, fdt_strerror(err));
+ int64p = check_getprop_64(fdt, 0, "prop-int64", ~TEST_VALUE64_1);
+ verbose_printf("New int64 value is 0x%016" PRIx64 "\n", *int64p);
+
+ strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1,
+ TEST_STRING_1);
+
+ verbose_printf("Old string value was \"%s\"\n", strp);
+ xstr = strdup(strp);
+ xlen = strlen(xstr);
+ for (i = 0; i < xlen; i++)
+ xstr[i] = toupper(xstr[i]);
+ err = fdt_setprop_inplace(fdt, 0, "prop-str", xstr, xlen+1);
+ if (err)
+ FAIL("Failed to set \"prop-str\" to \"%s\": %s",
+ xstr, fdt_strerror(err));
+
+ strp = check_getprop(fdt, 0, "prop-str", xlen+1, xstr);
+ verbose_printf("New string value is \"%s\"\n", strp);
+
+ err = fdt_setprop_inplace_namelen_partial(fdt, 0, "compatible",
+ strlen("compatible"), 4,
+ TEST_STRING_4_PARTIAL,
+ strlen(TEST_STRING_4_PARTIAL));
+ if (err)
+ FAIL("Failed to set \"compatible\": %s\n", fdt_strerror(err));
+
+ check_getprop(fdt, 0, "compatible", strlen(TEST_STRING_4_RESULT) + 1,
+ TEST_STRING_4_RESULT);
+
+ PASS();
+}
diff --git a/dtc/tests/sized_cells.c b/dtc/tests/sized_cells.c
new file mode 100644
index 000000000..9ca5a594e
--- /dev/null
+++ b/dtc/tests/sized_cells.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for variable sized cells in dtc
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright (C) 2011 The Chromium Authors. All rights reserved.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check_compare_properties(void *fdt,
+ char const *name_one,
+ char const *name_two)
+{
+ const void *propval;
+ int proplen;
+
+ propval = fdt_getprop(fdt, 0, name_one, &proplen);
+
+ if (!propval)
+ FAIL("fdt_getprop(\"%s\"): %s",
+ name_one,
+ fdt_strerror(proplen));
+
+ check_getprop(fdt, 0, name_two, proplen, propval);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ uint8_t expected_8[6] = {TEST_CHAR1,
+ TEST_CHAR2,
+ TEST_CHAR3,
+ TEST_CHAR4,
+ TEST_CHAR5,
+ TEST_VALUE_1 >> 24};
+ fdt16_t expected_16[6];
+ fdt32_t expected_32[6];
+ fdt64_t expected_64[6];
+ int i;
+
+ for (i = 0; i < 5; ++i) {
+ expected_16[i] = cpu_to_fdt16(expected_8[i]);
+ expected_32[i] = cpu_to_fdt32(expected_8[i]);
+ expected_64[i] = cpu_to_fdt64(expected_8[i]);
+ }
+
+ expected_16[5] = cpu_to_fdt16(TEST_VALUE_1 >> 16);
+ expected_32[5] = cpu_to_fdt32(TEST_VALUE_1);
+ expected_64[5] = cpu_to_fdt64(TEST_ADDR_1);
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_getprop(fdt, 0, "cells-8b", sizeof(expected_8), expected_8);
+ check_getprop(fdt, 0, "cells-16b", sizeof(expected_16), expected_16);
+ check_getprop(fdt, 0, "cells-32b", sizeof(expected_32), expected_32);
+ check_getprop(fdt, 0, "cells-64b", sizeof(expected_64), expected_64);
+
+ check_compare_properties(fdt, "cells-one-16b", "cells-one-32b");
+
+ PASS();
+}
diff --git a/dtc/tests/sized_cells.dts b/dtc/tests/sized_cells.dts
new file mode 100644
index 000000000..efea9f567
--- /dev/null
+++ b/dtc/tests/sized_cells.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/ {
+ cells-8b = /bits/ 8 <'\r' 'b' '\0' '\'' '\xff' 0xde>;
+ cells-16b = /bits/ 16 <'\r' 'b' '\0' '\'' '\xff' 0xdead>;
+ cells-32b = /bits/ 32 <'\r' 'b' '\0' '\'' '\xff' 0xdeadbeef>;
+ cells-64b = /bits/ 64 <'\r' 'b' '\0' '\'' '\xff' 0xdeadbeef00000000>;
+
+ cells-one-16b = /bits/ 16 <0x1234 0x5678 0x0 0xffff>;
+ cells-one-32b = <0x12345678 0x0000ffff>;
+};
diff --git a/dtc/tests/sourceoutput.dts b/dtc/tests/sourceoutput.dts
new file mode 100644
index 000000000..5a7459bff
--- /dev/null
+++ b/dtc/tests/sourceoutput.dts
@@ -0,0 +1,14 @@
+/dts-v1/;
+
+/ {
+ /* Some versions had an off-by-2 bug which caused an abort
+ * when outputting labels within strings like this in source
+ * format */
+ prop1: prop1 = start1: "foo", mid1: "bar" end1: ;
+
+ /* Make sure that we correctly handle source output of things
+ * which could almost be expressed as strings, except for the
+ * embedded labels */
+ prop2 = start2: [66 6f 6f], mid2: "bar" end2: ;
+};
+
diff --git a/dtc/tests/stacked_overlay_addlabel.dts b/dtc/tests/stacked_overlay_addlabel.dts
new file mode 100644
index 000000000..e7187a36e
--- /dev/null
+++ b/dtc/tests/stacked_overlay_addlabel.dts
@@ -0,0 +1,15 @@
+/dts-v1/;
+/plugin/;
+/ {
+ frag1: fragment@1 {
+ target-path = "/foonode";
+ local: localinfo {
+ };
+ foo: __overlay__ {
+ overlay-1-property;
+ bar: barnode {
+ bar-property = "bar";
+ };
+ };
+ };
+};
diff --git a/dtc/tests/stacked_overlay_bar.dts b/dtc/tests/stacked_overlay_bar.dts
new file mode 100644
index 000000000..c64639952
--- /dev/null
+++ b/dtc/tests/stacked_overlay_bar.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+/plugin/;
+/ {
+ fragment@1 {
+ target = <&foo>;
+ __overlay__ {
+ overlay-1-property;
+ bar: barnode {
+ bar-property = "bar";
+ };
+ };
+ };
+};
diff --git a/dtc/tests/stacked_overlay_base.dts b/dtc/tests/stacked_overlay_base.dts
new file mode 100644
index 000000000..29164230d
--- /dev/null
+++ b/dtc/tests/stacked_overlay_base.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+/ {
+ foo: foonode {
+ foo-property = "foo";
+ };
+};
diff --git a/dtc/tests/stacked_overlay_base_nolabel.dts b/dtc/tests/stacked_overlay_base_nolabel.dts
new file mode 100644
index 000000000..0c47f0ddc
--- /dev/null
+++ b/dtc/tests/stacked_overlay_base_nolabel.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+/ {
+ foonode {
+ foo-property = "foo";
+ };
+};
diff --git a/dtc/tests/stacked_overlay_baz.dts b/dtc/tests/stacked_overlay_baz.dts
new file mode 100644
index 000000000..a52f0cc60
--- /dev/null
+++ b/dtc/tests/stacked_overlay_baz.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+/plugin/;
+/ {
+ fragment@1 {
+ target = <&bar>;
+ __overlay__ {
+ overlay-2-property;
+ baz: baznode {
+ baz-property = "baz";
+ };
+ };
+ };
+};
diff --git a/dtc/tests/string_escapes.c b/dtc/tests/string_escapes.c
new file mode 100644
index 000000000..53c9dfc3d
--- /dev/null
+++ b/dtc/tests/string_escapes.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for string escapes in dtc
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_getprop(fdt, 0, "escape-str",
+ strlen(TEST_STRING_2)+1, TEST_STRING_2);
+ check_getprop(fdt, 0, "escape-str-2",
+ strlen(TEST_STRING_3)+1, TEST_STRING_3);
+
+ PASS();
+}
diff --git a/dtc/tests/stringlist.c b/dtc/tests/stringlist.c
new file mode 100644
index 000000000..bbc302029
--- /dev/null
+++ b/dtc/tests/stringlist.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for string handling
+ * Copyright (C) 2015 NVIDIA Corporation
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check_expected_failure(const void *fdt, const char *path,
+ const char *property)
+{
+ int offset, err;
+
+ offset = fdt_path_offset(fdt, "/");
+ if (offset < 0)
+ FAIL("Couldn't find path %s", path);
+
+ err = fdt_stringlist_count(fdt, offset, "#address-cells");
+ if (err != -FDT_ERR_BADVALUE)
+ FAIL("unexpectedly succeeded in parsing #address-cells\n");
+
+ err = fdt_stringlist_search(fdt, offset, "#address-cells", "foo");
+ if (err != -FDT_ERR_BADVALUE)
+ FAIL("found string in #address-cells: %d\n", err);
+
+ /*
+ * Note that the #address-cells property contains a small 32-bit
+ * unsigned integer, hence some bytes will be zero, and searching for
+ * the empty string will succeed.
+ *
+ * The reason for this oddity is that the function will exit when the
+ * first occurrence of the string is found, but in order to determine
+ * that the property does not contain a valid string list it would
+ * need to process the whole value.
+ */
+ err = fdt_stringlist_search(fdt, offset, "#address-cells", "");
+ if (err != 0)
+ FAIL("empty string not found in #address-cells: %d\n", err);
+
+ /*
+ * fdt_getprop_string() can successfully extract strings from
+ * non-string properties. This is because it doesn't
+ * necessarily parse the whole property value, which would be
+ * necessary for it to determine if a valid string or string
+ * list is present.
+ */
+}
+
+static void check_string_count(const void *fdt, const char *path,
+ const char *property, int count)
+{
+ int offset, err;
+
+ offset = fdt_path_offset(fdt, path);
+ if (offset < 0)
+ FAIL("Couldn't find path %s", path);
+
+ err = fdt_stringlist_count(fdt, offset, property);
+ if (err < 0)
+ FAIL("Couldn't count strings in property %s of node %s: %d\n",
+ property, path, err);
+
+ if (err != count)
+ FAIL("String count for property %s of node %s is %d instead of %d\n",
+ path, property, err, count);
+}
+
+static void check_string_index(const void *fdt, const char *path,
+ const char *property, const char *string,
+ int idx)
+{
+ int offset, err;
+
+ offset = fdt_path_offset(fdt, path);
+ if (offset < 0)
+ FAIL("Couldn't find path %s", path);
+
+ err = fdt_stringlist_search(fdt, offset, property, string);
+
+ if (err != idx)
+ FAIL("Index of %s in property %s of node %s is %d, expected %d\n",
+ string, property, path, err, idx);
+}
+
+static void check_string(const void *fdt, const char *path,
+ const char *property, int idx,
+ const char *string)
+{
+ const char *result;
+ int offset, len;
+
+ offset = fdt_path_offset(fdt, path);
+ if (offset < 0)
+ FAIL("Couldn't find path %s", path);
+
+ result = fdt_stringlist_get(fdt, offset, property, idx, &len);
+ if (!result)
+ FAIL("Couldn't extract string %d from property %s of node %s: %d\n",
+ idx, property, path, len);
+
+ if (strcmp(string, result) != 0)
+ FAIL("String %d in property %s of node %s is %s, expected %s\n",
+ idx, property, path, result, string);
+}
+
+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_expected_failure(fdt, "/", "#address-cells");
+ check_expected_failure(fdt, "/", "#size-cells");
+
+ check_string_count(fdt, "/", "compatible", 1);
+ check_string_count(fdt, "/device", "compatible", 2);
+ check_string_count(fdt, "/device", "big-endian", 0);
+
+ check_string_index(fdt, "/", "compatible", "test-strings", 0);
+ check_string_index(fdt, "/device", "compatible", "foo", 0);
+ check_string_index(fdt, "/device", "compatible", "bar", 1);
+ check_string_index(fdt, "/device", "big-endian", "baz", -1);
+
+ check_string(fdt, "/", "compatible", 0, "test-strings");
+ check_string(fdt, "/device", "compatible", 0, "foo");
+ check_string(fdt, "/device", "compatible", 1, "bar");
+
+ PASS();
+}
diff --git a/dtc/tests/stringlist.dts b/dtc/tests/stringlist.dts
new file mode 100644
index 000000000..1e4d31404
--- /dev/null
+++ b/dtc/tests/stringlist.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/ {
+ compatible = "test-strings";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ device {
+ compatible = "foo", "bar";
+ big-endian;
+ };
+};
diff --git a/dtc/tests/subnode_iterate.c b/dtc/tests/subnode_iterate.c
new file mode 100644
index 000000000..2dc9b2d35
--- /dev/null
+++ b/dtc/tests/subnode_iterate.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Tests that fdt_next_subnode() works as expected
+ *
+ * Copyright (C) 2013 Google, Inc
+ *
+ * Copyright (C) 2007 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void test_node(void *fdt, int parent_offset)
+{
+ uint32_t subnodes;
+ const fdt32_t *prop;
+ int offset;
+ int count;
+ int len;
+
+ /* This property indicates the number of subnodes to expect */
+ prop = fdt_getprop(fdt, parent_offset, "subnodes", &len);
+ if (!prop || len != sizeof(fdt32_t)) {
+ FAIL("Missing/invalid subnodes property at '%s'",
+ fdt_get_name(fdt, parent_offset, NULL));
+ }
+ subnodes = fdt32_to_cpu(*prop);
+
+ count = 0;
+ fdt_for_each_subnode(offset, fdt, parent_offset)
+ count++;
+
+ if (count != subnodes) {
+ FAIL("Node '%s': Expected %d subnodes, got %d\n",
+ fdt_get_name(fdt, parent_offset, NULL), subnodes,
+ count);
+ }
+}
+
+static void check_fdt_next_subnode(void *fdt)
+{
+ int offset;
+ int count = 0;
+
+ fdt_for_each_subnode(offset, fdt, 0) {
+ test_node(fdt, offset);
+ count++;
+ }
+
+ if (count != 2)
+ FAIL("Expected %d tests, got %d\n", 2, count);
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+ if (argc != 2)
+ CONFIG("Usage: %s <dtb file>", argv[0]);
+
+ fdt = load_blob(argv[1]);
+ if (!fdt)
+ FAIL("No device tree available");
+
+ check_fdt_next_subnode(fdt);
+
+ PASS();
+}
diff --git a/dtc/tests/subnode_iterate.dts b/dtc/tests/subnode_iterate.dts
new file mode 100644
index 000000000..14a0d3aba
--- /dev/null
+++ b/dtc/tests/subnode_iterate.dts
@@ -0,0 +1,44 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ test1 {
+ subnodes = <2>;
+ linux,phandle = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ PowerPC,970@0 {
+ name = "PowerPC,970";
+ device_type = "cpu";
+ reg = <0x00000000>;
+ clock-frequency = <1600000000>;
+ timebase-frequency = <33333333>;
+ linux,boot-cpu;
+ i-cache-size = <65536>;
+ d-cache-size = <32768>;
+ another-sub-node {
+ should-be-ignored;
+ yet-another {
+ should-also-be-ignored;
+ };
+ };
+ };
+
+ PowerPC,970@1 {
+ name = "PowerPC,970";
+ device_type = "cpu";
+ reg = <0x00000001>;
+ clock-frequency = <1600000000>;
+ timebase-frequency = <33333333>;
+ i-cache-size = <65536>;
+ d-cache-size = <32768>;
+ };
+ };
+
+ test2 {
+ subnodes = <0>;
+ };
+};
+
diff --git a/dtc/tests/subnode_offset.c b/dtc/tests/subnode_offset.c
new file mode 100644
index 000000000..1362f998b
--- /dev/null
+++ b/dtc/tests/subnode_offset.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_subnode_offset()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static int check_subnode(struct fdt_header *fdt, int parent, const char *name)
+{
+ int offset;
+ const struct fdt_node_header *nh;
+ uint32_t tag;
+
+ verbose_printf("Checking subnode \"%s\" of %d...", name, parent);
+ offset = fdt_subnode_offset(fdt, parent, name);
+ verbose_printf("offset %d...", offset);
+ if (offset < 0)
+ FAIL("fdt_subnode_offset(\"%s\"): %s", name, fdt_strerror(offset));
+ nh = fdt_offset_ptr(fdt, offset, sizeof(*nh));
+ verbose_printf("pointer %p\n", nh);
+ if (! nh)
+ FAIL("NULL retrieving subnode \"%s\"", name);
+
+ tag = fdt32_to_cpu(nh->tag);
+
+ if (tag != FDT_BEGIN_NODE)
+ FAIL("Incorrect tag 0x%08x on property \"%s\"", tag, name);
+ if (!nodename_eq(nh->name, name))
+ FAIL("Subnode name mismatch \"%s\" instead of \"%s\"",
+ nh->name, name);
+
+ return offset;
+}
+
+int main(int argc, char *argv[])
+{
+ void *fdt;
+ int subnode1_offset, subnode2_offset;
+ int subsubnode1_offset, subsubnode2_offset, subsubnode2_offset2;
+ int ss12_off, ss21_off;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ subnode1_offset = check_subnode(fdt, 0, "subnode@1");
+ subnode2_offset = check_subnode(fdt, 0, "subnode@2");
+
+ if (subnode1_offset == subnode2_offset)
+ FAIL("Different subnodes have same offset");
+
+ check_property_cell(fdt, subnode1_offset, "prop-int", TEST_VALUE_1);
+ check_property_cell(fdt, subnode2_offset, "prop-int", TEST_VALUE_2);
+
+ subsubnode1_offset = check_subnode(fdt, subnode1_offset, "subsubnode");
+ subsubnode2_offset = check_subnode(fdt, subnode2_offset, "subsubnode@0");
+ subsubnode2_offset2 = check_subnode(fdt, subnode2_offset, "subsubnode");
+
+ check_property_cell(fdt, subsubnode1_offset, "prop-int", TEST_VALUE_1);
+ check_property_cell(fdt, subsubnode2_offset, "prop-int", TEST_VALUE_2);
+ check_property_cell(fdt, subsubnode2_offset2, "prop-int", TEST_VALUE_2);
+
+ if (subsubnode2_offset != subsubnode2_offset2)
+ FAIL("Different offsets with and without unit address");
+
+ check_subnode(fdt, subnode1_offset, "ss1");
+ ss21_off = fdt_subnode_offset(fdt, subnode2_offset, "ss1");
+ if (ss21_off != -FDT_ERR_NOTFOUND)
+ FAIL("Incorrectly found ss1 in subnode2");
+
+ ss12_off = fdt_subnode_offset(fdt, subnode1_offset, "ss2");
+ if (ss12_off != -FDT_ERR_NOTFOUND)
+ FAIL("Incorrectly found ss2 in subnode1");
+ check_subnode(fdt, subnode2_offset, "ss2");
+
+ PASS();
+}
diff --git a/dtc/tests/supernode_atdepth_offset.c b/dtc/tests/supernode_atdepth_offset.c
new file mode 100644
index 000000000..4435b4949
--- /dev/null
+++ b/dtc/tests/supernode_atdepth_offset.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_supernode_atdepth_offset()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static int path_depth(const char *path)
+{
+ const char *p;
+ int depth = 0;
+
+ if (path[0] != '/')
+ TEST_BUG();
+
+ if (strcmp(path, "/") == 0)
+ return 0;
+ for (p = path; *p; p++)
+ if (*p == '/')
+ depth++;
+
+ /* Special case for path == "/" */
+ if (p == (path + 1))
+ return 0;
+ else
+ return depth;
+}
+
+static int path_prefix(const char *path, int depth)
+{
+ const char *p;
+ int i;
+
+ if (path[0] != '/')
+ TEST_BUG();
+
+ if (depth == 0)
+ return 1;
+
+ p = path;
+ for (i = 0; i < depth; i++)
+ p = p+1 + strcspn(p+1, "/");
+
+ return p - path;
+}
+
+static void check_supernode_atdepth(struct fdt_header *fdt, const char *path,
+ int depth)
+{
+ int pdepth = path_depth(path);
+ char *superpath;
+ int nodeoffset, supernodeoffset, superpathoffset, pathprefixlen;
+ int nodedepth;
+
+ pathprefixlen = path_prefix(path, depth);
+ superpath = alloca(pathprefixlen + 1);
+ strncpy(superpath, path, pathprefixlen);
+ superpath[pathprefixlen] = '\0';
+
+ verbose_printf("Path %s (%d), depth %d, supernode is %s\n",
+ path, pdepth, depth, superpath);
+
+ nodeoffset = fdt_path_offset(fdt, path);
+ if (nodeoffset < 0)
+ FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(nodeoffset));
+ superpathoffset = fdt_path_offset(fdt, superpath);
+ if (superpathoffset < 0)
+ FAIL("fdt_path_offset(%s): %s", superpath,
+ fdt_strerror(superpathoffset));
+
+ supernodeoffset = fdt_supernode_atdepth_offset(fdt, nodeoffset,
+ depth, &nodedepth);
+ if (supernodeoffset < 0)
+ FAIL("fdt_supernode_atdepth_offset(): %s",
+ fdt_strerror(supernodeoffset));
+
+ if (supernodeoffset != superpathoffset)
+ FAIL("fdt_supernode_atdepth_offset() returns %d instead of %d",
+ supernodeoffset, superpathoffset);
+
+ if (nodedepth != pdepth)
+ FAIL("fdt_supernode_atdept_offset() returns node depth %d "
+ "instead of %d", nodedepth, pdepth);
+}
+
+static void check_supernode_overdepth(struct fdt_header *fdt, const char *path)
+{
+ int pdepth = path_depth(path);
+ int nodeoffset, err;
+
+ nodeoffset = fdt_path_offset(fdt, path);
+ if (nodeoffset < 0)
+ FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(nodeoffset));
+
+ err = fdt_supernode_atdepth_offset(fdt, nodeoffset, pdepth + 1, NULL);
+ if (err != -FDT_ERR_NOTFOUND)
+ FAIL("fdt_supernode_atdept_offset(%s, %d) returns %d instead "
+ "of FDT_ERR_NOTFOUND", path, pdepth+1, err);
+}
+
+static void check_path(struct fdt_header *fdt, const char *path)
+{
+ int i;
+
+ for (i = 0; i <= path_depth(path); i++)
+ check_supernode_atdepth(fdt, path, i);
+ check_supernode_overdepth(fdt, path);
+}
+int main(int argc, char *argv[])
+{
+ void *fdt;
+
+ test_init(argc, argv);
+ fdt = load_blob_arg(argc, argv);
+
+ check_path(fdt, "/");
+ check_path(fdt, "/subnode@1");
+ check_path(fdt, "/subnode@2");
+ check_path(fdt, "/subnode@1/subsubnode");
+ check_path(fdt, "/subnode@2/subsubnode@0");
+
+ PASS();
+}
diff --git a/dtc/tests/sw_states.c b/dtc/tests/sw_states.c
new file mode 100644
index 000000000..42d57ae52
--- /dev/null
+++ b/dtc/tests/sw_states.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for error handling with sequential write states
+ * Copyright (C) 2018 David Gibson, Red Hat Inc.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define SPACE 65536
+
+#define CHECK_OK(code) \
+ do { \
+ verbose_printf(" OK: %s\n", #code); \
+ err = (code); \
+ if (err) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ } while (0)
+
+#define CHECK_BADSTATE(code) \
+ do { \
+ verbose_printf("BAD: %s\n", #code); \
+ err = (code); \
+ if (err == 0) \
+ FAIL(#code ": succeeded in bad state"); \
+ else if (err != -FDT_ERR_BADSTATE) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ } while (0)
+
+int main(int argc, char *argv[])
+{
+ void *fdt = NULL;
+ int err;
+
+ test_init(argc, argv);
+
+ fdt = xmalloc(SPACE);
+
+ err = fdt_create(fdt, SPACE);
+ if (err)
+ FAIL("fdt_create(): %s", fdt_strerror(err));
+
+ /* Memory reserve state */
+
+ CHECK_BADSTATE(fdt_begin_node(fdt, ""));
+ CHECK_BADSTATE(fdt_property_string(fdt, "bad-str", "TEST_STRING_1"));
+ CHECK_BADSTATE(fdt_end_node(fdt));
+ CHECK_BADSTATE(fdt_finish(fdt));
+
+ CHECK_OK(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1));
+ CHECK_OK(fdt_add_reservemap_entry(fdt, TEST_ADDR_2, TEST_SIZE_2));
+
+ CHECK_BADSTATE(fdt_begin_node(fdt, ""));
+ CHECK_BADSTATE(fdt_property_string(fdt, "bad-str", "TEST_STRING_1"));
+ CHECK_BADSTATE(fdt_end_node(fdt));
+ CHECK_BADSTATE(fdt_finish(fdt));
+
+ CHECK_OK(fdt_finish_reservemap(fdt));
+
+ /* Structure state */
+
+ CHECK_BADSTATE(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1));
+ CHECK_BADSTATE(fdt_finish_reservemap(fdt));
+
+ CHECK_OK(fdt_begin_node(fdt, ""));
+ CHECK_OK(fdt_property_string(fdt, "compatible", "test_tree1"));
+ CHECK_OK(fdt_property_u32(fdt, "prop-int", TEST_VALUE_1));
+ CHECK_OK(fdt_property_u64(fdt, "prop-int64", TEST_VALUE64_1));
+ CHECK_OK(fdt_property_string(fdt, "prop-str", TEST_STRING_1));
+ CHECK_OK(fdt_property_u32(fdt, "#address-cells", 1));
+ CHECK_OK(fdt_property_u32(fdt, "#size-cells", 0));
+
+ CHECK_OK(fdt_begin_node(fdt, "subnode@1"));
+ CHECK_OK(fdt_property_string(fdt, "compatible", "subnode1"));
+ CHECK_OK(fdt_property_u32(fdt, "reg", 1));
+ CHECK_OK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1));
+ CHECK_OK(fdt_begin_node(fdt, "subsubnode"));
+ CHECK_OK(fdt_property(fdt, "compatible", "subsubnode1\0subsubnode",
+ 23));
+ CHECK_OK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1));
+ CHECK_OK(fdt_end_node(fdt));
+ CHECK_OK(fdt_begin_node(fdt, "ss1"));
+ CHECK_OK(fdt_end_node(fdt));
+ CHECK_OK(fdt_end_node(fdt));
+
+ CHECK_OK(fdt_begin_node(fdt, "subnode@2"));
+ CHECK_OK(fdt_property_u32(fdt, "reg", 2));
+ CHECK_OK(fdt_property_cell(fdt, "linux,phandle", PHANDLE_1));
+ CHECK_OK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2));
+ CHECK_OK(fdt_property_u32(fdt, "#address-cells", 1));
+ CHECK_OK(fdt_property_u32(fdt, "#size-cells", 0));
+ CHECK_OK(fdt_begin_node(fdt, "subsubnode@0"));
+ CHECK_OK(fdt_property_u32(fdt, "reg", 0));
+ CHECK_OK(fdt_property_cell(fdt, "phandle", PHANDLE_2));
+ CHECK_OK(fdt_property(fdt, "compatible", "subsubnode2\0subsubnode",
+ 23));
+ CHECK_OK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2));
+ CHECK_OK(fdt_end_node(fdt));
+ CHECK_OK(fdt_begin_node(fdt, "ss2"));
+ CHECK_OK(fdt_end_node(fdt));
+
+ CHECK_OK(fdt_end_node(fdt));
+
+ CHECK_OK(fdt_end_node(fdt));
+
+ CHECK_OK(fdt_finish(fdt));
+
+ /* Completed state */
+
+ CHECK_BADSTATE(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1));
+ CHECK_BADSTATE(fdt_finish_reservemap(fdt));
+ CHECK_BADSTATE(fdt_begin_node(fdt, ""));
+ CHECK_BADSTATE(fdt_property_string(fdt, "bad-str", "TEST_STRING_1"));
+ CHECK_BADSTATE(fdt_end_node(fdt));
+ CHECK_BADSTATE(fdt_finish(fdt));
+
+ PASS();
+}
diff --git a/dtc/tests/sw_tree1.c b/dtc/tests/sw_tree1.c
new file mode 100644
index 000000000..7069ace0a
--- /dev/null
+++ b/dtc/tests/sw_tree1.c
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for fdt_nop_node()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define SPACE 65536
+
+static enum {
+ FIXED = 0,
+ RESIZE,
+ REALLOC,
+ NEWALLOC,
+} alloc_mode;
+
+static void realloc_fdt(void **fdt, size_t *size, bool created)
+{
+ int err;
+
+ switch (alloc_mode) {
+ case FIXED:
+ if (!(*fdt))
+ *fdt = xmalloc(*size);
+ else
+ FAIL("Ran out of space");
+ return;
+
+ case RESIZE:
+ if (!(*fdt)) {
+ *fdt = xmalloc(SPACE);
+ } else if (*size < SPACE) {
+ *size += 1;
+ err = fdt_resize(*fdt, *fdt, *size);
+ if (err < 0)
+ FAIL("fdt_resize() failed: %s",
+ fdt_strerror(err));
+ } else {
+ FAIL("Ran out of space");
+ }
+ return;
+
+ case REALLOC:
+ *size += 1;
+ *fdt = xrealloc(*fdt, *size);
+ if (created) {
+ err = fdt_resize(*fdt, *fdt, *size);
+ if (err < 0)
+ FAIL("fdt_resize() failed: %s",
+ fdt_strerror(err));
+ }
+ return;
+
+ case NEWALLOC: {
+ void *buf;
+
+ *size += 1;
+ buf = xmalloc(*size);
+ if (created) {
+ err = fdt_resize(*fdt, buf, *size);
+ if (err < 0)
+ FAIL("fdt_resize() failed: %s",
+ fdt_strerror(err));
+ }
+ free(*fdt);
+ *fdt = buf;
+ return;
+ }
+
+ default:
+ CONFIG("Bad allocation mode");
+ }
+}
+
+#define CHECK(code) \
+ do { \
+ err = (code); \
+ if (err == -FDT_ERR_NOSPACE) \
+ realloc_fdt(&fdt, &size, created); \
+ else if (err) \
+ FAIL(#code ": %s", fdt_strerror(err)); \
+ } while (err != 0)
+
+int main(int argc, char *argv[])
+{
+ void *fdt = NULL;
+ size_t size;
+ int err;
+ bool created = false;
+ void *place;
+ const char place_str[] = "this is a placeholder string\0string2";
+ int place_len = sizeof(place_str);
+ int create_flags;
+
+ test_init(argc, argv);
+
+ alloc_mode = FIXED;
+ size = SPACE;
+ create_flags = 0;
+
+ if (argc == 2 || argc == 3) {
+ if (streq(argv[1], "fixed")) {
+ alloc_mode = FIXED;
+ size = SPACE;
+ } else if (streq(argv[1], "resize")) {
+ alloc_mode = REALLOC;
+ size = 0;
+ } else if (streq(argv[1], "realloc")) {
+ alloc_mode = REALLOC;
+ size = 0;
+ } else if (streq(argv[1], "newalloc")) {
+ alloc_mode = NEWALLOC;
+ size = 0;
+ } else {
+ char *endp;
+
+ size = strtoul(argv[1], &endp, 0);
+ if (*endp == '\0')
+ alloc_mode = FIXED;
+ else
+ CONFIG("Bad allocation mode \"%s\" specified",
+ argv[1]);
+ }
+ }
+ if (argc == 3) {
+ char *str = argv[2], *saveptr, *tok;
+ bool default_flag = false;
+
+ while ((tok = strtok_r(str, ",", &saveptr)) != NULL) {
+ str = NULL;
+ if (streq(tok, "default")) {
+ default_flag = true;
+ } else if (streq(tok, "no_name_dedup")) {
+ create_flags |= FDT_CREATE_FLAG_NO_NAME_DEDUP;
+ } else if (streq(tok, "bad")) {
+ create_flags |= 0xffffffff;
+ } else {
+ CONFIG("Bad creation flags \"%s\" specified",
+ argv[2]);
+ }
+ }
+
+ if (default_flag && create_flags != 0)
+ CONFIG("Bad creation flags \"%s\" specified",
+ argv[2]);
+ }
+
+ if (argc > 3) {
+ CONFIG("sw_tree1 [<allocation mode>] [<create flags>]");
+ }
+
+ fdt = xmalloc(size);
+ CHECK(fdt_create_with_flags(fdt, size, create_flags));
+
+ created = true;
+
+ CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1));
+
+ CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_2, TEST_SIZE_2));
+ CHECK(fdt_finish_reservemap(fdt));
+
+ CHECK(fdt_begin_node(fdt, ""));
+ CHECK(fdt_property_string(fdt, "compatible", "test_tree1"));
+ CHECK(fdt_property_u32(fdt, "prop-int", TEST_VALUE_1));
+ CHECK(fdt_property_u64(fdt, "prop-int64", TEST_VALUE64_1));
+ CHECK(fdt_property_string(fdt, "prop-str", TEST_STRING_1));
+ CHECK(fdt_property_u32(fdt, "#address-cells", 1));
+ CHECK(fdt_property_u32(fdt, "#size-cells", 0));
+
+ CHECK(fdt_begin_node(fdt, "subnode@1"));
+ CHECK(fdt_property_string(fdt, "compatible", "subnode1"));
+ CHECK(fdt_property_u32(fdt, "reg", 1));
+ CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1));
+ CHECK(fdt_begin_node(fdt, "subsubnode"));
+ CHECK(fdt_property(fdt, "compatible", "subsubnode1\0subsubnode",
+ 23));
+ CHECK(fdt_property_placeholder(fdt, "placeholder", place_len, &place));
+ memcpy(place, place_str, place_len);
+ CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1));
+ CHECK(fdt_end_node(fdt));
+ CHECK(fdt_begin_node(fdt, "ss1"));
+ CHECK(fdt_end_node(fdt));
+ CHECK(fdt_end_node(fdt));
+
+ CHECK(fdt_begin_node(fdt, "subnode@2"));
+ CHECK(fdt_property_u32(fdt, "reg", 2));
+ CHECK(fdt_property_cell(fdt, "linux,phandle", PHANDLE_1));
+ CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2));
+ CHECK(fdt_property_u32(fdt, "#address-cells", 1));
+ CHECK(fdt_property_u32(fdt, "#size-cells", 0));
+ CHECK(fdt_begin_node(fdt, "subsubnode@0"));
+ CHECK(fdt_property_u32(fdt, "reg", 0));
+ CHECK(fdt_property_cell(fdt, "phandle", PHANDLE_2));
+ CHECK(fdt_property(fdt, "compatible", "subsubnode2\0subsubnode",
+ 23));
+ CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2));
+ CHECK(fdt_end_node(fdt));
+ CHECK(fdt_begin_node(fdt, "ss2"));
+ CHECK(fdt_end_node(fdt));
+
+ CHECK(fdt_end_node(fdt));
+
+ CHECK(fdt_end_node(fdt));
+
+ save_blob("unfinished_tree1.test.dtb", fdt);
+
+ CHECK(fdt_finish(fdt));
+
+ verbose_printf("Completed tree, totalsize = %d\n",
+ fdt_totalsize(fdt));
+
+ save_blob("sw_tree1.test.dtb", fdt);
+
+ PASS();
+}
diff --git a/dtc/tests/test01.asm b/dtc/tests/test01.asm
new file mode 100644
index 000000000..bbf66c771
--- /dev/null
+++ b/dtc/tests/test01.asm
@@ -0,0 +1,294 @@
+/* autogenerated by dtc, do not edit */
+
+#define OF_DT_HEADER 0xd00dfeed
+#define OF_DT_BEGIN_NODE 0x1
+#define OF_DT_END_NODE 0x2
+#define OF_DT_PROP 0x3
+#define OF_DT_END 0x9
+
+ .globl dt_blob_start
+dt_blob_start:
+_dt_blob_start:
+ .globl dt_header
+dt_header:
+_dt_header:
+ .long OF_DT_HEADER /* magic */
+ .long _dt_blob_end - _dt_blob_start /* totalsize */
+ .long _dt_struct_start - _dt_blob_start /* off_dt_struct */
+ .long _dt_strings_start - _dt_blob_start /* off_dt_strings */
+ .long _dt_reserve_map - _dt_blob_start /* off_dt_strings */
+ .long 16 /* version */
+ .long 16 /* last_comp_version */
+ .long 0 /*boot_cpuid_phys*/
+ .long _dt_strings_end - _dt_strings_start /* size_dt_strings */
+ .balign 8
+ .globl dt_reserve_map
+dt_reserve_map:
+_dt_reserve_map:
+/* Memory reserve map from source file */
+ .long 0x10000000
+ .long 0x00000000
+ .long 0x00000000
+ .long 0x02000000
+ .long 0x20000000
+ .long 0x00000000
+ .long 0x01000000
+ .long 0x00000000
+ .long 0x00000000
+ .long 0x00000000
+ .long 0x00000000
+ .long 0x00000014
+ .long 0, 0
+ .long 0, 0
+ .globl dt_struct_start
+dt_struct_start:
+_dt_struct_start:
+ .long OF_DT_BEGIN_NODE
+ .string ""
+ .balign 4
+ .long OF_DT_PROP
+ .long 0xc
+ .long 0x0
+ .long 0x4d79426f
+ .long 0x6172644e
+ .long 0x616d6500
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x1e
+ .long 0x6
+ .long 0x4d79426f
+ .long 0x6172644e
+ .long 0x616d6500
+ .long 0x4d79426f
+ .long 0x61726446
+ .long 0x616d696c
+ .long 0x794e616d
+ .short 0x6500
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x11
+ .long 0x2
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x20
+ .long 0x2
+ .balign 4
+ .long OF_DT_BEGIN_NODE
+ .string "cpus"
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x2c
+ .long 0x1
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x11
+ .long 0x1
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x20
+ .long 0x0
+ .balign 4
+ .long OF_DT_BEGIN_NODE
+ .string "PowerPC,970@0"
+ .balign 4
+ .long OF_DT_PROP
+ .long 0xc
+ .long 0x3a
+ .long 0x506f7765
+ .long 0x7250432c
+ .long 0x39373000
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x3f
+ .long 0x63707500
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x4b
+ .long 0x0
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x4f
+ .long 0x5f5e1000
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x5f
+ .long 0x1fca055
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x0
+ .long 0x72
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x81
+ .long 0x10000
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x8e
+ .long 0x8000
+ .balign 4
+ .long OF_DT_END_NODE
+ .long OF_DT_BEGIN_NODE
+ .string "PowerPC,970@1"
+ .balign 4
+ .long OF_DT_PROP
+ .long 0xc
+ .long 0x3a
+ .long 0x506f7765
+ .long 0x7250432c
+ .long 0x39373000
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x3f
+ .long 0x63707500
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x4b
+ .long 0x1
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x4f
+ .long 0x5f5e1000
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x5f
+ .long 0x1fca055
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x81
+ .long 0x10000
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x8e
+ .long 0x8000
+ .balign 4
+ .long OF_DT_END_NODE
+ .long OF_DT_END_NODE
+ .long OF_DT_BEGIN_NODE
+ .string "randomnode"
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x13
+ .long 0x9b
+ .long 0xff007374
+ .long 0x75666673
+ .long 0x74756666
+ .long 0x909090a
+ .short 0xa0a
+ .byte 0x0
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x9
+ .long 0xa2
+ .long 0xa0b0c0d
+ .long 0xdeeaadbe
+ .byte 0xef
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0xa7
+ .long 0x2
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x14
+ .long 0xab
+ .long 0x61626300
+ .long 0x12340000
+ .long 0xa
+ .long 0xb
+ .long 0xc
+ .balign 4
+ .long OF_DT_END_NODE
+ .long OF_DT_BEGIN_NODE
+ .string "memory@0"
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x7
+ .long 0x3f
+ .long 0x6d656d6f
+ .short 0x7279
+ .byte 0x0
+ .balign 4
+ .globl memreg
+memreg:
+ .long OF_DT_PROP
+ .long 0x10
+ .long 0x4b
+ .long 0x0
+ .long 0x0
+ .long 0x0
+ .long 0x20000000
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0x2c
+ .long 0x2
+ .balign 4
+ .long OF_DT_END_NODE
+ .long OF_DT_BEGIN_NODE
+ .string "chosen"
+ .balign 4
+ .long OF_DT_PROP
+ .long 0xf
+ .long 0xb1
+ .long 0x726f6f74
+ .long 0x3d2f6465
+ .long 0x762f7364
+ .short 0x6132
+ .byte 0x0
+ .balign 4
+ .long OF_DT_PROP
+ .long 0x4
+ .long 0xba
+ .long 0x600
+ .balign 4
+ .long OF_DT_END_NODE
+ .long OF_DT_END_NODE
+ .long OF_DT_END
+ .globl dt_struct_end
+dt_struct_end:
+_dt_struct_end:
+ .globl dt_strings_start
+dt_strings_start:
+_dt_strings_start:
+ .string "model"
+ .string "compatible"
+ .string "#address-cells"
+ .string "#size-cells"
+ .string "linux,phandle"
+ .string "name"
+ .string "device_type"
+ .string "reg"
+ .string "clock-frequency"
+ .string "timebase-frequency"
+ .string "linux,boot-cpu"
+ .string "i-cache-size"
+ .string "d-cache-size"
+ .string "string"
+ .string "blob"
+ .string "ref"
+ .string "mixed"
+ .string "bootargs"
+ .string "linux,platform"
+ .globl dt_strings_end
+dt_strings_end:
+_dt_strings_end:
+ .globl dt_blob_end
+dt_blob_end:
+_dt_blob_end:
diff --git a/dtc/tests/test01.dts b/dtc/tests/test01.dts
new file mode 100644
index 000000000..f9fd16534
--- /dev/null
+++ b/dtc/tests/test01.dts
@@ -0,0 +1,57 @@
+/dts-v1/;
+
+/memreserve/ 0x1000000000000000 0x0000000002000000;
+/memreserve/ 0x2000000000000000 0x0100000000000000;
+/memreserve/ 0x0000000000000000 0x0000000000000014;
+
+/ {
+ model = "MyBoardName";
+ compatible = "MyBoardName", "MyBoardFamilyName";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ linux,phandle = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ PowerPC,970@0 {
+ name = "PowerPC,970";
+ device_type = "cpu";
+ reg = <0x00000000>;
+ clock-frequency = <1600000000>;
+ timebase-frequency = <33333333>;
+ linux,boot-cpu;
+ i-cache-size = <65536>;
+ d-cache-size = <32768>;
+ };
+
+ PowerPC,970@1 {
+ name = "PowerPC,970";
+ device_type = "cpu";
+ reg = <0x00000001>;
+ clock-frequency = <1600000000>;
+ timebase-frequency = <33333333>;
+ i-cache-size = <65536>;
+ d-cache-size = <32768>;
+ };
+
+ };
+
+ randomnode {
+ string = "\xff\0stuffstuff\t\t\t\n\n\n";
+ blob = [0a 0b 0c 0d de ea ad be ef];
+ ref = < &{/memory@0} >;
+ mixed = "abc", [1234], <0xa 0xb 0xc>;
+ };
+
+ memory@0 {
+ device_type = "memory";
+ memreg: reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
+ };
+
+ chosen {
+ bootargs = "root=/dev/sda2";
+ linux,platform = <0x600>;
+ };
+
+};
diff --git a/dtc/tests/test01.stderr b/dtc/tests/test01.stderr
new file mode 100644
index 000000000..82ea3f634
--- /dev/null
+++ b/dtc/tests/test01.stderr
@@ -0,0 +1,4 @@
+DTC: dts->asm on file "test.dts"
+Warning: "linux,boot-cpu" property is deprecated in blob version 2 or higher
+Warning: /chosen has no "linux,stdout-path" property
+Warning: /chosen has no "interrupt-controller" property
diff --git a/dtc/tests/test_kernel_dts b/dtc/tests/test_kernel_dts
new file mode 100755
index 000000000..238f3f7c6
--- /dev/null
+++ b/dtc/tests/test_kernel_dts
@@ -0,0 +1,86 @@
+#!/usr/bin/perl
+
+my $dtc_old = "/home/jdl/FSL/dtc/dtc-old";
+my $dtc_new = "/home/jdl/FSL/dtc/dtc-new";
+
+my $basic_options = "-b 0 -f -I dts -O dtb";
+
+my $linux_dts_dir = "/usr/src/linux-2.6/arch/powerpc/boot/dts";
+
+# Yeah, sure, we could, like, readdir() this instead...
+my @boards = (
+ "bamboo",
+ "ebony",
+ "ep88xc",
+ "holly",
+ "kilauea",
+ "kuroboxHD",
+ "kuroboxHG",
+ "lite5200",
+ "lite5200b",
+ "mpc7448hpc2",
+ "mpc8272ads",
+ "mpc8313erdb",
+ "mpc832x_mds",
+ "mpc832x_rdb",
+ "mpc8349emitx",
+ "mpc8349emitxgp",
+ "mpc834x_mds",
+ "mpc836x_mds",
+ "mpc8540ads",
+ "mpc8541cds",
+ "mpc8544ds",
+ "mpc8548cds",
+ "mpc8555cds",
+ "mpc8560ads",
+ "mpc8568mds",
+ "mpc8572ds",
+ "mpc8610_hpcd",
+ "mpc8641_hpcn",
+ "mpc866ads", # Feh. Bad node references...
+ "mpc885ads",
+ "pq2fads",
+ "prpmc2800",
+ "ps3",
+ "sequoia",
+ "walnut",
+);
+
+foreach my $board (@boards) {
+ my $dts_file = "$linux_dts_dir/$board.dts";
+
+ my $old_dtb_file = "/tmp/$board.dtb.old";
+ my $new_dtb_file = "/tmp/$board.dtb.new";
+
+ my $cmd_old = "$dtc_old $basic_options -o $old_dtb_file $dts_file";
+ my $cmd_new = "$dtc_new $basic_options -o $new_dtb_file $dts_file";
+ my $cmd_cmp = "cmp $old_dtb_file $new_dtb_file";
+
+ print "------------------------------------------------\n";
+ print "OLD: $cmd_old\n";
+ unlink($old_dtb_file) if (-f $old_dtb_file);
+ system("$cmd_old >& /dev/null");
+ my $status = $?;
+ if ($status) {
+ print " FAILED to run old DTC on $board\n";
+ }
+
+ print "NEW: $cmd_new\n";
+ unlink($new_dtb_file) if (-f $new_dtb_file);
+ system("$cmd_new >& /dev/null");
+ $status = $?;
+ if ($status) {
+ print " FAILED to run new DTC on $board\n";
+ }
+
+ if (-f $old_dtb_file && -f $new_dtb_file) {
+ print "CMP: $cmd_cmp\n";
+ system($cmd_cmp);
+ $status = $?;
+ if ($status) {
+ print " FAILED $board\n";
+ }
+ } else {
+ printf " FAILED: Missing dtb file\n";
+ }
+}
diff --git a/dtc/tests/test_label_ref.dts b/dtc/tests/test_label_ref.dts
new file mode 100644
index 000000000..7009c7953
--- /dev/null
+++ b/dtc/tests/test_label_ref.dts
@@ -0,0 +1,9 @@
+/dts-v1/;
+
+/ {
+
+};
+
+label: &handle {
+
+};
diff --git a/dtc/tests/test_props.dts b/dtc/tests/test_props.dts
new file mode 100644
index 000000000..7e59bd1b8
--- /dev/null
+++ b/dtc/tests/test_props.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/ {
+ compatible = "test_props";
+ prop-hex32 = <0xdeadbeef>;
+ prop-uint32 = <123>;
+ prop-int32 = <0xfffffffe>;
+ prop-hex64 = /bits/ 64 <0xdeadbeef01abcdef>;
+ prop-uint64 = /bits/ 64 <9223372036854775807>;
+ prop-int64 = /bits/ 64 <0xfffffffffffffffe>;
+};
diff --git a/dtc/tests/test_tree1.dts b/dtc/tests/test_tree1.dts
new file mode 100644
index 000000000..77ea32569
--- /dev/null
+++ b/dtc/tests/test_tree1.dts
@@ -0,0 +1,46 @@
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 123456789 010000;
+
+/ {
+ compatible = "test_tree1";
+ prop-int = <0xdeadbeef>;
+ prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
+ prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+ prop-int = [deadbeef];
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ placeholder = "this is a placeholder string", "string2";
+ prop-int = <0xdeadbeef>;
+ };
+
+ ss1 {
+ };
+ };
+
+ subnode@2 {
+ reg = <2>;
+ linux,phandle = <0x2000>;
+ prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ssn0: subsubnode@0 {
+ reg = <0>;
+ phandle = <0x2001>;
+ compatible = "subsubnode2", "subsubnode";
+ prop-int = <0726746425>;
+ };
+
+ ss2 {
+ };
+ };
+};
diff --git a/dtc/tests/test_tree1_delete.dts b/dtc/tests/test_tree1_delete.dts
new file mode 100644
index 000000000..b95ef1e71
--- /dev/null
+++ b/dtc/tests/test_tree1_delete.dts
@@ -0,0 +1,68 @@
+/dts-v1/;
+
+/include/ "test_tree1.dts"
+
+/ {
+ nonexistant-property = <0xdeadbeef>;
+
+ nonexistant-subnode {
+ prop-int = <1>;
+ };
+
+ dellabel: deleted-by-label {
+ prop-int = <1>;
+ };
+
+ subnode@1 {
+ delete-this-str = "deadbeef";
+ };
+
+};
+
+/ {
+ /delete-property/ nonexistant-property;
+
+ /delete-node/ nonexistant-subnode;
+
+ subnode@1 {
+ /delete-property/ delete-this-str;
+ };
+};
+
+/delete-node/ &dellabel;
+
+/ {
+ /delete-property/ prop-str;
+};
+
+/ {
+ prop-str = "hello world";
+};
+
+/ {
+ subnode@1 {
+ /delete-node/ ss1;
+ };
+};
+
+/ {
+ subnode@1 {
+ ss1 {
+ };
+ };
+};
+
+/{
+ duplabel1: foo1 = "bar";
+ duplabel2: foo2 = "bar";
+};
+
+/{
+ duplabel1: baz1 = "qux";
+ duplabel2: baz2 = "qux";
+};
+
+/{
+ /delete-property/ foo1;
+ /delete-property/ baz2;
+};
diff --git a/dtc/tests/test_tree1_label_noderef.dts b/dtc/tests/test_tree1_label_noderef.dts
new file mode 100644
index 000000000..cfe5946f8
--- /dev/null
+++ b/dtc/tests/test_tree1_label_noderef.dts
@@ -0,0 +1,56 @@
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 123456789 010000;
+
+/ {
+ compatible = "test_tree1";
+ prop-int = <0xdeadbeef>;
+ prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
+ prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+ prop-int = [deadbeef];
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ placeholder = "this is a placeholder string", "string2";
+ prop-int = <0xdeadbeef>;
+ };
+
+ ss1 {
+ };
+ };
+
+ subnode@2 {
+ reg = <2>;
+ linux,phandle = <0x2000>;
+ prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ssn0: subsubnode@0 {
+ phandle = <0x2001>;
+ prop-int = <0xbad>;
+ };
+
+ ss2 {
+ };
+ };
+};
+
+/* Add label to a noderef */
+ssn1: &ssn0 {
+ reg = <0>;
+ prop-int = <123456789>;
+};
+
+/* Use the new label for merging */
+&ssn1 {
+ prop-int = <0726746425>;
+ compatible = "subsubnode2", "subsubnode";
+};
diff --git a/dtc/tests/test_tree1_merge.dts b/dtc/tests/test_tree1_merge.dts
new file mode 100644
index 000000000..b100c12de
--- /dev/null
+++ b/dtc/tests/test_tree1_merge.dts
@@ -0,0 +1,51 @@
+/dts-v1/;
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 123456789 010000;
+
+/ {
+ compatible = "test_tree1";
+ prop-int = "wrong!";
+ prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ prop-int = <0xdeadbeef>;
+ };
+
+ ss1 {
+ };
+ };
+
+ subnode@2 {
+ reg = <2>;
+ linux,phandle = <0x2000>;
+ prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ss2 {
+ };
+ };
+};
+
+/ {
+ prop-int = <0xdeadbeef>;
+ prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
+ subnode@1 {
+ prop-int = [deadbeef];
+ };
+ subnode@2 {
+ ssn0: subsubnode@0 {
+ reg = <0>;
+ phandle = <0x2001>;
+ compatible = "subsubnode2", "subsubnode";
+ prop-int = <0726746425>;
+ };
+ };
+};
diff --git a/dtc/tests/test_tree1_merge_labelled.dts b/dtc/tests/test_tree1_merge_labelled.dts
new file mode 100644
index 000000000..fcf5dc45a
--- /dev/null
+++ b/dtc/tests/test_tree1_merge_labelled.dts
@@ -0,0 +1,49 @@
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 123456789 010000;
+
+/ {
+ compatible = "test_tree1";
+ prop-int = <0xdeadbeef>;
+ prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
+ prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+ prop-int = [deadbeef];
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ prop-int = <0xdeadbeef>;
+ };
+
+ ss1 {
+ };
+ };
+
+ subnode@2 {
+ reg = <2>;
+ linux,phandle = <0x2000>;
+ prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ssn0: subsubnode@0 {
+ reg = <0>;
+ phandle = <0x2001>;
+ prop-int = <0xbad>;
+ };
+
+ ss2 {
+ };
+ };
+};
+
+&ssn0 {
+ compatible = "subsubnode2", "subsubnode";
+ prop-int = <0726746425>;
+};
diff --git a/dtc/tests/test_tree1_merge_path.dts b/dtc/tests/test_tree1_merge_path.dts
new file mode 100644
index 000000000..c2ad82972
--- /dev/null
+++ b/dtc/tests/test_tree1_merge_path.dts
@@ -0,0 +1,49 @@
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 123456789 010000;
+
+/ {
+ compatible = "test_tree1";
+ prop-int = <0xdeadbeef>;
+ prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
+ prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+ prop-int = [deadbeef];
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ prop-int = <0xdeadbeef>;
+ };
+
+ ss1 {
+ };
+ };
+
+ subnode@2 {
+ reg = <2>;
+ linux,phandle = <0x2000>;
+ prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ssn0: subsubnode@0 {
+ reg = <0>;
+ phandle = <0x2001>;
+ prop-int = <0xbad>;
+ };
+
+ ss2 {
+ };
+ };
+};
+
+&{/subnode@2/subsubnode@0} {
+ compatible = "subsubnode2", "subsubnode";
+ prop-int = <0726746425>;
+};
diff --git a/dtc/tests/test_tree1_wrong1.dts b/dtc/tests/test_tree1_wrong1.dts
new file mode 100644
index 000000000..900d38582
--- /dev/null
+++ b/dtc/tests/test_tree1_wrong1.dts
@@ -0,0 +1,43 @@
+/dts-v1/;
+
+/memreserve/ 123456789 010000;
+
+/ {
+ compatible = "test_tree1";
+ prop-int = <0xdeadbeef>;
+ prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+ prop-int = [deadbeef];
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ prop-int = <0xdeadbeef>;
+ };
+
+ ss1 {
+ };
+ };
+
+ subnode@2 {
+ reg = <2>;
+ linux,phandle = <0x2000>;
+ prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subsubnode@0 {
+ reg = <0>;
+ phandle = <0x2001>;
+ compatible = "subsubnode2", "subsubnode";
+ prop-int = <0726746425>;
+ };
+
+ ss2 {
+ };
+ };
+};
diff --git a/dtc/tests/test_tree1_wrong2.dts b/dtc/tests/test_tree1_wrong2.dts
new file mode 100644
index 000000000..099752b37
--- /dev/null
+++ b/dtc/tests/test_tree1_wrong2.dts
@@ -0,0 +1,43 @@
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 123456789 010000;
+
+/ {
+ compatible = "test_tree1";
+ prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+ prop-int = [deadbeef];
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ prop-int = <0xdeadbeef>;
+ };
+
+ ss1 {
+ };
+ };
+
+ subnode@2 {
+ reg = <2>;
+ linux,phandle = <0x2000>;
+ prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subsubnode@0 {
+ reg = <0>;
+ phandle = <0x2001>;
+ compatible = "subsubnode2", "subsubnode";
+ prop-int = <0726746425>;
+ };
+
+ ss2 {
+ };
+ };
+};
diff --git a/dtc/tests/test_tree1_wrong3.dts b/dtc/tests/test_tree1_wrong3.dts
new file mode 100644
index 000000000..069353a94
--- /dev/null
+++ b/dtc/tests/test_tree1_wrong3.dts
@@ -0,0 +1,43 @@
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 123456789 010000;
+
+/ {
+ compatible = "test_tree1";
+ prop-int = <0xdeadbeef>;
+ prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ prop-int = <0xdeadbeef>;
+ };
+
+ ss1 {
+ };
+ };
+
+ subnode@2 {
+ reg = <2>;
+ linux,phandle = <0x2000>;
+ prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subsubnode@0 {
+ reg = <0>;
+ phandle = <0x2001>;
+ compatible = "subsubnode2", "subsubnode";
+ prop-int = <0726746425>;
+ };
+
+ ss2 {
+ };
+ };
+};
diff --git a/dtc/tests/test_tree1_wrong4.dts b/dtc/tests/test_tree1_wrong4.dts
new file mode 100644
index 000000000..2c5641618
--- /dev/null
+++ b/dtc/tests/test_tree1_wrong4.dts
@@ -0,0 +1,41 @@
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 123456789 010000;
+
+/ {
+ compatible = "test_tree1";
+ prop-int = <0xdeadbeef>;
+ prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+ prop-int = [deadbeef];
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ prop-int = <0xdeadbeef>;
+ };
+
+ ss1 {
+ };
+ };
+
+ subnode@2 {
+ reg = <2>;
+ linux,phandle = <0x2000>;
+ prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subsubnode@0 {
+ reg = <0>;
+ phandle = <0x2001>;
+ compatible = "subsubnode2", "subsubnode";
+ prop-int = <0726746425>;
+ };
+ };
+};
diff --git a/dtc/tests/test_tree1_wrong5.dts b/dtc/tests/test_tree1_wrong5.dts
new file mode 100644
index 000000000..6ddd72d52
--- /dev/null
+++ b/dtc/tests/test_tree1_wrong5.dts
@@ -0,0 +1,44 @@
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 123456789 010000;
+
+/ {
+ compatible = "test_tree1";
+ prop-int = <0xdeadbefe>;
+ prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+ prop-int = [deadbeef];
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ prop-int = <0xdeadbeef>;
+ };
+
+ ss1 {
+ };
+ };
+
+ subnode@2 {
+ reg = <2>;
+ linux,phandle = <0x2000>;
+ prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subsubnode@0 {
+ reg = <0>;
+ phandle = <0x2001>;
+ compatible = "subsubnode2", "subsubnode";
+ prop-int = <0726746425>;
+ };
+
+ ss2 {
+ };
+ };
+};
diff --git a/dtc/tests/test_tree1_wrong6.dts b/dtc/tests/test_tree1_wrong6.dts
new file mode 100644
index 000000000..36b4e1f66
--- /dev/null
+++ b/dtc/tests/test_tree1_wrong6.dts
@@ -0,0 +1,45 @@
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 123456789 010000;
+
+/ {
+ compatible = "test_tree1";
+ prop-int = <0xdeadbeef>;
+ prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+ prop-int = [deadbeef];
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ prop-int = <0xdeadbeef>;
+ };
+
+ ss1 {
+ extra-prop;
+ };
+ };
+
+ subnode@2 {
+ reg = <2>;
+ linux,phandle = <0x2000>;
+ prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subsubnode@0 {
+ reg = <0>;
+ phandle = <0x2001>;
+ compatible = "subsubnode2", "subsubnode";
+ prop-int = <0726746425>;
+ };
+
+ ss2 {
+ };
+ };
+};
diff --git a/dtc/tests/test_tree1_wrong7.dts b/dtc/tests/test_tree1_wrong7.dts
new file mode 100644
index 000000000..54150e6d9
--- /dev/null
+++ b/dtc/tests/test_tree1_wrong7.dts
@@ -0,0 +1,46 @@
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 123456789 010000;
+
+/ {
+ compatible = "test_tree1";
+ prop-int = <0xdeadbeef>;
+ prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+ prop-int = [deadbeef];
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ prop-int = <0xdeadbeef>;
+ };
+
+ ss1 {
+ };
+ };
+
+ subnode@2 {
+ reg = <2>;
+ linux,phandle = <0x2000>;
+ prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subsubnode@0 {
+ reg = <0>;
+ phandle = <0x2001>;
+ compatible = "subsubnode2", "subsubnode";
+ prop-int = <0726746425>;
+ };
+
+ ss2 {
+ extranode {
+ };
+ };
+ };
+};
diff --git a/dtc/tests/test_tree1_wrong8.dts b/dtc/tests/test_tree1_wrong8.dts
new file mode 100644
index 000000000..7a28a9f29
--- /dev/null
+++ b/dtc/tests/test_tree1_wrong8.dts
@@ -0,0 +1,44 @@
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 123456789 010001;
+
+/ {
+ compatible = "test_tree1";
+ prop-int = <0xdeadbeef>;
+ prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+ prop-int = [deadbeef];
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ prop-int = <0xdeadbeef>;
+ };
+
+ ss1 {
+ };
+ };
+
+ subnode@2 {
+ linux,phandle = <0x2000>;
+ prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+
+ subsubnode@0 {
+ reg = <0>;
+ phandle = <0x2001>;
+ compatible = "subsubnode2", "subsubnode";
+ prop-int = <0726746425>;
+ };
+
+ ss2 {
+ };
+ };
+};
diff --git a/dtc/tests/test_tree1_wrong9.dts b/dtc/tests/test_tree1_wrong9.dts
new file mode 100644
index 000000000..f6486fa93
--- /dev/null
+++ b/dtc/tests/test_tree1_wrong9.dts
@@ -0,0 +1,45 @@
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 123456789 010000;
+/memreserve/ 0 1;
+
+/ {
+ compatible = "test_tree1";
+ prop-int = <0xdeadbeef>;
+ prop-str = "hello world";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subnode@1 {
+ compatible = "subnode1";
+ reg = <1>;
+ prop-int = [deadbeef];
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ prop-int = <0xdeadbeef>;
+ };
+
+ ss1 {
+ };
+ };
+
+ subnode@2 {
+ reg = <2>;
+ linux,phandle = <0x2000>;
+ prop-int = <123456789>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ subsubnode@0 {
+ reg = <0>;
+ phandle = <0x2001>;
+ compatible = "subsubnode2", "subsubnode";
+ prop-int = <0726746425>;
+ };
+
+ ss2 {
+ };
+ };
+};
diff --git a/dtc/tests/testdata.h b/dtc/tests/testdata.h
new file mode 100644
index 000000000..4f9e3ba07
--- /dev/null
+++ b/dtc/tests/testdata.h
@@ -0,0 +1,60 @@
+#ifdef __ASSEMBLY__
+#define ASM_CONST_LL(x) (x)
+#else
+#define ASM_CONST_LL(x) (x##ULL)
+#endif
+
+#define TEST_ADDR_1H ASM_CONST_LL(0xdeadbeef)
+#define TEST_ADDR_1L ASM_CONST_LL(0x00000000)
+#define TEST_ADDR_1 ((TEST_ADDR_1H << 32) | TEST_ADDR_1L)
+#define TEST_SIZE_1H ASM_CONST_LL(0x00000000)
+#define TEST_SIZE_1L ASM_CONST_LL(0x00100000)
+#define TEST_SIZE_1 ((TEST_SIZE_1H << 32) | TEST_SIZE_1L)
+#define TEST_ADDR_2H ASM_CONST_LL(0)
+#define TEST_ADDR_2L ASM_CONST_LL(123456789)
+#define TEST_ADDR_2 ((TEST_ADDR_2H << 32) | TEST_ADDR_2L)
+#define TEST_SIZE_2H ASM_CONST_LL(0)
+#define TEST_SIZE_2L ASM_CONST_LL(010000)
+#define TEST_SIZE_2 ((TEST_SIZE_2H << 32) | TEST_SIZE_2L)
+
+#define TEST_VALUE_1 0xdeadbeef
+#define TEST_VALUE_2 123456789
+
+#define TEST_VALUE64_1H ASM_CONST_LL(0xdeadbeef)
+#define TEST_VALUE64_1L ASM_CONST_LL(0x01abcdef)
+#define TEST_VALUE64_1 ((TEST_VALUE64_1H << 32) | TEST_VALUE64_1L)
+
+#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"
+
+#define TEST_STRING_4_PARTIAL "foobar"
+#define TEST_STRING_4_RESULT "testfoobar"
+
+#define TEST_CHAR1 '\r'
+#define TEST_CHAR2 'b'
+#define TEST_CHAR3 '\0'
+#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;
+extern struct fdt_header bad_node_char;
+extern struct fdt_header bad_node_format;
+extern struct fdt_header bad_prop_char;
+extern struct fdt_header ovf_size_strings;
+extern struct fdt_header truncated_string;
+extern struct fdt_header truncated_memrsv;
+extern struct fdt_header two_roots;
+extern struct fdt_header named_root;
+#endif /* ! __ASSEMBLY */
diff --git a/dtc/tests/tests.h b/dtc/tests/tests.h
new file mode 100644
index 000000000..1017366b2
--- /dev/null
+++ b/dtc/tests/tests.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#ifndef TESTS_H
+#define TESTS_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase definitions
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#define DEBUG
+
+/* Test return codes */
+#define RC_PASS 0
+#define RC_CONFIG 1
+#define RC_FAIL 2
+#define RC_BUG 99
+
+extern int verbose_test;
+extern char *test_name;
+void test_init(int argc, char *argv[]);
+
+#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
+#define PALIGN(p, a) ((void *)ALIGN((unsigned long)(p), (a)))
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define streq(s1, s2) (strcmp((s1),(s2)) == 0)
+
+/* Each test case must define this function */
+void cleanup(void);
+
+#define verbose_printf(...) \
+ if (verbose_test) { \
+ printf(__VA_ARGS__); \
+ fflush(stdout); \
+ }
+#define ERR "ERR: "
+#define ERROR(fmt, args...) fprintf(stderr, ERR fmt, ## args)
+
+
+#define PASS() \
+ do { \
+ cleanup(); \
+ printf("PASS\n"); \
+ exit(RC_PASS); \
+ } while (0)
+
+#define PASS_INCONCLUSIVE() \
+ do { \
+ cleanup(); \
+ printf("PASS (inconclusive)\n"); \
+ exit(RC_PASS); \
+ } while (0)
+
+#define IRRELEVANT() \
+ do { \
+ cleanup(); \
+ printf("PASS (irrelevant)\n"); \
+ exit(RC_PASS); \
+ } while (0)
+
+/* Look out, gcc extension below... */
+#define FAIL(fmt, ...) \
+ do { \
+ cleanup(); \
+ printf("FAIL\t" fmt "\n", ##__VA_ARGS__); \
+ exit(RC_FAIL); \
+ } while (0)
+
+#define CONFIG(fmt, ...) \
+ do { \
+ cleanup(); \
+ printf("Bad configuration: " fmt "\n", ##__VA_ARGS__); \
+ exit(RC_CONFIG); \
+ } while (0)
+
+#define TEST_BUG(fmt, ...) \
+ do { \
+ cleanup(); \
+ printf("BUG in testsuite: " fmt "\n", ##__VA_ARGS__); \
+ exit(RC_BUG); \
+ } while (0)
+
+void check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size);
+
+void check_property(void *fdt, int nodeoffset, const char *name,
+ int len, const void *val);
+#define check_property_cell(fdt, nodeoffset, name, val) \
+ ({ \
+ fdt32_t x = cpu_to_fdt32(val); \
+ check_property(fdt, nodeoffset, name, sizeof(x), &x); \
+ })
+
+
+const void *check_getprop(void *fdt, int nodeoffset, const char *name,
+ int len, const void *val);
+#define check_getprop_cell(fdt, nodeoffset, name, val) \
+ ({ \
+ fdt32_t x = cpu_to_fdt32(val); \
+ check_getprop(fdt, nodeoffset, name, sizeof(x), &x); \
+ })
+#define check_getprop_64(fdt, nodeoffset, name, val) \
+ ({ \
+ fdt64_t x = cpu_to_fdt64(val); \
+ check_getprop(fdt, nodeoffset, name, sizeof(x), &x); \
+ })
+#define check_getprop_string(fdt, nodeoffset, name, s) \
+ check_getprop((fdt), (nodeoffset), (name), strlen(s)+1, (s))
+
+/* Returns non-NULL if the property at poffset has the name in_name */
+const void *check_get_prop_offset(void *fdt, int poffset, const char *in_name,
+ int in_len, const void *in_val);
+#define check_get_prop_offset_cell(fdt, poffset, name, val) \
+ ({ \
+ fdt32_t x = cpu_to_fdt32(val); \
+ 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);
+void *load_blob_arg(int argc, char *argv[]);
+void save_blob(const char *filename, void *blob);
+void *open_blob_rw(void *blob);
+
+#include "util.h"
+
+#endif /* TESTS_H */
diff --git a/dtc/tests/testutils.c b/dtc/tests/testutils.c
new file mode 100644
index 000000000..5e494c559
--- /dev/null
+++ b/dtc/tests/testutils.c
@@ -0,0 +1,351 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase common utility functions
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#define _GNU_SOURCE /* for strsignal() in glibc. FreeBSD has it either way */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#if NO_VALGRIND
+static inline void VALGRIND_MAKE_MEM_UNDEFINED(void *p, size_t len)
+{
+}
+
+static inline void VALGRIND_MAKE_MEM_DEFINED(void *p, size_t len)
+{
+}
+#else
+#include <valgrind/memcheck.h>
+#endif
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+/* For FDT_SW_MAGIC */
+#include "libfdt_internal.h"
+
+int verbose_test = 1;
+char *test_name;
+
+void __attribute__((weak)) cleanup(void)
+{
+}
+
+static void sigint_handler(int signum, siginfo_t *si, void *uc)
+{
+ cleanup();
+ fprintf(stderr, "%s: %s (pid=%d)\n", test_name,
+ strsignal(signum), getpid());
+ exit(RC_BUG);
+}
+
+void test_init(int argc, char *argv[])
+{
+ int err;
+ struct sigaction sa_int = {
+ .sa_sigaction = sigint_handler,
+ };
+
+ test_name = argv[0];
+
+ err = sigaction(SIGINT, &sa_int, NULL);
+ if (err)
+ FAIL("Can't install SIGINT handler");
+
+ if (getenv("QUIET_TEST"))
+ verbose_test = 0;
+
+ verbose_printf("Starting testcase \"%s\", pid %d\n",
+ test_name, getpid());
+}
+
+void check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size)
+{
+ int err;
+ uint64_t addr_v, size_v;
+
+ err = fdt_get_mem_rsv(fdt, n, &addr_v, &size_v);
+ if (err < 0)
+ FAIL("fdt_get_mem_rsv(%d): %s", n, fdt_strerror(err));
+ if ((addr_v != addr) || (size_v != size))
+ FAIL("fdt_get_mem_rsv() returned (0x%llx,0x%llx) "
+ "instead of (0x%llx,0x%llx)",
+ (unsigned long long)addr_v, (unsigned long long)size_v,
+ (unsigned long long)addr, (unsigned long long)size);
+}
+
+void check_property(void *fdt, int nodeoffset, const char *name,
+ int len, const void *val)
+{
+ const struct fdt_property *prop;
+ int retlen, namelen;
+ uint32_t tag, nameoff, proplen;
+ const char *propname;
+
+ verbose_printf("Checking property \"%s\"...", name);
+ prop = fdt_get_property(fdt, nodeoffset, name, &retlen);
+ verbose_printf("pointer %p\n", prop);
+ if (! prop)
+ FAIL("Error retrieving \"%s\" pointer: %s", name,
+ fdt_strerror(retlen));
+
+ tag = fdt32_to_cpu(prop->tag);
+ nameoff = fdt32_to_cpu(prop->nameoff);
+ proplen = fdt32_to_cpu(prop->len);
+
+ if (tag != FDT_PROP)
+ FAIL("Incorrect tag 0x%08x on property \"%s\"", tag, name);
+
+ propname = fdt_get_string(fdt, nameoff, &namelen);
+ if (!propname)
+ FAIL("Couldn't get property name: %s", fdt_strerror(namelen));
+ if (namelen != strlen(propname))
+ FAIL("Incorrect prop name length: %d instead of %zd",
+ namelen, strlen(propname));
+ if (!streq(propname, name))
+ FAIL("Property name mismatch \"%s\" instead of \"%s\"",
+ propname, name);
+ if (proplen != retlen)
+ FAIL("Length retrieved for \"%s\" by fdt_get_property()"
+ " differs from stored length (%d != %d)",
+ name, retlen, proplen);
+ if (proplen != len)
+ FAIL("Size mismatch on property \"%s\": %d insead of %d",
+ name, proplen, len);
+ if (len && memcmp(val, prop->data, len) != 0)
+ FAIL("Data mismatch on property \"%s\"", name);
+}
+
+const void *check_getprop(void *fdt, int nodeoffset, const char *name,
+ int len, const void *val)
+{
+ const void *propval;
+ int proplen;
+
+ propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
+ if (! propval)
+ FAIL("fdt_getprop(\"%s\"): %s", name, fdt_strerror(proplen));
+
+ if (proplen != len)
+ FAIL("Size mismatch on property \"%s\": %d insead of %d",
+ name, proplen, len);
+ if (len && memcmp(val, propval, len) != 0)
+ FAIL("Data mismatch on property \"%s\"", name);
+
+ return propval;
+}
+
+const void *check_get_prop_offset(void *fdt, int poffset, const char *exp_name,
+ int exp_len, const void *exp_val)
+{
+ const void *propval;
+ const char *name;
+ int proplen;
+
+ propval = fdt_getprop_by_offset(fdt, poffset, &name, &proplen);
+ if (!propval)
+ FAIL("fdt_getprop(\"%s\"): %s", name, fdt_strerror(proplen));
+
+ /* Not testing for this field, so ignore */
+ if (strcmp(name, exp_name))
+ return NULL;
+
+ if (proplen != exp_len)
+ FAIL("Size mismatch on property \"%s\": %d insead of %d",
+ name, proplen, exp_len);
+ if (exp_len && memcmp(exp_val, propval, exp_len))
+ FAIL("Data mismatch on property \"%s\"", 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)
+{
+ int len = strlen(s2);
+
+ if (strncmp(s1, s2, len) != 0)
+ return 0;
+ if (s1[len] == '\0')
+ return 1;
+ else if (!memchr(s2, '@', len) && (s1[len] == '@'))
+ return 1;
+ else
+ return 0;
+}
+
+void vg_prepare_blob(void *fdt, size_t bufsize)
+{
+ char *blob = fdt;
+ int off_memrsv, off_strings, off_struct;
+ int num_memrsv;
+ size_t size_memrsv, size_strings, size_struct;
+
+ off_memrsv = fdt_off_mem_rsvmap(fdt);
+ num_memrsv = fdt_num_mem_rsv(fdt);
+ if (num_memrsv < 0)
+ size_memrsv = fdt_totalsize(fdt) - off_memrsv;
+ else
+ size_memrsv = (num_memrsv + 1)
+ * sizeof(struct fdt_reserve_entry);
+
+ VALGRIND_MAKE_MEM_UNDEFINED(blob, bufsize);
+ VALGRIND_MAKE_MEM_DEFINED(blob, FDT_V1_SIZE);
+ VALGRIND_MAKE_MEM_DEFINED(blob, fdt_header_size(fdt));
+
+ if (fdt_magic(fdt) == FDT_MAGIC) {
+ off_strings = fdt_off_dt_strings(fdt);
+ if (fdt_version(fdt) >= 3)
+ size_strings = fdt_size_dt_strings(fdt);
+ else
+ size_strings = fdt_totalsize(fdt) - off_strings;
+
+ off_struct = fdt_off_dt_struct(fdt);
+ if (fdt_version(fdt) >= 17)
+ size_struct = fdt_size_dt_struct(fdt);
+ else
+ size_struct = fdt_totalsize(fdt) - off_struct;
+ } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
+ size_strings = fdt_size_dt_strings(fdt);
+ off_strings = fdt_off_dt_strings(fdt) - size_strings;
+
+ off_struct = fdt_off_dt_struct(fdt);
+ size_struct = fdt_size_dt_struct(fdt);
+ size_struct = fdt_totalsize(fdt) - off_struct;
+
+ } else {
+ CONFIG("Bad magic on vg_prepare_blob()");
+ }
+
+ VALGRIND_MAKE_MEM_DEFINED(blob + off_memrsv, size_memrsv);
+ VALGRIND_MAKE_MEM_DEFINED(blob + off_strings, size_strings);
+ VALGRIND_MAKE_MEM_DEFINED(blob + off_struct, size_struct);
+}
+
+void *load_blob(const char *filename)
+{
+ char *blob;
+ size_t len;
+ int ret = utilfdt_read_err(filename, &blob, &len);
+
+ if (ret)
+ CONFIG("Couldn't open blob from \"%s\": %s", filename,
+ strerror(ret));
+
+ vg_prepare_blob(blob, len);
+
+ return blob;
+}
+
+void *load_blob_arg(int argc, char *argv[])
+{
+ if (argc != 2)
+ CONFIG("Usage: %s <dtb file>", argv[0]);
+ return load_blob(argv[1]);
+}
+
+void save_blob(const char *filename, void *fdt)
+{
+ size_t size = fdt_totalsize(fdt);
+ void *tmp;
+ int ret;
+
+ /* Make a temp copy of the blob so that valgrind won't check
+ * about uninitialized bits in the pieces between blocks */
+ tmp = xmalloc(size);
+ fdt_move(fdt, tmp, size);
+ VALGRIND_MAKE_MEM_DEFINED(tmp, size);
+ ret = utilfdt_write_err(filename, tmp);
+ if (ret)
+ CONFIG("Couldn't write blob to \"%s\": %s", filename,
+ strerror(ret));
+ free(tmp);
+}
+
+void *open_blob_rw(void *blob)
+{
+ int err;
+ void *buf = blob;
+
+ err = fdt_open_into(blob, buf, fdt_totalsize(blob));
+ if (err == -FDT_ERR_NOSPACE) {
+ /* Ran out of space converting to v17 */
+ int newsize = fdt_totalsize(blob) + 8;
+
+ buf = xmalloc(newsize);
+ err = fdt_open_into(blob, buf, newsize);
+ }
+ if (err)
+ FAIL("fdt_open_into(): %s", fdt_strerror(err));
+ return buf;
+}
diff --git a/dtc/tests/testutils.sh b/dtc/tests/testutils.sh
new file mode 100644
index 000000000..6b2f0d14e
--- /dev/null
+++ b/dtc/tests/testutils.sh
@@ -0,0 +1,67 @@
+# Common functions for shell testcases
+
+PASS () {
+ echo "PASS"
+ exit 0
+}
+
+FAIL () {
+ echo "FAIL" "$@"
+ exit 2
+}
+
+FAIL_IF_SIGNAL () {
+ ret="$1"
+ if [ "$ret" -gt 127 ]; then
+ signame=$(kill -l $((ret - 128)))
+ FAIL "Killed by SIG$signame"
+ fi
+}
+
+if [ -z "$TEST_BINDIR" ]; then
+ TEST_BINDIR=..
+fi
+
+DTC=${TEST_BINDIR}/dtc
+DTGET=${TEST_BINDIR}/fdtget
+DTPUT=${TEST_BINDIR}/fdtput
+FDTDUMP=${TEST_BINDIR}/fdtdump
+FDTOVERLAY=${TEST_BINDIR}/fdtoverlay
+
+verbose_run () {
+ if [ -z "$QUIET_TEST" ]; then
+ "$@"
+ else
+ "$@" > /dev/null 2> /dev/null
+ fi
+}
+
+verbose_run_check () {
+ verbose_run "$@"
+ ret="$?"
+ FAIL_IF_SIGNAL $ret
+ if [ $ret != 0 ]; then
+ FAIL "Returned error code $ret"
+ fi
+}
+
+verbose_run_log () {
+ LOG="$1"
+ shift
+ "$@" > "$LOG" 2>&1
+ ret=$?
+ if [ -z "$QUIET_TEST" ]; then
+ cat "$LOG" >&2
+ fi
+ return $ret
+}
+
+verbose_run_log_check () {
+ verbose_run_log "$@"
+ ret="$?"
+ FAIL_IF_SIGNAL $ret
+ if [ $ret != 0 ]; then
+ FAIL "Returned error code $ret"
+ fi
+}
+
diff --git a/dtc/tests/trees.S b/dtc/tests/trees.S
new file mode 100644
index 000000000..95d599d68
--- /dev/null
+++ b/dtc/tests/trees.S
@@ -0,0 +1,315 @@
+#include <fdt.h>
+#include "testdata.h"
+
+#define FDTLONG(val) \
+ .byte ((val) >> 24) & 0xff ; \
+ .byte ((val) >> 16) & 0xff ; \
+ .byte ((val) >> 8) & 0xff ; \
+ .byte (val) & 0xff ;
+
+#define TREE_HDR(tree) \
+ .balign 8 ; \
+ .globl tree ; \
+tree: \
+ FDTLONG(FDT_MAGIC) ; \
+ FDTLONG(tree##_end - tree) ; \
+ FDTLONG(tree##_struct - tree) ; \
+ FDTLONG(tree##_strings - tree) ; \
+ FDTLONG(tree##_rsvmap - tree) ; \
+ FDTLONG(0x11) ; \
+ FDTLONG(0x10) ; \
+ FDTLONG(0) ; \
+ FDTLONG(tree##_strings_end - tree##_strings) ; \
+ FDTLONG(tree##_struct_end - tree##_struct) ;
+
+#define RSVMAP_ENTRY(addrh, addrl, lenh, lenl) \
+ FDTLONG(addrh) ; \
+ FDTLONG(addrl) ; \
+ FDTLONG(lenh) ; \
+ FDTLONG(lenl)
+
+#define EMPTY_RSVMAP(tree) \
+ .balign 8 ; \
+tree##_rsvmap: ; \
+ RSVMAP_ENTRY(0, 0, 0, 0) \
+tree##_rsvmap_end: ;
+
+#define PROPHDR(tree, name, len) \
+ FDTLONG(FDT_PROP) ; \
+ FDTLONG(len) ; \
+ FDTLONG(tree##_##name - tree##_strings) ;
+
+#define PROP_EMPTY(tree, name) \
+ PROPHDR(tree, name, 0) ;
+
+#define PROP_INT(tree, name, val) \
+ PROPHDR(tree, name, 4) \
+ FDTLONG(val) ;
+
+#define PROP_INT64(tree, name, valh, vall) \
+ PROPHDR(tree, name, 8) \
+ FDTLONG(valh) ; \
+ FDTLONG(vall) ;
+
+#define PROP_STR(tree, name, str) \
+ PROPHDR(tree, name, 55f - 54f) \
+54: \
+ .string str ; \
+55: \
+ .balign 4 ;
+
+#define BEGIN_NODE(name) \
+ FDTLONG(FDT_BEGIN_NODE) ; \
+ .string name ; \
+ .balign 4 ;
+
+#define END_NODE \
+ FDTLONG(FDT_END_NODE) ;
+
+#define STRING(tree, name, str) \
+tree##_##name: ; \
+ .string str ;
+
+ .data
+
+ TREE_HDR(test_tree1)
+
+ .balign 8
+test_tree1_rsvmap:
+ RSVMAP_ENTRY(TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L)
+ RSVMAP_ENTRY(TEST_ADDR_2H, TEST_ADDR_2L, TEST_SIZE_2H, TEST_SIZE_2L)
+ RSVMAP_ENTRY(0, 0, 0, 0)
+test_tree1_rsvmap_end:
+
+test_tree1_struct:
+ BEGIN_NODE("")
+ PROP_STR(test_tree1, compatible, "test_tree1")
+ PROP_INT(test_tree1, prop_int, TEST_VALUE_1)
+ PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1H, TEST_VALUE64_1L)
+ PROP_STR(test_tree1, prop_str, TEST_STRING_1)
+ PROP_INT(test_tree1, address_cells, 1)
+ PROP_INT(test_tree1, size_cells, 0)
+
+ BEGIN_NODE("subnode@1")
+ PROP_STR(test_tree1, compatible, "subnode1")
+ PROP_INT(test_tree1, reg, 1)
+ PROP_INT(test_tree1, prop_int, TEST_VALUE_1)
+
+ BEGIN_NODE("subsubnode")
+ PROP_STR(test_tree1, compatible, "subsubnode1\0subsubnode")
+ PROP_STR(test_tree1, placeholder, "this is a placeholder string\0string2")
+ PROP_INT(test_tree1, prop_int, TEST_VALUE_1)
+ END_NODE
+
+ BEGIN_NODE("ss1")
+ END_NODE
+
+ END_NODE
+
+ BEGIN_NODE("subnode@2")
+ PROP_INT(test_tree1, reg, 2)
+ PROP_INT(test_tree1, linux_phandle, PHANDLE_1)
+ PROP_INT(test_tree1, prop_int, TEST_VALUE_2)
+ PROP_INT(test_tree1, address_cells, 1)
+ PROP_INT(test_tree1, size_cells, 0)
+
+ BEGIN_NODE("subsubnode@0")
+ PROP_INT(test_tree1, reg, 0)
+ PROP_INT(test_tree1, phandle, PHANDLE_2)
+ PROP_STR(test_tree1, compatible, "subsubnode2\0subsubnode")
+ PROP_INT(test_tree1, prop_int, TEST_VALUE_2)
+ END_NODE
+
+ BEGIN_NODE("ss2")
+ END_NODE
+
+ END_NODE
+
+ END_NODE
+ FDTLONG(FDT_END)
+test_tree1_struct_end:
+
+test_tree1_strings:
+ STRING(test_tree1, compatible, "compatible")
+ STRING(test_tree1, prop_int, "prop-int")
+ STRING(test_tree1, prop_int64, "prop-int64")
+ STRING(test_tree1, prop_str, "prop-str")
+ STRING(test_tree1, linux_phandle, "linux,phandle")
+ STRING(test_tree1, phandle, "phandle")
+ STRING(test_tree1, reg, "reg")
+ STRING(test_tree1, placeholder, "placeholder")
+ STRING(test_tree1, address_cells, "#address-cells")
+ STRING(test_tree1, size_cells, "#size-cells")
+test_tree1_strings_end:
+test_tree1_end:
+
+
+ TREE_HDR(truncated_property)
+ EMPTY_RSVMAP(truncated_property)
+
+truncated_property_struct:
+ BEGIN_NODE("")
+ PROPHDR(truncated_property, prop_truncated, 4)
+ /* Oops, no actual property data here */
+truncated_property_struct_end:
+
+truncated_property_strings:
+ STRING(truncated_property, prop_truncated, "truncated")
+truncated_property_strings_end:
+
+truncated_property_end:
+
+
+ TREE_HDR(bad_node_char)
+ EMPTY_RSVMAP(bad_node_char)
+
+bad_node_char_struct:
+ BEGIN_NODE("")
+ BEGIN_NODE("sub$node")
+ END_NODE
+ END_NODE
+ FDTLONG(FDT_END)
+bad_node_char_struct_end:
+
+bad_node_char_strings:
+bad_node_char_strings_end:
+bad_node_char_end:
+
+
+ TREE_HDR(bad_node_format)
+ EMPTY_RSVMAP(bad_node_format)
+
+bad_node_format_struct:
+ BEGIN_NODE("")
+ BEGIN_NODE("subnode@1@2")
+ END_NODE
+ END_NODE
+ FDTLONG(FDT_END)
+bad_node_format_struct_end:
+
+bad_node_format_strings:
+bad_node_format_strings_end:
+bad_node_format_end:
+
+
+ TREE_HDR(bad_prop_char)
+ EMPTY_RSVMAP(bad_prop_char)
+
+bad_prop_char_struct:
+ BEGIN_NODE("")
+ PROP_INT(bad_prop_char, prop, TEST_VALUE_1)
+ END_NODE
+ FDTLONG(FDT_END)
+bad_prop_char_struct_end:
+
+bad_prop_char_strings:
+ STRING(bad_prop_char, prop, "prop$erty")
+bad_prop_char_strings_end:
+bad_prop_char_end:
+
+
+ /* overflow_size_strings */
+ .balign 8
+ .globl ovf_size_strings
+ovf_size_strings:
+ FDTLONG(FDT_MAGIC)
+ FDTLONG(ovf_size_strings_end - ovf_size_strings)
+ FDTLONG(ovf_size_strings_struct - ovf_size_strings)
+ FDTLONG(ovf_size_strings_strings - ovf_size_strings)
+ FDTLONG(ovf_size_strings_rsvmap - ovf_size_strings)
+ FDTLONG(0x11)
+ FDTLONG(0x10)
+ FDTLONG(0)
+ FDTLONG(0xffffffff)
+ FDTLONG(ovf_size_strings_struct_end - ovf_size_strings_struct)
+ EMPTY_RSVMAP(ovf_size_strings)
+
+ovf_size_strings_struct:
+ BEGIN_NODE("")
+ PROP_INT(ovf_size_strings, bad_string, 0)
+ END_NODE
+ FDTLONG(FDT_END)
+ovf_size_strings_struct_end:
+
+ovf_size_strings_strings:
+ STRING(ovf_size_strings, x, "x")
+ ovf_size_strings_bad_string = ovf_size_strings_strings + 0x10000000
+ovf_size_strings_strings_end:
+ovf_size_strings_end:
+
+
+ /* truncated_string */
+ TREE_HDR(truncated_string)
+ EMPTY_RSVMAP(truncated_string)
+
+truncated_string_struct:
+ BEGIN_NODE("")
+ PROP_EMPTY(truncated_string, good_string)
+ PROP_EMPTY(truncated_string, bad_string)
+ END_NODE
+ FDTLONG(FDT_END)
+truncated_string_struct_end:
+
+truncated_string_strings:
+ STRING(truncated_string, good_string, "good")
+truncated_string_bad_string:
+ .byte 'b'
+ .byte 'a'
+ .byte 'd'
+ /* NOTE: terminating \0 deliberately missing */
+truncated_string_strings_end:
+truncated_string_end:
+
+
+ /* truncated_memrsv */
+ TREE_HDR(truncated_memrsv)
+
+truncated_memrsv_struct:
+ BEGIN_NODE("")
+ END_NODE
+ FDTLONG(FDT_END)
+truncated_memrsv_struct_end:
+
+truncated_memrsv_strings:
+truncated_memrsv_strings_end:
+
+ .balign 8
+truncated_memrsv_rsvmap:
+ RSVMAP_ENTRY(TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L)
+truncated_memrsv_rsvmap_end:
+
+truncated_memrsv_end:
+
+
+ /* two root nodes */
+ TREE_HDR(two_roots)
+ EMPTY_RSVMAP(two_roots)
+
+two_roots_struct:
+ BEGIN_NODE("")
+ END_NODE
+ BEGIN_NODE("")
+ END_NODE
+ FDTLONG(FDT_END)
+two_roots_struct_end:
+
+two_roots_strings:
+two_roots_strings_end:
+
+two_roots_end:
+
+
+ /* root node with a non-empty name */
+ TREE_HDR(named_root)
+ EMPTY_RSVMAP(named_root)
+
+named_root_struct:
+ BEGIN_NODE("fake")
+ END_NODE
+ FDTLONG(FDT_END)
+named_root_struct_end:
+
+named_root_strings:
+named_root_strings_end:
+
+named_root_end:
diff --git a/dtc/tests/truncated_memrsv.c b/dtc/tests/truncated_memrsv.c
new file mode 100644
index 000000000..d78036cc9
--- /dev/null
+++ b/dtc/tests/truncated_memrsv.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for misbehaviour on a truncated string
+ * Copyright (C) 2018 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt = &truncated_memrsv;
+ int err;
+ uint64_t addr, size;
+
+ test_init(argc, argv);
+
+ err = fdt_check_header(fdt);
+ if (err != 0)
+ FAIL("Bad header: %s", fdt_strerror(err));
+
+ err = fdt_num_mem_rsv(fdt);
+ if (err != -FDT_ERR_TRUNCATED)
+ FAIL("fdt_num_mem_rsv() returned %d instead of -FDT_ERR_TRUNCATED",
+ err);
+
+ err = fdt_get_mem_rsv(fdt, 0, &addr, &size);
+ if (err != 0)
+ FAIL("fdt_get_mem_rsv() failed on first entry: %s",
+ fdt_strerror(err));
+ if ((addr != TEST_ADDR_1) || (size != TEST_SIZE_1))
+ FAIL("Entry doesn't match: (0x%llx, 0x%llx) != (0x%llx, 0x%llx)",
+ (unsigned long long)addr, (unsigned long long)size,
+ TEST_ADDR_1, TEST_SIZE_1);
+
+ err = fdt_get_mem_rsv(fdt, 1, &addr, &size);
+ if (err != -FDT_ERR_BADOFFSET)
+ FAIL("fdt_get_mem_rsv(1) returned %d instead of -FDT_ERR_BADOFFSET",
+ err);
+
+ PASS();
+}
diff --git a/dtc/tests/truncated_property.c b/dtc/tests/truncated_property.c
new file mode 100644
index 000000000..d9d52b2f3
--- /dev/null
+++ b/dtc/tests/truncated_property.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for misbehaviour on a truncated property
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt = &truncated_property;
+ const void *prop;
+ int len;
+
+ test_init(argc, argv);
+
+ vg_prepare_blob(fdt, fdt_totalsize(fdt));
+
+ prop = fdt_getprop(fdt, 0, "truncated", &len);
+ if (prop)
+ FAIL("fdt_getprop() succeeded on truncated property");
+ if (len != -FDT_ERR_BADSTRUCTURE)
+ FAIL("fdt_getprop() failed with \"%s\" instead of \"%s\"",
+ fdt_strerror(len), fdt_strerror(-FDT_ERR_BADSTRUCTURE));
+
+ PASS();
+}
diff --git a/dtc/tests/truncated_string.c b/dtc/tests/truncated_string.c
new file mode 100644
index 000000000..d7454147b
--- /dev/null
+++ b/dtc/tests/truncated_string.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Testcase for misbehaviour on a truncated string
+ * Copyright (C) 2018 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+ void *fdt = &truncated_string;
+ const struct fdt_property *good, *bad;
+ int off, len;
+ const char *name;
+
+ test_init(argc, argv);
+
+ vg_prepare_blob(fdt, fdt_totalsize(fdt));
+
+ off = fdt_first_property_offset(fdt, 0);
+ good = fdt_get_property_by_offset(fdt, off, NULL);
+
+ off = fdt_next_property_offset(fdt, off);
+ bad = fdt_get_property_by_offset(fdt, off, NULL);
+
+ if (fdt32_to_cpu(good->len) != 0)
+ FAIL("Unexpected length for good property");
+ name = fdt_get_string(fdt, fdt32_to_cpu(good->nameoff), &len);
+ if (!name)
+ FAIL("fdt_get_string() failed on good property: %s",
+ fdt_strerror(len));
+ if (len != 4)
+ FAIL("fdt_get_string() returned length %d (not 4) on good property",
+ len);
+ if (!streq(name, "good"))
+ FAIL("fdt_get_string() returned \"%s\" (not \"good\") on good property",
+ name);
+
+ if (fdt32_to_cpu(bad->len) != 0)
+ FAIL("Unexpected length for bad property\n");
+ name = fdt_get_string(fdt, fdt32_to_cpu(bad->nameoff), &len);
+ if (name)
+ FAIL("fdt_get_string() succeeded incorrectly on bad property");
+ else if (len != -FDT_ERR_TRUNCATED)
+ FAIL("fdt_get_string() gave unexpected error on bad property: %s",
+ fdt_strerror(len));
+
+ /* Make sure the 'good' property breaks correctly if we
+ * truncate the strings section */
+ fdt_set_size_dt_strings(fdt, fdt32_to_cpu(good->nameoff) + 4);
+ name = fdt_get_string(fdt, fdt32_to_cpu(good->nameoff), &len);
+ if (name)
+ FAIL("fdt_get_string() succeeded incorrectly on mangled property");
+ else if (len != -FDT_ERR_TRUNCATED)
+ FAIL("fdt_get_string() gave unexpected error on mangled property: %s",
+ fdt_strerror(len));
+
+ PASS();
+}
diff --git a/dtc/tests/type-preservation.dt.yaml b/dtc/tests/type-preservation.dt.yaml
new file mode 100644
index 000000000..ee8cfdebe
--- /dev/null
+++ b/dtc/tests/type-preservation.dt.yaml
@@ -0,0 +1,20 @@
+---
+- '#address-cells': [[0x1]]
+ '#size-cells': [[0x0]]
+ subnode@1:
+ compatible: ["subnode1"]
+ reg: [[0x1]]
+ int-array: [[0x0, 0x1], [0x2, 0x3]]
+ int8: [!u8 [0x56]]
+ int8-array: [!u8 [0x0, 0x12, 0x34, 0x56]]
+ int16: [!u16 [0x3210]]
+ int16-array: [!u16 [0x1234, 0x5678, 0x90ab, 0xcdef]]
+ int16-matrix: [!u16 [0x1234, 0x5678], [0x90ab, 0xcdef]]
+ int64: [!u64 [0x200000000]]
+ int64-array: [!u64 [0x100000000, 0x0]]
+ a-string-with-nulls: ["foo\0bar", "baz"]
+ subsubnode:
+ compatible: ["subsubnode1", "subsubnode"]
+ subsubsubnode:
+ compatible: ["subsubsubnode1", [0x1234], "subsubsubnode"]
+...
diff --git a/dtc/tests/type-preservation.dts b/dtc/tests/type-preservation.dts
new file mode 100644
index 000000000..3e380ba6c
--- /dev/null
+++ b/dtc/tests/type-preservation.dts
@@ -0,0 +1,28 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <0x01>;
+ #size-cells = <0x00>;
+
+ sub1: subnode@1 {
+ prop_label: compatible = value_label: "subnode1";
+ reg = <0x01>;
+ int-array = <0x00 0x01>, int_value_label: <0x02 0x03>;
+ int8 = [56];
+ int8-array = [00 12 34 56] label:;
+ int16 = /bits/ 16 <0x3210>;
+ int16-array = /bits/ 16 <0x1234 0x5678 0x90ab 0xcdef>;
+ int16-matrix = /bits/ 16 <0x1234 0x5678>, <0x90ab 0xcdef>;
+ int64 = /bits/ 64 <0x200000000>;
+ int64-array = /bits/ 64 <0x100000000 0x00> int64_array_label_end:;
+ a-string-with-nulls = "foo\0bar", "baz";
+
+ subsub1: subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+
+ subsubsub1: subsubsubnode {
+ compatible = "subsubsubnode1", <0x1234>, valuea: valueb: "subsubsubnode";
+ };
+ };
+ };
+};
diff --git a/dtc/tests/unit-addr-leading-0s.dts b/dtc/tests/unit-addr-leading-0s.dts
new file mode 100644
index 000000000..cc017e943
--- /dev/null
+++ b/dtc/tests/unit-addr-leading-0s.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ bus {
+ node@001 {
+ reg = <1 0>;
+ };
+ };
+};
diff --git a/dtc/tests/unit-addr-leading-0x.dts b/dtc/tests/unit-addr-leading-0x.dts
new file mode 100644
index 000000000..74f19678c
--- /dev/null
+++ b/dtc/tests/unit-addr-leading-0x.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ bus {
+ node@0x1 {
+ reg = <1 0>;
+ };
+ };
+};
diff --git a/dtc/tests/unit-addr-simple-bus-compatible.dts b/dtc/tests/unit-addr-simple-bus-compatible.dts
new file mode 100644
index 000000000..c8f9341c1
--- /dev/null
+++ b/dtc/tests/unit-addr-simple-bus-compatible.dts
@@ -0,0 +1,18 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ bus@10000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "foo-bus", "simple-bus";
+ ranges = <0x0 0x10000000 0x10000>;
+
+ node@100 {
+ reg = <0x1000 1>;
+ };
+ };
+
+};
diff --git a/dtc/tests/unit-addr-simple-bus-reg-mismatch.dts b/dtc/tests/unit-addr-simple-bus-reg-mismatch.dts
new file mode 100644
index 000000000..282337770
--- /dev/null
+++ b/dtc/tests/unit-addr-simple-bus-reg-mismatch.dts
@@ -0,0 +1,18 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ bus@10000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x0 0x10000000 0x10000>;
+
+ node@100 {
+ reg = <0x1000 1>;
+ };
+ };
+
+};
diff --git a/dtc/tests/unit-addr-unique.dts b/dtc/tests/unit-addr-unique.dts
new file mode 100644
index 000000000..7cc650b40
--- /dev/null
+++ b/dtc/tests/unit-addr-unique.dts
@@ -0,0 +1,14 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ foo@1 {
+ reg = <1>;
+ };
+
+ bar@1 {
+ reg = <1>;
+ };
+};
diff --git a/dtc/tests/unit-addr-without-reg.dts b/dtc/tests/unit-addr-without-reg.dts
new file mode 100644
index 000000000..ac786ebb6
--- /dev/null
+++ b/dtc/tests/unit-addr-without-reg.dts
@@ -0,0 +1,9 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ node@1 {
+ };
+};
diff --git a/dtc/tests/utilfdt_test.c b/dtc/tests/utilfdt_test.c
new file mode 100644
index 000000000..c62175935
--- /dev/null
+++ b/dtc/tests/utilfdt_test.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * Copyright 2011 The Chromium Authors, All Rights Reserved.
+ *
+ * utilfdt_test - Tests for utilfdt library
+ */
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdarg.h>
+
+#include <libfdt.h>
+#include <util.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check(const char *fmt, int expect_type, int expect_size)
+{
+ int type;
+ int size;
+
+ if (utilfdt_decode_type(fmt, &type, &size))
+ FAIL("format '%s': valid format string returned failure", fmt);
+ if (expect_type != type)
+ FAIL("format '%s': expected type='%c', got type='%c'", fmt,
+ expect_type, type);
+ if (expect_size != size)
+ FAIL("format '%s': expected size=%d, got size=%d", fmt,
+ expect_size, size);
+}
+
+static void checkfail(const char *fmt)
+{
+ int type;
+ int size;
+
+ if (!utilfdt_decode_type(fmt, &type, &size))
+ FAIL("format '%s': invalid format string returned success",
+ fmt);
+}
+
+/**
+ * Add the given modifier to each of the valid sizes, and check that we get
+ * correct values.
+ *
+ * \param modifier Modifer string to use as a prefix
+ * \param expected_size The size (in bytes) that we expect (ignored for
+ * strings)
+ */
+static void check_sizes(char *modifier, int expected_size)
+{
+ char fmt[10], *ptr;
+
+ /* set up a string with a hole in it for the format character */
+ if (strlen(modifier) + 2 >= sizeof(fmt))
+ FAIL("modifier string '%s' too long", modifier);
+ strcpy(fmt, modifier);
+ ptr = fmt + strlen(fmt);
+ ptr[1] = '\0';
+
+ /* now try each format character in turn */
+ *ptr = 'i';
+ check(fmt, 'i', expected_size);
+
+ *ptr = 'u';
+ check(fmt, 'u', expected_size);
+
+ *ptr = 'x';
+ check(fmt, 'x', expected_size);
+
+ *ptr = 's';
+ check(fmt, 's', -1);
+}
+
+static void test_utilfdt_decode_type(void)
+{
+ char fmt[10];
+ int ch;
+
+ /* check all the valid modifiers and sizes */
+ check_sizes("", -1);
+ check_sizes("b", 1);
+ check_sizes("hh", 1);
+ check_sizes("h", 2);
+ check_sizes("l", 4);
+
+ /* try every other character */
+ checkfail("");
+ for (ch = ' '; ch < 127; ch++) {
+ if (!strchr("iuxs", ch)) {
+ *fmt = ch;
+ fmt[1] = '\0';
+ checkfail(fmt);
+ }
+ }
+
+ /* try a few modifiers at the end */
+ checkfail("sx");
+ checkfail("ihh");
+ checkfail("xb");
+
+ /* and one for the doomsday archives */
+ checkfail("He has all the virtues I dislike and none of the vices "
+ "I admire.");
+}
+
+int main(int argc, char *argv[])
+{
+ test_utilfdt_decode_type();
+ PASS();
+}
diff --git a/dtc/tests/value-labels.c b/dtc/tests/value-labels.c
new file mode 100644
index 000000000..e3183574d
--- /dev/null
+++ b/dtc/tests/value-labels.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Test labels within values
+ * Copyright (C) 2008 David Gibson, IBM Corporation.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include <dlfcn.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+struct val_label {
+ const char *labelname;
+ int propoff;
+};
+
+static struct val_label labels1[] = {
+ { "start1", 0 },
+ { "mid1", 2 },
+ { "end1", -1 },
+};
+
+static struct val_label labels2[] = {
+ { "start2", 0 },
+ { "innerstart2", 0 },
+ { "innermid2", 4 },
+ { "innerend2", -1 },
+ { "end2", -1 },
+};
+
+static struct val_label labels3[] = {
+ { "start3", 0 },
+ { "innerstart3", 0 },
+ { "innermid3", 1 },
+ { "innerend3", -1 },
+ { "end3", -1 },
+};
+
+static void check_prop_labels(void *sohandle, void *fdt, const char *name,
+ const struct val_label* labels, int n)
+{
+ const struct fdt_property *prop;
+ const char *p;
+ int len;
+ int i;
+
+ prop = fdt_get_property(fdt, 0, name, &len);
+ if (!prop)
+ FAIL("Couldn't locate property \"%s\"", name);
+
+ p = dlsym(sohandle, name);
+ if (!p)
+ FAIL("Couldn't locate label symbol \"%s\"", name);
+
+ if (p != (const char *)prop)
+ FAIL("Label \"%s\" does not point to correct property", name);
+
+ for (i = 0; i < n; i++) {
+ int off = labels[i].propoff;
+
+ if (off == -1)
+ off = len;
+
+ p = dlsym(sohandle, labels[i].labelname);
+ if (!p)
+ FAIL("Couldn't locate label symbol \"%s\"", name);
+
+ if ((p - prop->data) != off)
+ FAIL("Label \"%s\" points to offset %ld instead of %d"
+ "in property \"%s\"", labels[i].labelname,
+ (long)(p - prop->data), off, name);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ void *sohandle;
+ void *fdt;
+ int err;
+
+ test_init(argc, argv);
+ if (argc != 2)
+ CONFIG("Usage: %s <so file>", argv[0]);
+
+ sohandle = dlopen(argv[1], RTLD_NOW);
+ if (!sohandle)
+ FAIL("Couldn't dlopen() %s", argv[1]);
+
+ fdt = dlsym(sohandle, "dt_blob_start");
+ if (!fdt)
+ FAIL("Couldn't locate \"dt_blob_start\" symbol in %s",
+ argv[1]);
+
+ err = fdt_check_header(fdt);
+ if (err != 0)
+ FAIL("%s contains invalid tree: %s", argv[1],
+ fdt_strerror(err));
+
+
+ check_prop_labels(sohandle, fdt, "prop1", labels1, ARRAY_SIZE(labels1));
+ check_prop_labels(sohandle, fdt, "prop2", labels2, ARRAY_SIZE(labels2));
+ check_prop_labels(sohandle, fdt, "prop3", labels3, ARRAY_SIZE(labels3));
+
+ PASS();
+}
diff --git a/dtc/tests/value-labels.dts b/dtc/tests/value-labels.dts
new file mode 100644
index 000000000..490c609f7
--- /dev/null
+++ b/dtc/tests/value-labels.dts
@@ -0,0 +1,8 @@
+/dts-v1/;
+
+/ {
+ prop1: prop1 = start1: "a", mid1: "b" end1:;
+ prop2: prop2 = start2: < innerstart2: 0xdeadbeef innermid2: 0xabcd1234 innerend2: > end2:;
+ prop3: prop3 = start3: [ innerstart3: ab innermid3: cd innerend3: ] end3:;
+};
+
diff --git a/dtc/tests/zero-phandle.dts b/dtc/tests/zero-phandle.dts
new file mode 100644
index 000000000..7997d980d
--- /dev/null
+++ b/dtc/tests/zero-phandle.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+ node {
+ linux,phandle = <0>;
+ };
+};