EFI_RNG_PROTOCOL with a TPM
This commit is contained in:
Tom Rini 2022-08-05 08:01:32 -04:00
commit 46b5c8ed01
13 changed files with 213 additions and 82 deletions

View File

@ -1964,6 +1964,7 @@ config CMD_GETTIME
config CMD_RNG config CMD_RNG
bool "rng command" bool "rng command"
depends on DM_RNG depends on DM_RNG
default y if SANDBOX
select HEXDUMP select HEXDUMP
help help
Print bytes from the hardware random number generator. Print bytes from the hardware random number generator.

View File

@ -13,24 +13,38 @@
static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{ {
size_t n = 0x40; size_t n;
u8 buf[64];
int devnum;
struct udevice *dev; struct udevice *dev;
void *buf;
int ret = CMD_RET_SUCCESS; int ret = CMD_RET_SUCCESS;
if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) { switch (argc) {
case 1:
devnum = 0;
n = 0x40;
break;
case 2:
devnum = hextoul(argv[1], NULL);
n = 0x40;
break;
case 3:
devnum = hextoul(argv[1], NULL);
n = hextoul(argv[2], NULL);
break;
default:
return CMD_RET_USAGE;
}
if (uclass_get_device_by_seq(UCLASS_RNG, devnum, &dev) || !dev) {
printf("No RNG device\n"); printf("No RNG device\n");
return CMD_RET_FAILURE; return CMD_RET_FAILURE;
} }
if (argc >= 2) if (!n)
n = hextoul(argv[1], NULL); return 0;
buf = malloc(n); n = min(n, sizeof(buf));
if (!buf) {
printf("Out of memory\n");
return CMD_RET_FAILURE;
}
if (dm_rng_read(dev, buf, n)) { if (dm_rng_read(dev, buf, n)) {
printf("Reading RNG failed\n"); printf("Reading RNG failed\n");
@ -39,19 +53,17 @@ static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, n); print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, n);
} }
free(buf);
return ret; return ret;
} }
#ifdef CONFIG_SYS_LONGHELP #ifdef CONFIG_SYS_LONGHELP
static char rng_help_text[] = static char rng_help_text[] =
"[n]\n" "[dev [n]]\n"
" - print n random bytes\n"; " - print n random bytes(max 64) read from dev\n";
#endif #endif
U_BOOT_CMD( U_BOOT_CMD(
rng, 2, 0, do_rng, rng, 3, 0, do_rng,
"print bytes from the hardware random number generator", "print bytes from the hardware random number generator",
rng_help_text rng_help_text
); );

26
doc/usage/cmd/rng.rst Normal file
View File

@ -0,0 +1,26 @@
.. SPDX-License-Identifier: GPL-2.0+
rng command
===========
Synopsis
--------
::
rng [devnum [n]]
Description
-----------
The *rng* command reads the random number generator(RNG) device and
prints the random bytes read on the console. A maximum of 64 bytes can
be read in one invocation of the command.
devnum
The RNG device from which the random bytes are to be
read. Defaults to 0.
n
Number of random bytes to be read and displayed on the
console. Default value is 0x40. Max value is 0x40.

View File

@ -56,6 +56,7 @@ Shell commands
cmd/pstore cmd/pstore
cmd/qfw cmd/qfw
cmd/reset cmd/reset
cmd/rng
cmd/sbi cmd/sbi
cmd/sf cmd/sf
cmd/scp03 cmd/scp03

View File

@ -74,4 +74,13 @@ config RNG_SMCCC_TRNG
Enable random number generator for platforms that support Arm Enable random number generator for platforms that support Arm
SMCCC TRNG interface. SMCCC TRNG interface.
config TPM_RNG
bool "Enable random number generator on TPM device"
depends on TPM
default y
help
The TPM device has an inbuilt random number generator
functionality. Enable random number generator on TPM
devices.
endif endif

View File

