Date   

Re: 回复: [PATCH v3 0/2] MdePkg,SecurityPkg: Add support to RngDxe and BaseRngLib for AARCH64 RNDR

Ard Biesheuvel
 

On Tue, 11 May 2021 at 05:03, gaoliming <gaoliming@byosoft.com.cn> wrote:

Thanks for your update. This version patches are good to me.

Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
Merged as #1633

Thanks all,

-----邮件原件-----
发件人: Rebecca Cran <rebecca@nuviainc.com>
发送时间: 2021年5月11日 5:53
收件人: devel@edk2.groups.io; Jiewen Yao <jiewen.yao@intel.com>; Jian J
Wang <jian.j.wang@intel.com>; Michael D Kinney
<michael.d.kinney@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>;
Zhiguang Liu <zhiguang.liu@intel.com>; Ard Biesheuvel
<ardb+tianocore@kernel.org>; Sami Mujawar <sami.mujawar@arm.com>
抄送: Rebecca Cran <rebecca@nuviainc.com>
主题: [PATCH v3 0/2] MdePkg,SecurityPkg: Add support to RngDxe and
BaseRngLib for AARCH64 RNDR

Update MdePkg BaseRngLib and SecurityPkg RngDxe to add support for
the AARCH64 RNDR instruction.

Changes from v2 to v3:

o Fixed the default value of
gEfiSecurityPkgTokenSpaceGuid.PcdCpuRngSupportedAlgorithm
to be an empty GUID.
o Removed RNDRRS since it wasn't being used.
o Fixed the commit message to remove mention of BaseLib.

Rebecca Cran (2):
MdePkg/BaseRngLib: Add support for ARMv8.5 RNG instructions
SecurityPkg: Add support for RngDxe on AARCH64

MdePkg/MdePkg.dec
| 9 +-
SecurityPkg/SecurityPkg.dec |
2 +
MdePkg/MdePkg.dsc
| 4 +-
SecurityPkg/SecurityPkg.dsc |
11 +-
MdePkg/Library/BaseRngLib/BaseRngLib.inf |
23 ++-
SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf |
24 ++-
MdePkg/Library/BaseRngLib/AArch64/ArmRng.h |
43 +++++
MdePkg/Library/BaseRngLib/BaseRngLibInternals.h |
78 +++++++++
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/AesCore.h |
0
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/RdRand.h |
17 --
SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h |
117 ++++++++++++++
MdePkg/Library/BaseRngLib/AArch64/Rndr.c |
139 ++++++++++++++++
MdePkg/Library/BaseRngLib/BaseRng.c |
87 +++++-----
MdePkg/Library/BaseRngLib/Rand/RdRand.c |
131 +++++++++++++++
SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c |
127 +++++++++++++++
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/AesCore.c |
0
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/RdRand.c |
45 +-----
SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c |
146 +++++++++++++++++
SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c |
170 ++++++++------------
MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.S |
31 ++++
MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.asm |
30 ++++
MdePkg/Library/BaseRngLib/AArch64/ArmRng.S |
37 +++++
MdePkg/Library/BaseRngLib/AArch64/ArmRng.asm |
39 +++++
MdePkg/Library/BaseRngLib/BaseRngLib.uni |
6 +-
24 files changed, 1086 insertions(+), 230 deletions(-)
create mode 100644 MdePkg/Library/BaseRngLib/AArch64/ArmRng.h
create mode 100644 MdePkg/Library/BaseRngLib/BaseRngLibInternals.h
rename SecurityPkg/RandomNumberGenerator/RngDxe/{ =>
Rand}/AesCore.h (100%)
rename SecurityPkg/RandomNumberGenerator/RngDxe/{ =>
Rand}/RdRand.h (72%)
create mode 100644
SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
create mode 100644 MdePkg/Library/BaseRngLib/AArch64/Rndr.c
create mode 100644 MdePkg/Library/BaseRngLib/Rand/RdRand.c
create mode 100644
SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
rename SecurityPkg/RandomNumberGenerator/RngDxe/{ =>
Rand}/AesCore.c (100%)
rename SecurityPkg/RandomNumberGenerator/RngDxe/{ =>
Rand}/RdRand.c (71%)
create mode 100644
SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
create mode 100644
MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.S
create mode 100644
MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.asm
create mode 100644 MdePkg/Library/BaseRngLib/AArch64/ArmRng.S
create mode 100644 MdePkg/Library/BaseRngLib/AArch64/ArmRng.asm

--
2.26.2







Re: [PATCH] IntelSiliconPkg/VTd: Support queued invalidation interface

Huang, Jenny <jenny.huang@...>
 

Reviewed by Jenny Huang.

-----Original Message-----
From: Sheng, W <w.sheng@intel.com>
Sent: Thursday, April 29, 2021 11:55 PM
To: devel@edk2.groups.io
Cc: Huang, Jenny <jenny.huang@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>
Subject: [PATCH] IntelSiliconPkg/VTd: Support queued invalidation interface

Add queued invalidation interface support for VTd core driver.
For software to invalidate the various caching structures, the architecture supports the following two types of invalidation interfaces.
1. Register-based invalidation interface 2. Queued invalidation interface.
BIOS shall check VER_REG to determine if register based invalidation can be used. Only for Major Version 6 or lower can support register based invalidation. For any version newer than that should use queue invalidation interface instead.

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3366

Signed-off-by: Sheng Wei <w.sheng@intel.com>
Cc: Jenny Huang <jenny.huang@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
---
.../Feature/VTd/IntelVTdDmarPei/DmarTable.c | 2 +
.../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c | 443 +++++++++++++++++++--
.../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c | 15 + .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h | 19 +
.../Feature/VTd/IntelVTdDmarPei/TranslationTable.c | 2 -
.../Feature/VTd/IntelVTdDxe/DmaProtection.h | 29 ++
.../Feature/VTd/IntelVTdDxe/VtdReg.c | 313 +++++++++++++--
.../IntelSiliconPkg/Include/IndustryStandard/Vtd.h | 57 +++
8 files changed, 813 insertions(+), 67 deletions(-)

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
index d188f917..2154690d 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTabl
+++ e.c
@@ -561,6 +561,8 @@ ProcessDhrd (
DEBUG ((DEBUG_INFO," VTD BaseAddress - 0x%016lx\n", DmarDrhd->RegisterBaseAddress));
VTdUnitInfo->VtdUnitBaseAddress = (UINT32) DmarDrhd->RegisterBaseAddress;

+ VTdUnitInfo->EnableQueuedInvalidation = 0;
+
DEBUG ((DEBUG_INFO," VTD Segment - %d\n", DmarDrhd->SegmentNumber));
VTdUnitInfo->Segment = DmarDrhd->SegmentNumber;

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
index 9ad2a494..f0bd7dc6 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTd
+++ Dmar.c
@@ -66,30 +66,269 @@ FlushWriteBuffer (
}

/**
- Invalidate VTd context cache.
+ Perpare cache invalidation interface.

- @param[in] VtdUnitBaseAddress The base address of the VTd engine.
+ @param[in] VTdUnitInfo The VTd engine unit information.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_UNSUPPORTED Invalidation method is not supported.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
**/
EFI_STATUS
-InvalidateContextCache (
- IN UINTN VtdUnitBaseAddress
+PerpareCacheInvalidationInterface (
+ IN VTD_UNIT_INFO *VTdUnitInfo
)
{
- UINT64 Reg64;
+ UINT16 QueueSize;
+ UINT64 Reg64;
+ UINT32 Reg32;
+ VTD_ECAP_REG ECapReg;
+
+
+ if (VTdUnitInfo->VerReg.Bits.Major <= 6) {
+ VTdUnitInfo->EnableQueuedInvalidation = 0;
+ DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for engine [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress));
+ return EFI_SUCCESS;
+ }
+
+ ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
+ R_ECAP_REG); if (ECapReg.Bits.QI == 0) {
+ DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations interface for engine [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress));
+ return EFI_UNSUPPORTED;
+ }
+
+ VTdUnitInfo->EnableQueuedInvalidation = 1; DEBUG ((DEBUG_INFO, "Use
+ Queued Invalidation Interface for engine [0x%x]\n",
+ VTdUnitInfo->VtdUnitBaseAddress));
+
+ Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
+ R_GSTS_REG); if ((Reg32 & B_GSTS_REG_QIES) != 0) {
+ DEBUG ((DEBUG_INFO,"Queued Invalidation Interface was enabled.\n"));
+ Reg32 &= (~B_GSTS_REG_QIES);
+ MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ do {
+ Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ } while ((Reg32 & B_GSTS_REG_QIES) != 0);
+ MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQA_REG,
+ 0);
+
+ if (VTdUnitInfo->QiDesc != NULL) {
+ FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * VTdUnitInfo->QiDescLength));
+ VTdUnitInfo->QiDesc = NULL;
+ VTdUnitInfo->QiDescLength = 0;
+ }
+ }
+
+ //
+ // Initialize the Invalidation Queue Tail Register to zero.
+ //
+ MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, 0);
+
+ //
+ // Setup the IQ address, size and descriptor width through the
+ Invalidation Queue Address Register // QueueSize = 0;
+ VTdUnitInfo->QiDescLength = 1 << (QueueSize + 8); VTdUnitInfo->QiDesc
+ = (QI_DESC *) AllocatePages (EFI_SIZE_TO_PAGES(sizeof(QI_DESC) *
+ VTdUnitInfo->QiDescLength));
+
+ if (VTdUnitInfo->QiDesc == NULL) {
+ VTdUnitInfo->QiDescLength = 0;
+ DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n",
+ VTdUnitInfo->QiDescLength));
+ Reg64 = (UINT64) VTdUnitInfo->QiDesc;
+ Reg64 |= QueueSize;
+ MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQA_REG,
+ Reg64);
+
+ //
+ // Enable the queued invalidation interface through the Global Command Register.
+ // When enabled, hardware sets the QIES field in the Global Status Register.
+ //
+ Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
+ R_GSTS_REG);
+ Reg32 |= B_GMCD_REG_QIE;
+ MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG,
+ Reg32); DEBUG ((DEBUG_INFO, "Enable Queued Invalidation Interface.
+ GCMD_REG = 0x%x\n", Reg32)); do {
+ Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
+ R_GSTS_REG); } while ((Reg32 & B_GSTS_REG_QIES) == 0);
+
+ VTdUnitInfo->QiFreeHead = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Disable queued invalidation interface.
+
+ @param[in] VTdUnitInfo The VTd engine unit information.
+**/
+VOID
+DisableQueuedInvalidationInterface (
+ IN VTD_UNIT_INFO *VTdUnitInfo
+ )
+{
+ UINT32 Reg32;
+
+ if (VTdUnitInfo->EnableQueuedInvalidation != 0) {
+ Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 &= (~B_GMCD_REG_QIE);
+ MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ DEBUG ((DEBUG_INFO, "Disable Queued Invalidation Interface. GCMD_REG = 0x%x\n", Reg32));
+ do {
+ Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+ } while ((Reg32 & B_GSTS_REG_QIES) != 0);
+
+ if (VTdUnitInfo->QiDesc != NULL) {
+ FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * VTdUnitInfo->QiDescLength));
+ VTdUnitInfo->QiDesc = NULL;
+ VTdUnitInfo->QiDescLength = 0;
+ }
+
+ VTdUnitInfo->EnableQueuedInvalidation = 0;
+ }
+}
+
+/**
+ Check Queued Invalidation Fault.
+
+ @param[in] VTdUnitInfo The VTd engine unit information.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval RETURN_DEVICE_ERROR A fault is detected.
+**/
+EFI_STATUS
+QueuedInvalidationCheckFault (
+ IN VTD_UNIT_INFO *VTdUnitInfo
+ )
+{
+ UINT32 fault_reg;
+
+ fault_reg = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
+ R_FSTS_REG);
+
+ if (fault_reg & B_FSTS_REG_IQE) {
+ DEBUG((DEBUG_ERROR, "Detect Invalidation Queue Error [0x%08x]\n", fault_reg));
+ fault_reg |= B_FSTS_REG_IQE;
+ MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, fault_reg);
+ return RETURN_DEVICE_ERROR;
+ }
+
+ if (fault_reg & B_FSTS_REG_ITE) {
+ DEBUG((DEBUG_ERROR, "Detect Invalidation Time-out Error [0x%08x]\n", fault_reg));
+ fault_reg |= B_FSTS_REG_ITE;
+ MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, fault_reg);
+ return RETURN_DEVICE_ERROR;
+ }
+
+ if (fault_reg & B_FSTS_REG_ICE) {
+ DEBUG((DEBUG_ERROR, "Detect Invalidation Completion Error [0x%08x]\n", fault_reg));
+ fault_reg |= B_FSTS_REG_ICE;
+ MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, fault_reg);
+ return RETURN_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Submit the queued invalidation descriptor to the remapping
+ hardware unit and wait for its completion.

- Reg64 = MmioRead64 (VtdUnitBaseAddress + R_CCMD_REG);
- if ((Reg64 & B_CCMD_REG_ICC) != 0) {
- DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%x)\n",VtdUnitBaseAddress));
- return EFI_DEVICE_ERROR;
+ @param[in] VTdUnitInfo The VTd engine unit information.
+ @param[in] desc The invalidate descriptor
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval RETURN_DEVICE_ERROR A fault is detected.
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.
+**/
+EFI_STATUS
+SubmitQueuedInvalidationDescriptor (
+ IN VTD_UNIT_INFO *VTdUnitInfo,
+ IN QI_DESC *desc
+ )
+{
+ EFI_STATUS rc;
+ UINT16 QiDescLength;
+ QI_DESC *BaseDesc;
+ UINT64 Reg64Iqt;
+ UINT64 Reg64Iqh;
+
+ if (desc == NULL) {
+ return EFI_INVALID_PARAMETER;
}

- Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));
- Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);
- MmioWrite64 (VtdUnitBaseAddress + R_CCMD_REG, Reg64);
+ QiDescLength = VTdUnitInfo->QiDescLength; BaseDesc =
+ VTdUnitInfo->QiDesc;
+
+ DEBUG((DEBUG_INFO, "[0x%x] Submit QI Descriptor [0x%08x, 0x%08x]\n",
+ VTdUnitInfo->VtdUnitBaseAddress, desc->low, desc->high));
+
+ BaseDesc[VTdUnitInfo->QiFreeHead].low = desc->low;
+ BaseDesc[VTdUnitInfo->QiFreeHead].high = desc->high;
+ FlushPageTableMemory(VTdUnitInfo, (UINTN)
+ &BaseDesc[VTdUnitInfo->QiFreeHead], sizeof(QI_DESC));
+
+ DEBUG((DEBUG_INFO,"QI Free Head=0x%x\n", VTdUnitInfo->QiFreeHead));
+ VTdUnitInfo->QiFreeHead = (VTdUnitInfo->QiFreeHead + 1) %
+ QiDescLength;
+
+ Reg64Iqh = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
+ R_IQH_REG); // // Update the HW tail register indicating the
+ presence of new descriptors.
+ //
+ Reg64Iqt = VTdUnitInfo->QiFreeHead << DMAR_IQ_SHIFT;
+ MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG,
+ Reg64Iqt);

+ rc = EFI_SUCCESS;
do {
- Reg64 = MmioRead64 (VtdUnitBaseAddress + R_CCMD_REG);
- } while ((Reg64 & B_CCMD_REG_ICC) != 0);
+ rc = QueuedInvalidationCheckFault(VTdUnitInfo);
+ if (rc != EFI_SUCCESS) {
+ DEBUG((DEBUG_ERROR,"Detect Queued Invalidation Fault.\n"));
+ break;
+ }
+
+ Reg64Iqh = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
+ R_IQH_REG); } while (Reg64Iqt != Reg64Iqh);
+
+ DEBUG((DEBUG_ERROR,"SubmitQueuedInvalidationDescriptor end\n"));
+ return rc;
+}
+
+/**
+ Invalidate VTd context cache.
+
+ @param[in] VTdUnitInfo The VTd engine unit information.
+**/
+EFI_STATUS
+InvalidateContextCache (
+ IN VTD_UNIT_INFO *VTdUnitInfo
+ )
+{
+ UINT64 Reg64;
+ QI_DESC QiDesc;
+
+ if (VTdUnitInfo->EnableQueuedInvalidation == 0) {
+ //
+ // Register-based Invalidation
+ //
+ Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);
+ if ((Reg64 & B_CCMD_REG_ICC) != 0) {
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%x)\n", (UINTN)VTdUnitInfo->VtdUnitBaseAddress));
+ return EFI_DEVICE_ERROR;
+ }
+
+ Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));
+ Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);
+ MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG,
+ Reg64);
+
+ do {
+ Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);
+ } while ((Reg64 & B_CCMD_REG_ICC) != 0); } else {
+ //
+ // Queued Invalidation
+ //
+ QiDesc.low = QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC_GRAN(1) | QI_CC_TYPE;
+ QiDesc.high = 0;
+
+ return SubmitQueuedInvalidationDescriptor(VTdUnitInfo, &QiDesc); }

return EFI_SUCCESS;
}
@@ -97,31 +336,102 @@ InvalidateContextCache (
/**
Invalidate VTd IOTLB.

- @param[in] VtdUnitBaseAddress The base address of the VTd engine.
+ @param[in] VTdUnitInfo The VTd engine unit information.
**/
EFI_STATUS
InvalidateIOTLB (
- IN UINTN VtdUnitBaseAddress
+ IN VTD_UNIT_INFO *VTdUnitInfo
)
{
UINT64 Reg64;
VTD_ECAP_REG ECapReg;
+ QI_DESC QiDesc;
+
+ if (VTdUnitInfo->EnableQueuedInvalidation == 0) {
+ //
+ // Register-based Invalidation
+ //
+ ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress
+ + R_ECAP_REG);
+
+ Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
+ if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
+ DEBUG ((DEBUG_ERROR, "ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set for VTD(%x)\n", (UINTN)VTdUnitInfo->VtdUnitBaseAddress));
+ return EFI_DEVICE_ERROR;
+ }

- ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);
+ Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
+ Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);
+ MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
+ (ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);

- Reg64 = MmioRead64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
- if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
- DEBUG ((DEBUG_ERROR, "ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set for VTD(%x)\n", VtdUnitBaseAddress));
- return EFI_DEVICE_ERROR;
+ do {
+ Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
+ } while ((Reg64 & B_IOTLB_REG_IVT) != 0); } else {
+ //
+ // Queued Invalidation
+ //
+ ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
+ QiDesc.low = QI_IOTLB_DID(0) | QI_IOTLB_DR(cap_read_drain(ECapReg.Uint64)) | QI_IOTLB_DW(cap_write_drain(ECapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE;
+ QiDesc.high = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0);
+
+ return SubmitQueuedInvalidationDescriptor(VTdUnitInfo, &QiDesc);
}

- Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
- Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);
- MmioWrite64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
+ return EFI_SUCCESS;
+}
+
+/**
+ Enable DMAR translation inpre-mem phase.
+
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.
+ @param[in] RootEntryTable The address of the VTd RootEntryTable.
+
+ @retval EFI_SUCCESS DMAR translation is enabled.
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.
+**/
+EFI_STATUS
+EnableDmarPreMem (
+ IN UINTN VtdUnitBaseAddress,
+ IN UINTN RootEntryTable
+ )
+{
+ UINT32 Reg32;
+
+ DEBUG ((DEBUG_INFO, ">>>>>>EnableDmarPreMem() for engine [%x] \n",
+ VtdUnitBaseAddress));
+
+ DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
+ MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) (UINTN)
+ RootEntryTable);
+
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 |
+ B_GMCD_REG_SRTP);
+
+ DEBUG ((DEBUG_INFO, "EnableDmarPreMem: waiting for RTPS bit to be
+ set... \n")); do {
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); }
+ while((Reg32 & B_GSTS_REG_RTPS) == 0); DEBUG ((DEBUG_INFO,
+ "EnableDmarPreMem: R_GSTS_REG = 0x%x \n", Reg32));

+ //
+ // Init DMAr Fault Event and Data registers //
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG);
+
+ //
+ // Write Buffer Flush before invalidation // FlushWriteBuffer
+ (VtdUnitBaseAddress);
+
+ //
+ // Enable VTd
+ //
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_TE);
+ DEBUG ((DEBUG_INFO, "EnableDmarPreMem: Waiting B_GSTS_REG_TE ...\n"));
do {
- Reg64 = MmioRead64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
- } while ((Reg64 & B_IOTLB_REG_IVT) != 0);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); } while
+ ((Reg32 & B_GSTS_REG_TE) == 0);
+
+ DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n"));

return EFI_SUCCESS;
}
@@ -129,59 +439,62 @@ InvalidateIOTLB (
/**
Enable DMAR translation.

- @param[in] VtdUnitBaseAddress The base address of the VTd engine.
- @param[in] RootEntryTable The address of the VTd RootEntryTable.
+ @param[in] VTdUnitInfo The VTd engine unit information.
+ @param[in] RootEntryTable The address of the VTd RootEntryTable.

@retval EFI_SUCCESS DMAR translation is enabled.
@retval EFI_DEVICE_ERROR DMAR translation is not enabled.
**/
EFI_STATUS
EnableDmar (
- IN UINTN VtdUnitBaseAddress,
+ IN VTD_UNIT_INFO *VTdUnitInfo,
IN UINTN RootEntryTable
)
{
UINT32 Reg32;

- DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VtdUnitBaseAddress));
+ DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n",
+ VTdUnitInfo->VtdUnitBaseAddress));

DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
- MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) (UINTN) RootEntryTable);
+ MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_RTADDR_REG,
+ (UINT64) (UINTN) RootEntryTable);

- MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);
+ Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
+ R_GSTS_REG);
+ MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG,
+ Reg32 | B_GMCD_REG_SRTP);

DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
do {
- Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
+ R_GSTS_REG);
} while((Reg32 & B_GSTS_REG_RTPS) == 0);
+ DEBUG ((DEBUG_INFO, "EnableDmar: R_GSTS_REG = 0x%x \n", Reg32));

//
// Init DMAr Fault Event and Data registers
//
- Reg32 = MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG);
+ Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
+ R_FEDATA_REG);

//
// Write Buffer Flush before invalidation
//
- FlushWriteBuffer (VtdUnitBaseAddress);
+ FlushWriteBuffer ((UINTN)VTdUnitInfo->VtdUnitBaseAddress);

//
// Invalidate the context cache
//
- InvalidateContextCache (VtdUnitBaseAddress);
+ InvalidateContextCache (VTdUnitInfo);

//
// Invalidate the IOTLB cache
//
- InvalidateIOTLB (VtdUnitBaseAddress);
+ InvalidateIOTLB (VTdUnitInfo);

//
// Enable VTd
//
- MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_TE);
+ Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
+ R_GSTS_REG);
+ MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG,
+ Reg32 | B_GMCD_REG_TE);
DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
do {
- Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress +
+ R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_TE) == 0);

DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n")); @@ -286,7 +599,7 @@ EnableVTdTranslationProtectionAll (
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
- EnableDmar ((UINTN) VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress, (UINTN) *RootEntryTable);
+ EnableDmarPreMem (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress,
+ (UINTN) *RootEntryTable);
}

return;
@@ -311,10 +624,10 @@ EnableVTdTranslationProtection (
for (VtdIndex = 0; VtdIndex < VTdInfo->VTdEngineCount; VtdIndex++) {
if (VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable != 0) {
DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) ExtRootEntryTable 0x%x\n", VtdIndex, VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable));
- Status = EnableDmar (VTdInfo->VtdUnitInfo[VtdIndex].VtdUnitBaseAddress, VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable);
+ Status = EnableDmar (&VTdInfo->VtdUnitInfo[VtdIndex],
+ VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable);
} else {
DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) RootEntryTable 0x%x\n", VtdIndex, VTdInfo->VtdUnitInfo[VtdIndex].RootEntryTable));
- Status = EnableDmar (VTdInfo->VtdUnitInfo[VtdIndex].VtdUnitBaseAddress, VTdInfo->VtdUnitInfo[VtdIndex].RootEntryTable);
+ Status = EnableDmar (&VTdInfo->VtdUnitInfo[VtdIndex],
+ VTdInfo->VtdUnitInfo[VtdIndex].RootEntryTable);
}
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "EnableVtdDmar (%d) Failed !\n", VtdIndex)); @@ -345,11 +658,28 @@ DisableVTdTranslationProtection (
continue;
}
DisableDmar ((UINTN) VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress);
+
+ DisableQueuedInvalidationInterface(&VTdInfo->VtdUnitInfo[Index]);
}

return;
}

+/**
+ Dump VTd version registers.
+
+ @param[in] VerReg The version register.
+**/
+VOID
+DumpVtdVerRegs (
+ IN VTD_VER_REG *VerReg
+ )
+{
+ DEBUG ((DEBUG_INFO, " VerReg:\n", VerReg->Uint32));
+ DEBUG ((DEBUG_INFO, " Major - 0x%x\n", VerReg->Bits.Major));
+ DEBUG ((DEBUG_INFO, " Minor - 0x%x\n", VerReg->Bits.Minor));
+}
+
/**
Dump VTd capability registers.

@@ -414,6 +744,31 @@ DumpVtdECapRegs (
DEBUG ((DEBUG_INFO, " PSS - 0x%x\n", ECapReg->Bits.PSS));
}

+/**
+ Prepare VTD cache invalidation configuration.
+
+ @param[in] VTdInfo The VTd engine context information.
+
+ @retval EFI_SUCCESS Prepare Vtd config success
+**/
+EFI_STATUS
+PrepareVtdCacheInvalidationConfig (
+ IN VTD_INFO *VTdInfo
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+
+ for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
+ Status = PerpareCacheInvalidationInterface(&VTdInfo->VtdUnitInfo[Index]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
/**
Prepare VTD configuration.

@@ -431,6 +786,9 @@ PrepareVtdConfig (

for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
DEBUG ((DEBUG_ERROR, "Dump VTd Capability (%d)\n", Index));
+ VTdInfo->VtdUnitInfo[Index].VerReg.Uint32 = MmioRead32 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_VER_REG);
+ VTdInfo->VtdUnitInfo[Index].VerReg.Bits.Major = 7;
+ DumpVtdVerRegs (&VTdInfo->VtdUnitInfo[Index].VerReg);
VTdInfo->VtdUnitInfo[Index].CapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_CAP_REG);
DumpVtdCapRegs (&VTdInfo->VtdUnitInfo[Index].CapReg);
VTdInfo->VtdUnitInfo[Index].ECapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_ECAP_REG); @@ -464,3 +822,4 @@ PrepareVtdConfig (
return EFI_SUCCESS;
}

+
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c
index f3c4a2bc..a8f7bfee 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTd
+++ DmarPei.c
@@ -482,6 +482,7 @@ InitVTdDmarForAll (
VOID *Hob;
VTD_INFO *VTdInfo;
UINT64 EngineMask;
+ EFI_STATUS Status;

Hob = GetFirstGuidHob (&mVTdInfoGuid);
if (Hob == NULL) {
@@ -491,6 +492,13 @@ InitVTdDmarForAll (
VTdInfo = GET_GUID_HOB_DATA (Hob);
EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;

+ DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n")); Status =
+ PrepareVtdConfig (VTdInfo); if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
EnableVTdTranslationProtectionAll (VTdInfo, EngineMask);

return EFI_SUCCESS;
@@ -596,6 +604,13 @@ InitVTdDmarForDma (
return Status;
}

+ DEBUG ((DEBUG_INFO, "PrepareVtdCacheInvalidationConfig\n"));
+ Status = PrepareVtdCacheInvalidationConfig (VTdInfo); if (EFI_ERROR
+ (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
// create root entry table
DEBUG ((DEBUG_INFO, "SetupTranslationTable\n"));
Status = SetupTranslationTable (VTdInfo); diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
index a3bb8827..e23a6c8e 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTd
+++ DmarPei.h
@@ -11,6 +11,8 @@

#define MAX_VTD_PCI_DATA_NUMBER 0x100

+#define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi,
+32))
+
typedef struct {
UINT8 DeviceType;
VTD_SOURCE_ID PciSourceId;
@@ -27,6 +29,7 @@ typedef struct {
typedef struct {
UINT32 VtdUnitBaseAddress;
UINT16 Segment;
+ VTD_VER_REG VerReg;
VTD_CAP_REG CapReg;
VTD_ECAP_REG ECapReg;
BOOLEAN Is5LevelPaging;
@@ -37,6 +40,10 @@ typedef struct {
UINT16 RootEntryTablePageSize;
UINT16 ExtRootEntryTablePageSize;
PEI_PCI_DEVICE_INFORMATION PciDeviceInfo;
+ UINT8 EnableQueuedInvalidation;
+ UINT16 QiDescLength;
+ QI_DESC *QiDesc;
+ UINT16 QiFreeHead;
} VTD_UNIT_INFO;

typedef struct {
@@ -123,6 +130,18 @@ DumpAcpiDMAR (
IN EFI_ACPI_DMAR_HEADER *Dmar
);

+/**
+ Prepare VTD cache invalidation configuration.
+
+ @param[in] VTdInfo The VTd engine context information.
+
+ @retval EFI_SUCCESS Prepare Vtd config success
+**/
+EFI_STATUS
+PrepareVtdCacheInvalidationConfig (
+ IN VTD_INFO *VTdInfo
+ );
+
/**
Prepare VTD configuration.

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c
index d417f5af..341e2beb 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/Translat
+++ ionTable.c
@@ -26,8 +26,6 @@
#define ALIGN_VALUE_UP(Value, Alignment) (((Value) + (Alignment) - 1) & (~((Alignment) - 1))) #define ALIGN_VALUE_LOW(Value, Alignment) ((Value) & (~((Alignment) - 1)))

-#define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32))
-
/**
Allocate zero pages.

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
index f641cea0..a24fbc37 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtectio
+++ n.h
@@ -69,6 +69,7 @@ typedef struct {
typedef struct {
UINTN VtdUnitBaseAddress;
UINT16 Segment;
+ VTD_VER_REG VerReg;
VTD_CAP_REG CapReg;
VTD_ECAP_REG ECapReg;
VTD_ROOT_ENTRY *RootEntryTable;
@@ -78,6 +79,10 @@ typedef struct {
BOOLEAN HasDirtyPages;
PCI_DEVICE_INFORMATION PciDeviceInfo;
BOOLEAN Is5LevelPaging;
+ UINT8 EnableQueuedInvalidation;
+ UINT16 QiDescLength;
+ QI_DESC *QiDesc;
+ UINT16 QiFreeHead;
} VTD_UNIT_INFORMATION;

//
@@ -179,6 +184,20 @@ FlushWriteBuffer (
IN UINTN VtdIndex
);

+/**
+ Perpare cache invalidation interface.
+
+ @param[in] VtdIndex The index used to identify a VTd engine.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_UNSUPPORTED Invalidation method is not supported.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+PerpareCacheInvalidationInterface (
+ IN UINTN VtdIndex
+ );
+
/**
Invalidate VTd context cache.

@@ -230,6 +249,16 @@ DumpVtdRegsAll (
VOID
);

+/**
+ Dump VTd version registers.
+
+ @param[in] VerReg The version register.
+**/
+VOID
+DumpVtdVerRegs (
+ IN VTD_VER_REG *VerReg
+ );
+
/**
Dump VTd capability registers.

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
index 686d235f..1049e940 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
@@ -55,31 +55,256 @@ FlushWriteBuffer (
}

/**
- Invalidate VTd context cache.
+ Perpare cache invalidation interface.

@param[in] VtdIndex The index used to identify a VTd engine.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_UNSUPPORTED Invalidation method is not supported.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
**/
EFI_STATUS
-InvalidateContextCache (
+PerpareCacheInvalidationInterface (
IN UINTN VtdIndex
)
{
+ UINT16 QueueSize;
UINT64 Reg64;
+ UINT32 Reg32;

- Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);
- if ((Reg64 & B_CCMD_REG_ICC) != 0) {
- DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%d)\n",VtdIndex));
- return EFI_DEVICE_ERROR;
+ if (mVtdUnitInformation[VtdIndex].VerReg.Bits.Major <= 6) {
+ mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation = 0;
+ DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for engine [%d]\n", VtdIndex));
+ return EFI_SUCCESS;
+ }
+
+ if (mVtdUnitInformation[VtdIndex].ECapReg.Bits.QI == 0) {
+ DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations interface for engine [%d]\n", VtdIndex));
+ return EFI_UNSUPPORTED;
+ }
+
+ mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation = 1; DEBUG
+ ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [%d]\n",
+ VtdIndex));
+
+ Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress
+ + R_GSTS_REG); if ((Reg32 & B_GSTS_REG_QIES) != 0) {
+ DEBUG ((DEBUG_ERROR,"Queued Invalidation Interface was enabled.\n"));
+ Reg32 &= (~B_GSTS_REG_QIES);
+ MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ do {
+ Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
+ } while ((Reg32 & B_GSTS_REG_QIES) != 0); }
+
+ //
+ // Initialize the Invalidation Queue Tail Register to zero.
+ //
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
+ R_IQT_REG, 0);
+
+ //
+ // Setup the IQ address, size and descriptor width through the
+ Invalidation Queue Address Register // QueueSize = 0;
+ mVtdUnitInformation[VtdIndex].QiDescLength = 1 << (QueueSize + 8);
+ mVtdUnitInformation[VtdIndex].QiDesc = (QI_DESC *) AllocatePages
+ (EFI_SIZE_TO_PAGES(sizeof(QI_DESC) *
+ mVtdUnitInformation[VtdIndex].QiDescLength));
+
+ if (mVtdUnitInformation[VtdIndex].QiDesc == NULL) {
+ mVtdUnitInformation[VtdIndex].QiDescLength = 0;
+ DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n",
+ mVtdUnitInformation[VtdIndex].QiDescLength));
+ Reg64 = (UINT64) mVtdUnitInformation[VtdIndex].QiDesc;
+ Reg64 |= QueueSize;
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
+ R_IQA_REG, Reg64);
+
+ //
+ // Enable the queued invalidation interface through the Global Command Register.
+ // When enabled, hardware sets the QIES field in the Global Status Register.
+ //
+ Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress
+ + R_GSTS_REG);
+ Reg32 |= B_GMCD_REG_QIE;
+ MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
+ R_GCMD_REG, Reg32); DEBUG ((DEBUG_INFO, "Enable Queued Invalidation
+ Interface. GCMD_REG = 0x%x\n", Reg32)); do {
+ Reg32 = MmioRead32
+ (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG); }
+ while ((Reg32 & B_GSTS_REG_QIES) == 0);
+
+ mVtdUnitInformation[VtdIndex].QiFreeHead = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Disable queued invalidation interface.
+
+ @param[in] VtdIndex The index used to identify a VTd engine.
+**/
+VOID
+DisableQueuedInvalidationInterface (
+ IN UINTN VtdIndex
+ )
+{
+ UINT32 Reg32;
+
+ if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation != 0) {
+ Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 &= (~B_GMCD_REG_QIE);
+ MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ DEBUG ((DEBUG_INFO, "Disable Queued Invalidation Interface. GCMD_REG = 0x%x\n", Reg32));
+ do {
+ Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
+ } while ((Reg32 & B_GSTS_REG_QIES) != 0);
+
+ if (mVtdUnitInformation[VtdIndex].QiDesc != NULL) {
+ FreePages(mVtdUnitInformation[VtdIndex].QiDesc, EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * mVtdUnitInformation[VtdIndex].QiDescLength));
+ mVtdUnitInformation[VtdIndex].QiDesc = NULL;
+ mVtdUnitInformation[VtdIndex].QiDescLength = 0;
+ }
+
+ mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation = 0;
+ }
+}
+
+/**
+ Check Queued Invalidation Fault.
+
+ @param[in] VtdIndex The index used to identify a VTd engine.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval RETURN_DEVICE_ERROR A fault is detected.
+**/
+EFI_STATUS
+QueuedInvalidationCheckFault (
+ IN UINTN VtdIndex
+ )
+{
+ UINT32 fault_reg;
+
+ fault_reg = MmioRead32
+ (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG);
+
+ if (fault_reg & B_FSTS_REG_IQE) {
+ DEBUG((DEBUG_ERROR, "Detect Invalidation Queue Error [0x%08x]\n", fault_reg));
+ fault_reg |= B_FSTS_REG_IQE;
+ MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG, fault_reg);
+ return RETURN_DEVICE_ERROR;
+ }
+
+ if (fault_reg & B_FSTS_REG_ITE) {
+ DEBUG((DEBUG_ERROR, "Detect Invalidation Time-out Error [0x%08x]\n", fault_reg));
+ fault_reg |= B_FSTS_REG_ITE;
+ MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG, fault_reg);
+ return RETURN_DEVICE_ERROR;
+ }
+
+ if (fault_reg & B_FSTS_REG_ICE) {
+ DEBUG((DEBUG_ERROR, "Detect Invalidation Completion Error [0x%08x]\n", fault_reg));
+ fault_reg |= B_FSTS_REG_ICE;
+ MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG, fault_reg);
+ return RETURN_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Submit the queued invalidation descriptor to the remapping
+ hardware unit and wait for its completion.
+
+ @param[in] VtdIndex The index used to identify a VTd engine.
+ @param[in] desc The invalidate descriptor
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval RETURN_DEVICE_ERROR A fault is detected.
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.
+**/
+EFI_STATUS
+SubmitQueuedInvalidationDescriptor (
+ IN UINTN VtdIndex,
+ IN QI_DESC *desc
+ )
+{
+ EFI_STATUS rc;
+ UINT16 QiDescLength;
+ QI_DESC *BaseDesc;
+ UINT64 Reg64Iqt;
+ UINT64 Reg64Iqh;
+
+ if (desc == NULL) {
+ return EFI_INVALID_PARAMETER;
}

- Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));
- Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);
- MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG, Reg64);
+ QiDescLength = mVtdUnitInformation[VtdIndex].QiDescLength;
+ BaseDesc = mVtdUnitInformation[VtdIndex].QiDesc;
+
+ DEBUG((DEBUG_INFO, "[%d] Submit QI Descriptor [0x%08x, 0x%08x] Free
+ Head (%d)\n", VtdIndex, desc->low, desc->high,
+ mVtdUnitInformation[VtdIndex].QiFreeHead));
+
+ BaseDesc[mVtdUnitInformation[VtdIndex].QiFreeHead].low = desc->low;
+ BaseDesc[mVtdUnitInformation[VtdIndex].QiFreeHead].high = desc->high;
+ FlushPageTableMemory(VtdIndex, (UINTN)
+ &BaseDesc[mVtdUnitInformation[VtdIndex].QiFreeHead], sizeof(QI_DESC));
+
+ mVtdUnitInformation[VtdIndex].QiFreeHead =
+ (mVtdUnitInformation[VtdIndex].QiFreeHead + 1) % QiDescLength;
+
+ //
+ // Update the HW tail register indicating the presence of new descriptors.
+ //
+ Reg64Iqt = mVtdUnitInformation[VtdIndex].QiFreeHead << DMAR_IQ_SHIFT;
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
+ R_IQT_REG, Reg64Iqt);

+ rc = EFI_SUCCESS;
do {
+ rc = QueuedInvalidationCheckFault(VtdIndex);
+ if (rc != EFI_SUCCESS) {
+ DEBUG((DEBUG_ERROR,"Detect Queued Invalidation Fault.\n"));
+ break;
+ }
+
+ Reg64Iqh = MmioRead64
+ (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_IQH_REG); }
+ while (Reg64Iqt != Reg64Iqh);
+
+ return rc;
+}
+
+/**
+ Invalidate VTd context cache.
+
+ @param[in] VtdIndex The index used to identify a VTd engine.
+**/
+EFI_STATUS
+InvalidateContextCache (
+ IN UINTN VtdIndex
+ )
+{
+ UINT64 Reg64;
+ QI_DESC QiDesc;
+
+ if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation == 0) {
+ //
+ // Register-based Invalidation
+ //
Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);
- } while ((Reg64 & B_CCMD_REG_ICC) != 0);
+ if ((Reg64 & B_CCMD_REG_ICC) != 0) {
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%d)\n",VtdIndex));
+ return EFI_DEVICE_ERROR;
+ }
+
+ Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));
+ Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
+ R_CCMD_REG, Reg64);

+ do {
+ Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);
+ } while ((Reg64 & B_CCMD_REG_ICC) != 0); } else {
+ //
+ // Queued Invalidation
+ //
+ QiDesc.low = QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC_GRAN(1) | QI_CC_TYPE;
+ QiDesc.high = 0;
+
+ return SubmitQueuedInvalidationDescriptor(VtdIndex, &QiDesc); }
return EFI_SUCCESS;
}

@@ -94,20 +319,34 @@ InvalidateIOTLB (
)
{
UINT64 Reg64;
+ QI_DESC QiDesc;

- Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
- if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
- DEBUG ((DEBUG_ERROR,"ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set for VTD(%d)\n", VtdIndex));
- return EFI_DEVICE_ERROR;
- }
+ if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation == 0) {
+ //
+ // Register-based Invalidation
+ //
+ Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
+ if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set for VTD(%d)\n", VtdIndex));
+ return EFI_DEVICE_ERROR;
+ }

- Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
- Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);
- MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
+ Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
+ Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
+ (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG,
+ Reg64);

- do {
- Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
- } while ((Reg64 & B_IOTLB_REG_IVT) != 0);
+ do {
+ Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
+ } while ((Reg64 & B_IOTLB_REG_IVT) != 0); } else {
+ //
+ // Queued Invalidation
+ //
+ QiDesc.low = QI_IOTLB_DID(0) | QI_IOTLB_DR(cap_read_drain(mVtdUnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_DW(cap_write_drain(mVtdUnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE;
+ QiDesc.high = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0);
+
+ return SubmitQueuedInvalidationDescriptor(VtdIndex, &QiDesc); }

return EFI_SUCCESS;
}
@@ -163,9 +402,12 @@ PrepareVtdConfig (
{
UINTN Index;
UINTN DomainNumber;
+ EFI_STATUS Status;

for (Index = 0; Index < mVtdUnitNumber; Index++) {
DEBUG ((DEBUG_INFO, "Dump VTd Capability (%d)\n", Index));
+ mVtdUnitInformation[Index].VerReg.Uint32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_VER_REG);
+ DumpVtdVerRegs (&mVtdUnitInformation[Index].VerReg);
mVtdUnitInformation[Index].CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CAP_REG);
DumpVtdCapRegs (&mVtdUnitInformation[Index].CapReg);
mVtdUnitInformation[Index].ECapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_ECAP_REG); @@ -190,6 +432,12 @@ PrepareVtdConfig (
DEBUG((DEBUG_ERROR, "!!!! Pci device Number(0x%x) >= DomainNumber(0x%x) !!!!\n", mVtdUnitInformation[Index].PciDeviceInfo.PciDeviceDataNumber, DomainNumber));
return ;
}
+
+ Status = PerpareCacheInvalidationInterface(Index);
+ if (EFI_ERROR (Status)) {
+ ASSERT(FALSE);
+ return;
+ }
}
return ;
}
@@ -252,7 +500,8 @@ EnableDmar (
MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)mVtdUnitInformation[Index].RootEntryTable);
}

- MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);
+ Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
+ MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
+ R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);

DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
do {
@@ -282,7 +531,8 @@ EnableDmar (
//
// Enable VTd
//
- MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_TE);
+ Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
+ MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
+ R_GCMD_REG, Reg32 | B_GMCD_REG_TE);
DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
do {
Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG); @@ -360,6 +610,8 @@ DisableDmar (
DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));

DEBUG ((DEBUG_INFO,"VTD (%d) Disabled!<<<<<<\n",Index));
+
+ DisableQueuedInvalidationInterface(Index);
}

mVtdEnabled = FALSE;
@@ -380,6 +632,21 @@ DisableDmar (
return EFI_SUCCESS;
}

