[PATCH 3/5] hw_random: add EFI RNG driver

Ahmad Fatoum a.fatoum at pengutronix.de
Sun Oct 9 23:08:40 PDT 2022


The EFI_RNG_PROTOCOL_GUID is quite simple and as such was a good first
protocol to implement for the barebox EFI loader support. We don't yet
have a payload-side driver making use of it though, so add that here.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 common/efi/guid.c           |  1 +
 drivers/hw_random/Kconfig   |  7 +++++
 drivers/hw_random/Makefile  |  1 +
 drivers/hw_random/efi-rng.c | 53 +++++++++++++++++++++++++++++++++++++
 include/efi.h               | 18 +++++++++++++
 5 files changed, 80 insertions(+)
 create mode 100644 drivers/hw_random/efi-rng.c

diff --git a/common/efi/guid.c b/common/efi/guid.c
index f16c597a20fc..93418d57b469 100644
--- a/common/efi/guid.c
+++ b/common/efi/guid.c
@@ -11,6 +11,7 @@ efi_guid_t efi_unknown_device_guid = EFI_UNKNOWN_DEVICE_GUID;
 efi_guid_t efi_null_guid = EFI_NULL_GUID;
 efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
 efi_guid_t efi_block_io_protocol_guid = EFI_BLOCK_IO_PROTOCOL_GUID;
+efi_guid_t efi_rng_protocol_guid = EFI_RNG_PROTOCOL_GUID;
 efi_guid_t efi_barebox_vendor_guid = EFI_BAREBOX_VENDOR_GUID;
 efi_guid_t efi_systemd_vendor_guid = EFI_SYSTEMD_VENDOR_GUID;
 
diff --git a/drivers/hw_random/Kconfig b/drivers/hw_random/Kconfig
index 32b84b028b0e..bf86240623c4 100644
--- a/drivers/hw_random/Kconfig
+++ b/drivers/hw_random/Kconfig
@@ -44,4 +44,11 @@ config HW_RANDOM_STARFIVE
 	  This driver provides barebox support for the Random Number
 	  Generator hardware found on the StarFive family of SoCs.
 
+config HW_RANDOM_EFI
+	tristate "EFI Random Number Generator"
+	depends on EFI
+	help
+	  This driver provides barebox support for the Random Number
+	  Generator Protocol offered by EFI firmware
+
 endif
diff --git a/drivers/hw_random/Makefile b/drivers/hw_random/Makefile
index 6fe21bb84c28..9ea064340916 100644
--- a/drivers/hw_random/Makefile
+++ b/drivers/hw_random/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_HWRNG_STM32) += stm32-rng.o
 obj-$(CONFIG_HWRNG_DEV_RANDOM) += dev-random.o
 obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
 obj-$(CONFIG_HW_RANDOM_STARFIVE) += starfive-vic-rng.o
+obj-$(CONFIG_HW_RANDOM_EFI) += efi-rng.o
diff --git a/drivers/hw_random/efi-rng.c b/drivers/hw_random/efi-rng.c
new file mode 100644
index 000000000000..b74075e3a4ac
--- /dev/null
+++ b/drivers/hw_random/efi-rng.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <linux/hw_random.h>
+#include <efi/efi-util.h>
+#include <efi/efi-device.h>
+
+struct efi_rng_priv {
+	struct efi_rng_protocol *protocol;
+	struct hwrng hwrng;
+};
+
+static inline struct efi_rng_priv *to_efi_rng(struct hwrng *hwrng)
+{
+	return container_of(hwrng, struct efi_rng_priv, hwrng);
+}
+
+static int efi_rng_read(struct hwrng *hwrng, void *data, size_t len, bool wait)
+{
+	struct efi_rng_protocol *protocol = to_efi_rng(hwrng)->protocol;
+	efi_status_t efiret;
+
+	efiret = protocol->get_rng(protocol, NULL, len, data);
+
+	return -efi_errno(efiret) ?: len;
+}
+
+static int efi_rng_probe(struct efi_device *efidev)
+{
+	struct efi_rng_priv *priv;
+
+	priv = xzalloc(sizeof(*priv));
+
+	BS->handle_protocol(efidev->handle, &efi_rng_protocol_guid,
+			(void **)&priv->protocol);
+	if (!priv->protocol)
+		return -ENODEV;
+
+	priv->hwrng.name = dev_name(&efidev->dev);
+	priv->hwrng.read = efi_rng_read;
+
+	return hwrng_register(&efidev->dev, &priv->hwrng);
+}
+
+static struct efi_driver efi_rng_driver = {
+        .driver = {
+		.name  = "efi-rng",
+	},
+        .probe = efi_rng_probe,
+	.guid = EFI_RNG_PROTOCOL_GUID,
+};
+device_efi_driver(efi_rng_driver);
diff --git a/include/efi.h b/include/efi.h
index 864158259c53..149c4e74c6cb 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -538,6 +538,7 @@ extern efi_guid_t efi_unknown_device_guid;
 extern efi_guid_t efi_null_guid;
 extern efi_guid_t efi_global_variable_guid;
 extern efi_guid_t efi_block_io_protocol_guid;
+extern efi_guid_t efi_rng_protocol_guid;
 extern efi_guid_t efi_barebox_vendor_guid;
 extern efi_guid_t efi_systemd_vendor_guid;
 
@@ -691,4 +692,21 @@ char *device_path_to_partuuid(struct efi_device_path *dev_path);
 
 const char *efi_guid_string(efi_guid_t *g);
 
+#define EFI_RNG_PROTOCOL_GUID \
+	EFI_GUID(0x3152bca5, 0xeade, 0x433d, 0x86, 0x2e, \
+		 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44)
+
+#define EFI_RNG_ALGORITHM_RAW \
+	EFI_GUID(0xe43176d7, 0xb6e8, 0x4827, 0xb7, 0x84, \
+		 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61)
+
+struct efi_rng_protocol {
+	efi_status_t (EFIAPI *get_info)(struct efi_rng_protocol *protocol,
+					size_t *rng_algorithm_list_size,
+					efi_guid_t *rng_algorithm_list);
+	efi_status_t (EFIAPI *get_rng)(struct efi_rng_protocol *protocol,
+				       efi_guid_t *rng_algorithm,
+				       size_t rng_value_length, uint8_t *rng_value);
+};
+
 #endif /* _LINUX_EFI_H */
-- 
2.30.2




More information about the barebox mailing list