#include <common.h> | |
#include <config.h> | |
#include <ubi_uboot.h> | |
#include <asm/arch/cpu.h> | |
#include <kgdb.h> | |
#include <asm/processor.h> | |
#include <asm/io.h> | |
#include <malloc.h> | |
#include "asr_geu.h" | |
#include "asr_rng.h" | |
static struct random_data random_data = { | |
.random_base = GEU_BASE, | |
.random_num_saved = 0 | |
}; | |
#define random_read(x) readl(random_data.random_base + x) | |
#define random_write(x, y) writel(y, (random_data.random_base + x)) | |
static void geu_rng_enable(void) | |
{ | |
uint32_t val; | |
uint32_t seed = read_timer(); //TODO | |
val = random_read(GEU_PRNG_CTRL_REG); | |
if (!(val & GEU_PRNG_EN)) { | |
val |= GEU_PRNG_EN; | |
random_write(GEU_PRNG_CTRL_REG, val); | |
udelay(1000); /* means a reset happens */ | |
} | |
random_write(GEU_HW_RANDOM_NUM_SEED, seed & 0xFF); | |
} | |
static uint32_t geu_get_random_data(void) | |
{ | |
uint32_t val = 0; | |
uint32_t timeout = 100, mytime; | |
int ret = 0; | |
uint32_t start = get_timer(0); | |
do { | |
val = random_read(GEU_HW_RANDOM_NUM_GEN); | |
mytime = get_timer(start); | |
if (mytime >= timeout) { | |
// porintf("fail to generate rng seed, time out!"); | |
panic("fail to generate rng seed, time out!\n"); | |
} | |
}while(val ==0 || val == random_data.random_num_saved); | |
exit: | |
random_data.random_num_saved = val; | |
return val; | |
} | |
uint32_t crypto_rng_read(void *buf, size_t len) | |
{ | |
uint32_t *rngbuf = buf; | |
uint32_t val = 0; | |
assert(buf); | |
asr_geu_get(); | |
geu_enable_clk(); | |
geu_rng_enable(); | |
while (len) { | |
val = geu_get_random_data(); | |
if (len > sizeof(uint32_t)) { | |
len = len - sizeof(uint32_t); | |
memcpy(rngbuf, &val, sizeof(uint32_t)); | |
rngbuf++; | |
} else { | |
memcpy(rngbuf, &val, len); | |
len = 0; | |
} | |
} | |
geu_disable_clk(); | |
asr_geu_put(); | |
return 0; | |
} | |
uint8_t hw_get_random_byte(void) | |
{ | |
uint8_t data = 0; | |
if (crypto_rng_read(&data, 1)) | |
panic("rng read failed\n"); | |
return data; | |
} | |
uint32_t hw_get_random_32(void) | |
{ | |
uint32_t data = 0; | |
if (crypto_rng_read(&data, 4)) | |
panic("rng read failed\n"); | |
return data; | |
} | |
void geu_random_test(void) | |
{ | |
uint8_t buf[32] = {0}; | |
uint32_t size = sizeof(buf); | |
if (crypto_rng_read(buf, size)) { | |
printf("geu rng test failed"); | |
return; | |
} | |
for (uint32_t i = 0; i < size; i++) { | |
printf("%.2x ", buf[i]); | |
if ((i + 1) == 0) | |
printf("\n"); | |
} | |
printf("\n"); | |
} |