Files
thead-uboot/drivers/trng/rambus_trng.c
2022-09-13 11:04:33 +08:00

215 lines
5.5 KiB
C

/*
* Copyright (C) 2017-2020 Alibaba Group Holding Limited
*/
/******************************************************************************
* @file trng.c
* @brief
* @version
* @date 2020-09-28
******************************************************************************/
#include <string.h>
#include <stdint.h>
//#include <drv/tick.h>
#include "rng.h"
#include "eip76_internal.h"
#include "eip76_read.h"
#include "eip76_init.h"
//#include <unistd.h>
#include "rambus.h"
#define DRIVER_HRNG_RANDOM_BUFFER_LEN 16
#define DEFAULT_TIMEOUT 1000U
#define EIP76_ALARM_EVENTS 0
#define EIP76_ALARM_EVENTS 0
#define EIP76_FATAL_EVENTS (EIP76_STUCK_OUT_EVENT | EIP76_NOISE_FAIL_EVENT)
#define EIP76_IMPFRO_ENABLED_MASK 0x00000F
static uint32_t trng_initialized = 0;
#define ADAPTER_EIP76_PS_WORD32_COUNT 12
#if 1
uint32_t Adapter_EIP76_PS_Data[ADAPTER_EIP76_PS_WORD32_COUNT] = {
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0};
#else
static uint32_t Adapter_EIP76_PS_Data[ADAPTER_EIP76_PS_WORD32_COUNT] = {
0x64299d83, 0xc34d7098, 0x5bd1f51d, 0xddccfdc1, 0xdd0455b7, 0x166279e5,
0x0974cb1b, 0x2f2cd100, 0x59a5060a, 0xca79940d, 0xd4e29a40, 0x56b7b779};
#endif
/*----------------------------------------------------------------------------
* Adapter_SleepMS
*/
void Adapter_SleepMS(const unsigned int Duration_ms)
{
//usleep(Duration_ms * 1000);
udelay(Duration_ms * 1000); // Wait what's left from it
}
csi_error_t trng_init()
{
EIP76_Status_t ret;
EIP76_IOArea_t io;
Device_Handle_t handle = NULL;
if (trng_initialized) {
TRACE();
return CSI_OK;
}
ret = EIP76_Initialize(&io, handle, Adapter_EIP76_PS_Data, ADAPTER_EIP76_PS_WORD32_COUNT);
CHECK_RET_WITH_RET(ret == EIP76_NO_ERROR, SC_DRV_FAILED);
trng_initialized = 1;
return CSI_OK;
}
void trng_uninit(void)
{
/* EIP76_Shutdown(); */
}
static int s_event_check(EIP76_EventStatus_t events)
{
if (events & EIP76_FATAL_EVENTS) {
TRACE_ERR(SC_DRV_FAILED);
return SC_DRV_FAILED;
}
if (events & (EIP76_APROP_FAIL_EVENT | EIP76_REPCNT_FAIL_EVENT | EIP76_STUCK_NRBG_EVENT)) {
TRACE_ERR(SC_DRV_FAILED);
return SC_DRV_FAILED;
}
if (events & EIP76_ALARM_EVENTS) {
TRACE_ERR(SC_DRV_FAILED);
return SC_DRV_FAILED;
}
return 0;
}
extern uint32_t g_long_request_mode;
static int s_get_random_data_once(uint8_t *buf)
{
EIP76_Status_t res;
EIP76_EventStatus_t events = 0;
unsigned int actual = 0;
EIP76_IOArea_t ioarea;
uint32_t timestart;
uint32_t rt = 0;
csi_error_t ret = CSI_OK;
//timestart = csi_tick_get();
timestart = 0;//TODO
rt = timestart;
EIP76_Request_Random_Data(&ioarea, 16);
while ((rt - timestart) < DEFAULT_TIMEOUT) {
res = EIP76_Random_IsBusy(&ioarea, &events);
if (res != EIP76_NO_ERROR) {
//rt = csi_tick_get();
rt = 0;
ret = SC_DRV_FAILED;
continue;
}
/* 1 block */
res = EIP76_Random_Get(&ioarea, (EIP76_Random128_t *)buf, 1, &actual, &events);
/* retry */
if (res == EIP76_BUSY_RETRY_LATER) {
//rt = csi_tick_get();
rt = 0;
ret = SC_DRV_FAILED;
continue;
}
/* err */
if (res != EIP76_NO_ERROR) {
TRACE_ERR(res);
return SC_DRV_FAILED;
}
/* retry with wrong len */
if (actual == 0) {
//rt = csi_tick_get();
rt = 0;
ret = SC_DRV_FAILED;
continue;
}
/* check event */
return s_event_check(events);
}
return ret;
}
static int s_get_random_data(uint8_t *buf, const int count)
{
EIP76_Status_t res = CSI_ERROR;
uint32_t times = count / DRIVER_HRNG_RANDOM_BUFFER_LEN;
uint32_t rm = count % DRIVER_HRNG_RANDOM_BUFFER_LEN;
uint8_t * p = buf;
while (times > 0) {
res = s_get_random_data_once(p);
CHECK_RET_WITH_RET(res == EIP76_NO_ERROR, res);
p += DRIVER_HRNG_RANDOM_BUFFER_LEN;
times--;
}
if (rm > 0) {
EIP76_Random128_t tmp_buf;
/* Use a temporary buffer of a single random block. Only copy as
many bytes to the caller buffer as desired. */
res = s_get_random_data_once((uint8_t *)&tmp_buf);
CHECK_RET_WITH_RET(res == EIP76_NO_ERROR, res);
memcpy(p, &tmp_buf, rm);
memset(&tmp_buf, 0, DRIVER_HRNG_RANDOM_BUFFER_LEN);
return res;
}
return res;
}
/**
\brief Get data from the TRNG engine
\param[out] data Pointer to buffer with data get from TRNG
\param[in] num Number of data items,uinit in uint32
\return error code
*/
csi_error_t csi_rng_get_multi_word(uint32_t *data, uint32_t num)
{
CHECK_RET_WITH_RET(data, SC_PARAM_INV);
CHECK_RET_WITH_RET(num > 0, SC_PARAM_INV);
#if 0
uint32_t ret = trng_init();
CHECK_RET_WITH_RET(ret == CSI_OK, ret);
#endif
RB_PERF_START_POINT();
uint32_t ret = s_get_random_data((uint8_t *)data, num * sizeof(uint32_t));
RB_PERF_END_POINT();
trng_uninit();
return ret;
}
/**
\brief Get data from the TRNG engine
\return error code
*/
csi_error_t csi_rng_get_single_word(uint32_t *data)
{
CHECK_RET_WITH_RET(data, SC_PARAM_INV);
uint32_t ret = trng_init();
CHECK_RET_WITH_RET(ret == CSI_OK, ret);
ret = s_get_random_data((uint8_t *)data, sizeof(uint32_t));
trng_uninit();
return ret;
}