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@xxxxxxxxxxxxxx> --- 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