The Bcm283x Random Number Generator does not work in regular mode
on the Bcm2711 powered Raspberry Pi 4. It does however work when
using FIFO mode. So we add this new mode, which is governed by the
use of the new PcdBcm283xRngUseFifo boolean PCD.

Note that just as a Pi 4 doesn't seem to support regular mode, a
Pi 3 doesn't seem to support FIFO mode, which is why we can't
switch to simply using FIFO mode for both platforms.

We also fix the register to which RNG_WARMUP_COUNT is written,
which was incorrect.

Signed-off-by: Pete Batard <p...@akeo.ie>
---
 Silicon/Broadcom/Bcm283x/Bcm283x.dec               |  1 +
 Silicon/Broadcom/Bcm283x/Drivers/RngDxe/RngDxe.c   | 96 +++++++++++++++-----
 Silicon/Broadcom/Bcm283x/Drivers/RngDxe/RngDxe.inf |  2 +
 3 files changed, 74 insertions(+), 25 deletions(-)

diff --git a/Silicon/Broadcom/Bcm283x/Bcm283x.dec 
b/Silicon/Broadcom/Bcm283x/Bcm283x.dec
index 5b839b00d286..4a9be7b18c97 100644
--- a/Silicon/Broadcom/Bcm283x/Bcm283x.dec
+++ b/Silicon/Broadcom/Bcm283x/Bcm283x.dec
@@ -21,3 +21,4 @@ [Guids]
 
 [PcdsFixedAtBuild.common]
   gBcm283xTokenSpaceGuid.PcdBcm283xRegistersAddress|0x0|UINT32|0x00000001
+  gBcm283xTokenSpaceGuid.PcdBcm283xRngUseFifo|0x0|BOOLEAN|0x00000002
diff --git a/Silicon/Broadcom/Bcm283x/Drivers/RngDxe/RngDxe.c 
b/Silicon/Broadcom/Bcm283x/Drivers/RngDxe/RngDxe.c
index 722815d32f06..462a21a6f3c3 100644
--- a/Silicon/Broadcom/Bcm283x/Drivers/RngDxe/RngDxe.c
+++ b/Silicon/Broadcom/Bcm283x/Drivers/RngDxe/RngDxe.c
@@ -2,6 +2,7 @@
 
   This driver produces an EFI_RNG_PROTOCOL instance for the Broadcom 2836 RNG
 
+  Copyright (C) 2019, Pete Batard <p...@akeo.ie>
   Copyright (C) 2019, Linaro Ltd. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -12,6 +13,8 @@
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
 #include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 
 #include <IndustryStandard/Bcm2836.h>
@@ -20,6 +23,8 @@
 
 #define RNG_WARMUP_COUNT        0x40000
 #define RNG_MAX_RETRIES         0x100         // arbitrary upper bound
