From nobody Mon Feb 9 19:53:02 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+51527+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+51527+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1575287730; cv=none; d=zohomail.com; s=zohoarc; b=BwtNhRg8dFH3/4WWo0UBSS13qJAghzOUYpOeu3HDxsqO9Lebj8Kw/Vtn5LtiOU5Ozur6cx2EJSZ/FvvzACiSUeHk/BFRFVsyhYgUnlnT6GL044uS8djpu9ptJ41ulgHT1FyijusshF5wpbw47dcsYlOQx6T4IUeXO7FzWSaHQSU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1575287730; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=OJF6xfLHkWV5A4EOrg44d5Ik3Ws1tsnX+/Wtfbs9A2I=; b=hE5y7nBUcolbiExcGUiWg3U0rsz23F0rN8eFkos7xUP9Ccio8Z8D0LhJN8Nk3mCsJuDUDItoTZ+75SP/BuAl35RX0IzH3BF7GNDYyLzHu2Mx1PH33bj7zLyyAutyrKhftq7TTyqRPgSEN+5k7EZOUYIir88Xx3znNKlXU88OAFw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+51527+1787277+3901457@groups.io Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1575287730075116.1889908433269; Mon, 2 Dec 2019 03:55:30 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id YPwZYY1788612xGim9I18gnd; Mon, 02 Dec 2019 03:55:29 -0800 X-Received: from mail-wm1-f67.google.com (mail-wm1-f67.google.com [209.85.128.67]) by mx.groups.io with SMTP id smtpd.web10.50.1575287727948378392 for ; Mon, 02 Dec 2019 03:55:28 -0800 X-Received: by mail-wm1-f67.google.com with SMTP id f129so22950353wmf.2 for ; Mon, 02 Dec 2019 03:55:27 -0800 (PST) X-Gm-Message-State: rxdYPT5FlLTVcdNNqQNONJBMx1787277AA= X-Google-Smtp-Source: APXvYqyc50yWUYJxMaP+/DC+HaC2L3pcSyiJRFuuR8FdzYM30fjW5s70UWaO4Kf7eDb2cAgLhYO/hQ== X-Received: by 2002:a7b:c318:: with SMTP id k24mr15322457wmj.54.1575287725673; Mon, 02 Dec 2019 03:55:25 -0800 (PST) X-Received: from localhost.localdomain ([84.203.45.230]) by smtp.gmail.com with ESMTPSA id p10sm8500291wmi.15.2019.12.02.03.55.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 02 Dec 2019 03:55:24 -0800 (PST) From: "Pete Batard" To: devel@edk2.groups.io Cc: ard.biesheuvel@linaro.org, leif.lindholm@linaro.org, philmd@redhat.com Subject: [edk2-devel] [edk2-platforms][PATCH 3/3] Silicon/Broadcom/Bcm283x: Add Bcm2838 RNG driver Date: Mon, 2 Dec 2019 11:55:06 +0000 Message-Id: <20191202115506.4068-4-pete@akeo.ie> In-Reply-To: <20191202115506.4068-1-pete@akeo.ie> References: <20191202115506.4068-1-pete@akeo.ie> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,pete@akeo.ie Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1575287729; bh=qVwu+m9VDivJvbfwZi/Tw1sIelZXrTWleZ0l7B+2StA=; h=Cc:Date:From:Reply-To:Subject:To; b=UZhvb7Z7GNmg0cri7HhaV7YzWe9Ay7J+Y/nlH6xZgxIWHooj8K7wgJBmH+3BwVD7rlo zuafEea20qVqypwTnNvweDcWfGvL+t8pF2j9J7GaEo/OPZwHAffzZHQdco/Vr8k9dl2Pm 2tZfsOxbFAfb7K0QtGbvrYQZww5/0Aid87s= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" This adds the Bcm2838 Random Number Generator Driver, which is also the type of RNG that the Bmc2711-based Raspberry Pi 4 uses. Signed-off-by: Pete Batard --- Silicon/Broadcom/Bcm283x/Drivers/Bcm2838RngDxe/Bcm2838RngDxe.c | 285 +++= +++++++++++++++++ Silicon/Broadcom/Bcm283x/Drivers/Bcm2838RngDxe/Bcm2838RngDxe.inf | 46 ++++ Silicon/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2838Rng.h | 30 +++ 3 files changed, 361 insertions(+) diff --git a/Silicon/Broadcom/Bcm283x/Drivers/Bcm2838RngDxe/Bcm2838RngDxe.c= b/Silicon/Broadcom/Bcm283x/Drivers/Bcm2838RngDxe/Bcm2838RngDxe.c new file mode 100644 index 000000000000..5737876e52c6 --- /dev/null +++ b/Silicon/Broadcom/Bcm283x/Drivers/Bcm2838RngDxe/Bcm2838RngDxe.c @@ -0,0 +1,285 @@ +/** @file + + This driver produces an EFI_RNG_PROTOCOL instance for the Broadcom 2838 = RNG + + Copyright (C) 2019, Pete Batard + Copyright (C) 2019, Linaro Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#define RNG_WARMUP_COUNT 0x40000 +#define RNG_MAX_RETRIES 0x100 // arbitrary upper bound + +/** + 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 fil= led + by the driver with one EFI_RNG_ALGOR= ITHM + element for each supported RNG algor= ithm. + The list must not change across mult= iple + 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 firmw= are + error. + @retval EFI_INVALID_PARAMETER One or more of the parameters are + incorrect. + @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too s= mall + to hold the result. + +**/ +STATIC +EFI_STATUS +EFIAPI +Bcm2838RngGetInfo ( + IN EFI_RNG_PROTOCOL *This, + IN OUT UINTN *RNGAlgorithmListSize, + OUT EFI_RNG_ALGORITHM *RNGAlgorithmList + ) +{ + if (This =3D=3D NULL || RNGAlgorithmListSize =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if (*RNGAlgorithmListSize < sizeof (EFI_RNG_ALGORITHM)) { + *RNGAlgorithmListSize =3D sizeof (EFI_RNG_ALGORITHM); + return EFI_BUFFER_TOO_SMALL; + } + + if (RNGAlgorithmList =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + *RNGAlgorithmListSize =3D sizeof (EFI_RNG_ALGORITHM); + CopyGuid (RNGAlgorithmList, &gEfiRngAlgorithmRaw); + + 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 +Bcm2838RngReadValue ( + IN OUT UINT32 *Val +) +{ + UINT32 Avail; + UINT32 i; + + ASSERT (Val !=3D NULL); + + Avail =3D MmioRead32 (RNG_FIFO_COUNT) & RNG_FIFO_DATA_AVAIL_MASK; + + // + // If we don't have a value ready, wait 1 us and retry. + // + // Empirical testing on the platform this driver is designed to be used + // with shows that, unless you set a large divisor for the sample rate, + // random bits should be generated around the MHz frequency. + // Therefore a retry that doesn't expire until at least RNG_MAX_RETRIES + // microseconds should give us ample time to obtain a value. Besides, + // even outside of calling MicroSecondDelay (), we expect MMIO reads to + // be slow anyway... + // + // On the other hand, we may run into a timeout here if the warmup period + // has not been completed since the RNG locks RNG_FIFO_COUNT to zero + // until then. However, with the values we use for the target platform, + // (RPi4) you'd need to start requesting random data within the first + // 250 to 500 ms after driver instantiation for this to happen. + // + for (i =3D 0; Avail < 1 && i < RNG_MAX_RETRIES; i++) { + MicroSecondDelay (1); + Avail =3D MmioRead32 (RNG_FIFO_COUNT) & RNG_FIFO_DATA_AVAIL_MASK; + } + if (Avail < 1) { + return EFI_NOT_READY; + } + + *Val =3D MmioRead32 (RNG_FIFO_DATA); + + return EFI_SUCCESS; +} + +/** + 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 t= hat + identifies the RNG algorithm to use.= May + be NULL in which case the function w= ill + use its default RNG algorithm. + @param[in] RNGValueLength The length in bytes of the memory bu= ffer + pointed to by RNGValue. The driver s= hall + return exactly this numbers of bytes. + @param[out] RNGValue A caller-allocated memory buffer fil= led + by the driver with the resulting RNG + value. + + @retval EFI_SUCCESS The RNG value was returned successfu= lly. + @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgori= thm + 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 avai= lable + to satisfy the length requested by + RNGValueLength. + @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is + zero. + +**/ +STATIC +EFI_STATUS +EFIAPI +Bcm2838RngGetRNG ( + IN EFI_RNG_PROTOCOL *This, + IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL + IN UINTN RNGValueLength, + OUT UINT8 *RNGValue + ) +{ + EFI_STATUS Status; + UINT32 Val; + + if (This =3D=3D NULL || RNGValueLength =3D=3D 0 || RNGValue =3D=3D NULL)= { + return EFI_INVALID_PARAMETER; + } + + // + // We only support the raw algorithm, so reject requests for anything el= se + // + if (RNGAlgorithm !=3D NULL && + !CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) { + return EFI_UNSUPPORTED; + } + + // + // The Linux driver from Broadcom checks RNG_BIT_COUNT here to ensure th= at + // the warmup threshold has been reached, but our testing shows that thi= s is + // pointless as RNG_BIT_COUNT is increased even during warmup and, as lo= ng + // as warmup isn't complete, the FIFO reports that no values are availab= le. + // + // Also note that RNG_BIT_COUNT doesn't roll over. Once it reaches 0xFFF= FFFFF + // it just stays there... + // + + while (RNGValueLength >=3D sizeof (UINT32)) { + Status =3D Bcm2838RngReadValue (&Val); + if (EFI_ERROR (Status)) { + return Status; + } + WriteUnaligned32 ((VOID *)RNGValue, Val); + RNGValue +=3D sizeof (UINT32); + RNGValueLength -=3D sizeof (UINT32); + } + + if (RNGValueLength > 0) { + Status =3D Bcm2838RngReadValue (&Val); + if (EFI_ERROR (Status)) { + return Status; + } + while (RNGValueLength--) { + *RNGValue++ =3D (UINT8)Val; + Val >>=3D 8; + } + } + return EFI_SUCCESS; +} + +STATIC EFI_RNG_PROTOCOL mBcm2838RngProtocol =3D { + Bcm2838RngGetInfo, + Bcm2838RngGetRNG +}; + +// +// Entry point of this driver. +// +EFI_STATUS +EFIAPI +Bcm2838RngEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status =3D gBS->InstallMultipleProtocolInterfaces (&ImageHandle, + &gEfiRngProtocolGuid, &mBcm2838RngProtocol, + NULL); + ASSERT_EFI_ERROR (Status); + + // + // Set the warm up bit count. + // + // This results in the RNG holding off from populating any value into the + // FIFO until the value below has been reached in RNG_BIT_COUNT. + // + MmioWrite32 (RNG_BIT_COUNT_THRESHOLD, RNG_WARMUP_COUNT); + + // + // We would disable RNG interrupts here... if we had access to the datas= heet. + // + + // + // Enable the RNG with a sample rate divisor of 3. + // + // For a Bcm2711 running at 1.5 GHz, this should generate random bits at= a + // rate of about 1 every microsecond (1 MHz). + // + // Note that The divisor is a power of two index, meaning that each + // consecutive divisor halves the frequency at which bits are being + // produced. Zero is a special value that seems to set the rate somewhere + // between divisors 1 and 2. + // + // Also note that Broadcom set the whole ENABLE_MASK in the Linux driver, + // instead of single bits, which may be unintended. But since we don't h= ave + // any public documentation on what each of these bits do, we follow sui= t. + // + MmioWrite32 (RNG_CTRL, + RNG_CTRL_ENABLE_MASK | (3 << RNG_CTRL_SAMPLE_RATE_DIVISOR_SHIFT)); + + return EFI_SUCCESS; +} diff --git a/Silicon/Broadcom/Bcm283x/Drivers/Bcm2838RngDxe/Bcm2838RngDxe.i= nf b/Silicon/Broadcom/Bcm283x/Drivers/Bcm2838RngDxe/Bcm2838RngDxe.inf new file mode 100644 index 000000000000..fdc1b25743cf --- /dev/null +++ b/Silicon/Broadcom/Bcm283x/Drivers/Bcm2838RngDxe/Bcm2838RngDxe.inf @@ -0,0 +1,46 @@ +#/** @file +# +# Copyright (c) 2019, Pete Batard +# Copyright (c) 2019, ARM Limited. All rights reserved. +# Copyright (c) 2019, Linaro, Ltd. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#**/ + +[Defines] + INF_VERSION =3D 0x0001001B + BASE_NAME =3D Bcm2838RngDxe + FILE_GUID =3D 5ec564ce-b656-435c-a652-5cb719784542 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D Bcm2838RngEntryPoint + +[Sources] + Bcm2838RngDxe.c + +[Packages] + MdePkg/MdePkg.dec + Silicon/Broadcom/Bcm283x/Bcm283x.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + IoLib + PcdLib + TimerLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Protocols] + gEfiRngProtocolGuid ## PRODUCES + +[Guids] + gEfiRngAlgorithmRaw + +[FixedPcd] + gBcm283xTokenSpaceGuid.PcdBcm283xRegistersAddress + +[Depex] + TRUE diff --git a/Silicon/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2838Rng.h= b/Silicon/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2838Rng.h new file mode 100644 index 000000000000..003866fa866e --- /dev/null +++ b/Silicon/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2838Rng.h @@ -0,0 +1,30 @@ +/** @file + * + * Copyright (c) 2019, Pete Batard + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + * + **/ + +#ifndef BCM2838_RNG_H__ +#define BCM2838_RNG_H__ + +#define BCM2838_RNG_OFFSET 0x00104000 +#define RNG_BASE_ADDRESS ((FixedPcdGet64 (PcdBcm283xReg= istersAddress)) \ + + BCM2838_RNG_OFFSET) + +#define RNG_CTRL (RNG_BASE_ADDRESS + 0x0) +#define RNG_STATUS (RNG_BASE_ADDRESS + 0x4) +#define RNG_DATA (RNG_BASE_ADDRESS + 0x8) +#define RNG_BIT_COUNT (RNG_BASE_ADDRESS + 0xc) +#define RNG_BIT_COUNT_THRESHOLD (RNG_BASE_ADDRESS + 0x10) +#define RNG_INT_STATUS (RNG_BASE_ADDRESS + 0x18) +#define RNG_INT_ENABLE (RNG_BASE_ADDRESS + 0x1c) +#define RNG_FIFO_DATA (RNG_BASE_ADDRESS + 0x20) +#define RNG_FIFO_COUNT (RNG_BASE_ADDRESS + 0x24) + +#define RNG_CTRL_ENABLE_MASK 0x1fff +#define RNG_CTRL_SAMPLE_RATE_DIVISOR_SHIFT 13 // Unmasked bits from = above +#define RNG_FIFO_DATA_AVAIL_MASK 0xff + +#endif /* BCM2838_RNG_H__ */ --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#51527): https://edk2.groups.io/g/devel/message/51527 Mute This Topic: https://groups.io/mt/64721638/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-