@ -13,3 +13,4 @@ obj-$(CONFIG_RNG_STM32MP1) += stm32mp1_rng.o
obj-$(CONFIG_RNG_ROCKCHIP) += rockchip_rng.o obj-$(CONFIG_RNG_ROCKCHIP) += rockchip_rng.o
obj-$(CONFIG_RNG_IPROC200) += iproc_rng200.o obj-$(CONFIG_RNG_IPROC200) += iproc_rng200.o
obj-$(CONFIG_RNG_SMCCC_TRNG) += smccc_trng.o obj-$(CONFIG_RNG_SMCCC_TRNG) += smccc_trng.o
obj-$(CONFIG_TPM_RNG) += tpm_rng.o

23
drivers/rng/tpm_rng.c Normal file
View File

@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2022, Linaro Limited
*/
#include <dm.h>
#include <rng.h>
#include <tpm_api.h>
static int rng_tpm_random_read(struct udevice *dev, void *data, size_t count)
{
return tpm_get_random(dev_get_parent(dev), data, count);
}
static const struct dm_rng_ops tpm_rng_ops = {
.read = rng_tpm_random_read,
};
U_BOOT_DRIVER(tpm_rng) = {
.name = "tpm-rng",
.id = UCLASS_RNG,
.ops = &tpm_rng_ops,
};

View File