+/**
+ Dump VTd version registers.
+
+ @param[in] VerReg The version register.
+**/
+VOID
+DumpVtdVerRegs (
+ IN VTD_VER_REG *VerReg
+ )
+{
+ DEBUG ((DEBUG_INFO, " VerReg:\n", VerReg->Uint32));
+ DEBUG ((DEBUG_INFO, " Major - 0x%x\n", VerReg->Bits.Major));
+ DEBUG ((DEBUG_INFO, " Minor - 0x%x\n", VerReg->Bits.Minor));
+}
+
/**
Dump VTd capability registers.

diff --git a/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h b/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
index b2f745bd..199cb398 100644
--- a/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
+++ b/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
@@ -206,10 +206,12 @@ typedef union {
#define B_CAP_REG_RWBF BIT4
#define R_ECAP_REG 0x10
#define R_GCMD_REG 0x18
+#define B_GMCD_REG_QIE BIT26
#define B_GMCD_REG_WBF BIT27
#define B_GMCD_REG_SRTP BIT30
#define B_GMCD_REG_TE BIT31
#define R_GSTS_REG 0x1C
+#define B_GSTS_REG_QIES BIT26
#define B_GSTS_REG_WBF BIT27
#define B_GSTS_REG_RTPS BIT30
#define B_GSTS_REG_TE BIT31
@@ -221,6 +223,9 @@ typedef union {
#define V_CCMD_REG_CIRG_DEVICE (BIT62|BIT61)
#define B_CCMD_REG_ICC BIT63
#define R_FSTS_REG 0x34
+#define B_FSTS_REG_IQE BIT4
+#define B_FSTS_REG_ICE BIT5
+#define B_FSTS_REG_ITE BIT6
#define R_FECTL_REG 0x38
#define R_FEDATA_REG 0x3C
#define R_FEADDR_REG 0x40
@@ -247,6 +252,58 @@ typedef union {
#define R_PMEN_HIGH_BASE_REG 0x70
#define R_PMEN_HIGH_LIMITE_REG 0x78

+#define R_IQH_REG 0x80
+#define R_IQT_REG 0x88
+#define DMAR_IQ_SHIFT 4 /* Invalidation queue head/tail shift */
+
+#define R_IQA_REG 0x90
+
+#define VTD_PAGE_SHIFT (12)
+#define VTD_PAGE_SIZE (1UL << VTD_PAGE_SHIFT)
+#define VTD_PAGE_MASK (((UINT64)-1) << VTD_PAGE_SHIFT)
+
+#define QI_CC_TYPE 0x1
+#define QI_IOTLB_TYPE 0x2
+#define QI_DIOTLB_TYPE 0x3
+#define QI_IEC_TYPE 0x4
+#define QI_IWD_TYPE 0x5
+
+#define QI_CC_FM(fm) (((UINT64)fm) << 48)
+#define QI_CC_SID(sid) (((UINT64)sid) << 32)
+#define QI_CC_DID(did) (((UINT64)did) << 16)
+#define QI_CC_GRAN(gran) (((UINT64)gran) << 4)
+
+#define QI_IOTLB_DID(did) (((UINT64)did) << 16)
+#define QI_IOTLB_DR(dr) (((UINT64)dr) << 7)
+#define QI_IOTLB_DW(dw) (((UINT64)dw) << 6)
+#define QI_IOTLB_GRAN(gran) (((UINT64)gran) << 4) #define
+QI_IOTLB_ADDR(addr) (((UINT64)addr) & VTD_PAGE_MASK)
+#define QI_IOTLB_IH(ih) (((UINT64)ih) << 6)
+#define QI_IOTLB_AM(am) (((UINT8)am))
+
+#define cap_read_drain(c) (((c) >> 55) & 1)
+#define cap_write_drain(c) (((c) >> 54) & 1)
+
+#define QI_IWD_STATUS_DATA(d) (((UINT64)d) << 32)
+#define QI_IWD_STATUS_WRITE (((UINT64)1) << 5)
+
+//
+// This is the queued invalidate descriptor.
+//
+typedef struct {
+ UINT64 low;
+ UINT64 high;
+} QI_DESC;
+
+typedef union {
+ struct {
+ UINT8 Minor:4;
+ UINT8 Major:4;
+ UINT32 Rsvd:24;
+ } Bits;
+ UINT32 Uint32;
+} VTD_VER_REG;
+
typedef union {
struct {
UINT8 ND:3; // Number of domains supported
--
2.16.2.windows.1


Re: [PATCH v1 0/2] Add GIC ITS entry to MADT

Shashi Mallela
 

Gentle reminder for ITS changes review.

The accompanying qemu git branch with ITS changes is available at
https://github.com/shashi-j/qemu.git


Re: [PATCH v3 2/2] SecurityPkg: Add support for RngDxe on AARCH64

Sami Mujawar
 

This patch looks good to me.

Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>

Regards,

Sami Mujawar


On 10/05/2021 10:53 PM, Rebecca Cran wrote:
AARCH64 support has been added to BaseRngLib via the optional
ARMv8.5 FEAT_RNG.

Refactor RngDxe to support AARCH64, note support for it in the
VALID_ARCHITECTURES line of RngDxe.inf and enable it in SecurityPkg.dsc.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
SecurityPkg/SecurityPkg.dec | 2 +
SecurityPkg/SecurityPkg.dsc | 11 +-
SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf | 24 ++-
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/AesCore.h | 0
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/RdRand.h | 17 --
SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h | 117 ++++++++++++++
SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c | 127 +++++++++++++++
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/AesCore.c | 0
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/RdRand.c | 45 +-----
SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c | 146 +++++++++++++++++
SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c | 170 ++++++++------------
11 files changed, 483 insertions(+), 176 deletions(-)

diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
index dfbbb0365a2b..4001650fa28e 100644
--- a/SecurityPkg/SecurityPkg.dec
+++ b/SecurityPkg/SecurityPkg.dec
@@ -297,6 +297,8 @@ [PcdsFixedAtBuild, PcdsPatchableInModule]
gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeFvVerificationPass|0x0303100A|UINT32|0x00010030
gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeFvVerificationFail|0x0303100B|UINT32|0x00010031

+ gEfiSecurityPkgTokenSpaceGuid.PcdCpuRngSupportedAlgorithm|{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}|VOID*|0x00010032
+
[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
## Image verification policy for OptionRom. Only following values are valid:<BR><BR>
# NOTE: Do NOT use 0x5 and 0x2 since it violates the UEFI specification and has been removed.<BR>
diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index 12ccd1634941..bd4b810bce61 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -259,6 +259,12 @@ [Components]
[Components.IA32, Components.X64, Components.ARM, Components.AARCH64]
SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf

+[Components.IA32, Components.X64, Components.AARCH64]
+ #
+ # Random Number Generator
+ #
+ SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
+
[Components.IA32, Components.X64]
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf

@@ -334,11 +340,6 @@ [Components.IA32, Components.X64]
SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf
SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalPresenceLib.inf

- #
- # Random Number Generator
- #
- SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
-
#
# Opal Password solution
#
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
index 99d6f6b35fc2..f3300971993f 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
@@ -26,15 +26,22 @@ [Defines]
#
# The following information is for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = IA32 X64
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
#

[Sources.common]
RngDxe.c
- RdRand.c
- RdRand.h
- AesCore.c
- AesCore.h
+ RngDxeInternals.h
+
+[Sources.IA32, Sources.X64]
+ Rand/RngDxe.c
+ Rand/RdRand.c
+ Rand/RdRand.h
+ Rand/AesCore.c
+ Rand/AesCore.h
+
+[Sources.AARCH64]
+ AArch64/RngDxe.c

[Packages]
MdePkg/MdePkg.dec
@@ -50,12 +57,19 @@ [LibraryClasses]
RngLib

[Guids]
+ gEfiRngAlgorithmSp80090Hash256Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
+ gEfiRngAlgorithmSp80090Hmac256Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
gEfiRngAlgorithmSp80090Ctr256Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
+ gEfiRngAlgorithmX9313DesGuid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
+ gEfiRngAlgorithmX931AesGuid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
gEfiRngAlgorithmRaw ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG

[Protocols]
gEfiRngProtocolGuid ## PRODUCES

+[Pcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdCpuRngSupportedAlgorithm ## CONSUMES
+
[Depex]
TRUE

diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.h b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.h
similarity index 100%
rename from SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.h
rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.h
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.h b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.h
similarity index 72%
rename from SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.h
rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.h
index 12ab1f34ec6d..072378e062e7 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.h
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.h
@@ -23,23 +23,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/TimerLib.h>
#include <Protocol/Rng.h>

-/**
- Calls RDRAND to fill a buffer of arbitrary size with random bytes.
-
- @param[in] Length Size of the buffer, in bytes, to fill with.
- @param[out] RandBuffer Pointer to the buffer to store the random result.
-
- @retval EFI_SUCCESS Random bytes generation succeeded.
- @retval EFI_NOT_READY Failed to request random bytes.
-
-**/
-EFI_STATUS
-EFIAPI
-RdRandGetBytes (
- IN UINTN Length,
- OUT UINT8 *RandBuffer
- );
-
/**
Generate high-quality entropy source through RDRAND.

diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
new file mode 100644
index 000000000000..2660ed5875e0
--- /dev/null
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
@@ -0,0 +1,117 @@
+/** @file
+ Function prototypes for UEFI Random Number Generator protocol support.
+
+ Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef RNGDXE_INTERNALS_H_
+#define RNGDXE_INTERNALS_H_
+
+/**
+ 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.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetInfo (
+ IN EFI_RNG_PROTOCOL *This,
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ );
+
+/**
+ 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.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetRNG (
+ IN EFI_RNG_PROTOCOL *This,
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
+ IN UINTN RNGValueLength,
+ OUT UINT8 *RNGValue
+ );
+
+/**
+ Returns information about the random number generation implementation.
+
+ @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_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small to hold the result.
+
+**/
+UINTN
+EFIAPI
+ArchGetSupportedRngAlgorithms (
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ );
+
+/**
+ Runs CPU RNG instruction to fill a buffer of arbitrary size with random bytes.
+
+ @param[in] Length Size of the buffer, in bytes, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random bytes generation succeeded.
+ @retval EFI_NOT_READY Failed to request random bytes.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetBytes (
+ IN UINTN Length,
+ OUT UINT8 *RandBuffer
+ );
+
+#endif // RNGDXE_INTERNALS_H_
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
new file mode 100644
index 000000000000..2810a9eb94ad
--- /dev/null
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
@@ -0,0 +1,127 @@
+/** @file
+ RNG Driver to produce the UEFI Random Number Generator protocol.
+
+ The driver will use the RNDR instruction to produce random numbers.
+
+ RNG Algorithms defined in UEFI 2.4:
+ - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID
+ - EFI_RNG_ALGORITHM_RAW - Unsupported
+ - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID
+ - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID
+ - EFI_RNG_ALGORITHM_X9_31_3DES_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_X9_31_AES_GUID - Unsupported
+
+ Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+ Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/TimerLib.h>
+#include <Protocol/Rng.h>
+
+#include "RngDxeInternals.h"
+
+/**
+ 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.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetRNG (
+ IN EFI_RNG_PROTOCOL *This,
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
+ IN UINTN RNGValueLength,
+ OUT UINT8 *RNGValue
+ )
+{
+ EFI_STATUS Status;
+
+ if ((RNGValueLength == 0) || (RNGValue == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (RNGAlgorithm == NULL) {
+ //
+ // Use the default RNG algorithm if RNGAlgorithm is NULL.
+ //
+ RNGAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);
+ }
+
+ if (CompareGuid (RNGAlgorithm, PcdGetPtr (PcdCpuRngSupportedAlgorithm))) {
+ Status = RngGetBytes (RNGValueLength, RNGValue);
+ return Status;
+ }
+
+ //
+ // Other algorithms are unsupported by this driver.
+ //
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Returns information about the random number generation implementation.
+
+ @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_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small to hold the result.
+
+**/
+UINTN
+EFIAPI
+ArchGetSupportedRngAlgorithms (
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ )
+{
+ UINTN RequiredSize;
+ EFI_RNG_ALGORITHM *CpuRngSupportedAlgorithm;
+
+ RequiredSize = sizeof (EFI_RNG_ALGORITHM);
+
+ if (*RNGAlgorithmListSize < RequiredSize) {
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ CpuRngSupportedAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);
+
+ CopyMem(&RNGAlgorithmList[0], CpuRngSupportedAlgorithm, sizeof (EFI_RNG_ALGORITHM));
+
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_SUCCESS;
+}
+
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.c b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.c
similarity index 100%
rename from SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.c
rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.c
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.c
similarity index 71%
rename from SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c
rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.c
index e7dd5ab18111..83025a47d43d 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.c
@@ -8,48 +8,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/RngLib.h>

-#include "RdRand.h"
#include "AesCore.h"
-
-/**
- Calls RDRAND to fill a buffer of arbitrary size with random bytes.
-
- @param[in] Length Size of the buffer, in bytes, to fill with.
- @param[out] RandBuffer Pointer to the buffer to store the random result.
-
- @retval EFI_SUCCESS Random bytes generation succeeded.
- @retval EFI_NOT_READY Failed to request random bytes.
-
-**/
-EFI_STATUS
-EFIAPI
-RdRandGetBytes (
- IN UINTN Length,
- OUT UINT8 *RandBuffer
- )
-{
- BOOLEAN IsRandom;
- UINT64 TempRand[2];
-
- while (Length > 0) {
- IsRandom = GetRandomNumber128 (TempRand);
- if (!IsRandom) {
- return EFI_NOT_READY;
- }
- if (Length >= sizeof (TempRand)) {
- WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[0]);
- RandBuffer += sizeof (UINT64);
- WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[1]);
- RandBuffer += sizeof (UINT64);
- Length -= sizeof (TempRand);
- } else {
- CopyMem (RandBuffer, TempRand, Length);
- Length = 0;
- }
- }
-
- return EFI_SUCCESS;
-}
+#include "RdRand.h"
+#include "RngDxeInternals.h"

/**
Creates a 128bit random value that is fully forward and backward prediction resistant,
@@ -92,7 +53,7 @@ RdRandGetSeed128 (
//
for (Index = 0; Index < 32; Index++) {
MicroSecondDelay (10);
- Status = RdRandGetBytes (16, RandByte);
+ Status = RngGetBytes (16, RandByte);
if (EFI_ERROR (Status)) {
return Status;
}
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
new file mode 100644
index 000000000000..6b628a9f8bc6
--- /dev/null
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
@@ -0,0 +1,146 @@
+/** @file
+ RNG Driver to produce the UEFI Random Number Generator protocol.
+
+ The driver will use the new RDRAND instruction to produce high-quality, high-performance
+ entropy and random number.
+
+ RNG Algorithms defined in UEFI 2.4:
+ - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID - Supported
+ (RDRAND implements a hardware NIST SP800-90 AES-CTR-256 based DRBG)
+ - EFI_RNG_ALGORITHM_RAW - Supported
+ (Structuring RDRAND invocation can be guaranteed as high-quality entropy source)
+ - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_X9_31_3DES_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_X9_31_AES_GUID - Unsupported
+
+ Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RdRand.h"
+#include "RngDxeInternals.h"
+
+/**
+ 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.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetRNG (
+ IN EFI_RNG_PROTOCOL *This,
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
+ IN UINTN RNGValueLength,
+ OUT UINT8 *RNGValue
+ )
+{
+ EFI_STATUS Status;
+
+ if ((RNGValueLength == 0) || (RNGValue == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ if (RNGAlgorithm == NULL) {
+ //
+ // Use the default RNG algorithm if RNGAlgorithm is NULL.
+ //
+ RNGAlgorithm = &gEfiRngAlgorithmSp80090Ctr256Guid;
+ }
+
+ //
+ // NIST SP800-90-AES-CTR-256 supported by RDRAND
+ //
+ if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmSp80090Ctr256Guid)) {
+ Status = RngGetBytes (RNGValueLength, RNGValue);
+ return Status;
+ }
+
+ //
+ // The "raw" algorithm is intended to provide entropy directly
+ //
+ if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) {
+ //
+ // When a DRBG is used on the output of a entropy source,
+ // its security level must be at least 256 bits according to UEFI Spec.
+ //
+ if (RNGValueLength < 32) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = RdRandGenerateEntropy (RNGValueLength, RNGValue);
+ return Status;
+ }
+
+ //
+ // Other algorithms were unsupported by this driver.
+ //
+ return Status;
+}
+
+/**
+ Returns information about the random number generation implementation.
+
+ @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_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small to hold the result.
+
+**/
+UINTN
+EFIAPI
+ArchGetSupportedRngAlgorithms (
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ )
+{
+ UINTN RequiredSize;
+ EFI_RNG_ALGORITHM *CpuRngSupportedAlgorithm;
+
+ RequiredSize = 2 * sizeof (EFI_RNG_ALGORITHM);
+
+ if (*RNGAlgorithmListSize < RequiredSize) {
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ CpuRngSupportedAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);
+
+ CopyMem(&RNGAlgorithmList[0], CpuRngSupportedAlgorithm, sizeof (EFI_RNG_ALGORITHM));
+
+ // x86 platforms also support EFI_RNG_ALGORITHM_RAW via RDSEED
+ CopyMem(&RNGAlgorithmList[1], &gEfiRngAlgorithmRaw, sizeof (EFI_RNG_ALGORITHM));
+
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_SUCCESS;
+}
+
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
index 13d3dbd0bfbe..b959c70536ea 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
@@ -1,34 +1,32 @@
/** @file
RNG Driver to produce the UEFI Random Number Generator protocol.

- The driver will use the new RDRAND instruction to produce high-quality, high-performance
- entropy and random number.
+ The driver uses CPU RNG instructions to produce high-quality,
+ high-performance entropy and random number.

RNG Algorithms defined in UEFI 2.4:
- - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID - Supported
- (RDRAND implements a hardware NIST SP800-90 AES-CTR-256 based DRBG)
- - EFI_RNG_ALGORITHM_RAW - Supported
- (Structuring RDRAND invocation can be guaranteed as high-quality entropy source)
- - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID - Unsupported
- - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID - Unsupported
- - EFI_RNG_ALGORITHM_X9_31_3DES_GUID - Unsupported
- - EFI_RNG_ALGORITHM_X9_31_AES_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID
+ - EFI_RNG_ALGORITHM_RAW
+ - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID
+ - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID
+ - EFI_RNG_ALGORITHM_X9_31_3DES_GUID
+ - EFI_RNG_ALGORITHM_X9_31_AES_GUID

Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

-#include "RdRand.h"
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/RngLib.h>
+#include <Library/TimerLib.h>
+#include <Protocol/Rng.h>

-//
-// Supported RNG Algorithms list by this driver.
-//
-EFI_RNG_ALGORITHM mSupportedRngAlgorithms[] = {
- EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID,
- EFI_RNG_ALGORITHM_RAW
-};
+#include "RngDxeInternals.h"

/**
Returns information about the random number generation implementation.
@@ -62,106 +60,23 @@ RngGetInfo (
)
{
EFI_STATUS Status;
- UINTN RequiredSize;

if ((This == NULL) || (RNGAlgorithmListSize == NULL)) {
return EFI_INVALID_PARAMETER;
}

- RequiredSize = sizeof (mSupportedRngAlgorithms);
- if (*RNGAlgorithmListSize < RequiredSize) {
- Status = EFI_BUFFER_TOO_SMALL;
+ //
+ // Return algorithm list supported by driver.
+ //
+ if (RNGAlgorithmList != NULL) {
+ Status = ArchGetSupportedRngAlgorithms (RNGAlgorithmListSize, RNGAlgorithmList);
} else {
- //
- // Return algorithm list supported by driver.
- //
- if (RNGAlgorithmList != NULL) {
- CopyMem (RNGAlgorithmList, mSupportedRngAlgorithms, RequiredSize);
- Status = EFI_SUCCESS;
- } else {
- Status = EFI_INVALID_PARAMETER;
- }
+ Status = EFI_INVALID_PARAMETER;
}
- *RNGAlgorithmListSize = RequiredSize;

return Status;
}

-/**
- 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.
-
-**/
-EFI_STATUS
-EFIAPI
-RngGetRNG (
- IN EFI_RNG_PROTOCOL *This,
- IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
- IN UINTN RNGValueLength,
- OUT UINT8 *RNGValue
- )
-{
- EFI_STATUS Status;
-
- if ((RNGValueLength == 0) || (RNGValue == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Status = EFI_UNSUPPORTED;
- if (RNGAlgorithm == NULL) {
- //
- // Use the default RNG algorithm if RNGAlgorithm is NULL.
- //
- RNGAlgorithm = &gEfiRngAlgorithmSp80090Ctr256Guid;
- }
-
- //
- // NIST SP800-90-AES-CTR-256 supported by RDRAND
- //
- if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmSp80090Ctr256Guid)) {
- Status = RdRandGetBytes (RNGValueLength, RNGValue);
- return Status;
- }
-
- //
- // The "raw" algorithm is intended to provide entropy directly
- //
- if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) {
- //
- // When a DRBG is used on the output of a entropy source,
- // its security level must be at least 256 bits according to UEFI Spec.
- //
- if (RNGValueLength < 32) {
- return EFI_INVALID_PARAMETER;
- }
-
- Status = RdRandGenerateEntropy (RNGValueLength, RNGValue);
- return Status;
- }
-
- //
- // Other algorithms were unsupported by this driver.
- //
- return Status;
-}
-
//
// The Random Number Generator (RNG) protocol
//
@@ -204,3 +119,44 @@ RngDriverEntry (

return Status;
}
+
+
+/**
+ Calls RDRAND to fill a buffer of arbitrary size with random bytes.
+
+ @param[in] Length Size of the buffer, in bytes, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random bytes generation succeeded.
+ @retval EFI_NOT_READY Failed to request random bytes.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetBytes (
+ IN UINTN Length,
+ OUT UINT8 *RandBuffer
+ )
+{
+ BOOLEAN IsRandom;
+ UINT64 TempRand[2];
+
+ while (Length > 0) {
+ IsRandom = GetRandomNumber128 (TempRand);
+ if (!IsRandom) {
+ return EFI_NOT_READY;
+ }
+ if (Length >= sizeof (TempRand)) {
+ WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[0]);
+ RandBuffer += sizeof (UINT64);
+ WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[1]);
+ RandBuffer += sizeof (UINT64);
+ Length -= sizeof (TempRand);
+ } else {
+ CopyMem (RandBuffer, TempRand, Length);
+ Length = 0;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.


Re: [PATCH 06/13] MdePkg/Register/Amd: define GHCB macros for SNP AP creation

Lendacky, Thomas
 

On 5/11/21 4:59 AM, Laszlo Ersek wrote:
On 05/07/21 22:38, Brijesh Singh wrote:
From: Tom Lendacky <thomas.lendacky@amd.com>

BZ: https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D3275&;data=04%7C01%7Cthomas.lendacky%40amd.com%7C92c1323bd1e84a2a38e208d914636ddf%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637563239563579592%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=DMDhcseilROSsL6EISUoT9p0pI%2BmXtEC3rLHIQS4NmI%3D&amp;reserved=0

Version 2 of GHCB introduces NAE for creating AP when SEV-SNP is
enabled in the guest VM. See the GHCB spec section for additional
details.
(1) The actual section reference is missing. I'll fix it up: from where
the spec introduces exit code 0x8000_0013, the sections appear to be
4.1.9 and 4.3.2. Also, Table 5. "List of Supported Non-Automatic Events"
is relevant for the SVM_VMGEXIT_SNP_AP_* macros.
There are some needed changes to this patch, so I can fix that up. I just
avoided putting actual section numbers in there because it is possible
that they can change in future versions.



While at it, define the VMSA state save area that are required for
(2) I think "area" (singular) is correct here, so we should say "is".
I'll update it.
I can fix that up.


creating the AP. The save area format is defined in AMD APM volume
2 (Table B-4).

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
MdePkg/Include/Register/Amd/Ghcb.h | 70 ++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)

diff --git a/MdePkg/Include/Register/Amd/Ghcb.h b/MdePkg/Include/Register/Amd/Ghcb.h
index a15b4b7e2760..956cefbc003c 100644
--- a/MdePkg/Include/Register/Amd/Ghcb.h
+++ b/MdePkg/Include/Register/Amd/Ghcb.h
@@ -55,6 +55,7 @@
#define SVM_EXIT_AP_RESET_HOLD 0x80000004ULL
#define SVM_EXIT_AP_JUMP_TABLE 0x80000005ULL
#define SVM_EXIT_SNP_PAGE_STATE_CHANGE 0x80000010ULL
+#define SVM_EXIT_SNP_AP_CREATION 0x80000013ULL
#define SVM_EXIT_HYPERVISOR_FEATURES 0x8000FFFDULL
#define SVM_EXIT_UNSUPPORTED 0x8000FFFFULL

@@ -83,6 +84,12 @@
#define IOIO_SEG_ES 0
#define IOIO_SEG_DS (BIT11 | BIT10)

+//
+// AP Creation Information
+//
+#define SVM_VMGEXIT_SNP_AP_CREATE_ON_INIT 0
+#define SVM_VMGEXIT_SNP_AP_CREATE 1
+#define SVM_VMGEXIT_SNP_AP_DESTROY 2

typedef PACKED struct {
UINT8 Reserved1[203];
@@ -195,4 +202,67 @@ typedef struct {
SNP_PAGE_STATE_ENTRY Entry[SNP_PAGE_STATE_MAX_ENTRY];
} SNP_PAGE_STATE_CHANGE_INFO;

+//
+// SEV-ES save area mapping structures used for SEV-SNP AP Creation.
+// Only the fields required to be set to a non-zero value are defined.
+//
+#pragma pack(1)
+typedef struct {
+ UINT16 Selector;
+ UINT16 Attributes;
+ UINT32 Limit;
+ UINT64 Base;
+} SEV_ES_SEGMENT_REGISTER;
+#pragma pack()
(3) there should be a space character between "pack" and "(" -- two
instances.
Will do.


+
+#define SEV_ES_RESET_CS_ATTRIBUTES (BIT7 | BIT4 | BIT3 | BIT1)
+#define SEV_ES_RESET_DS_ATTRIBUTES (BIT7 | BIT4 | BIT1)
+#define SEV_ES_RESET_ES_ATTRIBUTES SEV_ES_RESET_DS_ATTRIBUTES
+#define SEV_ES_RESET_FS_ATTRIBUTES SEV_ES_RESET_DS_ATTRIBUTES
+#define SEV_ES_RESET_GS_ATTRIBUTES SEV_ES_RESET_DS_ATTRIBUTES
+#define SEV_ES_RESET_SS_ATTRIBUTES SEV_ES_RESET_DS_ATTRIBUTES
+
+#define SEV_ES_RESET_GDTR_ATTRIBUTES 0
+#define SEV_ES_RESET_LDTR_ATTRIBUTES (BIT7 | 2)
+#define SEV_ES_RESET_IDTR_ATTRIBUTES 0
+#define SEV_ES_RESET_TR_ATTRIBUTES (BIT7 | 3)
(4) ... I guess I can't go ahead merging this myself, after all (Liming
may of course still merge the MdePkg patches, if he wants to).

My problem here is that the bit positions are cryptic.

I've found the *normal* (not SEV-ES) segment descriptor attributes in
the AMD APM (publication #24593, revision 3.37, date March 2021, volume
2, sections sections 4.7 and 4.8).

However, the bit positions SEV-ES descriptors are surely different. For
the "normal" segment descriptors, we already have the
IA32_SEGMENT_DESCRIPTOR type in edk2, with the nicely broken-out
attribute bits. The bit meanings within
"SEV_ES_SEGMENT_REGISTER.Attributes" remain unclear to me.

Please at least provide a *specific* documentation reference in the
commit message where I can verify (or at least "decode") the attribute bits.
Yeah, it is a strange format. The format is documented in sections 15.5
(VMRUN Instruction) and 10 (System-Management Mode).

I can try to further document the bit assignments, e.g.

#define SEV_ES_SEGMENT_ATTRIBUTE_PRESENT BIT7
#define SEV_ES_SEGMENT_ATTRIBUTE_USER BIT4
etc.


+
+#pragma pack(1)
+typedef struct {
+ SEV_ES_SEGMENT_REGISTER Es;
+ SEV_ES_SEGMENT_REGISTER Cs;
+ SEV_ES_SEGMENT_REGISTER Ss;
+ SEV_ES_SEGMENT_REGISTER Ds;
+ SEV_ES_SEGMENT_REGISTER Fs;
+ SEV_ES_SEGMENT_REGISTER Gs;
+ SEV_ES_SEGMENT_REGISTER Gdtr;
+ SEV_ES_SEGMENT_REGISTER Ldtr;
+ SEV_ES_SEGMENT_REGISTER Idtr;
+ SEV_ES_SEGMENT_REGISTER Tr;
+ UINT8 Reserved1[42];
(5) This doesn't seem right. The comment higher up says that "Only the
fields required to be set to a non-zero value are defined", which is
fine. But in Table B-4, between fields "Tr" and "Vmpl", we have 5 qword
fields (PL0_SSP through PL3_SSP, plus U_CET), and a reserved dword
field. That makes for 5*8+4 = 44 bytes, not 42.

Hmmm. If I look at the table differently, I get a different result.
Namely, the first offset right after Tr is 0A0h, and the start offset of
Vmpl is 0CAh. The difference is indeed 42 (decimal).

Ah, I've found it. The bug is in the spec. The Reserved field at offset
0C8h is listed with size "dword", but the field right after it, namely
VMPL, starts at offset 0CAh -- that is, only two bytes later. Which
means that the "dword" size for Reserved is wrong; it should be "word" only.
Right, the offsets are correct, the use of "dword" is incorrect.


I couldn't find a more recent release of the APM than "revision 3.37".
Please add a remark to the commit message on this patch that highlights
this typo in the spec.
Will do.


+ UINT8 Vmpl;
+ UINT8 Reserved2[5];
+ UINT64 Efer;
+ UINT8 Reserved3[112];
OK

+ UINT64 Cr4;
+ UINT8 Reserved4[8];
OK (although I'm not sure much is saved over spelling out "Cr3")

+ UINT64 Cr0;
+ UINT64 Dr7;
+ UINT64 Dr6;
+ UINT64 Rflags;
+ UINT64 Rip;
+ UINT8 Reserved5[232];
OK

+ UINT64 GPat;
+ UINT8 Reserved6[320];
OK

+ UINT64 SevFeatures;
+ UINT8 Reserved7[48];
OK

+ UINT64 XCr0;
+ UINT8 Reserved8[24];
OK

+ UINT32 Mxcsr;
+ UINT64 X87Ftw;
(6) If you are packing all four words (X87_FTW, X87_FSW, X87_FCW,
X87_FOP) into a qword, then please give the latter a different name. The
spec associates X87_FTW with just the word at offset 40Ch. I propose the
name "FpState" for the UINT64 field in the edk2 structure.
Yes, that is incorrect. They should be UINT16 entries as you state below.


+ UINT64 Reserved9[8];
+ UINT64 X87Fcw;
(7) Ugh, wait, something's wrong -- you *are* apparently adding a field
for X87_FCW separately! But then the type of X87Ftw is wrong -- it
should be UINT16. Same for X87Fcw.

The distance between them is also wrong, it should be only 2 bytes
(basically the X87_FSW field). I have no idea at all where the 8*8=64
bytes padding comes from!

+} SEV_ES_SAVE_AREA;
+#pragma pack()
(8) same as (3); please insert a space character between
Will do.

Thanks,
Tom


+
#endif
Thanks
Laszlo


Re: [PATCH v3 1/2] MdePkg/BaseRngLib: Add support for ARMv8.5 RNG instructions

Sami Mujawar
 

This patch looks good to me.

Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>

Regards,

Sami Mujawar


On 10/05/2021 10:53 PM, Rebecca Cran wrote:
Make BaseRngLib more generic by moving x86-specific functionality into
'Rand' and adding files under 'AArch64' to support the optional ARMv8.5
RNG instruction RNDR that is a part of FEAT_RNG.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
---
MdePkg/MdePkg.dec | 9 +-
MdePkg/MdePkg.dsc | 4 +-
MdePkg/Library/BaseRngLib/BaseRngLib.inf | 23 +++-
MdePkg/Library/BaseRngLib/AArch64/ArmRng.h | 43 ++++++
MdePkg/Library/BaseRngLib/BaseRngLibInternals.h | 78 +++++++++++
MdePkg/Library/BaseRngLib/AArch64/Rndr.c | 139 ++++++++++++++++++++
MdePkg/Library/BaseRngLib/BaseRng.c | 87 ++++++------
MdePkg/Library/BaseRngLib/Rand/RdRand.c | 131 ++++++++++++++++++
MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.S | 31 +++++
MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.asm | 30 +++++
MdePkg/Library/BaseRngLib/AArch64/ArmRng.S | 37 ++++++
MdePkg/Library/BaseRngLib/AArch64/ArmRng.asm | 39 ++++++
MdePkg/Library/BaseRngLib/BaseRngLib.uni | 6 +-
13 files changed, 603 insertions(+), 54 deletions(-)

diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
index 8965e903e093..b49f88d8e18f 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -267,6 +267,11 @@ [LibraryClasses]
#
RegisterFilterLib|Include/Library/RegisterFilterLib.h

+[LibraryClasses.IA32, LibraryClasses.X64, LibraryClasses.AARCH64]
+ ## @libraryclass Provides services to generate random number.
+ #
+ RngLib|Include/Library/RngLib.h
+
[LibraryClasses.IA32, LibraryClasses.X64]
## @libraryclass Abstracts both S/W SMI generation and detection.
##
@@ -288,10 +293,6 @@ [LibraryClasses.IA32, LibraryClasses.X64]
#
SmmPeriodicSmiLib|Include/Library/SmmPeriodicSmiLib.h

- ## @libraryclass Provides services to generate random number.
- #
- RngLib|Include/Library/RngLib.h
-
## @libraryclass Provides services to log the SMI handler registration.
SmiHandlerProfileLib|Include/Library/SmiHandlerProfileLib.h

diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc
index d363419006ea..a94959169b2f 100644
--- a/MdePkg/MdePkg.dsc
+++ b/MdePkg/MdePkg.dsc
@@ -145,6 +145,9 @@ [Components.IA32, Components.X64, Components.ARM, Components.AARCH64]
MdePkg/Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLibSmm.inf
MdePkg/Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLibUefiShell.inf

+[Components.IA32, Components.X64, Components.AARCH64]
+ MdePkg/Library/BaseRngLib/BaseRngLib.inf
+
[Components.IA32, Components.X64]
MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf
@@ -168,7 +171,6 @@ [Components.IA32, Components.X64]
MdePkg/Library/BaseS3StallLib/BaseS3StallLib.inf
MdePkg/Library/SmmMemLib/SmmMemLib.inf
MdePkg/Library/SmmIoLib/SmmIoLib.inf
- MdePkg/Library/BaseRngLib/BaseRngLib.inf
MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf
MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf
diff --git a/MdePkg/Library/BaseRngLib/BaseRngLib.inf b/MdePkg/Library/BaseRngLib/BaseRngLib.inf
index 31740751c69c..1fcceb941495 100644
--- a/MdePkg/Library/BaseRngLib/BaseRngLib.inf
+++ b/MdePkg/Library/BaseRngLib/BaseRngLib.inf
@@ -1,9 +1,10 @@
## @file
# Instance of RNG (Random Number Generator) Library.
#
-# BaseRng Library that uses CPU RdRand instruction access to provide
-# high-quality random numbers.
+# BaseRng Library that uses CPU RNG instructions (e.g. RdRand) to
+# provide random numbers.
#
+# Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -22,11 +23,25 @@ [Defines]
CONSTRUCTOR = BaseRngLibConstructor

#
-# VALID_ARCHITECTURES = IA32 X64
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
#

-[Sources.Ia32, Sources.X64]
+[Sources]
BaseRng.c
+ BaseRngLibInternals.h
+
+[Sources.Ia32, Sources.X64]
+ Rand/RdRand.c
+
+[Sources.AARCH64]
+ AArch64/Rndr.c
+ AArch64/ArmRng.h
+
+ AArch64/ArmReadIdIsar0.S | GCC
+ AArch64/ArmRng.S | GCC
+
+ AArch64/ArmReadIdIsar0.asm | MSFT
+ AArch64/ArmRng.asm | MSFT

[Packages]
MdePkg/MdePkg.dec
diff --git a/MdePkg/Library/BaseRngLib/AArch64/ArmRng.h b/MdePkg/Library/BaseRngLib/AArch64/ArmRng.h
new file mode 100644
index 000000000000..a597e98bf0d5
--- /dev/null
+++ b/MdePkg/Library/BaseRngLib/AArch64/ArmRng.h
@@ -0,0 +1,43 @@
+/** @file
+ Random number generator service that uses the RNDR instruction
+ to provide pseudorandom numbers.
+
+ Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef ARM_RNG_H_
+#define ARM_RNG_H_
+
+/**
+ Generates a random number using RNDR.
+ Returns TRUE on success; FALSE on failure.
+
+ @param[out] Rand Buffer pointer to store the 64-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArmRndr (
+ OUT UINT64 *Rand
+ );
+
+/**
+ Reads the ID_AA64ISAR0 Register.
+
+ @return The contents of the ID_AA64ISAR0 register.
+
+**/
+UINT64
+EFIAPI
+ArmReadIdIsar0 (
+ VOID
+ );
+
+#endif /* ARM_RNG_H_ */
+
diff --git a/MdePkg/Library/BaseRngLib/BaseRngLibInternals.h b/MdePkg/Library/BaseRngLib/BaseRngLibInternals.h
new file mode 100644
index 000000000000..b6b4e9eef227
--- /dev/null
+++ b/MdePkg/Library/BaseRngLib/BaseRngLibInternals.h
@@ -0,0 +1,78 @@
+/** @file
+
+ Architecture specific interface to RNG functionality.
+
+Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef BASE_RNGLIB_INTERNALS_H_
+
+/**
+ Generates a 16-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 16-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber16 (
+ OUT UINT16 *Rand
+ );
+
+/**
+ Generates a 32-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 32-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber32 (
+ OUT UINT32 *Rand
+ );
+
+/**
+ Generates a 64-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 64-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber64 (
+ OUT UINT64 *Rand
+ );
+
+/**
+ Checks whether the RNG instruction is supported.
+
+ @retval TRUE RNG instruction is supported.
+ @retval FALSE RNG instruction is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+ArchIsRngSupported (
+ VOID
+ );
+
+#if defined (MDE_CPU_AARCH64)
+
+// RNDR, Random Number
+#define RNDR S3_3_C2_C4_0
+
+#endif
+
+#endif // BASE_RNGLIB_INTERNALS_H_
diff --git a/MdePkg/Library/BaseRngLib/AArch64/Rndr.c b/MdePkg/Library/BaseRngLib/AArch64/Rndr.c
new file mode 100644
index 000000000000..c9f8c813ed35
--- /dev/null
+++ b/MdePkg/Library/BaseRngLib/AArch64/Rndr.c
@@ -0,0 +1,139 @@
+/** @file
+ Random number generator service that uses the RNDR instruction
+ to provide pseudorandom numbers.
+
+ Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+ Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/RngLib.h>
+
+#include "ArmRng.h"
+#include "BaseRngLibInternals.h"
+
+STATIC BOOLEAN mRndrSupported;
+
+//
+// Bit mask used to determine if RNDR instruction is supported.
+//
+#define RNDR_MASK ((UINT64)MAX_UINT16 << 60U)
+
+/**
+ The constructor function checks whether or not RNDR instruction is supported
+ by the host hardware.
+
+ The constructor function checks whether or not RNDR instruction is supported.
+ It will ASSERT() if RNDR instruction is not supported.
+ It will always return EFI_SUCCESS.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+BaseRngLibConstructor (
+ VOID
+ )
+{
+ UINT64 Isar0;
+ //
+ // Determine RNDR support by examining bits 63:60 of the ISAR0 register returned by
+ // MSR. A non-zero value indicates that the processor supports the RNDR instruction.
+ //
+ Isar0 = ArmReadIdIsar0 ();
+ ASSERT ((Isar0 & RNDR_MASK) != 0);
+
+ mRndrSupported = ((Isar0 & RNDR_MASK) != 0);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Generates a 16-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 16-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber16 (
+ OUT UINT16 *Rand
+ )
+{
+ UINT64 Rand64;
+
+ if (ArchGetRandomNumber64 (&Rand64)) {
+ *Rand = Rand64 & MAX_UINT16;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Generates a 32-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 32-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber32 (
+ OUT UINT32 *Rand
+ )
+{
+ UINT64 Rand64;
+
+ if (ArchGetRandomNumber64 (&Rand64)) {
+ *Rand = Rand64 & MAX_UINT32;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Generates a 64-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 64-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber64 (
+ OUT UINT64 *Rand
+ )
+{
+ return ArmRndr (Rand);
+}
+
+/**
+ Checks whether RNDR is supported.
+
+ @retval TRUE RNDR is supported.
+ @retval FALSE RNDR is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+ArchIsRngSupported (
+ VOID
+ )
+{
+ return mRndrSupported;
+}
diff --git a/MdePkg/Library/BaseRngLib/BaseRng.c b/MdePkg/Library/BaseRngLib/BaseRng.c
index 7ad7aec9d38f..5b63d8f7146b 100644
--- a/MdePkg/Library/BaseRngLib/BaseRng.c
+++ b/MdePkg/Library/BaseRngLib/BaseRng.c
@@ -1,8 +1,10 @@
/** @file
- Random number generator services that uses RdRand instruction access
- to provide high-quality random numbers.
+ Random number generator services that uses CPU RNG instructions to
+ provide random numbers.

+Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+
SPDX-License-Identifier: BSD-2-Clause-Patent

**/
@@ -10,46 +12,15 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>

-//
-// Bit mask used to determine if RdRand instruction is supported.
-//
-#define RDRAND_MASK BIT30
+#include "BaseRngLibInternals.h"

//
// Limited retry number when valid random data is returned.
// Uses the recommended value defined in Section 7.3.17 of "Intel 64 and IA-32
-// Architectures Software Developer's Mannual".
+// Architectures Software Developer's Manual".
//
-#define RDRAND_RETRY_LIMIT 10
+#define GETRANDOM_RETRY_LIMIT 10

-/**
- The constructor function checks whether or not RDRAND instruction is supported
- by the host hardware.
-
- The constructor function checks whether or not RDRAND instruction is supported.
- It will ASSERT() if RDRAND instruction is not supported.
- It will always return RETURN_SUCCESS.
-
- @retval RETURN_SUCCESS The constructor always returns EFI_SUCCESS.
-
-**/
-RETURN_STATUS
-EFIAPI
-BaseRngLibConstructor (
- VOID
- )
-{
- UINT32 RegEcx;
-
- //
- // Determine RDRAND support by examining bit 30 of the ECX register returned by
- // CPUID. A value of 1 indicates that processor support RDRAND instruction.
- //
- AsmCpuid (1, 0, 0, &RegEcx, 0);
- ASSERT ((RegEcx & RDRAND_MASK) == RDRAND_MASK);
-
- return RETURN_SUCCESS;
-}

/**
Generates a 16-bit random number.
@@ -72,11 +43,19 @@ GetRandomNumber16 (

ASSERT (Rand != NULL);

+ if (Rand == NULL) {
+ return FALSE;
+ }
+
+ if (!ArchIsRngSupported ()) {
+ return FALSE;
+ }
+
//
// A loop to fetch a 16 bit random value with a retry count limit.
//
- for (Index = 0; Index < RDRAND_RETRY_LIMIT; Index++) {
- if (AsmRdRand16 (Rand)) {
+ for (Index = 0; Index < GETRANDOM_RETRY_LIMIT; Index++) {
+ if (ArchGetRandomNumber16 (Rand)) {
return TRUE;
}
}
@@ -105,11 +84,19 @@ GetRandomNumber32 (

ASSERT (Rand != NULL);

+ if (Rand == NULL) {
+ return FALSE;
+ }
+
+ if (!ArchIsRngSupported ()) {
+ return FALSE;
+ }
+
//
// A loop to fetch a 32 bit random value with a retry count limit.
//
- for (Index = 0; Index < RDRAND_RETRY_LIMIT; Index++) {
- if (AsmRdRand32 (Rand)) {
+ for (Index = 0; Index < GETRANDOM_RETRY_LIMIT; Index++) {
+ if (ArchGetRandomNumber32 (Rand)) {
return TRUE;
}
}
@@ -138,11 +125,19 @@ GetRandomNumber64 (

ASSERT (Rand != NULL);

+ if (Rand == NULL) {
+ return FALSE;
+ }
+
+ if (!ArchIsRngSupported ()) {
+ return FALSE;
+ }
+
//
// A loop to fetch a 64 bit random value with a retry count limit.
//
- for (Index = 0; Index < RDRAND_RETRY_LIMIT; Index++) {
- if (AsmRdRand64 (Rand)) {
+ for (Index = 0; Index < GETRANDOM_RETRY_LIMIT; Index++) {
+ if (ArchGetRandomNumber64 (Rand)) {
return TRUE;
}
}
@@ -169,6 +164,14 @@ GetRandomNumber128 (
{
ASSERT (Rand != NULL);

+ if (Rand == NULL) {
+ return FALSE;
+ }
+
+ if (!ArchIsRngSupported ()) {
+ return FALSE;
+ }
+
//
// Read first 64 bits
//
diff --git a/MdePkg/Library/BaseRngLib/Rand/RdRand.c b/MdePkg/Library/BaseRngLib/Rand/RdRand.c
new file mode 100644
index 000000000000..09fb875ac3f9
--- /dev/null
+++ b/MdePkg/Library/BaseRngLib/Rand/RdRand.c
@@ -0,0 +1,131 @@
+/** @file
+ Random number generator services that uses RdRand instruction access
+ to provide high-quality random numbers.
+
+Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#include "BaseRngLibInternals.h"
+
+//
+// Bit mask used to determine if RdRand instruction is supported.
+//
+#define RDRAND_MASK BIT30
+
+
+STATIC BOOLEAN mRdRandSupported;
+
+/**
+ The constructor function checks whether or not RDRAND instruction is supported
+ by the host hardware.
+
+ The constructor function checks whether or not RDRAND instruction is supported.
+ It will ASSERT() if RDRAND instruction is not supported.
+ It will always return EFI_SUCCESS.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+BaseRngLibConstructor (
+ VOID
+ )
+{
+ UINT32 RegEcx;
+
+ //
+ // Determine RDRAND support by examining bit 30 of the ECX register returned by
+ // CPUID. A value of 1 indicates that processor support RDRAND instruction.
+ //
+ AsmCpuid (1, 0, 0, &RegEcx, 0);
+ ASSERT ((RegEcx & RDRAND_MASK) == RDRAND_MASK);
+
+ mRdRandSupported = ((RegEcx & RDRAND_MASK) == RDRAND_MASK);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Generates a 16-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 16-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber16 (
+ OUT UINT16 *Rand
+ )
+{
+ return AsmRdRand16 (Rand);
+}
+
+/**
+ Generates a 32-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 32-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber32 (
+ OUT UINT32 *Rand
+ )
+{
+ return AsmRdRand32 (Rand);
+}
+
+/**
+ Generates a 64-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 64-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber64 (
+ OUT UINT64 *Rand
+ )
+{
+ return AsmRdRand64 (Rand);
+}
+
+/**
+ Checks whether RDRAND is supported.
+
+ @retval TRUE RDRAND is supported.
+ @retval FALSE RDRAND is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+ArchIsRngSupported (
+ VOID
+ )
+{
+ /*
+ Existing software depends on this always returning TRUE, so for
+ now hard-code it.
+
+ return mRdRandSupported;
+ */
+ return TRUE;
+}
diff --git a/MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.S b/MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.S
new file mode 100644
index 000000000000..82a00d362212
--- /dev/null
+++ b/MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.S
@@ -0,0 +1,31 @@
+#------------------------------------------------------------------------------
+#
+# ArmReadIdIsar0() for AArch64
+#
+# Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#------------------------------------------------------------------------------
+
+.text
+.p2align 2
+GCC_ASM_EXPORT(ArmReadIdIsar0)
+
+#/**
+# Reads the ID_AA64ISAR0 Register.
+#
+# @return The contents of the ID_AA64ISAR0 register.
+#
+#**/
+#UINT64
+#EFIAPI
+#ArmReadIdIsar0 (
+# VOID
+# );
+#
+ASM_PFX(ArmReadIdIsar0):
+ mrs x0, id_aa64isar0_el1 // Read ID_AA64ISAR0 Register
+ ret
+
+
diff --git a/MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.asm b/MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.asm
new file mode 100644
index 000000000000..1d9f9a808c0c
--- /dev/null
+++ b/MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.asm
@@ -0,0 +1,30 @@
+;------------------------------------------------------------------------------
+;
+; ArmReadIdIsar0() for AArch64
+;
+; Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+ EXPORT ArmReadIdIsar0
+ AREA BaseLib_LowLevel, CODE, READONLY
+
+;/**
+; Reads the ID_AA64ISAR0 Register.
+;
+; @return The contents of the ID_AA64ISAR0 register.
+;
+;**/
+;UINT64
+;EFIAPI
+;ArmReadIdIsar0 (
+; VOID
+; );
+;
+ArmReadIdIsar0
+ mrs x0, id_aa64isar0_el1 // Read ID_AA64ISAR0 Register
+ ret
+
+ END
diff --git a/MdePkg/Library/BaseRngLib/AArch64/ArmRng.S b/MdePkg/Library/BaseRngLib/AArch64/ArmRng.S
new file mode 100644
index 000000000000..5159f467e3a6
--- /dev/null
+++ b/MdePkg/Library/BaseRngLib/AArch64/ArmRng.S
@@ -0,0 +1,37 @@
+#------------------------------------------------------------------------------
+#
+# ArmRndr() for AArch64
+#
+# Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#------------------------------------------------------------------------------
+
+#include "BaseRngLibInternals.h"
+
+.text
+.p2align 2
+GCC_ASM_EXPORT(ArmRndr)
+
+#/**
+# Generates a random number using RNDR.
+# Returns TRUE on success; FALSE on failure.
+#
+# @param[out] Rand Buffer pointer to store the 64-bit random value.
+#
+# @retval TRUE Random number generated successfully.
+# @retval FALSE Failed to generate the random number.
+#
+#**/
+#BOOLEAN
+#EFIAPI
+#ArmRndr (
+# OUT UINT64 *Rand
+# );
+#
+ASM_PFX(ArmRndr):
+ mrs x1, RNDR
+ str x1, [x0]
+ cset x0, ne // RNDR sets NZCV to 0b0100 on failure
+ ret
diff --git a/MdePkg/Library/BaseRngLib/AArch64/ArmRng.asm b/MdePkg/Library/BaseRngLib/AArch64/ArmRng.asm
new file mode 100644
index 000000000000..33144196cb54
--- /dev/null
+++ b/MdePkg/Library/BaseRngLib/AArch64/ArmRng.asm
@@ -0,0 +1,39 @@
+;------------------------------------------------------------------------------
+;
+; ArmRndr() for AArch64
+;
+; Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+#include "BaseRngLibInternals.h"
+
+ EXPORT ArmRndr
+ AREA BaseLib_LowLevel, CODE, READONLY
+
+
+;/**
+; Generates a random number using RNDR.
+; Returns TRUE on success; FALSE on failure.
+;
+; @param[out] Rand Buffer pointer to store the 64-bit random value.
+;
+; @retval TRUE Random number generated successfully.
+; @retval FALSE Failed to generate the random number.
+;
+;**/
+;BOOLEAN
+;EFIAPI
+;ArmRndr (
+; OUT UINT64 *Rand
+; );
+;
+ArmRndr
+ mrs x1, RNDR
+ str x1, [x0]
+ cset x0, ne // RNDR sets NZCV to 0b0100 on failure
+ ret
+
+ END
diff --git a/MdePkg/Library/BaseRngLib/BaseRngLib.uni b/MdePkg/Library/BaseRngLib/BaseRngLib.uni
index f3ed954c5209..de5d4f9dd869 100644
--- a/MdePkg/Library/BaseRngLib/BaseRngLib.uni
+++ b/MdePkg/Library/BaseRngLib/BaseRngLib.uni
@@ -1,8 +1,8 @@
// /** @file
// Instance of RNG (Random Number Generator) Library.
//
-// BaseRng Library that uses CPU RdRand instruction access to provide
-// high-quality random numbers.
+// BaseRng Library that uses CPU RNG instructions to provide
+// random numbers.
//
// Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
//
@@ -13,5 +13,5 @@

#string STR_MODULE_ABSTRACT #language en-US "Instance of RNG Library"

-#string STR_MODULE_DESCRIPTION #language en-US "BaseRng Library that uses CPU RdRand instruction access to provide high-quality random numbers"
+#string STR_MODULE_DESCRIPTION #language en-US "BaseRng Library that uses CPU RNG instructions to provide random numbers"
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.


Re: [PATCH v2] BaseTools: Add support for version 3 of FMP Image Header structure

Michael D Kinney
 

Hi Sughosh,

 

Thanks for the reminder. 

 

We need to wait for one of the BaseTools maintainers to provide an Rb for the V2 version of this patch, then we will be able to merge.

 

Thanks,

 

Mike

 

From: Sughosh Ganu <sughosh.ganu@...>
Sent: Tuesday, May 11, 2021 3:21 AM
To: Kinney, Michael D <michael.d.kinney@...>; Feng, Bob C <bob.c.feng@...>; Liming Gao <gaoliming@...>; Chen, Christine <yuwei.chen@...>
Cc: devel@edk2.groups.io
Subject: Re: [edk2-devel] [PATCH v2] BaseTools: Add support for version 3 of FMP Image Header structure

 

hi,

Can this patch be merged. Thanks.

 

-sughosh

 

On Mon, 26 Apr 2021 at 21:27, Kinney, Michael D <michael.d.kinney@...> wrote:

Reviewed-by: Michael D Kinney <michael.d.kinney@...>

