├── manual.pdf ├── multizone.jar ├── libhexfive ├── libhexfive64.a └── libhexfive.h ├── bsp └── U540 │ ├── memory.lds │ ├── openocd.cfg │ ├── plic.h │ ├── plic_driver.h │ ├── newlib │ ├── crt0.S │ ├── newlib.mk │ └── newlib.c │ ├── multizone.cfg │ ├── platform.h │ └── plic_driver.c ├── zone4 ├── owi_task.h ├── Makefile ├── owi_task.c ├── linker.lds └── main.c ├── zone3 ├── Makefile ├── linker.lds └── main.c ├── zone1 ├── Makefile ├── linker.lds └── main.c ├── zone2 ├── Makefile ├── linker.lds └── main.c ├── .gitignore ├── Makefile ├── LICENSE └── README.md /manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hex-five/multizone-linux/HEAD/manual.pdf -------------------------------------------------------------------------------- /multizone.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hex-five/multizone-linux/HEAD/multizone.jar -------------------------------------------------------------------------------- /libhexfive/libhexfive64.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hex-five/multizone-linux/HEAD/libhexfive/libhexfive64.a -------------------------------------------------------------------------------- /bsp/U540/memory.lds: -------------------------------------------------------------------------------- 1 | /* Copyright(C) 2019 Hex Five Security, Inc. - All Rights Reserved */ 2 | 3 | flash = 0x20000000; /* SPI0 FLASH 0x2000_0000-0x2080_0000 8M */ 4 | ram = 0x08000000; /* L2LIM 0x0800_0000-0x0802_0000 128K */ 5 | -------------------------------------------------------------------------------- /zone4/owi_task.h: -------------------------------------------------------------------------------- 1 | /* Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved */ 2 | 3 | #ifndef OWI_TASK_H_ 4 | #define OWI_TASK_H_ 5 | 6 | #include 7 | 8 | void owi_task_start_request(void); 9 | void owi_task_stop_request(void); 10 | void owi_task_fold(void); 11 | void owi_task_unfold(void); 12 | int32_t owi_task_run(const uint64_t time); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /zone3/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved 2 | 3 | TARGET = zone3.elf 4 | 5 | BSP_BASE := ../bsp 6 | PLATFORM_DIR := $(BSP_BASE)/$(BOARD) 7 | NEWLIB_DIR := $(PLATFORM_DIR)/newlib 8 | 9 | LINKER_SCRIPT := linker.lds 10 | 11 | C_SRCS += main.c 12 | 13 | INCLUDES += -I../libhexfive 14 | LDFLAGS += -L../libhexfive 15 | LDFLAGS += $(if $(findstring rv64, $(RISCV_ARCH)), -lhexfive64, -lhexfive32) 16 | 17 | include $(NEWLIB_DIR)/newlib.mk 18 | 19 | 20 | -------------------------------------------------------------------------------- /zone4/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved 2 | 3 | TARGET = zone4.elf 4 | 5 | BSP_BASE := ../bsp 6 | PLATFORM_DIR := $(BSP_BASE)/$(BOARD) 7 | NEWLIB_DIR := $(PLATFORM_DIR)/newlib 8 | 9 | LINKER_SCRIPT := linker.lds 10 | 11 | C_SRCS += main.c owi_task.c 12 | 13 | INCLUDES += -I../libhexfive 14 | LDFLAGS += -L../libhexfive 15 | LDFLAGS += $(if $(findstring rv64, $(RISCV_ARCH)), -lhexfive64, -lhexfive32) 16 | 17 | include $(NEWLIB_DIR)/newlib.mk 18 | 19 | -------------------------------------------------------------------------------- /zone1/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved 2 | 3 | TARGET = zone1.elf 4 | 5 | BSP_BASE := ../bsp 6 | PLATFORM_DIR := $(BSP_BASE)/$(BOARD) 7 | NEWLIB_DIR := $(PLATFORM_DIR)/newlib 8 | 9 | LINKER_SCRIPT := linker.lds 10 | 11 | C_SRCS += main.c 12 | HEADERS += 13 | 14 | INCLUDES += -I. -I../libhexfive 15 | LDFLAGS += -L../libhexfive 16 | LDFLAGS += $(if $(findstring rv64, $(RISCV_ARCH)), -lhexfive64, -lhexfive32) 17 | 18 | include $(NEWLIB_DIR)/newlib.mk 19 | 20 | -------------------------------------------------------------------------------- /zone2/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved 2 | 3 | TARGET = zone2.elf 4 | 5 | BSP_BASE := ../bsp 6 | PLATFORM_DIR := $(BSP_BASE)/$(BOARD) 7 | NEWLIB_DIR := $(PLATFORM_DIR)/newlib 8 | 9 | LINKER_SCRIPT := linker.lds 10 | 11 | C_SRCS += main.c 12 | HEADERS += 13 | 14 | INCLUDES += -I. -I../libhexfive 15 | LDFLAGS += -L../libhexfive 16 | LDFLAGS += $(if $(findstring rv64, $(RISCV_ARCH)), -lhexfive64, -lhexfive32) 17 | 18 | include $(NEWLIB_DIR)/newlib.mk 19 | 20 | -------------------------------------------------------------------------------- /bsp/U540/openocd.cfg: -------------------------------------------------------------------------------- 1 | adapter_khz 10000 2 | 3 | interface ftdi 4 | ftdi_device_desc "Dual RS232-HS" 5 | ftdi_vid_pid 0x0403 0x6010 6 | 7 | ftdi_layout_init 0x0008 0x001b 8 | ftdi_layout_signal nSRST -oe 0x0020 -data 0x0020 9 | 10 | set _CHIPNAME riscv 11 | jtag newtap $_CHIPNAME cpu -irlen 5 12 | 13 | set _TARGETNAME $_CHIPNAME.cpu 14 | #target create $_TARGETNAME riscv -chain-position $_TARGETNAME -rtos riscv 15 | target create $_TARGETNAME riscv -chain-position $_TARGETNAME 16 | 17 | $_TARGETNAME configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1 18 | 19 | flash bank onboard_spi_flash fespi 0x20000000 0 0 0 $_TARGETNAME 0x10040000 20 | init 21 | halt 22 | 23 | flash protect 0 0 0 off 24 | -------------------------------------------------------------------------------- /libhexfive/libhexfive.h: -------------------------------------------------------------------------------- 1 | /* Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved */ 2 | 3 | #include 4 | 5 | #ifndef LIBHEXFIVE_H_ 6 | #define LIBHEXFIVE_H_ 7 | 8 | void ECALL_YIELD(); 9 | void ECALL_WFI(); 10 | 11 | int ECALL_SEND(int, void *); 12 | int ECALL_RECV(int, void *); 13 | 14 | void ECALL_TRP_VECT(int, void *); 15 | void ECALL_IRQ_VECT(int, void *); 16 | 17 | void ECALL_CSRS_MIE(); 18 | void ECALL_CSRC_MIE(); 19 | 20 | void ECALL_CSRW_MTIMECMP(uint64_t); 21 | 22 | uint64_t ECALL_CSRR_MTIME(); 23 | uint64_t ECALL_CSRR_MCYCLE(); 24 | uint64_t ECALL_CSRR_MINSTR(); 25 | uint64_t ECALL_CSRR_MHPMC3(); 26 | uint64_t ECALL_CSRR_MHPMC4(); 27 | 28 | uint64_t ECALL_CSRR_MISA(); 29 | uint64_t ECALL_CSRR_MVENDID(); 30 | uint64_t ECALL_CSRR_MARCHID(); 31 | uint64_t ECALL_CSRR_MIMPID(); 32 | uint64_t ECALL_CSRR_MHARTID(); 33 | 34 | #endif /* LIBHEXFIVE_H_ */ 35 | -------------------------------------------------------------------------------- /bsp/U540/plic.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #ifndef PLIC_H 4 | #define PLIC_H 5 | 6 | #ifdef __ASSEMBLER__ 7 | #define _AC(X,Y) X 8 | #define _AT(T,X) X 9 | #else 10 | #define _AC(X,Y) (X##Y) 11 | #define _AT(T,X) ((T)(X)) 12 | #endif /* !__ASSEMBLER__*/ 13 | 14 | #define _BITUL(x) (_AC(1,UL) << (x)) 15 | #define _BITULL(x) (_AC(1,ULL) << (x)) 16 | 17 | // 32 bits per source 18 | #define PLIC_PRIORITY_OFFSET _AC(0x0000,UL) 19 | #define PLIC_PRIORITY_SHIFT_PER_SOURCE 2 20 | // 1 bit per source (1 address) 21 | #define PLIC_PENDING_OFFSET _AC(0x1000,UL) 22 | #define PLIC_PENDING_SHIFT_PER_SOURCE 0 23 | 24 | //0x80 per target 25 | #define PLIC_ENABLE_OFFSET _AC(0x2000,UL) 26 | #define PLIC_ENABLE_SHIFT_PER_TARGET 7 27 | 28 | #define PLIC_THRESHOLD_OFFSET _AC(0x200000,UL) 29 | #define PLIC_CLAIM_OFFSET _AC(0x200004,UL) 30 | #define PLIC_THRESHOLD_SHIFT_PER_TARGET 12 31 | #define PLIC_CLAIM_SHIFT_PER_TARGET 12 32 | 33 | #define PLIC_MAX_SOURCE 1023 34 | #define PLIC_SOURCE_MASK 0x3FF 35 | 36 | #define PLIC_MAX_TARGET 15871 37 | #define PLIC_TARGET_MASK 0x3FFF 38 | 39 | #endif /* PLIC_H */ 40 | -------------------------------------------------------------------------------- /bsp/U540/plic_driver.h: -------------------------------------------------------------------------------- 1 | // See LICENSE file for licence details 2 | 3 | #ifndef PLIC_DRIVER_H 4 | #define PLIC_DRIVER_H 5 | 6 | #include 7 | 8 | typedef struct __plic_instance_t 9 | { 10 | uintptr_t base_addr; 11 | 12 | uint32_t num_sources; 13 | uint32_t num_priorities; 14 | 15 | } plic_instance_t; 16 | 17 | typedef uint32_t plic_source; 18 | typedef uint32_t plic_priority; 19 | typedef uint32_t plic_threshold; 20 | 21 | void PLIC_init ( 22 | plic_instance_t * this_plic, 23 | uintptr_t base_addr, 24 | uint32_t num_sources, 25 | uint32_t num_priorities 26 | ); 27 | 28 | void PLIC_set_threshold (plic_instance_t * this_plic, 29 | plic_threshold threshold); 30 | 31 | void PLIC_enable_interrupt (plic_instance_t * this_plic, 32 | plic_source source); 33 | 34 | void PLIC_disable_interrupt (plic_instance_t * this_plic, 35 | plic_source source); 36 | 37 | void PLIC_set_priority (plic_instance_t * this_plic, 38 | plic_source source, 39 | plic_priority priority); 40 | 41 | plic_source PLIC_claim_interrupt(plic_instance_t * this_plic); 42 | 43 | void PLIC_complete_interrupt(plic_instance_t * this_plic, 44 | plic_source source); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /bsp/U540/newlib/crt0.S: -------------------------------------------------------------------------------- 1 | /* Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved */ 2 | 3 | .section .init 4 | .globl _start 5 | .type _start,@function 6 | 7 | _start: 8 | .cfi_startproc 9 | .cfi_undefined ra 10 | .option push 11 | .option norelax 12 | la gp, __global_pointer$ 13 | .option pop 14 | la sp, _sp 15 | 16 | /* Load data section */ 17 | la a0, _data_lma 18 | la a1, _data 19 | la a2, _edata 20 | bgeu a1, a2, 2f 21 | 1: 22 | lw t0, (a0) 23 | sw t0, (a1) 24 | addi a0, a0, 4 25 | addi a1, a1, 4 26 | bltu a1, a2, 1b 27 | 2: 28 | 29 | /* Clear bss section */ 30 | la a0, __bss_start 31 | la a1, __bss_end 32 | bgeu a0, a1, 2f 33 | 1: 34 | sw zero, (a0) 35 | addi a0, a0, 4 36 | bltu a0, a1, 1b 37 | 2: 38 | 39 | /* Call global constructors */ 40 | la a0, __libc_fini_array 41 | call atexit 42 | call __libc_init_array 43 | 44 | auipc ra, 0 45 | addi sp, sp, -16 46 | sw ra, 8(sp) 47 | 48 | /* argc = argv = 0 */ 49 | li a0, 0 50 | li a1, 0 51 | call main 52 | tail exit 53 | 54 | 1: j 1b 55 | 56 | .cfi_endproc 57 | 58 | .global _init 59 | .type _init, @function 60 | _init: ret 61 | .size _init, .-_init 62 | 63 | .global _fini 64 | .type _fini, @function 65 | _fini: ret 66 | .size _fini, .-_fini 67 | 68 | /* .global _init 69 | .type _init, @function 70 | .global _fini 71 | .type _fini, @function 72 | _init: 73 | _fini: 74 | # These don't have to do anything since we use init_array/fini_array. 75 | ret 76 | .size _init, .-_init 77 | .size _fini, .-_fini 78 | */ 79 | -------------------------------------------------------------------------------- /bsp/U540/multizone.cfg: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved 2 | 3 | Tick = 1 # ms 4 | 5 | Zone = 1 6 | base = 0x0008000000; size = 28K; rwx = rx; load = 0x20010000 7 | base = 0x0008007000; size = 4K; rwx = rw 8 | 9 | Zone = 2 10 | base = 0x0008008000; size = 28K; rwx = rx; load = 0x20020000 11 | base = 0x000800F000; size = 4K; rwx = rw 12 | 13 | Zone = 3 14 | base = 0x0008010000; size = 28K; rwx = rx; load = 0x20030000 15 | base = 0x0008017000; size = 4K; rwx = rw 16 | base = 0x2000104000; size = 0x100; rwx = rw # UART0 EXP 17 | 18 | Zone = 4 19 | base = 0x0008018000; size = 28K; rwx = rx; load = 0x20040000 20 | base = 0x000801F000; size = 4K; rwx = rw 21 | base = 0x0010020000; size = 0x100; rwx = rw # PWM (LED) 22 | base = 0x000200BFF8; size = 0x8; rwx = r # RTC 23 | base = 0x2000103000; size = 0x100; rwx = rw # GPIO EXP (LED) 24 | 25 | Hart = 1,2,3,4 26 | base = 0x01000000; size = 256; rwx = rw # DTIM0 [0x0100_0000 - 0x0100_00FF] 256 27 | base = 0x01000000; size = 8K; rwx = --- # DTIM0 [0x0100_0000 - 0x0100_1FFF] 8K 28 | base = 0x01800000; size = 8K; rwx = --- # ITIM0 [0x0180_0000 - 0x0180_1FFF] 8K 29 | base = 0x08000000; size = 128K; rwx = --- # L2LIM [0x0800_0000 - 0x0801_FFFF] 128K 30 | base = 0x20000000; size = 8M; rwx = --- # FLASH [0x2000_0000 - 0x207F_FFFF] 8M 31 | base = 0x02004000; size = 8; rwx = --- # MTIMECMP0 32 | base = 0x10020000; size =0x100; rwx = --- # PWM 33 | base = 0x00000000; size = 256G; rwx = rwx # ACCESS ALL [0x0 - 0x3F_FFFF_FFFF] 256G 34 | -------------------------------------------------------------------------------- /bsp/U540/newlib/newlib.mk: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved 2 | 3 | .PHONY: all 4 | all: $(TARGET) 5 | 6 | 7 | ASM_SRCS += $(NEWLIB_DIR)/crt0.S 8 | C_SRCS += $(NEWLIB_DIR)/newlib.c 9 | C_SRCS += $(PLATFORM_DIR)/plic_driver.c 10 | 11 | INCLUDES += -I$(PLATFORM_DIR) 12 | 13 | LDFLAGS += -T $(PLATFORM_DIR)/memory.lds 14 | LDFLAGS += -T $(LINKER_SCRIPT) 15 | LDFLAGS += --specs=nano.specs 16 | LDFLAGS += -nostartfiles 17 | LDFLAGS += -Xlinker --gc-sections 18 | 19 | ASM_OBJS := $(ASM_SRCS:.S=.o) 20 | C_OBJS := $(C_SRCS:.c=.o) 21 | 22 | LINK_OBJS += $(ASM_OBJS) $(C_OBJS) 23 | LINK_DEPS += $(LINKER_SCRIPT) 24 | 25 | CLEAN_OBJS += $(TARGET) $(LINK_OBJS) 26 | 27 | CFLAGS += -g 28 | CFLAGS += -ffunction-sections -fdata-sections 29 | CFLAGS += -march=$(RISCV_ARCH) 30 | CFLAGS += -mabi=$(RISCV_ABI) 31 | CFLAGS += -mcmodel=medany 32 | CFLAGS += -msmall-data-limit=8 33 | CFLAGS += -mdiv 34 | CFLAGS += -O3 35 | 36 | HEX = $(subst .elf,.hex,$(TARGET)) 37 | LST = $(subst .elf,.lst,$(TARGET)) 38 | CLEAN_OBJS += $(HEX) 39 | CLEAN_OBJS += $(LST) 40 | 41 | $(TARGET): $(LINK_OBJS) $(LINK_DEPS) 42 | $(CC) $(CFLAGS) $(INCLUDES) $(LINK_OBJS) -o $@ $(LDFLAGS) 43 | $(OBJCOPY) -O ihex $(TARGET) $(HEX) --gap-fill 0x00 44 | $(OBJDUMP) --all-headers --demangle --disassemble --file-headers --wide -D $(TARGET) > $(LST) 45 | 46 | $(ASM_OBJS): %.o: %.S $(HEADERS) 47 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 48 | 49 | $(C_OBJS): %.o: %.c $(HEADERS) 50 | $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< 51 | 52 | .PHONY: clean 53 | clean: 54 | rm -f $(CLEAN_OBJS) 55 | 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### https://github.com/github/gitignore/blob/master/Global/Eclipse.gitignore 2 | 3 | .project 4 | .metadata 5 | bin/ 6 | tmp/ 7 | *.tmp 8 | *.bak 9 | *.swp 10 | *~.nib 11 | local.properties 12 | .settings/ 13 | .loadpath 14 | .recommenders 15 | 16 | # External tool builders 17 | .externalToolBuilders/ 18 | 19 | # Locally stored "Eclipse launch configurations" 20 | *.launch 21 | 22 | # PyDev specific (Python IDE for Eclipse) 23 | *.pydevproject 24 | 25 | # CDT-specific (C/C++ Development Tooling) 26 | .cproject 27 | 28 | # CDT- autotools 29 | .autotools 30 | 31 | # Java annotation processor (APT) 32 | .factorypath 33 | 34 | # PDT-specific (PHP Development Tools) 35 | .buildpath 36 | 37 | # sbteclipse plugin 38 | .target 39 | 40 | # Tern plugin 41 | .tern-project 42 | 43 | # TeXlipse plugin 44 | .texlipse 45 | 46 | # STS (Spring Tool Suite) 47 | .springBeans 48 | 49 | # Code Recommenders 50 | .recommenders/ 51 | 52 | # Annotation Processing 53 | .apt_generated/ 54 | 55 | # Scala IDE specific (Scala & Java development for Eclipse) 56 | .cache-main 57 | .scala_dependencies 58 | .worksheet 59 | 60 | 61 | ### https://github.com/github/gitignore/blob/master/C.gitignore 62 | 63 | # Prerequisites 64 | *.d 65 | 66 | # Object files 67 | *.o 68 | *.ko 69 | *.obj 70 | *.elf 71 | 72 | # Linker output 73 | *.ilk 74 | *.map 75 | *.exp 76 | *.lst 77 | 78 | # Precompiled Headers 79 | *.gch 80 | *.pch 81 | 82 | # Libraries 83 | *.lib 84 | #*.a libhexfive*.a 85 | *.la 86 | *.lo 87 | 88 | # Shared objects (inc. Windows DLLs) 89 | *.dll 90 | *.so 91 | *.so.* 92 | *.dylib 93 | 94 | # Executables 95 | *.exe 96 | *.out 97 | *.app 98 | *.i*86 99 | *.x86_64 100 | *.hex 101 | 102 | # Debug files 103 | *.dSYM/ 104 | *.su 105 | *.idb 106 | *.pdb 107 | 108 | # Kernel Module Compile Results 109 | *.mod* 110 | *.cmd 111 | .tmp_versions/ 112 | modules.order 113 | Module.symvers 114 | Mkfile.old 115 | dkms.conf 116 | 117 | 118 | ### https://github.com/github/gitignore/blob/master/Java.gitignore 119 | 120 | # Compiled class file 121 | *.class 122 | 123 | # Log file 124 | *.log 125 | 126 | # BlueJ files 127 | *.ctxt 128 | 129 | # Mobile Tools for Java (J2ME) 130 | .mtj.tmp/ 131 | 132 | # Package Files # 133 | #*.jar multizone.jar 134 | *.war 135 | *.nar 136 | *.ear 137 | *.zip 138 | *.tar.gz 139 | *.rar 140 | 141 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 142 | hs_err_pid* 143 | 144 | # VScode 145 | .vscode/** 146 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved 2 | 3 | 4 | ############################################################# 5 | # Toolchain definitions 6 | ############################################################# 7 | 8 | ifndef RISCV 9 | $(error RISCV not set) 10 | endif 11 | 12 | export CROSS_COMPILE := $(abspath $(RISCV))/bin/riscv64-unknown-elf- 13 | export CC := $(CROSS_COMPILE)gcc 14 | export OBJDUMP := $(CROSS_COMPILE)objdump 15 | export OBJCOPY := $(CROSS_COMPILE)objcopy 16 | export GDB := $(CROSS_COMPILE)gdb 17 | export AR := $(CROSS_COMPILE)ar 18 | 19 | 20 | ############################################################# 21 | # Platform definitions 22 | ############################################################# 23 | 24 | BOARD ?= U540 25 | ifeq ($(BOARD),U540) 26 | ARCH := rv64 27 | RISCV_ARCH := $(ARCH)imac 28 | RISCV_ABI := lp64 29 | else 30 | $(error Unsupported board $(BOARD)) 31 | endif 32 | 33 | 34 | ############################################################# 35 | # Arguments/variables available to all submakes 36 | ############################################################# 37 | 38 | export BOARD 39 | export RISCV_ARCH 40 | export RISCV_ABI 41 | 42 | 43 | ############################################################# 44 | # Rules for building multizone 45 | ############################################################# 46 | 47 | .PHONY: all 48 | all: clean 49 | $(MAKE) -C zone1 50 | $(MAKE) -C zone2 51 | $(MAKE) -C zone3 52 | $(MAKE) -C zone4 53 | java -jar multizone.jar -c bsp/$(BOARD)/multizone.cfg --arch=$(BOARD) \ 54 | zone1/zone1.hex \ 55 | zone2/zone2.hex \ 56 | zone3/zone3.hex \ 57 | zone4/zone4.hex 58 | 59 | .PHONY: clean 60 | clean: 61 | $(MAKE) -C zone1 clean 62 | $(MAKE) -C zone2 clean 63 | $(MAKE) -C zone3 clean 64 | $(MAKE) -C zone4 clean 65 | rm -f multizone.hex 66 | 67 | 68 | ############################################################# 69 | # Load and debug variables and rules 70 | ############################################################# 71 | 72 | ifndef OPENOCD 73 | $(error OPENOCD not set) 74 | endif 75 | 76 | OPENOCD := $(abspath $(OPENOCD))/bin/openocd 77 | 78 | OPENOCDCFG ?= bsp/$(BOARD)/openocd.cfg 79 | OPENOCDARGS += -f $(OPENOCDCFG) 80 | 81 | GDB_PORT ?= 3333 82 | GDB_LOAD_ARGS ?= --batch 83 | GDB_LOAD_CMDS += -ex "set mem inaccessible-by-default off" 84 | GDB_LOAD_CMDS += -ex "set remotetimeout 240" 85 | GDB_LOAD_CMDS += -ex "set arch riscv:$(ARCH)" 86 | GDB_LOAD_CMDS += -ex "target extended-remote localhost:$(GDB_PORT)" 87 | GDB_LOAD_CMDS += -ex "monitor reset halt" 88 | GDB_LOAD_CMDS += -ex "monitor flash protect 0 64 last off" 89 | GDB_LOAD_CMDS += -ex "load" 90 | GDB_LOAD_CMDS += -ex "monitor resume" 91 | GDB_LOAD_CMDS += -ex "monitor shutdown" 92 | GDB_LOAD_CMDS += -ex "quit" 93 | 94 | .PHONY: load 95 | 96 | load: 97 | $(OPENOCD) $(OPENOCDARGS) & \ 98 | $(GDB) multizone.hex $(GDB_LOAD_ARGS) $(GDB_LOAD_CMDS) 99 | 100 | -------------------------------------------------------------------------------- /bsp/U540/platform.h: -------------------------------------------------------------------------------- 1 | /* Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved */ 2 | 3 | #ifndef HEXFIVE_PLATFORM_H 4 | #define HEXFIVE_PLATFORM_H 5 | 6 | #define CPU_FREQ 1000000000 7 | #define RTC_FREQ 1000000 8 | #define AXI_FREQ 75000000 // ChipLink 9 | 10 | // ----------------------------------------------------------------------------- 11 | // RTC (MTIME) 12 | // ----------------------------------------------------------------------------- 13 | #define RTC_BASE 0x02000000 14 | #define RTC_MTIME 0xBFF8 15 | 16 | // ----------------------------------------------------------------------------- 17 | // UART0 - Chiplink 18 | // ----------------------------------------------------------------------------- 19 | #define UART0_BASE 0x2000104000 20 | 21 | #define UART_RBR 0x00 // Receiver buffer register 22 | #define UART_THR 0x00 // Transmit holding register 23 | #define UART_DLR 0x00 // Divisor latch (LSB) 24 | #define UART_DRM 0x04 // Divisor latch (MSB) 25 | #define UART_LCR 0x0C // Line control register 26 | #define UART_FCR 0x08 // FIFO control register 27 | #define UART_LSR 0x14 // Line status register 28 | 29 | // ----------------------------------------------------------------------------- 30 | // GPIO - ChipLink 31 | // ----------------------------------------------------------------------------- 32 | #define GPIO_BASE 0x2000103000 33 | 34 | #define GPIO_0_CFG 0x00 // LED4 35 | #define GPIO_1_CFG 0x04 // LED5 36 | #define GPIO_2_CFG 0x08 // J2 pin13 37 | #define GPIO_3_CFG 0x0C // J2 pin14 38 | #define GPIO_4_CFG 0x10 // SW1 39 | #define GPIO_5_CFG 0x14 // SW2 40 | #define GPIO_6_CFG 0x18 // J2-pin9 41 | #define GPIO_7_CFG 0x1C // USB1 reset 42 | #define GPIO_IN 0x84 43 | #define GPIO_OUT 0x88 44 | 45 | // ----------------------------------------------------------------------------- 46 | // PWM - Unleashed 47 | // ----------------------------------------------------------------------------- 48 | #define PWM0_BASE 0x10020000 49 | 50 | #define PWM_CFG 0x00 // PWM configuration register 51 | #define PWM_COUNT 0x08 // PWM count register 52 | #define PWM_SCOUNT 0x10 // PWM scaled count register 53 | #define PWM_CMP0 0x20 // D1 Green 54 | #define PWM_CMP1 0x24 // D2 Green 55 | #define PWM_CMP2 0x28 // D3 Green 56 | #define PWM_CMP3 0x2C // D4 Green 57 | 58 | /* 59 | // ----------------------------------------------------------------------------- 60 | // UART0 - Unleashed 61 | // ----------------------------------------------------------------------------- 62 | #define UART0_BASE 0x10010000 63 | 64 | #define UART_TXFIFO 0x00 65 | #define UART_RXFIFO 0x04 66 | #define UART_TXCTRL 0x08 67 | #define UART_RXCTRL 0x0c 68 | #define UART_IE 0x10 69 | #define UART_IP 0x14 70 | #define UART_DIV 0x18 71 | 72 | // ----------------------------------------------------------------------------- 73 | // GPIO - Unleashed 74 | // ----------------------------------------------------------------------------- 75 | #define GPIO_BASE 0x10060000 76 | 77 | #define GPIO_INPUT_VAL 0x00 78 | #define GPIO_INPUT_EN 0x04 79 | #define GPIO_OUTPUT_EN 0x08 80 | #define GPIO_OUTPUT_VAL 0x0C 81 | #define GPIO_PULLUP_EN 0x10 82 | #define GPIO_DRIVE 0x14 83 | #define GPIO_RISE_IE 0x18 84 | #define GPIO_RISE_IP 0x1C 85 | #define GPIO_FALL_IE 0x20 86 | #define GPIO_FALL_IP 0x24 87 | #define GPIO_HIGH_IE 0x28 88 | #define GPIO_HIGH_IP 0x2C 89 | #define GPIO_LOW_IE 0x30 90 | #define GPIO_LOW_IP 0x34 91 | #define GPIO_OUTPUT_XOR 0x40 92 | */ 93 | 94 | // ----------------------------------------------------------------------------- 95 | // C Helper functions 96 | // ----------------------------------------------------------------------------- 97 | 98 | #define _REG64(base, offset) (*(volatile uint64_t *)((base) + (offset))) 99 | #define _REG32(base, offset) (*(volatile uint32_t *)((base) + (offset))) 100 | #define _REG16(base, offset) (*(volatile uint16_t *)((base) + (offset))) 101 | 102 | #define RTC_REG(offset) _REG64(RTC_BASE, offset) 103 | #define UART0_REG(offset) _REG32(UART0_BASE, offset) 104 | #define PWM0_REG(offset) _REG32(PWM0_BASE, offset) 105 | #define GPIO_REG(offset) _REG32(GPIO_BASE, offset) 106 | 107 | #endif /* HEXFIVE_PLATFORM_H */ 108 | 109 | -------------------------------------------------------------------------------- /zone4/owi_task.c: -------------------------------------------------------------------------------- 1 | /* Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved */ 2 | 3 | #include // RTC_FREQ 4 | #include "owi_task.h" 5 | 6 | typedef enum{ 7 | START_REQUEST, 8 | STARTED, 9 | STOP_REQUEST, 10 | STOPPED, 11 | FOLD, 12 | UNFOLD 13 | } state_enum; 14 | 15 | typedef enum{ 16 | STOP = 0x000000, 17 | GRIP_CLOSE = 0x000001, 18 | GRIP_OPEN = 0x000002, 19 | WRIST_UP = 0x000004, 20 | WRIST_DOWN = 0x000008, 21 | ELBOW_UP = 0x000010, 22 | ELBOW_DOWN = 0x000020, 23 | SHOULDER_UP = 0x000040, 24 | SHOULDER_DOWN = 0x000080, 25 | BASE_CLOCKWISE = 0x000100, 26 | BASE_COUNTERCLOCK = 0x000200, 27 | LIGHT_ON = 0x010000, 28 | ARM_UP = 0x000008 | 0x000010 | 0x000040, // wrist down + elbow up + shoulder up 29 | ARM_DOWN = 0x000004 | 0x000020 | 0x000080 | 0x000100, // wrist up + elbow down + shoulder down + base clockwise 30 | } cmd; 31 | 32 | struct sequence_step{ 33 | uint32_t command; 34 | int duration_ms; 35 | }; 36 | 37 | #define T_STOP 1000 38 | #define T_GRIP 1400 39 | #define T_WRIST 1900 40 | #define T_ARM 1600 41 | #define T_BASE 3000 42 | static struct sequence_step main_sequence[] = { 43 | { .command = STOP, .duration_ms = T_STOP }, 44 | { .command = GRIP_CLOSE, .duration_ms = T_GRIP }, 45 | { .command = WRIST_UP, .duration_ms = T_WRIST}, 46 | { .command = ARM_DOWN, .duration_ms = T_ARM }, 47 | { .command = BASE_CLOCKWISE, .duration_ms = T_BASE }, 48 | { .command = GRIP_OPEN, .duration_ms = T_GRIP }, 49 | { .command = STOP, .duration_ms = T_STOP }, 50 | { .command = GRIP_CLOSE, .duration_ms = T_GRIP }, 51 | { .command = BASE_COUNTERCLOCK, .duration_ms = T_BASE+T_ARM -125}, // -100 52 | { .command = ARM_UP, .duration_ms = T_ARM }, 53 | { .command = SHOULDER_UP, .duration_ms = +50 }, // +75 54 | { .command = ELBOW_UP, .duration_ms = +125 }, // +150 55 | { .command = WRIST_DOWN, .duration_ms = T_WRIST -300}, 56 | { .command = GRIP_OPEN, .duration_ms = T_GRIP }, 57 | }; 58 | 59 | #define T_FOLD 4500 60 | #define T_FOLD_SHOULDER 800 61 | static struct sequence_step fold_sequence[] = { 62 | { .command = STOP, .duration_ms = 0}, 63 | { .command = GRIP_OPEN, .duration_ms = 100}, 64 | { .command = ELBOW_DOWN | SHOULDER_UP | WRIST_DOWN, .duration_ms = T_FOLD}, 65 | { .command = ELBOW_DOWN, .duration_ms = 200}, 66 | { .command = SHOULDER_UP, .duration_ms = T_FOLD_SHOULDER}, 67 | }; 68 | static struct sequence_step unfold_sequence[] = { 69 | { .command = STOP, .duration_ms = 0}, 70 | { .command = ELBOW_UP, .duration_ms = 200}, 71 | { .command = SHOULDER_DOWN, .duration_ms = T_FOLD_SHOULDER + 50}, 72 | { .command = ELBOW_UP | SHOULDER_DOWN | WRIST_UP, .duration_ms = T_FOLD}, 73 | }; 74 | 75 | static state_enum state = STOPPED; 76 | static int step = -1; 77 | static uint64_t timer = 0; 78 | 79 | void owi_task_start_request(void){if (state==STOPPED) state=START_REQUEST;} 80 | void owi_task_stop_request(void){if (state==STARTED) state=STOP_REQUEST;} 81 | void owi_task_fold(void){if (state==STOPPED) state=FOLD; step=0; timer=0;} 82 | void owi_task_unfold(void){if (state==STOPPED) state=UNFOLD; step=0; timer=0;} 83 | 84 | int32_t owi_task_run(const uint64_t time){ 85 | 86 | int32_t cmd = -1; 87 | 88 | switch(state){ 89 | 90 | case START_REQUEST : 91 | step = 0; timer = 0; state=STARTED; 92 | break; 93 | 94 | case (STARTED) : 95 | case (STOP_REQUEST) : 96 | if (time > timer){ 97 | step = (step+1) % (sizeof(main_sequence)/sizeof(main_sequence[0])); 98 | timer = time + main_sequence[step].duration_ms * RTC_FREQ/1000; 99 | cmd = main_sequence[step].command; 100 | cmd = (state==STOP_REQUEST ? cmd & ~(1UL<<16) : cmd | (1UL<<16)); 101 | } 102 | if (state==STOP_REQUEST && step==0) state = STOPPED; 103 | break; 104 | 105 | case (FOLD) : 106 | if (time > timer){ 107 | step = (step+1) % (sizeof(fold_sequence)/sizeof(fold_sequence[0])); 108 | timer = time + fold_sequence[step].duration_ms * RTC_FREQ/1000; 109 | cmd = fold_sequence[step].command; 110 | if (step==0) state = STOPPED; 111 | } break; 112 | 113 | case (UNFOLD) : 114 | if (time > timer){ 115 | step = (step+1) % (sizeof(unfold_sequence)/sizeof(unfold_sequence[0])); 116 | timer = time + unfold_sequence[step].duration_ms * RTC_FREQ/1000; 117 | cmd = unfold_sequence[step].command; 118 | if (step==0) state = STOPPED; 119 | } break; 120 | 121 | case STOPPED : 122 | break; 123 | 124 | default: break; 125 | 126 | } 127 | 128 | return cmd; 129 | 130 | } 131 | 132 | -------------------------------------------------------------------------------- /bsp/U540/plic_driver.c: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #include 4 | #include "plic_driver.h" 5 | #include "plic.h" 6 | 7 | // Note that there are no assertions or bounds checking on these 8 | // parameter values. 9 | 10 | void volatile_memzero(uint8_t * base, unsigned int size) 11 | { 12 | volatile uint8_t * ptr; 13 | for (ptr = base; ptr < (base + size); ptr++){ 14 | *ptr = 0; 15 | } 16 | } 17 | 18 | void PLIC_init ( 19 | plic_instance_t * this_plic, 20 | uintptr_t base_addr, 21 | uint32_t num_sources, 22 | uint32_t num_priorities 23 | ) 24 | { 25 | 26 | this_plic->base_addr = base_addr; 27 | this_plic->num_sources = num_sources; 28 | this_plic->num_priorities = num_priorities; 29 | 30 | // Disable all interrupts (don't assume that these registers are reset). 31 | unsigned long hart_id = 0; //read_csr(mhartid); 32 | volatile_memzero((uint8_t*) (this_plic->base_addr + 33 | PLIC_ENABLE_OFFSET + 34 | (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET)), 35 | (num_sources + 8) / 8); 36 | 37 | // Set all priorities to 0 (equal priority -- don't assume that these are reset). 38 | volatile_memzero ((uint8_t *)(this_plic->base_addr + 39 | PLIC_PRIORITY_OFFSET), 40 | (num_sources + 1) << PLIC_PRIORITY_SHIFT_PER_SOURCE); 41 | 42 | // Set the threshold to 0. 43 | volatile plic_threshold* threshold = (plic_threshold*) 44 | (this_plic->base_addr + 45 | PLIC_THRESHOLD_OFFSET + 46 | (hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET)); 47 | 48 | *threshold = 0; 49 | 50 | } 51 | 52 | void PLIC_set_threshold (plic_instance_t * this_plic, 53 | plic_threshold threshold){ 54 | 55 | unsigned long hart_id = 0; //read_csr(mhartid); 56 | volatile plic_threshold* threshold_ptr = (plic_threshold*) (this_plic->base_addr + 57 | PLIC_THRESHOLD_OFFSET + 58 | (hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET)); 59 | 60 | *threshold_ptr = threshold; 61 | 62 | } 63 | 64 | 65 | void PLIC_enable_interrupt (plic_instance_t * this_plic, plic_source source){ 66 | 67 | unsigned long hart_id = 0; //read_csr(mhartid); 68 | volatile uint8_t * current_ptr = (volatile uint8_t *)(this_plic->base_addr + 69 | PLIC_ENABLE_OFFSET + 70 | (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) + 71 | (source >> 3)); 72 | uint8_t current = *current_ptr; 73 | current = current | ( 1 << (source & 0x7)); 74 | *current_ptr = current; 75 | 76 | } 77 | 78 | void PLIC_disable_interrupt (plic_instance_t * this_plic, plic_source source){ 79 | 80 | unsigned long hart_id = 0; //read_csr(mhartid); 81 | volatile uint8_t * current_ptr = (volatile uint8_t *) (this_plic->base_addr + 82 | PLIC_ENABLE_OFFSET + 83 | (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) + 84 | (source >> 3)); 85 | uint8_t current = *current_ptr; 86 | current = current & ~(( 1 << (source & 0x7))); 87 | *current_ptr = current; 88 | 89 | } 90 | 91 | void PLIC_set_priority (plic_instance_t * this_plic, plic_source source, plic_priority priority){ 92 | 93 | if (this_plic->num_priorities > 0) { 94 | volatile plic_priority * priority_ptr = (volatile plic_priority *) 95 | (this_plic->base_addr + 96 | PLIC_PRIORITY_OFFSET + 97 | (source << PLIC_PRIORITY_SHIFT_PER_SOURCE)); 98 | *priority_ptr = priority; 99 | } 100 | } 101 | 102 | plic_source PLIC_claim_interrupt(plic_instance_t * this_plic){ 103 | 104 | unsigned long hart_id = 0; //read_csr(mhartid); 105 | 106 | volatile plic_source * claim_addr = (volatile plic_source * ) 107 | (this_plic->base_addr + 108 | PLIC_CLAIM_OFFSET + 109 | (hart_id << PLIC_CLAIM_SHIFT_PER_TARGET)); 110 | 111 | return *claim_addr; 112 | 113 | } 114 | 115 | void PLIC_complete_interrupt(plic_instance_t * this_plic, plic_source source){ 116 | 117 | unsigned long hart_id = 0; //read_csr(mhartid); 118 | volatile plic_source * claim_addr = (volatile plic_source *) (this_plic->base_addr + 119 | PLIC_CLAIM_OFFSET + 120 | (hart_id << PLIC_CLAIM_SHIFT_PER_TARGET)); 121 | *claim_addr = source; 122 | 123 | } 124 | 125 | -------------------------------------------------------------------------------- /zone1/linker.lds: -------------------------------------------------------------------------------- 1 | /* Copyright(C) 2020 Hex Five Security, Inc. - All Rights Reserved */ 2 | 3 | OUTPUT_ARCH( "riscv" ) 4 | 5 | ENTRY( _start ) 6 | 7 | MEMORY { 8 | flash (rxai!w) : ORIGIN = 0x20010000, LENGTH = 28K /* SPI0 FLASH 0x2000_0000-0x2080_0000 8M */ 9 | ram_c (rxai!w) : ORIGIN = 0x08000000, LENGTH = 28K /* L2LIM 0x0800_0000-0x0802_0000 128K */ 10 | ram (wxa!ri) : ORIGIN = 0x08007000, LENGTH = 4K /* L2LIM 0x0800_0000-0x0802_0000 128K */ 11 | } 12 | 13 | SECTIONS { 14 | 15 | __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; 16 | PROVIDE(__stack_size = __stack_size); 17 | 18 | 19 | /** Init / Fini related code | run once - loaded in slower memory **/ 20 | 21 | .init : ALIGN(64 / 8) 22 | { 23 | KEEP (*(SORT_NONE(.init))) 24 | } >ram_c AT>flash 25 | 26 | .fini : ALIGN(64 / 8) 27 | { 28 | KEEP (*(SORT_NONE(.fini))) 29 | } >ram_c AT>flash 30 | 31 | .preinit_array : ALIGN(64 / 8) 32 | { 33 | PROVIDE_HIDDEN (__preinit_array_start = .); 34 | KEEP (*(.preinit_array)) 35 | PROVIDE_HIDDEN (__preinit_array_end = .); 36 | } >ram_c AT>flash 37 | 38 | .init_array : ALIGN(64 / 8) 39 | { 40 | PROVIDE_HIDDEN (__init_array_start = .); 41 | KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) 42 | KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) 43 | PROVIDE_HIDDEN (__init_array_end = .); 44 | } >ram_c AT>flash 45 | 46 | .fini_array : ALIGN(64 / 8) 47 | { 48 | PROVIDE_HIDDEN (__fini_array_start = .); 49 | KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) 50 | KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) 51 | PROVIDE_HIDDEN (__fini_array_end = .); 52 | } >ram_c AT>flash 53 | 54 | .ctors : ALIGN(64 / 8) 55 | { 56 | KEEP (*crtbegin.o(.ctors)) 57 | KEEP (*crtbegin?.o(.ctors)) 58 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) 59 | KEEP (*(SORT(.ctors.*))) 60 | KEEP (*(.ctors)) 61 | } >ram_c AT>flash 62 | 63 | .dtors : ALIGN(64 / 8) 64 | { 65 | KEEP (*crtbegin.o(.dtors)) 66 | KEEP (*crtbegin?.o(.dtors)) 67 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) 68 | KEEP (*(SORT(.dtors.*))) 69 | KEEP (*(.dtors)) 70 | } >ram_c AT>flash 71 | 72 | 73 | /** Text section | program - can be loaded to faster memory **/ 74 | 75 | .text : ALIGN(64 / 8) 76 | { 77 | *(.text.unlikely .text.*_unlikely .text.unlikely.*) 78 | *(.text.exit .text.exit.*) 79 | *(.text.startup .text.startup.*) 80 | *(.text.hot .text.hot.*) 81 | *(SORT(.text.sorted.*)) 82 | *(.text .stub .text.* .gnu.linkonce.t.*) 83 | /* .gnu.warning sections are handled specially by elf.em. */ 84 | *(.gnu.warning) 85 | } >ram_c AT>flash 86 | 87 | PROVIDE (__etext = .); 88 | PROVIDE (_etext = .); 89 | PROVIDE (etext = .); 90 | 91 | .rodata : ALIGN(64 / 8) 92 | { 93 | *(.rdata) 94 | *(.rodata .rodata.*) 95 | *(.gnu.linkonce.r.*) 96 | } >ram_c AT>flash 97 | 98 | 99 | /* Data section - copied from rom to ram */ 100 | 101 | .lalign : ALIGN(64 / 8) 102 | { 103 | PROVIDE( _data_lma = . ); 104 | } >ram_c AT>flash 105 | 106 | .data : ALIGN(64 / 8) 107 | { 108 | __DATA_BEGIN__ = .; 109 | _data = .; 110 | *(.data .data.* .gnu.linkonce.d.*) 111 | } >ram AT>flash 112 | 113 | .sdata : ALIGN(64 / 8) 114 | { 115 | PROVIDE( __global_pointer$ = . + 0x800 ); 116 | __SDATA_BEGIN__ = .; 117 | *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) 118 | *(.sdata .sdata.* .sdata* .gnu.linkonce.s.*) 119 | } >ram AT>flash 120 | 121 | _edata = .; 122 | PROVIDE (edata = .); 123 | 124 | .bss (NOLOAD): ALIGN(64 / 8) 125 | { 126 | __bss_start = .; 127 | *(.sbss .sbss.* .gnu.linkonce.sb.*) 128 | *(.bss .bss.* .gnu.linkonce.b.*) 129 | *(COMMON) 130 | . = ALIGN(. != 0 ? 64 / 8 : 1); 131 | } >ram AT>ram 132 | 133 | . = ALIGN(64 / 8); 134 | . = SEGMENT_START("ldata-segment", .); 135 | . = ALIGN(64 / 8); 136 | __bss_end = .; 137 | __BSS_END__ = .; 138 | 139 | 140 | /* Stack definition - change size at top of this script */ 141 | 142 | .stack (NOLOAD): ALIGN(16) 143 | { 144 | . += __stack_size; 145 | PROVIDE( _sp = . ); 146 | } >ram AT>ram 147 | 148 | 149 | /* Heap definition - calculated to use the remaining memory */ 150 | 151 | .heap (NOLOAD): ALIGN(64 / 8) 152 | { 153 | PROVIDE( _end = . ); 154 | PROVIDE( __end = . ); 155 | PROVIDE( __heap_start = . ); 156 | . += LENGTH(ram) - ( . - ORIGIN(ram)); 157 | PROVIDE( _heap_end = . ); 158 | PROVIDE( __heap_end = . ); 159 | } >ram AT>ram 160 | 161 | } -------------------------------------------------------------------------------- /zone2/linker.lds: -------------------------------------------------------------------------------- 1 | /* Copyright(C) 2020 Hex Five Security, Inc. - All Rights Reserved */ 2 | 3 | OUTPUT_ARCH( "riscv" ) 4 | 5 | ENTRY( _start ) 6 | 7 | MEMORY { 8 | flash (rxai!w) : ORIGIN = 0x20020000, LENGTH = 28K /* SPI0 FLASH 0x2000_0000-0x2080_0000 8M */ 9 | ram_c (rxai!w) : ORIGIN = 0x08008000, LENGTH = 28K /* L2LIM 0x0800_0000-0x0802_0000 128K */ 10 | ram (wxa!ri) : ORIGIN = 0x0800F000, LENGTH = 4K /* L2LIM 0x0800_0000-0x0802_0000 128K */ 11 | } 12 | 13 | SECTIONS { 14 | 15 | __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; 16 | PROVIDE(__stack_size = __stack_size); 17 | 18 | 19 | /** Init / Fini related code | run once - loaded in slower memory **/ 20 | 21 | .init : ALIGN(64 / 8) 22 | { 23 | KEEP (*(SORT_NONE(.init))) 24 | } >ram_c AT>flash 25 | 26 | .fini : ALIGN(64 / 8) 27 | { 28 | KEEP (*(SORT_NONE(.fini))) 29 | } >ram_c AT>flash 30 | 31 | .preinit_array : ALIGN(64 / 8) 32 | { 33 | PROVIDE_HIDDEN (__preinit_array_start = .); 34 | KEEP (*(.preinit_array)) 35 | PROVIDE_HIDDEN (__preinit_array_end = .); 36 | } >ram_c AT>flash 37 | 38 | .init_array : ALIGN(64 / 8) 39 | { 40 | PROVIDE_HIDDEN (__init_array_start = .); 41 | KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) 42 | KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) 43 | PROVIDE_HIDDEN (__init_array_end = .); 44 | } >ram_c AT>flash 45 | 46 | .fini_array : ALIGN(64 / 8) 47 | { 48 | PROVIDE_HIDDEN (__fini_array_start = .); 49 | KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) 50 | KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) 51 | PROVIDE_HIDDEN (__fini_array_end = .); 52 | } >ram_c AT>flash 53 | 54 | .ctors : ALIGN(64 / 8) 55 | { 56 | KEEP (*crtbegin.o(.ctors)) 57 | KEEP (*crtbegin?.o(.ctors)) 58 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) 59 | KEEP (*(SORT(.ctors.*))) 60 | KEEP (*(.ctors)) 61 | } >ram_c AT>flash 62 | 63 | .dtors : ALIGN(64 / 8) 64 | { 65 | KEEP (*crtbegin.o(.dtors)) 66 | KEEP (*crtbegin?.o(.dtors)) 67 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) 68 | KEEP (*(SORT(.dtors.*))) 69 | KEEP (*(.dtors)) 70 | } >ram_c AT>flash 71 | 72 | 73 | /** Text section | program - can be loaded to faster memory **/ 74 | 75 | .text : ALIGN(64 / 8) 76 | { 77 | *(.text.unlikely .text.*_unlikely .text.unlikely.*) 78 | *(.text.exit .text.exit.*) 79 | *(.text.startup .text.startup.*) 80 | *(.text.hot .text.hot.*) 81 | *(SORT(.text.sorted.*)) 82 | *(.text .stub .text.* .gnu.linkonce.t.*) 83 | /* .gnu.warning sections are handled specially by elf.em. */ 84 | *(.gnu.warning) 85 | } >ram_c AT>flash 86 | 87 | PROVIDE (__etext = .); 88 | PROVIDE (_etext = .); 89 | PROVIDE (etext = .); 90 | 91 | .rodata : ALIGN(64 / 8) 92 | { 93 | *(.rdata) 94 | *(.rodata .rodata.*) 95 | *(.gnu.linkonce.r.*) 96 | } >ram_c AT>flash 97 | 98 | 99 | /* Data section - copied from rom to ram */ 100 | 101 | .lalign : ALIGN(64 / 8) 102 | { 103 | PROVIDE( _data_lma = . ); 104 | } >ram_c AT>flash 105 | 106 | .data : ALIGN(64 / 8) 107 | { 108 | __DATA_BEGIN__ = .; 109 | _data = .; 110 | *(.data .data.* .gnu.linkonce.d.*) 111 | } >ram AT>flash 112 | 113 | .sdata : ALIGN(64 / 8) 114 | { 115 | PROVIDE( __global_pointer$ = . + 0x800 ); 116 | __SDATA_BEGIN__ = .; 117 | *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) 118 | *(.sdata .sdata.* .sdata* .gnu.linkonce.s.*) 119 | } >ram AT>flash 120 | 121 | _edata = .; 122 | PROVIDE (edata = .); 123 | 124 | .bss (NOLOAD): ALIGN(64 / 8) 125 | { 126 | __bss_start = .; 127 | *(.sbss .sbss.* .gnu.linkonce.sb.*) 128 | *(.bss .bss.* .gnu.linkonce.b.*) 129 | *(COMMON) 130 | . = ALIGN(. != 0 ? 64 / 8 : 1); 131 | } >ram AT>ram 132 | 133 | . = ALIGN(64 / 8); 134 | . = SEGMENT_START("ldata-segment", .); 135 | . = ALIGN(64 / 8); 136 | __bss_end = .; 137 | __BSS_END__ = .; 138 | 139 | 140 | /* Stack definition - change size at top of this script */ 141 | 142 | .stack (NOLOAD): ALIGN(16) 143 | { 144 | . += __stack_size; 145 | PROVIDE( _sp = . ); 146 | } >ram AT>ram 147 | 148 | 149 | /* Heap definition - calculated to use the remaining memory */ 150 | 151 | .heap (NOLOAD): ALIGN(64 / 8) 152 | { 153 | PROVIDE( _end = . ); 154 | PROVIDE( __end = . ); 155 | PROVIDE( __heap_start = . ); 156 | . += LENGTH(ram) - ( . - ORIGIN(ram)); 157 | PROVIDE( _heap_end = . ); 158 | PROVIDE( __heap_end = . ); 159 | } >ram AT>ram 160 | 161 | } -------------------------------------------------------------------------------- /zone3/linker.lds: -------------------------------------------------------------------------------- 1 | /* Copyright(C) 2020 Hex Five Security, Inc. - All Rights Reserved */ 2 | 3 | OUTPUT_ARCH( "riscv" ) 4 | 5 | ENTRY( _start ) 6 | 7 | MEMORY { 8 | flash (rxai!w) : ORIGIN = 0x20030000, LENGTH = 28K /* SPI0 FLASH 0x2000_0000-0x2080_0000 8M */ 9 | ram_c (rxai!w) : ORIGIN = 0x08010000, LENGTH = 28K /* L2LIM 0x0800_0000-0x0802_0000 128K */ 10 | ram (wxa!ri) : ORIGIN = 0x08017000, LENGTH = 4K /* L2LIM 0x0800_0000-0x0802_0000 128K */ 11 | } 12 | 13 | SECTIONS { 14 | 15 | __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; 16 | PROVIDE(__stack_size = __stack_size); 17 | 18 | 19 | /** Init / Fini related code | run once - loaded in slower memory **/ 20 | 21 | .init : ALIGN(64 / 8) 22 | { 23 | KEEP (*(SORT_NONE(.init))) 24 | } >ram_c AT>flash 25 | 26 | .fini : ALIGN(64 / 8) 27 | { 28 | KEEP (*(SORT_NONE(.fini))) 29 | } >ram_c AT>flash 30 | 31 | .preinit_array : ALIGN(64 / 8) 32 | { 33 | PROVIDE_HIDDEN (__preinit_array_start = .); 34 | KEEP (*(.preinit_array)) 35 | PROVIDE_HIDDEN (__preinit_array_end = .); 36 | } >ram_c AT>flash 37 | 38 | .init_array : ALIGN(64 / 8) 39 | { 40 | PROVIDE_HIDDEN (__init_array_start = .); 41 | KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) 42 | KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) 43 | PROVIDE_HIDDEN (__init_array_end = .); 44 | } >ram_c AT>flash 45 | 46 | .fini_array : ALIGN(64 / 8) 47 | { 48 | PROVIDE_HIDDEN (__fini_array_start = .); 49 | KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) 50 | KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) 51 | PROVIDE_HIDDEN (__fini_array_end = .); 52 | } >ram_c AT>flash 53 | 54 | .ctors : ALIGN(64 / 8) 55 | { 56 | KEEP (*crtbegin.o(.ctors)) 57 | KEEP (*crtbegin?.o(.ctors)) 58 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) 59 | KEEP (*(SORT(.ctors.*))) 60 | KEEP (*(.ctors)) 61 | } >ram_c AT>flash 62 | 63 | .dtors : ALIGN(64 / 8) 64 | { 65 | KEEP (*crtbegin.o(.dtors)) 66 | KEEP (*crtbegin?.o(.dtors)) 67 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) 68 | KEEP (*(SORT(.dtors.*))) 69 | KEEP (*(.dtors)) 70 | } >ram_c AT>flash 71 | 72 | 73 | /** Text section | program - can be loaded to faster memory **/ 74 | 75 | .text : ALIGN(64 / 8) 76 | { 77 | *(.text.unlikely .text.*_unlikely .text.unlikely.*) 78 | *(.text.exit .text.exit.*) 79 | *(.text.startup .text.startup.*) 80 | *(.text.hot .text.hot.*) 81 | *(SORT(.text.sorted.*)) 82 | *(.text .stub .text.* .gnu.linkonce.t.*) 83 | /* .gnu.warning sections are handled specially by elf.em. */ 84 | *(.gnu.warning) 85 | } >ram_c AT>flash 86 | 87 | PROVIDE (__etext = .); 88 | PROVIDE (_etext = .); 89 | PROVIDE (etext = .); 90 | 91 | .rodata : ALIGN(64 / 8) 92 | { 93 | *(.rdata) 94 | *(.rodata .rodata.*) 95 | *(.gnu.linkonce.r.*) 96 | } >ram_c AT>flash 97 | 98 | 99 | /* Data section - copied from rom to ram */ 100 | 101 | .lalign : ALIGN(64 / 8) 102 | { 103 | PROVIDE( _data_lma = . ); 104 | } >ram_c AT>flash 105 | 106 | .data : ALIGN(64 / 8) 107 | { 108 | __DATA_BEGIN__ = .; 109 | _data = .; 110 | *(.data .data.* .gnu.linkonce.d.*) 111 | } >ram AT>flash 112 | 113 | .sdata : ALIGN(64 / 8) 114 | { 115 | PROVIDE( __global_pointer$ = . + 0x800 ); 116 | __SDATA_BEGIN__ = .; 117 | *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) 118 | *(.sdata .sdata.* .sdata* .gnu.linkonce.s.*) 119 | } >ram AT>flash 120 | 121 | _edata = .; 122 | PROVIDE (edata = .); 123 | 124 | .bss (NOLOAD): ALIGN(64 / 8) 125 | { 126 | __bss_start = .; 127 | *(.sbss .sbss.* .gnu.linkonce.sb.*) 128 | *(.bss .bss.* .gnu.linkonce.b.*) 129 | *(COMMON) 130 | . = ALIGN(. != 0 ? 64 / 8 : 1); 131 | } >ram AT>ram 132 | 133 | . = ALIGN(64 / 8); 134 | . = SEGMENT_START("ldata-segment", .); 135 | . = ALIGN(64 / 8); 136 | __bss_end = .; 137 | __BSS_END__ = .; 138 | 139 | 140 | /* Stack definition - change size at top of this script */ 141 | 142 | .stack (NOLOAD): ALIGN(16) 143 | { 144 | . += __stack_size; 145 | PROVIDE( _sp = . ); 146 | } >ram AT>ram 147 | 148 | 149 | /* Heap definition - calculated to use the remaining memory */ 150 | 151 | .heap (NOLOAD): ALIGN(64 / 8) 152 | { 153 | PROVIDE( _end = . ); 154 | PROVIDE( __end = . ); 155 | PROVIDE( __heap_start = . ); 156 | . += LENGTH(ram) - ( . - ORIGIN(ram)); 157 | PROVIDE( _heap_end = . ); 158 | PROVIDE( __heap_end = . ); 159 | } >ram AT>ram 160 | 161 | } -------------------------------------------------------------------------------- /zone4/linker.lds: -------------------------------------------------------------------------------- 1 | /* Copyright(C) 2020 Hex Five Security, Inc. - All Rights Reserved */ 2 | 3 | OUTPUT_ARCH( "riscv" ) 4 | 5 | ENTRY( _start ) 6 | 7 | MEMORY { 8 | flash (rxai!w) : ORIGIN = 0x20040000, LENGTH = 28K /* SPI0 FLASH 0x2000_0000-0x2080_0000 8M */ 9 | ram_c (rxai!w) : ORIGIN = 0x08018000, LENGTH = 28K /* L2LIM 0x0800_0000-0x0802_0000 128K */ 10 | ram (wxa!ri) : ORIGIN = 0x0801F000, LENGTH = 4K /* L2LIM 0x0800_0000-0x0802_0000 128K */ 11 | } 12 | 13 | SECTIONS { 14 | 15 | __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; 16 | PROVIDE(__stack_size = __stack_size); 17 | 18 | 19 | /** Init / Fini related code | run once - loaded in slower memory **/ 20 | 21 | .init : ALIGN(64 / 8) 22 | { 23 | KEEP (*(SORT_NONE(.init))) 24 | } >ram_c AT>flash 25 | 26 | .fini : ALIGN(64 / 8) 27 | { 28 | KEEP (*(SORT_NONE(.fini))) 29 | } >ram_c AT>flash 30 | 31 | .preinit_array : ALIGN(64 / 8) 32 | { 33 | PROVIDE_HIDDEN (__preinit_array_start = .); 34 | KEEP (*(.preinit_array)) 35 | PROVIDE_HIDDEN (__preinit_array_end = .); 36 | } >ram_c AT>flash 37 | 38 | .init_array : ALIGN(64 / 8) 39 | { 40 | PROVIDE_HIDDEN (__init_array_start = .); 41 | KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) 42 | KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) 43 | PROVIDE_HIDDEN (__init_array_end = .); 44 | } >ram_c AT>flash 45 | 46 | .fini_array : ALIGN(64 / 8) 47 | { 48 | PROVIDE_HIDDEN (__fini_array_start = .); 49 | KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) 50 | KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) 51 | PROVIDE_HIDDEN (__fini_array_end = .); 52 | } >ram_c AT>flash 53 | 54 | .ctors : ALIGN(64 / 8) 55 | { 56 | KEEP (*crtbegin.o(.ctors)) 57 | KEEP (*crtbegin?.o(.ctors)) 58 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) 59 | KEEP (*(SORT(.ctors.*))) 60 | KEEP (*(.ctors)) 61 | } >ram_c AT>flash 62 | 63 | .dtors : ALIGN(64 / 8) 64 | { 65 | KEEP (*crtbegin.o(.dtors)) 66 | KEEP (*crtbegin?.o(.dtors)) 67 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) 68 | KEEP (*(SORT(.dtors.*))) 69 | KEEP (*(.dtors)) 70 | } >ram_c AT>flash 71 | 72 | 73 | /** Text section | program - can be loaded to faster memory **/ 74 | 75 | .text : ALIGN(64 / 8) 76 | { 77 | *(.text.unlikely .text.*_unlikely .text.unlikely.*) 78 | *(.text.exit .text.exit.*) 79 | *(.text.startup .text.startup.*) 80 | *(.text.hot .text.hot.*) 81 | *(SORT(.text.sorted.*)) 82 | *(.text .stub .text.* .gnu.linkonce.t.*) 83 | /* .gnu.warning sections are handled specially by elf.em. */ 84 | *(.gnu.warning) 85 | } >ram_c AT>flash 86 | 87 | PROVIDE (__etext = .); 88 | PROVIDE (_etext = .); 89 | PROVIDE (etext = .); 90 | 91 | .rodata : ALIGN(64 / 8) 92 | { 93 | *(.rdata) 94 | *(.rodata .rodata.*) 95 | *(.gnu.linkonce.r.*) 96 | } >ram_c AT>flash 97 | 98 | 99 | /* Data section - copied from rom to ram */ 100 | 101 | .lalign : ALIGN(64 / 8) 102 | { 103 | PROVIDE( _data_lma = . ); 104 | } >ram_c AT>flash 105 | 106 | .data : ALIGN(64 / 8) 107 | { 108 | __DATA_BEGIN__ = .; 109 | _data = .; 110 | *(.data .data.* .gnu.linkonce.d.*) 111 | } >ram AT>flash 112 | 113 | .sdata : ALIGN(64 / 8) 114 | { 115 | PROVIDE( __global_pointer$ = . + 0x800 ); 116 | __SDATA_BEGIN__ = .; 117 | *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) 118 | *(.sdata .sdata.* .sdata* .gnu.linkonce.s.*) 119 | } >ram AT>flash 120 | 121 | _edata = .; 122 | PROVIDE (edata = .); 123 | 124 | .bss (NOLOAD): ALIGN(64 / 8) 125 | { 126 | __bss_start = .; 127 | *(.sbss .sbss.* .gnu.linkonce.sb.*) 128 | *(.bss .bss.* .gnu.linkonce.b.*) 129 | *(COMMON) 130 | . = ALIGN(. != 0 ? 64 / 8 : 1); 131 | } >ram AT>ram 132 | 133 | . = ALIGN(64 / 8); 134 | . = SEGMENT_START("ldata-segment", .); 135 | . = ALIGN(64 / 8); 136 | __bss_end = .; 137 | __BSS_END__ = .; 138 | 139 | 140 | /* Stack definition - change size at top of this script */ 141 | 142 | .stack (NOLOAD): ALIGN(16) 143 | { 144 | . += __stack_size; 145 | PROVIDE( _sp = . ); 146 | } >ram AT>ram 147 | 148 | 149 | /* Heap definition - calculated to use the remaining memory */ 150 | 151 | .heap (NOLOAD): ALIGN(64 / 8) 152 | { 153 | PROVIDE( _end = . ); 154 | PROVIDE( __end = . ); 155 | PROVIDE( __heap_start = . ); 156 | . += LENGTH(ram) - ( . - ORIGIN(ram)); 157 | PROVIDE( _heap_end = . ); 158 | PROVIDE( __heap_end = . ); 159 | } >ram AT>ram 160 | 161 | } -------------------------------------------------------------------------------- /zone4/main.c: -------------------------------------------------------------------------------- 1 | /* Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved */ 2 | 3 | #include // strcmp() strlen() 4 | #include 5 | #include 6 | #include "owi_task.h" 7 | 8 | #define SPI_TDI 3 // in - pin 14 9 | #define SPI_TCK 2 // out - pin 13 10 | #define SPI_TDO 6 // out - pin 9 11 | #define LED4 0 // green 12 | 13 | uint8_t CRC8(uint8_t bytes[]){ 14 | 15 | const uint8_t generator = 0x1D; 16 | uint8_t crc = 0; 17 | 18 | for(int b=0; b<3; b++) { 19 | 20 | crc ^= bytes[b]; /* XOR-in the next input byte */ 21 | 22 | for (int i = 0; i < 8; i++) 23 | if ((crc & 0x80) != 0) 24 | crc = (uint8_t)((crc << 1) ^ generator); 25 | else 26 | crc <<= 1; 27 | } 28 | 29 | return crc; 30 | } 31 | 32 | uint32_t spi_rw(uint8_t cmd[]){ 33 | 34 | uint32_t rx_data = 0; 35 | 36 | const uint32_t tx_data = ((uint8_t)cmd[0] << 24) | ((uint8_t)cmd[1] << 16) | ((uint8_t)cmd[2] << 8) | CRC8(cmd); 37 | 38 | for (int i=32-1, bit; i>=0; i--){ 39 | 40 | bit = (tx_data >> i) & 1U; 41 | GPIO_REG(GPIO_OUT) = (bit==1 ? GPIO_REG(GPIO_OUT) | (0x1 << SPI_TDO) : 42 | GPIO_REG(GPIO_OUT) & ~(0x1 << SPI_TDO) ); 43 | 44 | GPIO_REG(GPIO_OUT) |= (0x1 << SPI_TCK); volatile int w1=0; while(w1<5) w1++; 45 | 46 | GPIO_REG(GPIO_OUT) ^= (0x1 << SPI_TCK); volatile int w2=0; while(w2<1) w2++; 47 | 48 | bit = ( GPIO_REG(GPIO_IN) >> SPI_TDI) & 1U; 49 | rx_data = ( bit==1 ? rx_data | (0x1 << i) : rx_data & ~(0x1 << i) ); 50 | 51 | } 52 | 53 | return rx_data; 54 | } 55 | 56 | int main (void){ 57 | 58 | //volatile int w=0; while(1){w++;} 59 | //while(1) {ECALL_YIELD();} 60 | 61 | GPIO_REG(GPIO_3_CFG) = 0b010; // in 62 | GPIO_REG(GPIO_2_CFG) = 0b101; // out buffer 63 | GPIO_REG(GPIO_6_CFG) = 0b101; // out buffer 64 | GPIO_REG(GPIO_0_CFG) = 0b101; // out buffer 65 | 66 | PWM0_REG(PWM_CFG) = 0x0; 67 | PWM0_REG(PWM_COUNT) = 0x0; 68 | PWM0_REG(PWM_SCOUNT) = 0x0; 69 | 70 | PWM0_REG(PWM_CMP0) = 0x1; // LED1 OFF 71 | PWM0_REG(PWM_CMP1) = 0x1; // LED2 OFF 72 | PWM0_REG(PWM_CMP2) = 0x1; // LED3 OFF 73 | PWM0_REG(PWM_CMP3) = 0x1; // LED4 OFF 74 | 75 | #define CMD_STOP ((uint8_t[]){0x00, 0x00, 0x00}) 76 | #define CMD_DUMMY ((uint8_t[]){0xFF, 0xFF, 0xFF}) 77 | #define CMD_TIME 250*RTC_FREQ/1000 // 250ms 78 | #define PING_TIME 1000*RTC_FREQ/1000 // 1000ms 79 | #define SYS_TIME RTC_REG(RTC_MTIME) 80 | 81 | uint64_t ping_timer=0, cmd_timer=0; 82 | uint32_t rx_data = 0, usb_state = 0; 83 | 84 | while(1){ 85 | 86 | // Message listener 87 | char msg[16]=""; int zone=-1; 88 | for (zone=1; zone<4; zone++) 89 | if (ECALL_RECV(zone, msg)) break; 90 | 91 | if (strlen(msg)){ 92 | 93 | // Ping 94 | if (strcmp("ping", msg) == 0) ECALL_SEND(zone, "pong"); 95 | 96 | // Manual cmd 97 | else if (usb_state==0x12670000 && cmd_timer==0){ 98 | 99 | uint8_t cmd[3] = {0x00, 0x00, 0x00}; 100 | 101 | switch (msg[0]){ 102 | case 'q' : cmd[0] = 0x01; break; // grip close 103 | case 'a' : cmd[0] = 0x02; break; // grip open 104 | case 'w' : cmd[0] = 0x04; break; // wrist up 105 | case 's' : cmd[0] = 0x08; break; // wrist down 106 | case 'e' : cmd[0] = 0x10; break; // elbow up 107 | case 'd' : cmd[0] = 0x20; break; // elbow down 108 | case 'r' : cmd[0] = 0x40; break; // shoulder up 109 | case 'f' : cmd[0] = 0x80; break; // shoulder down 110 | case 't' : cmd[1] = 0x01; break; // base clockwise 111 | case 'g' : cmd[1] = 0x02; break; // base counterclockwise 112 | case 'y' : cmd[2] = 0x01; break; // light on 113 | default : break; 114 | } 115 | 116 | if ( cmd[0] + cmd[1] + cmd[2] != 0 ){ 117 | rx_data = spi_rw(cmd); 118 | cmd_timer = SYS_TIME + CMD_TIME; 119 | ping_timer = SYS_TIME + PING_TIME; 120 | } 121 | 122 | } 123 | 124 | } 125 | 126 | // Auto stop manual commands after CMD_TIME 127 | if (cmd_timer >0 && SYS_TIME > cmd_timer){ 128 | rx_data = spi_rw(CMD_STOP); 129 | cmd_timer=0; 130 | ping_timer = SYS_TIME + PING_TIME; 131 | } 132 | 133 | // Detect USB state every 1s & blink pwm led (Unleashed) 134 | if (SYS_TIME > ping_timer){ 135 | rx_data = spi_rw(CMD_DUMMY); 136 | PWM0_REG(PWM_CMP3) ^= 0x1; // CMP3 = LED4; 137 | ping_timer = SYS_TIME + PING_TIME; 138 | } 139 | 140 | // Update USB state & led on EXP board and broadcast usb messages 141 | if (rx_data != usb_state){ 142 | if (rx_data==0x12670000){ 143 | for (int z=1; z<4; z++) ECALL_SEND(z, "USB DEV ATTACH"); 144 | GPIO_REG(GPIO_OUT) |= 1<' && usb_state==0x12670000) owi_task_unfold(); 156 | if (msg[0]=='1' && usb_state==0x12670000) owi_task_start_request(); 157 | if (msg[0]=='0' || usb_state!=0x12670000) owi_task_stop_request(); 158 | int32_t cmd = -1; 159 | if ( usb_state==0x12670000 && (cmd = owi_task_run(SYS_TIME)) != -1){ 160 | rx_data = spi_rw((uint8_t[]){(uint8_t)cmd, (uint8_t)(cmd>>8), (uint8_t)(cmd>>16)}); 161 | ping_timer = SYS_TIME + PING_TIME; 162 | } 163 | 164 | // Yield CPU to other zones 165 | ECALL_YIELD(); 166 | 167 | } // while(1) 168 | 169 | } // main() 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /bsp/U540/newlib/newlib.c: -------------------------------------------------------------------------------- 1 | /* Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | 13 | //File descriptor 14 | enum FD { 15 | UART_FD = 0, 16 | ZONE0_FD = 3, 17 | ZONE1_FD, 18 | ZONE2_FD, 19 | ZONE3_FD, 20 | ZONE4_FD, 21 | MAX_FD, 22 | }; 23 | 24 | // ---------------------------------------------------------------------------- 25 | int _close(int file) { 26 | // ---------------------------------------------------------------------------- 27 | 28 | return -1; 29 | } 30 | 31 | // ---------------------------------------------------------------------------- 32 | int _fstat(int file, struct stat *st) { 33 | // ---------------------------------------------------------------------------- 34 | 35 | st->st_mode = S_IFCHR; 36 | return 0; 37 | } 38 | 39 | // ---------------------------------------------------------------------------- 40 | void * _sbrk(int incr) { 41 | // ---------------------------------------------------------------------------- 42 | 43 | extern char _end[]; 44 | extern char _heap_end[]; 45 | static char *_heap_ptr = _end; 46 | 47 | if ((_heap_ptr + incr < _end) || (_heap_ptr + incr > _heap_end)) 48 | return (void *) -1; 49 | 50 | _heap_ptr += incr; 51 | return _heap_ptr - incr; 52 | } 53 | 54 | // ---------------------------------------------------------------------------- 55 | int _isatty(int file) { 56 | // ---------------------------------------------------------------------------- 57 | 58 | return (file == STDIN_FILENO || file == STDOUT_FILENO || file == STDERR_FILENO 59 | || file == ZONE0_FD || file == ZONE1_FD || file == ZONE2_FD || file == ZONE3_FD 60 | || file == ZONE4_FD ) ? 1 : 0; 61 | 62 | } 63 | 64 | struct _file { 65 | const char *name; 66 | uint32_t rp; 67 | }; 68 | 69 | static struct _file files[MAX_FD] = { 70 | { 71 | .name = "UART", 72 | }, 73 | { 74 | .name = "UART", 75 | }, 76 | { 77 | .name = "UART", 78 | }, 79 | { 80 | .name = "ZONE0", 81 | }, 82 | { 83 | .name = "ZONE1", 84 | }, 85 | { 86 | .name = "ZONE2", 87 | }, 88 | { 89 | .name = "ZONE3", 90 | }, 91 | { 92 | .name = "ZONE4", 93 | }, 94 | }; 95 | 96 | // ---------------------------------------------------------------------------- 97 | const char * _ttyname(int file) { 98 | // ---------------------------------------------------------------------------- 99 | 100 | if (file >= MAX_FD) { 101 | return NULL; 102 | } else { 103 | return files[file].name; 104 | } 105 | 106 | } 107 | 108 | // ---------------------------------------------------------------------------- 109 | int _lseek(int file, off_t ptr, int dir) { 110 | // ---------------------------------------------------------------------------- 111 | 112 | return 0; 113 | } 114 | 115 | // ---------------------------------------------------------------------------- 116 | int _open(const char* name, int flags, int mode) { 117 | // ---------------------------------------------------------------------------- 118 | 119 | if ( strcmp(name, files[UART_FD].name) == 0 ) { 120 | 121 | UART0_REG(UART_LCR) = 0b10000000; // Enable Divisor latch access 122 | UART0_REG(UART_DLR) = AXI_FREQ/16/115200; 123 | UART0_REG(UART_LCR) = 0b00000011; // Disable Divisor latch access & set Word length=8bit 124 | 125 | UART0_REG(UART_FCR) = 0b00000111; // Clear TX/RX FIFO 126 | 127 | return (enum FD) UART_FD; 128 | 129 | } else { 130 | 131 | for (int i = ZONE0_FD; i <= ZONE4_FD; i++) { 132 | if ( strcmp(name, files[i].name) == 0 ) { 133 | files[i].rp = 0; 134 | return i; 135 | } 136 | } 137 | 138 | } 139 | 140 | return -1; 141 | } 142 | 143 | // ---------------------------------------------------------------------------- 144 | int _read(int file, char *ptr, size_t len) { 145 | // ---------------------------------------------------------------------------- 146 | 147 | ssize_t count = 0; 148 | static uint32_t msg[4] = {0}; 149 | int i = 0; 150 | 151 | if( _isatty(file) ) { 152 | 153 | switch (file){ 154 | 155 | case UART_FD: 156 | 157 | while( count>= 8; 179 | 180 | return i; 181 | break; 182 | 183 | default: 184 | 185 | /* Do nothing */ 186 | break; 187 | } 188 | 189 | } 190 | 191 | return -1; 192 | } 193 | 194 | // ---------------------------------------------------------------------------- 195 | size_t _write(int file, const void *ptr, size_t len) { 196 | // ---------------------------------------------------------------------------- 197 | 198 | uint8_t * buff = (uint8_t *)ptr; 199 | int i = 0; 200 | uint32_t msg[4]; 201 | 202 | if( _isatty(file) ) { 203 | 204 | switch (file){ 205 | 206 | case UART_FD: 207 | 208 | for (i = 0; i < len; i++) { 209 | 210 | while ( (UART0_REG(UART_LSR) & 1<<5) == 0){ECALL_YIELD();} // THRE Transmitter register empty 211 | 212 | UART0_REG(UART_THR) = buff[i]; 213 | 214 | if (buff[i] == '\n') { 215 | while ( (UART0_REG(UART_LSR) & 1<<5) == 0){;} // THRE 216 | UART0_REG(UART_THR) = '\r'; 217 | } 218 | 219 | } 220 | 221 | return len; 222 | break; 223 | 224 | case ZONE0_FD: 225 | case ZONE1_FD: 226 | case ZONE2_FD: 227 | case ZONE3_FD: 228 | case ZONE4_FD:{ 229 | 230 | /* Pack buff into a message & send - non blocking, timeout 5 x jiffy */ 231 | const unsigned long timeout = ECALL_CSRR_MTIME() + 5*10*RTC_FREQ/1000; 232 | 233 | while (i < len) { 234 | 235 | int transfer = len - i; 236 | if (transfer > sizeof(msg)) 237 | transfer = sizeof(msg); 238 | 239 | memset(msg, 0, sizeof(msg)); 240 | 241 | /* Copy buff to msg (8-bit operations) */ 242 | int real_transfer = 0; 243 | for(int j=0; j timeout){ 267 | return -1; 268 | } 269 | 270 | ECALL_YIELD(); 271 | 272 | } // while() 273 | 274 | return i; 275 | break; 276 | } 277 | 278 | } // switch() 279 | 280 | } // if(_isatty) 281 | 282 | return -1; 283 | 284 | } // _write() 285 | 286 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | HEX FIVE SECURITY, INC. 2 | SOFTWARE EVALUATION AGREEMENT 3 | 4 | THE TERMS AND CONDITIONS CONTAINED HEREIN CONSTITUTE A LEGAL AGREEMENT. 5 | THIS AGREEMENT ("AGREEMENT") CONTAINS THE ENTIRE AGREEMENT BETWEEN YOU 6 | LICENSEE ("YOU") AND HEX FIVE SECURITY, INC. ("HEX FIVE") WITH RESPECT TO 7 | THE TERMS AND CONDITIONS DESCRIBED HEREIN. READ THIS AGREEMENT CAREFULLY. 8 | BY DOWNLOADING/INSTALLING THE PRODUCT, YOU ACKNOWLEDGE THAT (1) YOU ARE 9 | AUTHORIZED TO ENTER THIS AGREEMENT FOR AND ON BEHALF OF YOUR COMPANY, AND 10 | ARE DOING SO, AND (2) YOU HAVE READ AND UNDERSTAND AND AGREE THAT YOU AND 11 | THE COMPANY SHALL BE BOUND BY THESE TERMS AND CONDITIONS AND ALL 12 | MODIFICATIONS AND ADDITIONS PROVIDED FOR 13 | 14 | Software products included with this product that are not Hex Five 15 | products are licensed to you by the software provider. Please refer to 16 | the license contained in the provider's product for the terms of use 17 | before using such products. 18 | 19 | 1. License Grant. Hex Five grants you a limited, non-exclusive, non- 20 | transferable license to use, for non-commercial, non-production 21 | evaluation purposes only, the Hex Five software program(s), known as 22 | MultiZone(TM) Security (the "Software") and related product documentation at 23 | no charge subject to the terms and restrictions set forth in this License 24 | Agreement. You are not permitted to use the Software in any manner not 25 | expressly authorized by this License. You acknowledge and agree that 26 | ownership of the Software and all subsequent copies thereof regardless of 27 | the form or media are held by Hex Five. 28 | 29 | 2. Term of Agreement. Your license is effective until terminated by Hex 30 | Five (at Hex Five's sole discretion and without notice). The License will 31 | terminate automatically if you fail to comply with any of the limitations 32 | or other requirements described herein. At termination you shall cease 33 | all use of the Software and destroy all copies, full or partial of the 34 | Software. 35 | 36 | 3. Ownership Rights. The Software and related documentation are protected 37 | by United States copyright laws and international treaties. Hex Five, 38 | third party component providers and open source component providers own 39 | and retain all right, title and interest in and to the Software and 40 | related documentation, including all copyrights, patents, trade secret 41 | rights, trademarks and other intellectual property rights therein. 42 | 43 | 4. Use of Name and Trademarks. You shall not use the name, trade names or 44 | trademarks of Hex Five or any of its affiliates in any advertising, 45 | promotional literature or any other material, whether in written, 46 | electronic or other form without express written permission of Hex Five. 47 | 48 | 5. Restrictions. 49 | (A) You may not rent, lease, lend, redistribute or sublicense the 50 | Software. You may not copy the Software except to make archival or backup 51 | copies, provided that the backup copy must include all copyright or other 52 | proprietary notices contained on the original. You may not copy the 53 | related product documentation. You may not modify, reverse engineer, 54 | decompile, or disassemble the Software, except to the extent the 55 | foregoing restriction is expressly prohibited by applicable law. You may 56 | not publish any results from tests using the Software without the express 57 | written permission of Hex Five. 58 | 59 | (B) Certain components of the Software are provided under various Open 60 | Source licenses that have been made available to Hex Five. You may modify 61 | or replace only these Open-Sourced Components; provided that (i) the 62 | resultant Software is used in place of the unmodified Software, on a 63 | single computer; and (ii) you otherwise comply with the terms of this 64 | License and any applicable licensing terms governing use of the Open- 65 | Sourced Components. Hex Five is not obligated to provide any maintenance, 66 | technical or other support for the resultant Software. 67 | 68 | (C) This license is strictly for non-commercial, non-production 69 | evaluation purposes. You agree and acknowledge that you may not use the 70 | Software for any commercial purpose whatsoever. 71 | 72 | 6. Feedback. You agree that any feedback or ideas you provide to us 73 | regarding any Software or any suggested improvements thereto (together, 74 | the "Feedback") will be the exclusive property of Hex Five. To the extent 75 | you own any rights in the Feedback, you agree to assign and hereby do 76 | assign to us all right, title and interest in and to the Feedback. You 77 | agree to perform all acts reasonably requested by us to perfect and 78 | enforce such rights, including without limitation executing copyright 79 | assignments. We will reimburse you for direct out of pocket costs 80 | incurred in complying with our requests. 81 | 82 | 7. Exclusion of Warranties. THE SOFTWARE IS PROVIDED TO LICENSEE "AS IS", 83 | AND ANY USE BY LICENSEE OF THE SOFTWARE WILL BE AT LICENSEE'S SOLE RISK. 84 | HEX FIVE MAKES NO WARRANTIES RELATING TO THE SOFTWARE AND EXPRESSLY 85 | DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT 86 | LIMITATION THOSE OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 87 | 88 | 8. Limitation of Liability. IN NO EVENT SHALL HEX FIVE BE LIABLE FOR ANY 89 | INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES WHATSOEVER, 90 | INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, LOSS OF DATA, 91 | BUSINESS INTERRUPTON OR ANY OTHER COMMERCIAL DAMAGES OR LOSSES, ARISING 92 | OUT OF OR RELATED TO YOUR USE OR INABILITY TO USE THE HEX FIVE SOFTWARE, 93 | HOWEVER CAUSED, REGARDLESS OF THE THEORY OF LIABILTY (CONTRACT, TORT OR 94 | OTHERWISE) AND EVEN IF HEX FIVE HAS BEEN ADVISED OF THE POSSIBILITY OF 95 | SUCH DAMAGES. 96 | 97 | 9. Governing Law, Dispute Resolution. This Agreement is governed by the 98 | law of the State of California, U.S.A., without reference to conflict of 99 | laws principles. The application of the United Nations Convention of 100 | Contracts for the International Sale of Goods is expressly excluded. 101 | Venue for any disputes shall be in the state and federal courts located 102 | in San Jose, California. 103 | 104 | 10.No Export. You agree not to export, directly or indirectly, the 105 | Software or any components thereof to any country for which the U.S. 106 | Government or any agency thereof at the time of export requires an export 107 | license or other government approval without first obtaining such license 108 | or approval. 109 | 110 | 11.Assignment/Transfers. You may not assign or transfer this Agreement, 111 | in whole or in part, without Hex Five's prior written consent. Any 112 | attempted assignment or transfer in violation of this Section will be 113 | null and void. 114 | 115 | 12.Third Party Acknowledgements. 116 | (A) Aspects of the Software utilize or include third party software and 117 | other copyrighted material. Acknowledgements, licensing terms and 118 | disclaimers for such material are available when accessing the Software 119 | on the Hex Five website, and your use of such material is governed by 120 | their respective terms. 121 | (B) The Software includes certain software provided under various Open 122 | Source licenses. You may obtain complete machine-readable copies of the 123 | source code and licenses for the Open Source software at the Hex Five 124 | Open Source website (https://www.hex-five.com/oslicenses). Open Source 125 | Software is distributed WITHOUT ANY WARRANTY, without even the implied 126 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE 127 | 128 | 13.Severability. If any provision of this Agreement is held invalid, 129 | illegal or unenforceable, the validity, legality and enforceability of 130 | any of the remaining provisions of this Agreement shall not in any way be 131 | affected or impaired. 132 | 133 | 14.Entire Agreement. This Agreement is the entire agreement between you 134 | and Hex Five concerning the Software and all related documentation and 135 | supersedes any other prior or contemporaneous agreements or 136 | communications with respect to the Software and related documentation, 137 | whether written or oral. 138 | 139 | 140 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MultiZone for Linux SDK 2 | 3 | Initial target is SiFive's Unleashed U540. 4 | 5 | U540 BSP components: 6 | 7 | * MultiZone: loaded to flash via OpenOCD => 0x2000_0000; 8 | * ZSBL: loaded to flash via OpenOCD => 0x2080_0000; 9 | * FSBL: loaded to mSD card => 0x0800_0000 L2 LIM; 10 | * BBL Linux: loaded to mSD card => 0x8000_0000 DDR; 11 | 12 | This repository is maintained by Hex Five Security. 13 | For Questions or feedback - send email to info 'at' hex-five.com 14 | 15 | 16 | ## Get it Ready 17 | 18 | ### Prebuilt RISC-V Toolchain 19 | 20 | Download Hex Five's reference toolchain or build your own: 21 | 22 | 1. GNU Embedded Toolchain - v2018.12.26: 23 | http://hex-five.com/riscv-gnu-toolchain-20181226 24 | 25 | 2. OpenOCD - v2018.12.26: 26 | http://hex-five.com/riscv-openocd-20181226 27 | 28 | ### Install the Toolchain 29 | 30 | Install the prebuilt RISC-V toolchain for Linux: 31 | ``` 32 | sudo apt update 33 | sudo apt upgrade -y 34 | sudo apt install git make default-jre libftdi1-dev 35 | sudo ln -s /usr/lib/x86_64-linux-gnu/libmpfr.so.6 /usr/lib/x86_64-linux-gnu/libmpfr.so.4 36 | wget https://hex-five.com/wp-content/uploads/riscv-gnu-toolchain-20181226.tar.xz 37 | tar -xvf riscv-gnu-toolchain-20181226.tar.xz 38 | wget https://hex-five.com/wp-content/uploads/riscv-openocd-20181226.tar.xz 39 | tar -xvf riscv-openocd-20181226.tar.xz 40 | git clone https://github.com/hex-five/multizone-sdk 41 | sudo apt-get install libusb-0.1-4 42 | sudo apt-get install picocom 43 | sudo apt-get install screen 44 | ``` 45 | 46 | > Note: for the Ubuntu 19.04 LTS you may need to install the libncurses5 package. 47 | > ``` 48 | > sudo apt-get install libncurses5:i386 49 | > sudo apt-get install libncurses5:amd64 50 | > ``` 51 | 52 | Add environment variables and a path to allow the Makefiles to find the toolchain by editing the ~/.bashrc and placing the following text at the bottom of the file: 53 | 54 | ``` 55 | export RISCV=/home//riscv-gnu-toolchain-20181226 56 | export OPENOCD=/home//riscv-openocd-20181226 57 | export PATH="$PATH:/home//riscv-gnu-toolchain-20181226/bin" 58 | ``` 59 | 60 | > Note: <_username_> shall be replaced by your username. 61 | 62 | Close and restart the terminal session for these changes to take effect. 63 | 64 | 65 | 66 | ## Flash Programming Instructions 67 | 68 | 1. Download the prebuilt MultiZone for Linux package from Hex Five's website (http://hex-five.com/multizone-linux-20190808): 69 | 70 | ``` 71 | $ wget https://hex-five.com/wp-content/uploads/multizone-linux-20190808.tar.xz 72 | $ tar -xvf multizone-linux-20190808.tar.xz 73 | $ cd multizone-linux-release/ 74 | ``` 75 | 76 | 2. Flash the Board (Multizone & ZSBL): 77 | 78 | ``` 79 | $ ./flash.sh board 80 | ``` 81 | 82 | 2. Flash the SD Card (FSBL & BBL) 83 | 84 | ``` 85 | $ ./flash.sh 86 | ``` 87 | 88 | > Note: shall be replaced with the device name of the SD card (e.g, /dev/mmcblock0 or /dev/sda). 89 | 90 | 91 | ## MultiZone Instructions 92 | 93 | (If you just want to test the Multizone for Linux SDK reference image, please skip directly to "Demo".) 94 | 95 | 1. Clone the MultiZone for Linux SDK repo: 96 | 97 | ``` 98 | $ git clone https://github.com/hex-five/multizone-linux 99 | ``` 100 | 101 | 2. Build the MultiZone SDK for the U540: 102 | ``` 103 | $ make BOARD=U540 104 | ``` 105 | 106 | 3. Load the MultiZone SDK image to flash (0x2000_0000): 107 | ``` 108 | $ make load BOARD=U540 109 | ``` 110 | 111 | 112 | 113 | ## Demo 114 | 115 | The MultiZone system contains four zones: 116 | 117 | * Zone 1: Multizone demo console accessible via Linux device /dev/multizone1; 118 | * Zone 2: Multizone demo console accessible via Linux device /dev/multizone2; 119 | * Zone 3: Multizone demo console accessible via UART 115200/8/N/1 (expansion board); 120 | * Zone 4: MultiZone Heartbeat LED D4 and message echo; 121 | 122 | 123 | ### Get the board ready 124 | 125 | Set the mode select switches to '0001': 126 | 127 | ``` 128 | USB LED Mode Select Ethernet 129 | +===|___|==****==+-+-+-+-+-+-+=================|******|===+ 130 | | | | | |X|X|X| | | | 131 | | | | | | | | | | | | 132 | | HFXSEL->|X|X|X| | | | |______| | 133 | | +-+-+-+-+-+-+ | 134 | | RTCSEL-----/ 0 1 2 3 <--MSEL | 135 | | | 136 | ``` 137 | 138 | ### Operate the Demo 139 | 140 | 1. Power the board. 141 | 142 | 2. Connect to the UART by setting the baudrate to 115200/8/N/1: 143 | 144 | ``` 145 | $ picocom /dev/ -b 115200 146 | ``` 147 | 148 | > Note: shall be replaced with the correct UART device name (e.g, ttyUSB0, ttyUSB1). 149 | 150 | You should be able to see on the terminal the FSBL loading the BBL image: 151 | 152 | ``` 153 | SiFive FSBL: 2019-08-7-d8f6e2f 154 | Using FSBL DTB 155 | HiFive-U serial #: 00000068 156 | Loading boot payload......................... 157 | ``` 158 | 159 | Once the BBL boots Linux, Linux starts executing: 160 | 161 | ``` 162 | bbl loader 163 | ... 164 | ``` 165 | 166 | 3. Login to Linux using the root accout: 167 | 168 | ``` 169 | Welcome to Buildroot 170 | buildroot login: root 171 | Password: hexfive 172 | # 173 | ``` 174 | 175 | 4. Connect to Zone1 via Linux: 176 | 177 | ``` 178 | # screen /dev/multizone1 179 | ``` 180 | 181 | You shall be able to see and operate the terminal running on Zone1: 182 | 183 | ``` 184 | ===================================================================== 185 | Hex Five MultiZone(TM) Security 186 | Copyright (C) 2018 Hex Five Security Inc. All Rights Reserved 187 | ===================================================================== 188 | This version of MultiZone(TM) is meant for evaluation purposes only. 189 | As such, use of this software is governed by your Evaluation License. 190 | There may be other functional limitations as described in the 191 | evaluation kit documentation. The full version of the software does 192 | not have these restrictions. 193 | ===================================================================== 194 | Machine ISA : 0x00101105 RV64 ACIMU 195 | Vendor : 0x00000000 196 | Architecture : 0x00000000 197 | Implementation: 0x00000000 198 | Hart ID : 0x00000000 199 | CPU clock : 1000 MHz 200 | 201 | Z1 > 202 | ``` 203 | 204 | > Note: you may need to type 'restart' to see the full initial screen. 205 | 206 | 207 | 5. Connect to Zone2 via Linux using SSH: 208 | 209 | ``` 210 | $ ssh root@192.168.0.2 211 | The authenticity of host '192.168.0.2 (192.168.0.2)' can't be established. 212 | ECDSA key fingerprint is SHA256:5CMY+vBWX7VIyJ+ejpwtw9kojdYogIdBFPSJ9YmG33g. 213 | Are you sure you want to continue connecting (yes/no)? yes 214 | Warning: Permanently added '192.168.0.2' (ECDSA) to the list of known hosts. 215 | root@192.168.0.2's password: hexfive 216 | # screen /dev/multizone2 217 | ``` 218 | 219 | > Note: you may need to delete the old key before executing the SSH command. 220 | > ``` 221 | > ssh-keygen -f "/home//.ssh/known_hosts" -R "192.168.0.2" 222 | > ``` 223 | 224 | 225 | 6. Operate the Zone2 console: 226 | 227 | ``` 228 | ===================================================================== 229 | Hex Five MultiZone(TM) Security 230 | Copyright (C) 2018 Hex Five Security Inc. All Rights Reserved 231 | ===================================================================== 232 | This version of MultiZone(TM) is meant for evaluation purposes only. 233 | As such, use of this software is governed by your Evaluation License. 234 | There may be other functional limitations as described in the 235 | evaluation kit documentation. The full version of the software does 236 | not have these restrictions. 237 | ===================================================================== 238 | Machine ISA : 0x00101105 RV64 ACIMU 239 | Vendor : 0x00000000 240 | Architecture : 0x00000000 241 | Implementation: 0x00000000 242 | Hart ID : 0x00000000 243 | CPU clock : 1000 MHz 244 | 245 | Z2 > pmp 246 | 0x20020000 0x2002FFFF r-x NAPOT 247 | 0x08002000 0x08002FFF rw- NAPOT 248 | 249 | Z2 > 250 | ``` 251 | 252 | 7. In case the HiFive Unleashed U540 is connected to the Microchip / Microsemi Aloe Vera kit, it's possible to operate Zone3 via the UART (J36) available on the expansion board: 253 | 254 | ``` 255 | $ picocom /dev/ -b 115200 256 | ``` 257 | 258 | > Note: shall be replaced with the correct UART device name (e.g, ttyUSB0, ttyUSB1). 259 | 260 | You shall be able to see and operate the terminal running on Zone3: 261 | 262 | ``` 263 | ===================================================================== 264 | Hex Five MultiZone(TM) Security 265 | Copyright (C) 2018 Hex Five Security Inc. All Rights Reserved 266 | ===================================================================== 267 | This version of MultiZone(TM) is meant for evaluation purposes only. 268 | As such, use of this software is governed by your Evaluation License. 269 | There may be other functional limitations as described in the 270 | evaluation kit documentation. The full version of the software does 271 | not have these restrictions. 272 | ===================================================================== 273 | Machine ISA : 0x00101105 RV64 ACIMU 274 | Vendor : 0x00000000 275 | Architecture : 0x00000000 276 | Implementation: 0x00000000 277 | Hart ID : 0x00000000 278 | CPU clock : 1000 MHz 279 | 280 | Z3 > 281 | ``` 282 | 283 | > Note: 284 | > Alternative way to run the demo via Ethernet (no UART connection required): 285 | > 286 | > Open a first SSH session as described above then connect to Zone1 via: 287 | > ``` 288 | ># screen /dev/multizone1 289 | > ``` 290 | > Open a second SSH sessions as described above then connect to Zone2 via: 291 | > ``` 292 | > # screen /dev/multizone2 293 | > ``` 294 | > 295 | > To terminate screen sessions type: crtl-a k. 296 | 297 | 298 | _MultiZone and HEX-Five are registered trademarks of Hex Five Security, Inc._ 299 | 300 | _MultiZone technology is protected by patents US 11,151,262 and PCT/US2019/038774_ 301 | -------------------------------------------------------------------------------- /zone3/main.c: -------------------------------------------------------------------------------- 1 | /* Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include // round() 9 | 10 | #include 11 | #include 12 | 13 | #define CMD_LINE_SIZE 32 14 | #define MSG_SIZE 4 15 | #define ZONE 3 16 | #define STD_OUT 0 17 | #define STD_IN 0 18 | 19 | void trap_0x0_handler(void)__attribute__((interrupt("user"))); 20 | void trap_0x0_handler(void){ 21 | 22 | int msg[MSG_SIZE]={0,0,0,0}; 23 | ECALL_RECV(ZONE, msg); 24 | printf("Instruction address misaligned : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 25 | 26 | printf("\nPress any key to restart"); 27 | char c='\0'; while ( read(STD_IN, &c, 1) <=0 ); asm ("j _start"); // blocking 28 | 29 | } 30 | 31 | void trap_0x1_handler(void)__attribute__((interrupt("user"))); 32 | void trap_0x1_handler(void){ 33 | 34 | int msg[MSG_SIZE]={0,0,0,0}; 35 | ECALL_RECV(ZONE, msg); 36 | printf("Instruction access fault : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 37 | 38 | printf("\nPress any key to restart"); 39 | char c='\0'; while ( read(STD_IN, &c, 1) <=0 ); asm ("j _start"); // blocking 40 | 41 | } 42 | 43 | void trap_0x2_handler(void)__attribute__((interrupt("user"))); 44 | void trap_0x2_handler(void){ 45 | 46 | int msg[MSG_SIZE]={0,0,0,0}; 47 | ECALL_RECV(ZONE, msg); 48 | printf("Illegal instruction : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 49 | 50 | } 51 | 52 | void trap_0x3_handler(void)__attribute__((interrupt("user"))); 53 | void trap_0x3_handler(void){ 54 | 55 | const uint64_t T = ECALL_CSRR_MTIME(); 56 | 57 | printf("\e7"); // save curs pos 58 | printf("\e[r"); // scroll all screen 59 | printf("\e[2M"); // scroll up up 60 | printf("\e8"); // restore curs pos 61 | printf("\e[2A"); // curs up 2 lines 62 | printf("\e[2L\r"); // insert 2 lines 63 | 64 | printf("Z%d > ",ZONE); 65 | printf("timer expired : %lu", (unsigned long)(T*1000/RTC_FREQ)); 66 | 67 | printf("\e8"); // restore curs pos 68 | 69 | } 70 | 71 | void trap_0x4_handler(void)__attribute__((interrupt("user"))); 72 | void trap_0x4_handler(void){ 73 | 74 | int msg[MSG_SIZE]={0,0,0,0}; 75 | ECALL_RECV(ZONE, msg); 76 | printf("Load address misaligned : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 77 | 78 | } 79 | 80 | void trap_0x5_handler(void)__attribute__((interrupt("user"))); 81 | void trap_0x5_handler(void){ 82 | 83 | int msg[MSG_SIZE]={0,0,0,0}; 84 | ECALL_RECV(ZONE, msg); 85 | printf("Load access fault : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 86 | 87 | } 88 | 89 | void trap_0x6_handler(void)__attribute__((interrupt("user"))); 90 | void trap_0x6_handler(void){ 91 | 92 | int msg[MSG_SIZE]={0,0,0,0}; 93 | ECALL_RECV(ZONE, msg); 94 | printf("Store/AMO address misaligned : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 95 | 96 | } 97 | 98 | void trap_0x7_handler(void)__attribute__((interrupt("user"))); 99 | void trap_0x7_handler(void){ 100 | 101 | int msg[MSG_SIZE]={0,0,0,0}; 102 | ECALL_RECV(ZONE, msg); 103 | printf("Store access fault : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 104 | 105 | } 106 | 107 | // ------------------------------------------------------------------------ 108 | void print_cpu_info(void) { 109 | // ------------------------------------------------------------------------ 110 | 111 | // misa 112 | uint64_t misa = 0x0; asm volatile("csrr %0, misa" : "=r"(misa)); // trap & emulate example 113 | //const uint64_t misa = ECALL_CSRR_MISA(); 114 | 115 | const int xlen = ((misa >> __riscv_xlen-2)&0b11)==1 ? 32 : 116 | ((misa >> __riscv_xlen-2)&0b11)==2 ? 64 : 117 | ((misa >> __riscv_xlen-2)&0b11)==1 ? 128 : 0; 118 | 119 | char misa_str[26+1]=""; 120 | for (int i=0, j=0; i<26; i++) 121 | if ( (misa & (1ul << i)) !=0){ 122 | misa_str[j++]=(char)('A'+i); misa_str[j]='\0'; 123 | } 124 | 125 | printf("Machine ISA : 0x%08x RV%d %s \n", (int)misa, xlen, misa_str); 126 | 127 | // mvendorid 128 | const uint64_t mvendorid = ECALL_CSRR_MVENDID(); 129 | const char *mvendorid_str = (mvendorid==0x10e31913 ? "SiFive, Inc.\0" : 130 | mvendorid==0x489 ? "SiFive, Inc.\0" : 131 | mvendorid==0x57c ? "Hex Five, Inc.\0" : 132 | "\0"); 133 | printf("Vendor : 0x%08x %s \n", (int)mvendorid, mvendorid_str); 134 | 135 | // marchid 136 | const uint64_t marchid = ECALL_CSRR_MARCHID(); 137 | const char *marchid_str = (mvendorid==0x489 && (int)misa==0x40101105 && marchid==0x80000002 ? "E21\0" : 138 | mvendorid==0x489 && (int)misa==0x40101105 && marchid==0x00000001 ? "E31\0" : 139 | mvendorid==0x489 && misa==0x8000000000101105 && marchid==0x00000001 ? "S51\0" : 140 | mvendorid==0x57c && (int)misa==0x40101105 && marchid==0x00000001 ? "X300\0" : 141 | "\0"); 142 | printf("Architecture : 0x%08x %s \n", (int)marchid, marchid_str); 143 | 144 | // mimpid 145 | const uint64_t mimpid = ECALL_CSRR_MIMPID(); 146 | printf("Implementation: 0x%08x \n", (int)mimpid ); 147 | 148 | // mhartid 149 | const uint64_t mhartid = ECALL_CSRR_MHARTID(); 150 | printf("Hart ID : 0x%08x \n", (int)mhartid ); 151 | 152 | // CPU Clock 153 | const int cpu_clk = round(CPU_FREQ/1E+6); 154 | printf("CPU clock : %d MHz \n", cpu_clk ); 155 | 156 | } 157 | 158 | // ------------------------------------------------------------------------ 159 | int cmpfunc(const void* a , const void* b){ 160 | // ------------------------------------------------------------------------ 161 | const int ai = *(const int* )a; 162 | const int bi = *(const int* )b; 163 | return ai < bi ? -1 : ai > bi ? 1 : 0; 164 | } 165 | 166 | // ------------------------------------------------------------------------ 167 | void print_stats(void){ 168 | // ------------------------------------------------------------------------ 169 | 170 | #define COUNT (10+1) // odd values for median 171 | #define MHZ (CPU_FREQ/1000000) 172 | 173 | int cycles[COUNT]; 174 | 175 | for (int i=0, first=1; i max_cycle ? cycles[i] : max_cycle; 187 | int max_col = 0; 188 | while(max_cycle>0){ 189 | max_col++; max_cycle /= 10; 190 | } 191 | for (int i=0; i0 && cycles>0){ // mhpmcounters might not be implemented 204 | printf("\n"); 205 | printf("ctx sw instr = %lu \n", ctxsw_instr); 206 | printf("ctx sw cycles = %lu \n", ctxsw_cycle); 207 | printf("ctx sw time = %d us \n", (int)(ctxsw_cycle/MHZ)); 208 | } 209 | 210 | } 211 | 212 | // ------------------------------------------------------------------------ 213 | void print_pmp(void){ 214 | // ------------------------------------------------------------------------ 215 | 216 | #define TOR 0b00001000 217 | #define NA4 0b00010000 218 | #define NAPOT 0b00011000 219 | 220 | #define PMP_R 1<<0 221 | #define PMP_W 1<<1 222 | #define PMP_X 1<<2 223 | 224 | volatile uint64_t pmpcfg=0x0; 225 | #if __riscv_xlen==32 226 | volatile uint32_t pmpcfg0; asm ( "csrr %0, pmpcfg0" : "=r"(pmpcfg0) ); 227 | volatile uint32_t pmpcfg1; asm ( "csrr %0, pmpcfg1" : "=r"(pmpcfg1) ); 228 | pmpcfg = pmpcfg1; 229 | pmpcfg <<= 32; 230 | pmpcfg |= pmpcfg0; 231 | #else 232 | asm ( "csrr %0, pmpcfg0" : "=r"(pmpcfg) ); 233 | #endif 234 | 235 | #if __riscv_xlen==32 236 | uint32_t pmpaddr[8]; 237 | #else 238 | uint64_t pmpaddr[8]; 239 | #endif 240 | asm ( "csrr %0, pmpaddr0" : "=r"(pmpaddr[0]) ); 241 | asm ( "csrr %0, pmpaddr1" : "=r"(pmpaddr[1]) ); 242 | asm ( "csrr %0, pmpaddr2" : "=r"(pmpaddr[2]) ); 243 | asm ( "csrr %0, pmpaddr3" : "=r"(pmpaddr[3]) ); 244 | asm ( "csrr %0, pmpaddr4" : "=r"(pmpaddr[4]) ); 245 | asm ( "csrr %0, pmpaddr5" : "=r"(pmpaddr[5]) ); 246 | asm ( "csrr %0, pmpaddr6" : "=r"(pmpaddr[6]) ); 247 | asm ( "csrr %0, pmpaddr7" : "=r"(pmpaddr[7]) ); 248 | 249 | for (int i=0; i<8; i++){ 250 | 251 | const uint8_t cfg = (pmpcfg >> 8*i); if (cfg==0x0) continue; 252 | 253 | char rwx[3+1] = {cfg & PMP_R ? 'r':'-', cfg & PMP_W ? 'w':'-', cfg & PMP_X ? 'x':'-', '\0'}; 254 | 255 | uint64_t start=0, end=0; 256 | 257 | char type[5+1]=""; 258 | 259 | if ( (cfg & (TOR | NA4 | NAPOT)) == TOR){ 260 | start = pmpaddr[i-1]<<2; 261 | end = (pmpaddr[i]<<2) -1; 262 | strcpy(type, "TOR"); 263 | 264 | } else if ( (cfg & (TOR | NA4 | NAPOT)) == NA4){ 265 | start = pmpaddr[i]<<2; 266 | end = start+4 -1; 267 | strcpy(type, "NA4"); 268 | 269 | } else if ( (cfg & (TOR | NA4 | NAPOT)) == NAPOT){ 270 | for (int j=0; j<__riscv_xlen; j++){ 271 | if ( ((pmpaddr[i] >> j) & 0x1) == 0){ 272 | const uint64_t size = 1 << (3+j); 273 | start = (pmpaddr[i] >>j) <<(j+2); 274 | end = start + size -1; 275 | strcpy(type, "NAPOT"); 276 | break; 277 | } 278 | } 279 | 280 | } else break; 281 | 282 | #if __riscv_xlen==32 283 | printf("0x%08x 0x%08x %s %s \n", (unsigned int)start, (unsigned int)end, rwx, type); 284 | #else 285 | printf("0x%08" PRIX64 " 0x%08" PRIX64 " %s %s \n", start, end, rwx, type); 286 | #endif 287 | 288 | } 289 | 290 | } 291 | 292 | // ------------------------------------------------------------------------ 293 | int readline(char *cmd_line) { 294 | // ------------------------------------------------------------------------ 295 | int p=0; 296 | char c='\0'; 297 | int esc=0; 298 | cmd_line[0] = '\0'; 299 | static char history[CMD_LINE_SIZE+1]=""; 300 | 301 | while(c!='\r' && c!='\n'){ 302 | 303 | if ( read(STD_IN, &c, 1) > 0 ) { 304 | 305 | if (c=='\e'){ 306 | esc=1; 307 | 308 | } else if (esc==1 && c=='['){ 309 | esc=2; 310 | 311 | } else if (esc==2 && c=='3'){ 312 | esc=3; 313 | 314 | } else if (esc==3 && c=='~'){ // del key 315 | for (int i=p; i0){ 332 | p--; 333 | printf("\e[D"); 334 | } 335 | 336 | } else if (esc==2 && c=='A'){ // up arrow 337 | esc=0; 338 | if (strlen(history)>0){ 339 | p=strlen(history); 340 | strcpy(cmd_line, history); 341 | printf("\e[2K\r"); // 2K clear entire line - cur pos dosn't change 342 | printf("Z%d > ",ZONE); 343 | printf("%s",&cmd_line[0]); 344 | } 345 | 346 | } else if (esc==2 && c=='B'){ // down arrow 347 | esc=0; 348 | 349 | } else if ((c=='\b' || c=='\x7f') && p>0 && esc==0){ // backspace 350 | p--; 351 | for (int i=p; i=' ' && c<='~' && p < CMD_LINE_SIZE && esc==0){ 359 | for (int i = CMD_LINE_SIZE-1; i > p; i--) cmd_line[i]=cmd_line[i-1]; // make room for 1 ch 360 | cmd_line[p]=c; 361 | printf("\e7"); // save curs pos 362 | printf("\e[K"); // clear line from curs pos 363 | printf("%s",&cmd_line[p]); p++; 364 | printf("\e8"); // restore curs pos 365 | printf("\e[C"); // move curs right 1 pos 366 | 367 | } else 368 | esc=0; 369 | } 370 | 371 | // Message handler 372 | for (int zone=1; zone<=4; zone++){ 373 | 374 | char msg[16]=""; 375 | 376 | if (ECALL_RECV(zone, msg)) { 377 | 378 | if (strcmp("ping", msg) == 0) 379 | ECALL_SEND(zone, "pong"); 380 | 381 | else { 382 | printf("\e7\e[2K"); // save curs pos & clear entire line 383 | printf("\rZ%d > %.16s\n", zone, msg); // print source zone 384 | printf("\nZ%d > %s", ZONE, cmd_line); // print message 385 | printf("\e8\e[2B"); // restore curs pos & curs down 2x 386 | } 387 | } 388 | 389 | } 390 | 391 | ECALL_YIELD(); 392 | 393 | } 394 | 395 | for (int i = CMD_LINE_SIZE-1; i > 0; i--) 396 | if (cmd_line[i]==' ') cmd_line[i]='\0'; else break; 397 | 398 | if (strlen(cmd_line)>0) 399 | strcpy(history, cmd_line); 400 | 401 | return strlen(cmd_line); 402 | 403 | } 404 | 405 | // ------------------------------------------------------------------------ 406 | int main (void) { 407 | // ------------------------------------------------------------------------ 408 | 409 | //volatile int w=0; while(1){w++;} 410 | //while(1) ECALL_YIELD(); 411 | 412 | ECALL_TRP_VECT(0x0, trap_0x0_handler); // 0x0 Instruction address misaligned 413 | ECALL_TRP_VECT(0x1, trap_0x1_handler); // 0x1 Instruction access fault 414 | ECALL_TRP_VECT(0x2, trap_0x2_handler); // 0x2 Illegal Instruction 415 | ECALL_TRP_VECT(0x3, trap_0x3_handler); // 0x3 Soft timer 416 | ECALL_TRP_VECT(0x4, trap_0x4_handler); // 0x4 Load address misaligned 417 | ECALL_TRP_VECT(0x5, trap_0x5_handler); // 0x5 Load access fault 418 | ECALL_TRP_VECT(0x6, trap_0x6_handler); // 0x6 Store/AMO address misaligned 419 | ECALL_TRP_VECT(0x7, trap_0x7_handler); // 0x7 Store access fault 420 | 421 | freopen("UART", "r+", stdin); 422 | freopen("UART", "a+", stdout); 423 | 424 | printf("\e[2J\e[H"); // clear terminal screen 425 | printf("=====================================================================\n"); 426 | printf(" Hex Five MultiZone(TM) Security \n"); 427 | printf(" Copyright (C) 2018 Hex Five Security Inc. All Rights Reserved \n"); 428 | printf("=====================================================================\n"); 429 | printf("This version of MultiZone(TM) is meant for evaluation purposes only. \n"); 430 | printf("As such, use of this software is governed by your Evaluation License.\n"); 431 | printf("There may be other functional limitations as described in the \n"); 432 | printf("evaluation kit documentation. The full version of the software does \n"); 433 | printf("not have these restrictions. \n"); 434 | printf("=====================================================================\n"); 435 | 436 | print_cpu_info(); 437 | 438 | char cmd_line[CMD_LINE_SIZE+1]=""; 439 | int msg[MSG_SIZE]={0,0,0,0}; 440 | 441 | while(1){ 442 | 443 | printf("\nZ%d > ",ZONE); 444 | 445 | readline(cmd_line); 446 | 447 | printf("\n"); 448 | 449 | char * tk1 = strtok (cmd_line, " "); 450 | char * tk2 = strtok (NULL, " "); 451 | char * tk3 = strtok (NULL, " "); 452 | 453 | // -------------------------------------------------------------------- 454 | if (tk1 != NULL && strcmp(tk1, "load")==0){ 455 | // -------------------------------------------------------------------- 456 | if (tk2 != NULL){ 457 | uint8_t data = 0x00; 458 | const uint64_t addr = strtoull(tk2, NULL, 16); 459 | asm ("lbu %0, (%1)" : "+r"(data) : "r"(addr)); 460 | printf("0x%08x : 0x%02x \n", (unsigned int)addr, data); 461 | } else printf("Syntax: load address \n"); 462 | 463 | // -------------------------------------------------------------------- 464 | } else if (tk1 != NULL && strcmp(tk1, "store")==0){ 465 | // -------------------------------------------------------------------- 466 | if (tk2 != NULL && tk3 != NULL){ 467 | const uint32_t data = (uint32_t)strtoul(tk3, NULL, 16); 468 | const uint64_t addr = strtoull(tk2, NULL, 16); 469 | 470 | if ( strlen(tk3) <=2 ) 471 | asm ( "sb %0, (%1)" : : "r"(data), "r"(addr)); 472 | else if ( strlen(tk3) <=4 ) 473 | asm ( "sh %0, (%1)" : : "r"(data), "r"(addr)); 474 | else 475 | asm ( "sw %0, (%1)" : : "r"(data), "r"(addr)); 476 | 477 | printf("0x%08x : 0x%02x \n", (unsigned int)addr, (unsigned int)data); 478 | } else printf("Syntax: store address data \n"); 479 | 480 | // -------------------------------------------------------------------- 481 | } else if (tk1 != NULL && strcmp(tk1, "exec")==0){ 482 | // -------------------------------------------------------------------- 483 | if (tk2 != NULL){ 484 | const uint64_t addr = strtoull(tk2, NULL, 16); 485 | asm ( "jr (%0)" : : "r"(addr)); 486 | } else printf("Syntax: exec address \n"); 487 | 488 | // -------------------------------------------------------------------- 489 | } else if (tk1 != NULL && strcmp(tk1, "send")==0){ 490 | // -------------------------------------------------------------------- 491 | if (tk2 != NULL && tk2[0]>='1' && tk2[0]<='4' && tk3 != NULL){ 492 | char msg[16]; strncpy(msg, tk3, 16); 493 | if (!ECALL_SEND( tk2[0]-'0', msg) ) 494 | printf("Error: Inbox full.\n"); 495 | } else printf("Syntax: send {1|2|3|4} message \n"); 496 | 497 | // -------------------------------------------------------------------- 498 | } else if (tk1 != NULL && strcmp(tk1, "recv")==0){ 499 | // -------------------------------------------------------------------- 500 | if (tk2 != NULL && tk2[0]>='1' && tk2[0]<='4'){ 501 | char msg[16]; 502 | if (ECALL_RECV(tk2[0]-'0', msg)) 503 | printf("msg : %.16s\n", msg); 504 | else 505 | printf("Error: Inbox empty.\n"); 506 | } else printf("Syntax: recv {1|2|3|4} \n"); 507 | 508 | // -------------------------------------------------------------------- 509 | } else if (tk1 != NULL && strcmp(tk1, "yield")==0){ 510 | // -------------------------------------------------------------------- 511 | uint64_t C1 = ECALL_CSRR_MCYCLE(); 512 | ECALL_YIELD(); 513 | uint64_t C2 = ECALL_CSRR_MCYCLE(); 514 | const int T = ((C2-C1)*1000000)/CPU_FREQ; 515 | printf( (T>0 ? "yield : elapsed time %dus \n" : "yield : n/a \n"), T); 516 | 517 | } else if (tk1 != NULL && strcmp(tk1, "stats")==0){ 518 | print_stats(); 519 | 520 | } else if (tk1 != NULL && strcmp(tk1, "restart")==0){ 521 | asm ("j _start"); 522 | 523 | } else if (tk1 != NULL && strcmp(tk1, "timer")==0){ 524 | if (tk2 != NULL){ 525 | const uint64_t ms = abs(strtoull(tk2, NULL, 10)); 526 | const uint64_t T0 = ECALL_CSRR_MTIME(); 527 | const uint64_t T1 = T0 + ms*RTC_FREQ/1000; 528 | ECALL_CSRW_MTIMECMP(T1); 529 | printf("timer set T0=%lu, T1=%lu \n", (unsigned long)(T0*1000/RTC_FREQ), 530 | (unsigned long)(T1*1000/RTC_FREQ) ); 531 | } else printf("Syntax: timer ms \n"); 532 | 533 | } else if (tk1 != NULL && strcmp(tk1, "pmp")==0){ 534 | print_pmp(); 535 | 536 | } else 537 | printf("Commands: load store exec send recv yield pmp stats timer restart \n"); 538 | 539 | } 540 | 541 | } 542 | -------------------------------------------------------------------------------- /zone1/main.c: -------------------------------------------------------------------------------- 1 | /* Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include // round() 9 | 10 | #include 11 | #include 12 | 13 | #define CMD_LINE_SIZE 32 14 | #define MSG_SIZE 4 15 | #define ZONE 1 16 | #define STD_OUT 3 17 | #define STD_IN 3 18 | 19 | void trap_0x0_handler(void)__attribute__((interrupt("user"))); 20 | void trap_0x0_handler(void){ 21 | 22 | int msg[MSG_SIZE]={0,0,0,0}; 23 | ECALL_RECV(ZONE, msg); 24 | printf("Instruction address misaligned : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 25 | 26 | printf("\nPress any key to restart"); 27 | char c='\0'; while ( read(STD_IN, &c, 1) <=0 ); asm ("j _start"); // blocking 28 | 29 | } 30 | 31 | void trap_0x1_handler(void)__attribute__((interrupt("user"))); 32 | void trap_0x1_handler(void){ 33 | 34 | int msg[MSG_SIZE]={0,0,0,0}; 35 | ECALL_RECV(ZONE, msg); 36 | printf("Instruction access fault : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 37 | 38 | printf("\nPress any key to restart"); 39 | char c='\0'; while ( read(STD_IN, &c, 1) <=0 ); asm ("j _start"); // blocking 40 | 41 | } 42 | 43 | void trap_0x2_handler(void)__attribute__((interrupt("user"))); 44 | void trap_0x2_handler(void){ 45 | 46 | int msg[MSG_SIZE]={0,0,0,0}; 47 | ECALL_RECV(ZONE, msg); 48 | printf("Illegal instruction : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 49 | 50 | } 51 | 52 | void trap_0x3_handler(void)__attribute__((interrupt("user"))); 53 | void trap_0x3_handler(void){ 54 | 55 | const uint64_t T = ECALL_CSRR_MTIME(); 56 | 57 | printf("\e7"); // save curs pos 58 | printf("\e[r"); // scroll all screen 59 | printf("\e[2M"); // scroll up up 60 | printf("\e8"); // restore curs pos 61 | printf("\e[2A"); // curs up 2 lines 62 | printf("\e[2L\r"); // insert 2 lines 63 | 64 | printf("Z%d > ",ZONE); 65 | printf("timer expired : %lu", (unsigned long)(T*1000/RTC_FREQ)); 66 | 67 | printf("\e8"); // restore curs pos 68 | 69 | } 70 | 71 | void trap_0x4_handler(void)__attribute__((interrupt("user"))); 72 | void trap_0x4_handler(void){ 73 | 74 | int msg[MSG_SIZE]={0,0,0,0}; 75 | ECALL_RECV(ZONE, msg); 76 | printf("Load address misaligned : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 77 | 78 | } 79 | 80 | void trap_0x5_handler(void)__attribute__((interrupt("user"))); 81 | void trap_0x5_handler(void){ 82 | 83 | int msg[MSG_SIZE]={0,0,0,0}; 84 | ECALL_RECV(ZONE, msg); 85 | printf("Load access fault : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 86 | 87 | } 88 | 89 | void trap_0x6_handler(void)__attribute__((interrupt("user"))); 90 | void trap_0x6_handler(void){ 91 | 92 | int msg[MSG_SIZE]={0,0,0,0}; 93 | ECALL_RECV(ZONE, msg); 94 | printf("Store/AMO address misaligned : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 95 | 96 | } 97 | 98 | void trap_0x7_handler(void)__attribute__((interrupt("user"))); 99 | void trap_0x7_handler(void){ 100 | 101 | int msg[MSG_SIZE]={0,0,0,0}; 102 | ECALL_RECV(ZONE, msg); 103 | printf("Store access fault : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 104 | 105 | } 106 | 107 | // ------------------------------------------------------------------------ 108 | void print_cpu_info(void) { 109 | // ------------------------------------------------------------------------ 110 | 111 | // misa 112 | uint64_t misa = 0x0; asm volatile("csrr %0, misa" : "=r"(misa)); // trap & emulate example 113 | //const uint64_t misa = ECALL_CSRR_MISA(); 114 | 115 | const int xlen = ((misa >> __riscv_xlen-2)&0b11)==1 ? 32 : 116 | ((misa >> __riscv_xlen-2)&0b11)==2 ? 64 : 117 | ((misa >> __riscv_xlen-2)&0b11)==1 ? 128 : 0; 118 | 119 | char misa_str[26+1]=""; 120 | for (int i=0, j=0; i<26; i++) 121 | if ( (misa & (1ul << i)) !=0){ 122 | misa_str[j++]=(char)('A'+i); misa_str[j]='\0'; 123 | } 124 | 125 | printf("Machine ISA : 0x%08x RV%d %s \n", (int)misa, xlen, misa_str); 126 | 127 | // mvendorid 128 | const uint64_t mvendorid = ECALL_CSRR_MVENDID(); 129 | const char *mvendorid_str = (mvendorid==0x10e31913 ? "SiFive, Inc.\0" : 130 | mvendorid==0x489 ? "SiFive, Inc.\0" : 131 | mvendorid==0x57c ? "Hex Five, Inc.\0" : 132 | "\0"); 133 | printf("Vendor : 0x%08x %s \n", (int)mvendorid, mvendorid_str); 134 | 135 | // marchid 136 | const uint64_t marchid = ECALL_CSRR_MARCHID(); 137 | const char *marchid_str = (mvendorid==0x489 && (int)misa==0x40101105 && marchid==0x80000002 ? "E21\0" : 138 | mvendorid==0x489 && (int)misa==0x40101105 && marchid==0x00000001 ? "E31\0" : 139 | mvendorid==0x489 && misa==0x8000000000101105 && marchid==0x00000001 ? "S51\0" : 140 | mvendorid==0x57c && (int)misa==0x40101105 && marchid==0x00000001 ? "X300\0" : 141 | "\0"); 142 | printf("Architecture : 0x%08x %s \n", (int)marchid, marchid_str); 143 | 144 | // mimpid 145 | const uint64_t mimpid = ECALL_CSRR_MIMPID(); 146 | printf("Implementation: 0x%08x \n", (int)mimpid ); 147 | 148 | // mhartid 149 | const uint64_t mhartid = ECALL_CSRR_MHARTID(); 150 | printf("Hart ID : 0x%08x \n", (int)mhartid ); 151 | 152 | // CPU Clock 153 | const int cpu_clk = round(CPU_FREQ/1E+6); 154 | printf("CPU clock : %d MHz \n", cpu_clk ); 155 | 156 | } 157 | 158 | // ------------------------------------------------------------------------ 159 | int cmpfunc(const void* a , const void* b){ 160 | // ------------------------------------------------------------------------ 161 | const int ai = *(const int* )a; 162 | const int bi = *(const int* )b; 163 | return ai < bi ? -1 : ai > bi ? 1 : 0; 164 | } 165 | 166 | // ------------------------------------------------------------------------ 167 | void print_stats(void){ 168 | // ------------------------------------------------------------------------ 169 | 170 | #define COUNT (10+1) // odd values for median 171 | #define MHZ (CPU_FREQ/1000000) 172 | 173 | int cycles[COUNT]; 174 | 175 | for (int i=0, first=1; i max_cycle ? cycles[i] : max_cycle; 187 | int max_col = 0; 188 | while(max_cycle>0){ 189 | max_col++; max_cycle /= 10; 190 | } 191 | for (int i=0; i0 && cycles>0){ // mhpmcounters might not be implemented 204 | printf("\n"); 205 | printf("ctx sw instr = %lu \n", ctxsw_instr); 206 | printf("ctx sw cycles = %lu \n", ctxsw_cycle); 207 | printf("ctx sw time = %d us \n", (int)(ctxsw_cycle/MHZ)); 208 | } 209 | 210 | } 211 | 212 | // ------------------------------------------------------------------------ 213 | void print_pmp(void){ 214 | // ------------------------------------------------------------------------ 215 | 216 | #define TOR 0b00001000 217 | #define NA4 0b00010000 218 | #define NAPOT 0b00011000 219 | 220 | #define PMP_R 1<<0 221 | #define PMP_W 1<<1 222 | #define PMP_X 1<<2 223 | 224 | volatile uint64_t pmpcfg=0x0; 225 | #if __riscv_xlen==32 226 | volatile uint32_t pmpcfg0; asm ( "csrr %0, pmpcfg0" : "=r"(pmpcfg0) ); 227 | volatile uint32_t pmpcfg1; asm ( "csrr %0, pmpcfg1" : "=r"(pmpcfg1) ); 228 | pmpcfg = pmpcfg1; 229 | pmpcfg <<= 32; 230 | pmpcfg |= pmpcfg0; 231 | #else 232 | asm ( "csrr %0, pmpcfg0" : "=r"(pmpcfg) ); 233 | #endif 234 | 235 | #if __riscv_xlen==32 236 | uint32_t pmpaddr[8]; 237 | #else 238 | uint64_t pmpaddr[8]; 239 | #endif 240 | asm ( "csrr %0, pmpaddr0" : "=r"(pmpaddr[0]) ); 241 | asm ( "csrr %0, pmpaddr1" : "=r"(pmpaddr[1]) ); 242 | asm ( "csrr %0, pmpaddr2" : "=r"(pmpaddr[2]) ); 243 | asm ( "csrr %0, pmpaddr3" : "=r"(pmpaddr[3]) ); 244 | asm ( "csrr %0, pmpaddr4" : "=r"(pmpaddr[4]) ); 245 | asm ( "csrr %0, pmpaddr5" : "=r"(pmpaddr[5]) ); 246 | asm ( "csrr %0, pmpaddr6" : "=r"(pmpaddr[6]) ); 247 | asm ( "csrr %0, pmpaddr7" : "=r"(pmpaddr[7]) ); 248 | 249 | for (int i=0; i<8; i++){ 250 | 251 | const uint8_t cfg = (pmpcfg >> 8*i); if (cfg==0x0) continue; 252 | 253 | char rwx[3+1] = {cfg & PMP_R ? 'r':'-', cfg & PMP_W ? 'w':'-', cfg & PMP_X ? 'x':'-', '\0'}; 254 | 255 | uint64_t start=0, end=0; 256 | 257 | char type[5+1]=""; 258 | 259 | if ( (cfg & (TOR | NA4 | NAPOT)) == TOR){ 260 | start = pmpaddr[i-1]<<2; 261 | end = (pmpaddr[i]<<2) -1; 262 | strcpy(type, "TOR"); 263 | 264 | } else if ( (cfg & (TOR | NA4 | NAPOT)) == NA4){ 265 | start = pmpaddr[i]<<2; 266 | end = start+4 -1; 267 | strcpy(type, "NA4"); 268 | 269 | } else if ( (cfg & (TOR | NA4 | NAPOT)) == NAPOT){ 270 | for (int j=0; j<__riscv_xlen; j++){ 271 | if ( ((pmpaddr[i] >> j) & 0x1) == 0){ 272 | const uint64_t size = 1 << (3+j); 273 | start = (pmpaddr[i] >>j) <<(j+2); 274 | end = start + size -1; 275 | strcpy(type, "NAPOT"); 276 | break; 277 | } 278 | } 279 | 280 | } else break; 281 | 282 | #if __riscv_xlen==32 283 | printf("0x%08x 0x%08x %s %s \n", (unsigned int)start, (unsigned int)end, rwx, type); 284 | #else 285 | printf("0x%08" PRIX64 " 0x%08" PRIX64 " %s %s \n", start, end, rwx, type); 286 | #endif 287 | 288 | } 289 | 290 | } 291 | 292 | // ------------------------------------------------------------------------ 293 | int readline(char *cmd_line) { 294 | // ------------------------------------------------------------------------ 295 | int p=0; 296 | char c='\0'; 297 | int esc=0; 298 | cmd_line[0] = '\0'; 299 | static char history[CMD_LINE_SIZE+1]=""; 300 | 301 | while(c!='\r' && c!='\n'){ 302 | 303 | if ( read(STD_IN, &c, 1) > 0 ) { 304 | 305 | if (c=='\e'){ 306 | esc=1; 307 | 308 | } else if (esc==1 && c=='['){ 309 | esc=2; 310 | 311 | } else if (esc==2 && c=='3'){ 312 | esc=3; 313 | 314 | } else if (esc==3 && c=='~'){ // del key 315 | for (int i=p; i0){ 332 | p--; 333 | printf("\e[D"); 334 | } 335 | 336 | } else if (esc==2 && c=='A'){ // up arrow 337 | esc=0; 338 | if (strlen(history)>0){ 339 | p=strlen(history); 340 | strcpy(cmd_line, history); 341 | printf("\e[2K\r"); // 2K clear entire line - cur pos dosn't change 342 | printf("Z%d > ",ZONE); 343 | printf("%s",&cmd_line[0]); 344 | } 345 | 346 | } else if (esc==2 && c=='B'){ // down arrow 347 | esc=0; 348 | 349 | } else if ((c=='\b' || c=='\x7f') && p>0 && esc==0){ // backspace 350 | p--; 351 | for (int i=p; i=' ' && c<='~' && p < CMD_LINE_SIZE && esc==0){ 359 | for (int i = CMD_LINE_SIZE-1; i > p; i--) cmd_line[i]=cmd_line[i-1]; // make room for 1 ch 360 | cmd_line[p]=c; 361 | printf("\e7"); // save curs pos 362 | printf("\e[K"); // clear line from curs pos 363 | printf("%s",&cmd_line[p]); p++; 364 | printf("\e8"); // restore curs pos 365 | printf("\e[C"); // move curs right 1 pos 366 | 367 | } else 368 | esc=0; 369 | } 370 | 371 | // Message handler 372 | for (int zone=1; zone<=4; zone++){ 373 | 374 | char msg[16]=""; 375 | 376 | if (ECALL_RECV(zone, msg)) { 377 | 378 | if (strcmp("ping", msg) == 0) 379 | ECALL_SEND(zone, "pong"); 380 | 381 | else { 382 | printf("\e7\e[2K"); // save curs pos & clear entire line 383 | printf("\rZ%d > %.16s\n", zone, msg); // print source zone 384 | printf("\nZ%d > %s", ZONE, cmd_line); // print message 385 | printf("\e8\e[2B"); // restore curs pos & curs down 2x 386 | } 387 | } 388 | 389 | } 390 | 391 | ECALL_YIELD(); 392 | 393 | } 394 | 395 | for (int i = CMD_LINE_SIZE-1; i > 0; i--) 396 | if (cmd_line[i]==' ') cmd_line[i]='\0'; else break; 397 | 398 | if (strlen(cmd_line)>0) 399 | strcpy(history, cmd_line); 400 | 401 | return strlen(cmd_line); 402 | 403 | } 404 | 405 | // ------------------------------------------------------------------------ 406 | int main (void) { 407 | // ------------------------------------------------------------------------ 408 | 409 | //volatile int w=0; while(1){w++;} 410 | //while(1) ECALL_YIELD(); 411 | 412 | ECALL_TRP_VECT(0x0, trap_0x0_handler); // 0x0 Instruction address misaligned 413 | ECALL_TRP_VECT(0x1, trap_0x1_handler); // 0x1 Instruction access fault 414 | ECALL_TRP_VECT(0x2, trap_0x2_handler); // 0x2 Illegal Instruction 415 | ECALL_TRP_VECT(0x3, trap_0x3_handler); // 0x3 Soft timer 416 | ECALL_TRP_VECT(0x4, trap_0x4_handler); // 0x4 Load address misaligned 417 | ECALL_TRP_VECT(0x5, trap_0x5_handler); // 0x5 Load access fault 418 | ECALL_TRP_VECT(0x6, trap_0x6_handler); // 0x6 Store/AMO address misaligned 419 | ECALL_TRP_VECT(0x7, trap_0x7_handler); // 0x7 Store access fault 420 | 421 | freopen("ZONE0", "r+", stdin); 422 | freopen("ZONE0", "a+", stdout); 423 | 424 | printf("\e[2J\e[H"); // clear terminal screen 425 | printf("=====================================================================\n"); 426 | printf(" Hex Five MultiZone(TM) Security \n"); 427 | printf(" Copyright (C) 2018 Hex Five Security Inc. All Rights Reserved \n"); 428 | printf("=====================================================================\n"); 429 | printf("This version of MultiZone(TM) is meant for evaluation purposes only. \n"); 430 | printf("As such, use of this software is governed by your Evaluation License.\n"); 431 | printf("There may be other functional limitations as described in the \n"); 432 | printf("evaluation kit documentation. The full version of the software does \n"); 433 | printf("not have these restrictions. \n"); 434 | printf("=====================================================================\n"); 435 | 436 | print_cpu_info(); 437 | 438 | char cmd_line[CMD_LINE_SIZE+1]=""; 439 | int msg[MSG_SIZE]={0,0,0,0}; 440 | 441 | while(1){ 442 | 443 | printf("\nZ%d > ",ZONE); 444 | 445 | readline(cmd_line); 446 | 447 | printf("\n"); 448 | 449 | char * tk1 = strtok (cmd_line, " "); 450 | char * tk2 = strtok (NULL, " "); 451 | char * tk3 = strtok (NULL, " "); 452 | 453 | // -------------------------------------------------------------------- 454 | if (tk1 != NULL && strcmp(tk1, "load")==0){ 455 | // -------------------------------------------------------------------- 456 | if (tk2 != NULL){ 457 | uint8_t data = 0x00; 458 | const uint64_t addr = strtoull(tk2, NULL, 16); 459 | asm ("lbu %0, (%1)" : "+r"(data) : "r"(addr)); 460 | printf("0x%08x : 0x%02x \n", (unsigned int)addr, data); 461 | } else printf("Syntax: load address \n"); 462 | 463 | // -------------------------------------------------------------------- 464 | } else if (tk1 != NULL && strcmp(tk1, "store")==0){ 465 | // -------------------------------------------------------------------- 466 | if (tk2 != NULL && tk3 != NULL){ 467 | const uint32_t data = (uint32_t)strtoul(tk3, NULL, 16); 468 | const uint64_t addr = strtoull(tk2, NULL, 16); 469 | 470 | if ( strlen(tk3) <=2 ) 471 | asm ( "sb %0, (%1)" : : "r"(data), "r"(addr)); 472 | else if ( strlen(tk3) <=4 ) 473 | asm ( "sh %0, (%1)" : : "r"(data), "r"(addr)); 474 | else 475 | asm ( "sw %0, (%1)" : : "r"(data), "r"(addr)); 476 | 477 | printf("0x%08x : 0x%02x \n", (unsigned int)addr, (unsigned int)data); 478 | } else printf("Syntax: store address data \n"); 479 | 480 | // -------------------------------------------------------------------- 481 | } else if (tk1 != NULL && strcmp(tk1, "exec")==0){ 482 | // -------------------------------------------------------------------- 483 | if (tk2 != NULL){ 484 | const uint64_t addr = strtoull(tk2, NULL, 16); 485 | asm ( "jr (%0)" : : "r"(addr)); 486 | } else printf("Syntax: exec address \n"); 487 | 488 | // -------------------------------------------------------------------- 489 | } else if (tk1 != NULL && strcmp(tk1, "send")==0){ 490 | // -------------------------------------------------------------------- 491 | if (tk2 != NULL && tk2[0]>='1' && tk2[0]<='4' && tk3 != NULL){ 492 | char msg[16]; strncpy(msg, tk3, 16); 493 | if (!ECALL_SEND( tk2[0]-'0', msg) ) 494 | printf("Error: Inbox full.\n"); 495 | } else printf("Syntax: send {1|2|3|4} message \n"); 496 | 497 | // -------------------------------------------------------------------- 498 | } else if (tk1 != NULL && strcmp(tk1, "recv")==0){ 499 | // -------------------------------------------------------------------- 500 | if (tk2 != NULL && tk2[0]>='1' && tk2[0]<='4'){ 501 | char msg[16]; 502 | if (ECALL_RECV(tk2[0]-'0', msg)) 503 | printf("msg : %.16s\n", msg); 504 | else 505 | printf("Error: Inbox empty.\n"); 506 | } else printf("Syntax: recv {1|2|3|4} \n"); 507 | 508 | // -------------------------------------------------------------------- 509 | } else if (tk1 != NULL && strcmp(tk1, "yield")==0){ 510 | // -------------------------------------------------------------------- 511 | uint64_t C1 = ECALL_CSRR_MCYCLE(); 512 | ECALL_YIELD(); 513 | uint64_t C2 = ECALL_CSRR_MCYCLE(); 514 | const int T = ((C2-C1)*1000000)/CPU_FREQ; 515 | printf( (T>0 ? "yield : elapsed time %dus \n" : "yield : n/a \n"), T); 516 | 517 | } else if (tk1 != NULL && strcmp(tk1, "stats")==0){ 518 | print_stats(); 519 | 520 | } else if (tk1 != NULL && strcmp(tk1, "restart")==0){ 521 | asm ("j _start"); 522 | 523 | } else if (tk1 != NULL && strcmp(tk1, "timer")==0){ 524 | if (tk2 != NULL){ 525 | const uint64_t ms = abs(strtoull(tk2, NULL, 10)); 526 | const uint64_t T0 = ECALL_CSRR_MTIME(); 527 | const uint64_t T1 = T0 + ms*RTC_FREQ/1000; 528 | ECALL_CSRW_MTIMECMP(T1); 529 | printf("timer set T0=%lu, T1=%lu \n", (unsigned long)(T0*1000/RTC_FREQ), 530 | (unsigned long)(T1*1000/RTC_FREQ) ); 531 | } else printf("Syntax: timer ms \n"); 532 | 533 | } else if (tk1 != NULL && strcmp(tk1, "pmp")==0){ 534 | print_pmp(); 535 | 536 | } else 537 | printf("Commands: load store exec send recv yield pmp stats timer restart \n"); 538 | 539 | } 540 | 541 | } 542 | -------------------------------------------------------------------------------- /zone2/main.c: -------------------------------------------------------------------------------- 1 | /* Copyright(C) 2018 Hex Five Security, Inc. - All Rights Reserved */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include // round() 9 | 10 | #include 11 | #include 12 | 13 | #define CMD_LINE_SIZE 32 14 | #define MSG_SIZE 4 15 | #define ZONE 2 16 | #define STD_OUT 3 17 | #define STD_IN 3 18 | 19 | void trap_0x0_handler(void)__attribute__((interrupt("user"))); 20 | void trap_0x0_handler(void){ 21 | 22 | int msg[MSG_SIZE]={0,0,0,0}; 23 | ECALL_RECV(ZONE, msg); 24 | printf("Instruction address misaligned : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 25 | 26 | printf("\nPress any key to restart"); 27 | char c='\0'; while ( read(STD_IN, &c, 1) <=0 ); asm ("j _start"); // blocking 28 | 29 | } 30 | 31 | void trap_0x1_handler(void)__attribute__((interrupt("user"))); 32 | void trap_0x1_handler(void){ 33 | 34 | int msg[MSG_SIZE]={0,0,0,0}; 35 | ECALL_RECV(ZONE, msg); 36 | printf("Instruction access fault : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 37 | 38 | printf("\nPress any key to restart"); 39 | char c='\0'; while ( read(STD_IN, &c, 1) <=0 ); asm ("j _start"); // blocking 40 | 41 | } 42 | 43 | void trap_0x2_handler(void)__attribute__((interrupt("user"))); 44 | void trap_0x2_handler(void){ 45 | 46 | int msg[MSG_SIZE]={0,0,0,0}; 47 | ECALL_RECV(ZONE, msg); 48 | printf("Illegal instruction : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 49 | 50 | } 51 | 52 | void trap_0x3_handler(void)__attribute__((interrupt("user"))); 53 | void trap_0x3_handler(void){ 54 | 55 | const uint64_t T = ECALL_CSRR_MTIME(); 56 | 57 | printf("\e7"); // save curs pos 58 | printf("\e[r"); // scroll all screen 59 | printf("\e[2M"); // scroll up up 60 | printf("\e8"); // restore curs pos 61 | printf("\e[2A"); // curs up 2 lines 62 | printf("\e[2L\r"); // insert 2 lines 63 | 64 | printf("Z%d > ",ZONE); 65 | printf("timer expired : %lu", (unsigned long)(T*1000/RTC_FREQ)); 66 | 67 | printf("\e8"); // restore curs pos 68 | 69 | } 70 | 71 | void trap_0x4_handler(void)__attribute__((interrupt("user"))); 72 | void trap_0x4_handler(void){ 73 | 74 | int msg[MSG_SIZE]={0,0,0,0}; 75 | ECALL_RECV(ZONE, msg); 76 | printf("Load address misaligned : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 77 | 78 | } 79 | 80 | void trap_0x5_handler(void)__attribute__((interrupt("user"))); 81 | void trap_0x5_handler(void){ 82 | 83 | int msg[MSG_SIZE]={0,0,0,0}; 84 | ECALL_RECV(ZONE, msg); 85 | printf("Load access fault : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 86 | 87 | } 88 | 89 | void trap_0x6_handler(void)__attribute__((interrupt("user"))); 90 | void trap_0x6_handler(void){ 91 | 92 | int msg[MSG_SIZE]={0,0,0,0}; 93 | ECALL_RECV(ZONE, msg); 94 | printf("Store/AMO address misaligned : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 95 | 96 | } 97 | 98 | void trap_0x7_handler(void)__attribute__((interrupt("user"))); 99 | void trap_0x7_handler(void){ 100 | 101 | int msg[MSG_SIZE]={0,0,0,0}; 102 | ECALL_RECV(ZONE, msg); 103 | printf("Store access fault : 0x%08x 0x%08x 0x%08x \n", msg[0], msg[1], msg[2]); 104 | 105 | } 106 | 107 | // ------------------------------------------------------------------------ 108 | void print_cpu_info(void) { 109 | // ------------------------------------------------------------------------ 110 | 111 | // misa 112 | uint64_t misa = 0x0; asm volatile("csrr %0, misa" : "=r"(misa)); // trap & emulate example 113 | //const uint64_t misa = ECALL_CSRR_MISA(); 114 | 115 | const int xlen = ((misa >> __riscv_xlen-2)&0b11)==1 ? 32 : 116 | ((misa >> __riscv_xlen-2)&0b11)==2 ? 64 : 117 | ((misa >> __riscv_xlen-2)&0b11)==1 ? 128 : 0; 118 | 119 | char misa_str[26+1]=""; 120 | for (int i=0, j=0; i<26; i++) 121 | if ( (misa & (1ul << i)) !=0){ 122 | misa_str[j++]=(char)('A'+i); misa_str[j]='\0'; 123 | } 124 | 125 | printf("Machine ISA : 0x%08x RV%d %s \n", (int)misa, xlen, misa_str); 126 | 127 | // mvendorid 128 | const uint64_t mvendorid = ECALL_CSRR_MVENDID(); 129 | const char *mvendorid_str = (mvendorid==0x10e31913 ? "SiFive, Inc.\0" : 130 | mvendorid==0x489 ? "SiFive, Inc.\0" : 131 | mvendorid==0x57c ? "Hex Five, Inc.\0" : 132 | "\0"); 133 | printf("Vendor : 0x%08x %s \n", (int)mvendorid, mvendorid_str); 134 | 135 | // marchid 136 | const uint64_t marchid = ECALL_CSRR_MARCHID(); 137 | const char *marchid_str = (mvendorid==0x489 && (int)misa==0x40101105 && marchid==0x80000002 ? "E21\0" : 138 | mvendorid==0x489 && (int)misa==0x40101105 && marchid==0x00000001 ? "E31\0" : 139 | mvendorid==0x489 && misa==0x8000000000101105 && marchid==0x00000001 ? "S51\0" : 140 | mvendorid==0x57c && (int)misa==0x40101105 && marchid==0x00000001 ? "X300\0" : 141 | "\0"); 142 | printf("Architecture : 0x%08x %s \n", (int)marchid, marchid_str); 143 | 144 | // mimpid 145 | const uint64_t mimpid = ECALL_CSRR_MIMPID(); 146 | printf("Implementation: 0x%08x \n", (int)mimpid ); 147 | 148 | // mhartid 149 | const uint64_t mhartid = ECALL_CSRR_MHARTID(); 150 | printf("Hart ID : 0x%08x \n", (int)mhartid ); 151 | 152 | // CPU Clock 153 | const int cpu_clk = round(CPU_FREQ/1E+6); 154 | printf("CPU clock : %d MHz \n", cpu_clk ); 155 | 156 | } 157 | 158 | // ------------------------------------------------------------------------ 159 | int cmpfunc(const void* a , const void* b){ 160 | // ------------------------------------------------------------------------ 161 | const int ai = *(const int* )a; 162 | const int bi = *(const int* )b; 163 | return ai < bi ? -1 : ai > bi ? 1 : 0; 164 | } 165 | 166 | // ------------------------------------------------------------------------ 167 | void print_stats(void){ 168 | // ------------------------------------------------------------------------ 169 | 170 | #define COUNT (10+1) // odd values for median 171 | #define MHZ (CPU_FREQ/1000000) 172 | 173 | int cycles[COUNT]; 174 | 175 | for (int i=0, first=1; i max_cycle ? cycles[i] : max_cycle; 187 | int max_col = 0; 188 | while(max_cycle>0){ 189 | max_col++; max_cycle /= 10; 190 | } 191 | for (int i=0; i0 && cycles>0){ // mhpmcounters might not be implemented 204 | printf("\n"); 205 | printf("ctx sw instr = %lu \n", ctxsw_instr); 206 | printf("ctx sw cycles = %lu \n", ctxsw_cycle); 207 | printf("ctx sw time = %d us \n", (int)(ctxsw_cycle/MHZ)); 208 | } 209 | 210 | } 211 | 212 | // ------------------------------------------------------------------------ 213 | void print_pmp(void){ 214 | // ------------------------------------------------------------------------ 215 | 216 | #define TOR 0b00001000 217 | #define NA4 0b00010000 218 | #define NAPOT 0b00011000 219 | 220 | #define PMP_R 1<<0 221 | #define PMP_W 1<<1 222 | #define PMP_X 1<<2 223 | 224 | volatile uint64_t pmpcfg=0x0; 225 | #if __riscv_xlen==32 226 | volatile uint32_t pmpcfg0; asm ( "csrr %0, pmpcfg0" : "=r"(pmpcfg0) ); 227 | volatile uint32_t pmpcfg1; asm ( "csrr %0, pmpcfg1" : "=r"(pmpcfg1) ); 228 | pmpcfg = pmpcfg1; 229 | pmpcfg <<= 32; 230 | pmpcfg |= pmpcfg0; 231 | #else 232 | asm ( "csrr %0, pmpcfg0" : "=r"(pmpcfg) ); 233 | #endif 234 | 235 | #if __riscv_xlen==32 236 | uint32_t pmpaddr[8]; 237 | #else 238 | uint64_t pmpaddr[8]; 239 | #endif 240 | asm ( "csrr %0, pmpaddr0" : "=r"(pmpaddr[0]) ); 241 | asm ( "csrr %0, pmpaddr1" : "=r"(pmpaddr[1]) ); 242 | asm ( "csrr %0, pmpaddr2" : "=r"(pmpaddr[2]) ); 243 | asm ( "csrr %0, pmpaddr3" : "=r"(pmpaddr[3]) ); 244 | asm ( "csrr %0, pmpaddr4" : "=r"(pmpaddr[4]) ); 245 | asm ( "csrr %0, pmpaddr5" : "=r"(pmpaddr[5]) ); 246 | asm ( "csrr %0, pmpaddr6" : "=r"(pmpaddr[6]) ); 247 | asm ( "csrr %0, pmpaddr7" : "=r"(pmpaddr[7]) ); 248 | 249 | for (int i=0; i<8; i++){ 250 | 251 | const uint8_t cfg = (pmpcfg >> 8*i); if (cfg==0x0) continue; 252 | 253 | char rwx[3+1] = {cfg & PMP_R ? 'r':'-', cfg & PMP_W ? 'w':'-', cfg & PMP_X ? 'x':'-', '\0'}; 254 | 255 | uint64_t start=0, end=0; 256 | 257 | char type[5+1]=""; 258 | 259 | if ( (cfg & (TOR | NA4 | NAPOT)) == TOR){ 260 | start = pmpaddr[i-1]<<2; 261 | end = (pmpaddr[i]<<2) -1; 262 | strcpy(type, "TOR"); 263 | 264 | } else if ( (cfg & (TOR | NA4 | NAPOT)) == NA4){ 265 | start = pmpaddr[i]<<2; 266 | end = start+4 -1; 267 | strcpy(type, "NA4"); 268 | 269 | } else if ( (cfg & (TOR | NA4 | NAPOT)) == NAPOT){ 270 | for (int j=0; j<__riscv_xlen; j++){ 271 | if ( ((pmpaddr[i] >> j) & 0x1) == 0){ 272 | const uint64_t size = 1 << (3+j); 273 | start = (pmpaddr[i] >>j) <<(j+2); 274 | end = start + size -1; 275 | strcpy(type, "NAPOT"); 276 | break; 277 | } 278 | } 279 | 280 | } else break; 281 | 282 | #if __riscv_xlen==32 283 | printf("0x%08x 0x%08x %s %s \n", (unsigned int)start, (unsigned int)end, rwx, type); 284 | #else 285 | printf("0x%08" PRIX64 " 0x%08" PRIX64 " %s %s \n", start, end, rwx, type); 286 | #endif 287 | 288 | } 289 | 290 | } 291 | 292 | // ------------------------------------------------------------------------ 293 | int readline(char *cmd_line) { 294 | // ------------------------------------------------------------------------ 295 | int p=0; 296 | char c='\0'; 297 | int esc=0; 298 | cmd_line[0] = '\0'; 299 | static char history[CMD_LINE_SIZE+1]=""; 300 | 301 | while(c!='\r' && c!='\n'){ 302 | 303 | if ( read(STD_IN, &c, 1) > 0 ) { 304 | 305 | if (c=='\e'){ 306 | esc=1; 307 | 308 | } else if (esc==1 && c=='['){ 309 | esc=2; 310 | 311 | } else if (esc==2 && c=='3'){ 312 | esc=3; 313 | 314 | } else if (esc==3 && c=='~'){ // del key 315 | for (int i=p; i0){ 332 | p--; 333 | printf("\e[D"); 334 | } 335 | 336 | } else if (esc==2 && c=='A'){ // up arrow 337 | esc=0; 338 | if (strlen(history)>0){ 339 | p=strlen(history); 340 | strcpy(cmd_line, history); 341 | printf("\e[2K\r"); // 2K clear entire line - cur pos dosn't change 342 | printf("Z%d > ",ZONE); 343 | printf("%s",&cmd_line[0]); 344 | } 345 | 346 | } else if (esc==2 && c=='B'){ // down arrow 347 | esc=0; 348 | 349 | } else if ((c=='\b' || c=='\x7f') && p>0 && esc==0){ // backspace 350 | p--; 351 | for (int i=p; i=' ' && c<='~' && p < CMD_LINE_SIZE && esc==0){ 359 | for (int i = CMD_LINE_SIZE-1; i > p; i--) cmd_line[i]=cmd_line[i-1]; // make room for 1 ch 360 | cmd_line[p]=c; 361 | printf("\e7"); // save curs pos 362 | printf("\e[K"); // clear line from curs pos 363 | printf("%s",&cmd_line[p]); p++; 364 | printf("\e8"); // restore curs pos 365 | printf("\e[C"); // move curs right 1 pos 366 | 367 | } else 368 | esc=0; 369 | } 370 | 371 | // Message handler 372 | for (int zone=1; zone<=4; zone++){ 373 | 374 | char msg[16]=""; 375 | 376 | if (ECALL_RECV(zone, msg)) { 377 | 378 | if (strcmp("ping", msg) == 0) 379 | ECALL_SEND(zone, "pong"); 380 | 381 | else { 382 | printf("\e7\e[2K"); // save curs pos & clear entire line 383 | printf("\rZ%d > %.16s\n", zone, msg); // print source zone 384 | printf("\nZ%d > %s", ZONE, cmd_line); // print message 385 | printf("\e8\e[2B"); // restore curs pos & curs down 2x 386 | } 387 | } 388 | 389 | } 390 | 391 | ECALL_YIELD(); 392 | 393 | } 394 | 395 | for (int i = CMD_LINE_SIZE-1; i > 0; i--) 396 | if (cmd_line[i]==' ') cmd_line[i]='\0'; else break; 397 | 398 | if (strlen(cmd_line)>0) 399 | strcpy(history, cmd_line); 400 | 401 | return strlen(cmd_line); 402 | 403 | } 404 | 405 | // ------------------------------------------------------------------------ 406 | int main (void) { 407 | // ------------------------------------------------------------------------ 408 | 409 | //volatile int w=0; while(1){w++;} 410 | //while(1) ECALL_YIELD(); 411 | 412 | ECALL_TRP_VECT(0x0, trap_0x0_handler); // 0x0 Instruction address misaligned 413 | ECALL_TRP_VECT(0x1, trap_0x1_handler); // 0x1 Instruction access fault 414 | ECALL_TRP_VECT(0x2, trap_0x2_handler); // 0x2 Illegal Instruction 415 | ECALL_TRP_VECT(0x3, trap_0x3_handler); // 0x3 Soft timer 416 | ECALL_TRP_VECT(0x4, trap_0x4_handler); // 0x4 Load address misaligned 417 | ECALL_TRP_VECT(0x5, trap_0x5_handler); // 0x5 Load access fault 418 | ECALL_TRP_VECT(0x6, trap_0x6_handler); // 0x6 Store/AMO address misaligned 419 | ECALL_TRP_VECT(0x7, trap_0x7_handler); // 0x7 Store access fault 420 | 421 | freopen("ZONE0", "r+", stdin); 422 | freopen("ZONE0", "a+", stdout); 423 | 424 | printf("\e[2J\e[H"); // clear terminal screen 425 | printf("=====================================================================\n"); 426 | printf(" Hex Five MultiZone(TM) Security \n"); 427 | printf(" Copyright (C) 2018 Hex Five Security Inc. All Rights Reserved \n"); 428 | printf("=====================================================================\n"); 429 | printf("This version of MultiZone(TM) is meant for evaluation purposes only. \n"); 430 | printf("As such, use of this software is governed by your Evaluation License.\n"); 431 | printf("There may be other functional limitations as described in the \n"); 432 | printf("evaluation kit documentation. The full version of the software does \n"); 433 | printf("not have these restrictions. \n"); 434 | printf("=====================================================================\n"); 435 | 436 | print_cpu_info(); 437 | 438 | char cmd_line[CMD_LINE_SIZE+1]=""; 439 | int msg[MSG_SIZE]={0,0,0,0}; 440 | 441 | while(1){ 442 | 443 | printf("\nZ%d > ",ZONE); 444 | 445 | readline(cmd_line); 446 | 447 | printf("\n"); 448 | 449 | char * tk1 = strtok (cmd_line, " "); 450 | char * tk2 = strtok (NULL, " "); 451 | char * tk3 = strtok (NULL, " "); 452 | 453 | // -------------------------------------------------------------------- 454 | if (tk1 != NULL && strcmp(tk1, "load")==0){ 455 | // -------------------------------------------------------------------- 456 | if (tk2 != NULL){ 457 | uint8_t data = 0x00; 458 | const uint64_t addr = strtoull(tk2, NULL, 16); 459 | asm ("lbu %0, (%1)" : "+r"(data) : "r"(addr)); 460 | printf("0x%08x : 0x%02x \n", (unsigned int)addr, data); 461 | } else printf("Syntax: load address \n"); 462 | 463 | // -------------------------------------------------------------------- 464 | } else if (tk1 != NULL && strcmp(tk1, "store")==0){ 465 | // -------------------------------------------------------------------- 466 | if (tk2 != NULL && tk3 != NULL){ 467 | const uint32_t data = (uint32_t)strtoul(tk3, NULL, 16); 468 | const uint64_t addr = strtoull(tk2, NULL, 16); 469 | 470 | if ( strlen(tk3) <=2 ) 471 | asm ( "sb %0, (%1)" : : "r"(data), "r"(addr)); 472 | else if ( strlen(tk3) <=4 ) 473 | asm ( "sh %0, (%1)" : : "r"(data), "r"(addr)); 474 | else 475 | asm ( "sw %0, (%1)" : : "r"(data), "r"(addr)); 476 | 477 | printf("0x%08x : 0x%02x \n", (unsigned int)addr, (unsigned int)data); 478 | } else printf("Syntax: store address data \n"); 479 | 480 | // -------------------------------------------------------------------- 481 | } else if (tk1 != NULL && strcmp(tk1, "exec")==0){ 482 | // -------------------------------------------------------------------- 483 | if (tk2 != NULL){ 484 | const uint64_t addr = strtoull(tk2, NULL, 16); 485 | asm ( "jr (%0)" : : "r"(addr)); 486 | } else printf("Syntax: exec address \n"); 487 | 488 | // -------------------------------------------------------------------- 489 | } else if (tk1 != NULL && strcmp(tk1, "send")==0){ 490 | // -------------------------------------------------------------------- 491 | if (tk2 != NULL && tk2[0]>='1' && tk2[0]<='4' && tk3 != NULL){ 492 | char msg[16]; strncpy(msg, tk3, 16); 493 | if (!ECALL_SEND( tk2[0]-'0', msg) ) 494 | printf("Error: Inbox full.\n"); 495 | } else printf("Syntax: send {1|2|3|4} message \n"); 496 | 497 | // -------------------------------------------------------------------- 498 | } else if (tk1 != NULL && strcmp(tk1, "recv")==0){ 499 | // -------------------------------------------------------------------- 500 | if (tk2 != NULL && tk2[0]>='1' && tk2[0]<='4'){ 501 | char msg[16]; 502 | if (ECALL_RECV(tk2[0]-'0', msg)) 503 | printf("msg : %.16s\n", msg); 504 | else 505 | printf("Error: Inbox empty.\n"); 506 | } else printf("Syntax: recv {1|2|3|4} \n"); 507 | 508 | // -------------------------------------------------------------------- 509 | } else if (tk1 != NULL && strcmp(tk1, "yield")==0){ 510 | // -------------------------------------------------------------------- 511 | uint64_t C1 = ECALL_CSRR_MCYCLE(); 512 | ECALL_YIELD(); 513 | uint64_t C2 = ECALL_CSRR_MCYCLE(); 514 | const int T = ((C2-C1)*1000000)/CPU_FREQ; 515 | printf( (T>0 ? "yield : elapsed time %dus \n" : "yield : n/a \n"), T); 516 | 517 | } else if (tk1 != NULL && strcmp(tk1, "stats")==0){ 518 | print_stats(); 519 | 520 | } else if (tk1 != NULL && strcmp(tk1, "restart")==0){ 521 | asm ("j _start"); 522 | 523 | } else if (tk1 != NULL && strcmp(tk1, "timer")==0){ 524 | if (tk2 != NULL){ 525 | const uint64_t ms = abs(strtoull(tk2, NULL, 10)); 526 | const uint64_t T0 = ECALL_CSRR_MTIME(); 527 | const uint64_t T1 = T0 + ms*RTC_FREQ/1000; 528 | ECALL_CSRW_MTIMECMP(T1); 529 | printf("timer set T0=%lu, T1=%lu \n", (unsigned long)(T0*1000/RTC_FREQ), 530 | (unsigned long)(T1*1000/RTC_FREQ) ); 531 | } else printf("Syntax: timer ms \n"); 532 | 533 | } else if (tk1 != NULL && strcmp(tk1, "pmp")==0){ 534 | print_pmp(); 535 | 536 | } else 537 | printf("Commands: load store exec send recv yield pmp stats timer restart \n"); 538 | 539 | } 540 | 541 | } 542 | --------------------------------------------------------------------------------