+#define RNG_FIFO_NUMVAL_MASK    0xff
+#define RNG_STATUS_NUMVAL_SHIFT 24
 
 /**
   Returns information about the random number generation implementation.
@@ -84,6 +89,54 @@ Bcm2836RngGetInfo (
   return EFI_SUCCESS;
 }
 
+/**
+  Read a single random value, in either FIFO or regular mode.
+
+  @param[in]  Val                     A pointer to the 32-bit word that is to
+                                      be filled with a random value.
+
+  @retval EFI_SUCCESS                 A random value was successfully read.
+  @retval EFI_NOT_READY               The number of retries elapsed before a
+                                      random value was generated.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+Bcm2836RngReadValue (
+  IN OUT  UINT32                  *Val
+)
+{
+  UINT32 Avail;
+  UINT32 i;
+  BOOLEAN UseFifo = FixedPcdGetBool (PcdBcm283xRngUseFifo);
+
+  ASSERT (Val != NULL);
+
+  Avail = UseFifo ?
+    (MmioRead32 (RNG_FIFO_COUNT) & RNG_FIFO_NUMVAL_MASK) :
+    (MmioRead32 (RNG_STATUS) >> RNG_STATUS_NUMVAL_SHIFT);
+
+  //
+  // If we don't have a value ready, wait 1 us and retry.
+  //
+  for (i = 0; Avail < 1 && i < RNG_MAX_RETRIES; i++) {
+    MicroSecondDelay (1);
+    Avail = UseFifo ?
+      (MmioRead32 (RNG_FIFO_COUNT) & RNG_FIFO_NUMVAL_MASK) :
+      (MmioRead32 (RNG_STATUS) >> RNG_STATUS_NUMVAL_SHIFT);
+  }
+  if (Avail < 1) {
+    return EFI_NOT_READY;
+  }
+
+  *Val = UseFifo ?
+    MmioRead32 (RNG_FIFO_DATA):
+    MmioRead32 (RNG_DATA);
+
+  return EFI_SUCCESS;
+}
+
 /**
   Produces and returns an RNG value using either the default or specified RNG
   algorithm.
@@ -123,9 +176,8 @@ Bcm2836RngGetRNG (
   OUT UINT8                      *RNGValue
   )
 {
-  UINT32 Val;
-  UINT32 Num;
-  UINT32 Retries;
+  EFI_STATUS      Status;
+  UINT32          Val;
 
   if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) {
     return EFI_INVALID_PARAMETER;
@@ -139,30 +191,24 @@ Bcm2836RngGetRNG (
     return EFI_UNSUPPORTED;
   }
 
-  while (RNGValueLength > 0) {
-    Retries = RNG_MAX_RETRIES;
-    do {
-      Num = MmioRead32 (RNG_STATUS) >> 24;
-      MemoryFence ();
-    } while (!Num && Retries-- > 0);
-
-    if (!Num) {
-      return EFI_DEVICE_ERROR;
+  while (RNGValueLength >= sizeof (UINT32)) {
+    Status = Bcm2836RngReadValue (&Val);
+    if (EFI_ERROR (Status)) {
+      return Status;
     }
+    WriteUnaligned32 ((VOID *)RNGValue, Val);
+    RNGValue += sizeof (UINT32);
+    RNGValueLength -= sizeof (UINT32);
+  }
 
-    while (RNGValueLength >= sizeof (UINT32) && Num > 0) {
-      WriteUnaligned32 ((VOID *)RNGValue, MmioRead32 (RNG_DATA));
-      RNGValue += sizeof (UINT32);
-      RNGValueLength -= sizeof (UINT32);
-      Num--;
+  if (RNGValueLength > 0) {
+    Status = Bcm2836RngReadValue (&Val);
+    if (EFI_ERROR (Status)) {
+      return Status;
     }
-
-    if (RNGValueLength > 0 && Num > 0) {
-      Val = MmioRead32 (RNG_DATA);
-      while (RNGValueLength--) {
-        *RNGValue++ = (UINT8)Val;
-        Val >>= 8;
-      }
+    while (RNGValueLength--) {
+      *RNGValue++ = (UINT8)Val;
+      Val >>= 8;
     }
   }
   return EFI_SUCCESS;
@@ -190,7 +236,7 @@ Bcm2836RngEntryPoint (
                   NULL);
   ASSERT_EFI_ERROR (Status);
 
-  MmioWrite32 (RNG_STATUS, RNG_WARMUP_COUNT);
+  MmioWrite32 (RNG_BIT_COUNT_THRESHOLD, RNG_WARMUP_COUNT);
   MmioWrite32 (RNG_CTRL, RNG_CTRL_ENABLE);
 
   return EFI_SUCCESS;
diff --git a/Silicon/Broadcom/Bcm283x/Drivers/RngDxe/RngDxe.inf 
b/Silicon/Broadcom/Bcm283x/Drivers/RngDxe/RngDxe.inf
index 8eb90de85cfd..31415231ae0b 100644
--- a/Silicon/Broadcom/Bcm283x/Drivers/RngDxe/RngDxe.inf
+++ b/Silicon/Broadcom/Bcm283x/Drivers/RngDxe/RngDxe.inf
@@ -28,6 +28,7 @@ [LibraryClasses]
   DebugLib
   IoLib
   PcdLib
+  TimerLib
   UefiBootServicesTableLib
   UefiDriverEntryPoint
 
@@ -39,6 +40,7 @@ [Guids]
 
 [FixedPcd]
   gBcm283xTokenSpaceGuid.PcdBcm283xRegistersAddress
+  gBcm283xTokenSpaceGuid.PcdBcm283xRngUseFifo
 
 [Depex]
   TRUE
-- 
2.21.0.windows.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#51336): https://edk2.groups.io/g/devel/message/51336
Mute This Topic: https://groups.io/mt/62504740/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to