/* * novena-eim.c * ------------ * This module contains the userland magic to set up and use the EIM bus. * * * Author: Pavel Shatov * Copyright (c) 2014-2015, 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. */ //------------------------------------------------------------------------------ // Headers //------------------------------------------------------------------------------ #include #include #include #include #include #include #include #include "novena-eim.h" //------------------------------------------------------------------------------ // Defines //------------------------------------------------------------------------------ #define MEMORY_DEVICE "/dev/mem" #define IOMUXC_MUX_MODE_ALT0 0 // 000 #define IOMUXC_PAD_CTL_SRE_FAST 1 // 1 #define IOMUXC_PAD_CTL_DSE_33_OHM 7 // 111 #define IOMUXC_PAD_CTL_SPEED_MEDIUM_10 2 // 10 #define IOMUXC_PAD_CTL_ODE_DISABLED 0 // 0 #define IOMUXC_PAD_CTL_PKE_DISABLED 0 // 0 #define IOMUXC_PAD_CTL_PUE_PULL 1 // 1 #define IOMUXC_PAD_CTL_PUS_100K_OHM_PU 2 // 10 #define IOMUXC_PAD_CTL_HYS_DISABLED 0 // 0 #define CCM_CGR_OFF 0 // 00 #define CCM_CGR_ON_EXCEPT_STOP 3 // 11 //------------------------------------------------------------------------------ // CPU Registers //------------------------------------------------------------------------------ enum IMX6DQ_REGISTER_OFFSET { IOMUXC_SW_MUX_CTL_PAD_EIM_CS0_B = 0x020E00F8, IOMUXC_SW_MUX_CTL_PAD_EIM_OE_B = 0x020E0100, IOMUXC_SW_MUX_CTL_PAD_EIM_RW = 0x020E0104, IOMUXC_SW_MUX_CTL_PAD_EIM_LBA_B = 0x020E0108, IOMUXC_SW_MUX_CTL_PAD_EIM_AD00 = 0x020E0114, IOMUXC_SW_MUX_CTL_PAD_EIM_AD01 = 0x020E0118, IOMUXC_SW_MUX_CTL_PAD_EIM_AD02 = 0x020E011C, IOMUXC_SW_MUX_CTL_PAD_EIM_AD03 = 0x020E0120, IOMUXC_SW_MUX_CTL_PAD_EIM_AD04 = 0x020E0124, IOMUXC_SW_MUX_CTL_PAD_EIM_AD05 = 0x020E0128, IOMUXC_SW_MUX_CTL_PAD_EIM_AD06 = 0x020E012C, IOMUXC_SW_MUX_CTL_PAD_EIM_AD07 = 0x020E0130, IOMUXC_SW_MUX_CTL_PAD_EIM_AD08 = 0x020E0134, IOMUXC_SW_MUX_CTL_PAD_EIM_AD09 = 0x020E0138, IOMUXC_SW_MUX_CTL_PAD_EIM_AD10 = 0x020E013C, IOMUXC_SW_MUX_CTL_PAD_EIM_AD11 = 0x020E0140, IOMUXC_SW_MUX_CTL_PAD_EIM_AD12 = 0x020E0144, IOMUXC_SW_MUX_CTL_PAD_EIM_AD13 = 0x020E0148, IOMUXC_SW_MUX_CTL_PAD_EIM_AD14 = 0x020E014C, IOMUXC_SW_MUX_CTL_PAD_EIM_AD15 = 0x020E0150, IOMUXC_SW_MUX_CTL_PAD_EIM_WAIT_B = 0x020E0154, IOMUXC_SW_MUX_CTL_PAD_EIM_BCLK = 0x020E0158, IOMUXC_SW_PAD_CTL_PAD_EIM_CS0_B = 0x020E040C, IOMUXC_SW_PAD_CTL_PAD_EIM_OE_B = 0x020E0414, IOMUXC_SW_PAD_CTL_PAD_EIM_RW = 0x020E0418, IOMUXC_SW_PAD_CTL_PAD_EIM_LBA_B = 0x020E041C, IOMUXC_SW_PAD_CTL_PAD_EIM_AD00 = 0x020E0428, IOMUXC_SW_PAD_CTL_PAD_EIM_AD01 = 0x020E042C, IOMUXC_SW_PAD_CTL_PAD_EIM_AD02 = 0x020E0430, IOMUXC_SW_PAD_CTL_PAD_EIM_AD03 = 0x020E0434, IOMUXC_SW_PAD_CTL_PAD_EIM_AD04 = 0x020E0438, IOMUXC_SW_PAD_CTL_PAD_EIM_AD05 = 0x020E043C, IOMUXC_SW_PAD_CTL_PAD_EIM_AD06 = 0x020E0440, IOMUXC_SW_PAD_CTL_PAD_EIM_AD07 = 0x020E0444, IOMUXC_SW_PAD_CTL_PAD_EIM_AD08 = 0x020E0448, IOMUXC_SW_PAD_CTL_PAD_EIM_AD09 = 0x020E044C, IOMUXC_SW_PAD_CTL_PAD_EIM_AD10 = 0x020E0450, IOMUXC_SW_PAD_CTL_PAD_EIM_AD11 = 0x020E0454, IOMUXC_SW_PAD_CTL_PAD_EIM_AD12 = 0x020E0458, IOMUXC_SW_PAD_CTL_PAD_EIM_AD13 = 0x020E045C, IOMUXC_SW_PAD_CTL_PAD_EIM_AD14 = 0x020E0460, IOMUXC_SW_PAD_CTL_PAD_EIM_AD15 = 0x020E0464, IOMUXC_SW_PAD_CTL_PAD_EIM_WAIT_B = 0x020E0468, IOMUXC_SW_PAD_CTL_PAD_EIM_BCLK = 0x020E046C, CCM_CCGR6 = 0x020C4080, EIM_CS0GCR1 = 0x021B8000, EIM_CS0GCR2 = 0x021B8004, EIM_CS0RCR1 = 0x021B8008, EIM_CS0RCR2 = 0x021B800C, EIM_CS0WCR1 = 0x021B8010, EIM_CS0WCR2 = 0x021B8014, EIM_WCR = 0x021B8090, EIM_WIAR = 0x021B8094, EIM_EAR = 0x021B8098, }; //------------------------------------------------------------------------------ // Structures //------------------------------------------------------------------------------ struct IOMUXC_SW_MUX_CTL_PAD_EIM { unsigned int mux_mode : 3; unsigned int reserved_3 : 1; unsigned int sion : 1; unsigned int reserved_31_5 : 27; }; struct IOMUXC_SW_PAD_CTL_PAD_EIM { unsigned int sre : 1; unsigned int reserved_2_1 : 2; unsigned int dse : 3; unsigned int speed : 2; unsigned int reserved_10_8 : 3; unsigned int ode : 1; unsigned int pke : 1; unsigned int pue : 1; unsigned int pus : 2; unsigned int hys : 1; unsigned int reserved_31_17 : 15; }; struct CCM_CCGR6 { unsigned int cg0_usboh3 : 2; unsigned int cg1_usdhc1 : 2; unsigned int cg2_usdhc2 : 2; unsigned int cg3_usdhc3 : 2; unsigned int cg3_usdhc4 : 2; unsigned int cg5_eim_slow : 2; unsigned int cg6_vdoaxiclk : 2; unsigned int cg7_vpu : 2; unsigned int cg8_reserved : 2; unsigned int cg9_reserved : 2; unsigned int cg10_reserved : 2; unsigned int cg11_reserved : 2; unsigned int cg12_reserved : 2; unsigned int cg13_reserved : 2; unsigned int cg14_reserved : 2; unsigned int cg15_reserved : 2; }; struct EIM_CS_GCR1 { unsigned int csen : 1; unsigned int swr : 1; unsigned int srd : 1; unsigned int mum : 1; unsigned int wfl : 1; unsigned int rfl : 1; unsigned int cre : 1; unsigned int crep : 1; unsigned int bl : 3; unsigned int wc : 1; unsigned int bcd : 2; unsigned int bcs : 2; unsigned int dsz : 3; unsigned int sp : 1; unsigned int csrec : 3; unsigned int aus : 1; unsigned int gbc : 3; unsigned int wp : 1; unsigned int psz : 4; }; struct EIM_CS_GCR2 { unsigned int adh : 2; unsigned int reserved_3_2 : 2; unsigned int daps : 4; unsigned int dae : 1; unsigned int dap : 1; unsigned int reserved_11_10 : 2; unsigned int mux16_byp_grant : 1; unsigned int reserved_31_13 : 19; }; struct EIM_CS_RCR1 { unsigned int rcsn : 3; unsigned int reserved_3 : 1; unsigned int rcsa : 3; unsigned int reserved_7 : 1; unsigned int oen : 3; unsigned int reserved_11 : 1; unsigned int oea : 3; unsigned int reserved_15 : 1; unsigned int radvn : 3; unsigned int ral : 1; unsi
/*
 * 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>

/* Rename both CMSIS HAL_OK and libhal HAL_OK to disambiguate */
#define HAL_OK CMSIS_HAL_OK
#include "cmsis_os.h"

#include "stm-init.h"
#include "stm-uart.h"
#include "stm-led.h"

#include "mgmt-cli.h"
#include "mgmt-firmware.h"
#include "mgmt-bootloader.h"
#include "mgmt-fpga.h"
#include "mgmt-misc.h"
#include "mgmt-keystore.h"
#include "mgmt-masterkey.h"
#include "mgmt-thread.h"

#undef HAL_OK
#define HAL_OK LIBHAL_OK
#include "hal.h"
#warning Refactor so we do not need to include hal_internal.h here
#include "hal_internal.h"
#undef HAL_OK

#ifndef CLI_UART_RECVBUF_SIZE
#define CLI_UART_RECVBUF_SIZE  256
#endif

typedef struct {
    int ridx;
    volatile int widx;
    mgmt_cli_dma_state_t rx_state;
    uint8_t buf[CLI_UART_RECVBUF_SIZE];
} ringbuf_t;

inline void ringbuf_init(ringbuf_t *rb)
{
    memset(rb, 0, sizeof(*rb));
}

/* return number of characters read */
inline int ringbuf_read_char(ringbuf_t *rb, uint8_t *c)
{
    if (rb->ridx != rb->widx) {
        *c = rb->buf[rb->ridx];
        if (++rb->ridx >= sizeof(rb->buf))
            rb->ridx = 0;
        return 1;
    }
    return 0;
}

