rpi3: Introduce hardware RNG driver
Note that this is a non-secure RNG. This is only useful for educational purposes. Change-Id: If359c8d0f755ef8e416986de7fbca34679a523e1 Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
This commit is contained in:
parent
98967fb14a
commit
4ad2696d88
|
@ -58,6 +58,24 @@
|
|||
*/
|
||||
#define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555)
|
||||
|
||||
/*
|
||||
* Hardware random number generator.
|
||||
*/
|
||||
#define RPI3_IO_RNG_OFFSET ULL(0x00104000)
|
||||
#define RPI3_RNG_BASE (RPI3_IO_BASE + RPI3_IO_RNG_OFFSET)
|
||||
#define RPI3_RNG_CTRL_OFFSET ULL(0x00000000)
|
||||
#define RPI3_RNG_STATUS_OFFSET ULL(0x00000004)
|
||||
#define RPI3_RNG_DATA_OFFSET ULL(0x00000008)
|
||||
#define RPI3_RNG_INT_MASK_OFFSET ULL(0x00000010)
|
||||
/* Enable/disable RNG */
|
||||
#define RPI3_RNG_CTRL_ENABLE U(0x1)
|
||||
#define RPI3_RNG_CTRL_DISABLE U(0x0)
|
||||
/* Number of currently available words */
|
||||
#define RPI3_RNG_STATUS_NUM_WORDS_SHIFT U(24)
|
||||
#define RPI3_RNG_STATUS_NUM_WORDS_MASK U(0xFF)
|
||||
/* Value to mask interrupts caused by the RNG */
|
||||
#define RPI3_RNG_INT_MASK_DISABLE U(0x1)
|
||||
|
||||
/*
|
||||
* Serial port (called 'Mini UART' in the BCM docucmentation).
|
||||
*/
|
||||
|
|
|
@ -33,6 +33,9 @@ uint32_t rpi3_get_spsr_for_bl33_entry(void);
|
|||
/* IO storage utility functions */
|
||||
void plat_rpi3_io_setup(void);
|
||||
|
||||
/* Hardware RNG functions */
|
||||
void rpi3_rng_read(void *buf, size_t len);
|
||||
|
||||
/* VideoCore firmware commands */
|
||||
int rpi3_vc_hardware_get_board_revision(uint32_t *revision);
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <mmio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rpi3_hw.h"
|
||||
|
||||
/* Initial amount of values to discard */
|
||||
#define RNG_WARMUP_COUNT U(0x40000)
|
||||
|
||||
static void rpi3_rng_initialize(void)
|
||||
{
|
||||
uint32_t int_mask, ctrl;
|
||||
|
||||
/* Return if it is already enabled */
|
||||
ctrl = mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_CTRL_OFFSET);
|
||||
if ((ctrl & RPI3_RNG_CTRL_ENABLE) != 0U) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Mask interrupts */
|
||||
int_mask = mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_INT_MASK_OFFSET);
|
||||
int_mask |= RPI3_RNG_INT_MASK_DISABLE;
|
||||
mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_INT_MASK_OFFSET, int_mask);
|
||||
|
||||
/* Discard several values when initializing to give it time to warmup */
|
||||
mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_STATUS_OFFSET, RNG_WARMUP_COUNT);
|
||||
|
||||
mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_CTRL_OFFSET,
|
||||
RPI3_RNG_CTRL_ENABLE);
|
||||
}
|
||||
|
||||
static uint32_t rpi3_rng_get_word(void)
|
||||
{
|
||||
size_t nwords;
|
||||
|
||||
do {
|
||||
/* Get number of available words to read */
|
||||
nwords = (mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_STATUS_OFFSET)
|
||||
>> RPI3_RNG_STATUS_NUM_WORDS_SHIFT)
|
||||
& RPI3_RNG_STATUS_NUM_WORDS_MASK;
|
||||
} while (nwords == 0U);
|
||||
|
||||
return mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_DATA_OFFSET);
|
||||
}
|
||||
|
||||
void rpi3_rng_read(void *buf, size_t len)
|
||||
{
|
||||
uint32_t data;
|
||||
size_t left = len;
|
||||
uint32_t *dst = buf;
|
||||
|
||||
assert(buf != NULL);
|
||||
assert(len != 0U);
|
||||
assert(check_uptr_overflow((uintptr_t) buf, (uintptr_t) len) == 0);
|
||||
|
||||
rpi3_rng_initialize();
|
||||
|
||||
while (left >= sizeof(uint32_t)) {
|
||||
data = rpi3_rng_get_word();
|
||||
*dst++ = data;
|
||||
left -= sizeof(uint32_t);
|
||||
}
|
||||
|
||||
if (left > 0U) {
|
||||
data = rpi3_rng_get_word();
|
||||
memcpy(dst, &data, left);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue