From: "PierreGondois" <pierre.gondois@arm.com>
To: devel@edk2.groups.io
Cc: Sami Mujawar <sami.mujawar@arm.com>,
Leif Lindholm <quic_llindhol@quicinc.com>,
Ard Biesheuvel <ardb+tianocore@kernel.org>,
Rebecca Cran <rebecca@bsdio.com>,
Michael D Kinney <michael.d.kinney@intel.com>,
Liming Gao <gaoliming@byosoft.com.cn>,
Jiewen Yao <jiewen.yao@intel.com>,
Jian J Wang <jian.j.wang@intel.com>
Subject: [PATCH v8 09/19] ArmPkg/TrngLib: Add Arm Firmware TRNG library
Date: Tue, 18 Oct 2022 15:20:42 +0200 [thread overview]
Message-ID: <20221018132052.1359530-10-Pierre.Gondois@arm.com> (raw)
In-Reply-To: <20221018132052.1359530-1-Pierre.Gondois@arm.com>
From: Sami Mujawar <sami.mujawar@arm.com>
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.
Acked-by: Leif Lindholm <quic_llindhol@quicinc.com>
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
ArmPkg/ArmPkg.dsc | 1 +
ArmPkg/Library/ArmFwTrngLib/ArmFwTrngDefs.h | 50 +++
ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.c | 388 +++++++++++++++++++
ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf | 29 ++
4 files changed, 468 insertions(+)
create mode 100644 ArmPkg/Library/ArmFwTrngLib/ArmFwTrngDefs.h
create mode 100644 ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.c
create mode 100644 ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf
diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc
index 11b473974463..8726989bc73d 100644
--- a/ArmPkg/ArmPkg.dsc
+++ b/ArmPkg/ArmPkg.dsc
@@ -131,6 +131,7 @@ [Components.common]
ArmPkg/Library/ArmGenericTimerPhyCounterLib/ArmGenericTimerPhyCounterLib.inf
ArmPkg/Library/ArmGenericTimerVirtCounterLib/ArmGenericTimerVirtCounterLib.inf
+ ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf
ArmPkg/Library/ArmHvcLib/ArmHvcLib.inf
ArmPkg/Library/ArmHvcLibNull/ArmHvcLibNull.inf
ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.inf
diff --git a/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngDefs.h b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngDefs.h
new file mode 100644
index 000000000000..8038a968b50f
--- /dev/null
+++ b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngDefs.h
@@ -0,0 +1,50 @@
+/** @file
+ Arm Firmware TRNG definitions.
+
+ Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.<BR>
+
+ 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_
+
+#include <IndustryStandard/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
+
+#if defined (MDE_CPU_ARM)
+
+/** FID to use on AArch32 platform to request entropy.
+*/
+#define ARM_SMC_ID_TRNG_RND ARM_SMC_ID_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 ARM_SMC_ID_TRNG_RND ARM_SMC_ID_TRNG_RND_AARCH64
+
+/** Maximum bits of entropy supported on AArch64.
+*/
+#define MAX_ENTROPY_BITS 192
+#else
+ #error "Firmware TRNG not supported. Unknown chipset."
+#endif
+
+#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 000000000000..426a6f221d78
--- /dev/null
+++ b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.c
@@ -0,0 +1,388 @@
+/** @file
+ Arm Firmware TRNG interface library.
+
+ Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - [1] 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)
+ - [2] 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
+**/
+
+#include <Base.h>
+#include <Library/ArmLib.h>
+#include <Library/ArmMonitorLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+
+#include "ArmFwTrngDefs.h"
+
+/** Convert TRNG status codes to RETURN status codes.
+
+ @param [in] TrngStatus TRNG status code.
+
+ @retval RETURN_SUCCESS Success.
+ @retval RETURN_UNSUPPORTED Function not implemented or
+ negative return code.
+ @retval RETURN_INVALID_PARAMETER A parameter is invalid.
+ @retval RETURN_NOT_READY No Entropy available.
+**/
+STATIC
+RETURN_STATUS
+TrngStatusToReturnStatus (
+ IN INT32 TrngStatus
+ )
+{
+ switch (TrngStatus) {
+ case TRNG_STATUS_NOT_SUPPORTED:
+ return RETURN_UNSUPPORTED;
+
+ case TRNG_STATUS_INVALID_PARAMETER:
+ return RETURN_INVALID_PARAMETER;
+
+ case TRNG_STATUS_NO_ENTROPY:
+ return RETURN_NOT_READY;
+
+ case TRNG_STATUS_SUCCESS:
+ return RETURN_SUCCESS;
+
+ default:
+ if (TrngStatus < 0) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ return RETURN_SUCCESS;
+ }
+}
+
+/** 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));
+
+ Parameters.Arg0 = ARM_SMC_ID_TRNG_VERSION;
+ ArmMonitorCall (&Parameters);
+
+ Revision = (INT32)Parameters.Arg0;
+ Status = TrngStatusToReturnStatus (Revision);
+ if (RETURN_ERROR (Status)) {
+ return Status;
+ }
+
+ *MinorRevision = (Revision & TRNG_REV_MINOR_MASK);
+ *MajorRevision = ((Revision >> TRNG_REV_MAJOR_SHIFT) & TRNG_REV_MAJOR_MASK);
+ return RETURN_SUCCESS;
+}
+
+/** 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.
+
+ @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;
+ RETURN_STATUS Status;
+
+ ZeroMem (&Parameters, sizeof (Parameters));
+
+ Parameters.Arg0 = ARM_SMC_ID_TRNG_FEATURES;
+ Parameters.Arg1 = FunctionId;
+ ArmMonitorCall (&Parameters);
+
+ Status = TrngStatusToReturnStatus (Parameters.Arg0);
+ if (RETURN_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Capability != NULL) {
+ *Capability = (UINT32)Parameters.Arg0;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+/** 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
+ )
+{
+ ARM_MONITOR_ARGS Parameters;
+
+ if (Guid == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ ZeroMem (&Parameters, sizeof (Parameters));
+
+ Parameters.Arg0 = ARM_SMC_ID_TRNG_GET_UUID;
+ ArmMonitorCall (&Parameters);
+
+ // Only invalid value is TRNG_STATUS_NOT_SUPPORTED (-1).
+ if ((INT32)Parameters.Arg0 == TRNG_STATUS_NOT_SUPPORTED) {
+ return TrngStatusToReturnStatus ((INT32)Parameters.Arg0);
+ }
+
+ 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 GetTrngEntropy().
+**/
+UINTN
+EFIAPI
+GetTrngMaxSupportedEntropyBits (
+ VOID
+ )
+{
+ return MAX_ENTROPY_BITS;
+}
+
+/** Returns N bits of conditioned entropy.
+
+ See [1] 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.
+
+ @param [in] EntropyBits Number of entropy bits requested.
+ @param [in] BufferSize Size of the Buffer in bytes.
+ @param [out] Buffer Buffer to return the entropy bits.
+
+ @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
+GetTrngEntropy (
+ IN UINTN EntropyBits,
+ IN UINTN BufferSize,
+ OUT UINT8 *Buffer
+ )
+{
+ RETURN_STATUS Status;
+ ARM_MONITOR_ARGS Parameters;
+ UINTN EntropyBytes;
+ UINTN LastValidBits;
+ UINTN BytesToClear;
+ UINTN EntropyData[3];
+
+ if ((EntropyBits == 0) ||
+ (EntropyBits > MAX_ENTROPY_BITS) ||
+ (Buffer == NULL))
+ {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ EntropyBytes = (EntropyBits + 7) >> 3;
+ if (EntropyBytes > BufferSize) {
+ return RETURN_BAD_BUFFER_SIZE;
+ }
+
+ ZeroMem (Buffer, BufferSize);
+ ZeroMem (&Parameters, sizeof (Parameters));
+
+ Parameters.Arg0 = ARM_SMC_ID_TRNG_RND;
+ Parameters.Arg1 = EntropyBits;
+ ArmMonitorCall (&Parameters);
+
+ Status = TrngStatusToReturnStatus ((INT32)Parameters.Arg0);
+ if (RETURN_ERROR (Status)) {
+ return Status;
+ }
+
+ // The entropy data is returned in the Parameters.Arg<3..1>
+ // With the lower order bytes in Parameters.Arg3 and the higher
+ // order bytes being stored in Parameters.Arg1.
+ EntropyData[0] = Parameters.Arg3;
+ EntropyData[1] = Parameters.Arg2;
+ EntropyData[2] = Parameters.Arg1;
+
+ CopyMem (Buffer, EntropyData, EntropyBytes);
+
+ // Mask off any unused top bytes, in accordance with specification.
+ BytesToClear = BufferSize - 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
+ )
+{
+ ARM_MONITOR_ARGS Parameters;
+ RETURN_STATUS Status;
+ UINT16 MajorRev;
+ UINT16 MinorRev;
+ GUID Guid;
+
+ ZeroMem (&Parameters, sizeof (Parameters));
+
+ Parameters.Arg0 = SMCCC_VERSION;
+ ArmMonitorCall (&Parameters);
+ Status = TrngStatusToReturnStatus ((INT32)Parameters.Arg0);
+ if (RETURN_ERROR (Status)) {
+ ASSERT_RETURN_ERROR (Status);
+ goto ErrorHandler;
+ }
+
+ // Cf [1] s2.1.3 'Caller responsibilities',
+ // SMCCC version must be greater or equal than 1.1
+ if ((INT32)Parameters.Arg0 < 0x10001) {
+ ASSERT_RETURN_ERROR (RETURN_UNSUPPORTED);
+ goto ErrorHandler;
+ }
+
+ Status = GetTrngVersion (&MajorRev, &MinorRev);
+ if (RETURN_ERROR (Status)) {
+ ASSERT_RETURN_ERROR (Status);
+ goto ErrorHandler;
+ }
+
+ // Check that the required features are present.
+ Status = GetTrngFeatures (ARM_SMC_ID_TRNG_RND, NULL);
+ if (RETURN_ERROR (Status)) {
+ ASSERT_RETURN_ERROR (Status);
+ goto ErrorHandler;
+ }
+
+ // Check if TRNG UUID is supported and if so trace the GUID.
+ Status = GetTrngFeatures (ARM_SMC_ID_TRNG_GET_UUID, NULL);
+ if (RETURN_ERROR (Status)) {
+ ASSERT_RETURN_ERROR (Status);
+ goto ErrorHandler;
+ }
+
+ DEBUG_CODE_BEGIN ();
+
+ Status = GetTrngUuid (&Guid);
+ if (RETURN_ERROR (Status)) {
+ ASSERT_RETURN_ERROR (Status);
+ goto ErrorHandler;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "FW-TRNG: Version %d.%d, GUID {%g}\n",
+ MajorRev,
+ MinorRev,
+ Guid
+ ));
+
+ DEBUG_CODE_END ();
+
+ return RETURN_SUCCESS;
+
+ErrorHandler:
+ DEBUG ((DEBUG_ERROR, "ArmFwTrngLib could not be correctly initialized.\n"));
+ return RETURN_SUCCESS;
+}
diff --git a/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf
new file mode 100644
index 000000000000..ae3eb9bcfe7d
--- /dev/null
+++ b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf
@@ -0,0 +1,29 @@
+## @file
+# Arm Firmware TRNG interface library.
+#
+# Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ 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]
+ ArmMonitorLib
+ BaseLib
+ BaseMemoryLib
--
2.25.1
next prev parent reply other threads:[~2022-10-18 13:30 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-18 13:20 [PATCH v8 00/19] Add Raw algorithm support using Arm FW-TRNG interface PierreGondois
2022-10-18 13:20 ` [PATCH v8 01/19] ArmPkg: PCD to select conduit for monitor calls PierreGondois
2022-10-18 13:20 ` [PATCH v8 02/19] ArmPkg/ArmMonitorLib: Definition for ArmMonitorLib library class PierreGondois
2022-10-18 13:20 ` [PATCH v8 03/19] ArmPkg/ArmMonitorLib: Add ArmMonitorLib PierreGondois
2022-10-18 13:20 ` [PATCH v8 04/19] ArmPkg: Sort HVC/SMC section alphbetically in ArmPkg.dsc PierreGondois
2022-10-18 13:20 ` [PATCH v8 05/19] ArmPkg/ArmHvcLibNull: Add NULL instance of ArmHvcLib PierreGondois
2022-10-18 13:20 ` [PATCH v8 06/19] MdePkg/TrngLib: Definition for TRNG library class interface PierreGondois
2022-10-26 13:25 ` [edk2-devel] " Yao, Jiewen
2022-10-26 13:56 ` Leif Lindholm
2022-10-26 14:06 ` Yao, Jiewen
2022-10-26 15:44 ` Leif Lindholm
2022-10-18 13:20 ` [PATCH v8 07/19] MdePkg/TrngLib: Add NULL instance of TRNG Library PierreGondois
2022-10-18 13:20 ` [PATCH v8 08/19] ArmPkg: Add FID definitions for Firmware TRNG PierreGondois
2022-10-20 8:55 ` Leif Lindholm
2022-10-18 13:20 ` PierreGondois [this message]
2022-10-18 13:20 ` [PATCH v8 10/19] SecurityPkg/RngDxe: Rename RdRandGenerateEntropy to generic name PierreGondois
2022-10-18 13:20 ` [PATCH v8 11/19] SecurityPkg/RngDxe: Replace Pcd with Sp80090Ctr256Guid PierreGondois
2022-10-18 13:20 ` [PATCH v8 12/19] SecurityPkg/RngDxe: Remove ArchGetSupportedRngAlgorithms() PierreGondois
2022-10-18 13:20 ` [PATCH v8 13/19] SecurityPkg/RngDxe: Documentation/include/parameter cleanup PierreGondois
2022-10-18 13:20 ` [PATCH v8 14/19] SecurityPkg/RngDxe: Check before advertising Cpu Rng algo PierreGondois
2022-10-18 13:20 ` [PATCH v8 15/19] SecurityPkg/RngDxe: Add AArch64 RawAlgorithm support through TrngLib PierreGondois
2022-10-18 13:20 ` [PATCH v8 16/19] SecurityPkg/RngDxe: Add debug warning for NULL PcdCpuRngSupportedAlgorithm PierreGondois
2022-10-18 13:20 ` [PATCH v8 17/19] SecurityPkg/RngDxe: Rename AArch64/RngDxe.c PierreGondois
2022-10-18 13:20 ` [PATCH v8 18/19] SecurityPkg/RngDxe: Add Arm support of RngDxe PierreGondois
2022-10-18 13:20 ` [PATCH v8 19/19] ArmVirtPkg: Kvmtool: Add RNG support using FW-TRNG interface PierreGondois
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221018132052.1359530-10-Pierre.Gondois@arm.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox