diff --git a/.github/workflows/test-parse-tools.yml b/.github/workflows/test-parse-tools.yml new file mode 100644 index 000000000..f8a2f1468 --- /dev/null +++ b/.github/workflows/test-parse-tools.yml @@ -0,0 +1,46 @@ +name: Test parsing tools (elf and fdt) + +on: + push: + branches: [ 'master', 'main', 'release/**' ] + pull_request: + branches: [ '*' ] + +jobs: + + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + submodules: true + + - name: Install cross compilers + run: | + sudo apt-get install -y gcc-arm-none-eabi gcc-powerpc-linux-gnu + + - name: make distclean + run: | + make distclean + + - name: Select config + run: | + cp config/examples/nxp-t1024.config .config + + - name: Build wolfBoot + run: | + make + + - name: Build tools + run: | + make elf-parser + make fdt-parser + + - name: Run elf-parser test + run: | + ./tools/elf-parser/elf-parser + + - name: Run fdt-parser test (nxp_t1024.dtb) + run: | + ./tools/fdt-parser/fdt-parser ./tools/fdt-parser/nxp_t1024.dtb -t diff --git a/hal/nxp_t1024.c b/hal/nxp_t1024.c index 48ccf02fc..6a0323750 100644 --- a/hal/nxp_t1024.c +++ b/hal/nxp_t1024.c @@ -1984,9 +1984,12 @@ int hal_dts_fixup(void* dts_addr) uint64_t core_spin_table; reg = (uint32_t*)fdt_getprop(fdt, off, "reg", NULL); - if (reg == NULL || *reg >= CPU_NUMCORES) + if (reg == NULL) break; - core = *reg; + core = (int)fdt32_to_cpu(*reg); + if (core >= CPU_NUMCORES) { + break; /* invalid core index */ + } /* calculate location of spin table for core */ core_spin_table = (uint64_t)((uintptr_t)( @@ -2035,14 +2038,18 @@ int hal_dts_fixup(void* dts_addr) /* fixup the QMAN portals */ off = fdt_node_offset_by_compatible(fdt, -1, "fsl,qman-portal"); while (off != -FDT_ERR_NOTFOUND) { - const int *ci = fdt_getprop(fdt, off, "cell-index", NULL); uint32_t liodns[2]; - if (!ci) - break; - i = *ci; + reg = (uint32_t*)fdt_getprop(fdt, off, "cell-index", NULL); + if (reg == NULL) + break; + i = (int)fdt32_to_cpu(*reg); + if (i >= QMAN_NUM_PORTALS) { + break; /* invalid index */ + } liodns[0] = qp_info[i].dliodn; liodns[1] = qp_info[i].fliodn; + wolfBoot_printf("FDT: Set %s@%d (%d), %s=%d,%d\n", "qman-portal", i, off, "fsl,liodn", liodns[0], liodns[1]); fdt_setprop(fdt, off, "fsl,liodn", liodns, sizeof(liodns)); @@ -2055,8 +2062,6 @@ int hal_dts_fixup(void* dts_addr) if (off != -FDT_ERR_NOTFOUND) { fdt_fixup_val(fdt, off, "open-pic", "clock-frequency", hal_get_bus_clk()); } - - #endif /* !BUILD_LOADER_STAGE1 */ return 0; } diff --git a/include/fdt.h b/include/fdt.h index 24efb3a6b..7a74a8106 100644 --- a/include/fdt.h +++ b/include/fdt.h @@ -130,8 +130,8 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset); int fdt_next_property_offset(const void *fdt, int offset); const struct fdt_property *fdt_get_property_by_offset(const void *fdt, int offset, int *lenp); -const char *fdt_get_name(const void *fdt, int nodeoffset, int *len); -const char *fdt_get_string(const void *fdt, int stroffset, int *lenp); +const char* fdt_get_name(const void *fdt, int nodeoffset, int *len); +const char* fdt_get_string(const void *fdt, int stroffset, int *lenp); const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp); int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len); @@ -145,6 +145,8 @@ int fdt_fixup_str(void* fdt, int off, const char* node, const char* name, const int fdt_fixup_val(void* fdt, int off, const char* node, const char* name, uint32_t val); int fdt_fixup_val64(void* fdt, int off, const char* node, const char* name, uint64_t val); +int fdt_shrink(void* fdt); + #ifdef __cplusplus } #endif diff --git a/src/fdt.c b/src/fdt.c index f2bffcd5d..91039c7c3 100644 --- a/src/fdt.c +++ b/src/fdt.c @@ -30,6 +30,7 @@ #include "hal.h" #include "printf.h" #include "string.h" +#include uint32_t cpu_to_fdt32(uint32_t x) { @@ -293,7 +294,7 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, return prop; } -const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) +const char* fdt_get_name(const void *fdt, int nodeoffset, int *len) { int err; const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset); @@ -315,7 +316,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) return name; } -const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) +const char* fdt_get_string(const void *fdt, int stroffset, int *lenp) { const char *s = (const char*)fdt + fdt_off_dt_strings(fdt) + stroffset; if (lenp) { @@ -370,7 +371,7 @@ const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, return fdt_get_property_namelen(fdt, nodeoffset, name, strlen(name), lenp); } -struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, +static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, const char *name, int *lenp) { return (struct fdt_property*)(uintptr_t) @@ -443,7 +444,7 @@ static int fdt_splice_string_(void *fdt, int newlen) return 0; } -const char *fdt_find_string_(const char *strtab, int tabsize, const char *s) +const char* fdt_find_string_(const char *strtab, int tabsize, const char *s) { int len = strlen(s) + 1; const char *last = strtab + tabsize - len; @@ -584,7 +585,8 @@ int fdt_fixup_val(void* fdt, int off, const char* node, const char* name, int fdt_fixup_val64(void* fdt, int off, const char* node, const char* name, uint64_t val) { - wolfBoot_printf("FDT: Set %s (%d), %s=%lu\n", node, off, name, val); + wolfBoot_printf("FDT: Set %s (%d), %s=%llu\n", + node, off, name, (unsigned long long)val); val = cpu_to_fdt64(val); fdt_setprop(fdt, off, name, &val, sizeof(val)); return off; @@ -657,4 +659,14 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, return offset; } +int fdt_shrink(void* fdt) +{ + uint32_t total_size; + /* the last part of the FDT is the DT string, so use that offset to + * determine total size */ + total_size = fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); + + return fdt_set_totalsize(fdt, total_size); +} + #endif /* MMU && !BUILD_LOADER_STAGE1 */ diff --git a/test-app/Makefile b/test-app/Makefile index e0bca642c..91398def6 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -166,8 +166,13 @@ endif ifeq ($(TARGET),sim) APP_OBJS=app_$(TARGET).o ../test-app/libwolfboot.o ../hal/$(TARGET).o - # Override linker flags - LDFLAGS=-Wl,-Map=image.map + # LD on MacOS does not support "-Map=" + LDMAPSUPPORTED=$(shell $(CC) -Wl,-Map=image.map 2>&1 | grep 'unknown option') + LDFLAGS= + ifeq ($(LDMAPSUPPORTED),) + # Override linker flags + LDFLAGS+=-Wl,-Map=image.map + endif endif ifeq ($(EXT_FLASH),1) diff --git a/tools/elf-parser/Makefile b/tools/elf-parser/Makefile index fd89e343c..585d8a973 100644 --- a/tools/elf-parser/Makefile +++ b/tools/elf-parser/Makefile @@ -4,7 +4,7 @@ CC=gcc CFLAGS=-Wall -g -ggdb -CFLAGS+=-I../../include -DWOLFBOOT_ELF -DELF_PARSER -DPRINTF_ENABLED +CFLAGS+=-I../../include -DWOLFBOOT_ELF -DELF_PARSER -DDEBUG_ELF -DPRINTF_ENABLED EXE=elf-parser LIBS= diff --git a/tools/fdt-parser/bcm2710-rpi-3-b.dtb b/tools/fdt-parser/bcm2710-rpi-3-b.dtb new file mode 100644 index 000000000..8a13a454f Binary files /dev/null and b/tools/fdt-parser/bcm2710-rpi-3-b.dtb differ diff --git a/tools/fdt-parser/fdt-parser.c b/tools/fdt-parser/fdt-parser.c index e5a9306ca..aabe1bcf9 100644 --- a/tools/fdt-parser/fdt-parser.c +++ b/tools/fdt-parser/fdt-parser.c @@ -29,6 +29,182 @@ #include #include +static int gEnableUnitTest = 0; +#define UNIT_TEST_GROW_SIZE 1024 + +/* Test case for "nxp_t1024.dtb" */ +static int fdt_test(void* fdt) +{ + int off, i; + uint32_t *reg, oldsize; + + #define DDR_ADDRESS 0 + #define DDR_SIZE (2048ULL * 1024ULL * 1024ULL) + #define CPU_NUMCORES 2 + #define SPIN_TABLE_ADDR 0x7FF01900 + #define ENTRY_SIZE 64 + #define SYS_CLK (100000000) /* 100MHz */ + #define PLAT_CLK (SYS_CLK * 4) + #define BUS_CLK (PLAT_CLK / 2) + #define TIMEBASE_HZ (PLAT_CLK / 16) + + struct qportal_info { + uint16_t dliodn; /* DQRR LIODN */ + uint16_t fliodn; /* frame data LIODN */ + uint16_t liodn_offset; + uint8_t sdest; + }; + + #define SET_QP_INFO(dqrr, fdata, off, dest) \ + { .dliodn = dqrr, .fliodn = fdata, .liodn_offset = off, .sdest = dest } + + #define QMAN_NUM_PORTALS 10 + const struct qportal_info qp_info[QMAN_NUM_PORTALS] = { + /* dqrr liodn, frame data liodn, liodn off, sdest */ + SET_QP_INFO(1, 27, 1, 0), + SET_QP_INFO(2, 28, 1, 0), + SET_QP_INFO(3, 29, 1, 1), + SET_QP_INFO(4, 30, 1, 1), + SET_QP_INFO(5, 31, 1, 2), + SET_QP_INFO(6, 32, 1, 2), + SET_QP_INFO(7, 33, 1, 3), + SET_QP_INFO(8, 34, 1, 3), + SET_QP_INFO(9, 35, 1, 0), + SET_QP_INFO(10, 36, 1, 0) + }; + + struct liodn_id_table { + const char* compat; + uint32_t id; + }; + #define SET_LIODN(fdtcomp, liodn) \ + {.compat = fdtcomp, .id = liodn} + + const struct liodn_id_table liodn_tbl[] = { + SET_LIODN("fsl-usb2-mph", 553), + SET_LIODN("fsl-usb2-dr", 554), + SET_LIODN("fsl,esdhc", 552), + SET_LIODN("fsl,pq-sata-v2", 555), + SET_LIODN("fsl,tdm1.0", 560), + SET_LIODN("fsl,qe", 559), + SET_LIODN("fsl,elo3-dma", 147), + SET_LIODN("fsl,elo3-dma", 227), + + SET_LIODN("fsl,qman", 62), + SET_LIODN("fsl,bman", 63), + SET_LIODN("fsl,qoriq-pcie-v2.4", 148), + SET_LIODN("fsl,qoriq-pcie-v2.4", 228), + SET_LIODN("fsl,qoriq-pcie-v2.4", 308), + }; + + /* expand total size */ + oldsize = fdt_totalsize(fdt); + + /* fixup the memory region - single bank */ + off = fdt_find_devtype(fdt, -1, "memory"); + if (off != -FDT_ERR_NOTFOUND) { + /* build addr/size as 64-bit */ + uint8_t ranges[sizeof(uint64_t) * 2], *p = ranges; + *(uint64_t*)p = cpu_to_fdt64(DDR_ADDRESS); + p += sizeof(uint64_t); + *(uint64_t*)p = cpu_to_fdt64(DDR_SIZE); + p += sizeof(uint64_t); + fdt_setprop(fdt, off, "reg", ranges, (int)(p - ranges)); + wolfBoot_printf("FDT: Set memory, start=0x%x, size=0x%x\n", + DDR_ADDRESS, (uint32_t)DDR_SIZE); + } + + /* fixup CPU status and, release address and enable method */ + off = fdt_find_devtype(fdt, -1, "cpu"); + while (off != -FDT_ERR_NOTFOUND) { + int core; + uint64_t core_spin_table_addr; + + reg = (uint32_t*)fdt_getprop(fdt, off, "reg", NULL); + if (reg == NULL) + break; + core = (int)fdt32_to_cpu(*reg); + if (core >= CPU_NUMCORES) { + break; /* invalid core index */ + } + + /* calculate location of spin table for core */ + core_spin_table_addr = (uint64_t)((uintptr_t)( + (uint8_t*)SPIN_TABLE_ADDR + (core * ENTRY_SIZE))); + + fdt_fixup_str(fdt, off, "cpu", "status", (core == 0) ? "okay" : "disabled"); + fdt_fixup_val64(fdt, off, "cpu", "cpu-release-addr", core_spin_table_addr); + fdt_fixup_str(fdt, off, "cpu", "enable-method", "spin-table"); + fdt_fixup_val(fdt, off, "cpu", "timebase-frequency", TIMEBASE_HZ); + fdt_fixup_val(fdt, off, "cpu", "clock-frequency", PLAT_CLK); + fdt_fixup_val(fdt, off, "cpu", "bus-frequency", PLAT_CLK); + + off = fdt_find_devtype(fdt, off, "cpu"); + } + + /* fixup the soc clock */ + off = fdt_find_devtype(fdt, -1, "soc"); + if (off != -FDT_ERR_NOTFOUND) { + fdt_fixup_val(fdt, off, "soc", "bus-frequency", PLAT_CLK); + } + + /* fixup the serial clocks */ + off = fdt_find_devtype(fdt, -1, "serial"); + while (off != -FDT_ERR_NOTFOUND) { + fdt_fixup_val(fdt, off, "serial", "clock-frequency", BUS_CLK); + off = fdt_find_devtype(fdt, off, "serial"); + } + + /* fixup the QE bridge and bus blocks */ + off = fdt_find_devtype(fdt, -1, "qe"); + if (off != -FDT_ERR_NOTFOUND) { + fdt_fixup_val(fdt, off, "qe", "clock-frequency", BUS_CLK); + fdt_fixup_val(fdt, off, "qe", "bus-frequency", BUS_CLK); + fdt_fixup_val(fdt, off, "qe", "brg-frequency", BUS_CLK/2); + } + + /* fixup the LIODN */ + for (i=0; i<(int)(sizeof(liodn_tbl)/sizeof(struct liodn_id_table)); i++) { + off = fdt_node_offset_by_compatible(fdt, -1, liodn_tbl[i].compat); + if (off >= 0) { + fdt_fixup_val(fdt, off, liodn_tbl[i].compat, "fsl,liodn", + liodn_tbl[i].id); + } + } + + /* fixup the QMAN portals */ + off = fdt_node_offset_by_compatible(fdt, -1, "fsl,qman-portal"); + while (off != -FDT_ERR_NOTFOUND) { + const int *ci = fdt_getprop(fdt, off, "cell-index", NULL); + uint32_t liodns[2]; + if (!ci) + break; + i = fdt32_to_cpu(*ci); + + liodns[0] = qp_info[i].dliodn; + liodns[1] = qp_info[i].fliodn; + wolfBoot_printf("FDT: Set %s@%d (%d), %s=%d,%d\n", + "qman-portal", i, off, "fsl,liodn", liodns[0], liodns[1]); + fdt_setprop(fdt, off, "fsl,liodn", liodns, sizeof(liodns)); + + off = fdt_node_offset_by_compatible(fdt, off, "fsl,qman-portal"); + } + + /* mpic clock */ + off = fdt_find_devtype(fdt, -1, "open-pic"); + if (off != -FDT_ERR_NOTFOUND) { + fdt_fixup_val(fdt, off, "open-pic", "clock-frequency", BUS_CLK); + } + + /* resize the device tree */ + fdt_shrink(fdt); + + /* display information */ + printf("FDT Updated: Size %d -> %d\n", oldsize, fdt_totalsize(fdt)); + + return 0; +} + void print_bin(const uint8_t* buffer, uint32_t length) { uint32_t i, notprintable = 0; @@ -59,7 +235,7 @@ void print_bin(const uint8_t* buffer, uint32_t length) int dts_parse(void* dts_addr) { - int ret; + int ret = 0; struct fdt_header *fdt = (struct fdt_header *)dts_addr; const struct fdt_property* prop; int nlen, plen, slen; @@ -113,7 +289,7 @@ int dts_parse(void* dts_addr) } } - return 0; + return ret; } int main(int argc, char *argv[]) @@ -127,6 +303,12 @@ int main(int argc, char *argv[]) if (argc >= 2) { filename = argv[1]; } + while (argc > 2) { + if (strcmp(argv[argc-1], "-t") == 0) { + gEnableUnitTest = 1; + } + argc--; + } printf("FDT Parser (%s):\n", filename); if (filename == NULL) { @@ -144,7 +326,13 @@ int main(int argc, char *argv[]) fseek(f, 0, SEEK_END); imageSz = ftell(f); fseek(f, 0, SEEK_SET); - image = malloc(imageSz); + if (gEnableUnitTest) { + /* add extra 1KB for testing expansion room */ + image = malloc(imageSz + UNIT_TEST_GROW_SIZE); + } + else { + image = malloc(imageSz); + } if (image == NULL) { printf("Allocate %lu failed!\n", imageSz); ret = -1; @@ -159,13 +347,16 @@ int main(int argc, char *argv[]) } fclose(f); + if (ret == 0 && gEnableUnitTest) { + ret = fdt_test(image); + } if (ret == 0) { ret = dts_parse(image); } - printf("Return %d\n", ret); - free(image); + printf("Return %d\n", ret); + return ret; } diff --git a/tools/fdt-parser/nxp_t1024.dtb b/tools/fdt-parser/nxp_t1024.dtb new file mode 100755 index 000000000..03acde96f Binary files /dev/null and b/tools/fdt-parser/nxp_t1024.dtb differ