Mike

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Sughosh Ganu
> Sent: Friday, April 23, 2021 4:29 AM
> To: devel@edk2.groups.io
> Cc: Michal Simek <michal.simek@...>; Sughosh Ganu <sughosh.ganu@...>
> Subject: [edk2-devel] [PATCH v2] BaseTools: Add support for version 3 of FMP Image Header structure
>
> Add support for the ImageCapsuleSupport field, introduced in version 3
> of the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER structure. This
> structure member is used to indicate if the corresponding payload has
> support for authentication and dependency.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@...>
> ---
>
> Changes since v1:
> - Reword the patch header to get rid of the PatchCheck warning
> - Make passing of ImageCapsuleSupport parameter to the AddPayload
>   function as an optional parameter to maintain backward compatibility
> - Declare the values of CAPSULE_SUPPORT_DEPENDENCY and
>   CAPSULE_SUPPORT_AUTHENTICATION in the FmpCapsuleHeaderClass and use
>   those in the GenerateCapsule script
>
>  .../Source/Python/Capsule/GenerateCapsule.py  |  5 +++-
>  .../Common/Uefi/Capsule/FmpCapsuleHeader.py   | 28 +++++++++++++------
>  2 files changed, 24 insertions(+), 9 deletions(-)
>
> diff --git a/BaseTools/Source/Python/Capsule/GenerateCapsule.py b/BaseTools/Source/Python/Capsule/GenerateCapsule.py
> index a8de988253..b8039db878 100644
> --- a/BaseTools/Source/Python/Capsule/GenerateCapsule.py
> +++ b/BaseTools/Source/Python/Capsule/GenerateCapsule.py
> @@ -561,6 +561,7 @@ if __name__ == '__main__':
>                  print ('GenerateCapsule: error:' + str(Msg))
>                  sys.exit (1)
>          for SinglePayloadDescriptor in PayloadDescriptorList:
> +            ImageCapsuleSupport = 0x0000000000000000
>              Result = SinglePayloadDescriptor.Payload
>              try:
>                  FmpPayloadHeader.FwVersion              = SinglePayloadDescriptor.FwVersion
> @@ -575,6 +576,7 @@ if __name__ == '__main__':
>              if SinglePayloadDescriptor.UseDependency:
>                  CapsuleDependency.Payload = Result
>                  CapsuleDependency.DepexExp = SinglePayloadDescriptor.DepexExp
> +                ImageCapsuleSupport        |= FmpCapsuleHeader.CAPSULE_SUPPORT_DEPENDENCY
>                  Result = CapsuleDependency.Encode ()
>                  if args.Verbose:
>                      CapsuleDependency.DumpInfo ()
> @@ -607,13 +609,14 @@ if __name__ == '__main__':
>                      FmpAuthHeader.MonotonicCount = SinglePayloadDescriptor.MonotonicCount
>                      FmpAuthHeader.CertData       = CertData
>                      FmpAuthHeader.Payload        = Result
> +                    ImageCapsuleSupport          |= FmpCapsuleHeader.CAPSULE_SUPPORT_AUTHENTICATION
>                      Result = FmpAuthHeader.Encode ()
>                      if args.Verbose:
>                          FmpAuthHeader.DumpInfo ()
>                  except:
>                      print ('GenerateCapsule: error: can not encode FMP Auth Header')
>                      sys.exit (1)
> -            FmpCapsuleHeader.AddPayload (SinglePayloadDescriptor.Guid, Result, HardwareInstance =
> SinglePayloadDescriptor.HardwareInstance, UpdateImageIndex = SinglePayloadDescriptor.UpdateImageIndex)
> +            FmpCapsuleHeader.AddPayload (SinglePayloadDescriptor.Guid, Result, HardwareInstance =
> SinglePayloadDescriptor.HardwareInstance, UpdateImageIndex = SinglePayloadDescriptor.UpdateImageIndex, CapsuleSupport =
> ImageCapsuleSupport)
>          try:
>              for EmbeddedDriver in EmbeddedDriverDescriptorList:
>                  FmpCapsuleHeader.AddEmbeddedDriver(EmbeddedDriver)
> diff --git a/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
> b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
> index 91d24919c4..8abb449c6f 100644
> --- a/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
> +++ b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
> @@ -47,14 +47,19 @@ class FmpCapsuleImageHeaderClass (object):
>      #   /// therefore can be modified without changing the Auth data.
>      #   ///
>      #   UINT64   UpdateHardwareInstance;
> +    #
> +    #   ///
> +    #   /// Bits which indicate authentication and depex information for the image that follows this structure
> +    #   ///
> +    #   UINT64   ImageCapsuleSupport
>      # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER;
>      #
> -    #  #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION 0x00000002
> +    #  #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION 0x00000003
>
> -    _StructFormat = '<I16sB3BIIQ'
> +    _StructFormat = '<I16sB3BIIQQ'
>      _StructSize   = struct.calcsize (_StructFormat)
>
> -    EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION = 0x00000002
> +    EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION = 0x00000003
>
>      def __init__ (self):
>          self._Valid                 = False
> @@ -64,6 +69,7 @@ class FmpCapsuleImageHeaderClass (object):
>          self.UpdateImageSize        = 0
>          self.UpdateVendorCodeSize   = 0
>          self.UpdateHardwareInstance = 0x0000000000000000
> +        self.ImageCapsuleSupport    = 0x0000000000000000
>          self.Payload                = b''
>          self.VendorCodeBytes        = b''
>
> @@ -78,7 +84,8 @@ class FmpCapsuleImageHeaderClass (object):
>                                           0,0,0,
>                                           self.UpdateImageSize,
>                                           self.UpdateVendorCodeSize,
> -                                         self.UpdateHardwareInstance
> +                                         self.UpdateHardwareInstance,
> +                                         self.ImageCapsuleSupport
>                                           )
>          self._Valid = True
>          return FmpCapsuleImageHeader + self.Payload + self.VendorCodeBytes
> @@ -86,7 +93,7 @@ class FmpCapsuleImageHeaderClass (object):
>      def Decode (self, Buffer):
>          if len (Buffer) < self._StructSize:
>              raise ValueError
> -        (Version, UpdateImageTypeId, UpdateImageIndex, r0, r1, r2, UpdateImageSize, UpdateVendorCodeSize,
> UpdateHardwareInstance) = \
> +        (Version, UpdateImageTypeId, UpdateImageIndex, r0, r1, r2, UpdateImageSize, UpdateVendorCodeSize,
> UpdateHardwareInstance, ImageCapsuleSupport) = \
>              struct.unpack (
>                       self._StructFormat,
>                       Buffer[0:self._StructSize]
> @@ -105,6 +112,7 @@ class FmpCapsuleImageHeaderClass (object):
>          self.UpdateImageSize        = UpdateImageSize
>          self.UpdateVendorCodeSize   = UpdateVendorCodeSize
>          self.UpdateHardwareInstance = UpdateHardwareInstance
> +        self.ImageCapsuleSupport    = ImageCapsuleSupport
>          self.Payload                = Buffer[self._StructSize:self._StructSize + UpdateImageSize]
>          self.VendorCodeBytes        = Buffer[self._StructSize + UpdateImageSize:]
>          self._Valid                 = True
> @@ -119,6 +127,7 @@ class FmpCapsuleImageHeaderClass (object):
>          print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageSize        = {UpdateImageSize:08X}'.format
> (UpdateImageSize = self.UpdateImageSize))
>          print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateVendorCodeSize   = {UpdateVendorCodeSize:08X}'.format
> (UpdateVendorCodeSize = self.UpdateVendorCodeSize))
>          print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateHardwareInstance =
> {UpdateHardwareInstance:016X}'.format (UpdateHardwareInstance = self.UpdateHardwareInstance))
> +        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.ImageCapsuleSupport    = {ImageCapsuleSupport:016X}'.format
> (ImageCapsuleSupport = self.ImageCapsuleSupport))
>          print ('sizeof (Payload)                                                    = {Size:08X}'.format (Size = len
> (self.Payload)))
>          print ('sizeof (VendorCodeBytes)                                            = {Size:08X}'.format (Size = len
> (self.VendorCodeBytes)))
>
> @@ -153,6 +162,8 @@ class FmpCapsuleHeaderClass (object):
>      _ItemOffsetSize   = struct.calcsize (_ItemOffsetFormat)
>
>      EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION = 0x00000001
> +    CAPSULE_SUPPORT_AUTHENTICATION = 0x0000000000000001
> +    CAPSULE_SUPPORT_DEPENDENCY     = 0x0000000000000002
>
>      def __init__ (self):
>          self._Valid                     = False
> @@ -172,8 +183,8 @@ class FmpCapsuleHeaderClass (object):
>              raise ValueError
>          return self._EmbeddedDriverList[Index]
>
> -    def AddPayload (self, UpdateImageTypeId, Payload = b'', VendorCodeBytes = b'', HardwareInstance = 0, UpdateImageIndex
> = 1):
> -        self._PayloadList.append ((UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance, UpdateImageIndex))
> +    def AddPayload (self, UpdateImageTypeId, Payload = b'', VendorCodeBytes = b'', HardwareInstance = 0, UpdateImageIndex
> = 1, CapsuleSupport = 0):
> +        self._PayloadList.append ((UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance, UpdateImageIndex,
> CapsuleSupport))
>
>      def GetFmpCapsuleImageHeader (self, Index):
>          if Index >= len (self._FmpCapsuleImageHeaderList):
> @@ -198,13 +209,14 @@ class FmpCapsuleHeaderClass (object):
>              self._ItemOffsetList.append (Offset)
>              Offset = Offset + len (EmbeddedDriver)
>          Index = 1
> -        for (UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance, UpdateImageIndex) in self._PayloadList:
> +        for (UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance, UpdateImageIndex, CapsuleSupport) in
> self._PayloadList:
>              FmpCapsuleImageHeader = FmpCapsuleImageHeaderClass ()
>              FmpCapsuleImageHeader.UpdateImageTypeId      = UpdateImageTypeId
>              FmpCapsuleImageHeader.UpdateImageIndex       = UpdateImageIndex
>              FmpCapsuleImageHeader.Payload                = Payload
>              FmpCapsuleImageHeader.VendorCodeBytes        = VendorCodeBytes
>              FmpCapsuleImageHeader.UpdateHardwareInstance = HardwareInstance
> +            FmpCapsuleImageHeader.ImageCapsuleSupport    = CapsuleSupport
>              FmpCapsuleImage = FmpCapsuleImageHeader.Encode ()
>              FmpCapsuleData = FmpCapsuleData + FmpCapsuleImage
>
> --
> 2.17.1
>
>
>
>
>


Re: [PATCH v3 2/2] SecurityPkg: Add support for RngDxe on AARCH64

Yao, Jiewen
 

Acked-by: Jiewen Yao <Jiewen.yao@intel.com>

Need ARM expert to double confirm.

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Ard
Biesheuvel
Sent: Tuesday, May 11, 2021 10:44 PM
To: Rebecca Cran <rebecca@nuviainc.com>; Yao, Jiewen
<jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
Cc: edk2-devel-groups-io <devel@edk2.groups.io>; Kinney, Michael D
<michael.d.kinney@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>; Liu,
Zhiguang <zhiguang.liu@intel.com>; Ard Biesheuvel
<ardb+tianocore@kernel.org>; Sami Mujawar <sami.mujawar@arm.com>
Subject: Re: [edk2-devel] [PATCH v3 2/2] SecurityPkg: Add support for RngDxe
on AARCH64

On Mon, 10 May 2021 at 23:53, Rebecca Cran <rebecca@nuviainc.com> wrote:

AARCH64 support has been added to BaseRngLib via the optional
ARMv8.5 FEAT_RNG.

Refactor RngDxe to support AARCH64, note support for it in the
VALID_ARCHITECTURES line of RngDxe.inf and enable it in SecurityPkg.dsc.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
I'm happy to take these and merge them if I can get an ack from a
SecurityPkg maintainer.


---
SecurityPkg/SecurityPkg.dec | 2 +
SecurityPkg/SecurityPkg.dsc | 11 +-
SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf | 24 ++-
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/AesCore.h | 0
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/RdRand.h | 17 --
SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h | 117
++++++++++++++
SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c | 127
+++++++++++++++
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/AesCore.c | 0
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/RdRand.c | 45 +-
----
SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c | 146
+++++++++++++++++
SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c | 170
++++++++------------
11 files changed, 483 insertions(+), 176 deletions(-)

diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
index dfbbb0365a2b..4001650fa28e 100644
--- a/SecurityPkg/SecurityPkg.dec
+++ b/SecurityPkg/SecurityPkg.dec
@@ -297,6 +297,8 @@ [PcdsFixedAtBuild, PcdsPatchableInModule]
gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeFvVerificationPass|0x0303100A|
UINT32|0x00010030
gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeFvVerificationFail|0x0303100B|
UINT32|0x00010031

+
gEfiSecurityPkgTokenSpaceGuid.PcdCpuRngSupportedAlgorithm|{0x00,0x00,0x0
0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}|VOID
*|0x00010032
+
[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
## Image verification policy for OptionRom. Only following values are
valid:<BR><BR>
# NOTE: Do NOT use 0x5 and 0x2 since it violates the UEFI specification and
has been removed.<BR>
diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index 12ccd1634941..bd4b810bce61 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -259,6 +259,12 @@ [Components]
[Components.IA32, Components.X64, Components.ARM,
Components.AARCH64]
SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf

+[Components.IA32, Components.X64, Components.AARCH64]
+ #
+ # Random Number Generator
+ #
+ SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
+
[Components.IA32, Components.X64]
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDx
e.inf

@@ -334,11 +340,6 @@ [Components.IA32, Components.X64]
SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib
.inf
SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalP
resenceLib.inf

- #
- # Random Number Generator
- #
- SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
-
#
# Opal Password solution
#
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
index 99d6f6b35fc2..f3300971993f 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
@@ -26,15 +26,22 @@ [Defines]
#
# The following information is for reference only and not required by the build
tools.
#
-# VALID_ARCHITECTURES = IA32 X64
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
#

[Sources.common]
RngDxe.c
- RdRand.c
- RdRand.h
- AesCore.c
- AesCore.h
+ RngDxeInternals.h
+
+[Sources.IA32, Sources.X64]
+ Rand/RngDxe.c
+ Rand/RdRand.c
+ Rand/RdRand.h
+ Rand/AesCore.c
+ Rand/AesCore.h
+
+[Sources.AARCH64]
+ AArch64/RngDxe.c

[Packages]
MdePkg/MdePkg.dec
@@ -50,12 +57,19 @@ [LibraryClasses]
RngLib

[Guids]
+ gEfiRngAlgorithmSp80090Hash256Guid ## SOMETIMES_PRODUCES ##
GUID # Unique ID of the algorithm for RNG
+ gEfiRngAlgorithmSp80090Hmac256Guid ## SOMETIMES_PRODUCES ##
GUID # Unique ID of the algorithm for RNG
gEfiRngAlgorithmSp80090Ctr256Guid ## SOMETIMES_PRODUCES ## GUID
# Unique ID of the algorithm for RNG
+ gEfiRngAlgorithmX9313DesGuid ## SOMETIMES_PRODUCES ## GUID
# Unique ID of the algorithm for RNG
+ gEfiRngAlgorithmX931AesGuid ## SOMETIMES_PRODUCES ## GUID
# Unique ID of the algorithm for RNG
gEfiRngAlgorithmRaw ## SOMETIMES_PRODUCES ## GUID #
Unique ID of the algorithm for RNG

[Protocols]
gEfiRngProtocolGuid ## PRODUCES

+[Pcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdCpuRngSupportedAlgorithm ##
CONSUMES
+
[Depex]
TRUE

diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.h
b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.h
similarity index 100%
rename from SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.h
rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.h
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.h
b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.h
similarity index 72%
rename from SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.h
rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.h
index 12ab1f34ec6d..072378e062e7 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.h
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.h
@@ -23,23 +23,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/TimerLib.h>
#include <Protocol/Rng.h>

-/**
- Calls RDRAND to fill a buffer of arbitrary size with random bytes.
-
- @param[in] Length Size of the buffer, in bytes, to fill with.
- @param[out] RandBuffer Pointer to the buffer to store the random result.
-
- @retval EFI_SUCCESS Random bytes generation succeeded.
- @retval EFI_NOT_READY Failed to request random bytes.
-
-**/
-EFI_STATUS
-EFIAPI
-RdRandGetBytes (
- IN UINTN Length,
- OUT UINT8 *RandBuffer
- );
-
/**
Generate high-quality entropy source through RDRAND.

diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
new file mode 100644
index 000000000000..2660ed5875e0
--- /dev/null
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
@@ -0,0 +1,117 @@
+/** @file
+ Function prototypes for UEFI Random Number Generator protocol support.
+
+ Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef RNGDXE_INTERNALS_H_
+#define RNGDXE_INTERNALS_H_
+
+/**
+ 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.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetInfo (
+ IN EFI_RNG_PROTOCOL *This,
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ );
+
+/**
+ 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.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetRNG (
+ IN EFI_RNG_PROTOCOL *This,
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
+ IN UINTN RNGValueLength,
+ OUT UINT8 *RNGValue
+ );
+
+/**
+ Returns information about the random number generation implementation.
+
+ @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_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too
small to hold the result.
+
+**/
+UINTN
+EFIAPI
+ArchGetSupportedRngAlgorithms (
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ );
+
+/**
+ Runs CPU RNG instruction to fill a buffer of arbitrary size with random bytes.
+
+ @param[in] Length Size of the buffer, in bytes, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random bytes generation succeeded.
+ @retval EFI_NOT_READY Failed to request random bytes.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetBytes (
+ IN UINTN Length,
+ OUT UINT8 *RandBuffer
+ );
+
+#endif // RNGDXE_INTERNALS_H_
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
new file mode 100644
index 000000000000..2810a9eb94ad
--- /dev/null
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
@@ -0,0 +1,127 @@
+/** @file
+ RNG Driver to produce the UEFI Random Number Generator protocol.
+
+ The driver will use the RNDR instruction to produce random numbers.
+
+ RNG Algorithms defined in UEFI 2.4:
+ - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID
+ - EFI_RNG_ALGORITHM_RAW - Unsupported
+ - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID
+ - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID
+ - EFI_RNG_ALGORITHM_X9_31_3DES_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_X9_31_AES_GUID - Unsupported
+
+ Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+ Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/TimerLib.h>
+#include <Protocol/Rng.h>
+
+#include "RngDxeInternals.h"
+
+/**
+ 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.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetRNG (
+ IN EFI_RNG_PROTOCOL *This,
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
+ IN UINTN RNGValueLength,
+ OUT UINT8 *RNGValue
+ )
+{
+ EFI_STATUS Status;
+
+ if ((RNGValueLength == 0) || (RNGValue == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (RNGAlgorithm == NULL) {
+ //
+ // Use the default RNG algorithm if RNGAlgorithm is NULL.
+ //
+ RNGAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);
+ }
+
+ if (CompareGuid (RNGAlgorithm, PcdGetPtr
(PcdCpuRngSupportedAlgorithm))) {
+ Status = RngGetBytes (RNGValueLength, RNGValue);
+ return Status;
+ }
+
+ //
+ // Other algorithms are unsupported by this driver.
+ //
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Returns information about the random number generation implementation.
+
+ @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_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too
small to hold the result.
+
+**/
+UINTN
+EFIAPI
+ArchGetSupportedRngAlgorithms (
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ )
+{
+ UINTN RequiredSize;
+ EFI_RNG_ALGORITHM *CpuRngSupportedAlgorithm;
+
+ RequiredSize = sizeof (EFI_RNG_ALGORITHM);
+
+ if (*RNGAlgorithmListSize < RequiredSize) {
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ CpuRngSupportedAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);
+
+ CopyMem(&RNGAlgorithmList[0], CpuRngSupportedAlgorithm, sizeof
(EFI_RNG_ALGORITHM));
+
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_SUCCESS;
+}
+
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.c
b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.c
similarity index 100%
rename from SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.c
rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.c
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c
b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.c
similarity index 71%
rename from SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c
rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.c
index e7dd5ab18111..83025a47d43d 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.c
@@ -8,48 +8,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/RngLib.h>

-#include "RdRand.h"
#include "AesCore.h"
-
-/**
- Calls RDRAND to fill a buffer of arbitrary size with random bytes.
-
- @param[in] Length Size of the buffer, in bytes, to fill with.
- @param[out] RandBuffer Pointer to the buffer to store the random result.
-
- @retval EFI_SUCCESS Random bytes generation succeeded.
- @retval EFI_NOT_READY Failed to request random bytes.
-
-**/
-EFI_STATUS
-EFIAPI
-RdRandGetBytes (
- IN UINTN Length,
- OUT UINT8 *RandBuffer
- )
-{
- BOOLEAN IsRandom;
- UINT64 TempRand[2];
-
- while (Length > 0) {
- IsRandom = GetRandomNumber128 (TempRand);
- if (!IsRandom) {
- return EFI_NOT_READY;
- }
- if (Length >= sizeof (TempRand)) {
- WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[0]);
- RandBuffer += sizeof (UINT64);
- WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[1]);
- RandBuffer += sizeof (UINT64);
- Length -= sizeof (TempRand);
- } else {
- CopyMem (RandBuffer, TempRand, Length);
- Length = 0;
- }
- }
-
- return EFI_SUCCESS;
-}
+#include "RdRand.h"
+#include "RngDxeInternals.h"

