diff options
Diffstat (limited to 'projects')
-rw-r--r-- | projects/bootloader/Makefile | 4 | ||||
-rw-r--r-- | projects/bootloader/stm32f4xx_it.c | 220 | ||||
-rw-r--r-- | projects/cli-test/Makefile | 25 | ||||
-rw-r--r-- | projects/cli-test/cli-test.c | 1 | ||||
-rw-r--r-- | projects/hsm/Makefile | 33 | ||||
-rw-r--r-- | projects/hsm/crc32.c | 62 | ||||
-rw-r--r-- | projects/hsm/hsm.c (renamed from projects/hsm/main.c) | 166 | ||||
-rw-r--r-- | projects/hsm/mgmt-cli.c | 214 | ||||
-rw-r--r-- | projects/hsm/mgmt-cli.h | 80 | ||||
-rw-r--r-- | projects/hsm/mgmt-dfu.c | 123 | ||||
-rw-r--r-- | projects/hsm/mgmt-dfu.h | 48 | ||||
-rw-r--r-- | projects/hsm/mgmt-fpga.c | 136 | ||||
-rw-r--r-- | projects/hsm/mgmt-fpga.h | 50 | ||||
-rw-r--r-- | projects/hsm/mgmt-misc.c | 138 | ||||
-rw-r--r-- | projects/hsm/mgmt-misc.h | 49 | ||||
-rw-r--r-- | projects/hsm/mgmt-show.c | 133 | ||||
-rw-r--r-- | projects/hsm/mgmt-show.h | 43 | ||||
-rw-r--r-- | projects/rtos-test/Makefile | 4 |
18 files changed, 1230 insertions, 299 deletions
diff --git a/projects/bootloader/Makefile b/projects/bootloader/Makefile index fe75849..a63d29c 100644 --- a/projects/bootloader/Makefile +++ b/projects/bootloader/Makefile @@ -10,9 +10,7 @@ BOARD_OBJS = \ $(BOARD_DIR)/system_stm32f4xx.o \ $(BOARD_DIR)/stm32f4xx_hal_msp.o \ ./startup_stm32f429xx.o \ - ./stm32f4xx_it.o - -LIBS = $(MBED_DIR)/libstmf4.a + $(BOARD_DIR)/stm32f4xx_it.o all: $(PROG:=.elf) diff --git a/projects/bootloader/stm32f4xx_it.c b/projects/bootloader/stm32f4xx_it.c deleted file mode 100644 index 7aed16b..0000000 --- a/projects/bootloader/stm32f4xx_it.c +++ /dev/null @@ -1,220 +0,0 @@ -/** -****************************************************************************** -* @file GPIO/GPIO_IOToggle/Src/stm32f4xx_it.c -* @author MCD Application Team -* @version V1.0.1 -* @date 26-February-2014 -* @brief Main Interrupt Service Routines. -* This file provides template for all exceptions handler and -* peripherals interrupt service routine. -****************************************************************************** -* @attention -* -* <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2> -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* 1. Redistributions of source code must retain the above copyright notice, -* this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* 3. Neither the name of STMicroelectronics nor the names of its contributors -* may be used to endorse or promote products derived from this software -* without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -*/ - -#include "stm-init.h" -#include "stm-uart.h" - -/******************************************************************************/ -/* Cortex-M4 Processor Exceptions Handlers */ -/******************************************************************************/ - -/* - * We define these to make debugging easier, because otherwise gdb reports - * HardFault_Handler as WWDG_IRQHandler. - */ - -/** - * @brief This function handles NMI exception. - * @param None - * @retval None - */ -void NMI_Handler(void) -{ -} - -/** - * @brief This function handles Hard Fault exception. - * @param None - * @retval None - */ -void HardFault_Handler(void) -{ - /* Go to infinite loop when Hard Fault exception occurs */ - while (1) { ; } -} - -/** - * @brief This function handles Memory Manage exception. - * @param None - * @retval None - */ -void MemManage_Handler(void) -{ - /* Go to infinite loop when Memory Manage exception occurs */ - while (1) { ; } -} - -/** - * @brief This function handles Bus Fault exception. - * @param None - * @retval None - */ -void BusFault_Handler(void) -{ - /* Go to infinite loop when Bus Fault exception occurs */ - while (1) { ; } -} - -/** - * @brief This function handles Usage Fault exception. - * @param None - * @retval None - */ -void UsageFault_Handler(void) -{ - /* Go to infinite loop when Usage Fault exception occurs */ - while (1) { ; } -} - - -/** - * @brief This function handles SVCall exception. - * @param None - * @retval None - */ -void SVC_Handler(void) -{ -} - -/** - * @brief This function handles Debug Monitor exception. - * @param None - * @retval None - */ -void DebugMon_Handler(void) -{ -} - -/** - * @brief This function handles PendSVC exception. - * @param None - * @retval None - */ -void PendSV_Handler(void) -{ -} - -/** - * @brief This function handles SysTick Handler. - * @param None - * @retval None - */ -void SysTick_Handler(void) -{ - HAL_IncTick(); -} - -/******************************************************************************/ -/* STM32F4xx Peripherals Interrupt Handlers */ -/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ -/* available peripheral interrupt handler's name please refer to the startup */ -/* file (startup_stm32f4xx.s). */ -/******************************************************************************/ - -/** -* @brief This function handles DMA1 stream5 global interrupt. -*/ -void DMA1_Stream5_IRQHandler(void) -{ - HAL_DMA_IRQHandler(&hdma_usart_user_rx); -} - -/** -* @brief This function handles DMA2 stream2 global interrupt. -*/ -void DMA2_Stream2_IRQHandler(void) -{ - HAL_DMA_IRQHandler(&hdma_usart_mgmt_rx); -} - -/** - * @brief This function handles UART interrupt request. - * @param None - * @retval None - * @Note HAL_UART_IRQHandler will call HAL_UART_RxCpltCallback in main.c. - */ -void USART1_IRQHandler(void) -{ - HAL_UART_IRQHandler(&huart_mgmt); -} - -/** - * @brief This function handles UART interrupt request. - * @param None - * @retval None - * @Note HAL_UART_IRQHandler will call HAL_UART_RxCpltCallback in main.c. - */ -void USART2_IRQHandler(void) -{ - HAL_UART_IRQHandler(&huart_user); -} - -void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) -{ - extern void HAL_UART1_RxCpltCallback(UART_HandleTypeDef *huart); - extern void HAL_UART2_RxCpltCallback(UART_HandleTypeDef *huart); - - if (huart->Instance == USART1) - HAL_UART1_RxCpltCallback(huart); - - else if (huart->Instance == USART2) - HAL_UART2_RxCpltCallback(huart); -} - -/** - * @brief Rx Transfer completed callbacks. - * @param huart: pointer to a UART_HandleTypeDef structure that contains - * the configuration information for the specified UART module. - * @retval None - */ -__weak void HAL_UART1_RxCpltCallback(UART_HandleTypeDef *huart) -{ - /* NOTE: This function Should not be modified, when the callback is needed, - the HAL_UART_TxCpltCallback could be implemented in the user file - */ -} - -__weak void HAL_UART2_RxCpltCallback(UART_HandleTypeDef *huart) -{ - /* NOTE: This function Should not be modified, when the callback is needed, - the HAL_UART_TxCpltCallback could be implemented in the user file - */ -} - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/projects/cli-test/Makefile b/projects/cli-test/Makefile index cc1a281..e043566 100644 --- a/projects/cli-test/Makefile +++ b/projects/cli-test/Makefile @@ -1,10 +1,27 @@ TEST = cli-test -OBJS = crc32.o test_sdram.o mgmt-cli.o mgmt-dfu.c mgmt-fpga.c mgmt-misc.c mgmt-show.c mgmt-test.c mgmt-keystore.c +OBJS = crc32.o test_sdram.o mgmt-cli.o mgmt-dfu.c mgmt-fpga.c mgmt-misc.c mgmt-show.c mgmt-test.c -CFLAGS += -I$(LIBCLI_DIR) -I$(LIBHAL_DIR) -LIBS += $(LIBCLI_DIR)/libcli.a -LIBS += $(LIBHAL_DIR)/libhal.a +BOARD_OBJS = \ + $(TOPLEVEL)/stm-init.o \ + $(TOPLEVEL)/stm-fmc.o \ + $(TOPLEVEL)/stm-uart.o \ + $(TOPLEVEL)/syscalls.o \ + $(TOPLEVEL)/stm-rtc.o \ + $(TOPLEVEL)/spiflash_n25q128.o \ + $(TOPLEVEL)/stm-fpgacfg.o \ + $(TOPLEVEL)/stm-keystore.o \ + $(TOPLEVEL)/stm-sdram.o \ + $(TOPLEVEL)/stm-flash.o \ + $(BOARD_DIR)/TOOLCHAIN_GCC_ARM/startup_stm32f429xx_rtos.o \ + $(BOARD_DIR)/system_stm32f4xx.o \ + $(BOARD_DIR)/stm32f4xx_hal_msp.o \ + $(BOARD_DIR)/stm32f4xx_it_rtos.o + +CFLAGS += -I$(LIBCLI_DIR) +CFLAGS += -I$(RTOS_DIR)/rtos -I$(RTOS_DIR)/rtx/TARGET_CORTEX_M + +LIBS += $(LIBCLI_DIR)/libcli.a $(RTOS_DIR)/librtos.a all: $(TEST:=.elf) diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c index a387751..10b31a4 100644 --- a/projects/cli-test/cli-test.c +++ b/projects/cli-test/cli-test.c @@ -43,6 +43,7 @@ #include "mgmt-keystore.h" #include <string.h> +#include <strings.h> /* MGMT UART interrupt receive buffer (data will be put in a larger ring buffer) */ diff --git a/projects/hsm/Makefile b/projects/hsm/Makefile index f5546d8..55e021f 100644 --- a/projects/hsm/Makefile +++ b/projects/hsm/Makefile @@ -1,19 +1,38 @@ PROJ = hsm -SRCS = main.c +# objs in addition to $(PROJ).o +OBJS = crc32.o mgmt-cli.o mgmt-dfu.c mgmt-fpga.c mgmt-misc.c mgmt-show.c -OBJS = $(SRCS:.c=.o) +BOARD_OBJS = \ + $(TOPLEVEL)/stm-init.o \ + $(TOPLEVEL)/stm-fmc.o \ + $(TOPLEVEL)/stm-uart.o \ + $(TOPLEVEL)/syscalls.o \ + $(TOPLEVEL)/stm-rtc.o \ + $(TOPLEVEL)/spiflash_n25q128.o \ + $(TOPLEVEL)/stm-fpgacfg.o \ + $(TOPLEVEL)/stm-keystore.o \ + $(TOPLEVEL)/stm-sdram.o \ + $(TOPLEVEL)/stm-flash.o \ + $(BOARD_DIR)/TOOLCHAIN_GCC_ARM/startup_stm32f429xx_rtos.o \ + $(BOARD_DIR)/system_stm32f4xx.o \ + $(BOARD_DIR)/stm32f4xx_hal_msp.o \ + $(BOARD_DIR)/stm32f4xx_it_rtos.o -CFLAGS += -I $(LIBHAL_DIR) +CFLAGS += -I$(LIBHAL_DIR) +CFLAGS += -I$(LIBCLI_DIR) +CFLAGS += -I$(RTOS_DIR)/rtos -I$(RTOS_DIR)/rtx/TARGET_CORTEX_M LIBS += $(LIBHAL_DIR)/libhal.a $(LIBTFM_DIR)/libtfm.a +LIBS += $(RTOS_DIR)/librtos.a +LIBS += $(LIBCLI_DIR)/libcli.a all: $(PROJ:=.elf) -$(PROJ).elf: $(OBJS) $(BOARD_OBJS) $(LIBS) - $(CC) $(CFLAGS) $^ -o $@ -T$(LDSCRIPT) -g -Wl,-Map=$(PROJ).map - $(OBJCOPY) -O binary $(PROJ).elf $(PROJ).bin - $(SIZE) $(PROJ).elf +%.elf: %.o $(BOARD_OBJS) $(OBJS) $(LIBS) + $(CC) $(CFLAGS) $^ -o $@ -T$(LDSCRIPT) -g -Wl,-Map=$*.map + $(OBJCOPY) -O binary $*.elf $*.bin + $(SIZE) $*.elf clean: rm -f *.o diff --git a/projects/hsm/crc32.c b/projects/hsm/crc32.c new file mode 100644 index 0000000..4d1a0bc --- /dev/null +++ b/projects/hsm/crc32.c @@ -0,0 +1,62 @@ +/* Reference code from RFC1952. Not meant to be used outside test code. */ + +#include "stm32f4xx_hal.h" + + +/* Table of CRCs of all 8-bit messages. */ +unsigned long crc_table[256]; + +/* Flag: has the table been computed? Initially false. */ +int crc_table_computed = 0; + +/* Make the table for a fast CRC. */ +void make_crc_table(void) +{ + unsigned long c; + + int n, k; + for (n = 0; n < 256; n++) { + c = (unsigned long) n; + for (k = 0; k < 8; k++) { + if (c & 1) { + c = 0xedb88320L ^ (c >> 1); + } else { + c = c >> 1; + } + } + crc_table[n] = c; + } + crc_table_computed = 1; +} + +/* + Update a running crc with the bytes buf[0..len-1] and return + the updated crc. The crc should be initialized to zero. Pre- and + post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the caller. Usage example: + + unsigned long crc = 0L; + + while (read_buffer(buffer, length) != EOF) { + crc = update_crc(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ +uint32_t update_crc(uint32_t crc, uint8_t *buf, int len) +{ + unsigned long c = crc ^ 0xffffffffL; + int n; + + if (!crc_table_computed) + make_crc_table(); + for (n = 0; n < len; n++) { + c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); + } + return c ^ 0xffffffffL; +} + +/* Return the CRC of the bytes buf[0..len-1]. */ +unsigned long crc(unsigned char *buf, int len) +{ + return update_crc(0L, buf, len); +} diff --git a/projects/hsm/main.c b/projects/hsm/hsm.c index 79c567b..5758f05 100644 --- a/projects/hsm/main.c +++ b/projects/hsm/hsm.c @@ -53,6 +53,9 @@ #include "stm-led.h" #include "stm-fmc.h" #include "stm-uart.h" +#include "stm-sdram.h" + +#include "mgmt-cli.h" /* stm32f4xx_hal_def.h and hal.h both define HAL_OK as an enum value */ #define HAL_OK HAL_OKAY @@ -65,11 +68,18 @@ /* RPC buffers. For each active RPC, there will be two - input and output. */ -#ifndef NUM_RPC_BUFFER +#ifndef NUM_RPC_TASK /* An arbitrary number, but we don't expect to have more than 8 concurrent * RPC requests. */ -#define NUM_RPC_BUFFER 16 +#define NUM_RPC_TASK 8 +#endif + +#ifndef TASK_STACK_SIZE +/* Define an absurdly large task stack, because some pkey operation use a + * lot of stack variables. + */ +#define TASK_STACK_SIZE 200*1024 #endif #ifndef MAX_PKT_SIZE @@ -87,69 +97,34 @@ typedef struct { uint8_t buf[MAX_PKT_SIZE]; } rpc_buffer_t; -osPoolDef(rpc_buffer_pool, NUM_RPC_BUFFER, rpc_buffer_t); -osPoolId rpc_buffer_pool; - -static rpc_buffer_t *rpc_buffer_alloc(void) -{ - return (rpc_buffer_t *)osPoolCAlloc(rpc_buffer_pool); -} - /* A mutex to arbitrate concurrent UART transmits, from RPC responses. */ osMutexId uart_mutex; osMutexDef(uart_mutex); -/* Thread entry point for the RPC request handler. +/* A mutex so only one dispatch thread can receive requests. */ -static void dispatch_thread(void const *args) -{ - rpc_buffer_t *ibuf = (rpc_buffer_t *)args; - rpc_buffer_t *obuf = rpc_buffer_alloc(); - if (obuf == NULL) { - uint8_t buf[8]; - uint8_t * bufptr = &buf[4]; - const uint8_t * const limit = buf + sizeof(buf); - memcpy(buf, ibuf->buf, 4); - hal_xdr_encode_int(&bufptr, limit, HAL_ERROR_ALLOCATION_FAILURE); - osMutexWait(uart_mutex, osWaitForever); - hal_rpc_sendto(ibuf->buf, sizeof(buf), NULL); - osMutexRelease(uart_mutex); - osPoolFree(rpc_buffer_pool, ibuf); - Error_Handler(); - } - /* copy client ID from request to response */ - memcpy(obuf->buf, ibuf->buf, 4); - obuf->len = sizeof(obuf->buf) - 4; - hal_rpc_server_dispatch(ibuf->buf + 4, ibuf->len - 4, obuf->buf + 4, &obuf->len); - osPoolFree(rpc_buffer_pool, ibuf); - osMutexWait(uart_mutex, osWaitForever); - hal_error_t ret = hal_rpc_sendto(obuf->buf, obuf->len + 4, NULL); - osMutexRelease(uart_mutex); - osPoolFree(rpc_buffer_pool, obuf); - if (ret != HAL_OK) - Error_Handler(); -} -osThreadDef(dispatch_thread, osPriorityNormal, DEFAULT_STACK_SIZE); +osMutexId dispatch_mutex; +osMutexDef(dispatch_mutex); -/* Semaphore to inform the main thread that there's a new RPC request. +/* Semaphore to inform the dispatch thread that there's a new RPC request. */ -osSemaphoreId rpc_sem; +osSemaphoreId rpc_sem; osSemaphoreDef(rpc_sem); -static uint8_t c; /* current character received from UART */ -static rpc_buffer_t *ibuf; /* current RPC input buffer */ +static volatile uint8_t uart_rx; /* current character received from UART */ +static rpc_buffer_t * volatile rbuf; /* current RPC input buffer */ /* Callback for HAL_UART_Receive_IT(). */ void HAL_UART2_RxCpltCallback(UART_HandleTypeDef *huart) { int complete; - hal_slip_recv_char(ibuf->buf, &ibuf->len, sizeof(ibuf->buf), &complete); + hal_slip_recv_char(rbuf->buf, &rbuf->len, sizeof(rbuf->buf), &complete); if (complete) osSemaphoreRelease(rpc_sem); - HAL_UART_Receive_IT(huart, &c, 1); + HAL_UART_Receive_IT(huart, (uint8_t *)&uart_rx, 1); } hal_error_t hal_serial_send_char(uint8_t c) @@ -160,12 +135,73 @@ hal_error_t hal_serial_send_char(uint8_t c) hal_error_t hal_serial_recv_char(uint8_t *cp) { /* return the character from HAL_UART_Receive_IT */ - *cp = c; + *cp = uart_rx; return HAL_OK; } -/* The main thread. After the system setup, it waits for the RPC-request - * semaphore from HAL_UART_RxCpltCallback, and spawns a dispatch thread. +/* Thread entry point for the RPC request handler. + */ +static void dispatch_thread(void const *args) +{ + rpc_buffer_t ibuf, obuf; + + while (1) { + memset(&ibuf, 0, sizeof(ibuf)); + memset(&obuf, 0, sizeof(obuf)); + + /* Wait for access to the uart */ + osMutexWait(dispatch_mutex, osWaitForever); + + /* Wait for the complete rpc request */ + rbuf = &ibuf; + osSemaphoreWait(rpc_sem, osWaitForever); + + /* Let the next thread handle the next request */ + osMutexRelease(dispatch_mutex); + /* Let the next thread take the mutex */ + osThreadYield(); + + /* Copy client ID from request to response */ + memcpy(obuf.buf, ibuf.buf, 4); + obuf.len = sizeof(obuf.buf) - 4; + + /* Process the request */ + hal_rpc_server_dispatch(ibuf.buf + 4, ibuf.len - 4, obuf.buf + 4, &obuf.len); + + /* Send the response */ + osMutexWait(uart_mutex, osWaitForever); + hal_error_t ret = hal_rpc_sendto(obuf.buf, obuf.len + 4, NULL); + osMutexRelease(uart_mutex); + if (ret != HAL_OK) + Error_Handler(); + } +} +osThreadDef_t thread_def[NUM_RPC_TASK]; + +/* Allocate memory from SDRAM1. There is only malloc, no free, so we don't + * worry about fragmentation. */ +static uint8_t *sdram_malloc(size_t size) +{ + /* end of variables declared with __attribute__((section(".sdram1"))) */ + extern uint8_t _esdram1 __asm ("_esdram1"); + /* end of SDRAM1 section */ + extern uint8_t __end_sdram1 __asm ("__end_sdram1"); + + static uint8_t *sdram_heap = &_esdram1; + uint8_t *p = sdram_heap; + +#define pad(n) (((n) + 3) & ~3) + size = pad(size); + + if (p + size > &__end_sdram1) + return NULL; + + sdram_heap += size; + return p; +} + +/* The main thread. This does all the setup, and the worker threads handle + * the rest. */ int main() { @@ -183,6 +219,7 @@ int main() led_on(LED_GREEN); /* Prepare FMC interface. */ fmc_init(); + sdram_init(); /* Haaaack. probe_cores() calls malloc(), which works from the main * thread, but not from a spawned thread. It would be better to @@ -191,8 +228,8 @@ int main() */ hal_core_iterate(NULL); - rpc_buffer_pool = osPoolCreate(osPool(rpc_buffer_pool)); uart_mutex = osMutexCreate(osMutex(uart_mutex)); + dispatch_mutex = osMutexCreate(osMutex(dispatch_mutex)); rpc_sem = osSemaphoreCreate(osSemaphore(rpc_sem), 0); #ifdef TARGET_CRYPTECH_ALPHA @@ -205,22 +242,21 @@ int main() if (hal_rpc_server_init() != HAL_OK) Error_Handler(); - ibuf = rpc_buffer_alloc(); - if (ibuf == NULL) - /* Something is badly wrong. */ - Error_Handler(); + /* Create the rpc dispatch threads */ + for (int i = 0; i < NUM_RPC_TASK; ++i) { + osThreadDef_t *ot = &thread_def[i]; + ot->pthread = dispatch_thread; + ot->tpriority = osPriorityNormal; + ot->stacksize = TASK_STACK_SIZE; + ot->stack_pointer = (uint32_t *)(sdram_malloc(TASK_STACK_SIZE)); + if (ot->stack_pointer == NULL) + Error_Handler(); + if (osThreadCreate(ot, (void *)i) == NULL) + Error_Handler(); + } /* Start the non-blocking receive */ - HAL_UART_Receive_IT(&huart_user, &c, 1); + HAL_UART_Receive_IT(&huart_user, (uint8_t *)&uart_rx, 1); - while (1) { - osSemaphoreWait(rpc_sem, osWaitForever); - if (osThreadCreate(osThread(dispatch_thread), (void *)ibuf) == NULL) - Error_Handler(); - while ((ibuf = rpc_buffer_alloc()) == NULL); - /* XXX There's a potential race condition, where another request - * could write into the old ibuf, or into the null pointer if - * we're out of ibufs. - */ - } + return cli_main(); } diff --git a/projects/hsm/mgmt-cli.c b/projects/hsm/mgmt-cli.c new file mode 100644 index 0000000..bef530e --- /dev/null +++ b/projects/hsm/mgmt-cli.c @@ -0,0 +1,214 @@ +/* + * mgmt-cli.c + * --------- + * Management CLI code. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> + +#include "stm-init.h" +#include "stm-uart.h" +#include "stm-led.h" + +#include "mgmt-cli.h" +#include "mgmt-dfu.h" +#include "mgmt-fpga.h" +#include "mgmt-misc.h" +#include "mgmt-show.h" + +/* MGMT UART interrupt receive buffer (data will be put in a larger ring buffer) */ +volatile uint8_t uart_rx; + +#ifndef CLI_UART_RECVBUF_SIZE +#define CLI_UART_RECVBUF_SIZE 256 /* This must be a power of 2 */ +#endif +#define CLI_UART_RECVBUF_MASK (CLI_UART_RECVBUF_SIZE - 1) + +typedef struct { + uint32_t enabled, ridx; + mgmt_cli_dma_state_t rx_state; + uint8_t buf[CLI_UART_RECVBUF_SIZE]; +} uart_ringbuf_t; + +volatile uart_ringbuf_t uart_ringbuf = {1, 0, DMA_RX_STOP, {0}}; + +#define RINGBUF_RIDX(rb) (rb.ridx & CLI_UART_RECVBUF_MASK) +#define RINGBUF_WIDX(rb) (sizeof(rb.buf) - __HAL_DMA_GET_COUNTER(huart_mgmt.hdmarx)) +#define RINGBUF_COUNT(rb) ((unsigned)(RINGBUF_WIDX(rb) - RINGBUF_RIDX(rb))) +#define RINGBUF_READ(rb, dst) {dst = rb.buf[RINGBUF_RIDX(rb)]; rb.buf[RINGBUF_RIDX(rb)] = '.'; rb.ridx++;} + +static void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *buf) +{ + char crlf[] = "\r\n"; + uart_send_string2(STM_UART_MGMT, buf); + uart_send_string2(STM_UART_MGMT, crlf); +} + +static int uart_cli_read(struct cli_def *cli __attribute__ ((unused)), void *buf, size_t count) +{ + uint32_t timeout = 0xffffff; + while (count && timeout) { + if (RINGBUF_COUNT(uart_ringbuf)) { + RINGBUF_READ(uart_ringbuf, *(uint8_t *) buf); + buf++; + count--; + } + timeout--; + } + if (! timeout) return 0; + + return 1; +} + +static int uart_cli_write(struct cli_def *cli __attribute__ ((unused)), const void *buf, size_t count) +{ + uart_send_bytes(STM_UART_MGMT, (uint8_t *) buf, count); + return (int) count; +} + +int control_mgmt_uart_dma_rx(mgmt_cli_dma_state_t state) +{ + if (state == DMA_RX_START) { + if (uart_ringbuf.rx_state != DMA_RX_START) { + memset((void *) uart_ringbuf.buf, 0, sizeof(uart_ringbuf.buf)); + + /* Start receiving data from the UART using DMA */ + HAL_UART_Receive_DMA(&huart_mgmt, (uint8_t *) uart_ringbuf.buf, sizeof(uart_ringbuf.buf)); + uart_ringbuf.ridx = 0; + uart_ringbuf.rx_state = DMA_RX_START; + } + return 1; + } else if (state == DMA_RX_STOP) { + if (HAL_UART_DMAStop(&huart_mgmt) != HAL_OK) return 0; + uart_ringbuf.rx_state = DMA_RX_STOP; + return 1; + } + return 0; +} + +static int embedded_cli_loop(struct cli_def *cli) +{ + unsigned char c; + int n = 0; + static struct cli_loop_ctx ctx; + + memset(&ctx, 0, sizeof(ctx)); + ctx.insertmode = 1; + + cli->state = CLI_STATE_LOGIN; + + /* start off in unprivileged mode */ + cli_set_privilege(cli, PRIVILEGE_UNPRIVILEGED); + cli_set_configmode(cli, MODE_EXEC, NULL); + + cli_error(cli, "%s", cli->banner); + + while (1) { + cli_loop_start_new_command(cli, &ctx); + + control_mgmt_uart_dma_rx(DMA_RX_START); + + while (1) { + cli_loop_show_prompt(cli, &ctx); + + n = cli_loop_read_next_char(cli, &ctx, &c); + + /* + cli_print(cli, "Next char: '%c'/%i, ringbuf ridx %i, widx %i", + c, (int) c, + uart_ringbuf.ridx, + RINGBUF_WIDX(uart_ringbuf) + */ + if (n == CLI_LOOP_CTRL_BREAK) + break; + if (n == CLI_LOOP_CTRL_CONTINUE) + continue; + + n = cli_loop_process_char(cli, &ctx, c); + if (n == CLI_LOOP_CTRL_BREAK) + break; + if (n == CLI_LOOP_CTRL_CONTINUE) + continue; + } + + if (ctx.l < 0) + continue; + + /* cli_print(cli, "Process command: '%s'", ctx.cmd); */ + n = cli_loop_process_cmd(cli, &ctx); + if (n == CLI_LOOP_CTRL_BREAK) + break; + } + + return CLI_OK; +} + +static void mgmt_cli_init(struct cli_def *cli) +{ + cli_init(cli); + cli_read_callback(cli, uart_cli_read); + cli_write_callback(cli, uart_cli_write); + cli_print_callback(cli, uart_cli_print); + cli_set_banner(cli, "Cryptech Alpha"); + cli_set_hostname(cli, "cryptech"); + cli_telnet_protocol(cli, 0); +} + +static int check_auth(const char *username, const char *password) +{ + if (strcasecmp(username, "ct") != 0) + return CLI_ERROR; + if (strcasecmp(password, "ct") != 0) + return CLI_ERROR; + return CLI_OK; +} + +int cli_main(void) +{ + static struct cli_def cli; + + mgmt_cli_init(&cli); + cli_set_auth_callback(&cli, check_auth); + + configure_cli_show(&cli); + configure_cli_fpga(&cli); + configure_cli_misc(&cli); + configure_cli_dfu(&cli); + + while (1) { + embedded_cli_loop(&cli); + /* embedded_cli_loop returns when the user enters 'quit' or 'exit' */ + cli_print(&cli, "\nLogging out...\n"); + } + + /*NOTREACHED*/ + return -1; +} diff --git a/projects/hsm/mgmt-cli.h b/projects/hsm/mgmt-cli.h new file mode 100644 index 0000000..c96dae6 --- /dev/null +++ b/projects/hsm/mgmt-cli.h @@ -0,0 +1,80 @@ +/* + * mgmt-cli.h + * --------- + * Management CLI code. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __STM32_MGMT_CLI_H +#define __STM32_MGMT_CLI_H + +#include "stm-init.h" +#include <libcli.h> + + +/* A bunch of defines to make it easier to add/maintain the CLI commands. + * + */ +#define _cli_cmd_struct(name, fullname, func, help) \ + static struct cli_command cmd_##fullname##_s = \ + {(char *) #name, func, 0, help, \ + PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL} + +/* ROOT is a top-level label with no command */ +#define cli_command_root(name) \ + _cli_cmd_struct(name, name, NULL, NULL); \ + cli_register_command2(cli, &cmd_##name##_s, NULL) + +/* BRANCH is a label with a parent, but no command */ +#define cli_command_branch(parent, name) \ + _cli_cmd_struct(name, parent##_##name, NULL, NULL); \ + cli_register_command2(cli, &cmd_##parent##_##name##_s, &cmd_##parent##_s) + +/* NODE is a label with a parent and with a command associated with it */ +#define cli_command_node(parent, name, help) \ + _cli_cmd_struct(name, parent##_##name, cmd_##parent##_##name, (char *) help); \ + cli_register_command2(cli, &cmd_##parent##_##name##_s, &cmd_##parent##_s) + +/* ROOT NODE is a label without a parent, but with a command associated with it */ +#define cli_command_root_node(name, help) \ + _cli_cmd_struct(name, name, cmd_##name, (char *) help); \ + cli_register_command2(cli, &cmd_##name##_s, NULL) + + +typedef enum { + DMA_RX_STOP, + DMA_RX_START, +} mgmt_cli_dma_state_t; + +extern int control_mgmt_uart_dma_rx(mgmt_cli_dma_state_t state); + +extern int cli_main(void); + +#endif /* __STM32_MGMT_CLI_H */ diff --git a/projects/hsm/mgmt-dfu.c b/projects/hsm/mgmt-dfu.c new file mode 100644 index 0000000..e57c521 --- /dev/null +++ b/projects/hsm/mgmt-dfu.c @@ -0,0 +1,123 @@ +/* + * mgmt-dfu.c + * --------- + * CLI code for looking at, jumping to or erasing the loaded firmware. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stm-init.h" +#include "mgmt-cli.h" +#include "stm-uart.h" +#include "stm-flash.h" +#include "mgmt-dfu.h" + +#include <string.h> + +#define DFU_FIRMWARE_ADDR ((uint32_t) &CRYPTECH_FIRMWARE_START) +#define DFU_FIRMWARE_END_ADDR ((uint32_t) &CRYPTECH_FIRMWARE_END) +#define DFU_UPLOAD_CHUNK_SIZE 256 +#define HARDWARE_EARLY_DFU_JUMP 0xBADABADA + +extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len); + +/* Linker symbols are strange in C. Make regular pointers for sanity. */ +__IO uint32_t *dfu_control = &CRYPTECH_DFU_CONTROL; +__IO uint32_t *dfu_firmware = &CRYPTECH_FIRMWARE_START; +__IO uint32_t *dfu_firmware_end = &CRYPTECH_FIRMWARE_END; +/* The first word in the firmware is an address to the stack (msp) */ +__IO uint32_t *dfu_msp_ptr = &CRYPTECH_FIRMWARE_START; +/* The second word in the firmware is a pointer to the code + * (points at the Reset_Handler from the linker script). + */ +__IO uint32_t *dfu_code_ptr = &CRYPTECH_FIRMWARE_START + 1; + +static int cmd_dfu_dump(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + cli_print(cli, "First 256 bytes from DFU application address %p:\r\n", dfu_firmware); + + uart_send_hexdump(STM_UART_MGMT, (uint8_t *) dfu_firmware, 0, 0xff); + uart_send_string2(STM_UART_MGMT, (char *) "\r\n\r\n"); + + return CLI_OK; +} + +static int cmd_dfu_erase(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + int status; + + cli_print(cli, "Erasing flash sectors %i to %i (address %p to %p) - expect the CLI to crash now", + stm_flash_sector_num((uint32_t) dfu_firmware), + stm_flash_sector_num((uint32_t) dfu_firmware_end), + dfu_firmware, + dfu_firmware_end); + + if ((status = stm_flash_erase_sectors((uint32_t) dfu_firmware, (uint32_t) dfu_firmware_end)) != 0) { + cli_print(cli, "Failed erasing flash sectors (%i)", status); + } + + return CLI_OK; +} + +static int cmd_dfu_jump(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + uint32_t i; + /* Load first byte from the DFU_FIRMWARE_PTR to verify it contains an IVT before + * jumping there. + */ + cli_print(cli, "Checking for application at %p", dfu_firmware); + + i = *dfu_msp_ptr & 0xFF000000; + /* 'new_msp' is supposed to be a pointer to the new applications stack, it should + * point either at RAM (0x20000000) or at the CCM memory (0x10000000). + */ + if (i == 0x20000000 || i == 0x10000000) { + /* Set dfu_control to the magic value that will cause the us to jump to the + * firmware from the CLI main() function after rebooting. + */ + *dfu_control = HARDWARE_EARLY_DFU_JUMP; + cli_print(cli, "Making the leap"); + HAL_NVIC_SystemReset(); + while (1) { ; } + } else { + cli_print(cli, "No loaded application found at %p (read 0x%x)", + dfu_firmware, (unsigned int) *dfu_msp_ptr); + } + + return CLI_OK; +} + +void configure_cli_dfu(struct cli_def *cli) +{ + cli_command_root(dfu); + + cli_command_node(dfu, dump, "Show the first 256 bytes of the loaded firmware"); + cli_command_node(dfu, jump, "Jump to the loaded firmware"); + cli_command_node(dfu, erase, "Erase the firmware memory (will crash the CLI)"); +} diff --git a/projects/hsm/mgmt-dfu.h b/projects/hsm/mgmt-dfu.h new file mode 100644 index 0000000..047e30a --- /dev/null +++ b/projects/hsm/mgmt-dfu.h @@ -0,0 +1,48 @@ +/* + * mgmt-dfu.h + * --------- + * Management CLI Device Firmware Upgrade code. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __STM32_CLI_MGMT_DFU_H +#define __STM32_CLI_MGMT_DFU_H + +#include "stm-init.h" +#include <libcli.h> + +/* symbols defined in the linker script (STM32F429BI.ld) */ +extern uint32_t CRYPTECH_FIRMWARE_START; +extern uint32_t CRYPTECH_FIRMWARE_END; +extern uint32_t CRYPTECH_DFU_CONTROL; + +extern void configure_cli_dfu(struct cli_def *cli); + +#endif /* __STM32_CLI_MGMT_DFU_H */ diff --git a/projects/hsm/mgmt-fpga.c b/projects/hsm/mgmt-fpga.c new file mode 100644 index 0000000..b6eea3d --- /dev/null +++ b/projects/hsm/mgmt-fpga.c @@ -0,0 +1,136 @@ +/* + * mgmt-fpga.c + * ----------- + * CLI code to manage the FPGA configuration etc. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stm-init.h" +#include "stm-uart.h" +#include "stm-fpgacfg.h" + +#include "mgmt-cli.h" +#include "mgmt-fpga.h" +#include "mgmt-misc.h" + +#include <string.h> + + +static volatile uint32_t dfu_offset = 0; + + +static int _flash_write_callback(uint8_t *buf, size_t len) { + int res = fpgacfg_write_data(dfu_offset, buf, BITSTREAM_UPLOAD_CHUNK_SIZE) == 1; + dfu_offset += BITSTREAM_UPLOAD_CHUNK_SIZE; + return res; +} + +static int cmd_fpga_bitstream_upload(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + uint8_t buf[BITSTREAM_UPLOAD_CHUNK_SIZE]; + + dfu_offset = 0; + + fpgacfg_access_control(ALLOW_ARM); + + cli_print(cli, "Checking if FPGA config memory is accessible"); + if (fpgacfg_check_id() != 1) { + cli_print(cli, "ERROR: FPGA config memory not accessible. Check that jumpers JP7 and JP8 are installed."); + return CLI_ERROR; + } + + cli_receive_data(cli, &buf[0], sizeof(buf), _flash_write_callback); + + fpgacfg_access_control(ALLOW_FPGA); + + cli_print(cli, "DFU offset now: %li (%li chunks)", dfu_offset, dfu_offset / BITSTREAM_UPLOAD_CHUNK_SIZE); + return CLI_OK; +} + +static int cmd_fpga_bitstream_erase(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + fpgacfg_access_control(ALLOW_ARM); + + cli_print(cli, "Checking if FPGA config memory is accessible"); + if (fpgacfg_check_id() != 1) { + cli_print(cli, "ERROR: FPGA config memory not accessible. Check that jumpers JP7 and JP8 are installed."); + return CLI_ERROR; + } + + /* Erasing the whole config memory takes a while, we just need to erase the first sector. + * The bitstream has an EOF marker, so even if the next bitstream uploaded is shorter than + * the current one there should be no problem. + * + * This command could be made to accept an argument indicating the whole memory should be erased. + */ + if (! fpgacfg_erase_sectors(1)) { + cli_print(cli, "Erasing first sector in FPGA config memory failed"); + return CLI_ERROR; + } + + cli_print(cli, "Erased FPGA config memory"); + fpgacfg_access_control(ALLOW_FPGA); + + return CLI_OK; +} + +static int cmd_fpga_reset(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + fpgacfg_access_control(ALLOW_FPGA); + fpgacfg_reset_fpga(RESET_FULL); + cli_print(cli, "FPGA has been reset"); + + return CLI_OK; +} + +static int cmd_fpga_reset_registers(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + fpgacfg_access_control(ALLOW_FPGA); + fpgacfg_reset_fpga(RESET_REGISTERS); + cli_print(cli, "FPGA registers have been reset"); + + return CLI_OK; +} + +void configure_cli_fpga(struct cli_def *cli) +{ + /* fpga */ + cli_command_root(fpga); + /* fpga reset */ + cli_command_node(fpga, reset, "Reset FPGA (config reset)"); + /* fpga reset registers */ + cli_command_node(fpga_reset, registers, "Reset FPGA registers (soft reset)"); + + cli_command_branch(fpga, bitstream); + /* fpga bitstream upload */ + cli_command_node(fpga_bitstream, upload, "Upload new FPGA bitstream"); + /* fpga bitstream erase */ + cli_command_node(fpga_bitstream, erase, "Erase FPGA config memory"); +} diff --git a/projects/hsm/mgmt-fpga.h b/projects/hsm/mgmt-fpga.h new file mode 100644 index 0000000..ce185de --- /dev/null +++ b/projects/hsm/mgmt-fpga.h @@ -0,0 +1,50 @@ +/* + * mgmt-fpga.h + * ----------- + * Management FPGA related code. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __STM32_CLI_MGMT_FPGA_H +#define __STM32_CLI_MGMT_FPGA_H + +#include "stm-init.h" +#include <libcli.h> + + +/* The chunk size have to be a multiple of the SPI flash page size (256 bytes), + and it has to match the chunk size in the program sending the bitstream over the UART. +*/ +#define BITSTREAM_UPLOAD_CHUNK_SIZE 4096 + + +extern void configure_cli_fpga(struct cli_def *cli); + +#endif /* __STM32_CLI_MGMT_FPGA_H */ diff --git a/projects/hsm/mgmt-misc.c b/projects/hsm/mgmt-misc.c new file mode 100644 index 0000000..67bc875 --- /dev/null +++ b/projects/hsm/mgmt-misc.c @@ -0,0 +1,138 @@ +/* + * mgmt-misc.c + * ----------- + * Miscellaneous CLI functions. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stm-init.h" +#include "stm-uart.h" + +#include "mgmt-cli.h" +#include "mgmt-misc.h" + +#include <string.h> + + +extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len); + + +static volatile uint32_t demo_crc = 0; + +static int _count_bytes_callback(uint8_t *buf, size_t len) { + demo_crc = update_crc(demo_crc, buf, len); + return 1; +} + +int cli_receive_data(struct cli_def *cli, uint8_t *buf, size_t len, cli_data_callback data_callback) +{ + uint32_t filesize = 0, crc = 0, my_crc = 0, counter = 0; + size_t n = len; + + if (! control_mgmt_uart_dma_rx(DMA_RX_STOP)) { + cli_print(cli, "Failed stopping DMA"); + return CLI_OK; + } + + cli_print(cli, "OK, write size (4 bytes), data in %li byte chunks, CRC-32 (4 bytes)", (uint32_t) n); + + if (uart_receive_bytes(STM_UART_MGMT, (void *) &filesize, 4, 1000) != HAL_OK) { + cli_print(cli, "Receive timed out"); + return CLI_ERROR; + } + + cli_print(cli, "Send %li bytes of data", filesize); + + while (filesize) { + /* By initializing buf to the same value that erased flash has (0xff), we don't + * have to try and be smart when writing the last page of data to a flash memory. + */ + memset(buf, 0xff, len); + + if (filesize < n) n = filesize; + + if (uart_receive_bytes(STM_UART_MGMT, (void *) buf, n, 1000) != HAL_OK) { + cli_print(cli, "Receive timed out"); + return CLI_ERROR; + } + filesize -= n; + my_crc = update_crc(my_crc, buf, n); + + /* After reception of a chunk but before ACKing we have "all" the time in the world to + * calculate CRC and invoke the data_callback. + */ + if (data_callback != NULL && ! data_callback(buf, (size_t) n)) { + cli_print(cli, "Data processing failed"); + return CLI_OK; + } + + counter++; + uart_send_bytes(STM_UART_MGMT, (void *) &counter, 4); + } + + cli_print(cli, "Send CRC-32"); + uart_receive_bytes(STM_UART_MGMT, (void *) &crc, 4, 1000); + cli_print(cli, "CRC-32 0x%x, calculated CRC 0x%x", (unsigned int) crc, (unsigned int) my_crc); + if (crc == my_crc) { + cli_print(cli, "CRC checksum MATCHED"); + } else { + cli_print(cli, "CRC checksum did NOT match"); + } + + return CLI_OK; +} + +static int cmd_filetransfer(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + uint8_t buf[FILETRANSFER_UPLOAD_CHUNK_SIZE]; + + demo_crc = 0; + cli_receive_data(cli, &buf[0], sizeof(buf), _count_bytes_callback); + cli_print(cli, "Demo CRC is: %li/0x%x", demo_crc, (unsigned int) demo_crc); + return CLI_OK; +} + +static int cmd_reboot(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + cli_print(cli, "\n\n\nRebooting\n\n\n"); + HAL_NVIC_SystemReset(); + + /*NOTREACHED*/ + return CLI_OK; +} + +void configure_cli_misc(struct cli_def *cli) +{ + /* filetransfer */ + cli_command_root_node(filetransfer, "Test file transfering"); + /* reboot */ + cli_command_root_node(reboot, "Reboot the STM32"); +} + diff --git a/projects/hsm/mgmt-misc.h b/projects/hsm/mgmt-misc.h new file mode 100644 index 0000000..b7eb4f4 --- /dev/null +++ b/projects/hsm/mgmt-misc.h @@ -0,0 +1,49 @@ +/* + * mgmt-misc.h + * ----------- + * Management CLI miscellaneous functions. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __STM32_CLI_MGMT_MISC_H +#define __STM32_CLI_MGMT_MISC_H + +#include "stm-init.h" +#include <libcli.h> + + +#define FILETRANSFER_UPLOAD_CHUNK_SIZE 256 + +typedef int (*cli_data_callback)(uint8_t *, size_t); + +extern void configure_cli_misc(struct cli_def *cli); +extern int cli_receive_data(struct cli_def *cli, uint8_t *buf, size_t len, cli_data_callback data_callback); + +#endif /* __STM32_CLI_MGMT_MISC_H */ diff --git a/projects/hsm/mgmt-show.c b/projects/hsm/mgmt-show.c new file mode 100644 index 0000000..c9eb22c --- /dev/null +++ b/projects/hsm/mgmt-show.c @@ -0,0 +1,133 @@ +/* + * mgmt-show.c + * ----------- + * CLI 'show' functions. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stm-init.h" +#include "stm-keystore.h" +#include "stm-fpgacfg.h" +#include "stm-uart.h" + +#include "mgmt-cli.h" +#include "mgmt-show.h" + +#include <string.h> + + +static int cmd_show_cpuspeed(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + volatile uint32_t hclk; + + hclk = HAL_RCC_GetHCLKFreq(); + cli_print(cli, "HSE_VALUE: %li", HSE_VALUE); + cli_print(cli, "HCLK: %li (%i MHz)", hclk, (int) hclk / 1000 / 1000); + cli_print(cli, "SystemCoreClock: %li (%i MHz)", SystemCoreClock, (int) SystemCoreClock / 1000 / 1000); + return CLI_OK; +} + +static int cmd_show_fpga_status(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + cli_print(cli, "FPGA has %sloaded a bitstream", fpgacfg_check_done() ? "":"NOT "); + return CLI_OK; +} + +static int cmd_show_keystore_status(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + cli_print(cli, "Keystore memory is %sonline", (keystore_check_id() != 1) ? "NOT ":""); + return CLI_OK; +} + +static int cmd_show_keystore_data(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + uint8_t buf[KEYSTORE_PAGE_SIZE]; + uint32_t i; + + if (keystore_check_id() != 1) { + cli_print(cli, "ERROR: The keystore memory is not accessible."); + } + + memset(buf, 0, sizeof(buf)); + if ((i = keystore_read_data(0, buf, sizeof(buf))) != 1) { + cli_print(cli, "Failed reading first page from keystore memory: %li", i); + return CLI_ERROR; + } + + cli_print(cli, "First page from keystore memory:\r\n"); + uart_send_hexdump(STM_UART_MGMT, buf, 0, sizeof(buf) - 1); + uart_send_string2(STM_UART_MGMT, (char *) "\r\n\r\n"); + + for (i = 0; i < 8; i++) { + if (buf[i] == 0xff) break; /* never written */ + if (buf[i] != 0x55) break; /* something other than a tombstone */ + } + /* As a demo, tombstone byte after byte of the first 8 bytes in the keystore memory + * (as long as they do not appear to contain real data). + * If all of them are tombstones, erase the first sector to start over. + */ + if (i < 8) { + if (buf[i] == 0xff) { + cli_print(cli, "Tombstoning byte %li", i); + buf[i] = 0x55; + if ((i = keystore_write_data(0, buf, sizeof(buf))) != 1) { + cli_print(cli, "Failed writing data at offset 0: %li", i); + return CLI_ERROR; + } + } + } else { + cli_print(cli, "Erasing first sector since all the first 8 bytes are tombstones"); + if ((i = keystore_erase_sectors(1)) != 1) { + cli_print(cli, "Failed erasing the first sector: %li", i); + return CLI_ERROR; + } + cli_print(cli, "Erase result: %li", i); + } + + return CLI_OK; +} + +void configure_cli_show(struct cli_def *cli) +{ + /* show */ + cli_command_root(show); + + /* show cpuspeed */ + cli_command_node(show, cpuspeed, "Show the speed at which the CPU currently operates"); + + cli_command_branch(show, fpga); + /* show fpga status*/ + cli_command_node(show_fpga, status, "Show status about the FPGA"); + + cli_command_branch(show, keystore); + /* show keystore status*/ + cli_command_node(show_keystore, status, "Show status of the keystore memory"); + cli_command_node(show_keystore, data, "Show the first page of the keystore memory"); +} diff --git a/projects/hsm/mgmt-show.h b/projects/hsm/mgmt-show.h new file mode 100644 index 0000000..0d7ba3a --- /dev/null +++ b/projects/hsm/mgmt-show.h @@ -0,0 +1,43 @@ +/* + * mgmt-misc.h + * ----------- + * Management CLI 'show' functions. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __STM32_CLI_MGMT_SHOW_H +#define __STM32_CLI_MGMT_SHOW_H + +#include "stm-init.h" +#include <libcli.h> + +extern void configure_cli_show(struct cli_def *cli); + +#endif /* __STM32_CLI_MGMT_SHOW_H */ diff --git a/projects/rtos-test/Makefile b/projects/rtos-test/Makefile index dd2cab5..9e58a41 100644 --- a/projects/rtos-test/Makefile +++ b/projects/rtos-test/Makefile @@ -1,5 +1,9 @@ TEST = thread-test semaphore-test mutex-test +CFLAGS += -I$(RTOS_DIR)/rtos -I$(RTOS_DIR)/rtx/TARGET_CORTEX_M + +LIBS += $(RTOS_DIR)/librtos.a + all: $(TEST:=.elf) %.elf: %.o $(BOARD_OBJS) $(LIBS) |