diff mbox series

[edk2,platforms:,1/8] Marvell/Armada: Implement EFI_RNG_PROTOCOL driver for EIP76 TRNG

Message ID 1507736449-6073-2-git-send-email-mw@semihalf.com
State Superseded
Headers show
Series [edk2,platforms:,1/8] Marvell/Armada: Implement EFI_RNG_PROTOCOL driver for EIP76 TRNG | expand

Commit Message

Marcin Wojtas Oct. 11, 2017, 3:40 p.m. UTC
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>

---
 Platform/Marvell/Armada/Armada.dsc.inc                                |   4 +
 Platform/Marvell/Armada/Armada70x0.fdf                                |   1 +
 Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.c   | 254 ++++++++++++++++++++
 Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.inf |  47 ++++
 Platform/Marvell/Marvell.dec                                          |   3 +
 5 files changed, 309 insertions(+)

-- 
2.7.4

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Comments

Leif Lindholm Oct. 11, 2017, 4:47 p.m. UTC | #1
On Wed, Oct 11, 2017 at 05:40:42PM +0200, Marcin Wojtas wrote:
> 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>

> ---

>  Platform/Marvell/Armada/Armada.dsc.inc                                |   4 +

>  Platform/Marvell/Armada/Armada70x0.fdf                                |   1 +

>  Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.c   | 254 ++++++++++++++++++++

>  Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.inf |  47 ++++

>  Platform/Marvell/Marvell.dec                                          |   3 +

>  5 files changed, 309 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..dca6dcc

> --- /dev/null

> +++ b/Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.c

> @@ -0,0 +1,254 @@

> +/** @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;

> +    }

> +    gBS->Stall (10);


Why? Why 10? Please add a comment.

No other comments on this patch.

/
    Leif

> +  }

> +  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
Ard Biesheuvel Oct. 11, 2017, 6:15 p.m. UTC | #2
On 11 October 2017 at 17:47, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> On Wed, Oct 11, 2017 at 05:40:42PM +0200, Marcin Wojtas wrote:

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

>> ---

>>  Platform/Marvell/Armada/Armada.dsc.inc                                |   4 +

>>  Platform/Marvell/Armada/Armada70x0.fdf                                |   1 +

>>  Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.c   | 254 ++++++++++++++++++++

>>  Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.inf |  47 ++++

>>  Platform/Marvell/Marvell.dec                                          |   3 +

>>  5 files changed, 309 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..dca6dcc

>> --- /dev/null

>> +++ b/Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.c

>> @@ -0,0 +1,254 @@

>> +/** @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;

>> +    }

>> +    gBS->Stall (10);

>

> Why? Why 10? Please add a comment.

>

> No other comments on this patch.

>


I don't remember the details, and I think the 1 ms delay was chosen
arbitrarily, but the purpose of the delay is to allow the hardware to
assume the 'ready' state.


>> +  }

>> +  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
Marcin Wojtas Oct. 12, 2017, 4:39 a.m. UTC | #3
2017-10-11 20:15 GMT+02:00 Ard Biesheuvel <ard.biesheuvel@linaro.org>:
> On 11 October 2017 at 17:47, Leif Lindholm <leif.lindholm@linaro.org> wrote:

>> On Wed, Oct 11, 2017 at 05:40:42PM +0200, Marcin Wojtas wrote:

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

>>> ---

>>>  Platform/Marvell/Armada/Armada.dsc.inc                                |   4 +

>>>  Platform/Marvell/Armada/Armada70x0.fdf                                |   1 +

>>>  Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.c   | 254 ++++++++++++++++++++

>>>  Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.inf |  47 ++++

>>>  Platform/Marvell/Marvell.dec                                          |   3 +

>>>  5 files changed, 309 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..dca6dcc

>>> --- /dev/null

>>> +++ b/Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.c

>>> @@ -0,0 +1,254 @@

>>> +/** @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;

>>> +    }

>>> +    gBS->Stall (10);

>>

>> Why? Why 10? Please add a comment.

>>

>> No other comments on this patch.

>>

>

> I don't remember the details, and I think the 1 ms delay was chosen

> arbitrarily, but the purpose of the delay is to allow the hardware to

> assume the 'ready' state.

>


I don't have EIP150 docs, but how about a comment:

// Polling interval for obtaining TRNG data is 10us
gBS->Stall (10);

I know it's not perfect, but would you accept it?:)

Best regards,
Marcin
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Leif Lindholm Oct. 12, 2017, 10:24 a.m. UTC | #4
On Thu, Oct 12, 2017 at 06:39:46AM +0200, Marcin Wojtas wrote:
> 2017-10-11 20:15 GMT+02:00 Ard Biesheuvel <ard.biesheuvel@linaro.org>:

> > On 11 October 2017 at 17:47, Leif Lindholm <leif.lindholm@linaro.org> wrote:

> >> On Wed, Oct 11, 2017 at 05:40:42PM +0200, Marcin Wojtas wrote:

> >>> From: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> >>> +    }

> >>> +    gBS->Stall (10);

> >>

> >> Why? Why 10? Please add a comment.

> >>

> >> No other comments on this patch.

> >>

> >

> > I don't remember the details, and I think the 1 ms delay was chosen

> > arbitrarily, but the purpose of the delay is to allow the hardware to

> > assume the 'ready' state.

> >

> 

> I don't have EIP150 docs, but how about a comment:

> 

> // Polling interval for obtaining TRNG data is 10us

> gBS->Stall (10);

> 

> I know it's not perfect, but would you accept it?:)


Nearly. "Polling interval ... is" sounds a bit too authoritative
(unless that is actually what is documented).
"Wait for more TRNG data to arrive" would be sufficient.

/
    Leif
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
diff mbox series

Patch

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..dca6dcc
--- /dev/null
+++ b/Platform/Marvell/Armada/Drivers/Armada70x0RngDxe/Armada70x0RngDxe.c
@@ -0,0 +1,254 @@ 
+/** @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;
+    }
+    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 }}