inline void ringbuf_write_char(ringbuf_t *rb, uint8_t c)
{
    rb->buf[rb->widx] = c;
    if (++rb->widx >= sizeof(rb->buf))
        rb->widx = 0;
}

static ringbuf_t uart_ringbuf;

/* current character received from UART */
static uint8_t uart_rx;

/* Semaphore to inform uart_cli_read that there's a new character.
 */
osSemaphoreId  uart_sem;
osSemaphoreDef(uart_sem);

/* Callback for HAL_UART_Receive_DMA().
 */
void HAL_UART1_RxCpltCallback(UART_HandleTypeDef *huart)
{
    ringbuf_write_char(&uart_ringbuf, uart_rx);
    osSemaphoreRelease(uart_sem);
}

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 ssize_t uart_cli_read(struct cli_def *cli __attribute__ ((unused)), void *buf, size_t count)
{
    for (int i = 0; i < count; ++i) {
        while (ringbuf_read_char(&uart_ringbuf, (uint8_t *)(buf + i)) == 0)
            osSemaphoreWait(uart_sem, osWaitForever);
    }
    return (ssize_t)count;
}

static ssize_t 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 (ssize_t)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) {
            ringbuf_init(&uart_ringbuf);
            HAL_UART_Receive_DMA(&huart_mgmt, &uart_rx, 1);
            uart_ringbuf.rx_state = DMA_RX_START;
        }
        return 1;
    } else if (state == DMA_RX_STOP) {
        if (HAL_UART_DMAStop(&huart_mgmt) != CMSIS_HAL_OK) return 0;
        uart_ringbuf.rx_state = DMA_RX_STOP;
        return 1;
    }
    return 0;
}

hal_user_t user;

static int check_auth(const char *username, const char *password)
{
    hal_client_handle_t client = { -1 };

    /* PIN-based login */
    if (strcmp(username, "wheel") == 0)
        user = HAL_USER_WHEEL;
    else if (strcmp(username, "so") == 0)
        user = HAL_USER_SO;
    else if (strcmp(username, "user") == 0)
        user = HAL_USER_NORMAL;
    else
        user = HAL_USER_NONE;

    if (hal_rpc_login(client, user, password, strlen(password)) == LIBHAL_OK)
        return CLI_OK;

    user = HAL_USER_NONE;
    return CLI_ERROR;
}

int cli_main(void)
{
    uart_sem = osSemaphoreCreate(osSemaphore(uart_sem), 0);

    struct cli_def *cli;
    cli = cli_init();
    if (cli == NULL)
        Error_Handler();

    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_set_auth_callback(cli, check_auth);

    /* we don't have any privileged commands at the moment */
    cli_unregister_command(cli, "enable");

    configure_cli_fpga(cli);
    configure_cli_keystore(cli);
    configure_cli_masterkey(cli);
    configure_cli_firmware(cli);
    configure_cli_bootloader(cli);
    configure_cli_misc(cli);
    configure_cli_thread(cli);

    while (1) {
        control_mgmt_uart_dma_rx(DMA_RX_START);

        cli_loop(cli, 0);
        /* cli_loop returns when the user enters 'quit' or 'exit' */
        cli_print(cli, "\nLogging out...\n");
        user = HAL_USER_NONE;
    }

    /*NOTREACHED*/
    return -1;
}