From 7a59d778f2d5b8a442fbabeccfd42c19720345f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Th=C3=B6rnblad?= Date: Mon, 17 Mar 2025 16:39:45 +0100 Subject: [PATCH] Add resetinfo testapp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mikael Ă…gren Co-authored-by: Michael Cardell Widerkrantz --- hw/application_fpga/fw/reset_test/Makefile | 76 ++++++++++++++ hw/application_fpga/fw/reset_test/app.lds | 64 ++++++++++++ hw/application_fpga/fw/reset_test/crt0.S | 53 ++++++++++ hw/application_fpga/fw/reset_test/main.c | 110 ++++++++++++++++++++ hw/application_fpga/fw/reset_test/syscall.S | 85 +++++++++++++++ 5 files changed, 388 insertions(+) create mode 100644 hw/application_fpga/fw/reset_test/Makefile create mode 100644 hw/application_fpga/fw/reset_test/app.lds create mode 100644 hw/application_fpga/fw/reset_test/crt0.S create mode 100644 hw/application_fpga/fw/reset_test/main.c create mode 100644 hw/application_fpga/fw/reset_test/syscall.S diff --git a/hw/application_fpga/fw/reset_test/Makefile b/hw/application_fpga/fw/reset_test/Makefile new file mode 100644 index 0000000..ed09be5 --- /dev/null +++ b/hw/application_fpga/fw/reset_test/Makefile @@ -0,0 +1,76 @@ +P := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) +LIBDIR ?= ../../tkey-libs +OBJCOPY ?= llvm-objcopy +CC = clang +CFLAGS = \ + -target riscv32-unknown-none-elf \ + -march=rv32iczmmul \ + -mabi=ilp32 \ + -mcmodel=medany \ + -static \ + -std=gnu99 \ + -O2 \ + -ffast-math \ + -fno-common \ + -fno-builtin-printf \ + -fno-builtin-putchar \ + -fno-builtin-memcpy \ + -nostdlib \ + -mno-relax \ + -Wall \ + -Wpedantic \ + -Wno-language-extension-token \ + -Werror \ + -flto \ + -g \ + -I $(LIBDIR)/include \ + -I $(LIBDIR) \ + -DTKEY_DEBUG + +AS = clang + +ASFLAGS = \ + -target riscv32-unknown-none-elf \ + -march=rv32iczmmul \ + -mabi=ilp32 \ + -mno-relax + +LDFLAGS = \ + -T $(P)/app.lds \ + -L $(LIBDIR) -lcommon + +.PHONY: all +all: reset_test.bin + +# Turn elf into bin for device +%.bin: %.elf + $(OBJCOPY) --input-target=elf32-littleriscv --output-target=binary $^ $@ + chmod a-x $@ + +.PHONY: tkey-libs +tkey-libs: + make -C $(LIBDIR) + +RESET_TEST_FMTFILES = \ + $(P)/main.c \ + +RESET_TEST_OBJS = \ + $(P)/main.o \ + $(P)/crt0.o \ + $(P)/syscall.o + +reset_test.elf: tkey-libs $(RESET_TEST_OBJS) + $(CC) $(CFLAGS) $(RESET_TEST_OBJS) $(LDFLAGS) -o $@ + +.PHONY: fmt +fmt: + clang-format --dry-run --ferror-limit=0 $(RESET_TEST_FMTFILES) + clang-format --verbose -i $(RESET_TEST_FMTFILES) + +.PHONY: checkfmt +checkfmt: + clang-format --dry-run --ferror-limit=0 --Werror $(RESET_TEST_FMTFILES) + +.PHONY: clean +clean: + rm -f reset_test.bin reset_test.elf $(RESET_TEST_OBJS) diff --git a/hw/application_fpga/fw/reset_test/app.lds b/hw/application_fpga/fw/reset_test/app.lds new file mode 100644 index 0000000..421122c --- /dev/null +++ b/hw/application_fpga/fw/reset_test/app.lds @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2022 Tillitis AB + * SPDX-License-Identifier: BSD-2-Clause + */ + +OUTPUT_ARCH( "riscv" ) +ENTRY(_start) + +MEMORY +{ + RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 0x20000 /* 128 KB */ +} + +SECTIONS +{ + .text.init : + { + *(.text.init) + } >RAM + + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.srodata) /* .rodata sections (constants, strings, etc.) */ + *(.srodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + _etext = .; + _sidata = _etext; + } >RAM + + .data : AT (_etext) + { + . = ALIGN(4); + _sdata = .; + . = ALIGN(4); + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *(.sdata) /* .sdata sections */ + *(.sdata*) /* .sdata* sections */ + . = ALIGN(4); + _edata = .; + } >RAM + + /* Uninitialized data section */ + .bss : + { + . = ALIGN(4); + _sbss = .; + *(.bss) + *(.bss*) + *(.sbss) + *(.sbss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; + } >RAM + + /* libcrt0/crt0.S inits stack to start just below end of RAM */ +} diff --git a/hw/application_fpga/fw/reset_test/crt0.S b/hw/application_fpga/fw/reset_test/crt0.S new file mode 100644 index 0000000..f484b7d --- /dev/null +++ b/hw/application_fpga/fw/reset_test/crt0.S @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: 2022 Tillitis AB +// SPDX-License-Identifier: BSD-2-Clause + + .section ".text.init" + .global _start +_start: + li x1, 0 + li x2, 0 + li x3, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10,0 + li x11,0 + li x12,0 + li x13,0 + li x14,0 + li x15,0 + li x16,0 + li x17,0 + li x18,0 + li x19,0 + li x20,0 + li x21,0 + li x22,0 + li x23,0 + li x24,0 + li x25,0 + li x26,0 + li x27,0 + li x28,0 + li x29,0 + li x30,0 + li x31,0 + + /* init stack below 0x40020000 (TK1_RAM_BASE+TK1_RAM_SIZE) */ + li sp, 0x4001fff0 + + /* zero-init bss section */ + la a0, _sbss + la a1, _ebss + bge a0, a1, end_init_bss + +loop_init_bss: + sw zero, 0(a0) + addi a0, a0, 4 + blt a0, a1, loop_init_bss + +end_init_bss: + call main diff --git a/hw/application_fpga/fw/reset_test/main.c b/hw/application_fpga/fw/reset_test/main.c new file mode 100644 index 0000000..8488d8f --- /dev/null +++ b/hw/application_fpga/fw/reset_test/main.c @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2022, 2023 - Tillitis AB + * SPDX-License-Identifier: GPL-2.0-only + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "../testapp/syscall.h" +#include "../tk1/proto.h" +#include "../tk1/resetinfo.h" +#include "../tk1/syscall_num.h" + +// Converts a single hex character to its integer value +static uint8_t hex_char_to_byte(uint8_t c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + return 0; // Invalid character, should not happen if input is valid +} + +// Converts a 64-char hex string into a 32-byte array +int hex_string_to_bytes(uint8_t *hex_str, uint8_t *out_bytes, size_t out_len) +{ + if (!hex_str || !out_bytes || out_len < 32) + return -1; // Error handling + + for (size_t i = 0; i < 32; i++) { + out_bytes[i] = (hex_char_to_byte(hex_str[i * 2]) << 4) | + hex_char_to_byte(hex_str[i * 2 + 1]); + } + + return 0; // Success +} +//--------------------------------------- + +#define BUFSIZE 32 + +int main(void) +{ + uint8_t available = 0; + uint8_t cmdbuf[BUFSIZE] = {0}; + enum ioend endpoint = IO_NONE; + led_set(LED_BLUE); + struct reset rst = {0}; + + while (1) { + + debug_puts("Waiting for command\n"); + + memset(cmdbuf, 0, BUFSIZE); + + // Wait for data + if (readselect(IO_TKEYCTRL, &endpoint, &available) < 0) { + assert(1 == 2); + } + + if (read(IO_TKEYCTRL, cmdbuf, BUFSIZE, available) < 0) { + // read failed! I/O broken? Just redblink. + assert(1 == 2); + } + + switch (cmdbuf[0]) { + case '1': + rst.type = START_DEFAULT; + syscall(TK1_SYSCALL_RESET, (uint32_t)&rst, 0, 0); + break; + + case '2': + rst.type = START_CLIENT; + syscall(TK1_SYSCALL_RESET, (uint32_t)&rst, 0, 0); + break; + + case '3': + rst.type = START_FLASH1; + syscall(TK1_SYSCALL_RESET, (uint32_t)&rst, 0, 0); + break; + + case '4': { + uint8_t string[] = "83da11b65f9c3721879bc4d9cffa6eac236" + "8dcd9562aedde4002e6108ac939b3"; + rst.type = START_CLIENT_VER; + hex_string_to_bytes(string, (uint8_t *)&rst.app_digest, + sizeof(rst.app_digest)); + syscall(TK1_SYSCALL_RESET, (uint32_t)&rst, 0, 0); + } break; + + case '5': { + uint8_t string[] = "ef1337a922945fd87683b71ed275e02af44" + "b3489057a29d14fd78daff8b73a28"; + rst.type = START_CLIENT_VER; + hex_string_to_bytes(string, (uint8_t *)&rst.app_digest, + sizeof(rst.app_digest)); + syscall(TK1_SYSCALL_RESET, (uint32_t)&rst, 0, 0); + } break; + + default: + break; + } + } +} diff --git a/hw/application_fpga/fw/reset_test/syscall.S b/hw/application_fpga/fw/reset_test/syscall.S new file mode 100644 index 0000000..5fc9b3f --- /dev/null +++ b/hw/application_fpga/fw/reset_test/syscall.S @@ -0,0 +1,85 @@ +// SPDX-FileCopyrightText: 2024 Tillitis AB +// SPDX-License-Identifier: BSD-2-Clause + +#include "../tk1/picorv32/custom_ops.S" + + .section ".text" + .globl syscall + + +syscall: + // Save registers to stack + addi sp, sp, -32*4 + sw x0, 0*4(sp) + sw x1, 1*4(sp) + // x2 (sp) is assumed to be preserved by the interrupt handler. + sw x3, 3*4(sp) + sw x4, 4*4(sp) + sw x5, 5*4(sp) + sw x6, 6*4(sp) + sw x7, 7*4(sp) + sw x8, 8*4(sp) + sw x9, 9*4(sp) + // x10 (a0) will contain syscall return value. And should not be saved. + sw x11, 11*4(sp) + sw x12, 12*4(sp) + sw x13, 13*4(sp) + sw x14, 14*4(sp) + sw x15, 15*4(sp) + sw x16, 16*4(sp) + sw x17, 17*4(sp) + sw x18, 18*4(sp) + sw x19, 19*4(sp) + sw x20, 20*4(sp) + sw x21, 21*4(sp) + sw x22, 22*4(sp) + sw x23, 23*4(sp) + sw x24, 24*4(sp) + sw x25, 25*4(sp) + sw x26, 26*4(sp) + sw x27, 27*4(sp) + sw x28, 28*4(sp) + sw x29, 29*4(sp) + sw x30, 30*4(sp) + sw x31, 31*4(sp) + + // Trigger syscall interrupt + li t1, 0xe1000000 // Syscall interrupt trigger address + sw zero, 0(t1) // Trigger interrupt + + // Restore registers from stack + lw x0, 0*4(sp) + lw x1, 1*4(sp) + // x2 (sp) is assumed to be preserved by the interrupt handler. + lw x3, 3*4(sp) + lw x4, 4*4(sp) + lw x5, 5*4(sp) + lw x6, 6*4(sp) + lw x7, 7*4(sp) + lw x8, 8*4(sp) + lw x9, 9*4(sp) + // x10 (a0) contains syscall return value. And should not be destroyed. + lw x11, 11*4(sp) + lw x12, 12*4(sp) + lw x13, 13*4(sp) + lw x14, 14*4(sp) + lw x15, 15*4(sp) + lw x16, 16*4(sp) + lw x17, 17*4(sp) + lw x18, 18*4(sp) + lw x19, 19*4(sp) + lw x20, 20*4(sp) + lw x21, 21*4(sp) + lw x22, 22*4(sp) + lw x23, 23*4(sp) + lw x24, 24*4(sp) + lw x25, 25*4(sp) + lw x26, 26*4(sp) + lw x27, 27*4(sp) + lw x28, 28*4(sp) + lw x29, 29*4(sp) + lw x30, 30*4(sp) + lw x31, 31*4(sp) + addi sp, sp, 32*4 + + ret