summaryrefslogtreecommitdiff
path: root/FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/sha/ck_sha_v1.c
diff options
context:
space:
mode:
authoryuhzheng <yuhzheng@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2020-01-10 07:53:14 +0000
committeryuhzheng <yuhzheng@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2020-01-10 07:53:14 +0000
commit50ff3134dc87e8a059ea6f4a8cefdb85f2f6fd17 (patch)
tree7fe982d669c06b755140b122e86c21b16b34ffe5 /FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/sha/ck_sha_v1.c
parentc454f6e231815e0188e205731952ac758e1d955a (diff)
downloadfreertos-50ff3134dc87e8a059ea6f4a8cefdb85f2f6fd17.tar.gz
Introduce a port for T-HEAD CK802. A simple demo for T-HEAD CB2201 is also included.
git-svn-id: http://svn.code.sf.net/p/freertos/code/trunk@2802 1d2547de-c912-0410-9cb9-b8ca96c0e9e2
Diffstat (limited to 'FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/sha/ck_sha_v1.c')
-rw-r--r--FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/sha/ck_sha_v1.c559
1 files changed, 559 insertions, 0 deletions
diff --git a/FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/sha/ck_sha_v1.c b/FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/sha/ck_sha_v1.c
new file mode 100644
index 000000000..66fbf097e
--- /dev/null
+++ b/FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/sha/ck_sha_v1.c
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/******************************************************************************
+ * @file ck_sha.c
+ * @brief CSI Source File for SHA Driver
+ * @version V1.0
+ * @date 02. June 2017
+ ******************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include "csi_core.h"
+#include "drv_sha.h"
+#include "ck_sha_v1.h"
+
+#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
+#define CONFIG_SHA_SUPPORT_MUL_THREAD 1
+#endif
+
+typedef struct {
+ uint32_t base;
+ uint32_t irq;
+ sha_event_cb_t cb;
+ sha_status_t status;
+ sha_mode_e mode;
+ sha_endian_mode_e endian;
+#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
+ uint32_t state[16];
+ uint32_t sha_buffer[32];
+ uint32_t total;
+ uint8_t first_cal;
+#endif
+} ck_sha_priv_t;
+
+#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
+static ck_sha_priv_t sha_handle[CONFIG_SHA_NUM];
+#endif
+bool finish_flag = 0;
+
+/* Driver Capabilities */
+static const sha_capabilities_t driver_capabilities = {
+ .sha1 = 1, /* sha1 mode */
+ .sha224 = 1, /* sha224 mode */
+ .sha256 = 1, /* sha256 mode */
+ .sha384 = 1, /* sha384 mode */
+ .sha512 = 1, /* sha512 mode */
+ .sha512_224 = 1, /* sha512_224 mode */
+ .sha512_256 = 1, /* sha512_256 mode */
+ .endianmode = 1, /* endian mode */
+ .interruptmode = 1 /* interrupt mode */
+};
+
+#define ERR_SHA(errno) (CSI_DRV_ERRNO_SHA_BASE | errno)
+#define SHA_NULL_PARAM_CHK(para) \
+ do { \
+ if (para == NULL) { \
+ return ERR_SHA(EDRV_PARAMETER); \
+ } \
+ } while (0)
+
+extern int32_t target_get_sha(int32_t idx, uint32_t *base, uint32_t *irq);
+extern int32_t target_get_sha_count(void);
+//
+// Functions
+//
+
+ck_sha_reg_t *sha_reg = NULL;
+
+#ifndef CONFIG_SHA_SUPPORT_MUL_THREAD
+static uint32_t sha_buffer[32];
+static uint32_t total[2] = {0x0};
+static uint8_t first_cal = 1;
+#endif
+static uint8_t sha_result[64] = {0x0};
+
+static int32_t sha_set_mode(sha_mode_e mode)
+{
+ sha_reg->SHA_MODE &= ~0x7;
+ sha_reg->SHA_MODE |= mode;
+ return 0;
+}
+
+static void sha_set_source_message(uint32_t baseaddr)
+{
+ sha_reg->SHA_BASEADDR = baseaddr;
+}
+
+static void sha_set_dest_message(uint32_t destaddr)
+{
+ sha_reg->SHA_DESTADDR = destaddr;
+}
+
+static void sha_enable_without_count(void)
+{
+ sha_reg->SHA_MODE |= 1<<25;
+}
+
+static void sha_disable_without_count(void)
+{
+ sha_reg->SHA_MODE &= ~(1<<25);
+}
+
+static void sha_set_message_count(uint32_t count)
+{
+ sha_reg->SHA_COUNTER0 = count;
+ sha_reg->SHA_COUNTER1 = 0;
+}
+
+static int32_t sha_enable_initial(void)
+{
+ sha_reg->SHA_MODE |= 1 << SHA_INIT_OFFSET;
+ return 0;
+}
+
+static int32_t sha_disable_initial(void)
+{
+ sha_reg->SHA_MODE &= ~(1 << SHA_INIT_OFFSET);
+ return 0;
+}
+
+static int32_t sha_enable_calculate(void)
+{
+ sha_reg->SHA_CON |= 1;
+ return 0;
+}
+
+static int32_t sha_message_done(void)
+{
+ while(sha_reg->SHA_CON & 0x1);
+ return 0;
+}
+
+static void sha_new_encode(void)
+{
+ sha_reg->SHA_INTSTATE = 0;
+ sha_reg->SHA_MODE = 0;
+}
+
+#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
+static int32_t sha_restore_context(sha_handle_t handle, uint32_t *data)
+{
+ uint32_t *result = (uint32_t *)&sha_reg->SHA_H0L;
+
+ uint8_t i;
+ for (i = 0; i < 16; i++) {
+ result[i] = data[i];
+ }
+ return 0;
+}
+
+static int32_t sha_save_context(sha_handle_t handle, uint32_t *data)
+{
+ uint32_t *result = (uint32_t *)&sha_reg->SHA_H0L;
+
+ uint8_t i;
+ for (i = 0; i < 16; i++) {
+ data[i] = result[i];
+ }
+ return 0;
+}
+#endif
+
+static inline void sha_reverse_order(uint8_t *pdata, int32_t length)
+{
+ uint8_t input_data[length];
+ uint8_t result[length];
+ uint32_t tmp = 0;
+ int32_t i = 0;
+ memcpy((void *)input_data, (void *)pdata, length);
+
+ for (i = 0; i < length; i++) {
+ tmp = i >> 2;
+ tmp = tmp << 3;
+ result[i] = input_data[tmp + 3 - i];
+ }
+
+ memcpy((void *)pdata, (void *)result, length);
+}
+
+/**
+ \brief get sha handle count.
+ \return sha handle count
+*/
+int32_t csi_sha_get_instance_count(void)
+{
+ return target_get_sha_count();
+}
+
+/**
+ \brief Initialize SHA Interface. 1. Initializes the resources needed for the SHA interface 2.registers event callback function
+ \param[in] idx must not exceed return value of csi_sha_get_instance_count()
+ \param[in] cb_event Pointer to \ref sha_event_cb_t
+ \return return sha handle if success
+*/
+sha_handle_t csi_sha_initialize(sha_handle_t handle, sha_event_cb_t cb_event)
+{
+#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
+ uint32_t base = 0u;
+ uint32_t irq;
+ /* obtain the sha information */
+ target_get_sha(0, &base, &irq);
+ ck_sha_priv_t *sha_priv = handle;
+ memset(sha_priv->state, 0, sizeof(sha_priv->state));
+ sha_priv->total = 0;
+ sha_priv->first_cal = 1;
+
+#else
+ if (idx < 0 || idx >= CONFIG_SHA_NUM) {
+ return NULL;
+ }
+
+ uint32_t base = 0u;
+ uint32_t irq;
+ /* obtain the sha information */
+ int32_t real_idx = target_get_sha(idx, &base, &irq);
+
+ if (real_idx != idx) {
+ return NULL;
+ }
+ ck_sha_priv_t *sha_priv = &sha_handle[idx];
+#endif
+ sha_priv->base = base;
+ sha_priv->irq = irq;
+
+ /* initialize the sha context */
+ sha_priv->cb = cb_event;
+ sha_priv->status.busy = 0;
+
+ return (sha_handle_t)sha_priv;
+}
+
+/**
+ \brief De-initialize SHA Interface. stops operation and releases the software resources used by the interface
+ \param[in] handle sha handle to operate.
+ \return error code
+*/
+int32_t csi_sha_uninitialize(sha_handle_t handle)
+{
+ SHA_NULL_PARAM_CHK(handle);
+
+ ck_sha_priv_t *sha_priv = handle;
+ sha_priv->cb = NULL;
+
+ return 0;
+}
+
+/**
+ \brief Get driver capabilities.
+ \param[in] handle sha handle to operate.
+ \return \ref sha_capabilities_t
+*/
+sha_capabilities_t csi_sha_get_capabilities(sha_handle_t handle)
+{
+ return driver_capabilities;
+}
+
+/**
+ \brief config sha mode.
+ \param[in] handle sha handle to operate.
+ \param[in] mode \ref sha_mode_e
+ \param[in] endian \ref sha_endian_mode_e
+ \return error code
+*/
+int32_t csi_sha_config(sha_handle_t handle, sha_mode_e mode, sha_endian_mode_e endian_mode)
+{
+ SHA_NULL_PARAM_CHK(handle);
+
+ ck_sha_priv_t *sha_priv = handle;
+ sha_reg = (ck_sha_reg_t *)(sha_priv->base);
+
+ /* config the sha mode */
+ switch (mode) {
+ case SHA_MODE_512_256:
+ case SHA_MODE_512_224:
+ return ERR_SHA(EDRV_UNSUPPORTED);
+
+ case SHA_MODE_1:
+ case SHA_MODE_224:
+ case SHA_MODE_256:
+ case SHA_MODE_384:
+ case SHA_MODE_512:
+ sha_priv->mode = mode;
+ break;
+
+ default:
+ return ERR_SHA(EDRV_PARAMETER);
+ }
+
+ return 0;
+}
+
+/**
+ \brief start the engine
+ \param[in] handle sha handle to operate.
+ \param[in] context Pointer to the sha context.
+ \return error code
+*/
+int32_t csi_sha_starts(sha_handle_t handle, void *context)
+{
+ SHA_NULL_PARAM_CHK(handle);
+
+ ck_sha_priv_t *sha_priv = handle;
+ sha_priv->status.busy = 1;
+
+ sha_new_encode();
+ sha_set_mode(sha_priv->mode);
+
+#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
+ memset(sha_priv->sha_buffer, 0, sizeof(sha_priv->sha_buffer));
+ memset(sha_priv->state, 0, sizeof(sha_priv->state));
+ sha_priv->first_cal = 1;
+ sha_priv->total = 0;
+#endif
+
+ return 0;
+}
+
+/**
+ \brief updata the engine
+ \param[in] handle sha handle to operate.
+ \param[in] context Pointer to the sha context.
+ \param[in] input Pointer to the Source data
+ \param[in] len the data len
+ \return error code
+*/
+int32_t csi_sha_update(sha_handle_t handle, void *context, const void *input, uint32_t len)
+{
+ SHA_NULL_PARAM_CHK(handle);
+ SHA_NULL_PARAM_CHK(input);
+ if (len <= 0) {
+ return ERR_SHA(EDRV_PARAMETER);
+ }
+
+ ck_sha_priv_t *sha_priv = handle;
+ sha_reg = (ck_sha_reg_t *)(sha_priv->base);
+
+ uint8_t total_len_num;
+ uint32_t block_size;
+ if (sha_priv->mode < 4) {
+ block_size = 64;
+ total_len_num = 2;
+ } else {
+ block_size = 128;
+ total_len_num = 4;
+ }
+
+#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
+ uint32_t *sha_buffer = sha_priv->sha_buffer;
+ uint8_t first_cal = sha_priv->first_cal;
+ sha_set_mode(sha_priv->mode);
+ uint32_t left = sha_priv->total & (block_size - 1);
+ uint32_t fill = block_size - left;
+ uint32_t total_length = sha_priv->total << 3;
+ uint32_t index = left >> 2;
+
+ if (left & 0x3) {
+ index++;
+ }
+ sha_priv->total += len;
+ sha_priv->total &= 0xffffffff;
+#else
+ uint32_t left = total[0] & (block_size - 1);
+ uint32_t fill = block_size - left;
+ uint32_t total_length = total[0] << 3;
+ uint32_t index = left >> 2;
+
+ if (left & 0x3) {
+ index++;
+ }
+ total[0] += len;
+ total[0] &= 0xffffffff;
+#endif
+ uint8_t *p = (uint8_t *)input;
+ /* when the text is not aligned by block and len > fill */
+ if (left && len >= fill) {
+ if (finish_flag) {
+#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
+ memset(((uint8_t *)sha_buffer + left), 0x0, sizeof(sha_priv->sha_buffer) - left);
+#else
+ memset(((uint8_t *)sha_buffer + left), 0x0, sizeof(sha_buffer) - left);
+#endif
+ sha_buffer[index + total_len_num - 1] = total_length;
+
+ sha_disable_without_count();
+ sha_set_message_count(left << 3);
+ } else {
+ memcpy((void *)(((uint8_t *)sha_buffer) + left), p, fill);
+ p += fill;
+
+ sha_enable_without_count();
+ sha_set_message_count(block_size << 3);
+ }
+
+ sha_set_source_message((uint32_t)sha_buffer);
+ sha_set_dest_message((uint32_t)sha_result);
+ if (first_cal == 0) {
+ sha_enable_initial();
+ } else {
+ sha_disable_initial();
+ }
+
+#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
+ sha_restore_context(handle, (uint32_t *)sha_priv->state);
+#endif
+
+ sha_enable_calculate();
+ sha_message_done();
+
+#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
+ sha_save_context(handle, (uint32_t *)sha_priv->state);
+#endif
+ len -= fill;
+ left = 0;
+#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
+ sha_priv->first_cal = 0;
+ first_cal = 0;
+#else
+ first_cal = 0;
+#endif
+ }
+
+ /* calculate the hash by block */
+ while (len >= block_size) {
+ if (finish_flag) {
+#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
+ memset(sha_buffer, 0, sizeof(sha_priv->sha_buffer));
+#else
+ memset(sha_buffer, 0, sizeof(sha_buffer));
+#endif
+ sha_buffer[total_len_num - 1] = total_length;
+
+ sha_set_source_message((uint32_t)sha_buffer);
+ sha_disable_without_count();
+ sha_set_message_count(0);
+ } else {
+ memcpy(sha_buffer, p, block_size);
+ sha_set_source_message((uint32_t)sha_buffer);
+ sha_enable_without_count();
+ sha_set_message_count(block_size << 3);
+ p += block_size;
+ }
+ sha_set_dest_message((uint32_t)sha_result);
+ if (first_cal == 0) {
+ sha_enable_initial();
+ } else {
+ sha_disable_initial();
+ }
+#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
+ sha_restore_context(handle, (uint32_t *)sha_priv->state);
+#endif
+
+ sha_enable_calculate();
+ sha_message_done();
+#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
+ sha_save_context(handle, (uint32_t *)sha_priv->state);
+#endif
+#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
+ sha_priv->first_cal = 0;
+ first_cal = 0;
+#else
+ first_cal = 0;
+#endif
+ len -= block_size;
+ }
+
+ /* when the text is not aligned by block and len < fill */
+ if (len > 0) {
+ memcpy((void *)(((uint8_t *)sha_buffer) + left), p, len);
+ }
+
+ sha_priv->status.busy = 0;
+
+ return 0;
+}
+
+/**
+ \brief finish the engine
+ \param[in] handle sha handle to operate.
+ \param[in] context Pointer to the sha context.
+ \param[out] output Pointer to the dest data
+ \return error code
+*/
+int32_t csi_sha_finish(sha_handle_t handle, void *context, void *output)
+{
+ SHA_NULL_PARAM_CHK(handle);
+ SHA_NULL_PARAM_CHK(output);
+
+ ck_sha_priv_t *sha_priv = handle;
+ uint32_t block_size;
+ if (sha_priv->mode < 4) {
+ block_size = 64;
+ } else {
+ block_size = 128;
+ }
+
+#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
+ uint32_t last = sha_priv->total & (block_size - 1);
+#else
+ uint32_t last = total[0] & (block_size - 1);
+#endif
+ uint32_t padn = block_size - last;
+
+ finish_flag = 1;
+
+ csi_sha_update(handle, NULL, output, padn);
+
+ uint8_t result_len = 20;
+ /* convert the data endian according the sha mode */
+ if (sha_priv->mode == SHA_MODE_1) {
+ result_len = 20;
+ } else if (sha_priv->mode == SHA_MODE_224) {
+ result_len = 28;
+ } else if (sha_priv->mode == SHA_MODE_256) {
+ result_len = 32;
+ } else if (sha_priv->mode == SHA_MODE_512) {
+ result_len = 64;
+ } else if (sha_priv->mode == SHA_MODE_384) {
+ result_len = 48;
+ }
+ sha_reverse_order(sha_result, result_len);
+ memcpy((uint8_t*)output, sha_result, result_len);
+
+ finish_flag = 0;
+#ifdef CONFIG_SHA_SUPPORT_MUL_THREAD
+ memset(sha_priv->sha_buffer, 0, sizeof(sha_priv->sha_buffer));
+ sha_priv->first_cal = 1;
+ sha_priv->total = 0;
+#else
+ memset(sha_buffer, 0, sizeof(sha_buffer));
+ first_cal = 1;
+ total[0] = 0;
+#endif
+ return 0;
+}
+
+/**
+ \brief Get SHA status.
+ \param[in] handle sha handle to operate.
+ \return SHA status \ref sha_status_t
+*/
+sha_status_t csi_sha_get_status(sha_handle_t handle)
+{
+ ck_sha_priv_t *sha_priv = handle;
+ return sha_priv->status;
+}