summaryrefslogtreecommitdiffstats
path: root/drivers/hw_random/efi-rng.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hw_random/efi-rng.c')
-rw-r--r--drivers/hw_random/efi-rng.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/hw_random/efi-rng.c b/drivers/hw_random/efi-rng.c
new file mode 100644
index 0000000000..61cb01caf6
--- /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.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);