From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) by mx.groups.io with SMTP id smtpd.web09.5820.1637758920922691023 for ; Wed, 24 Nov 2021 05:02:01 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@nuviainc-com.20210112.gappssmtp.com header.s=20210112 header.b=Ahj8ljt0; spf=pass (domain: nuviainc.com, ip: 209.85.128.48, mailfrom: leif@nuviainc.com) Received: by mail-wm1-f48.google.com with SMTP id j140-20020a1c2392000000b003399ae48f58so5327972wmj.5 for ; Wed, 24 Nov 2021 05:02:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20210112.gappssmtp.com; s=20210112; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=u+kq+p74DaCQRd1VErIwobUKvFmiYuWQjP8+WLPPMQE=; b=Ahj8ljt04P1NrOUQMw7uAseHzp5zU9QOFXw7bWm0QhhrawN5OtqHrHiosqGbD3kGUo TbzkA9CMBrhbyX3THdgQXw3KdnuVGOcRdkeEtkHp6K0VGPPWe0iYJDJRgfiFc2CpIp4v RUQhz0pAPVvTsSBdr36p+bz+mtboYAs/Y54BTA4CA10HGxB+WTTHN+GOiHbxGvWxkTr4 inNdoMwMQVNPCOLXx4SYk37ro3oQg1upaopg6JqNk6JMw3kEw3BL/+8e5maxB/S+Qw6o C8ysghwugGVEmc0Lvsqjq08/JnWSdyuriSwvkWdcPspyDeHwbtzhR0rkIVuQD82OyC9K qtDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=u+kq+p74DaCQRd1VErIwobUKvFmiYuWQjP8+WLPPMQE=; b=aPro49ZtVlrlBinlAQmb0LK4Ccrd8hMip6UKaxzHkMHABO07uY2LLhKg9iygiwCoYl HCthAVcUvdODnhNN1mZBJHXw/8kQkq9ciG8l2jN4MeI4ZbUvEpkeD0HqFIAMEzb5IAQX SKm73LJI2Y7F6YOAmXeGG7qTCedYCyHkN9aycO6pY6tEBnajr/zlATfDISKiFfjgaj7j o3PRHNt+Ug4wfJK6vfC7x5i1tWUOZw34sy1YipvX0fs4DQvPhtoQ7R/fMjuxxLp1VHL1 OblYROPzheDKn64odcu6ilSDuZkEyvfqGufuE6YAzSQTfO7Z3b/cvMjNgznXmnDxo+Rz jJHw== X-Gm-Message-State: AOAM533Ib8iV+wnV+2MheOz6fNM4YzMnBtQNGhWUiXYY7YY1pOe7fSW4 8ISbeRUBrFkYb7B/6wuOq/nQls+ln3dhVvfeS/BSR4X4qFsecq7hy1YwGKqLLdGkpn571PYHs0G 5GvDDK4oJffRmktYhPs3RmTcRgOla4eHqlho8fakbPcV0aTWaKA73VWVSGVunDZ2FUj15 X-Google-Smtp-Source: ABdhPJwE3uwqHEf0D/2sVcKUcNH3PcXgSFEyr3t6S1tGf43T0PX45BEsZlb7+2Bx2CIn3/Zzvge0kg== X-Received: by 2002:a05:600c:4f0f:: with SMTP id l15mr14876436wmq.25.1637758918388; Wed, 24 Nov 2021 05:01:58 -0800 (PST) Return-Path: Received: from leviathan (cpc92314-cmbg19-2-0-cust559.5-4.cable.virginm.net. [82.11.186.48]) by smtp.gmail.com with ESMTPSA id d2sm4645877wmb.31.2021.11.24.05.01.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 24 Nov 2021 05:01:57 -0800 (PST) Date: Wed, 24 Nov 2021 13:01:55 +0000 From: "Leif Lindholm" To: devel@edk2.groups.io, sami.mujawar@arm.com Cc: ardb+tianocore@kernel.org, rebecca@bsdio.com, kraxel@redhat.com, michael.d.kinney@intel.com, gaoliming@byosoft.com.cn, zhiguang.liu@intel.com, jiewen.yao@intel.com, jian.j.wang@intel.com, Matteo.Carlini@arm.com, Akanksha.Jain2@arm.com, Ben.Adderson@arm.com, nd@arm.com Subject: Re: [edk2-devel] [PATCH v2 3/8] ArmPkg: Add Arm Firmware TRNG library Message-ID: References: <20211116113301.31088-1-sami.mujawar@arm.com> <20211116113301.31088-4-sami.mujawar@arm.com> MIME-Version: 1.0 In-Reply-To: <20211116113301.31088-4-sami.mujawar@arm.com> Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi Sami, On Tue, Nov 16, 2021 at 11:32:55 +0000, Sami Mujawar wrote: > Bugzilla: 3668 (https://bugzilla.tianocore.org/show_bug.cgi?id=3668) > > The Arm True Random Number Generator Firmware, Interface 1.0, > Platform Design Document > (https://developer.arm.com/documentation/den0098/latest/) > defines an interface between an Operating System (OS) executing > at EL1 and Firmware (FW) exposing a conditioned entropy source > that is provided by a TRNG back end. > > The conditioned entropy, that is provided by the TRNG FW interface, > is commonly used to seed deterministic random number generators. > > This patch adds a TrngLib library that implements the Arm TRNG > firmware interface. > > Signed-off-by: Sami Mujawar > --- > > Notes: > v2: > - MdePkg\Include\Library\TrngLib.h is base type [LIMING] > library. It can use RETURN_STATUS instead of > EFI_STATUS. > - Replaced EFI_STATUS with RETURN_STATUS. [SAMI] > - MdePkg\Include\Library\TrngLib.h API parameter [LIMING] > doesn't require CONST. CONST means the value > specified by the input pointer will not be > changed in API implementation. > - Removed the use of constant pointers in the [SAMI] > TRNG API. > > ArmPkg/ArmPkg.dsc | 1 + > ArmPkg/Library/ArmFwTrngLib/ArmFwTrngDefs.h | 64 +++ > ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.c | 483 ++++++++++++++++++++ > ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf | 34 ++ > 4 files changed, 582 insertions(+) > > diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc > index 59fd8f295d4f614cc68ee1021e691f94e279ab81..23df68c5eb53df11de5d96bde4949f3c833c9b2c 100644 > --- a/ArmPkg/ArmPkg.dsc > +++ b/ArmPkg/ArmPkg.dsc > @@ -156,6 +156,7 @@ [Components.common] > ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.inf > ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf > > + ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf > ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf > ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf > ArmPkg/Universal/Smbios/OemMiscLibNull/OemMiscLibNull.inf > diff --git a/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngDefs.h b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngDefs.h > new file mode 100644 > index 0000000000000000000000000000000000000000..42236e743d972df0df205b1565496afeff5785f3 > --- /dev/null > +++ b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngDefs.h > @@ -0,0 +1,64 @@ > +/** @file > + Arm Firmware TRNG definitions. > + > + Copyright (c) 2021, Arm Limited. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + @par Reference(s): > + - [1] Arm True Random Number Generator Firmware, Interface 1.0, > + Platform Design Document. > + (https://developer.arm.com/documentation/den0098/latest/) > + > + @par Glossary: > + - TRNG - True Random Number Generator > + - FID - Function ID > +**/ > + > +#ifndef ARM_FW_TRNG_DEFS_H_ > +#define ARM_FW_TRNG_DEFS_H_ > + > +// Firmware TRNG interface Function IDs > +#define FID_TRNG_VERSION 0x84000050 > +#define FID_TRNG_FEATURES 0x84000051 > +#define FID_TRNG_GET_UUID 0x84000052 > +#define FID_TRNG_RND_AARCH32 0x84000053 > +#define FID_TRNG_RND_AARCH64 0xC4000053 Do these belong in ArmStdSmc.h? > + > +// Firmware TRNG revision mask and shift > +#define TRNG_REV_MAJOR_MASK 0x7FFF > +#define TRNG_REV_MINOR_MASK 0xFFFF > +#define TRNG_REV_MAJOR_SHIFT 16 > +#define TRNG_REV_MINOR_SHIFT 0 > + > +// Firmware TRNG status codes > +#define TRNG_STATUS_SUCCESS (INT32)(0) > +#define TRNG_NOT_SUPPORTED (INT32)(-1) > +#define TRNG_INVALID_PARAMETER (INT32)(-2) > +#define TRNG_NO_ENTROPY (INT32)(-3) And the rest of the stuff to here, really? > +#if defined (MDE_CPU_ARM) > +/** FID to use on AArch32 platform to request entropy. > +*/ > +#define FID_TRNG_RND FID_TRNG_RND_AARCH32 > + > +/** Maximum bits of entropy supported on AArch32. > +*/ > +#define MAX_ENTROPY_BITS 96 > +#elif defined (MDE_CPU_AARCH64) > +/** FID to use on AArch64 platform to request entropy. > +*/ > +#define FID_TRNG_RND FID_TRNG_RND_AARCH64 > + > +/** Maximum bits of entropy supported on AArch64. > +*/ > +#define MAX_ENTROPY_BITS 192 > +#else > +#error "Firmware TRNG not supported. Unknown chipset." > +#endif > + > +/** Typedef for SMC or HVC arguments. > +*/ > +typedef ARM_SMC_ARGS ARM_MONITOR_ARGS; > + > +#endif // ARM_FW_TRNG_DEFS_H_ > diff --git a/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.c b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.c > new file mode 100644 > index 0000000000000000000000000000000000000000..314e7ffbc232ae90bbb77306f9c7113ce63012c8 > --- /dev/null > +++ b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.c > @@ -0,0 +1,483 @@ > +/** @file > + Arm Firmware TRNG interface library. > + > + Copyright (c) 2021, Arm Limited. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + @par Reference(s): > + - [1] Arm True Random Number Generator Firmware, Interface 1.0, > + Platform Design Document. > + (https://developer.arm.com/documentation/den0098/latest/) > + - [2] NIST Special Publication 800-90A Revision 1, June 2015, Recommendation > + for Random Number Generation Using Deterministic Random Bit Generators. > + (https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final) > + - [3] NIST Special Publication 800-90B, Recommendation for the Entropy > + Sources Used for Random Bit Generation. > + (https://csrc.nist.gov/publications/detail/sp/800-90b/final) > + - [4] (Second Draft) NIST Special Publication 800-90C, Recommendation for > + Random Bit Generator (RBG) Constructions. > + (https://csrc.nist.gov/publications/detail/sp/800-90c/draft) > + > + @par Glossary: > + - TRNG - True Random Number Generator > + - FID - Function ID > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "ArmFwTrngDefs.h" > + > +/** Convert TRNG status codes to EFI status codes. > + > + @param [in] TrngStatus TRNG status code. > + > + @retval RETURN_SUCCESS Success. > + @retval RETURN_UNSUPPORTED Function not implemented. > + @retval RETURN_INVALID_PARAMETER A parameter is invalid. > + @retval RETURN_NOT_READY No Entropy available. > +**/ > +STATIC > +RETURN_STATUS > +TrngStatusToEfiStatus ( > + IN INT32 TrngStatus > + ) > +{ > + switch (TrngStatus) { > + case TRNG_NOT_SUPPORTED: > + return RETURN_UNSUPPORTED; > + > + case TRNG_INVALID_PARAMETER: > + return RETURN_INVALID_PARAMETER; > + > + case TRNG_NO_ENTROPY: > + return RETURN_NOT_READY; > + > + case TRNG_STATUS_SUCCESS: > + default: > + return RETURN_SUCCESS; > + } > +} > + > +/** Invoke the monitor call using the appropriate conduit. > + If PcdMonitorConduitHvc is TRUE use the HVC conduit else use SMC conduit. > + > + @param [in, out] Args Arguments passed to and returned from the monitor. > + > + @return VOID > +**/ > +STATIC > +VOID > +ArmCallMonitor ( > + IN OUT ARM_MONITOR_ARGS *Args > + ) > +{ > + if (FeaturePcdGet (PcdMonitorConduitHvc)) { > + ArmCallHvc ((ARM_HVC_ARGS*)Args); > + } else { > + ArmCallSmc ((ARM_SMC_ARGS*)Args); > + } > +} Should this be in (a potentially renamed) ArmSmcLib? > + > +/** Get the version of the TRNG backend. > + > + A TRNG may be implemented by the system firmware, in which case this > + function shall return the version of the TRNG backend. > + The implementation must return NOT_SUPPORTED if a Back end is not present. > + > + @param [out] MajorRevision Major revision. > + @param [out] MinorRevision Minor revision. > + > + @retval RETURN_SUCCESS The function completed successfully. > + @retval RETURN_INVALID_PARAMETER Invalid parameter. > + @retval RETURN_UNSUPPORTED Backend not present. > +**/ > +RETURN_STATUS > +EFIAPI > +GetTrngVersion ( > + OUT UINT16 *MajorRevision, > + OUT UINT16 *MinorRevision > + ) > +{ > + RETURN_STATUS Status; > + ARM_MONITOR_ARGS Parameters; > + INT32 Revision; > + > + if ((MajorRevision == NULL) || (MinorRevision == NULL)) { > + return RETURN_INVALID_PARAMETER; > + } > + > + ZeroMem (&Parameters, sizeof (Parameters)); > + > + /* > + Cf. [1], 2.1 TRNG_VERSION > + Function ID (W0) 0x8400_0050 > + Parameters > + W1-W7 Reserved (MBZ) > + Returns > + Success (W0 > 0) W0[31] MBZ > + W0[30:16] Major revision > + W0[15:0] Minor revision > + W1 - W3 Reserved (MBZ) > + Error (W0 < 0) > + NOT_SUPPORTED Function not implemented > + */ I have a comment on the placement of API descriptions further down. > + Parameters.Arg0 = FID_TRNG_VERSION; > + ArmCallMonitor (&Parameters); > + > + Revision = (INT32)Parameters.Arg0; > + // Convert status codes to EFI status codes. > + Status = TrngStatusToEfiStatus (Revision); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *MinorRevision = (Revision & TRNG_REV_MINOR_MASK); > + *MajorRevision = ((Revision >> TRNG_REV_MAJOR_SHIFT) & TRNG_REV_MAJOR_MASK); > + return RETURN_SUCCESS; > +} > + > +#ifndef MDEPKG_NDEBUG > +/** Get the features supported by the TRNG backend. > + > + The caller can determine if functions defined in the TRNG ABI are > + present in the ABI implementation. > + > + @param [in] FunctionId Function Id. > + @param [out] Capability Function specific capability if present > + otherwise Zero is returned. > + > + @retval RETURN_SUCCESS The function completed successfully. > + @retval RETURN_INVALID_PARAMETER Invalid parameter. > + @retval RETURN_UNSUPPORTED Function not implemented. > +**/ > +STATIC > +RETURN_STATUS > +EFIAPI > +GetTrngFeatures ( > + IN CONST UINT32 FunctionId, > + OUT UINT32 *Capability OPTIONAL > + ) > +{ > + ARM_MONITOR_ARGS Parameters; > + > + ZeroMem (&Parameters, sizeof (Parameters)); > + > + /* > + Cf. [1], Section 2.2 TRNG_FEATURES > + Function ID (W0) 0x8400_0051 > + Parameters > + W1 trng_func_id > + W2-W7 Reserved (MBZ) > + Returns > + Success (W0 >= 0) > + SUCCESS Function is implemented. > + > 0 Function is implemented and > + has specific capabilities, > + see function definition. > + Error (W0 < 0) > + NOT_SUPPORTED Function with FID=trng_func_id > + is not implemented > + */ I have a comment on the placement of API descriptions further down. > + Parameters.Arg0 = FID_TRNG_FEATURES; > + Parameters.Arg1 = FunctionId; > + ArmCallMonitor (&Parameters); > + if (Parameters.Arg0 < TRNG_STATUS_SUCCESS) { > + return RETURN_UNSUPPORTED; > + } > + > + if (Capability != NULL) { > + *Capability = Parameters.Arg0; > + } > + > + return RETURN_SUCCESS; > +} > +#endif //MDEPKG_NDEBUG > + > +/** Get the UUID of the TRNG backend. > + > + A TRNG may be implemented by the system firmware, in which case this > + function shall return the UUID of the TRNG backend. > + Returning the TRNG UUID is optional and if not implemented, RETURN_UNSUPPORTED > + shall be returned. > + > + Note: The caller must not rely on the returned UUID as a trustworthy TRNG > + Back end identity > + > + @param [out] Guid UUID of the TRNG backend. > + > + @retval RETURN_SUCCESS The function completed successfully. > + @retval RETURN_INVALID_PARAMETER Invalid parameter. > + @retval RETURN_UNSUPPORTED Function not implemented. > +**/ > +RETURN_STATUS > +EFIAPI > +GetTrngUuid ( > + OUT GUID *Guid > + ) > +{ > + RETURN_STATUS Status; > + ARM_MONITOR_ARGS Parameters; > + > + ZeroMem (&Parameters, sizeof (Parameters)); > + > + /* > + Cf. [1], Section 2.3 TRNG_GET_UUID > + Function ID (W0) 0x8400_0052 > + Parameters > + W1-W7 Reserved (MBZ) > + Returns > + Success (W0 != -1) > + W0 UUID[31:0] > + W1 UUID[63:32] > + W2 UUID[95:64] > + W3 UUID[127:96] > + Error (W0 = -1) > + W0 NOT_SUPPORTED > + */ > + Parameters.Arg0 = FID_TRNG_GET_UUID; > + ArmCallMonitor (&Parameters); > + > + // Convert status codes to EFI status codes. > + Status = TrngStatusToEfiStatus ((INT32)Parameters.Arg0); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Guid->Data1 = (Parameters.Arg0 & MAX_UINT32); > + Guid->Data2 = (Parameters.Arg1 & MAX_UINT16); > + Guid->Data3 = ((Parameters.Arg1 >> 16) & MAX_UINT16); > + > + Guid->Data4[0] = (Parameters.Arg2 & MAX_UINT8); > + Guid->Data4[1] = ((Parameters.Arg2 >> 8) & MAX_UINT8); > + Guid->Data4[2] = ((Parameters.Arg2 >> 16) & MAX_UINT8); > + Guid->Data4[3] = ((Parameters.Arg2 >> 24) & MAX_UINT8); > + > + Guid->Data4[4] = (Parameters.Arg3 & MAX_UINT8); > + Guid->Data4[5] = ((Parameters.Arg3 >> 8) & MAX_UINT8); > + Guid->Data4[6] = ((Parameters.Arg3 >> 16) & MAX_UINT8); > + Guid->Data4[7] = ((Parameters.Arg3 >> 24) & MAX_UINT8); > + > + DEBUG ((DEBUG_INFO, "FW-TRNG: UUID %g\n", Guid)); > + > + return RETURN_SUCCESS; > +} > + > +/** Returns maximum number of entropy bits that can be returned in a single > + call. > + > + @return Returns the maximum number of Entropy bits that can be returned > + in a single call to GetEntropy(). > +**/ > +UINTN > +EFIAPI > +GetTrngMaxSupportedEntropyBits ( > + VOID > + ) > +{ > + return MAX_ENTROPY_BITS; > +} > + > +/** Returns N bits of conditioned entropy. > + > + See [3] Section 2.3.1 GetEntropy: An Interface to the Entropy Source > + GetEntropy > + Input: > + bits_of_entropy: the requested amount of entropy > + Output: > + entropy_bitstring: The string that provides the requested entropy. > + status: A Boolean value that is TRUE if the request has been satisfied, > + and is FALSE otherwise. > + > + Note: In this implementation this function returns a status code instead > + of a boolean value. > + This is also compatible with the definition of Get_Entropy, see [2] > + Section 7.4 Entropy Source Calls. > + (status, entropy_bitstring) = Get_Entropy ( > + requested_entropy, > + max_length > + ) > + > + @param [in] EntropyBits Number of entropy bits requested. > + @param [out] Buffer Buffer to return the entropy bits. > + @param [in] BufferSize Size of the Buffer in bytes. > + > + @retval RETURN_SUCCESS The function completed successfully. > + @retval RETURN_INVALID_PARAMETER Invalid parameter. > + @retval RETURN_UNSUPPORTED Function not implemented. > + @retval RETURN_BAD_BUFFER_SIZE Buffer size is too small. > + @retval RETURN_NOT_READY No Entropy available. > +**/ > +RETURN_STATUS > +EFIAPI > +GetEntropy ( > + IN CONST UINTN EntropyBits, > + OUT UINT8 *Buffer, > + IN CONST UINTN BufferSize > + ) > +{ > + RETURN_STATUS Status; > + ARM_MONITOR_ARGS Parameters; > + UINTN EntropyBytes; > + UINTN LastValidBits; > + UINTN ArgSelector; > + UINTN BytesToClear; > + > + // [1] Section 2.4.3 Caller responsibilities. > + // The caller cannot request more than MAX_BITS bits of conditioned > + // entropy per call. Comment is redundant, code is clearer without it. > + if ((EntropyBits == 0) || (EntropyBits > MAX_ENTROPY_BITS)) { > + return RETURN_INVALID_PARAMETER; > + } > + > + EntropyBytes = (EntropyBits + 7) >> 3; > + if (EntropyBytes > BufferSize) { Not for later: we're verifying the value of EntropyBytes here - if there are more aspects of it that need verifying, that should also be done here. > + return RETURN_BAD_BUFFER_SIZE; > + } > + > + ZeroMem (Buffer, BufferSize); > + ZeroMem (&Parameters, sizeof (Parameters)); > + > + /* > + Cf. [1], Section 2.4 TRNG_RND > + Function ID (W0) 0x8400_0053 > + 0xC400_0053 > + SMC32 Parameters > + W1 N bits of entropy (1 6 N 6 96) > + W2-W7 Reserved (MBZ) > + SMC64 Parameters > + X1 N bits of entropy (1 6 N 6 192) > + X2-X7 Reserved (MBZ) > + SMC32 Returns > + Success (W0 = 0): > + W0 MBZ > + W1 Entropy[95:64] > + W2 Entropy[63:32] > + W3 Entropy[31:0] > + Error (W0 < 0) > + W0 NOT_SUPPORTED > + NO_ENTROPY > + INVALID_PARAMETERS > + W1 - W3 Reserved (MBZ) > + SMC64 Returns > + Success (X0 = 0): > + X0 MBZ > + X1 Entropy[191:128] > + X2 Entropy[127:64] > + X3 Entropy[63:0] > + Error (X0 < 0) > + X0 NOT_SUPPORTED > + NO_ENTROPY > + INVALID_PARAMETERS > + X1 - X3 Reserved (MBZ) > + */ The above comment block completely wrecks the readability of the function. Would suggest putting it in the header file describing the monitor call. For our SIP SVC calls, we've done this in the following form: /* * SMC call to retrieve number of CPUs present in the system. * Input values: * x0: NUVIA_SIP_GET_NUM_CPUS * Return values: * x0: SMC_OK * x1: Number of CPUs present */ #define NUVIA_SIP_GET_NUM_CPUS SIP_FUNCTION_ID(0x20) (Where SIP_FUNCTION_ID is one of a set of macros I should submit for addition to ArmStdSmc.h) > + Parameters.Arg0 = FID_TRNG_RND; > + Parameters.Arg1 = EntropyBits; > + ArmCallMonitor (&Parameters); > + > + // Convert status codes to EFI status codes. Function name already says this, comment redundant. > + Status = TrngStatusToEfiStatus ((INT32)Parameters.Arg0); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + >>From here > + // Extract Data > + // ArgSelector = ((EntropyBytes + 3) >> 2); for AArch32 > + // ArgSelector = ((EntropyBytes + 7) >> 3); for AArch64 > + // ((sizeof (UINTN) >> 2) + 1) is 3 or 2 depending on size of UINTN > + ArgSelector = ((EntropyBytes + (sizeof (UINTN) - 1)) >> > + ((sizeof (UINTN) >> 2) + 1)); > + > + switch (ArgSelector) { > + case 3: > + CopyMem (&Buffer[(sizeof (UINTN) * 2)], &Parameters.Arg1, sizeof (UINTN)); > + > + case 2: > + CopyMem (&Buffer[sizeof (UINTN)], &Parameters.Arg2, sizeof (UINTN)); > + > + case 1: > + CopyMem (&Buffer[0], &Parameters.Arg3, sizeof (UINTN)); > + break; > + > + default: > + ASSERT (0); > + return RETURN_INVALID_PARAMETER; > + } // switch to here ... I'm not convinced you yourself would be able to read or explain this code a few months down the line. Is there a strong reason for why Buffer cannot be a UINTN *? I think what this code is doing can equally be written as: Buffer[0] = Parameters.Arg3; if ((EntropyBytes / sizeof (UINTN)) > 1) { Buffer[1] = Parameters.Arg2; } if ((EntropyBytes / sizeof (UINTN)) > 2) { Buffer[2] = Parameters.Arg1; } > + > + > + // [1] Section 2.4.3 Caller responsibilities. > + // The caller must ensure that only the value in Entropy[N-1:0] is consumed > + // and that the remaining bits in Entropy[MAX_BITS-1:N] are ignored. > + // Therefore, Clear the unused upper bytes. This is source code, not the specification. // Mask off any unused top bytes, in accordance with specification is sufficient as a comment. / Leif > + BytesToClear = (sizeof (UINTN) * ArgSelector) - EntropyBytes; > + if (BytesToClear != 0) { > + ZeroMem (&Buffer[EntropyBytes], BytesToClear); > + } > + > + // Clear the unused MSB bits of the last byte. > + LastValidBits = EntropyBits & 0x7; > + if (LastValidBits != 0) { > + Buffer[EntropyBytes - 1] &= (0xFF >> (8 - LastValidBits)); > + } > + > + return Status; > +} > + > +/** The constructor checks that the FW-TRNG interface is supported > + by the host firmware. > + > + It will ASSERT() if FW-TRNG is not supported. > + It will always return RETURN_SUCCESS. > + > + @retval RETURN_SUCCESS The constructor always returns RETURN_SUCCESS. > +**/ > +RETURN_STATUS > +EFIAPI > +ArmFwTrngLibConstructor ( > + VOID > + ) > +{ > + RETURN_STATUS Status; > + UINT16 MajorRev; > + UINT16 MinorRev; > + GUID Guid; > + > + Status = GetTrngVersion (&MajorRev, &MinorRev); > + if (EFI_ERROR (Status)) { > + return RETURN_SUCCESS; > + } > + > +#ifndef MDEPKG_NDEBUG > + // Check that the required features are present. > + Status = GetTrngFeatures (FID_TRNG_RND, NULL); > + if (EFI_ERROR (Status)) { > + return RETURN_SUCCESS; > + } > + > + // Check if TRNG UUID is supported and if so trace the GUID. > + Status = GetTrngFeatures (FID_TRNG_GET_UUID, NULL); > + if (EFI_ERROR (Status)) { > + return RETURN_SUCCESS; > + } > +#endif > + > + Status = GetTrngUuid (&Guid); > + if (EFI_ERROR (Status)) { > + return RETURN_SUCCESS; > + } > + > + DEBUG (( > + DEBUG_INFO, > + "FW-TRNG: Version %d.%d, GUID {%g}\n", > + MajorRev, > + MinorRev, > + Guid > + )); > + > + return RETURN_SUCCESS; > +} > diff --git a/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf > new file mode 100644 > index 0000000000000000000000000000000000000000..4b2c58251fbe8fbcb5af308736db014e8d954720 > --- /dev/null > +++ b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf > @@ -0,0 +1,34 @@ > +## @file > +# Arm Firmware TRNG interface library. > +# > +# Copyright (c) 2021, Arm Limited. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Defines] > + INF_VERSION = 0x0001001B > + BASE_NAME = ArmFwTrngLib > + FILE_GUID = 10DE97C9-28E4-4C9B-A53E-8D7D1B0DD4E0 > + VERSION_STRING = 1.0 > + MODULE_TYPE = BASE > + LIBRARY_CLASS = TrngLib > + CONSTRUCTOR = ArmFwTrngLibConstructor > + > +[Sources] > + ArmFwTrngDefs.h > + ArmFwTrngLib.c > + > +[Packages] > + ArmPkg/ArmPkg.dec > + MdePkg/MdePkg.dec > + > +[LibraryClasses] > + ArmSmcLib > + ArmHvcLib > + BaseLib > + BaseMemoryLib > + > +[Pcd] > + gArmTokenSpaceGuid.PcdMonitorConduitHvc > + > -- > 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' > > > > > >