From e94bce23e3629e1229efe4d86660c2f5a375a1fc Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Wed, 8 Jun 2016 23:32:05 -0400 Subject: Include strings.h, for strcasecmp(). --- projects/cli-test/cli-test.c | 1 + 1 file changed, 1 insertion(+) (limited to 'projects') diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c index a52dbec..7bac84e 100644 --- a/projects/cli-test/cli-test.c +++ b/projects/cli-test/cli-test.c @@ -42,6 +42,7 @@ #include "mgmt-test.h" #include +#include /* MGMT UART interrupt receive buffer (data will be put in a larger ring buffer) */ -- cgit v1.2.3 From 5a0c56d9b4d7076ddf8ed762c22519290de3f998 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Thu, 9 Jun 2016 11:47:00 -0400 Subject: Rename main.c to hsm.c for consistency and a slightly simpler Makefile. --- projects/hsm/Makefile | 13 ++- projects/hsm/hsm.c | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++ projects/hsm/main.c | 226 -------------------------------------------------- 3 files changed, 232 insertions(+), 233 deletions(-) create mode 100644 projects/hsm/hsm.c delete mode 100644 projects/hsm/main.c (limited to 'projects') diff --git a/projects/hsm/Makefile b/projects/hsm/Makefile index f5546d8..d8fd1f9 100644 --- a/projects/hsm/Makefile +++ b/projects/hsm/Makefile @@ -1,8 +1,7 @@ PROJ = hsm -SRCS = main.c - -OBJS = $(SRCS:.c=.o) +# objs in addition to $(PROJ).o +OBJS = CFLAGS += -I $(LIBHAL_DIR) @@ -10,10 +9,10 @@ LIBS += $(LIBHAL_DIR)/libhal.a $(LIBTFM_DIR)/libtfm.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/hsm.c b/projects/hsm/hsm.c new file mode 100644 index 0000000..79c567b --- /dev/null +++ b/projects/hsm/hsm.c @@ -0,0 +1,226 @@ +/* + * rpc_server.c + * ------------ + * Remote procedure call server-side private API implementation. + * + * 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. + */ + +/* + * This is the main RPC server moddule. It creates a new thread to deal + * with each request, to prevent a long-running request (e.g. RSA keygen) + * from blocking independent requests from other clients. This has a + * number of consequences. We can't do a blocking receive in the main + * thread, because that prevents the dispatch thread from transmitting the + * response (because they both want to lock the UART - see + * stm32f4xx_hal_uart.c). So we have to do a non-blocking receive with a + * callback routine. But we can't create a thread from the callback + * routine, because it's in the context of an ISR, so we raise a semaphore + * for the main thread to create the dispatch thread. + */ + +#include + +#include "cmsis_os.h" + +#include "stm-init.h" +#include "stm-led.h" +#include "stm-fmc.h" +#include "stm-uart.h" + +/* stm32f4xx_hal_def.h and hal.h both define HAL_OK as an enum value */ +#define HAL_OK HAL_OKAY + +#include "hal.h" +#include "hal_internal.h" +#include "slip_internal.h" +#include "xdr_internal.h" + +/* RPC buffers. For each active RPC, there will be two - input and output. + */ + +#ifndef NUM_RPC_BUFFER +/* An arbitrary number, but we don't expect to have more than 8 concurrent + * RPC requests. + */ +#define NUM_RPC_BUFFER 16 +#endif + +#ifndef MAX_PKT_SIZE +/* Another arbitrary number, more or less driven by the 4096-bit RSA + * keygen test. + */ +#define MAX_PKT_SIZE 4096 +#endif + +/* The thread entry point takes a single void* argument, so we bundle the + * packet buffer and length arguments together. + */ +typedef struct { + size_t len; + 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. + */ +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); + +/* Semaphore to inform the main thread that there's a new RPC request. + */ +osSemaphoreId rpc_sem; +osSemaphoreDef(rpc_sem); + +static uint8_t c; /* current character received from UART */ +static rpc_buffer_t *ibuf; /* 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); + if (complete) + osSemaphoreRelease(rpc_sem); + + HAL_UART_Receive_IT(huart, &c, 1); +} + +hal_error_t hal_serial_send_char(uint8_t c) +{ + return (uart_send_char(c) == 0) ? HAL_OK : HAL_ERROR_RPC_TRANSPORT; +} + +hal_error_t hal_serial_recv_char(uint8_t *cp) +{ + /* return the character from HAL_UART_Receive_IT */ + *cp = c; + 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. + */ +int main() +{ + stm_init(); + +#ifdef TARGET_CRYPTECH_DEV_BRIDGE + /* Wait six seconds to not upset the Novena at boot. */ + led_on(LED_BLUE); + for (int i = 0; i < 12; i++) { + osDelay(500); + led_toggle(LED_BLUE); + } + led_off(LED_BLUE); +#endif + led_on(LED_GREEN); + /* Prepare FMC interface. */ + fmc_init(); + + /* Haaaack. probe_cores() calls malloc(), which works from the main + * thread, but not from a spawned thread. It would be better to + * rewrite it to use static memory, but for now, just force it to + * probe early. + */ + hal_core_iterate(NULL); + + rpc_buffer_pool = osPoolCreate(osPool(rpc_buffer_pool)); + uart_mutex = osMutexCreate(osMutex(uart_mutex)); + rpc_sem = osSemaphoreCreate(osSemaphore(rpc_sem), 0); + +#ifdef TARGET_CRYPTECH_ALPHA + /* Launch other threads: + * - admin thread on USART1 + * - csprng warm-up thread? + */ +#endif + + if (hal_rpc_server_init() != HAL_OK) + Error_Handler(); + + ibuf = rpc_buffer_alloc(); + if (ibuf == NULL) + /* Something is badly wrong. */ + Error_Handler(); + + /* Start the non-blocking receive */ + HAL_UART_Receive_IT(&huart_user, &c, 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. + */ + } +} diff --git a/projects/hsm/main.c b/projects/hsm/main.c deleted file mode 100644 index 79c567b..0000000 --- a/projects/hsm/main.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * rpc_server.c - * ------------ - * Remote procedure call server-side private API implementation. - * - * 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. - */ - -/* - * This is the main RPC server moddule. It creates a new thread to deal - * with each request, to prevent a long-running request (e.g. RSA keygen) - * from blocking independent requests from other clients. This has a - * number of consequences. We can't do a blocking receive in the main - * thread, because that prevents the dispatch thread from transmitting the - * response (because they both want to lock the UART - see - * stm32f4xx_hal_uart.c). So we have to do a non-blocking receive with a - * callback routine. But we can't create a thread from the callback - * routine, because it's in the context of an ISR, so we raise a semaphore - * for the main thread to create the dispatch thread. - */ - -#include - -#include "cmsis_os.h" - -#include "stm-init.h" -#include "stm-led.h" -#include "stm-fmc.h" -#include "stm-uart.h" - -/* stm32f4xx_hal_def.h and hal.h both define HAL_OK as an enum value */ -#define HAL_OK HAL_OKAY - -#include "hal.h" -#include "hal_internal.h" -#include "slip_internal.h" -#include "xdr_internal.h" - -/* RPC buffers. For each active RPC, there will be two - input and output. - */ - -#ifndef NUM_RPC_BUFFER -/* An arbitrary number, but we don't expect to have more than 8 concurrent - * RPC requests. - */ -#define NUM_RPC_BUFFER 16 -#endif - -#ifndef MAX_PKT_SIZE -/* Another arbitrary number, more or less driven by the 4096-bit RSA - * keygen test. - */ -#define MAX_PKT_SIZE 4096 -#endif - -/* The thread entry point takes a single void* argument, so we bundle the - * packet buffer and length arguments together. - */ -typedef struct { - size_t len; - 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. - */ -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); - -/* Semaphore to inform the main thread that there's a new RPC request. - */ -osSemaphoreId rpc_sem; -osSemaphoreDef(rpc_sem); - -static uint8_t c; /* current character received from UART */ -static rpc_buffer_t *ibuf; /* 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); - if (complete) - osSemaphoreRelease(rpc_sem); - - HAL_UART_Receive_IT(huart, &c, 1); -} - -hal_error_t hal_serial_send_char(uint8_t c) -{ - return (uart_send_char(c) == 0) ? HAL_OK : HAL_ERROR_RPC_TRANSPORT; -} - -hal_error_t hal_serial_recv_char(uint8_t *cp) -{ - /* return the character from HAL_UART_Receive_IT */ - *cp = c; - 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. - */ -int main() -{ - stm_init(); - -#ifdef TARGET_CRYPTECH_DEV_BRIDGE - /* Wait six seconds to not upset the Novena at boot. */ - led_on(LED_BLUE); - for (int i = 0; i < 12; i++) { - osDelay(500); - led_toggle(LED_BLUE); - } - led_off(LED_BLUE); -#endif - led_on(LED_GREEN); - /* Prepare FMC interface. */ - fmc_init(); - - /* Haaaack. probe_cores() calls malloc(), which works from the main - * thread, but not from a spawned thread. It would be better to - * rewrite it to use static memory, but for now, just force it to - * probe early. - */ - hal_core_iterate(NULL); - - rpc_buffer_pool = osPoolCreate(osPool(rpc_buffer_pool)); - uart_mutex = osMutexCreate(osMutex(uart_mutex)); - rpc_sem = osSemaphoreCreate(osSemaphore(rpc_sem), 0); - -#ifdef TARGET_CRYPTECH_ALPHA - /* Launch other threads: - * - admin thread on USART1 - * - csprng warm-up thread? - */ -#endif - - if (hal_rpc_server_init() != HAL_OK) - Error_Handler(); - - ibuf = rpc_buffer_alloc(); - if (ibuf == NULL) - /* Something is badly wrong. */ - Error_Handler(); - - /* Start the non-blocking receive */ - HAL_UART_Receive_IT(&huart_user, &c, 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. - */ - } -} -- cgit v1.2.3 From 2a14d36ebd7bde9a3a6c98871050b14b54598389 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Thu, 9 Jun 2016 18:53:31 -0400 Subject: Put thread stack buffers in SDRAM, because pkey uses a lot of stack. Also rearchitect the way we handle RPC requests - have a bunch of waiting dispatch threads rather than continually creating and deleting threads. --- projects/hsm/hsm.c | 138 +++++++++++++++++++++++++++++------------------------ 1 file changed, 76 insertions(+), 62 deletions(-) (limited to 'projects') diff --git a/projects/hsm/hsm.c b/projects/hsm/hsm.c index 79c567b..e3c1c36 100644 --- a/projects/hsm/hsm.c +++ b/projects/hsm/hsm.c @@ -53,6 +53,7 @@ #include "stm-led.h" #include "stm-fmc.h" #include "stm-uart.h" +#include "stm-sdram.h" /* stm32f4xx_hal_def.h and hal.h both define HAL_OK as an enum value */ #define HAL_OK HAL_OKAY @@ -65,13 +66,24 @@ /* 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 64*1024 +#endif + +/* Put the task stack buffers in SDRAM, because ARM RAM is too small. + */ +__attribute__((section(".sdram1"))) uint8_t stack[NUM_RPC_TASK][TASK_STACK_SIZE]; + #ifndef MAX_PKT_SIZE /* Another arbitrary number, more or less driven by the 4096-bit RSA * keygen test. @@ -87,65 +99,30 @@ 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 uint8_t c; /* 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); @@ -164,8 +141,47 @@ hal_error_t hal_serial_recv_char(uint8_t *cp) 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]; + +/* The main thread. This does all the setup, and the worker threads handle + * the rest. */ int main() { @@ -183,6 +199,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 +208,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 +222,19 @@ 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 *)stack[i]; + if (osThreadCreate(ot, (void *)i) == NULL) + Error_Handler(); + } /* Start the non-blocking receive */ HAL_UART_Receive_IT(&huart_user, &c, 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. - */ - } + while (1) { ; } } -- cgit v1.2.3 From a5850b450733141f320a817c523b85dff49f52eb Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Mon, 13 Jun 2016 15:49:09 -0400 Subject: Only the HSM project needs the RTOS; most of the test projects can use the STM32 HAL code directly. --- projects/bootloader/Makefile | 4 +- projects/bootloader/stm32f4xx_it.c | 220 ------------------------------------- projects/cli-test/Makefile | 20 +++- projects/hsm/Makefile | 21 +++- projects/rtos-test/Makefile | 4 + 5 files changed, 43 insertions(+), 226 deletions(-) delete mode 100644 projects/bootloader/stm32f4xx_it.c (limited to 'projects') 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 -* -*

