From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Add an implementation of EFI_RNG_PROTOCOL so that the OS loader has
access to entropy for KASLR and other purposes (i.e., seeding the OS's
entropy pool very early on).
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
---
Platform/Marvell/Armada/Armada.dsc.inc | 4 +
Platform/Marvell/Armada/Armada70x0.fdf | 1 +
Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.c | 255 ++++++++++++++++++++
Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.inf | 47 ++++
Platform/Marvell/Marvell.dec | 3 +
5 files changed, 310 insertions(+)
diff --git a/Platform/Marvell/Armada/Armada.dsc.inc b/Platform/Marvell/Armada/Armada.dsc.inc
index 1aa485c..ec24d76 100644
--- a/Platform/Marvell/Armada/Armada.dsc.inc
+++ b/Platform/Marvell/Armada/Armada.dsc.inc
@@ -364,6 +364,9 @@
gArmTokenSpaceGuid.PcdSystemMemorySize|0x40000000
gArmTokenSpaceGuid.PcdArmScr|0x531
+ # TRNG
+ gMarvellTokenSpaceGuid.PcdEip76TrngBaseAddress|0xF2760000
+
################################################################################
#
# Components Section - list of all EDK II Modules needed by this Platform
@@ -400,6 +403,7 @@
Platform/Marvell/Drivers/I2c/Devices/MvEeprom/MvEeprom.inf
Platform/Marvell/Drivers/Spi/MvSpiDxe.inf
Platform/Marvell/Drivers/Spi/Devices/MvSpiFlash.inf
+ Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.inf
# Network support
MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf
diff --git a/Platform/Marvell/Armada/Armada70x0.fdf b/Platform/Marvell/Armada/Armada70x0.fdf
index 933c3ed..a94a9ff 100644
--- a/Platform/Marvell/Armada/Armada70x0.fdf
+++ b/Platform/Marvell/Armada/Armada70x0.fdf
@@ -113,6 +113,7 @@ FvNameGuid = 5eda4200-2c5f-43cb-9da3-0baf74b1b30c
INF Platform/Marvell/Drivers/I2c/Devices/MvEeprom/MvEeprom.inf
INF Platform/Marvell/Drivers/Spi/MvSpiDxe.inf
INF Platform/Marvell/Drivers/Spi/Devices/MvSpiFlash.inf
+ INF Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.inf
# Network support
INF MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf
diff --git a/Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.c b/Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.c
new file mode 100644
index 0000000..014443d
--- /dev/null
+++ b/Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.c
@@ -0,0 +1,255 @@
+/** @file
+
+ This driver produces an EFI_RNG_PROTOCOL instance for the Armada 70x0 TRNG
+
+ Copyright (C) 2017, Linaro Ltd. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/Rng.h>
+
+#define TRNG_OUTPUT_REG mTrngBaseAddress
+#define TRNG_OUTPUT_SIZE 0x10
+
+#define TRNG_STATUS_REG (mTrngBaseAddress + 0x10)
+#define TRNG_STATUS_READY BIT0
+
+#define TRNG_INTACK_REG (mTrngBaseAddress + 0x10)
+#define TRNG_INTACK_READY BIT0
+
+#define TRNG_CONTROL_REG (mTrngBaseAddress + 0x14)
+#define TRNG_CONTROL_REG_ENABLE BIT10
+
+#define TRNG_CONFIG_REG (mTrngBaseAddress + 0x18)
+#define __MIN_REFILL_SHIFT 0
+#define __MAX_REFILL_SHIFT 16
+#define TRNG_CONFIG_MIN_REFILL_CYCLES (0x05 << __MIN_REFILL_SHIFT)
+#define TRNG_CONFIG_MAX_REFILL_CYCLES (0x22 << __MAX_REFILL_SHIFT)
+
+#define TRNG_FRODETUNE_REG (mTrngBaseAddress + 0x24)
+#define TRNG_FRODETUNE_MASK 0x0
+
+#define TRNG_FROENABLE_REG (mTrngBaseAddress + 0x20)
+#define TRNG_FROENABLE_MASK 0xffffff
+
+#define TRNG_MAX_RETRIES 20
+
+STATIC EFI_PHYSICAL_ADDRESS mTrngBaseAddress;
+
+/**
+ Returns information about the random number generation implementation.
+
+ @param[in] This A pointer to the EFI_RNG_PROTOCOL
+ instance.
+ @param[in,out] RNGAlgorithmListSize On input, the size in bytes of
+ RNGAlgorithmList.
+ On output with a return code of
+ EFI_SUCCESS, the size in bytes of the
+ data returned in RNGAlgorithmList. On
+ output with a return code of
+ EFI_BUFFER_TOO_SMALL, the size of
+ RNGAlgorithmList required to obtain the
+ list.
+ @param[out] RNGAlgorithmList A caller-allocated memory buffer filled
+ by the driver with one EFI_RNG_ALGORITHM
+ element for each supported RNG algorithm.
+ The list must not change across multiple
+ calls to the same driver. The first
+ algorithm in the list is the default
+ algorithm for the driver.
+
+ @retval EFI_SUCCESS The RNG algorithm list was returned
+ successfully.
+ @retval EFI_UNSUPPORTED The services is not supported by this
+ driver.
+ @retval EFI_DEVICE_ERROR The list of algorithms could not be
+ retrieved due to a hardware or firmware
+ error.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters are
+ incorrect.
+ @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small
+ to hold the result.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+Armada70x0RngGetInfo (
+ IN EFI_RNG_PROTOCOL *This,
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ )
+{
+ if (This == NULL || RNGAlgorithmListSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*RNGAlgorithmListSize < sizeof (EFI_RNG_ALGORITHM)) {
+ *RNGAlgorithmListSize = sizeof (EFI_RNG_ALGORITHM);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (RNGAlgorithmList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *RNGAlgorithmListSize = sizeof (EFI_RNG_ALGORITHM);
+ CopyGuid (RNGAlgorithmList, &gEfiRngAlgorithmRaw);
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+GetTrngData (
+ IN UINTN Length,
+ OUT UINT8 *Bits
+ )
+{
+ UINTN Tries;
+ UINT32 Buf[TRNG_OUTPUT_SIZE / sizeof (UINT32)];
+ UINTN Index;
+
+ for (Tries = 0; Tries < TRNG_MAX_RETRIES; Tries++) {
+ if (MmioRead32 (TRNG_STATUS_REG) & TRNG_STATUS_READY) {
+ for (Index = 0; Index < ARRAY_SIZE (Buf); Index++) {
+ Buf[Index] = MmioRead32 (TRNG_OUTPUT_REG + Index * sizeof (UINT32));
+ }
+ CopyMem (Bits, Buf, Length);
+ MmioWrite32 (TRNG_INTACK_REG, TRNG_INTACK_READY);
+
+ return EFI_SUCCESS;
+ }
+ // Wait for more TRNG data to arrive
+ gBS->Stall (10);
+ }
+ return EFI_DEVICE_ERROR;
+}
+
+/**
+ Produces and returns an RNG value using either the default or specified RNG
+ algorithm.
+
+ @param[in] This A pointer to the EFI_RNG_PROTOCOL
+ instance.
+ @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that
+ identifies the RNG algorithm to use. May
+ be NULL in which case the function will
+ use its default RNG algorithm.
+ @param[in] RNGValueLength The length in bytes of the memory buffer
+ pointed to by RNGValue. The driver shall
+ return exactly this numbers of bytes.
+ @param[out] RNGValue A caller-allocated memory buffer filled
+ by the driver with the resulting RNG
+ value.
+
+ @retval EFI_SUCCESS The RNG value was returned successfully.
+ @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm
+ is not supported by this driver.
+ @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due
+ to a hardware or firmware error.
+ @retval EFI_NOT_READY There is not enough random data available
+ to satisfy the length requested by
+ RNGValueLength.
+ @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is
+ zero.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+Armada70x0RngGetRNG (
+ IN EFI_RNG_PROTOCOL *This,
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
+ IN UINTN RNGValueLength,
+ OUT UINT8 *RNGValue
+ )
+{
+ UINTN Length;
+ EFI_STATUS Status;
+
+ if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // We only support the raw algorithm, so reject requests for anything else
+ //
+ if (RNGAlgorithm != NULL &&
+ !CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ do {
+ Length = MIN (RNGValueLength, TRNG_OUTPUT_SIZE);
+ Status = GetTrngData (Length, RNGValue);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RNGValue += Length;
+ RNGValueLength -= Length;
+ } while (RNGValueLength > 0);
+
+ return EFI_SUCCESS;
+}
+
+STATIC EFI_RNG_PROTOCOL mArmada70x0RngProtocol = {
+ Armada70x0RngGetInfo,
+ Armada70x0RngGetRNG
+};
+
+//
+// Entry point of this driver.
+//
+EFI_STATUS
+EFIAPI
+Armada70x0RngDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ mTrngBaseAddress = PcdGet64 (PcdEip76TrngBaseAddress);
+
+ //
+ // Disable the TRNG before updating its configuration
+ //
+ MmioAnd32 (TRNG_CONTROL_REG, ~TRNG_CONTROL_REG_ENABLE);
+
+ //
+ // Configure the internal conditioning parameters of the TRNG
+ //
+ MmioWrite32 (TRNG_CONFIG_REG, TRNG_CONFIG_MIN_REFILL_CYCLES |
+ TRNG_CONFIG_MAX_REFILL_CYCLES);
+
+ //
+ // Configure the FROs
+ //
+ MmioWrite32 (TRNG_FRODETUNE_REG, TRNG_FRODETUNE_MASK);
+ MmioWrite32 (TRNG_FROENABLE_REG, TRNG_FROENABLE_MASK);
+
+ //
+ // Enable the TRNG
+ //
+ MmioOr32 (TRNG_CONTROL_REG, TRNG_CONTROL_REG_ENABLE);
+
+ return SystemTable->BootServices->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gEfiRngProtocolGuid,
+ &mArmada70x0RngProtocol,
+ NULL
+ );
+}
diff --git a/Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.inf b/Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.inf
new file mode 100644
index 0000000..189ffc5
--- /dev/null
+++ b/Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.inf
@@ -0,0 +1,47 @@
+## @file
+# This driver produces an EFI_RNG_PROTOCOL instance for the Armada 70x0 TRNG
+#
+# Copyright (C) 2017, Linaro Ltd. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License which accompanies this
+# distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010019
+ BASE_NAME = Armada70x0RngDxe
+ FILE_GUID = dd87096a-cae5-4328-bec1-2ddb755f2e08
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = Armada70x0RngDxeEntryPoint
+
+[Sources]
+ Armada70x0RngDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ Platform/Marvell/Marvell.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ IoLib
+ PcdLib
+ UefiDriverEntryPoint
+
+[Pcd]
+ gMarvellTokenSpaceGuid.PcdEip76TrngBaseAddress
+
+[Protocols]
+ gEfiRngProtocolGuid ## PRODUCES
+
+[Guids]
+ gEfiRngAlgorithmRaw
+
+[Depex]
+ TRUE
diff --git a/Platform/Marvell/Marvell.dec b/Platform/Marvell/Marvell.dec
index e7d7c2c..78f5e53 100644
--- a/Platform/Marvell/Marvell.dec
+++ b/Platform/Marvell/Marvell.dec
@@ -195,6 +195,9 @@
#RTC
gMarvellTokenSpaceGuid.PcdRtcEnabled|{ 0x0 }|VOID*|0x40000052
+#TRNG
+ gMarvellTokenSpaceGuid.PcdEip76TrngBaseAddress|0x0|UINT64|0x50000053
+
[Protocols]
gMarvellEepromProtocolGuid = { 0x71954bda, 0x60d3, 0x4ef8, { 0x8e, 0x3c, 0x0e, 0x33, 0x9f, 0x3b, 0xc2, 0x2b }}
gMarvellMdioProtocolGuid = { 0x40010b03, 0x5f08, 0x496a, { 0xa2, 0x64, 0x10, 0x5e, 0x72, 0xd3, 0x71, 0xaa }}
--
2.7.4
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
© 2016 - 2024 Red Hat, Inc.