1df9a39eaSdp-arm /* 2fd116b9fSRoberto Vargas * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. 3df9a39eaSdp-arm * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 5df9a39eaSdp-arm */ 6df9a39eaSdp-arm 7df9a39eaSdp-arm #include <assert.h> 8df9a39eaSdp-arm #include <string.h> 909d40e0eSAntonio Nino Diaz 1009d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 1109d40e0eSAntonio Nino Diaz #include <lib/utils_def.h> 12*234bc7f8SAntonio Nino Diaz #include <platform_def.h> 1309d40e0eSAntonio Nino Diaz 14fd116b9fSRoberto Vargas #include "juno_decl.h" 15df9a39eaSdp-arm 16df9a39eaSdp-arm #define NSAMPLE_CLOCKS 1 /* min 1 cycle, max 231 cycles */ 17df9a39eaSdp-arm #define NRETRIES 5 18df9a39eaSdp-arm 19df9a39eaSdp-arm static inline int output_valid(void) 20df9a39eaSdp-arm { 21df9a39eaSdp-arm int i; 22df9a39eaSdp-arm 23df9a39eaSdp-arm for (i = 0; i < NRETRIES; i++) { 24df9a39eaSdp-arm uint32_t val; 25df9a39eaSdp-arm 26df9a39eaSdp-arm val = mmio_read_32(TRNG_BASE + TRNG_STATUS); 27df9a39eaSdp-arm if (val & 1U) 28df9a39eaSdp-arm break; 29df9a39eaSdp-arm } 30df9a39eaSdp-arm if (i >= NRETRIES) 31df9a39eaSdp-arm return 0; /* No output data available. */ 32df9a39eaSdp-arm return 1; 33df9a39eaSdp-arm } 34df9a39eaSdp-arm 35df9a39eaSdp-arm /* 36df9a39eaSdp-arm * This function fills `buf` with `len` bytes of entropy. 37df9a39eaSdp-arm * It uses the Trusted Entropy Source peripheral on Juno. 38df9a39eaSdp-arm * Returns 0 when the buffer has been filled with entropy 39df9a39eaSdp-arm * successfully and -1 otherwise. 40df9a39eaSdp-arm */ 41df9a39eaSdp-arm int juno_getentropy(void *buf, size_t len) 42df9a39eaSdp-arm { 43df9a39eaSdp-arm uint8_t *bp = buf; 44df9a39eaSdp-arm 45df9a39eaSdp-arm assert(buf); 46df9a39eaSdp-arm assert(len); 47df9a39eaSdp-arm assert(!check_uptr_overflow((uintptr_t)bp, len)); 48df9a39eaSdp-arm 49df9a39eaSdp-arm /* Disable interrupt mode. */ 50df9a39eaSdp-arm mmio_write_32(TRNG_BASE + TRNG_INTMASK, 0); 51df9a39eaSdp-arm /* Program TRNG to sample for `NSAMPLE_CLOCKS`. */ 52df9a39eaSdp-arm mmio_write_32(TRNG_BASE + TRNG_CONFIG, NSAMPLE_CLOCKS); 53df9a39eaSdp-arm 54df9a39eaSdp-arm while (len > 0) { 55df9a39eaSdp-arm int i; 56df9a39eaSdp-arm 57df9a39eaSdp-arm /* Start TRNG. */ 58df9a39eaSdp-arm mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1); 59df9a39eaSdp-arm 60df9a39eaSdp-arm /* Check if output is valid. */ 61df9a39eaSdp-arm if (!output_valid()) 62df9a39eaSdp-arm return -1; 63df9a39eaSdp-arm 64df9a39eaSdp-arm /* Fill entropy buffer. */ 65df9a39eaSdp-arm for (i = 0; i < TRNG_NOUTPUTS; i++) { 66df9a39eaSdp-arm size_t n; 67df9a39eaSdp-arm uint32_t val; 68df9a39eaSdp-arm 69df9a39eaSdp-arm val = mmio_read_32(TRNG_BASE + i * sizeof(uint32_t)); 70df9a39eaSdp-arm n = MIN(len, sizeof(uint32_t)); 71df9a39eaSdp-arm memcpy(bp, &val, n); 72df9a39eaSdp-arm bp += n; 73df9a39eaSdp-arm len -= n; 74df9a39eaSdp-arm if (len == 0) 75df9a39eaSdp-arm break; 76df9a39eaSdp-arm } 77df9a39eaSdp-arm 78df9a39eaSdp-arm /* Reset TRNG outputs. */ 79df9a39eaSdp-arm mmio_write_32(TRNG_BASE + TRNG_STATUS, 1); 80df9a39eaSdp-arm } 81df9a39eaSdp-arm 82df9a39eaSdp-arm return 0; 83df9a39eaSdp-arm } 84