/**
Creates a 128bit random value that is fully forward and backward prediction
resistant,
@@ -92,7 +53,7 @@ RdRandGetSeed128 (
//
for (Index = 0; Index < 32; Index++) {
MicroSecondDelay (10);
- Status = RdRandGetBytes (16, RandByte);
+ Status = RngGetBytes (16, RandByte);
if (EFI_ERROR (Status)) {
return Status;
}
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
new file mode 100644
index 000000000000..6b628a9f8bc6
--- /dev/null
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
@@ -0,0 +1,146 @@
+/** @file
+ RNG Driver to produce the UEFI Random Number Generator protocol.
+
+ The driver will use the new RDRAND instruction to produce high-quality,
high-performance
+ entropy and random number.
+
+ RNG Algorithms defined in UEFI 2.4:
+ - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID - Supported
+ (RDRAND implements a hardware NIST SP800-90 AES-CTR-256 based
DRBG)
+ - EFI_RNG_ALGORITHM_RAW - Supported
+ (Structuring RDRAND invocation can be guaranteed as high-quality entropy
source)
+ - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_X9_31_3DES_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_X9_31_AES_GUID - Unsupported
+
+ Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RdRand.h"
+#include "RngDxeInternals.h"
+
+/**
+ 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.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetRNG (
+ IN EFI_RNG_PROTOCOL *This,
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
+ IN UINTN RNGValueLength,
+ OUT UINT8 *RNGValue
+ )
+{
+ EFI_STATUS Status;
+
+ if ((RNGValueLength == 0) || (RNGValue == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ if (RNGAlgorithm == NULL) {
+ //
+ // Use the default RNG algorithm if RNGAlgorithm is NULL.
+ //
+ RNGAlgorithm = &gEfiRngAlgorithmSp80090Ctr256Guid;
+ }
+
+ //
+ // NIST SP800-90-AES-CTR-256 supported by RDRAND
+ //
+ if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmSp80090Ctr256Guid)) {
+ Status = RngGetBytes (RNGValueLength, RNGValue);
+ return Status;
+ }
+
+ //
+ // The "raw" algorithm is intended to provide entropy directly
+ //
+ if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) {
+ //
+ // When a DRBG is used on the output of a entropy source,
+ // its security level must be at least 256 bits according to UEFI Spec.
+ //
+ if (RNGValueLength < 32) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = RdRandGenerateEntropy (RNGValueLength, RNGValue);
+ return Status;
+ }
+
+ //
+ // Other algorithms were unsupported by this driver.
+ //
+ return Status;
+}
+
+/**
+ Returns information about the random number generation implementation.
+
+ @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_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too
small to hold the result.
+
+**/
+UINTN
+EFIAPI
+ArchGetSupportedRngAlgorithms (
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ )
+{
+ UINTN RequiredSize;
+ EFI_RNG_ALGORITHM *CpuRngSupportedAlgorithm;
+
+ RequiredSize = 2 * sizeof (EFI_RNG_ALGORITHM);
+
+ if (*RNGAlgorithmListSize < RequiredSize) {
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ CpuRngSupportedAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);
+
+ CopyMem(&RNGAlgorithmList[0], CpuRngSupportedAlgorithm, sizeof
(EFI_RNG_ALGORITHM));
+
+ // x86 platforms also support EFI_RNG_ALGORITHM_RAW via RDSEED
+ CopyMem(&RNGAlgorithmList[1], &gEfiRngAlgorithmRaw, sizeof
(EFI_RNG_ALGORITHM));
+
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_SUCCESS;
+}
+
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
index 13d3dbd0bfbe..b959c70536ea 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
@@ -1,34 +1,32 @@
/** @file
RNG Driver to produce the UEFI Random Number Generator protocol.

- The driver will use the new RDRAND instruction to produce high-quality,
high-performance
- entropy and random number.
+ The driver uses CPU RNG instructions to produce high-quality,
+ high-performance entropy and random number.

RNG Algorithms defined in UEFI 2.4:
- - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID - Supported
- (RDRAND implements a hardware NIST SP800-90 AES-CTR-256 based DRBG)
- - EFI_RNG_ALGORITHM_RAW - Supported
- (Structuring RDRAND invocation can be guaranteed as high-quality entropy
source)
- - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID - Unsupported
- - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID - Unsupported
- - EFI_RNG_ALGORITHM_X9_31_3DES_GUID - Unsupported
- - EFI_RNG_ALGORITHM_X9_31_AES_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID
+ - EFI_RNG_ALGORITHM_RAW
+ - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID
+ - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID
+ - EFI_RNG_ALGORITHM_X9_31_3DES_GUID
+ - EFI_RNG_ALGORITHM_X9_31_AES_GUID

Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

-#include "RdRand.h"
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/RngLib.h>
+#include <Library/TimerLib.h>
+#include <Protocol/Rng.h>

-//
-// Supported RNG Algorithms list by this driver.
-//
-EFI_RNG_ALGORITHM mSupportedRngAlgorithms[] = {
- EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID,
- EFI_RNG_ALGORITHM_RAW
-};
+#include "RngDxeInternals.h"

/**
Returns information about the random number generation implementation.
@@ -62,106 +60,23 @@ RngGetInfo (
)
{
EFI_STATUS Status;
- UINTN RequiredSize;

if ((This == NULL) || (RNGAlgorithmListSize == NULL)) {
return EFI_INVALID_PARAMETER;
}

- RequiredSize = sizeof (mSupportedRngAlgorithms);
- if (*RNGAlgorithmListSize < RequiredSize) {
- Status = EFI_BUFFER_TOO_SMALL;
+ //
+ // Return algorithm list supported by driver.
+ //
+ if (RNGAlgorithmList != NULL) {
+ Status = ArchGetSupportedRngAlgorithms (RNGAlgorithmListSize,
RNGAlgorithmList);
} else {
- //
- // Return algorithm list supported by driver.
- //
- if (RNGAlgorithmList != NULL) {
- CopyMem (RNGAlgorithmList, mSupportedRngAlgorithms, RequiredSize);
- Status = EFI_SUCCESS;
- } else {
- Status = EFI_INVALID_PARAMETER;
- }
+ Status = EFI_INVALID_PARAMETER;
}
- *RNGAlgorithmListSize = RequiredSize;

return Status;
}

-/**
- 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.
-
-**/
-EFI_STATUS
-EFIAPI
-RngGetRNG (
- IN EFI_RNG_PROTOCOL *This,
- IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
- IN UINTN RNGValueLength,
- OUT UINT8 *RNGValue
- )
-{
- EFI_STATUS Status;
-
- if ((RNGValueLength == 0) || (RNGValue == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Status = EFI_UNSUPPORTED;
- if (RNGAlgorithm == NULL) {
- //
- // Use the default RNG algorithm if RNGAlgorithm is NULL.
- //
- RNGAlgorithm = &gEfiRngAlgorithmSp80090Ctr256Guid;
- }
-
- //
- // NIST SP800-90-AES-CTR-256 supported by RDRAND
- //
- if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmSp80090Ctr256Guid)) {
- Status = RdRandGetBytes (RNGValueLength, RNGValue);
- return Status;
- }
-
- //
- // The "raw" algorithm is intended to provide entropy directly
- //
- if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) {
- //
- // When a DRBG is used on the output of a entropy source,
- // its security level must be at least 256 bits according to UEFI Spec.
- //
- if (RNGValueLength < 32) {
- return EFI_INVALID_PARAMETER;
- }
-
- Status = RdRandGenerateEntropy (RNGValueLength, RNGValue);
- return Status;
- }
-
- //
- // Other algorithms were unsupported by this driver.
- //
- return Status;
-}
-
//
// The Random Number Generator (RNG) protocol
//
@@ -204,3 +119,44 @@ RngDriverEntry (

return Status;
}
+
+
+/**
+ Calls RDRAND to fill a buffer of arbitrary size with random bytes.
+
+ @param[in] Length Size of the buffer, in bytes, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random bytes generation succeeded.
+ @retval EFI_NOT_READY Failed to request random bytes.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetBytes (
+ IN UINTN Length,
+ OUT UINT8 *RandBuffer
+ )
+{
+ BOOLEAN IsRandom;
+ UINT64 TempRand[2];
+
+ while (Length > 0) {
+ IsRandom = GetRandomNumber128 (TempRand);
+ if (!IsRandom) {
+ return EFI_NOT_READY;
+ }
+ if (Length >= sizeof (TempRand)) {
+ WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[0]);
+ RandBuffer += sizeof (UINT64);
+ WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[1]);
+ RandBuffer += sizeof (UINT64);
+ Length -= sizeof (TempRand);
+ } else {
+ CopyMem (RandBuffer, TempRand, Length);
+ Length = 0;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
--
2.26.2



Re: [PATCH v3 2/2] SecurityPkg: Add support for RngDxe on AARCH64

Ard Biesheuvel
 

On Mon, 10 May 2021 at 23:53, Rebecca Cran <rebecca@nuviainc.com> wrote:

AARCH64 support has been added to BaseRngLib via the optional
ARMv8.5 FEAT_RNG.

Refactor RngDxe to support AARCH64, note support for it in the
VALID_ARCHITECTURES line of RngDxe.inf and enable it in SecurityPkg.dsc.

Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
I'm happy to take these and merge them if I can get an ack from a
SecurityPkg maintainer.


---
SecurityPkg/SecurityPkg.dec | 2 +
SecurityPkg/SecurityPkg.dsc | 11 +-
SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf | 24 ++-
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/AesCore.h | 0
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/RdRand.h | 17 --
SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h | 117 ++++++++++++++
SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c | 127 +++++++++++++++
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/AesCore.c | 0
SecurityPkg/RandomNumberGenerator/RngDxe/{ => Rand}/RdRand.c | 45 +-----
SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c | 146 +++++++++++++++++
SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c | 170 ++++++++------------
11 files changed, 483 insertions(+), 176 deletions(-)

diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
index dfbbb0365a2b..4001650fa28e 100644
--- a/SecurityPkg/SecurityPkg.dec
+++ b/SecurityPkg/SecurityPkg.dec
@@ -297,6 +297,8 @@ [PcdsFixedAtBuild, PcdsPatchableInModule]
gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeFvVerificationPass|0x0303100A|UINT32|0x00010030
gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeFvVerificationFail|0x0303100B|UINT32|0x00010031

+ gEfiSecurityPkgTokenSpaceGuid.PcdCpuRngSupportedAlgorithm|{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}|VOID*|0x00010032
+
[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
## Image verification policy for OptionRom. Only following values are valid:<BR><BR>
# NOTE: Do NOT use 0x5 and 0x2 since it violates the UEFI specification and has been removed.<BR>
diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index 12ccd1634941..bd4b810bce61 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -259,6 +259,12 @@ [Components]
[Components.IA32, Components.X64, Components.ARM, Components.AARCH64]
SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf

+[Components.IA32, Components.X64, Components.AARCH64]
+ #
+ # Random Number Generator
+ #
+ SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
+
[Components.IA32, Components.X64]
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf

@@ -334,11 +340,6 @@ [Components.IA32, Components.X64]
SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf
SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalPresenceLib.inf

- #
- # Random Number Generator
- #
- SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
-
#
# Opal Password solution
#
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
index 99d6f6b35fc2..f3300971993f 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
@@ -26,15 +26,22 @@ [Defines]
#
# The following information is for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = IA32 X64
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
#

[Sources.common]
RngDxe.c
- RdRand.c
- RdRand.h
- AesCore.c
- AesCore.h
+ RngDxeInternals.h
+
+[Sources.IA32, Sources.X64]
+ Rand/RngDxe.c
+ Rand/RdRand.c
+ Rand/RdRand.h
+ Rand/AesCore.c
+ Rand/AesCore.h
+
+[Sources.AARCH64]
+ AArch64/RngDxe.c

[Packages]
MdePkg/MdePkg.dec
@@ -50,12 +57,19 @@ [LibraryClasses]
RngLib

[Guids]
+ gEfiRngAlgorithmSp80090Hash256Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
+ gEfiRngAlgorithmSp80090Hmac256Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
gEfiRngAlgorithmSp80090Ctr256Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
+ gEfiRngAlgorithmX9313DesGuid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
+ gEfiRngAlgorithmX931AesGuid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
gEfiRngAlgorithmRaw ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG

[Protocols]
gEfiRngProtocolGuid ## PRODUCES

+[Pcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdCpuRngSupportedAlgorithm ## CONSUMES
+
[Depex]
TRUE

diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.h b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.h
similarity index 100%
rename from SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.h
rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.h
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.h b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.h
similarity index 72%
rename from SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.h
rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.h
index 12ab1f34ec6d..072378e062e7 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.h
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.h
@@ -23,23 +23,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/TimerLib.h>
#include <Protocol/Rng.h>

-/**
- Calls RDRAND to fill a buffer of arbitrary size with random bytes.
-
- @param[in] Length Size of the buffer, in bytes, to fill with.
- @param[out] RandBuffer Pointer to the buffer to store the random result.
-
- @retval EFI_SUCCESS Random bytes generation succeeded.
- @retval EFI_NOT_READY Failed to request random bytes.
-
-**/
-EFI_STATUS
-EFIAPI
-RdRandGetBytes (
- IN UINTN Length,
- OUT UINT8 *RandBuffer
- );
-
/**
Generate high-quality entropy source through RDRAND.

diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
new file mode 100644
index 000000000000..2660ed5875e0
--- /dev/null
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
@@ -0,0 +1,117 @@
+/** @file
+ Function prototypes for UEFI Random Number Generator protocol support.
+
+ Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef RNGDXE_INTERNALS_H_
+#define RNGDXE_INTERNALS_H_
+
+/**
+ 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.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetInfo (
+ IN EFI_RNG_PROTOCOL *This,
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ );
+
+/**
+ 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.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetRNG (
+ IN EFI_RNG_PROTOCOL *This,
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
+ IN UINTN RNGValueLength,
+ OUT UINT8 *RNGValue
+ );
+
+/**
+ Returns information about the random number generation implementation.
+
+ @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_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small to hold the result.
+
+**/
+UINTN
+EFIAPI
+ArchGetSupportedRngAlgorithms (
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ );
+
+/**
+ Runs CPU RNG instruction to fill a buffer of arbitrary size with random bytes.
+
+ @param[in] Length Size of the buffer, in bytes, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random bytes generation succeeded.
+ @retval EFI_NOT_READY Failed to request random bytes.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetBytes (
+ IN UINTN Length,
+ OUT UINT8 *RandBuffer
+ );
+
+#endif // RNGDXE_INTERNALS_H_
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
new file mode 100644
index 000000000000..2810a9eb94ad
--- /dev/null
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
@@ -0,0 +1,127 @@
+/** @file
+ RNG Driver to produce the UEFI Random Number Generator protocol.
+
+ The driver will use the RNDR instruction to produce random numbers.
+
+ RNG Algorithms defined in UEFI 2.4:
+ - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID
+ - EFI_RNG_ALGORITHM_RAW - Unsupported
+ - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID
+ - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID
+ - EFI_RNG_ALGORITHM_X9_31_3DES_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_X9_31_AES_GUID - Unsupported
+
+ Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+ Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/TimerLib.h>
+#include <Protocol/Rng.h>
+
+#include "RngDxeInternals.h"
+
+/**
+ 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.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetRNG (
+ IN EFI_RNG_PROTOCOL *This,
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
+ IN UINTN RNGValueLength,
+ OUT UINT8 *RNGValue
+ )
+{
+ EFI_STATUS Status;
+
+ if ((RNGValueLength == 0) || (RNGValue == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (RNGAlgorithm == NULL) {
+ //
+ // Use the default RNG algorithm if RNGAlgorithm is NULL.
+ //
+ RNGAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);
+ }
+
+ if (CompareGuid (RNGAlgorithm, PcdGetPtr (PcdCpuRngSupportedAlgorithm))) {
+ Status = RngGetBytes (RNGValueLength, RNGValue);
+ return Status;
+ }
+
+ //
+ // Other algorithms are unsupported by this driver.
+ //
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Returns information about the random number generation implementation.
+
+ @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_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small to hold the result.
+
+**/
+UINTN
+EFIAPI
+ArchGetSupportedRngAlgorithms (
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ )
+{
+ UINTN RequiredSize;
+ EFI_RNG_ALGORITHM *CpuRngSupportedAlgorithm;
+
+ RequiredSize = sizeof (EFI_RNG_ALGORITHM);
+
+ if (*RNGAlgorithmListSize < RequiredSize) {
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ CpuRngSupportedAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);
+
+ CopyMem(&RNGAlgorithmList[0], CpuRngSupportedAlgorithm, sizeof (EFI_RNG_ALGORITHM));
+
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_SUCCESS;
+}
+
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.c b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.c
similarity index 100%
rename from SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.c
rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.c
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.c
similarity index 71%
rename from SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c
rename to SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.c
index e7dd5ab18111..83025a47d43d 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.c
@@ -8,48 +8,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/RngLib.h>

-#include "RdRand.h"
#include "AesCore.h"
-
-/**
- Calls RDRAND to fill a buffer of arbitrary size with random bytes.
-
- @param[in] Length Size of the buffer, in bytes, to fill with.
- @param[out] RandBuffer Pointer to the buffer to store the random result.
-
- @retval EFI_SUCCESS Random bytes generation succeeded.
- @retval EFI_NOT_READY Failed to request random bytes.
-
-**/
-EFI_STATUS
-EFIAPI
-RdRandGetBytes (
- IN UINTN Length,
- OUT UINT8 *RandBuffer
- )
-{
- BOOLEAN IsRandom;
- UINT64 TempRand[2];
-
- while (Length > 0) {
- IsRandom = GetRandomNumber128 (TempRand);
- if (!IsRandom) {
- return EFI_NOT_READY;
- }
- if (Length >= sizeof (TempRand)) {
- WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[0]);
- RandBuffer += sizeof (UINT64);
- WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[1]);
- RandBuffer += sizeof (UINT64);
- Length -= sizeof (TempRand);
- } else {
- CopyMem (RandBuffer, TempRand, Length);
- Length = 0;
- }
- }
-
- return EFI_SUCCESS;
-}
+#include "RdRand.h"
+#include "RngDxeInternals.h"