@ -9,12 +9,16 @@
#include <common.h> #include <common.h>
#include <dm.h> #include <dm.h>
#include <log.h> #include <log.h>
#include <linux/delay.h> #include <tpm_api.h>
#include <linux/unaligned/be_byteshift.h>
#include <tpm-v1.h> #include <tpm-v1.h>
#include <tpm-v2.h> #include <tpm-v2.h>
#include <dm/lists.h>
#include <linux/delay.h>
#include <linux/unaligned/be_byteshift.h>
#include "tpm_internal.h" #include "tpm_internal.h"
#define TPM_RNG_DRV_NAME "tpm-rng"
int tpm_open(struct udevice *dev) int tpm_open(struct udevice *dev)
{ {
struct tpm_ops *ops = tpm_get_ops(dev); struct tpm_ops *ops = tpm_get_ops(dev);
@ -136,6 +140,29 @@ int tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, size_t send_size,
return 0; return 0;
} }
static int tpm_uclass_post_probe(struct udevice *dev)
{
int ret;
const char *drv = TPM_RNG_DRV_NAME;
struct udevice *child;
if (CONFIG_IS_ENABLED(TPM_RNG)) {
ret = device_find_first_child_by_uclass(dev, UCLASS_RNG,
&child);
if (ret != -ENODEV) {
log_debug("RNG child already added to the TPM device\n");
return ret;
}
ret = device_bind_driver(dev, drv, TPM_RNG_DRV_NAME, &child);
if (ret)
return log_msg_ret("bind", ret);
}
return 0;
}
UCLASS_DRIVER(tpm) = { UCLASS_DRIVER(tpm) = {
.id = UCLASS_TPM, .id = UCLASS_TPM,
.name = "tpm", .name = "tpm",
@ -143,5 +170,6 @@ UCLASS_DRIVER(tpm) = {
#if CONFIG_IS_ENABLED(OF_REAL) #if CONFIG_IS_ENABLED(OF_REAL)
.post_bind = dm_scan_fdt_dev, .post_bind = dm_scan_fdt_dev,
#endif #endif
.post_probe = tpm_uclass_post_probe,
.per_device_auto = sizeof(struct tpm_chip_priv), .per_device_auto = sizeof(struct tpm_chip_priv),
}; };

View File

@ -319,4 +319,14 @@ u32 tpm_write_lock(struct udevice *dev, u32 index);
*/ */
u32 tpm_resume(struct udevice *dev); u32 tpm_resume(struct udevice *dev);
static inline bool tpm_is_v1(struct udevice *dev)
{
return IS_ENABLED(CONFIG_TPM_V1) && tpm_get_version(dev) == TPM_V1;
}
static inline bool tpm_is_v2(struct udevice *dev)
{
return IS_ENABLED(CONFIG_TPM_V2) && tpm_get_version(dev) == TPM_V2;
}
#endif /* __TPM_API_H */ #endif /* __TPM_API_H */

View File

@ -360,6 +360,7 @@ source lib/crypt/Kconfig
config TPM config TPM
bool "Trusted Platform Module (TPM) Support" bool "Trusted Platform Module (TPM) Support"
depends on DM depends on DM
imply DM_RNG
help help
This enables support for TPMs which can be used to provide security This enables support for TPMs which can be used to provide security
features for your board. The TPM can be connected via LPC or I2C features for your board. The TPM can be connected via LPC or I2C

View File

@ -246,13 +246,6 @@ efi_status_t efi_init_obj_list(void)
/* Set up console modes */ /* Set up console modes */
efi_setup_console_size(); efi_setup_console_size();
/* Install EFI_RNG_PROTOCOL */
if (IS_ENABLED(CONFIG_EFI_RNG_PROTOCOL)) {
ret = efi_rng_register();
if (ret != EFI_SUCCESS)
goto out;
}
/* Initialize variable services */ /* Initialize variable services */
ret = efi_init_variables(); ret = efi_init_variables();
if (ret != EFI_SUCCESS) if (ret != EFI_SUCCESS)
@ -289,6 +282,13 @@ efi_status_t efi_init_obj_list(void)
goto out; goto out;
} }
/* Install EFI_RNG_PROTOCOL */
if (IS_ENABLED(CONFIG_EFI_RNG_PROTOCOL)) {
ret = efi_rng_register();
if (ret != EFI_SUCCESS)
goto out;
}
if (IS_ENABLED(CONFIG_EFI_RISCV_BOOT_PROTOCOL)) { if (IS_ENABLED(CONFIG_EFI_RISCV_BOOT_PROTOCOL)) {
ret = efi_riscv_register(); ret = efi_riscv_register();
if (ret != EFI_SUCCESS) if (ret != EFI_SUCCESS)

View File

@ -11,21 +11,11 @@
#include <tpm-v2.h> #include <tpm-v2.h>
#include <tpm_api.h> #include <tpm_api.h>
static bool is_tpm1(struct udevice *dev)
{
return IS_ENABLED(CONFIG_TPM_V1) && tpm_get_version(dev) == TPM_V1;
}
static bool is_tpm2(struct udevice *dev)
{
return IS_ENABLED(CONFIG_TPM_V2) && tpm_get_version(dev) == TPM_V2;
}
u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode) u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
{ {
if (is_tpm1(dev)) { if (tpm_is_v1(dev)) {
return tpm1_startup(dev, mode); return tpm1_startup(dev, mode);
} else if (is_tpm2(dev)) { } else if (tpm_is_v2(dev)) {
enum tpm2_startup_types type; enum tpm2_startup_types type;
switch (mode) { switch (mode) {
@ -47,9 +37,9 @@ u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
u32 tpm_resume(struct udevice *dev) u32 tpm_resume(struct udevice *dev)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_startup(dev, TPM_ST_STATE); return tpm1_startup(dev, TPM_ST_STATE);
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return tpm2_startup(dev, TPM2_SU_STATE); return tpm2_startup(dev, TPM2_SU_STATE);
else else
return -ENOSYS; return -ENOSYS;
@ -57,9 +47,9 @@ u32 tpm_resume(struct udevice *dev)
u32 tpm_self_test_full(struct udevice *dev) u32 tpm_self_test_full(struct udevice *dev)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_self_test_full(dev); return tpm1_self_test_full(dev);
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return tpm2_self_test(dev, TPMI_YES); return tpm2_self_test(dev, TPMI_YES);
else else
return -ENOSYS; return -ENOSYS;
@ -67,9 +57,9 @@ u32 tpm_self_test_full(struct udevice *dev)
u32 tpm_continue_self_test(struct udevice *dev) u32 tpm_continue_self_test(struct udevice *dev)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_continue_self_test(dev); return tpm1_continue_self_test(dev);
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return tpm2_self_test(dev, TPMI_NO); return tpm2_self_test(dev, TPMI_NO);
else else
return -ENOSYS; return -ENOSYS;
@ -86,7 +76,7 @@ u32 tpm_clear_and_reenable(struct udevice *dev)
return ret; return ret;
} }
if (is_tpm1(dev)) { if (tpm_is_v1(dev)) {
ret = tpm1_physical_enable(dev); ret = tpm1_physical_enable(dev);
if (ret != TPM_SUCCESS) { if (ret != TPM_SUCCESS) {
log_err("TPM: Can't set enabled state\n"); log_err("TPM: Can't set enabled state\n");
@ -105,9 +95,9 @@ u32 tpm_clear_and_reenable(struct udevice *dev)
u32 tpm_nv_enable_locking(struct udevice *dev) u32 tpm_nv_enable_locking(struct udevice *dev)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0); return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return -ENOSYS; return -ENOSYS;
else else
return -ENOSYS; return -ENOSYS;
@ -115,9 +105,9 @@ u32 tpm_nv_enable_locking(struct udevice *dev)
u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count) u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_nv_read_value(dev, index, data, count); return tpm1_nv_read_value(dev, index, data, count);
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return tpm2_nv_read_value(dev, index, data, count); return tpm2_nv_read_value(dev, index, data, count);
else else
return -ENOSYS; return -ENOSYS;
@ -126,9 +116,9 @@ u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data, u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
u32 count) u32 count)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_nv_write_value(dev, index, data, count); return tpm1_nv_write_value(dev, index, data, count);
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return tpm2_nv_write_value(dev, index, data, count); return tpm2_nv_write_value(dev, index, data, count);
else else
return -ENOSYS; return -ENOSYS;
@ -141,9 +131,9 @@ u32 tpm_set_global_lock(struct udevice *dev)
u32 tpm_write_lock(struct udevice *dev, u32 index) u32 tpm_write_lock(struct udevice *dev, u32 index)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return -ENOSYS; return -ENOSYS;
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return tpm2_write_lock(dev, index); return tpm2_write_lock(dev, index);
else else
return -ENOSYS; return -ENOSYS;
@ -152,9 +142,9 @@ u32 tpm_write_lock(struct udevice *dev, u32 index)
u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest, u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
void *out_digest) void *out_digest)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_extend(dev, index, in_digest, out_digest); return tpm1_extend(dev, index, in_digest, out_digest);
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return tpm2_pcr_extend(dev, index, TPM2_ALG_SHA256, in_digest, return tpm2_pcr_extend(dev, index, TPM2_ALG_SHA256, in_digest,
TPM2_DIGEST_LEN); TPM2_DIGEST_LEN);
else else
@ -163,9 +153,9 @@ u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest,
u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count) u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_pcr_read(dev, index, data, count); return tpm1_pcr_read(dev, index, data, count);
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return -ENOSYS; return -ENOSYS;
else else
return -ENOSYS; return -ENOSYS;
@ -173,14 +163,14 @@ u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence) u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_tsc_physical_presence(dev, presence); return tpm1_tsc_physical_presence(dev, presence);
/* /*
* Nothing to do on TPM2 for this; use platform hierarchy availability * Nothing to do on TPM2 for this; use platform hierarchy availability
* instead. * instead.
*/ */
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return 0; return 0;
else else
return -ENOSYS; return -ENOSYS;
@ -188,11 +178,11 @@ u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
u32 tpm_finalise_physical_presence(struct udevice *dev) u32 tpm_finalise_physical_presence(struct udevice *dev)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_finalise_physical_presence(dev); return tpm1_finalise_physical_presence(dev);
/* Nothing needs to be done with tpm2 */ /* Nothing needs to be done with tpm2 */
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return 0; return 0;
else else
return -ENOSYS; return -ENOSYS;
@ -200,9 +190,9 @@ u32 tpm_finalise_physical_presence(struct udevice *dev)
u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count) u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_read_pubek(dev, data, count); return tpm1_read_pubek(dev, data, count);
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return -ENOSYS; /* not implemented yet */ return -ENOSYS; /* not implemented yet */
else else
return -ENOSYS; return -ENOSYS;
@ -210,9 +200,9 @@ u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
u32 tpm_force_clear(struct udevice *dev) u32 tpm_force_clear(struct udevice *dev)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_force_clear(dev); return tpm1_force_clear(dev);
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return tpm2_clear(dev, TPM2_RH_PLATFORM, NULL, 0); return tpm2_clear(dev, TPM2_RH_PLATFORM, NULL, 0);
else else
return -ENOSYS; return -ENOSYS;
@ -220,11 +210,11 @@ u32 tpm_force_clear(struct udevice *dev)
u32 tpm_physical_enable(struct udevice *dev) u32 tpm_physical_enable(struct udevice *dev)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_physical_enable(dev); return tpm1_physical_enable(dev);
/* Nothing needs to be done with tpm2 */ /* Nothing needs to be done with tpm2 */
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return 0; return 0;
else else
return -ENOSYS; return -ENOSYS;
@ -232,11 +222,11 @@ u32 tpm_physical_enable(struct udevice *dev)
u32 tpm_physical_disable(struct udevice *dev) u32 tpm_physical_disable(struct udevice *dev)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_physical_disable(dev); return tpm1_physical_disable(dev);
/* Nothing needs to be done with tpm2 */ /* Nothing needs to be done with tpm2 */
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return 0; return 0;
else else
return -ENOSYS; return -ENOSYS;
@ -244,10 +234,10 @@ u32 tpm_physical_disable(struct udevice *dev)
u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state) u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_physical_set_deactivated(dev, state); return tpm1_physical_set_deactivated(dev, state);
/* Nothing needs to be done with tpm2 */ /* Nothing needs to be done with tpm2 */
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return 0; return 0;
else else
return -ENOSYS; return -ENOSYS;
@ -256,9 +246,9 @@ u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap, u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
void *cap, size_t count) void *cap, size_t count)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_get_capability(dev, cap_area, sub_cap, cap, count); return tpm1_get_capability(dev, cap_area, sub_cap, cap, count);
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return tpm2_get_capability(dev, cap_area, sub_cap, cap, count); return tpm2_get_capability(dev, cap_area, sub_cap, cap, count);
else else
return -ENOSYS; return -ENOSYS;
@ -266,9 +256,9 @@ u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm) u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_get_permissions(dev, index, perm); return tpm1_get_permissions(dev, index, perm);
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return -ENOSYS; /* not implemented yet */ return -ENOSYS; /* not implemented yet */
else else
return -ENOSYS; return -ENOSYS;
@ -276,10 +266,10 @@ u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
u32 tpm_get_random(struct udevice *dev, void *data, u32 count) u32 tpm_get_random(struct udevice *dev, void *data, u32 count)
{ {
if (is_tpm1(dev)) if (tpm_is_v1(dev))
return tpm1_get_random(dev, data, count); return tpm1_get_random(dev, data, count);
else if (is_tpm2(dev)) else if (tpm_is_v2(dev))
return -ENOSYS; /* not implemented yet */ return tpm2_get_random(dev, data, count);
else
return -ENOSYS; return -ENOSYS;
} }

View File

@ -25,3 +25,32 @@ static int dm_test_rng_read(struct unit_test_state *uts)
return 0; return 0;
} }
DM_TEST(dm_test_rng_read, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); DM_TEST(dm_test_rng_read, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
/* Test the rng command */
static int dm_test_rng_cmd(struct unit_test_state *uts)
{
struct udevice *dev;
ut_assertok(uclass_get_device(UCLASS_RNG, 0, &dev));
ut_assertnonnull(dev);
ut_assertok(console_record_reset_enable());
run_command("rng", 0);
ut_assert_nextlinen("00000000:");
ut_assert_nextlinen("00000010:");
ut_assert_nextlinen("00000020:");
ut_assert_nextlinen("00000030:");
ut_assert_console_end();
run_command("rng 0 10", 0);
ut_assert_nextlinen("00000000:");
ut_assert_console_end();
run_command("rng 20", 0);
ut_assert_nextlinen("No RNG device");
ut_assert_console_end();
return 0;
}
DM_TEST(dm_test_rng_cmd, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);