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/mgmt-cli.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 projects/hsm/mgmt-cli.c (limited to 'projects/hsm/mgmt-cli.c') 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; +} -- cgit v1.2.3