/**
Creates a 128bit random value that is fully forward and backward prediction resistant,
@@ -92,7 +53,7 @@ RdRandGetSeed128 (
//
for (Index = 0; Index < 32; Index++) {
MicroSecondDelay (10);
- Status = RdRandGetBytes (16, RandByte);
+ Status = RngGetBytes (16, RandByte);
if (EFI_ERROR (Status)) {
return Status;
}
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
new file mode 100644
index 000000000000..6b628a9f8bc6
--- /dev/null
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
@@ -0,0 +1,146 @@
+/** @file
+ RNG Driver to produce the UEFI Random Number Generator protocol.
+
+ The driver will use the new RDRAND instruction to produce high-quality, high-performance
+ entropy and random number.
+
+ RNG Algorithms defined in UEFI 2.4:
+ - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID - Supported
+ (RDRAND implements a hardware NIST SP800-90 AES-CTR-256 based DRBG)
+ - EFI_RNG_ALGORITHM_RAW - Supported
+ (Structuring RDRAND invocation can be guaranteed as high-quality entropy source)
+ - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_X9_31_3DES_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_X9_31_AES_GUID - Unsupported
+
+ Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RdRand.h"
+#include "RngDxeInternals.h"
+
+/**
+ 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.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetRNG (
+ IN EFI_RNG_PROTOCOL *This,
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
+ IN UINTN RNGValueLength,
+ OUT UINT8 *RNGValue
+ )
+{
+ EFI_STATUS Status;
+
+ if ((RNGValueLength == 0) || (RNGValue == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ if (RNGAlgorithm == NULL) {
+ //
+ // Use the default RNG algorithm if RNGAlgorithm is NULL.
+ //
+ RNGAlgorithm = &gEfiRngAlgorithmSp80090Ctr256Guid;
+ }
+
+ //
+ // NIST SP800-90-AES-CTR-256 supported by RDRAND
+ //
+ if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmSp80090Ctr256Guid)) {
+ Status = RngGetBytes (RNGValueLength, RNGValue);
+ return Status;
+ }
+
+ //
+ // The "raw" algorithm is intended to provide entropy directly
+ //
+ if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) {
+ //
+ // When a DRBG is used on the output of a entropy source,
+ // its security level must be at least 256 bits according to UEFI Spec.
+ //
+ if (RNGValueLength < 32) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = RdRandGenerateEntropy (RNGValueLength, RNGValue);
+ return Status;
+ }
+
+ //
+ // Other algorithms were unsupported by this driver.
+ //
+ return Status;
+}
+
+/**
+ Returns information about the random number generation implementation.
+
+ @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_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small to hold the result.
+
+**/
+UINTN
+EFIAPI
+ArchGetSupportedRngAlgorithms (
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ )
+{
+ UINTN RequiredSize;
+ EFI_RNG_ALGORITHM *CpuRngSupportedAlgorithm;
+
+ RequiredSize = 2 * sizeof (EFI_RNG_ALGORITHM);
+
+ if (*RNGAlgorithmListSize < RequiredSize) {
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ CpuRngSupportedAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);
+
+ CopyMem(&RNGAlgorithmList[0], CpuRngSupportedAlgorithm, sizeof (EFI_RNG_ALGORITHM));
+
+ // x86 platforms also support EFI_RNG_ALGORITHM_RAW via RDSEED
+ CopyMem(&RNGAlgorithmList[1], &gEfiRngAlgorithmRaw, sizeof (EFI_RNG_ALGORITHM));
+
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_SUCCESS;
+}
+
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
index 13d3dbd0bfbe..b959c70536ea 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
@@ -1,34 +1,32 @@
/** @file
RNG Driver to produce the UEFI Random Number Generator protocol.

- The driver will use the new RDRAND instruction to produce high-quality, high-performance
- entropy and random number.
+ The driver uses CPU RNG instructions to produce high-quality,
+ high-performance entropy and random number.

RNG Algorithms defined in UEFI 2.4:
- - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID - Supported
- (RDRAND implements a hardware NIST SP800-90 AES-CTR-256 based DRBG)
- - EFI_RNG_ALGORITHM_RAW - Supported
- (Structuring RDRAND invocation can be guaranteed as high-quality entropy source)
- - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID - Unsupported
- - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID - Unsupported
- - EFI_RNG_ALGORITHM_X9_31_3DES_GUID - Unsupported
- - EFI_RNG_ALGORITHM_X9_31_AES_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID
+ - EFI_RNG_ALGORITHM_RAW
+ - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID
+ - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID
+ - EFI_RNG_ALGORITHM_X9_31_3DES_GUID
+ - EFI_RNG_ALGORITHM_X9_31_AES_GUID

Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

-#include "RdRand.h"
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/RngLib.h>
+#include <Library/TimerLib.h>
+#include <Protocol/Rng.h>

-//
-// Supported RNG Algorithms list by this driver.
-//
-EFI_RNG_ALGORITHM mSupportedRngAlgorithms[] = {
- EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID,
- EFI_RNG_ALGORITHM_RAW
-};
+#include "RngDxeInternals.h"

/**
Returns information about the random number generation implementation.
@@ -62,106 +60,23 @@ RngGetInfo (
)
{
EFI_STATUS Status;
- UINTN RequiredSize;

if ((This == NULL) || (RNGAlgorithmListSize == NULL)) {
return EFI_INVALID_PARAMETER;
}

- RequiredSize = sizeof (mSupportedRngAlgorithms);
- if (*RNGAlgorithmListSize < RequiredSize) {
- Status = EFI_BUFFER_TOO_SMALL;
+ //
+ // Return algorithm list supported by driver.
+ //
+ if (RNGAlgorithmList != NULL) {
+ Status = ArchGetSupportedRngAlgorithms (RNGAlgorithmListSize, RNGAlgorithmList);
} else {
- //
- // Return algorithm list supported by driver.
- //
- if (RNGAlgorithmList != NULL) {
- CopyMem (RNGAlgorithmList, mSupportedRngAlgorithms, RequiredSize);
- Status = EFI_SUCCESS;
- } else {
- Status = EFI_INVALID_PARAMETER;
- }
+ Status = EFI_INVALID_PARAMETER;
}
- *RNGAlgorithmListSize = RequiredSize;

return Status;
}

-/**
- 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.
-
-**/
-EFI_STATUS
-EFIAPI
-RngGetRNG (
- IN EFI_RNG_PROTOCOL *This,
- IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
- IN UINTN RNGValueLength,
- OUT UINT8 *RNGValue
- )
-{
- EFI_STATUS Status;
-
- if ((RNGValueLength == 0) || (RNGValue == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Status = EFI_UNSUPPORTED;
- if (RNGAlgorithm == NULL) {
- //
- // Use the default RNG algorithm if RNGAlgorithm is NULL.
- //
- RNGAlgorithm = &gEfiRngAlgorithmSp80090Ctr256Guid;
- }
-
- //
- // NIST SP800-90-AES-CTR-256 supported by RDRAND
- //
- if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmSp80090Ctr256Guid)) {
- Status = RdRandGetBytes (RNGValueLength, RNGValue);
- return Status;
- }
-
- //
- // The "raw" algorithm is intended to provide entropy directly
- //
- if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) {
- //
- // When a DRBG is used on the output of a entropy source,
- // its security level must be at least 256 bits according to UEFI Spec.
- //
- if (RNGValueLength < 32) {
- return EFI_INVALID_PARAMETER;
- }
-
- Status = RdRandGenerateEntropy (RNGValueLength, RNGValue);
- return Status;
- }
-
- //
- // Other algorithms were unsupported by this driver.
- //
- return Status;
-}
-
//
// The Random Number Generator (RNG) protocol
//
@@ -204,3 +119,44 @@ RngDriverEntry (

return Status;
}
+
+
+/**
+ Calls RDRAND to fill a buffer of arbitrary size with random bytes.
+
+ @param[in] Length Size of the buffer, in bytes, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random bytes generation succeeded.
+ @retval EFI_NOT_READY Failed to request random bytes.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetBytes (
+ IN UINTN Length,
+ OUT UINT8 *RandBuffer
+ )
+{
+ BOOLEAN IsRandom;
+ UINT64 TempRand[2];
+
+ while (Length > 0) {
+ IsRandom = GetRandomNumber128 (TempRand);
+ if (!IsRandom) {
+ return EFI_NOT_READY;
+ }
+ if (Length >= sizeof (TempRand)) {
+ WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[0]);
+ RandBuffer += sizeof (UINT64);
+ WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[1]);
+ RandBuffer += sizeof (UINT64);
+ Length -= sizeof (TempRand);
+ } else {
+ CopyMem (RandBuffer, TempRand, Length);
+ Length = 0;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
--
2.26.2


Re: Build fails with VS2012

Laszlo Ersek
 

On 05/11/21 02:14, Rebecca Cran wrote:
Thanks. The obvious toolchains that are missing from ReadMe.rst are any
versions of XCODE and CLANG.
Also, it might be nice to specify _which_ GCC5 versions are supported,
since that covers gcc 5 through 11 and gcc 5.x currently causes a build
error. We maybe only care about gcc 7 and newer these days?

I just tried building with VS2015 and VS2013, and there was a build
error because it seems the location of rc.exe has changed. After fixing
that they successfully built OVMF. But it sounds like we possibly only
want to make sure that VS2017 and VS2019 are kept working now.

I've cc'd Bret and Sean because I'm wondering if there are plans to add
more toolchain/OS combinations into the GitHub/Azure solution? For
example adding macOS with XCODE5? Also, how about post-commit or nightly
builds that run more extensive tests, possibly generating binaries for
OVMF that people can try without building it themselves? Or would that
be something that might be useful for me to implement as a third-party
solution?
Too many good questions!

Personally, I care for gcc-8, and later.

Thanks
Laszlo


Re: [edk2-platforms][PATCH V3 00/14] Platform/Sgi: Add PPTT table for Neoverse Reference Design platforms

Sami Mujawar
 

Pushed as 67988fb53dbc..8549b1739183 with minor edits to doxygen comment style.

Thanks.

Regards,

Sami Mujawar

On 10/05/2021 09:06 PM, Pranav Madhu wrote:
Changes since V2:
- Introduced CPU container object into DSDT
- Addressed comments from Sami

Changes since V1:
- Rebase the patches on top of latest master branch
- Addressed comments from Pierre

Processor Properties Topology Table (PPTT) describes the topological
structure of processors, and their shared resources such as caches.
This patch series adds PPTT table for Arm's Neoverse Reference Design
platforms.

The first patch in this series adds helper macros for PPTT table, and
the subsequent patches in this series adds PPTT table for Neoverse
Reference Design platforms which is mandatory as per Arm SystemReady SR
specification.

Link to github branch with the patches in this series -
https://github.com/Pranav-Madhu/edk2-platforms/tree/topics/rd_pptt

Pranav Madhu (14):
Platform/Sgi: Helper macros for PPTT Table
Platform/Sgi: Add CPU container for SGI-575
Platform/Sgi: ACPI PPTT table for SGI-575 platform
Platform/Sgi: Add CPU container for RD-N1-Edge
Platform/Sgi: ACPI PPTT table for RD-N1-Edge platform
Platform/Sgi: Add DSDT ACPI table for RD-N1-Edge dual-chip platform
Platform/Sgi: ACPI PPTT table for RD-N1-Edge dual-chip
Platform/Sgi: ACPI PPTT table for RD-E1-Edge platform
Platform/Sgi: Add CPU container for RD-V1 platform
Platform/Sgi: ACPI PPTT Table for RD-V1 platform
Platform/Sgi: Add CPU container for RD-V1 quad-chip platform
Platform/Sgi: ACPI PPTT Table for RD-V1 quad-chip platform
Platform/Sgi: Add CPU container for RD-N2 platform
Platform/Sgi: ACPI PPTT table for RD-N2 platform

.../SgiPkg/AcpiTables/RdE1EdgeAcpiTables.inf | 3 +-
.../SgiPkg/AcpiTables/RdN1EdgeAcpiTables.inf | 3 +-
.../AcpiTables/RdN1EdgeX2AcpiTables.inf | 3 +-
.../ARM/SgiPkg/AcpiTables/RdN2AcpiTables.inf | 3 +-
.../ARM/SgiPkg/AcpiTables/RdV1AcpiTables.inf | 3 +-
.../SgiPkg/AcpiTables/RdV1McAcpiTables.inf | 1 +
.../SgiPkg/AcpiTables/Sgi575AcpiTables.inf | 3 +-
Platform/ARM/SgiPkg/Include/SgiAcpiHeader.h | 170 ++++++++++++
.../ARM/SgiPkg/AcpiTables/RdE1Edge/Pptt.aslc | 252 ++++++++++++++++++
.../ARM/SgiPkg/AcpiTables/RdN1Edge/Dsdt.asl | 88 +++---
.../ARM/SgiPkg/AcpiTables/RdN1Edge/Pptt.aslc | 186 +++++++++++++
.../ARM/SgiPkg/AcpiTables/RdN1EdgeX2/Dsdt.asl | 136 ++++++++++
.../SgiPkg/AcpiTables/RdN1EdgeX2/Pptt.aslc | 207 ++++++++++++++
Platform/ARM/SgiPkg/AcpiTables/RdN2/Dsdt.asl | 176 ++++++++----
Platform/ARM/SgiPkg/AcpiTables/RdN2/Pptt.aslc | 175 ++++++++++++
Platform/ARM/SgiPkg/AcpiTables/RdV1/Dsdt.asl | 176 ++++++++----
Platform/ARM/SgiPkg/AcpiTables/RdV1/Pptt.aslc | 175 ++++++++++++
.../ARM/SgiPkg/AcpiTables/RdV1Mc/Dsdt.asl | 177 ++++++++----
.../ARM/SgiPkg/AcpiTables/RdV1Mc/Pptt.aslc | 184 +++++++++++++
.../ARM/SgiPkg/AcpiTables/Sgi575/Dsdt.asl | 99 +++----
.../ARM/SgiPkg/AcpiTables/Sgi575/Pptt.aslc | 172 ++++++++++++
21 files changed, 2156 insertions(+), 236 deletions(-)
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/RdE1Edge/Pptt.aslc
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/RdN1Edge/Pptt.aslc
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/RdN1EdgeX2/Dsdt.asl
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/RdN1EdgeX2/Pptt.aslc
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/RdN2/Pptt.aslc
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/RdV1/Pptt.aslc
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/RdV1Mc/Pptt.aslc
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/Sgi575/Pptt.aslc


Re: [PATCH 13/13] OvmfPkg/BaseMemEncryptSevLib: remove Flush parameter

Laszlo Ersek
 

I don't fully understand the updates in this patch:

On 05/07/21 22:38, Brijesh Singh wrote:
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

The Flush parameter is used to provide a hint whether the specified range
is Mmio address. Now that we have a dedicated helper to clear the
memory encryption mask for the Mmio address range, its safe to remove the
Flush parameter from MemEncryptSev{Set,Clear}PageEncMask().
This looks good; it matches my request (1) from:

https://listman.redhat.com/archives/edk2-devel-archive/2021-May/msg00109.html


Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
OvmfPkg/Include/Library/MemEncryptSevLib.h | 10 ++----
.../BaseMemEncryptSevLib/X64/VirtualMemory.h | 10 ++----
OvmfPkg/AmdSevDxe/AmdSevDxe.c | 3 +-
OvmfPkg/IoMmuDxe/AmdSevIoMmu.c | 6 ++--
.../Ia32/MemEncryptSevLib.c | 10 ++----
.../X64/MemEncryptSevLib.c | 16 +++-------
.../X64/PeiDxeVirtualMemory.c | 32 +++++++++++--------
.../X64/SecVirtualMemory.c | 8 ++---
.../SmmCpuFeaturesLib/SmmCpuFeaturesLib.c | 3 +-
OvmfPkg/PlatformPei/AmdSev.c | 3 +-
10 files changed, 35 insertions(+), 66 deletions(-)

diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
index b91490d5d44d..76d06c206c8b 100644
--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
@@ -100,8 +100,6 @@ MemEncryptSevIsEnabled (
address of a memory region.
@param[in] NumPages The number of pages from start memory
region.
- @param[in] Flush Flush the caches before clearing the bit
- (mostly TRUE except MMIO addresses)

@retval RETURN_SUCCESS The attributes were cleared for the
memory region.
@@ -114,8 +112,7 @@ EFIAPI
MemEncryptSevClearPageEncMask (
IN PHYSICAL_ADDRESS Cr3BaseAddress,
IN PHYSICAL_ADDRESS BaseAddress,
- IN UINTN NumPages,
- IN BOOLEAN Flush
+ IN UINTN NumPages
);

/**
@@ -128,8 +125,6 @@ MemEncryptSevClearPageEncMask (
address of a memory region.
@param[in] NumPages The number of pages from start memory
region.
- @param[in] Flush Flush the caches before setting the bit
- (mostly TRUE except MMIO addresses)

@retval RETURN_SUCCESS The attributes were set for the memory
region.
@@ -142,8 +137,7 @@ EFIAPI
MemEncryptSevSetPageEncMask (
IN PHYSICAL_ADDRESS Cr3BaseAddress,
IN PHYSICAL_ADDRESS BaseAddress,
- IN UINTN NumPages,
- IN BOOLEAN Flush
+ IN UINTN NumPages
);


diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
index 8dc39e647b90..21bbbd1c4f9c 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
@@ -58,8 +58,6 @@ InternalGetMemEncryptionAddressMask (
@param[in] PhysicalAddress The physical address that is the start
address of a memory region.
@param[in] Length The length of memory region
- @param[in] Flush Flush the caches before applying the
- encryption mask

@retval RETURN_SUCCESS The attributes were cleared for the
memory region.
@@ -72,8 +70,7 @@ EFIAPI
InternalMemEncryptSevSetMemoryDecrypted (
IN PHYSICAL_ADDRESS Cr3BaseAddress,
IN PHYSICAL_ADDRESS PhysicalAddress,
- IN UINTN Length,
- IN BOOLEAN Flush
+ IN UINTN Length
);

/**
@@ -85,8 +82,6 @@ InternalMemEncryptSevSetMemoryDecrypted (
@param[in] PhysicalAddress The physical address that is the start
address of a memory region.
@param[in] Length The length of memory region
- @param[in] Flush Flush the caches before applying the
- encryption mask

@retval RETURN_SUCCESS The attributes were set for the memory
region.
@@ -99,8 +94,7 @@ EFIAPI
InternalMemEncryptSevSetMemoryEncrypted (
IN PHYSICAL_ADDRESS Cr3BaseAddress,
IN PHYSICAL_ADDRESS PhysicalAddress,
- IN UINTN Length,
- IN BOOLEAN Flush
+ IN UINTN Length
);

/**
diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
index 80831b81facf..41e4b291d070 100644
--- a/OvmfPkg/AmdSevDxe/AmdSevDxe.c
+++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
@@ -120,8 +120,7 @@ AmdSevDxeEntryPoint (
Status = MemEncryptSevClearPageEncMask (
0, // Cr3BaseAddress -- use current CR3
MapPagesBase, // BaseAddress
- MapPagesCount, // NumPages
- TRUE // Flush
+ MapPagesCount // NumPages
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: MemEncryptSevClearPageEncMask(): %r\n",
(1) You missed my comment (2) in
<https://listman.redhat.com/archives/edk2-devel-archive/2021-May/msg00109.html>.


diff --git a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
index 49ffa2448811..b30628078f73 100644
--- a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
+++ b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
@@ -252,8 +252,7 @@ IoMmuMap (
Status = MemEncryptSevClearPageEncMask (
0,
MapInfo->PlainTextAddress,
- MapInfo->NumberOfPages,
- TRUE
+ MapInfo->NumberOfPages
);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
@@ -407,8 +406,7 @@ IoMmuUnmapWorker (
Status = MemEncryptSevSetPageEncMask (
0,
MapInfo->PlainTextAddress,
- MapInfo->NumberOfPages,
- TRUE
+ MapInfo->NumberOfPages
);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
index 169d3118e44f..be260e0d1014 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
@@ -25,8 +25,6 @@
address of a memory region.
@param[in] NumPages The number of pages from start memory
region.
- @param[in] Flush Flush the caches before clearing the bit
- (mostly TRUE except MMIO addresses)

@retval RETURN_SUCCESS The attributes were cleared for the
memory region.
@@ -39,8 +37,7 @@ EFIAPI
MemEncryptSevClearPageEncMask (
IN PHYSICAL_ADDRESS Cr3BaseAddress,
IN PHYSICAL_ADDRESS BaseAddress,
- IN UINTN NumPages,
- IN BOOLEAN Flush
+ IN UINTN NumPages
)
{
//
@@ -59,8 +56,6 @@ MemEncryptSevClearPageEncMask (
address of a memory region.
@param[in] NumPages The number of pages from start memory
region.
- @param[in] Flush Flush the caches before setting the bit
- (mostly TRUE except MMIO addresses)

@retval RETURN_SUCCESS The attributes were set for the memory
region.
@@ -73,8 +68,7 @@ EFIAPI
MemEncryptSevSetPageEncMask (
IN PHYSICAL_ADDRESS Cr3BaseAddress,
IN PHYSICAL_ADDRESS BaseAddress,
- IN UINTN NumPages,
- IN BOOLEAN Flush
+ IN UINTN NumPages
)
{
//
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
index a2bf698bcde7..a57e8fd37fa7 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
@@ -27,8 +27,6 @@
address of a memory region.
@param[in] NumPages The number of pages from start memory
region.
- @param[in] Flush Flush the caches before clearing the bit
- (mostly TRUE except MMIO addresses)

@retval RETURN_SUCCESS The attributes were cleared for the
memory region.
@@ -41,15 +39,13 @@ EFIAPI
MemEncryptSevClearPageEncMask (
IN PHYSICAL_ADDRESS Cr3BaseAddress,
IN PHYSICAL_ADDRESS BaseAddress,
- IN UINTN NumPages,
- IN BOOLEAN Flush
+ IN UINTN NumPages
)
{
return InternalMemEncryptSevSetMemoryDecrypted (
Cr3BaseAddress,
BaseAddress,
- EFI_PAGES_TO_SIZE (NumPages),
- Flush
+ EFI_PAGES_TO_SIZE (NumPages)
);
}

@@ -63,8 +59,6 @@ MemEncryptSevClearPageEncMask (
address of a memory region.
@param[in] NumPages The number of pages from start memory
region.
- @param[in] Flush Flush the caches before setting the bit
- (mostly TRUE except MMIO addresses)

@retval RETURN_SUCCESS The attributes were set for the memory
region.
@@ -77,15 +71,13 @@ EFIAPI
MemEncryptSevSetPageEncMask (
IN PHYSICAL_ADDRESS Cr3BaseAddress,
IN PHYSICAL_ADDRESS BaseAddress,
- IN UINTN NumPages,
- IN BOOLEAN Flush
+ IN UINTN NumPages
)
{
return InternalMemEncryptSevSetMemoryEncrypted (
Cr3BaseAddress,
BaseAddress,
- EFI_PAGES_TO_SIZE (NumPages),
- Flush
+ EFI_PAGES_TO_SIZE (NumPages)
);
}

diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
index a18d336a8789..ad1021bd3e43 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
@@ -555,8 +555,7 @@ EnableReadOnlyPageWriteProtect (
address of a memory region.
@param[in] Length The length of memory region
@param[in] Mode Set or Clear mode
- @param[in] CacheFlush Flush the caches before applying the
- encryption mask
+ @param[in] Mmio The physical address range is Mmio.

@retval RETURN_SUCCESS The attributes were cleared for the
memory region.
@@ -572,7 +571,7 @@ SetMemoryEncDec (
IN PHYSICAL_ADDRESS PhysicalAddress,
IN UINTN Length,
IN MAP_RANGE_MODE Mode,
- IN BOOLEAN CacheFlush
+ IN BOOLEAN Mmio
)
{
PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
@@ -585,12 +584,23 @@ SetMemoryEncDec (
UINT64 AddressEncMask;
BOOLEAN IsWpEnabled;
RETURN_STATUS Status;
+ BOOLEAN CacheFlush;

//
// Set PageMapLevel4Entry to suppress incorrect compiler/analyzer warnings.
//
PageMapLevel4Entry = NULL;

+ //
+ // The cache need to flushed for the non-Mmio address range.
+ //
+ if (Mmio == TRUE) {
+ CacheFlush = FALSE;
+ } else {
+ CacheFlush = TRUE;
+ }
+
+ //
DEBUG ((
DEBUG_VERBOSE,
"%a:%a: Cr3Base=0x%Lx Physical=0x%Lx Length=0x%Lx Mode=%a CacheFlush=%u\n",
(2) The calculation of "CacheFlush" from "Mmio" is awkward. First, we
don't compare BOOLEANs against TRUE or FALSE, BOOLEANs just stand alone
in controlling expression (or otherwise "logical") context. Second, why
not just write:

CacheFlush = !Mmio;

But even so...

(3) ... The introduction of the "Mmio" parameter is inexplicable to me.
It apparently replaces CacheFlush (with inverse meaning), but neither
the commit message, nor the (RFCv2 -> PATCH) changelog, explain why this
replacement makes sense.

The SetMemoryEncDec() function is an internal function (not a library
class API), so this change doesn't necessarily conflict with the commit
message -- but having this change in this particular patch (the last
patch in the series) seems unjustified.

In the previous version, we updated two SetMemoryEncDec() call sites: in
InternalMemEncryptSevSetMemoryDecrypted() and
InternalMemEncryptSevSetMemoryEncrypted(), we replaced the forwarding of
"Flush" with TRUE constants.

In this version, we update *three* SetMemoryEncDec() call sites:

- in InternalMemEncryptSevSetMemoryDecrypted() and
InternalMemEncryptSevSetMemoryEncrypted(), we replace the forwarding of
"Flush" with FALSE constants,

- and in InternalMemEncryptSevClearMmioPageEncMask(), we replace the
*constant* FALSE with TRUE.

I think this very last point -- regarding
InternalMemEncryptSevClearMmioPageEncMask() -- shows that the
replacement of CacheFlush with Mmio, at this point in the series, is
unwarranted.

Minimally, this replacement / negation should be a separate patch, but
even then, I think we'd need a defensible purpose (which is not clear to
me at this point); *plus*, the "re-calculation" of CacheFlush inside
SetMemoryEncDec() from Mmio feels like a cop-out. It's only being done
to save some additional replacements in the patch, but it leaves us with
a stricly worse -- harder to understand -- function. If you really need
this replacement / negation, then please do it in a separate patch, with
a good commit message; furthermore, please replace CacheFlush
*completely*, in SetMemoryEncDec() -- please don't reintroduce it.

Thanks,
Laszlo


@@ -828,8 +838,6 @@ SetMemoryEncDec (
@param[in] PhysicalAddress The physical address that is the start
address of a memory region.
@param[in] Length The length of memory region
- @param[in] Flush Flush the caches before applying the
- encryption mask

@retval RETURN_SUCCESS The attributes were cleared for the
memory region.
@@ -842,8 +850,7 @@ EFIAPI
InternalMemEncryptSevSetMemoryDecrypted (
IN PHYSICAL_ADDRESS Cr3BaseAddress,
IN PHYSICAL_ADDRESS PhysicalAddress,
- IN UINTN Length,
- IN BOOLEAN Flush
+ IN UINTN Length
)
{

@@ -852,7 +859,7 @@ InternalMemEncryptSevSetMemoryDecrypted (
PhysicalAddress,
Length,
ClearCBit,
- Flush
+ FALSE
);
}

@@ -865,8 +872,6 @@ InternalMemEncryptSevSetMemoryDecrypted (
@param[in] PhysicalAddress The physical address that is the start
address of a memory region.
@param[in] Length The length of memory region
- @param[in] Flush Flush the caches before applying the
- encryption mask

@retval RETURN_SUCCESS The attributes were set for the memory
region.
@@ -879,8 +884,7 @@ EFIAPI
InternalMemEncryptSevSetMemoryEncrypted (
IN PHYSICAL_ADDRESS Cr3BaseAddress,
IN PHYSICAL_ADDRESS PhysicalAddress,
- IN UINTN Length,
- IN BOOLEAN Flush
+ IN UINTN Length
)
{
return SetMemoryEncDec (
@@ -888,7 +892,7 @@ InternalMemEncryptSevSetMemoryEncrypted (
PhysicalAddress,
Length,
SetCBit,
- Flush
+ FALSE
);
}

@@ -921,6 +925,6 @@ InternalMemEncryptSevClearMmioPageEncMask (
PhysicalAddress,
Length,
ClearCBit,
- FALSE
+ TRUE
);
}
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c
index bca5e3febb1b..24d19d3ca161 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c
@@ -42,8 +42,6 @@ InternalGetMemEncryptionAddressMask (
@param[in] PhysicalAddress The physical address that is the start
address of a memory region.
@param[in] Length The length of memory region
- @param[in] Flush Flush the caches before applying the
- encryption mask

@retval RETURN_SUCCESS The attributes were cleared for the
memory region.
@@ -56,8 +54,7 @@ EFIAPI
InternalMemEncryptSevSetMemoryDecrypted (
IN PHYSICAL_ADDRESS Cr3BaseAddress,
IN PHYSICAL_ADDRESS PhysicalAddress,
- IN UINTN Length,
- IN BOOLEAN Flush
+ IN UINTN Length
)
{
//
@@ -89,8 +86,7 @@ EFIAPI
InternalMemEncryptSevSetMemoryEncrypted (
IN PHYSICAL_ADDRESS Cr3BaseAddress,
IN PHYSICAL_ADDRESS PhysicalAddress,
- IN UINTN Length,
- IN BOOLEAN Flush
+ IN UINTN Length
)
{
//
diff --git a/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c b/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
index fdf2380974fa..c7cc5b0389c8 100644
--- a/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
+++ b/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
@@ -283,8 +283,7 @@ SmmCpuFeaturesSmmRelocationComplete (
Status = MemEncryptSevSetPageEncMask (
0, // Cr3BaseAddress -- use current CR3
MapPagesBase, // BaseAddress
- MapPagesCount, // NumPages
- TRUE // Flush
+ MapPagesCount // NumPages
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: MemEncryptSevSetPageEncMask(): %r\n",
diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
index dddffdebda4b..a8bf610022ba 100644
--- a/OvmfPkg/PlatformPei/AmdSev.c
+++ b/OvmfPkg/PlatformPei/AmdSev.c
@@ -72,8 +72,7 @@ AmdSevEsInitialize (
DecryptStatus = MemEncryptSevClearPageEncMask (
0,
GhcbBasePa + EFI_PAGES_TO_SIZE (PageCount),
- 1,
- TRUE
+ 1
);
ASSERT_RETURN_ERROR (DecryptStatus);
}


Re: [edk2-platforms][PATCH V3 08/14] Platform/Sgi: ACPI PPTT table for RD-E1-Edge platform

Pranav Madhu
 

Hi Sami,

Please find my response:


Hi Pranav,

Please find my response inline marked [SAMI].

Regards,

Sami Mujawar


On 10/05/2021 09:06 PM, Pranav Madhu wrote:
The RD-E1-Edge platform includes two clusters with eight multi-thread
CPUs. Each of the CPUs include 32KB L1 Data cache, 32KB L1 Instruction
cache and 256KB L2 cache. Each cluster includes a 2MB L3 cache. The
platform also includes a system level cache of 8MB. Add PPTT table for
RD-E1-Edge platform with this information.
<...>

\
+ PPTT_PROCESSOR_CLUSTER_THREADED_FLAGS, /* Flag */
\
[SAMI] I see that PPTT_PROCESSOR_CLUSTER_THREADED_FLAGS sets the
ACPI ID flag to invalid. Is there a reason for doing this?
Also, it looks like the DSDT for RD-E1-Edge platform does not have the
clusters definitions. Am I missing something here?
Can you take a look, please?
[/SAMI]
ACPI CPU container (ACPI0010) is introduced to support combined idles state for CPU core and container. Idle states are not supported for RDE1, and hence container is not added.

+ OFFSET_OF
(EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE, \
<...>

Regards,
Pranav
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.


Re: [PATCH 12/13] OvmfPkg/TpmMmioSevDecryptPei: use MemEncryptSevClearMmioPageEncMask()

Laszlo Ersek
 

On 05/07/21 22:38, Brijesh Singh wrote:
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

Use the MemEncryptSevClearMmioPageEncMask() to clear memory encryption mask
for the Mmio address range.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPeim.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPeim.c b/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPeim.c
index df2ad623308d..570c8467a673 100644
--- a/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPeim.c
+++ b/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPeim.c
@@ -62,11 +62,10 @@ TpmMmioSevDecryptPeimEntryPoint (
"%a: mapping TPM MMIO address range unencrypted\n",
__FUNCTION__));

