diff --git a/Makefile b/Makefile index 8d5b929..1cfa28a 100644 --- a/Makefile +++ b/Makefile @@ -175,7 +175,7 @@ include tests/Makefile.tests # # Clean rules # -STD_CLEANFILES = *~ *.o *.d *.a *.i *.s core a.out vgcore.* \ +STD_CLEANFILES = *~ *.o *.so *.d *.a *.i *.s core a.out vgcore.* \ *.tab.[ch] *.lex.c *.output clean: libfdt_clean tests_clean diff --git a/flattree.c b/flattree.c index 9197511..0ff8c45 100644 --- a/flattree.c +++ b/flattree.c @@ -127,11 +127,21 @@ static void emit_offset_label(FILE *f, const char *label, int offset) fprintf(f, "%s\t= . + %d\n", label, offset); } +#define ASM_EMIT_BELONG(f, fmt, ...) \ + { \ + fprintf((f), "\t.byte\t((" fmt ") >> 24) & 0xff\n", __VA_ARGS__); \ + fprintf((f), "\t.byte\t((" fmt ") >> 16) & 0xff\n", __VA_ARGS__); \ + fprintf((f), "\t.byte\t((" fmt ") >> 8) & 0xff\n", __VA_ARGS__); \ + fprintf((f), "\t.byte\t(" fmt ") & 0xff\n", __VA_ARGS__); \ + } + static void asm_emit_cell(void *e, cell_t val) { FILE *f = e; - fprintf(f, "\t.long\t0x%x\n", val); + fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n", + (val >> 24) & 0xff, (val >> 16) & 0xff, + (val >> 8) & 0xff, val & 0xff); } static void asm_emit_string(void *e, char *str, int len) @@ -169,8 +179,7 @@ static void asm_emit_data(void *e, struct data d) emit_offset_label(f, m->ref, m->offset); while ((d.len - off) >= sizeof(uint32_t)) { - fprintf(f, "\t.long\t0x%x\n", - fdt32_to_cpu(*((uint32_t *)(d.val+off)))); + asm_emit_cell(e, fdt32_to_cpu(*((uint32_t *)(d.val+off)))); off += sizeof(uint32_t); } @@ -190,14 +199,16 @@ static void asm_emit_beginnode(void *e, const char *label) fprintf(f, "\t.globl\t%s\n", label); fprintf(f, "%s:\n", label); } - fprintf(f, "\t.long\tFDT_BEGIN_NODE\n"); + fprintf(f, "\t/* FDT_BEGIN_NODE */\n"); + asm_emit_cell(e, FDT_BEGIN_NODE); } static void asm_emit_endnode(void *e, const char *label) { FILE *f = e; - fprintf(f, "\t.long\tFDT_END_NODE\n"); + fprintf(f, "\t/* FDT_END_NODE */\n"); + asm_emit_cell(e, FDT_END_NODE); if (label) { fprintf(f, "\t.globl\t%s_end\n", label); fprintf(f, "%s_end:\n", label); @@ -212,7 +223,8 @@ static void asm_emit_property(void *e, const char *label) fprintf(f, "\t.globl\t%s\n", label); fprintf(f, "%s:\n", label); } - fprintf(f, "\t.long\tFDT_PROP\n"); + fprintf(f, "\t/* FDT_PROP */\n"); + asm_emit_cell(e, FDT_PROP); } static struct emitter asm_emitter = { @@ -458,39 +470,44 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version) die("Unknown device tree blob version %d\n", version); fprintf(f, "/* autogenerated by dtc, do not edit */\n\n"); - fprintf(f, "#define FDT_MAGIC 0x%x\n", FDT_MAGIC); - fprintf(f, "#define FDT_BEGIN_NODE 0x%x\n", FDT_BEGIN_NODE); - fprintf(f, "#define FDT_END_NODE 0x%x\n", FDT_END_NODE); - fprintf(f, "#define FDT_PROP 0x%x\n", FDT_PROP); - fprintf(f, "#define FDT_END 0x%x\n", FDT_END); - fprintf(f, "\n"); emit_label(f, symprefix, "blob_start"); emit_label(f, symprefix, "header"); - fprintf(f, "\t.long\tFDT_MAGIC\t\t\t\t/* magic */\n"); - fprintf(f, "\t.long\t_%s_blob_abs_end - _%s_blob_start\t/* totalsize */\n", - symprefix, symprefix); - fprintf(f, "\t.long\t_%s_struct_start - _%s_blob_start\t/* off_dt_struct */\n", + fprintf(f, "\t/* magic */\n"); + asm_emit_cell(f, FDT_MAGIC); + fprintf(f, "\t/* totalsize */\n"); + ASM_EMIT_BELONG(f, "_%s_blob_abs_end - _%s_blob_start", + symprefix, symprefix); + fprintf(f, "\t/* off_dt_struct */\n"); + ASM_EMIT_BELONG(f, "_%s_struct_start - _%s_blob_start", symprefix, symprefix); - fprintf(f, "\t.long\t_%s_strings_start - _%s_blob_start\t/* off_dt_strings */\n", + fprintf(f, "\t/* off_dt_strings */\n"); + ASM_EMIT_BELONG(f, "_%s_strings_start - _%s_blob_start", symprefix, symprefix); - fprintf(f, "\t.long\t_%s_reserve_map - _%s_blob_start\t/* off_dt_strings */\n", + fprintf(f, "\t/* off_mem_rsvmap */\n"); + ASM_EMIT_BELONG(f, "_%s_reserve_map - _%s_blob_start", symprefix, symprefix); - fprintf(f, "\t.long\t%d\t\t\t\t\t/* version */\n", vi->version); - fprintf(f, "\t.long\t%d\t\t\t\t\t/* last_comp_version */\n", - vi->last_comp_version); - - if (vi->flags & FTF_BOOTCPUID) - fprintf(f, "\t.long\t%i\t\t\t\t\t/* boot_cpuid_phys */\n", - bi->boot_cpuid_phys); + fprintf(f, "\t/* version */\n"); + asm_emit_cell(f, vi->version); + fprintf(f, "\t/* last_comp_version */\n"); + asm_emit_cell(f, vi->last_comp_version); + + if (vi->flags & FTF_BOOTCPUID) { + fprintf(f, "\t/* boot_cpuid_phys */\n"); + asm_emit_cell(f, bi->boot_cpuid_phys); + } - if (vi->flags & FTF_STRTABSIZE) - fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n", - symprefix, symprefix); + if (vi->flags & FTF_STRTABSIZE) { + fprintf(f, "\t/* size_dt_strings */\n"); + ASM_EMIT_BELONG(f, "_%s_strings_end - _%s_strings_start", + symprefix, symprefix); + } - if (vi->flags & FTF_STRUCTSIZE) - fprintf(f, "\t.long\t_%s_struct_end - _%s_struct_start\t/* size_dt_struct */\n", + if (vi->flags & FTF_STRUCTSIZE) { + fprintf(f, "\t/* size_dt_struct */\n"); + ASM_EMIT_BELONG(f, "_%s_struct_end - _%s_struct_start", symprefix, symprefix); + } /* * Reserve map entries. @@ -512,12 +529,11 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version) fprintf(f, "\t.globl\t%s\n", re->label); fprintf(f, "%s:\n", re->label); } - fprintf(f, "\t.long\t0x%08x, 0x%08x\n", - (unsigned int)(re->re.address >> 32), - (unsigned int)(re->re.address & 0xffffffff)); - fprintf(f, "\t.long\t0x%08x, 0x%08x\n", - (unsigned int)(re->re.size >> 32), - (unsigned int)(re->re.size & 0xffffffff)); + ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32)); + ASM_EMIT_BELONG(f, "0x%08x", + (unsigned int)(re->re.address & 0xffffffff)); + ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32)); + ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff)); } for (i = 0; i < reservenum; i++) { fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); @@ -527,7 +543,9 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version) emit_label(f, symprefix, "struct_start"); flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi); - fprintf(f, "\t.long\tFDT_END\n"); + + fprintf(f, "\t/* FDT_END */\n"); + asm_emit_cell(f, FDT_END); emit_label(f, symprefix, "struct_end"); emit_label(f, symprefix, "strings_start"); diff --git a/tests/Makefile.tests b/tests/Makefile.tests index 3a041ff..f09c72a 100644 --- a/tests/Makefile.tests +++ b/tests/Makefile.tests @@ -18,7 +18,10 @@ LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%) -TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) +DL_LIB_TESTS_L = asm_tree_dump +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)%) @@ -37,6 +40,8 @@ tests: $(TESTS) $(TESTS_TREES) $(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o $(LIBFDT_archive) +$(DL_LIB_TESTS): %: $(TESTS_PREFIX)testutils.o $(LIBFDT_archive) -ldl + $(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o $(LIBFDT_archive) $(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o diff --git a/tests/asm_tree_dump.c b/tests/asm_tree_dump.c new file mode 100644 index 0000000..5ff5087 --- /dev/null +++ b/tests/asm_tree_dump.c @@ -0,0 +1,62 @@ +/* + * 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. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#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 ", 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/tests/data.S b/tests/data.S new file mode 100644 index 0000000..86ad539 --- /dev/null +++ b/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/tests/run_tests.sh b/tests/run_tests.sh index b27e2b5..040eca9 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -71,6 +71,15 @@ run_dtc_test () { base_run_test wrap_test $VALGRIND $DTC "$@" } +asm_to_so () { + as -o $1.test.o data.S $1.test.s && \ + ld -shared -o $1.test.so $1.test.o +} + +asm_to_so_test () { + run_wrap_test asm_to_so "$@" +} + tree1_tests () { TREE=$1 @@ -228,6 +237,16 @@ dtc_tests () { run_dtc_test -I dtb -O dtb -o boot_cpuid_preserved_test_tree1.test.dtb boot_cpuid_test_tree1.test.dtb run_test dtbs_equal_ordered boot_cpuid_preserved_test_tree1.test.dtb boot_cpuid_test_tree1.test.dtb + # Check -Oasm mode + for tree in test_tree1.dts escapes.dts references.dts path-references.dts \ + comments.dts aliases.dts include0.dts incbin.dts ; do + run_dtc_test -I dts -O asm -o oasm_$tree.test.s $tree + asm_to_so_test oasm_$tree + run_dtc_test -I dts -O dtb -o $tree.test.dtb $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 + # Check -Odts mode preserve all dtb information for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb \ dtc_references.test.dtb; do