From patchwork Tue Dec 24 15:54:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sughosh Ganu X-Patchwork-Id: 1215244 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47j15C0kgdz9sP3 for ; Wed, 25 Dec 2019 02:55:11 +1100 (AEDT) Received: from phobos.denx.de (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 7A2DB815DC; Tue, 24 Dec 2019 16:54:54 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id 78D3F8163F; Tue, 24 Dec 2019 16:54:51 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=SPF_HELO_NONE, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id F39ED801BA for ; Tue, 24 Dec 2019 16:54:46 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=fail smtp.mailfrom=sughosh.ganu@linaro.org Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id E079B1007; Tue, 24 Dec 2019 07:54:45 -0800 (PST) Received: from usa.arm.com (a074948-lin.blr.arm.com [10.162.17.24]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id B88D73F68F; Tue, 24 Dec 2019 07:54:43 -0800 (PST) From: Sughosh Ganu To: u-boot@lists.denx.de Subject: [PATCH 2/3] efi: qemu: arm64: Add efi_rng_protocol implementation for the platform Date: Tue, 24 Dec 2019 21:24:24 +0530 Message-Id: <1577202865-1215-3-git-send-email-sughosh.ganu@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1577202865-1215-1-git-send-email-sughosh.ganu@linaro.org> References: <1577202865-1215-1-git-send-email-sughosh.ganu@linaro.org> X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.26 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tom Rin , Heinrich Schuchardt , Tuomas Tynkkynen , Alexander Graf Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.101.4 at phobos.denx.de X-Virus-Status: Clean Add support for the EFI_RNG_PROTOCOL routines for the qemu arm64 platform. EFI_RNG_PROTOCOL is an uefi boottime service which is invoked by the efi stub in the kernel for getting random seed for kaslr. The routines are platform specific, and use the virtio-rng device on the platform to get random data. The feature can be enabled through the following config CONFIG_EFI_RNG_PROTOCOL Signed-off-by: Sughosh Ganu --- board/emulation/qemu-arm/qemu-arm.c | 50 +++++++++++++++++++++++++ include/efi_rng.h | 34 +++++++++++++++++ lib/efi_loader/Kconfig | 8 ++++ lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_rng.c | 74 +++++++++++++++++++++++++++++++++++++ 5 files changed, 167 insertions(+) create mode 100644 include/efi_rng.h create mode 100644 lib/efi_loader/efi_rng.c diff --git a/board/emulation/qemu-arm/qemu-arm.c b/board/emulation/qemu-arm/qemu-arm.c index e1f4709..3176421 100644 --- a/board/emulation/qemu-arm/qemu-arm.c +++ b/board/emulation/qemu-arm/qemu-arm.c @@ -91,3 +91,53 @@ void *board_fdt_blob_setup(void) /* QEMU loads a generated DTB for us at the start of RAM. */ return (void *)CONFIG_SYS_SDRAM_BASE; } + +#if defined(CONFIG_EFI_RNG_PROTOCOL) +#include +#include + +#include + +#define VIRTIO_RNG_PCI_DEVICE "virtio-pci.l#0" + +void platform_rng_getinfo(efi_rng_algorithm *rng_algo) +{ + const efi_guid_t rng_raw_guid = EFI_RNG_ALGORITHM_RAW; + + guidcpy(rng_algo, &rng_raw_guid); +} + +efi_status_t platform_get_rng_device(struct udevice **dev) +{ + int ret; + efi_status_t status = EFI_DEVICE_ERROR; + struct udevice *bus, *devp; + + for (uclass_first_device(UCLASS_VIRTIO, &bus); bus; + uclass_next_device(&bus)) { + for (device_find_first_child(bus, &devp); devp; device_find_next_child(&devp)) { + if (device_get_uclass_id(devp) == UCLASS_RNG) { + *dev = devp; + status = EFI_SUCCESS; + break; + } + } + } + + if (status != EFI_SUCCESS) { + debug("No rng device found\n"); + return EFI_DEVICE_ERROR; + } + + if (*dev) { + ret = device_probe(*dev); + if (ret) + return EFI_DEVICE_ERROR; + } else { + debug("Couldn't get child device\n"); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} +#endif /* CONFIG_EFI_RNG_PROTOCOL */ diff --git a/include/efi_rng.h b/include/efi_rng.h new file mode 100644 index 0000000..df749dd --- /dev/null +++ b/include/efi_rng.h @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019, Linaro Limited + */ + +#if !defined _EFI_RNG_H_ +#define _EFI_RNG_H_ + +#include +#include + +#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) + +typedef efi_guid_t efi_rng_algorithm; + +struct efi_rng_protocol { + efi_status_t (EFIAPI *getinfo)(struct efi_rng_protocol *this, + efi_uintn_t *rng_algo_size, + efi_rng_algorithm *rng_algo); + efi_status_t (EFIAPI *getrng)(struct efi_rng_protocol *this, + efi_rng_algorithm *rng_algo, + efi_uintn_t rng_len, uint8_t *rng_data); +}; + +void platform_rng_getinfo(efi_rng_algorithm *rng_algo); +efi_status_t platform_get_rng_device(struct udevice **dev); + +#endif /* _EFI_RNG_H_ */ diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 21ef440..7437442 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -120,4 +120,12 @@ config EFI_GRUB_ARM32_WORKAROUND GRUB prior to version 2.04 requires U-Boot to disable caches. This workaround currently is also needed on systems with caches that cannot be managed via CP15. + +config EFI_RNG_PROTOCOL + bool "EFI_RNG_PROTOCOL support" + depends on DM_RNG && TARGET_QEMU_ARM_64BIT + help + "Support for EFI_RNG_PROTOCOL implementation. Uses the rng + device on the platform" + endif diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 7db4060..04dc864 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -42,3 +42,4 @@ obj-$(CONFIG_PARTITIONS) += efi_disk.o obj-$(CONFIG_NET) += efi_net.o obj-$(CONFIG_GENERATE_ACPI_TABLE) += efi_acpi.o obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o +obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_rng.o diff --git a/lib/efi_loader/efi_rng.c b/lib/efi_loader/efi_rng.c new file mode 100644 index 0000000..8456592 --- /dev/null +++ b/lib/efi_loader/efi_rng.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static efi_status_t EFIAPI rng_getinfo(struct efi_rng_protocol *this, + efi_uintn_t *rng_algo_size, + efi_rng_algorithm *rng_algo) +{ + if (!this || !rng_algo_size || !rng_algo) + return EFI_INVALID_PARAMETER; + + if (*rng_algo_size < sizeof(*rng_algo)) { + *rng_algo_size = sizeof(*rng_algo); + return EFI_BUFFER_TOO_SMALL; + } + + *rng_algo_size = sizeof(*rng_algo); + platform_rng_getinfo(rng_algo); + + return EFI_SUCCESS; +} + +static efi_status_t EFIAPI getrng(struct efi_rng_protocol *protocol, + efi_rng_algorithm *rng_algo, + efi_uintn_t rng_len, uint8_t *rng_data) +{ + int ret; + struct udevice *dev; + const efi_guid_t rng_raw_guid = EFI_RNG_ALGORITHM_RAW; + + /* + * Booting into the linux kernel mangles + * x18, which holds the gd. + * When the efi stub in the kernel invokes + * the GetRng routine, gd needs to be + * restored back, without which bad things + * happen + */ + efi_restore_gd(); + + if (!protocol || !rng_data || !rng_len) + return EFI_INVALID_PARAMETER; + + if (rng_algo) { + if (guidcmp(rng_algo, &rng_raw_guid)) + return EFI_UNSUPPORTED; + } + + ret = platform_get_rng_device(&dev); + if (ret != EFI_SUCCESS) + return EFI_DEVICE_ERROR; + + ret = dm_rng_read(dev, rng_data, rng_len); + if (ret < 0) { + debug("Rng device read failed\n"); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +const struct efi_rng_protocol efi_rng_protocol_ops = { + .getinfo = rng_getinfo, + .getrng = getrng, +};