- DecryptStatus = MemEncryptSevClearPageEncMask (
+ DecryptStatus = MemEncryptSevClearMmioPageEncMask (
0,
FixedPcdGet64 (PcdTpmBaseAddress),
- EFI_SIZE_TO_PAGES ((UINTN) 0x5000),
- FALSE
+ EFI_SIZE_TO_PAGES ((UINTN) 0x5000)
);

if (RETURN_ERROR (DecryptStatus)) {
Reviewed-by: Laszlo Ersek <lersek@redhat.com>


Re: [PATCH 11/13] OvmfPkg/QemuFlashFvbServicesRuntimeDxe: use Mmio helper to clear enc mask

Laszlo Ersek
 

On 05/07/21 22:38, Brijesh Singh wrote:
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

Use the MemEncryptSevClearMmioPageEncMask() to clear memory encryption mask
for the Mmio address range.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c | 5 ++---
OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c | 5 ++---
2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c
index 1f285e008372..ab40087a8408 100644
--- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c
+++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c
@@ -205,11 +205,10 @@ MarkIoMemoryRangeForRuntimeAccess (
// memory range.
//
if (MemEncryptSevIsEnabled ()) {
- Status = MemEncryptSevClearPageEncMask (
+ Status = MemEncryptSevClearMmioPageEncMask (
0,
BaseAddress,
- EFI_SIZE_TO_PAGES (Length),
- FALSE
+ EFI_SIZE_TO_PAGES (Length)
);
ASSERT_EFI_ERROR (Status);
}
diff --git a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c
index 7eb80bfeffae..ea75b489c7fd 100644
--- a/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c
+++ b/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c
@@ -38,11 +38,10 @@ QemuFlashBeforeProbe (
// C-bit on flash ranges from SMM page table.
//

- Status = MemEncryptSevClearPageEncMask (
+ Status = MemEncryptSevClearMmioPageEncMask (
0,
BaseAddress,
- EFI_SIZE_TO_PAGES (FdBlockSize * FdBlockCount),
- FALSE
+ EFI_SIZE_TO_PAGES (FdBlockSize * FdBlockCount)
);
ASSERT_EFI_ERROR (Status);
}
Reviewed-by: Laszlo Ersek <lersek@redhat.com>


Re: [PATCH 10/13] OvmfPkg/AmdSevDxe: use MemEncryptSevClearMmioPageEncMask() to clear EncMask

Laszlo Ersek
 

On 05/07/21 22:38, Brijesh Singh wrote:
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

Use the MemEncryptSevClearMmioPageEncMask() to clear memory encryption mask
for the Mmio and NonExistent address range.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
OvmfPkg/AmdSevDxe/AmdSevDxe.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
index 689bfb376d03..80831b81facf 100644
--- a/OvmfPkg/AmdSevDxe/AmdSevDxe.c
+++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
@@ -53,11 +53,10 @@ AmdSevDxeEntryPoint (
Desc = &AllDescMap[Index];
if (Desc->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo ||
Desc->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
- Status = MemEncryptSevClearPageEncMask (
+ Status = MemEncryptSevClearMmioPageEncMask (
0,
Desc->BaseAddress,
- EFI_SIZE_TO_PAGES (Desc->Length),
- FALSE
+ EFI_SIZE_TO_PAGES (Desc->Length)
);
ASSERT_EFI_ERROR (Status);
}
@@ -73,11 +72,10 @@ AmdSevDxeEntryPoint (
// the range.
//
if (PcdGet16 (PcdOvmfHostBridgePciDevId) == INTEL_Q35_MCH_DEVICE_ID) {
- Status = MemEncryptSevClearPageEncMask (
+ Status = MemEncryptSevClearMmioPageEncMask (
0,
FixedPcdGet64 (PcdPciExpressBaseAddress),
- EFI_SIZE_TO_PAGES (SIZE_256MB),
- FALSE
+ EFI_SIZE_TO_PAGES (SIZE_256MB)
);

ASSERT_EFI_ERROR (Status);
Reviewed-by: Laszlo Ersek <lersek@redhat.com>


Re: [edk2-platforms][PATCH V3 00/14] Platform/Sgi: Add PPTT table for Neoverse Reference Design platforms

Pranav Madhu
 

Hi Sami,

Please find my comments inline:


Hi Pranav,

Comparing with the V2 series, I see that updates to the following files or
corresponding patches are missing in this series.

- RdV1Mc/Pptt.aslc
- RdN2/Pptt.aslc

Is this intentional?
No
RdN2: https://edk2.groups.io/g/devel/message/74924
RdV1Mc: https://edk2.groups.io/g/devel/message/74922


Regards,

Sami Mujawar

On 10/05/2021 09:06 PM, Pranav Madhu wrote:
Changes since V2:
- Introduced CPU container object into DSDT
- Addressed comments from Sami
<...>

Regards,
Pranav.


Re: [PATCH 09/13] OvmfPkg/BaseMemEncryptSevLib: introduce MemEncryptSevClearMmioPageEncMask()

Laszlo Ersek
 

On 05/07/21 22:38, Brijesh Singh wrote:
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275

The MemEncryptSevClearMmioPageEncMask() helper can be used for clearing
the memory encryption mask for the Mmio region.

The MemEncryptSevClearMmioPageEncMask() is a simplifies version of
(1) s/simplifies/simplified/

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Thanks
Laszlo

MemEncryptSevClearPageEncMask() -- it does not flush the caches after
clearing the page encryption mask.

Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
OvmfPkg/Include/Library/MemEncryptSevLib.h | 25 ++++++++++++++
.../BaseMemEncryptSevLib/X64/VirtualMemory.h | 23 +++++++++++++
.../Ia32/MemEncryptSevLib.c | 31 +++++++++++++++++
.../X64/MemEncryptSevLib.c | 33 +++++++++++++++++++
.../X64/PeiDxeVirtualMemory.c | 33 +++++++++++++++++++
5 files changed, 145 insertions(+)

diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
index 99f15a7d1271..b91490d5d44d 100644
--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
@@ -203,4 +203,29 @@ MemEncryptSevGetAddressRangeState (
IN UINTN Length
);

+/**
+ This function clears memory encryption bit for the MMIO region specified by
+ BaseAddress and NumPages.
+
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
+ current CR3)
+ @param[in] BaseAddress The physical address that is the start
+ address of a MMIO region.
+ @param[in] NumPages The number of pages from start memory
+ region.
+
+ @retval RETURN_SUCCESS The attributes were cleared for the
+ memory region.
+ @retval RETURN_INVALID_PARAMETER Number of pages is zero.
+ @retval RETURN_UNSUPPORTED Clearing the memory encryption attribute
+ is not supported
+**/
+RETURN_STATUS
+EFIAPI
+MemEncryptSevClearMmioPageEncMask (
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages
+ );
+
#endif // _MEM_ENCRYPT_SEV_LIB_H_
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
index fe2a0b2826cd..8dc39e647b90 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
@@ -126,4 +126,27 @@ InternalMemEncryptSevGetAddressRangeState (
IN UINTN Length
);

+/**
+ This function clears memory encryption bit for the MMIO region specified by
+ PhysicalAddress and Length.
+
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
+ current CR3)
+ @param[in] PhysicalAddress The physical address that is the start
+ address of a MMIO region.
+ @param[in] Length The length of memory region
+
+ @retval RETURN_SUCCESS The attributes were cleared for the
+ memory region.
+ @retval RETURN_INVALID_PARAMETER Length is zero.
+ @retval RETURN_UNSUPPORTED Clearing the memory encyrption attribute
+ is not supported
+**/
+RETURN_STATUS
+EFIAPI
+InternalMemEncryptSevClearMmioPageEncMask (
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress,
+ IN UINTN Length
+ );
#endif
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
index 12a5bf495bd7..169d3118e44f 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
@@ -111,3 +111,34 @@ MemEncryptSevGetAddressRangeState (
//
return MemEncryptSevAddressRangeEncrypted;
}
+
+/**
+ This function clears memory encryption bit for the MMIO region specified by
+ BaseAddress and NumPages.
+
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
+ current CR3)
+ @param[in] BaseAddress The physical address that is the start
+ address of a MMIO region.
+ @param[in] NumPages The number of pages from start memory
+ region.
+
+ @retval RETURN_SUCCESS The attributes were cleared for the
+ memory region.
+ @retval RETURN_INVALID_PARAMETER Number of pages is zero.
+ @retval RETURN_UNSUPPORTED Clearing the memory encryption attribute
+ is not supported
+**/
+RETURN_STATUS
+EFIAPI
+MemEncryptSevClearMmioPageEncMask (
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages
+ )
+{
+ //
+ // Memory encryption bit is not accessible in 32-bit mode
+ //
+ return RETURN_UNSUPPORTED;
+}
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
index 4fea6a6be0ac..a2bf698bcde7 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
@@ -118,3 +118,36 @@ MemEncryptSevGetAddressRangeState (
Length
);
}
+
+/**
+ This function clears memory encryption bit for the mmio region specified by
+ BaseAddress and NumPages.
+
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
+ current CR3)
+ @param[in] BaseAddress The physical address that is the start
+ address of a mmio region.
+ @param[in] NumPages The number of pages from start memory
+ region.
+
+ @retval RETURN_SUCCESS The attributes were cleared for the
+ memory region.
+ @retval RETURN_INVALID_PARAMETER Number of pages is zero.
+ @retval RETURN_UNSUPPORTED Clearing the memory encryption attribute
+ is not supported
+**/
+RETURN_STATUS
+EFIAPI
+MemEncryptSevClearMmioPageEncMask (
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN NumPages
+ )
+{
+ return InternalMemEncryptSevClearMmioPageEncMask (
+ Cr3BaseAddress,
+ BaseAddress,
+ EFI_PAGES_TO_SIZE (NumPages)
+ );
+
+}
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
index d3455e812bd1..a18d336a8789 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
@@ -891,3 +891,36 @@ InternalMemEncryptSevSetMemoryEncrypted (
Flush
);
}
+
+/**
+ This function clears memory encryption bit for the MMIO region specified by
+ PhysicalAddress and Length.
+
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
+ current CR3)
+ @param[in] PhysicalAddress The physical address that is the start
+ address of a MMIO region.
+ @param[in] Length The length of memory region
+
+ @retval RETURN_SUCCESS The attributes were cleared for the
+ memory region.
+ @retval RETURN_INVALID_PARAMETER Length is zero.
+ @retval RETURN_UNSUPPORTED Clearing the memory encyrption attribute
+ is not supported
+**/
+RETURN_STATUS
+EFIAPI
+InternalMemEncryptSevClearMmioPageEncMask (
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress,
+ IN UINTN Length
+ )
+{
+ return SetMemoryEncDec (
+ Cr3BaseAddress,
+ PhysicalAddress,
+ Length,
+ ClearCBit,
+ FALSE
+ );
+}


Re: [edk2-platforms][PATCH V3 00/14] Platform/Sgi: Add PPTT table for Neoverse Reference Design platforms

Sami Mujawar
 

Hi Pranav,

Comparing with the V2 series, I see that updates to the following files or corresponding patches are missing in this series.

- RdV1Mc/Pptt.aslc
- RdN2/Pptt.aslc

Is this intentional?

Regards,

Sami Mujawar

On 10/05/2021 09:06 PM, Pranav Madhu wrote:
Changes since V2:
- Introduced CPU container object into DSDT
- Addressed comments from Sami

Changes since V1:
- Rebase the patches on top of latest master branch
- Addressed comments from Pierre

Processor Properties Topology Table (PPTT) describes the topological
structure of processors, and their shared resources such as caches.
This patch series adds PPTT table for Arm's Neoverse Reference Design
platforms.

The first patch in this series adds helper macros for PPTT table, and
the subsequent patches in this series adds PPTT table for Neoverse
Reference Design platforms which is mandatory as per Arm SystemReady SR
specification.

Link to github branch with the patches in this series -
https://github.com/Pranav-Madhu/edk2-platforms/tree/topics/rd_pptt

Pranav Madhu (14):
Platform/Sgi: Helper macros for PPTT Table
Platform/Sgi: Add CPU container for SGI-575
Platform/Sgi: ACPI PPTT table for SGI-575 platform
Platform/Sgi: Add CPU container for RD-N1-Edge
Platform/Sgi: ACPI PPTT table for RD-N1-Edge platform
Platform/Sgi: Add DSDT ACPI table for RD-N1-Edge dual-chip platform
Platform/Sgi: ACPI PPTT table for RD-N1-Edge dual-chip
Platform/Sgi: ACPI PPTT table for RD-E1-Edge platform
Platform/Sgi: Add CPU container for RD-V1 platform
Platform/Sgi: ACPI PPTT Table for RD-V1 platform
Platform/Sgi: Add CPU container for RD-V1 quad-chip platform
Platform/Sgi: ACPI PPTT Table for RD-V1 quad-chip platform
Platform/Sgi: Add CPU container for RD-N2 platform
Platform/Sgi: ACPI PPTT table for RD-N2 platform

.../SgiPkg/AcpiTables/RdE1EdgeAcpiTables.inf | 3 +-
.../SgiPkg/AcpiTables/RdN1EdgeAcpiTables.inf | 3 +-
.../AcpiTables/RdN1EdgeX2AcpiTables.inf | 3 +-
.../ARM/SgiPkg/AcpiTables/RdN2AcpiTables.inf | 3 +-
.../ARM/SgiPkg/AcpiTables/RdV1AcpiTables.inf | 3 +-
.../SgiPkg/AcpiTables/RdV1McAcpiTables.inf | 1 +
.../SgiPkg/AcpiTables/Sgi575AcpiTables.inf | 3 +-
Platform/ARM/SgiPkg/Include/SgiAcpiHeader.h | 170 ++++++++++++
.../ARM/SgiPkg/AcpiTables/RdE1Edge/Pptt.aslc | 252 ++++++++++++++++++
.../ARM/SgiPkg/AcpiTables/RdN1Edge/Dsdt.asl | 88 +++---
.../ARM/SgiPkg/AcpiTables/RdN1Edge/Pptt.aslc | 186 +++++++++++++
.../ARM/SgiPkg/AcpiTables/RdN1EdgeX2/Dsdt.asl | 136 ++++++++++
.../SgiPkg/AcpiTables/RdN1EdgeX2/Pptt.aslc | 207 ++++++++++++++
Platform/ARM/SgiPkg/AcpiTables/RdN2/Dsdt.asl | 176 ++++++++----
Platform/ARM/SgiPkg/AcpiTables/RdN2/Pptt.aslc | 175 ++++++++++++
Platform/ARM/SgiPkg/AcpiTables/RdV1/Dsdt.asl | 176 ++++++++----
Platform/ARM/SgiPkg/AcpiTables/RdV1/Pptt.aslc | 175 ++++++++++++
.../ARM/SgiPkg/AcpiTables/RdV1Mc/Dsdt.asl | 177 ++++++++----
.../ARM/SgiPkg/AcpiTables/RdV1Mc/Pptt.aslc | 184 +++++++++++++
.../ARM/SgiPkg/AcpiTables/Sgi575/Dsdt.asl | 99 +++----
.../ARM/SgiPkg/AcpiTables/Sgi575/Pptt.aslc | 172 ++++++++++++
21 files changed, 2156 insertions(+), 236 deletions(-)
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/RdE1Edge/Pptt.aslc
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/RdN1Edge/Pptt.aslc
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/RdN1EdgeX2/Dsdt.asl
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/RdN1EdgeX2/Pptt.aslc
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/RdN2/Pptt.aslc
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/RdV1/Pptt.aslc
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/RdV1Mc/Pptt.aslc
create mode 100644 Platform/ARM/SgiPkg/AcpiTables/Sgi575/Pptt.aslc


Re: [edk2-platforms][PATCH V3 08/14] Platform/Sgi: ACPI PPTT table for RD-E1-Edge platform

Sami Mujawar
 

Hi Pranav,

Please find my response inline marked [SAMI].

Regards,

Sami Mujawar


On 10/05/2021 09:06 PM, Pranav Madhu wrote:
The RD-E1-Edge platform includes two clusters with eight multi-thread
CPUs. Each of the CPUs include 32KB L1 Data cache, 32KB L1 Instruction
cache and 256KB L2 cache. Each cluster includes a 2MB L3 cache. The
platform also includes a system level cache of 8MB. Add PPTT table for
RD-E1-Edge platform with this information.

Signed-off-by: Pranav Madhu <pranav.madhu@arm.com>
---
Platform/ARM/SgiPkg/AcpiTables/RdE1EdgeAcpiTables.inf | 3 +-
Platform/ARM/SgiPkg/AcpiTables/RdE1Edge/Pptt.aslc | 252 ++++++++++++++++++++
2 files changed, 254 insertions(+), 1 deletion(-)

diff --git a/Platform/ARM/SgiPkg/AcpiTables/RdE1EdgeAcpiTables.inf b/Platform/ARM/SgiPkg/AcpiTables/RdE1EdgeAcpiTables.inf
index 2dd2275665a2..04ef2bfcaa26 100644
--- a/Platform/ARM/SgiPkg/AcpiTables/RdE1EdgeAcpiTables.inf
+++ b/Platform/ARM/SgiPkg/AcpiTables/RdE1EdgeAcpiTables.inf
@@ -1,7 +1,7 @@
## @file
# ACPI table data and ASL sources required to boot the platform.
#
-# Copyright (c) 2018-2020, ARM Ltd. All rights reserved.
+# Copyright (c) 2018-2021, ARM Ltd. All rights reserved.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -23,6 +23,7 @@
Mcfg.aslc
RdE1Edge/Dsdt.asl
RdE1Edge/Madt.aslc
+ RdE1Edge/Pptt.aslc
Spcr.aslc
Ssdt.asl

diff --git a/Platform/ARM/SgiPkg/AcpiTables/RdE1Edge/Pptt.aslc b/Platform/ARM/SgiPkg/AcpiTables/RdE1Edge/Pptt.aslc
new file mode 100644
index 000000000000..91baab73d108
--- /dev/null
+++ b/Platform/ARM/SgiPkg/AcpiTables/RdE1Edge/Pptt.aslc
@@ -0,0 +1,252 @@
+/** @file
+* Processor Properties Topology Table (PPTT) for RD-E1-Edge platform
+*
+* This file describes the topological structure of the processor block on the
+* RD-E1-Edge platform in the form as defined by ACPI PPTT table. The RD-E1-Edge
+* platform includes two clusters with eight dual-thread CPUS. Each of the CPUs
+* include 32KB L1 Data cache, 32KB L1 Instruction cache and 256KB L2 cache.
+* Each cluster includes a 2MB L3 cache. The platform also includes a system
+* level cache of 8MB.
+*
+* Copyright (c) 2021, ARM Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+* @par Specification Reference:
+* - ACPI 6.3, Chapter 5, Section 5.2.29, Processor Properties Topology Table
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/AcpiLib.h>
+#include <Library/ArmLib.h>
+#include <Library/PcdLib.h>
+
+#include "SgiPlatform.h"
+#include "SgiAcpiHeader.h"
+
+#define THREAD_PER_CORE_E1 2
+
+/*!
+ \brief Define helper macro for populating processor thread information.
+ \param PackageId Package instance number.
+ \param ClusterId Cluster instance number.
+ \param CpuId CPU instance number.
+ \param ThreadId CPU thread number.
+*/
+#define PPTT_THREAD_INIT(PackageId, ClusterId, CpuId, ThreadId) \
+ { \
+ EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR_INIT ( \
+ sizeof (RDE1EDGE_PPTT_THREAD), /* Length */ \
+ PPTT_PROCESSOR_THREAD_FLAGS, /* Flag */ \
+ OFFSET_OF (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE, \
+ Package.Cluster[ClusterId].Core[CpuId]), /* Parent */ \
+ ((PackageId << 5) | (ClusterId << 4) | (CpuId << 1) | ThreadId), \
+ /* ACPI Id */ \
+ 0 /* Num of private resource */ \
+ ) \
+ }
+
+/*!
+ \brief Define helper macro for populating processor core information.
+ \param PackageId Package instance number.
+ \param ClusterId Cluster instance number.
+ \param CpuId CPU instance number.
+*/
+#define PPTT_CORE_INIT(PackageId, ClusterId, CpuId) \
+ { \
+ /* Parameters for CPU Core */ \
+ EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR_INIT ( \
+ OFFSET_OF (RDE1EDGE_PPTT_CORE, DCache), /* Length */ \
+ PPTT_PROCESSOR_CORE_THREADED_FLAGS, /* Flag */ \
+ OFFSET_OF (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE, \
+ Package.Cluster[ClusterId]), /* Parent */ \
+ 0, /* ACPI Id */ \
+ 2 /* Num of private resource */ \
+ ), \
+ \
+ /* Offsets of the private resources */ \
+ { \
+ OFFSET_OF (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE, \
+ Package.Cluster[ClusterId].Core[CpuId].DCache), \
+ OFFSET_OF (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE, \
+ Package.Cluster[ClusterId].Core[CpuId].ICache) \
+ }, \
+ \
+ /* L1 data cache parameters */ \
+ EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE_INIT ( \
+ PPTT_CACHE_STRUCTURE_FLAGS, /* Flag */ \
+ OFFSET_OF (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE, \
+ Package.Cluster[ClusterId].Core[CpuId].L2Cache), \
+ /* Next level of cache */ \
+ SIZE_32KB, /* Size */ \
+ 128, /* Num of sets */ \
+ 4, /* Associativity */ \
+ PPTT_DATA_CACHE_ATTR, /* Attributes */ \
+ 64 /* Line size */ \
+ ), \
+ \
+ /* L1 instruction cache parameters */ \
+ EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE_INIT ( \
+ PPTT_CACHE_STRUCTURE_FLAGS, /* Flag */ \
+ OFFSET_OF (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE, \
+ Package.Cluster[ClusterId].Core[CpuId].L2Cache), \
+ /* Next level of cache */ \
+ SIZE_32KB, /* Size */ \
+ 128, /* Num of sets */ \
+ 4, /* Associativity */ \
+ PPTT_INST_CACHE_ATTR, /* Attributes */ \
+ 64 /* Line size */ \
+ ), \
+ \
+ /* L2 cache parameters */ \
+ EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE_INIT ( \
+ PPTT_CACHE_STRUCTURE_FLAGS, /* Flag */ \
+ 0, /* Next level of cache */ \
+ SIZE_256KB, /* Size */ \
+ 1024, /* Num of sets */ \
+ 4, /* Associativity */ \
+ PPTT_UNIFIED_CACHE_ATTR, /* Attributes */ \
+ 64 /* Line size */ \
+ ), \
+ \
+ /* Thread Initialization */ \
+ { \
+ PPTT_THREAD_INIT (PackageId, ClusterId, CpuId, 0), \
+ PPTT_THREAD_INIT (PackageId, ClusterId, CpuId, 1) \
+ } \
+ }
+
+/*!
+ \brief Define helper macro for populating processor container information.
+ \param PackageId Package instance number.
+ \param ClusterId Cluster instance number.
+*/
+#define PPTT_CLUSTER_INIT(PackageId, ClusterId) \
+ { \
+ /* Parameters for Cluster */ \
+ EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR_INIT ( \
+ OFFSET_OF (RDE1EDGE_PPTT_CLUSTER, L3Cache), /* Length */ \
+ PPTT_PROCESSOR_CLUSTER_THREADED_FLAGS, /* Flag */ \
[SAMI] I see that PPTT_PROCESSOR_CLUSTER_THREADED_FLAGS sets the ACPI ID
flag to invalid. Is there a reason for doing this?
Also, it looks like the DSDT for RD-E1-Edge platform does not have the
clusters definitions. Am I missing something here?
Can you take a look, please?
[/SAMI]
+ OFFSET_OF (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE, \
+ Package), /* Parent */ \
+ 0, /* ACPI Id */ \
+ 1 /* Num of private resource */ \
+ ), \
+ \
+ /* Offsets of the private resources */ \
+ OFFSET_OF (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE, \
+ Package.Cluster[ClusterId].L3Cache), \
+ \
+ /* L3 cache parameters */ \
+ EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE_INIT ( \
+ PPTT_CACHE_STRUCTURE_FLAGS, /* Flag */ \
+ 0, /* Next level of cache */ \
+ SIZE_2MB, /* Size */ \
+ 2048, /* Num of sets */ \
+ 16, /* Associativity */ \
+ PPTT_UNIFIED_CACHE_ATTR, /* Attributes */ \
+ 64 /* Line size */ \
+ ), \
+ \
+ /* Initialize child cores */ \
+ { \
+ PPTT_CORE_INIT (PackageId, ClusterId, 0), \
+ PPTT_CORE_INIT (PackageId, ClusterId, 1), \
+ PPTT_CORE_INIT (PackageId, ClusterId, 2), \
+ PPTT_CORE_INIT (PackageId, ClusterId, 3), \
+ PPTT_CORE_INIT (PackageId, ClusterId, 4), \
+ PPTT_CORE_INIT (PackageId, ClusterId, 5), \
+ PPTT_CORE_INIT (PackageId, ClusterId, 6), \
+ PPTT_CORE_INIT (PackageId, ClusterId, 7) \
+ } \
+ }
+
+/*!
+ \brief Define helper macro for populating SoC package information.
+ \param PackageId Package instance number.
+*/
+#define PPTT_PACKAGE_INIT(PackageId) \
+ { \
+ EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR_INIT ( \
+ OFFSET_OF (RDE1EDGE_PPTT_PACKAGE, Slc), \
+ PPTT_PROCESSOR_PACKAGE_FLAGS, \
+ 0, \
+ 0, \
+ 1 \
+ ), \
+ \
+ /* Offsets of the private resources */ \
+ OFFSET_OF (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE, \
+ Package.Slc), \
+ \
+ /* SLC parameters */ \
+ EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE_INIT ( \
+ PPTT_CACHE_STRUCTURE_FLAGS, /* Flag */ \
+ 0, /* Next level of cache */ \
+ SIZE_8MB, /* Size */ \
+ 8192, /* Num of sets */ \
+ 16, /* Associativity */ \
+ PPTT_UNIFIED_CACHE_ATTR, /* Attributes */ \
+ 64 /* Line size */ \
+ ), \
+ \
+ { \
+ PPTT_CLUSTER_INIT (PackageId, 0), \
+ PPTT_CLUSTER_INIT (PackageId, 1), \
+ } \
+ }
+
+#pragma pack(1)
+typedef struct {
+ EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR Thread;
+} RDE1EDGE_PPTT_THREAD;
+
+typedef struct {
+ EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR Core;
+ UINT32 Offset[2];
+ EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE DCache;
+ EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE ICache;
+ EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE L2Cache;
+ RDE1EDGE_PPTT_THREAD Thread[THREAD_PER_CORE_E1];
+} RDE1EDGE_PPTT_CORE;
+
+typedef struct {
+ EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR Cluster;
+ UINT32 Offset;
+ EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE L3Cache;
+ RDE1EDGE_PPTT_CORE Core[CORE_COUNT / THREAD_PER_CORE_E1];
+} RDE1EDGE_PPTT_CLUSTER;
+
+typedef struct {
+ EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR Package;
+ UINT32 Offset;
+ EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE Slc;
+ RDE1EDGE_PPTT_CLUSTER Cluster[CLUSTER_COUNT];
+} RDE1EDGE_PPTT_PACKAGE;
+
+/*
+ * Processor Properties Topology Table
+ */
+typedef struct {
+ EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER Header;
+ RDE1EDGE_PPTT_PACKAGE Package;
+} EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE;
+#pragma pack ()
+
+STATIC EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE Pptt = {
+ {
+ ARM_ACPI_HEADER (
+ EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_STRUCTURE_SIGNATURE,
+ EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE,
+ EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_REVISION
+ )
+ },
+
+ PPTT_PACKAGE_INIT (0)
+};
+
+/*
+ * Reference the table being generated to prevent the optimizer from removing
+ * the data structure from the executable
+ */
+VOID* CONST ReferenceAcpiTable = &Pptt;
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

5841 - 5860 of 80786