On Wed, Oct 25, 2017 at 08:45:23AM +0200, Marcin Wojtas wrote:
> From: Ard Biesheuvel <[email protected]>
> 
> 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 <[email protected]>
> Signed-off-by: Marcin Wojtas <[email protected]>

Reviewed-by: Leif Lindholm <[email protected]>

> ---
>  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
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to