1205859Sjoel// SPDX-License-Identifier: GPL-2.0+
2162886Snetchild/*
3159687Snetchild * The 'rng' command prints bytes from the hardware random number generator.
4159687Snetchild *
5159687Snetchild * Copyright (c) 2019, Heinrich Schuchardt <xypron.glpk@gmx.de>
6159687Snetchild */
7159687Snetchild#include <common.h>
8159687Snetchild#include <command.h>
9159687Snetchild#include <dm.h>
10159687Snetchild#include <hexdump.h>
11159687Snetchild#include <malloc.h>
12159687Snetchild#include <rng.h>
13159687Snetchild
14159687Snetchildstatic int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
15159687Snetchild{
16159687Snetchild	size_t n;
17159687Snetchild	u8 buf[64];
18159687Snetchild	int devnum;
19159687Snetchild	struct udevice *dev;
20159687Snetchild	int ret = CMD_RET_SUCCESS, err;
21159687Snetchild
22159687Snetchild	if (argc == 2 && !strcmp(argv[1], "list")) {
23159687Snetchild		int idx = 0;
24159687Snetchild
25159687Snetchild		uclass_foreach_dev_probe(UCLASS_RNG, dev) {
26159687Snetchild			idx++;
27159687Snetchild			printf("RNG #%d - %s\n", dev->seq_, dev->name);
28159687Snetchild		}
29159687Snetchild
30159687Snetchild		if (!idx) {
31159687Snetchild			log_err("No RNG device\n");
32159687Snetchild			return CMD_RET_FAILURE;
33159687Snetchild		}
34159687Snetchild
35162886Snetchild		return CMD_RET_SUCCESS;
36159687Snetchild	}
37162886Snetchild
38162886Snetchild	switch (argc) {
39159687Snetchild	case 1:
40159687Snetchild		devnum = 0;
41159687Snetchild		n = 0x40;
42162886Snetchild		break;
43162886Snetchild	case 2:
44159687Snetchild		devnum = hextoul(argv[1], NULL);
45162886Snetchild		n = 0x40;
46162886Snetchild		break;
47159687Snetchild	case 3:
48162886Snetchild		devnum = hextoul(argv[1], NULL);
49162886Snetchild		n = hextoul(argv[2], NULL);
50162886Snetchild		break;
51162886Snetchild	default:
52162886Snetchild		return CMD_RET_USAGE;
53162886Snetchild	}
54162886Snetchild
55162886Snetchild	if (uclass_get_device_by_seq(UCLASS_RNG, devnum, &dev) || !dev) {
56159687Snetchild		printf("No RNG device\n");
57162886Snetchild		return CMD_RET_FAILURE;
58162886Snetchild	}
59162886Snetchild
60159687Snetchild	if (!n)
61162886Snetchild		return 0;
62162886Snetchild
63162886Snetchild	n = min(n, sizeof(buf));
64162886Snetchild
65162886Snetchild	err = dm_rng_read(dev, buf, n);
66162886Snetchild	if (err) {
67162886Snetchild		puts(err == -EINTR ? "Abort\n" : "Reading RNG failed\n");
68162886Snetchild		ret = CMD_RET_FAILURE;
69159687Snetchild	} else {
70162886Snetchild		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, n);
71162886Snetchild	}
72162886Snetchild
73159687Snetchild	return ret;
74162886Snetchild}
75162886Snetchild
76162886SnetchildU_BOOT_CMD(
77162886Snetchild	rng, 3, 0, do_rng,
78162886Snetchild	"print bytes from the hardware random number generator",
79162886Snetchild	"list         - list all the probed rng devices\n"
80162886Snetchild	"rng [dev] [n]    - print n random bytes(max 64) read from dev\n"
81162886Snetchild);
82162886Snetchild