© COPYRIGHT(c) 2014 STMicroelectronics

-* -* 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 acf2720..e043566 100644 --- a/projects/cli-test/Makefile +++ b/projects/cli-test/Makefile @@ -2,8 +2,26 @@ 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 +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) -LIBS += $(LIBCLI_DIR)/libcli.a +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/hsm/Makefile b/projects/hsm/Makefile index d8fd1f9..1ee5323 100644 --- a/projects/hsm/Makefile +++ b/projects/hsm/Makefile @@ -3,9 +3,26 @@ PROJ = hsm # objs in addition to $(PROJ).o OBJS = -CFLAGS += -I $(LIBHAL_DIR) +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 -LIBS += $(LIBHAL_DIR)/libhal.a $(LIBTFM_DIR)/libtfm.a +CFLAGS += -I$(LIBHAL_DIR) +CFLAGS += -I$(RTOS_DIR)/rtos -I$(RTOS_DIR)/rtx/TARGET_CORTEX_M + +LIBS += $(LIBHAL_DIR)/libhal.a $(LIBTFM_DIR)/libtfm.a $(RTOS_DIR)/librtos.a all: $(PROJ:=.elf) 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) -- cgit v1.2.3 From b7f9d44fe7a35c33bd6a5ee7db1cbd9a53e21ee2 Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Mon, 13 Jun 2016 15:55:56 -0400 Subject: RSA keygen needs even more stack space than I thought. Also, it turns out the linker wants to include initializers for sdram variables in the .elf and .bin files, even though it should handle it like bss. So now we manage sdram directly with a pseudo-malloc. --- projects/hsm/hsm.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'projects') diff --git a/projects/hsm/hsm.c b/projects/hsm/hsm.c index e3c1c36..70a7691 100644 --- a/projects/hsm/hsm.c +++ b/projects/hsm/hsm.c @@ -77,13 +77,9 @@ /* Define an absurdly large task stack, because some pkey operation use a * lot of stack variables. */ -#define TASK_STACK_SIZE 64*1024 +#define TASK_STACK_SIZE 200*1024 #endif -/* Put the task stack buffers in SDRAM, because ARM RAM is too small. - */ -__attribute__((section(".sdram1"))) uint8_t stack[NUM_RPC_TASK][TASK_STACK_SIZE]; - #ifndef MAX_PKT_SIZE /* Another arbitrary number, more or less driven by the 4096-bit RSA * keygen test. @@ -180,6 +176,28 @@ static void dispatch_thread(void const *args) } 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. */ @@ -228,7 +246,9 @@ int main() ot->pthread = dispatch_thread; ot->tpriority = osPriorityNormal; ot->stacksize = TASK_STACK_SIZE; - ot->stack_pointer = (uint32_t *)stack[i]; + 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(); } @@ -236,5 +256,5 @@ int main() /* Start the non-blocking receive */ HAL_UART_Receive_IT(&huart_user, &c, 1); - while (1) { ; } + return 0; } -- cgit v1.2.3 From 3e31061ff6cbba7ea5bcb16dd0fa55b65ebf586f Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Tue, 14 Jun 2016 12:03:15 -0400 Subject: Import cli-test into hsm pretty much as-is. --- projects/hsm/Makefile | 7 +- projects/hsm/crc32.c | 62 ++++++++++++++ projects/hsm/hsm.c | 12 +-- projects/hsm/mgmt-cli.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++ projects/hsm/mgmt-cli.h | 80 ++++++++++++++++++ projects/hsm/mgmt-dfu.c | 123 +++++++++++++++++++++++++++ projects/hsm/mgmt-dfu.h | 48 +++++++++++ projects/hsm/mgmt-fpga.c | 136 ++++++++++++++++++++++++++++++ projects/hsm/mgmt-fpga.h | 50 +++++++++++ projects/hsm/mgmt-misc.c | 138 ++++++++++++++++++++++++++++++ projects/hsm/mgmt-misc.h | 49 +++++++++++ projects/hsm/mgmt-show.c | 133 +++++++++++++++++++++++++++++ projects/hsm/mgmt-show.h | 43 ++++++++++ 13 files changed, 1088 insertions(+), 7 deletions(-) create mode 100644 projects/hsm/crc32.c create mode 100644 projects/hsm/mgmt-cli.c create mode 100644 projects/hsm/mgmt-cli.h create mode 100644 projects/hsm/mgmt-dfu.c create mode 100644 projects/hsm/mgmt-dfu.h create mode 100644 projects/hsm/mgmt-fpga.c create mode 100644 projects/hsm/mgmt-fpga.h create mode 100644 projects/hsm/mgmt-misc.c create mode 100644 projects/hsm/mgmt-misc.h create mode 100644 projects/hsm/mgmt-show.c create mode 100644 projects/hsm/mgmt-show.h (limited to 'projects') diff --git a/projects/hsm/Makefile b/projects/hsm/Makefile index 1ee5323..55e021f 100644 --- a/projects/hsm/Makefile +++ b/projects/hsm/Makefile @@ -1,7 +1,7 @@ PROJ = hsm # objs in addition to $(PROJ).o -OBJS = +OBJS = crc32.o mgmt-cli.o mgmt-dfu.c mgmt-fpga.c mgmt-misc.c mgmt-show.c BOARD_OBJS = \ $(TOPLEVEL)/stm-init.o \ @@ -20,9 +20,12 @@ BOARD_OBJS = \ $(BOARD_DIR)/stm32f4xx_it_rtos.o 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 $(RTOS_DIR)/librtos.a +LIBS += $(LIBHAL_DIR)/libhal.a $(LIBTFM_DIR)/libtfm.a +LIBS += $(RTOS_DIR)/librtos.a +LIBS += $(LIBCLI_DIR)/libcli.a all: $(PROJ:=.elf) 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/hsm.c b/projects/hsm/hsm.c index 70a7691..5758f05 100644 --- a/projects/hsm/hsm.c +++ b/projects/hsm/hsm.c @@ -55,6 +55,8 @@ #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 @@ -110,7 +112,7 @@ osMutexDef(dispatch_mutex); osSemaphoreId rpc_sem; osSemaphoreDef(rpc_sem); -static uint8_t c; /* current character received from UART */ +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(). @@ -122,7 +124,7 @@ void HAL_UART2_RxCpltCallback(UART_HandleTypeDef *huart) 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) @@ -133,7 +135,7 @@ 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; } @@ -254,7 +256,7 @@ int main() } /* Start the non-blocking receive */ - HAL_UART_Receive_IT(&huart_user, &c, 1); + HAL_UART_Receive_IT(&huart_user, (uint8_t *)&uart_rx, 1); - return 0; + 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 + +#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 + + +/* 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 + +#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 + +/* 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 + + +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 + + +/* 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 + + +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 + + +#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 + + +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 + +extern void configure_cli_show(struct cli_def *cli); + +#endif /* __STM32_CLI_MGMT_SHOW_H */ -- cgit v1.2.3