[PATCH v1] 2: Uboot RNG Driver using Data Co-processor
Heinrich Schuchardt
xypron.glpk at gmx.de
Thu Sep 8 21:29:37 CEST 2022
On 9/8/22 20:19, Simon Glass wrote:
> Hi Kshitiz,
>
> On Thu, 8 Sept 2022 at 02:59, Kshitiz Varshney <kshitiz.varshney at nxp.com> wrote:
>>
>> From: Kshitiz <kshitiz.varshney at nxp.com>
>>
>> This commit introduces Random number generator to uboot. It uses DCP
>> driver for number generation.
>> RNG driver can be invoked by using below command on uboot prompt:-
>> rng <number of bytes>
>>
>> Signed-off-by: Kshitiz Varshney <kshitiz.varshney at nxp.com>
CC the maintainer for RNG Sughosh Ganu <sughosh.ganu at linaro.org>.
>> Reviewed-by: Ye Li <ye.li at nxp.com>
>> ---
>> drivers/crypto/fsl/Kconfig | 10 ++
>> drivers/crypto/fsl/Makefile | 1 +
>> drivers/crypto/fsl/dcp_rng.c | 184 +++++++++++++++++++++++++++++++++++
>> 3 files changed, 195 insertions(+)
>> create mode 100644 drivers/crypto/fsl/dcp_rng.c
>
> Reviewed-by: Simon Glass <sjg at chromium.org>
>
> but please see below
>
>>
>> diff --git a/drivers/crypto/fsl/Kconfig b/drivers/crypto/fsl/Kconfig
>> index 702d204a3d..da5955e31d 100644
>> --- a/drivers/crypto/fsl/Kconfig
>> +++ b/drivers/crypto/fsl/Kconfig
>> @@ -96,3 +96,13 @@ config RNG_SELF_TEST
>> must be run before running any RNG based crypto implementation.
>>
>> endif
>> +
>> +config FSL_DCP_RNG
>> + bool "Enable Random Number Generator support"
>> + depends on DM_RNG
>> + default n
>> + help
>> + Enable support for the hardware based random number generator
>> + module of the DCP.It uses the True Random Number Generator (TRNG)
Please, use the same indentation as the other Kconfig entries in this
file: Add two space in each line of the help text.
>
> Space before It
>
>> + and a Pseudo-Random Number Generator (PRNG) to achieve a true
>> + randomness and cryptographic strength.
>> diff --git a/drivers/crypto/fsl/Makefile b/drivers/crypto/fsl/Makefile
>> index 926300e2ab..c653208d23 100644
>> --- a/drivers/crypto/fsl/Makefile
>> +++ b/drivers/crypto/fsl/Makefile
>> @@ -7,6 +7,7 @@ obj-$(CONFIG_FSL_CAAM) += jr.o fsl_hash.o jobdesc.o error.o
>> obj-$(CONFIG_FSL_BLOB) += fsl_blob.o
>> obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o
>> obj-$(CONFIG_FSL_CAAM_RNG) += rng.o
>> +obj-$(CONFIG_FSL_DCP_RNG) += dcp_rng.o
>> obj-$(CONFIG_IMX_CAAM_MFG_PROT) += fsl_mfgprot.o
>> obj-$(CONFIG_RNG_SELF_TEST) += rng_self_test.o
>> obj-$(CONFIG_CMD_PROVISION_KEY) += fsl_aes.o tag_object.o
>> diff --git a/drivers/crypto/fsl/dcp_rng.c b/drivers/crypto/fsl/dcp_rng.c
>> new file mode 100644
>> index 0000000000..a797710c2e
>> --- /dev/null
>> +++ b/drivers/crypto/fsl/dcp_rng.c
>> @@ -0,0 +1,184 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>> +/*
>> + * RNG driver for Freescale RNGC
>> + *
>> + * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
>> + * Copyright (C) 2017 Martin Kaiser <martin at kaiser.cx>
>> + * Copyright 2022 NXP
>> + *
>> + * Based on RNGC driver in drivers/char/hw_random/imx-rngc.c in Linux
>> + */
>> +
>> +#include <asm/cache.h>
>> +#include <common.h>
>> +#include <cpu_func.h>
>> +#include <dm.h>
>> +#include <rng.h>
>> +#include <linux/kernel.h>
>> +#include <linux/delay.h>
>> +#include <asm/io.h>
>> +#include <dm/root.h>
>
> Should be:
>
>> +#include <common.h>
>> +#include <cpu_func.h>
>> +#include <dm.h>
>> +#include <rng.h>
>> +#include <asm/cache.h>
>> +#include <asm/io.h>
>> +#include <dm/root.h>
>> +#include <linux/delay.h>
>> +#include <linux/kernel.h>
>
>
>> +
>> +#define DCP_RNG_MAX_FIFO_STORE_SIZE 4
>> +#define RNGC_VER_ID 0x0000
>> +#define RNGC_COMMAND 0x0004
>> +#define RNGC_CONTROL 0x0008
>> +#define RNGC_STATUS 0x000C
>> +#define RNGC_ERROR 0x0010
>> +#define RNGC_FIFO 0x0014
>> +
>> +/* the fields in the ver id register */
>> +#define RNGC_TYPE_SHIFT 28
>> +
>> +/* the rng_type field */
>> +#define RNGC_TYPE_RNGB 0x1
>> +#define RNGC_TYPE_RNGC 0x2
>> +
>> +#define RNGC_CMD_CLR_ERR 0x00000020
>> +#define RNGC_CMD_SEED 0x00000002
>> +
>> +#define RNGC_CTRL_AUTO_SEED 0x00000010
>> +
>> +#define RNGC_STATUS_ERROR 0x00010000
>> +#define RNGC_STATUS_FIFO_LEVEL_MASK 0x00000f00
>> +#define RNGC_STATUS_FIFO_LEVEL_SHIFT 8
>> +#define RNGC_STATUS_SEED_DONE 0x00000020
>> +#define RNGC_STATUS_ST_DONE 0x00000010
>
> Why all the leading zeroes?
>
>> +
>> +#define RNGC_ERROR_STATUS_STAT_ERR 0x00000008
>> +
>> +#define RNGC_TIMEOUT 3000000U /* 3 sec */
>> +
>> +struct imx_rngc {
>
> Normally the priv data should have a _priv suffix.
>
>> + unsigned long base;
>> +};
>> +
>> +static int rngc_read(struct udevice *dev, void *data, size_t len)
>> +{
>> + struct imx_rngc *rngc = dev_get_priv(dev);
>
> Normally the var should be called priv
This is described in doc/develop/codingstyle.rst line 192ff.
>
>> + u8 buffer[DCP_RNG_MAX_FIFO_STORE_SIZE];
>> + u32 status, level;
>> + size_t size;
>> +
>> + while (len) {
>> + status = readl(rngc->base + RNGC_STATUS);
>> +
>> + /* is there some error while reading this random number? */
>> + if (status & RNGC_STATUS_ERROR)
>> + break;
>> + /* how many random numbers are in FIFO? [0-16] */
>> + level = (status & RNGC_STATUS_FIFO_LEVEL_MASK) >>
>> + RNGC_STATUS_FIFO_LEVEL_SHIFT;
>> +
>> + if (level) {
>> + /* retrieve a random number from FIFO */
>> + *(u32 *)buffer = readl(rngc->base + RNGC_FIFO);
>> + size = min(len, sizeof(u32));
>> + memcpy(data, buffer, size);
>> + data += size;
>> + len -= size;
>> + }
>> + }
>> +
>> + return len ? -EIO : 0;
>> +}
>> +
>> +static int rngc_init(struct imx_rngc *rngc)
>> +{
>> + u32 cmd, ctrl, status, err_reg = 0;
>> + unsigned long long timeval = 0;
>> + unsigned long long timeout = RNGC_TIMEOUT;
>> +
>> + /* clear error */
>> + cmd = readl(rngc->base + RNGC_COMMAND);
>> + writel(cmd | RNGC_CMD_CLR_ERR, rngc->base + RNGC_COMMAND);
>> +
>> + /* create seed, repeat while there is some statistical error */
>> + do {
>> + /* seed creation */
>> + cmd = readl(rngc->base + RNGC_COMMAND);
>> + writel(cmd | RNGC_CMD_SEED, rngc->base + RNGC_COMMAND);
>> +
>> + udelay(1);
>> + timeval += 1;
As this loop can take rather long, should we call WATCHDOG_RESET()
before and after the loop?
Otherwise looks good to me.
Acked-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
>> +
>> + status = readl(rngc->base + RNGC_STATUS);
>> + err_reg = readl(rngc->base + RNGC_ERROR);
>> +
>> + if (status & (RNGC_STATUS_SEED_DONE | RNGC_STATUS_ST_DONE))
>> + break;
>> +
>> + if (timeval > timeout) {
>> + debug("rngc timed out\n");
>> + return -ETIMEDOUT;
>> + }
>> + } while (err_reg == RNGC_ERROR_STATUS_STAT_ERR);
>> +
>> + if (err_reg)
>> + return -EIO;
>> +
>> + /*
>> + * enable automatic seeding, the rngc creates a new seed automatically
>> + * after serving 2^20 random 160-bit words
>> + */
>> + ctrl = readl(rngc->base + RNGC_CONTROL);
>> + ctrl |= RNGC_CTRL_AUTO_SEED;
>> + writel(ctrl, rngc->base + RNGC_CONTROL);
>
> setbits_le32(rngc->base + RNGC_CONTROL, RNGC_CTRL_AUTO_SEED);
>
>> + return 0;
>> +}
>> +
>> +static int rngc_probe(struct udevice *dev)
>> +{
>> + struct imx_rngc *rngc = dev_get_priv(dev);
>> + fdt_addr_t addr;
>> + u32 ver_id;
>> + u8 rng_type;
>> + int ret;
>> +
>> + addr = dev_read_addr(dev);
>> + if (addr == FDT_ADDR_T_NONE) {
>> + ret = -EINVAL;
>> + goto err;
>> + }
>> +
>> + rngc->base = addr;
>> + ver_id = readl(rngc->base + RNGC_VER_ID);
>> + rng_type = ver_id >> RNGC_TYPE_SHIFT;
>> + /*
>> + * This driver supports only RNGC and RNGB. (There's a different
>> + * driver for RNGA.)
>> + */
>> + if (rng_type != RNGC_TYPE_RNGC && rng_type != RNGC_TYPE_RNGB) {
>> + ret = -ENODEV;
>> + goto err;
>> + }
>> +
>> + ret = rngc_init(rngc);
>> + if (ret)
>> + goto err;
>> +
>> + return 0;
>> +
>> +err:
>> + printf("%s error = %d\n", __func__, ret);
>> + return ret;
>> +}
>> +
>> +static const struct dm_rng_ops rngc_ops = {
>> + .read = rngc_read,
>> +};
>> +
>> +static const struct udevice_id rngc_dt_ids[] = {
>> + { .compatible = "fsl,imx25-rngb" },
>> + { }
>> +};
>> +
>> +U_BOOT_DRIVER(dcp_rng) = {
>> + .name = "dcp_rng",
>> + .id = UCLASS_RNG,
>> + .of_match = rngc_dt_ids,
>> + .ops = &rngc_ops,
>> + .probe = rngc_probe,
>> + .priv_auto = sizeof(struct imx_rngc),
>> + .flags = DM_FLAG_ALLOC_PRIV_DMA,
>> +};
>> --
>> 2.25.1
>>
>
> Regards,
> Simon
More information about the U-Boot
mailing list