Date   

[edk2-platforms][PATCH v2 1/1] MinPlatformPkg/AcpiTables: Update structures for ACPI 6.3

Michael Kubacki
 

From: Daniel Maddy <danmad@microsoft.com>

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

Updates ACPI table structures in MinPlatformPkg for ACPI 6.3.

Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Daniel Maddy <danmad@microsoft.com>
Co-authored-by: Michael Kubacki <michael.kubacki@microsoft.com>
Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>
---
Platform/Intel/MinPlatformPkg/Acpi/AcpiTables/AcpiPlatform.c | 181 +++++=
+++++----------
Platform/Intel/MinPlatformPkg/Acpi/AcpiTables/Facs/Facs.c | 11 +-
Platform/Intel/MinPlatformPkg/Acpi/AcpiTables/Fadt/Fadt.c | 74 ++++-=
---
3 files changed, 138 insertions(+), 128 deletions(-)

diff --git a/Platform/Intel/MinPlatformPkg/Acpi/AcpiTables/AcpiPlatform.c=
b/Platform/Intel/MinPlatformPkg/Acpi/AcpiTables/AcpiPlatform.c
index 843ba832ce67..f5c4f2c3f1a9 100644
--- a/Platform/Intel/MinPlatformPkg/Acpi/AcpiTables/AcpiPlatform.c
+++ b/Platform/Intel/MinPlatformPkg/Acpi/AcpiTables/AcpiPlatform.c
@@ -2,6 +2,7 @@
ACPI Platform Driver
=20
Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
=20
**/
@@ -11,7 +12,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#pragma pack(1)
=20
typedef struct {
- UINT32 AcpiProcessorId;
+ UINT32 AcpiProcessorUid;
UINT32 ApicId;
UINT32 Flags;
UINT32 SocketNum;
@@ -25,9 +26,9 @@ typedef struct {
// Define Union of IO APIC & Local APIC structure;
//
typedef union {
- EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE AcpiLocalApic;
- EFI_ACPI_4_0_IO_APIC_STRUCTURE AcpiIoApic;
- EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE AcpiLocalx2Apic;
+ EFI_ACPI_6_3_PROCESSOR_LOCAL_APIC_STRUCTURE AcpiLocalApic;
+ EFI_ACPI_6_3_IO_APIC_STRUCTURE AcpiIoApic;
+ EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC_STRUCTURE AcpiLocalx2Apic;
struct {
UINT8 Type;
UINT8 Length;
@@ -36,9 +37,9 @@ typedef union {
=20
#pragma pack()
=20
-extern EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE Facs;
-extern EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt;
-extern EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER Hpet;
+extern EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE Facs;
+extern EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE Fadt;
+extern EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER Hpet;
extern EFI_ACPI_WSMT_TABLE Wsmt;
=20
VOID *mLocalTable[] =3D {
@@ -103,7 +104,7 @@ DebugDisplayReOrderTable (
for (Index =3D 0; Index < mNumberOfCpus; Index++) {
DEBUG ((DEBUG_INFO, " %02d 0x%02X 0x%02X %d %d=
%d\n",
Index,
- CpuApicIdOrderTable[Index].AcpiProcessorId,
+ CpuApicIdOrderTable[Index].AcpiProcessorUid,
CpuApicIdOrderTable[Index].ApicId,
CpuApicIdOrderTable[Index].Thread,
CpuApicIdOrderTable[Index].Flags,
@@ -118,31 +119,31 @@ AppendCpuMapTableEntry (
)
{
EFI_STATUS Status;
- EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApicPtr;
- EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE *LocalX2ApicPtr;
+ EFI_ACPI_6_3_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApicPtr;
+ EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC_STRUCTURE *LocalX2ApicPtr;
UINT8 Type;
=20
Status =3D EFI_SUCCESS;
Type =3D ((ACPI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiApicCommon.Type;
- LocalApicPtr =3D (EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE *)(&((AC=
PI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiLocalApic);
- LocalX2ApicPtr =3D (EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE *)(&=
((ACPI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiLocalx2Apic);
+ LocalApicPtr =3D (EFI_ACPI_6_3_PROCESSOR_LOCAL_APIC_STRUCTURE *)(&((AC=
PI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiLocalApic);
+ LocalX2ApicPtr =3D (EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC_STRUCTURE *)(&=
((ACPI_APIC_STRUCTURE_PTR *)ApicPtr)->AcpiLocalx2Apic);
=20
- if(Type =3D=3D EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC) {
+ if(Type =3D=3D EFI_ACPI_6_3_PROCESSOR_LOCAL_APIC) {
if(!mX2ApicEnabled) {
- LocalApicPtr->Flags =3D (UINT8)mCpuApicIdOrderTable[Loca=
lApicCounter].Flags;
- LocalApicPtr->ApicId =3D (UINT8)mCpuApicIdOrderTable[Loca=
lApicCounter].ApicId;
- LocalApicPtr->AcpiProcessorId =3D (UINT8)mCpuApicIdOrderTable[Loca=
lApicCounter].AcpiProcessorId;
+ LocalApicPtr->Flags =3D (UINT8)mCpuApicIdOrderTable[Loc=
alApicCounter].Flags;
+ LocalApicPtr->ApicId =3D (UINT8)mCpuApicIdOrderTable[Loc=
alApicCounter].ApicId;
+ LocalApicPtr->AcpiProcessorUid =3D (UINT8)mCpuApicIdOrderTable[Loc=
alApicCounter].AcpiProcessorUid;
} else {
- LocalApicPtr->Flags =3D 0;
- LocalApicPtr->ApicId =3D 0xFF;
- LocalApicPtr->AcpiProcessorId =3D (UINT8)0xFF;
+ LocalApicPtr->Flags =3D 0;
+ LocalApicPtr->ApicId =3D 0xFF;
+ LocalApicPtr->AcpiProcessorUid =3D (UINT8)0xFF;
Status =3D EFI_UNSUPPORTED;
}
- } else if(Type =3D=3D EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC) {
+ } else if(Type =3D=3D EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC) {
if(mX2ApicEnabled) {
LocalX2ApicPtr->Flags =3D (UINT8)mCpuApicIdOrderTable[L=
ocalApicCounter].Flags;
LocalX2ApicPtr->X2ApicId =3D mCpuApicIdOrderTable[LocalApi=
cCounter].ApicId;
- LocalX2ApicPtr->AcpiProcessorUid =3D mCpuApicIdOrderTable[LocalApi=
cCounter].AcpiProcessorId;
+ LocalX2ApicPtr->AcpiProcessorUid =3D mCpuApicIdOrderTable[LocalApi=
cCounter].AcpiProcessorUid;
} else {
LocalX2ApicPtr->Flags =3D 0;
LocalX2ApicPtr->X2ApicId =3D (UINT32)-1;
@@ -201,15 +202,15 @@ SortCpuLocalApicInTable (
//update processorbitMask
if (CpuIdMapPtr->Flags =3D=3D 1) {
if (mForceX2ApicId) {
- CpuIdMapPtr->SocketNum &=3D 0x7;
- CpuIdMapPtr->AcpiProcessorId &=3D 0xFF; //keep lower 8bit due =
to use Proc obj in dsdt
+ CpuIdMapPtr->SocketNum &=3D 0x7;
+ CpuIdMapPtr->AcpiProcessorUid &=3D 0xFF; //keep lower 8bit due=
to use Proc obj in dsdt
}
}
} else { //not enabled
- CpuIdMapPtr->ApicId =3D (UINT32)-1;
- CpuIdMapPtr->Thread =3D (UINT32)-1;
- CpuIdMapPtr->Flags =3D 0;
- CpuIdMapPtr->SocketNum =3D (UINT32)-1;
+ CpuIdMapPtr->ApicId =3D (UINT32)-1;
+ CpuIdMapPtr->Thread =3D (UINT32)-1;
+ CpuIdMapPtr->Flags =3D 0;
+ CpuIdMapPtr->SocketNum =3D (UINT32)-1;
} //end if PROC ENABLE
} //end for CurrentProcessor
=20
@@ -280,12 +281,12 @@ SortCpuLocalApicInTable (
}
=20
//
- // 5. Re-assigen AcpiProcessorId for AcpiProcessorUId uses purpose.
+ // 5. Re-assign AcpiProcessorId for AcpiProcessorUid uses purpose.
//
for (Socket =3D 0; Socket < FixedPcdGet32 (PcdMaxCpuSocketCount); Sock=
et++) {
for (CurrProcessor =3D 0, Index =3D 0; CurrProcessor < mNumberOfCpus=
; CurrProcessor++) {
if (mCpuApicIdOrderTable[CurrProcessor].Flags && (mCpuApicIdOrderT=
able[CurrProcessor].SocketNum =3D=3D Socket)) {
- mCpuApicIdOrderTable[CurrProcessor].AcpiProcessorId =3D (Process=
orInfoBuffer.Location.Package << mNumOfBitShift) + Index;
+ mCpuApicIdOrderTable[CurrProcessor].AcpiProcessorUid =3D (Proces=
sorInfoBuffer.Location.Package << mNumOfBitShift) + Index;
Index++;
}
}
@@ -312,17 +313,17 @@ typedef struct {
} STRUCTURE_HEADER;
=20
STRUCTURE_HEADER mMadtStructureTable[] =3D {
- {EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC, sizeof (EFI_ACPI_4_0_PROC=
ESSOR_LOCAL_APIC_STRUCTURE)},
- {EFI_ACPI_4_0_IO_APIC, sizeof (EFI_ACPI_4_0_IO_A=
PIC_STRUCTURE)},
- {EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE, sizeof (EFI_ACPI_4_0_INTE=
RRUPT_SOURCE_OVERRIDE_STRUCTURE)},
- {EFI_ACPI_4_0_NON_MASKABLE_INTERRUPT_SOURCE, sizeof (EFI_ACPI_4_0_NON_=
MASKABLE_INTERRUPT_SOURCE_STRUCTURE)},
- {EFI_ACPI_4_0_LOCAL_APIC_NMI, sizeof (EFI_ACPI_4_0_LOCA=
L_APIC_NMI_STRUCTURE)},
- {EFI_ACPI_4_0_LOCAL_APIC_ADDRESS_OVERRIDE, sizeof (EFI_ACPI_4_0_LOCA=
L_APIC_ADDRESS_OVERRIDE_STRUCTURE)},
- {EFI_ACPI_4_0_IO_SAPIC, sizeof (EFI_ACPI_4_0_IO_S=
APIC_STRUCTURE)},
- {EFI_ACPI_4_0_LOCAL_SAPIC, sizeof (EFI_ACPI_4_0_PROC=
ESSOR_LOCAL_SAPIC_STRUCTURE)},
- {EFI_ACPI_4_0_PLATFORM_INTERRUPT_SOURCES, sizeof (EFI_ACPI_4_0_PLAT=
FORM_INTERRUPT_SOURCES_STRUCTURE)},
- {EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC, sizeof (EFI_ACPI_4_0_PROC=
ESSOR_LOCAL_X2APIC_STRUCTURE)},
- {EFI_ACPI_4_0_LOCAL_X2APIC_NMI, sizeof (EFI_ACPI_4_0_LOCA=
L_X2APIC_NMI_STRUCTURE)}
+ {EFI_ACPI_6_3_PROCESSOR_LOCAL_APIC, sizeof (EFI_ACPI_6_3_PROC=
ESSOR_LOCAL_APIC_STRUCTURE)},
+ {EFI_ACPI_6_3_IO_APIC, sizeof (EFI_ACPI_6_3_IO_A=
PIC_STRUCTURE)},
+ {EFI_ACPI_6_3_INTERRUPT_SOURCE_OVERRIDE, sizeof (EFI_ACPI_6_3_INTE=
RRUPT_SOURCE_OVERRIDE_STRUCTURE)},
+ {EFI_ACPI_6_3_NON_MASKABLE_INTERRUPT_SOURCE, sizeof (EFI_ACPI_6_3_NON_=
MASKABLE_INTERRUPT_SOURCE_STRUCTURE)},
+ {EFI_ACPI_6_3_LOCAL_APIC_NMI, sizeof (EFI_ACPI_6_3_LOCA=
L_APIC_NMI_STRUCTURE)},
+ {EFI_ACPI_6_3_LOCAL_APIC_ADDRESS_OVERRIDE, sizeof (EFI_ACPI_6_3_LOCA=
L_APIC_ADDRESS_OVERRIDE_STRUCTURE)},
+ {EFI_ACPI_6_3_IO_SAPIC, sizeof (EFI_ACPI_6_3_IO_S=
APIC_STRUCTURE)},
+ {EFI_ACPI_6_3_LOCAL_SAPIC, sizeof (EFI_ACPI_6_3_PROC=
ESSOR_LOCAL_SAPIC_STRUCTURE)},
+ {EFI_ACPI_6_3_PLATFORM_INTERRUPT_SOURCES, sizeof (EFI_ACPI_6_3_PLAT=
FORM_INTERRUPT_SOURCES_STRUCTURE)},
+ {EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC, sizeof (EFI_ACPI_6_3_PROC=
ESSOR_LOCAL_X2APIC_STRUCTURE)},
+ {EFI_ACPI_6_3_LOCAL_X2APIC_NMI, sizeof (EFI_ACPI_6_3_LOCA=
L_X2APIC_NMI_STRUCTURE)}
};
=20
/**
@@ -481,7 +482,7 @@ InitializeHeader (
**/
EFI_STATUS
InitializeMadtHeader (
- IN OUT EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *MadtHeader
+ IN OUT EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *MadtHeader
)
{
EFI_STATUS Status;
@@ -493,8 +494,8 @@ InitializeMadtHeader (
=20
Status =3D InitializeHeader (
&MadtHeader->Header,
- EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
- EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
+ EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE,
+ EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
0
);
if (EFI_ERROR (Status)) {
@@ -502,7 +503,7 @@ InitializeMadtHeader (
}
=20
MadtHeader->LocalApicAddress =3D PcdGet32(PcdLocalApicAddress);
- MadtHeader->Flags =3D EFI_ACPI_4_0_PCAT_COMPAT;
+ MadtHeader->Flags =3D EFI_ACPI_6_3_PCAT_COMPAT;
=20
return EFI_SUCCESS;
}
@@ -539,7 +540,7 @@ CopyStructure (
//
// Initialize the number of table entries and the table based on the t=
able header passed in.
//
- if (Header->Signature =3D=3D EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TA=
BLE_SIGNATURE) {
+ if (Header->Signature =3D=3D EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TA=
BLE_SIGNATURE) {
TableNumEntries =3D sizeof (mMadtStructureTable) / sizeof (STRUCTURE=
_HEADER);
StructureTable =3D mMadtStructureTable;
} else {
@@ -649,7 +650,7 @@ BuildAcpiTable (
return EFI_INVALID_PARAMETER;
}
=20
- if (AcpiHeader->Signature !=3D EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_=
TABLE_SIGNATURE) {
+ if (AcpiHeader->Signature !=3D EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_=
TABLE_SIGNATURE) {
DEBUG ((
DEBUG_ERROR,
"MADT header signature is expected, actually 0x%08x\n",
@@ -740,15 +741,15 @@ InstallMadtFromScratch (
{
EFI_STATUS Status;
UINTN Index;
- EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *NewMadtTable;
+ EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *NewMadtTable;
UINTN TableHandle;
- EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER MadtTableHeader;
- EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE ProcLocalApicStruc=
t;
- EFI_ACPI_4_0_IO_APIC_STRUCTURE IoApicStruct;
- EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE IntSrcOverrideStru=
ct;
- EFI_ACPI_4_0_LOCAL_APIC_NMI_STRUCTURE LocalApciNmiStruct=
;
- EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE ProcLocalX2ApicStr=
uct;
- EFI_ACPI_4_0_LOCAL_X2APIC_NMI_STRUCTURE LocalX2ApicNmiStru=
ct;
+ EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER MadtTableHeader;
+ EFI_ACPI_6_3_PROCESSOR_LOCAL_APIC_STRUCTURE ProcLocalApicStruc=
t;
+ EFI_ACPI_6_3_IO_APIC_STRUCTURE IoApicStruct;
+ EFI_ACPI_6_3_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE IntSrcOverrideStru=
ct;
+ EFI_ACPI_6_3_LOCAL_APIC_NMI_STRUCTURE LocalApciNmiStruct=
;
+ EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC_STRUCTURE ProcLocalX2ApicStr=
uct;
+ EFI_ACPI_6_3_LOCAL_X2APIC_NMI_STRUCTURE LocalX2ApicNmiStru=
ct;
STRUCTURE_HEADER **MadtStructs;
UINTN MaxMadtStructCount=
;
UINTN MadtStructsIndex;
@@ -809,11 +810,11 @@ InstallMadtFromScratch (
//
// Build Processor Local APIC Structures and Processor Local X2APIC St=
ructures
//
- ProcLocalApicStruct.Type =3D EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC;
- ProcLocalApicStruct.Length =3D sizeof (EFI_ACPI_4_0_PROCESSOR_LOCAL_AP=
IC_STRUCTURE);
+ ProcLocalApicStruct.Type =3D EFI_ACPI_6_3_PROCESSOR_LOCAL_APIC;
+ ProcLocalApicStruct.Length =3D sizeof (EFI_ACPI_6_3_PROCESSOR_LOCAL_AP=
IC_STRUCTURE);
=20
- ProcLocalX2ApicStruct.Type =3D EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC;
- ProcLocalX2ApicStruct.Length =3D sizeof (EFI_ACPI_4_0_PROCESSOR_LOCAL_=
X2APIC_STRUCTURE);
+ ProcLocalX2ApicStruct.Type =3D EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC;
+ ProcLocalX2ApicStruct.Length =3D sizeof (EFI_ACPI_6_3_PROCESSOR_LOCAL_=
X2APIC_STRUCTURE);
ProcLocalX2ApicStruct.Reserved[0] =3D 0;
ProcLocalX2ApicStruct.Reserved[1] =3D 0;
=20
@@ -824,9 +825,9 @@ InstallMadtFromScratch (
// use a processor local x2APIC structure.
//
if (!mX2ApicEnabled && mCpuApicIdOrderTable[Index].ApicId < MAX_UINT=
8) {
- ProcLocalApicStruct.Flags =3D (UINT8) mCpuApicIdOrderTab=
le[Index].Flags;
- ProcLocalApicStruct.ApicId =3D (UINT8) mCpuApicIdOrderTab=
le[Index].ApicId;
- ProcLocalApicStruct.AcpiProcessorId =3D (UINT8) mCpuApicIdOrderTab=
le[Index].AcpiProcessorId;
+ ProcLocalApicStruct.Flags =3D (UINT8) mCpuApicIdOrderTa=
ble[Index].Flags;
+ ProcLocalApicStruct.ApicId =3D (UINT8) mCpuApicIdOrderTa=
ble[Index].ApicId;
+ ProcLocalApicStruct.AcpiProcessorUid =3D (UINT8) mCpuApicIdOrderTa=
ble[Index].AcpiProcessorUid;
=20
ASSERT (MadtStructsIndex < MaxMadtStructCount);
Status =3D CopyStructure (
@@ -837,7 +838,7 @@ InstallMadtFromScratch (
} else if (mCpuApicIdOrderTable[Index].ApicId !=3D 0xFFFFFFFF) {
ProcLocalX2ApicStruct.Flags =3D (UINT8) mCpuApicIdOrder=
Table[Index].Flags;
ProcLocalX2ApicStruct.X2ApicId =3D mCpuApicIdOrderTable[In=
dex].ApicId;
- ProcLocalX2ApicStruct.AcpiProcessorUid =3D mCpuApicIdOrderTable[In=
dex].AcpiProcessorId;
+ ProcLocalX2ApicStruct.AcpiProcessorUid =3D mCpuApicIdOrderTable[In=
dex].AcpiProcessorUid;
=20
ASSERT (MadtStructsIndex < MaxMadtStructCount);
Status =3D CopyStructure (
@@ -855,8 +856,8 @@ InstallMadtFromScratch (
//
// Build I/O APIC Structures
//
- IoApicStruct.Type =3D EFI_ACPI_4_0_IO_APIC;
- IoApicStruct.Length =3D sizeof (EFI_ACPI_4_0_IO_APIC_STRUCTURE);
+ IoApicStruct.Type =3D EFI_ACPI_6_3_IO_APIC;
+ IoApicStruct.Length =3D sizeof (EFI_ACPI_6_3_IO_APIC_STRUCTURE);
IoApicStruct.Reserved =3D 0;
=20
PcIoApicEnable =3D PcdGet32 (PcdPcIoApicEnable);
@@ -902,8 +903,8 @@ InstallMadtFromScratch (
//
// Build Interrupt Source Override Structures
//
- IntSrcOverrideStruct.Type =3D EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE;
- IntSrcOverrideStruct.Length =3D sizeof (EFI_ACPI_4_0_INTERRUPT_SOURCE_=
OVERRIDE_STRUCTURE);
+ IntSrcOverrideStruct.Type =3D EFI_ACPI_6_3_INTERRUPT_SOURCE_OVERRIDE;
+ IntSrcOverrideStruct.Length =3D sizeof (EFI_ACPI_6_3_INTERRUPT_SOURCE_=
OVERRIDE_STRUCTURE);
=20
//
// IRQ0=3D>IRQ2 Interrupt Source Override Structure
@@ -946,11 +947,11 @@ InstallMadtFromScratch (
//
// Build Local APIC NMI Structures
//
- LocalApciNmiStruct.Type =3D EFI_ACPI_4_0_LOCAL_APIC_NMI;
- LocalApciNmiStruct.Length =3D sizeof (EFI_ACPI_4_0_LOCAL_APIC_NMI_STRU=
CTURE);
- LocalApciNmiStruct.AcpiProcessorId =3D 0xFF; // Applies to all pr=
ocessors
- LocalApciNmiStruct.Flags =3D 0x0005; // Flags - Edge-tigg=
ered, Active High
- LocalApciNmiStruct.LocalApicLint =3D 0x1;
+ LocalApciNmiStruct.Type =3D EFI_ACPI_6_3_LOCAL_APIC_NMI;
+ LocalApciNmiStruct.Length =3D sizeof (EFI_ACPI_6_3_LOCAL_APIC_NMI_STRU=
CTURE);
+ LocalApciNmiStruct.AcpiProcessorUid =3D 0xFF; // Applies to all p=
rocessors
+ LocalApciNmiStruct.Flags =3D 0x0005; // Flags - Edge-tig=
gered, Active High
+ LocalApciNmiStruct.LocalApicLint =3D 0x1;
=20
ASSERT (MadtStructsIndex < MaxMadtStructCount);
Status =3D CopyStructure (
@@ -967,8 +968,8 @@ InstallMadtFromScratch (
// Build Local x2APIC NMI Structure
//
if (mX2ApicEnabled) {
- LocalX2ApicNmiStruct.Type =3D EFI_ACPI_4_0_LOCAL_X2APIC_NMI;
- LocalX2ApicNmiStruct.Length =3D sizeof (EFI_ACPI_4_0_LOCAL_X2APIC_NM=
I_STRUCTURE);
+ LocalX2ApicNmiStruct.Type =3D EFI_ACPI_6_3_LOCAL_X2APIC_NMI;
+ LocalX2ApicNmiStruct.Length =3D sizeof (EFI_ACPI_6_3_LOCAL_X2APIC_NM=
I_STRUCTURE);
LocalX2ApicNmiStruct.Flags =3D 0x000D; // Flags - Le=
vel-tiggered, Active High
LocalX2ApicNmiStruct.AcpiProcessorUid =3D 0xFFFFFFFF; // Applies to=
all processors
LocalX2ApicNmiStruct.LocalX2ApicLint =3D 0x01;
@@ -992,12 +993,12 @@ InstallMadtFromScratch (
// Build Madt Structure from the Madt Header and collection of pointer=
s in MadtStructs[]
//
Status =3D BuildAcpiTable (
- (EFI_ACPI_DESCRIPTION_HEADER *) &MadtTableHeader,
- sizeof (EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER=
),
- MadtStructs,
- MadtStructsIndex,
- (UINT8 **) &NewMadtTable
- );
+ (EFI_ACPI_DESCRIPTION_HEADER *) &MadtTableHeader,
+ sizeof (EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER)=
,
+ MadtStructs,
+ MadtStructsIndex,
+ (UINT8 **)&NewMadtTable
+ );
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "BuildAcpiTable failed: %r\n", Status));
goto Done;
@@ -1087,7 +1088,7 @@ InstallMcfgFromScratch (
}
=20
//
- // Publish Madt Structure to ACPI
+ // Publish Mcfg Structure to ACPI
//
Status =3D mAcpiTable->InstallAcpiTable (
mAcpiTable,
@@ -1120,7 +1121,7 @@ PlatformUpdateTables (
EFI_ACPI_DESCRIPTION_HEADER *TableHeader;
UINT8 *TempOemId;
UINT64 TempOemTableId;
- EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader;
+ EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader;
EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *HpetTable;
UINT32 HpetBaseAddress;
EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_BLOCK_ID HpetBlockId;
@@ -1177,12 +1178,12 @@ PlatformUpdateTables (
//
switch (Table->Signature) {
=20
- case EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
- ASSERT (FALSE);
+ case EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
+ ASSERT(FALSE);
break;
=20
- case EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
- FadtHeader =3D (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *) Tabl=
e;
+ case EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
+ FadtHeader =3D (EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE *) Table;
=20
FadtHeader->PreferredPmProfile =3D PcdGet8 (PcdFadtPreferredPmProfil=
e);
FadtHeader->IaPcBootArch =3D PcdGet16 (PcdFadtIaPcBootArch);
@@ -1228,7 +1229,7 @@ PlatformUpdateTables (
DEBUG ((DEBUG_INFO, " Flags 0x%x\n", FadtHeader->Flags));
break;
=20
- case EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE:
+ case EFI_ACPI_6_3_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE:
HpetTable =3D (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *)Ta=
ble;
HpetBaseAddress =3D PcdGet32 (PcdHpetBaseAddress);
HpetTable->BaseAddressLower32Bit.Address =3D HpetBaseAddress;
@@ -1280,8 +1281,8 @@ IsHardwareChange (
UINTN HWChangeSize;
UINT32 PciId;
UINTN Handle;
- EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *FacsPtr;
- EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *pFADT;
+ EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE *FacsPtr;
+ EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE *pFADT;
=20
HandleCount =3D 0;
HandleBuffer =3D NULL;
@@ -1327,7 +1328,7 @@ IsHardwareChange (
//
Handle =3D 0;
Status =3D LocateAcpiTableBySignature (
- EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+ EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
(EFI_ACPI_DESCRIPTION_HEADER **) &pFADT,
&Handle
);
@@ -1349,7 +1350,7 @@ IsHardwareChange (
//
// Set HardwareSignature value based on CRC value.
//
- FacsPtr =3D (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)pFA=
DT->FirmwareCtrl;
+ FacsPtr =3D (EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)pFA=
DT->FirmwareCtrl;
FacsPtr->HardwareSignature =3D CRC;
FreePool (HWChange);
}
diff --git a/Platform/Intel/MinPlatformPkg/Acpi/AcpiTables/Facs/Facs.c b/=
Platform/Intel/MinPlatformPkg/Acpi/AcpiTables/Facs/Facs.c
index cde6e478c6b9..8700c44e633d 100644
--- a/Platform/Intel/MinPlatformPkg/Acpi/AcpiTables/Facs/Facs.c
+++ b/Platform/Intel/MinPlatformPkg/Acpi/AcpiTables/Facs/Facs.c
@@ -1,9 +1,10 @@
/** @file
- This file contains a structure definition for the ACPI 5.0 Firmware AC=
PI
+ This file contains a structure definition for the ACPI 6.3 Firmware AC=
PI
Control Structure (FACS). The contents of this file should only be mo=
dified
for bug fixes, no porting is required.
=20
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
=20
**/
@@ -35,9 +36,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
// Please modify all values in Facs.h only.
//
=20
-EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE Facs =3D {
- EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE,
- sizeof (EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE),
+EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE Facs =3D {
+ EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE,
+ sizeof (EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE),
=20
//
// Hardware Signature will be updated at runtime
@@ -48,7 +49,7 @@ EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE Facs =3D {
EFI_ACPI_GLOBAL_LOCK,
EFI_ACPI_FIRMWARE_CONTROL_STRUCTURE_FLAGS,
EFI_ACPI_X_FIRMWARE_WAKING_VECTOR,
- EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION,
+ EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION,
{
EFI_ACPI_RESERVED_BYTE,
EFI_ACPI_RESERVED_BYTE,
diff --git a/Platform/Intel/MinPlatformPkg/Acpi/AcpiTables/Fadt/Fadt.c b/=
Platform/Intel/MinPlatformPkg/Acpi/AcpiTables/Fadt/Fadt.c
index 6efb38cda40d..3418e960972f 100644
--- a/Platform/Intel/MinPlatformPkg/Acpi/AcpiTables/Fadt/Fadt.c
+++ b/Platform/Intel/MinPlatformPkg/Acpi/AcpiTables/Fadt/Fadt.c
@@ -1,9 +1,10 @@
/** @file
- This file contains a structure definition for the ACPI 5.0 Fixed ACPI
+ This file contains a structure definition for the ACPI 6.3 Fixed ACPI
Description Table (FADT). The contents of this file should only be mo=
dified
for bug fixes, no porting is required.
=20
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
=20
**/
@@ -44,9 +45,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
//
// IA-PC Boot Architecture Flags
//
-
#define EFI_ACPI_IAPC_BOOT_ARCH 0 // To be fixed
=20
+//
+// ARM Boot Architecture Flags
+//
+#define EFI_ACPI_ARM_BOOT_ARCH 0 // To be fixed
+
//
// Fixed Feature Flags
//
@@ -55,7 +60,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
//
// PM1A Event Register Block Generic Address Information
//
-#define EFI_ACPI_PM1A_EVT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM1A_EVT_BLK_ADDRESS_SPACE_ID EFI_ACPI_6_3_SYSTEM_IO
#define EFI_ACPI_PM1A_EVT_BLK_BIT_WIDTH 0x20
#define EFI_ACPI_PM1A_EVT_BLK_BIT_OFFSET 0x00
#define EFI_ACPI_PM1A_EVT_BLK_ADDRESS 0 // To be fixed
@@ -63,7 +68,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
//
// PM1B Event Register Block Generic Address Information
//
-#define EFI_ACPI_PM1B_EVT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM1B_EVT_BLK_ADDRESS_SPACE_ID EFI_ACPI_6_3_SYSTEM_IO
#define EFI_ACPI_PM1B_EVT_BLK_BIT_WIDTH 0x00
#define EFI_ACPI_PM1B_EVT_BLK_BIT_OFFSET 0x00
#define EFI_ACPI_PM1B_EVT_BLK_ADDRESS 0 // To be fixed
@@ -71,7 +76,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
//
// PM1A Control Register Block Generic Address Information
//
-#define EFI_ACPI_PM1A_CNT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM1A_CNT_BLK_ADDRESS_SPACE_ID EFI_ACPI_6_3_SYSTEM_IO
#define EFI_ACPI_PM1A_CNT_BLK_BIT_WIDTH 0x10
#define EFI_ACPI_PM1A_CNT_BLK_BIT_OFFSET 0x00
#define EFI_ACPI_PM1A_CNT_BLK_ADDRESS 0 // To be fixed
@@ -79,7 +84,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
//
// PM1B Control Register Block Generic Address Information
//
-#define EFI_ACPI_PM1B_CNT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM1B_CNT_BLK_ADDRESS_SPACE_ID EFI_ACPI_6_3_SYSTEM_IO
#define EFI_ACPI_PM1B_CNT_BLK_BIT_WIDTH 0x00
#define EFI_ACPI_PM1B_CNT_BLK_BIT_OFFSET 0x00
#define EFI_ACPI_PM1B_CNT_BLK_ADDRESS 0 // To be fixed
@@ -87,7 +92,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
//
// PM2 Control Register Block Generic Address Information
//
-#define EFI_ACPI_PM2_CNT_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM2_CNT_BLK_ADDRESS_SPACE_ID EFI_ACPI_6_3_SYSTEM_IO
#define EFI_ACPI_PM2_CNT_BLK_BIT_WIDTH 0x08
#define EFI_ACPI_PM2_CNT_BLK_BIT_OFFSET 0x00
#define EFI_ACPI_PM2_CNT_BLK_ADDRESS 0 // To be fixed
@@ -96,7 +101,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
// Power Management Timer Control Register Block Generic Address
// Information
//
-#define EFI_ACPI_PM_TMR_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_PM_TMR_BLK_ADDRESS_SPACE_ID EFI_ACPI_6_3_SYSTEM_IO
#define EFI_ACPI_PM_TMR_BLK_BIT_WIDTH 0x20
#define EFI_ACPI_PM_TMR_BLK_BIT_OFFSET 0x00
#define EFI_ACPI_PM_TMR_BLK_ADDRESS 0 // To be fixed
@@ -105,7 +110,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
// General Purpose Event 0 Register Block Generic Address
// Information
//
-#define EFI_ACPI_GPE0_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_GPE0_BLK_ADDRESS_SPACE_ID EFI_ACPI_6_3_SYSTEM_IO
#define EFI_ACPI_GPE0_BLK_BIT_WIDTH 0 // size of R_PCH_ACPI_GPE=
0_STS_127_96 + R_PCH_ACPI_GPE0_EN_127_96
#define EFI_ACPI_GPE0_BLK_BIT_OFFSET 0x00
#define EFI_ACPI_GPE0_BLK_ADDRESS 0 // To be fixed
@@ -114,14 +119,14 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
// General Purpose Event 1 Register Block Generic Address
// Information
//
-#define EFI_ACPI_GPE1_BLK_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_GPE1_BLK_ADDRESS_SPACE_ID EFI_ACPI_6_3_SYSTEM_IO
#define EFI_ACPI_GPE1_BLK_BIT_WIDTH 0x0
#define EFI_ACPI_GPE1_BLK_BIT_OFFSET 0x0
#define EFI_ACPI_GPE1_BLK_ADDRESS 0 // To be fixed
//
// Reset Register Generic Address Information
//
-#define EFI_ACPI_RESET_REG_ADDRESS_SPACE_ID EFI_ACPI_2_0_SYSTEM_IO
+#define EFI_ACPI_RESET_REG_ADDRESS_SPACE_ID EFI_ACPI_6_3_SYSTEM_IO
#define EFI_ACPI_RESET_REG_BIT_WIDTH 0x08
#define EFI_ACPI_RESET_REG_BIT_OFFSET 0x00
#define EFI_ACPI_RESET_REG_ADDRESS 0x00000CF9
@@ -162,11 +167,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
// Please modify all values in Fadt.h only.
//
=20
-EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt =3D {
+EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE Fadt =3D {
{
- EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
- sizeof (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE),
- EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
+ EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+ sizeof (EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE),
+ EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
=20
//
// Checksum will be updated at runtime
@@ -187,9 +192,9 @@ EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt =3D {
//
// These addresses will be updated at runtime
//
- 0x00000000,=20
0x00000000,
- =20
+ 0x00000000,
+
EFI_ACPI_RESERVED_BYTE,
EFI_ACPI_PREFERRED_PM_PROFILE,
EFI_ACPI_SCI_INT,
@@ -198,7 +203,7 @@ EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt =3D {
EFI_ACPI_ACPI_DISABLE,
EFI_ACPI_S4_BIOS_REQ,
EFI_ACPI_PSTATE_CNT,
- =20
+
EFI_ACPI_PM1A_EVT_BLK_ADDRESS,
EFI_ACPI_PM1B_EVT_BLK_ADDRESS,
EFI_ACPI_PM1A_CNT_BLK_ADDRESS,
@@ -240,15 +245,13 @@ EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt =3D =
{
EFI_ACPI_RESET_REG_ADDRESS_SPACE_ID,
EFI_ACPI_RESET_REG_BIT_WIDTH,
EFI_ACPI_RESET_REG_BIT_OFFSET,
- EFI_ACPI_5_0_BYTE,
+ EFI_ACPI_6_3_BYTE,
EFI_ACPI_RESET_REG_ADDRESS
},
EFI_ACPI_RESET_VALUE,
- {
- EFI_ACPI_RESERVED_BYTE,
- EFI_ACPI_RESERVED_BYTE,
- EFI_ACPI_RESERVED_BYTE
- },
+
+ EFI_ACPI_ARM_BOOT_ARCH,
+ EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION,
=20
//
// These addresses will be updated at runtime
@@ -263,7 +266,7 @@ EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt =3D {
EFI_ACPI_PM1A_EVT_BLK_ADDRESS_SPACE_ID,
EFI_ACPI_PM1A_EVT_BLK_BIT_WIDTH,
EFI_ACPI_PM1A_EVT_BLK_BIT_OFFSET,
- EFI_ACPI_5_0_WORD,
+ EFI_ACPI_6_3_WORD,
EFI_ACPI_PM1A_EVT_BLK_ADDRESS
},
{
@@ -273,7 +276,7 @@ EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt =3D {
EFI_ACPI_PM1B_EVT_BLK_ADDRESS_SPACE_ID,
EFI_ACPI_PM1B_EVT_BLK_BIT_WIDTH,
EFI_ACPI_PM1B_EVT_BLK_BIT_OFFSET,
- EFI_ACPI_5_0_WORD,
+ EFI_ACPI_6_3_WORD,
EFI_ACPI_PM1B_EVT_BLK_ADDRESS
},
{
@@ -283,7 +286,7 @@ EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt =3D {
EFI_ACPI_PM1A_CNT_BLK_ADDRESS_SPACE_ID,
EFI_ACPI_PM1A_CNT_BLK_BIT_WIDTH,
EFI_ACPI_PM1A_CNT_BLK_BIT_OFFSET,
- EFI_ACPI_5_0_WORD,
+ EFI_ACPI_6_3_WORD,
EFI_ACPI_PM1A_CNT_BLK_ADDRESS
},
{
@@ -293,7 +296,7 @@ EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt =3D {
EFI_ACPI_PM1B_CNT_BLK_ADDRESS_SPACE_ID,
EFI_ACPI_PM1B_CNT_BLK_BIT_WIDTH,
EFI_ACPI_PM1B_CNT_BLK_BIT_OFFSET,
- EFI_ACPI_5_0_WORD,
+ EFI_ACPI_6_3_WORD,
EFI_ACPI_PM1B_CNT_BLK_ADDRESS
},
{
@@ -303,7 +306,7 @@ EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt =3D {
EFI_ACPI_PM2_CNT_BLK_ADDRESS_SPACE_ID,
EFI_ACPI_PM2_CNT_BLK_BIT_WIDTH,
EFI_ACPI_PM2_CNT_BLK_BIT_OFFSET,
- EFI_ACPI_5_0_BYTE,
+ EFI_ACPI_6_3_BYTE,
EFI_ACPI_PM2_CNT_BLK_ADDRESS
},
{
@@ -313,7 +316,7 @@ EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt =3D {
EFI_ACPI_PM_TMR_BLK_ADDRESS_SPACE_ID,
EFI_ACPI_PM_TMR_BLK_BIT_WIDTH,
EFI_ACPI_PM_TMR_BLK_BIT_OFFSET,
- EFI_ACPI_5_0_DWORD,
+ EFI_ACPI_6_3_DWORD,
EFI_ACPI_PM_TMR_BLK_ADDRESS
},
{
@@ -323,7 +326,7 @@ EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt =3D {
EFI_ACPI_GPE0_BLK_ADDRESS_SPACE_ID,
EFI_ACPI_GPE0_BLK_BIT_WIDTH,
EFI_ACPI_GPE0_BLK_BIT_OFFSET,
- EFI_ACPI_5_0_BYTE,
+ EFI_ACPI_6_3_BYTE,
EFI_ACPI_GPE0_BLK_ADDRESS
},
{
@@ -333,7 +336,7 @@ EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt =3D {
EFI_ACPI_GPE1_BLK_ADDRESS_SPACE_ID,
EFI_ACPI_GPE1_BLK_BIT_WIDTH,
EFI_ACPI_GPE1_BLK_BIT_OFFSET,
- EFI_ACPI_5_0_BYTE,
+ EFI_ACPI_6_3_BYTE,
EFI_ACPI_GPE1_BLK_ADDRESS
},
{
@@ -355,5 +358,10 @@ EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE Fadt =3D {
0,
0,
0
- }
+ },
+
+ //
+ // Hypervisor Vendor Identity
+ //
+ 0x0000000000000000,
};
--=20
2.28.0.windows.1


Re: [PATCH V7 1/1] OvmfPkg: Enable TDX in ResetVector

Yao, Jiewen
 

Comment below

-----Original Message-----
From: kraxel@redhat.com <kraxel@redhat.com>
Sent: Friday, September 24, 2021 10:02 PM
To: Yao, Jiewen <jiewen.yao@intel.com>
Cc: devel@edk2.groups.io; Xu, Min M <min.m.xu@intel.com>; Brijesh Singh
<brijesh.singh@amd.com>; Ard Biesheuvel <ardb+tianocore@kernel.org>;
Justen, Jordan L <jordan.l.justen@intel.com>; Erdem Aktas
<erdemaktas@google.com>; James Bottomley <jejb@linux.ibm.com>; Tom
Lendacky <thomas.lendacky@amd.com>
Subject: Re: [edk2-devel] [PATCH V7 1/1] OvmfPkg: Enable TDX in ResetVector

On Fri, Sep 24, 2021 at 10:33:35AM +0000, Yao, Jiewen wrote:
Again. Two topics. We need discuss them separately.

Topic 1: TD metadata table is an architecture way to communicate with
VMM. We took the design from PE/COFF image section, which is flexible
to support different binary format.
EDKII TDVF is just one possible producer. There could be other
producer in the future. We don't want to define something only meet
current TDVF need.
Hmm. efi has a kind-of binary format (EFI_FIRMWARE_VOLUME_HEADER).
It's not fully self-contained though, you need to know where the
architecture places the firmware (i.e. just below 4G for x86)
because the load address isn't there. So I do see the point of
adding other headers adding that.

Possible alternative approach: Define an extension
(EFI_FIRMWARE_VOLUME_EXT_HEADER) for the load address and use that
instead of defining something new.
[Jiewen] I would say it is terrible idea to use EFI_FIRMWARE_VOLUME_HEADER.

This is defined by PI specification, the purpose is to have a way to manage the firmware file.
It is very complicated and with overhead only needed for flash.

Intel has multiple technologies requires firmware/hardware interface. None of them uses EFI_FIRMARE_VOLUME_HEADER, because it is unnecessary to carry the complexity.

The most famous firmware/hardware interface is called Firmware Interface Table (FIT) table. - https://software.intel.com/content/dam/develop/external/us/en/documents/firmware-interface-table-bios-specification-r1p2p1.pdf.

Also using EFI_FIRMWARE_VOLUME_HEADER means you have to use PI FV layout, which is another unnecessary limitation.

I would strongly disagree to using EFI_FIRMWARE_VOLUME_HEADER for metadata table.

Still not clear why the size is in there twice. I think you could
instead use a flag telling whenever a section must be loaded from
the image or not. This is what COFF and ELF are doing too.

Also not clear why you want stick to 64bit base address. Loading the
firmware above 4G isn't going to work without also changing a bunch of
other things and it will break backward compatibility anyway.
[Jiewen] That is our previously experience, when we define a physical address, we always use 64bit to leave room for extension.
Like UEFI specification defines PHYSICAL_ADDRESS to be UINT64 even in IA32 platform.

Let me tell you a story.
In https://github.com/tianocore/edk2/blob/master/SecurityPkg/Include/Ppi/FirmwareVolumeInfoPrehashedFV.h, we defined the physical address to be FvBase.
UINT32 FvBase;
UINT32 FvLength;

It is rare, because in other context, we usually define FvBase to be 64bit.

Later, when we want to enable a host app based unit test for this data structure, we got test crash directly, because the OS app test allocates an above 4G base address, and the test case cast it to UINT32.

Do we really care to save 4 bytes in the PPI definition? I don't think so.
But it just defines in this way and it brings a big burden to enable unit test.
This code has been checked in for 2 years. Till now, I still regret that why we didn't use UINT64 in the beginning.

I have seen other examples to define small size, such as PI Section Size (24 bit), FFS Size (24 bit), HOB size (16 bit). Then we run into problem to support large structure later and we have to figure out ugly work-around to support those cases.

Defining UINT64 gives us enough flexibility for the future, including test in above 4G environment.
I am wondering that, do you really care to save 4 bytes from UINT64 to UINT32 ?

For type, maybe 2^16 is enough. But for flags, I prefer 32bit.


I think the entry size can be cut in half with something like this:

struct {
uint32_t file_offset;
uint32_t load_address;
uint32_t section_size;
uint16_t section_type;
uint16_t section_flags;
};

Topic 2: In config-B we remove PEI.
I think we should say it in different way: We add PEI back in config-A.
In our original design we totally eliminated PEI, because it is unnecessary.
IMHO, it is totally an overdesign in OVMF to include PEI.

Granted. PEI basically allows OEMs to plug their binary PEIMs into
early hardware initialization. For a full open source firmware there
is little reason to support that, other than maybe using PEIMs from
other edk2 Pkgs unmodified.

But, again, I don't want have two completely different initialization
code paths in OVMF. We can certainly investigate and discuss dropping
PEI, but that clearly shouldn't be a TDX-only thing. When we eliminate
PEI, we should do it for all OVMF builds.
[Jiewen] I think this is out of scope of TDVF config-B patch series.
I don't think it is fair to enable OVMF to remove PEI, just because TDVF does not need PEI.

If you look around other edk2 platform projects, you can already find some of them does not have PEI. And EmbeddedPkg includes some libs to support those case, such as https://github.com/tianocore/edk2/tree/master/EmbeddedPkg/Library/PrePiHobLib, https://github.com/tianocore/edk2/tree/master/EmbeddedPkg/Library/PrePiLib.
But that does not mean, we need do that for every platform.

Each platform owner can have their own choice.

If you have intertest to remove PEI, I am happy to discuss with you on detail.
However, I would treat "removing PEI from OVMF" and "enable TDVF config-B" be two different tasks.



take care,
Gerd


Re: [PATCH V7 1/1] OvmfPkg: Enable TDX in ResetVector

Gerd Hoffmann
 

On Fri, Sep 24, 2021 at 10:33:35AM +0000, Yao, Jiewen wrote:
Again. Two topics. We need discuss them separately.

Topic 1: TD metadata table is an architecture way to communicate with
VMM. We took the design from PE/COFF image section, which is flexible
to support different binary format.
EDKII TDVF is just one possible producer. There could be other
producer in the future. We don't want to define something only meet
current TDVF need.
Hmm. efi has a kind-of binary format (EFI_FIRMWARE_VOLUME_HEADER).
It's not fully self-contained though, you need to know where the
architecture places the firmware (i.e. just below 4G for x86)
because the load address isn't there. So I do see the point of
adding other headers adding that.

Possible alternative approach: Define an extension
(EFI_FIRMWARE_VOLUME_EXT_HEADER) for the load address and use that
instead of defining something new.

Still not clear why the size is in there twice. I think you could
instead use a flag telling whenever a section must be loaded from
the image or not. This is what COFF and ELF are doing too.

Also not clear why you want stick to 64bit base address. Loading the
firmware above 4G isn't going to work without also changing a bunch of
other things and it will break backward compatibility anyway.

I think the entry size can be cut in half with something like this:

struct {
uint32_t file_offset;
uint32_t load_address;
uint32_t section_size;
uint16_t section_type;
uint16_t section_flags;
};

Topic 2: In config-B we remove PEI.
I think we should say it in different way: We add PEI back in config-A.
In our original design we totally eliminated PEI, because it is unnecessary. IMHO, it is totally an overdesign in OVMF to include PEI.
Granted. PEI basically allows OEMs to plug their binary PEIMs into
early hardware initialization. For a full open source firmware there
is little reason to support that, other than maybe using PEIMs from
other edk2 Pkgs unmodified.

But, again, I don't want have two completely different initialization
code paths in OVMF. We can certainly investigate and discuss dropping
PEI, but that clearly shouldn't be a TDX-only thing. When we eliminate
PEI, we should do it for all OVMF builds.

take care,
Gerd


Re: [PATCH v3 15/28] Ampere: PCIe: Add PciSegmentLib library instance

Ard Biesheuvel
 

On Wed, 15 Sept 2021 at 18:00, Nhi Pham <nhi@os.amperecomputing.com> wrote:

From: Vu Nguyen <vunguyen@os.amperecomputing.com>

Provides wrapper calls to the Ac01PcieLib to handle the PCIe access.
As Ampere Altra processor supports upto 16 PCIe Root Complexs, the
target Root Complex will depend on the segment number parsed from the
input address.

Cc: Thang Nguyen <thang@os.amperecomputing.com>
Cc: Chuong Tran <chuong@os.amperecomputing.com>
Cc: Phong Vo <phong@os.amperecomputing.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>

Signed-off-by: Vu Nguyen <vunguyen@os.amperecomputing.com>
OK, this is not your fault, but this file is 99% boilerplate, with the
only platform specific piece being the calls to Ac01PcieConfigRW(),
right?

Leif, Michael, do you see any avenues here to improve this situation?
I don't think it should hold up this patch, but I have seen this
pattern a few times now (and I am responsible for at least one of
them)

For the change itself,

Acked-by: Ard Biesheuvel <ardb@kernel.org>

---
Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc | 1 +
Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLibPci.inf | 28 +
Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLib.c | 1189 ++++++++++++++++++++
3 files changed, 1218 insertions(+)

diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
index dc66b711aba8..dbcd1c9acaa2 100644
--- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
+++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
@@ -229,6 +229,7 @@ [LibraryClasses.common.DXE_DRIVER]
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
FlashLib|Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf
PciHostBridgeLib|Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+ PciSegmentLib|Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLibPci.inf

[LibraryClasses.common.UEFI_APPLICATION]
UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiTianoCustomDecompressLib.inf
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLibPci.inf b/Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLibPci.inf
new file mode 100644
index 000000000000..64897653e126
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLibPci.inf
@@ -0,0 +1,28 @@
+## @file
+#
+# Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = PciSegmentLibPci
+ FILE_GUID = 0AF5E76D-D31E-492B-AE69-A7B441FF62D9
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PciSegmentLib
+
+[Sources]
+ PciSegmentLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+
+[LibraryClasses]
+ Ac01PcieLib
+ BaseLib
+ DebugLib
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLib.c b/Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLib.c
new file mode 100644
index 000000000000..c893c56dfadf
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLib.c
@@ -0,0 +1,1189 @@
+/** @file
+
+ Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/Ac01PcieLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PciLib.h>
+#include <Library/PciSegmentLib.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#include <Ac01PcieCommon.h>
+
+/**
+ Assert the validity of a PCI Segment address.
+ A valid PCI Segment address should not contain 1's in bits 28..31 and 48..63
+ and the segment should be 0.
+
+ @param A The address to validate.
+ @param M Additional bits to assert to be zero.
+
+**/
+#define ASSERT_INVALID_PCI_SEGMENT_ADDRESS(A,M) \
+ ASSERT (((A) & (0xffff0000f0000000ULL | (M))) == 0)
+
+/**
+ Convert the PCI Segment library address to PCI library address.
+
+ @param A The address to convert.
+**/
+#define PCI_SEGMENT_TO_PCI_ADDRESS(A) ((UINTN)(UINT32)A)
+
+/**
+ Register a PCI device so PCI configuration registers may be accessed after
+ SetVirtualAddressMap().
+
+ If any reserved bits in Address are set, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and
+ Register.
+
+ @retval RETURN_SUCCESS The PCI device was registered for runtime access.
+ @retval RETURN_UNSUPPORTED An attempt was made to call this function
+ after ExitBootServices().
+ @retval RETURN_UNSUPPORTED The resources required to access the PCI device
+ at runtime could not be mapped.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
+ complete the registration.
+
+**/
+RETURN_STATUS
+EFIAPI
+PciSegmentRegisterForRuntimeAccess (
+ IN UINTN Address
+ )
+{
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);
+ return PciRegisterForRuntimeAccess (PCI_SEGMENT_TO_PCI_ADDRESS (Address));
+}
+
+/**
+ Reads an 8-bit PCI configuration register.
+
+ Reads and returns the 8-bit PCI configuration register specified by Address.
+ This function must guarantee that all PCI read and write operations are serialized.
+
+ If any reserved bits in Address are set, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+ @return The 8-bit PCI configuration register specified by Address.
+
+**/
+UINT8
+EFIAPI
+PciSegmentRead8 (
+ IN UINT64 Address
+ )
+{
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);
+
+ return PciRead8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address));
+}
+
+/**
+ Writes an 8-bit PCI configuration register.
+
+ Writes the 8-bit PCI configuration register specified by Address with the value specified by Value.
+ Value is returned. This function must guarantee that all PCI read and write operations are serialized.
+
+ If any reserved bits in Address are set, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param Value The value to write.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentWrite8 (
+ IN UINT64 Address,
+ IN UINT8 Value
+ )
+{
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 0);
+
+ return PciWrite8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value);
+}
+
+/**
+ Performs a bitwise OR of an 8-bit PCI configuration register with an 8-bit value.
+
+ Reads the 8-bit PCI configuration register specified by Address,
+ performs a bitwise OR between the read result and the value specified by OrData,
+ and writes the result to the 8-bit PCI configuration register specified by Address.
+ The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are serialized.
+
+ If any reserved bits in Address are set, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentOr8 (
+ IN UINT64 Address,
+ IN UINT8 OrData
+ )
+{
+ return PciWrite8 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), (UINT8)(PciSegmentRead8 (Address) | OrData));
+}
+
+/**
+ Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value.
+
+ Reads the 8-bit PCI configuration register specified by Address,
+ performs a bitwise AND between the read result and the value specified by AndData,
+ and writes the result to the 8-bit PCI configuration register specified by Address.
+ The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are serialized.
+ If any reserved bits in Address are set, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentAnd8 (
+ IN UINT64 Address,
+ IN UINT8 AndData
+ )
+{
+ return PciSegmentWrite8 (Address, (UINT8)(PciSegmentRead8 (Address) & AndData));
+}
+
+/**
+ Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value,
+ followed a bitwise OR with another 8-bit value.
+
+ Reads the 8-bit PCI configuration register specified by Address,
+ performs a bitwise AND between the read result and the value specified by AndData,
+ performs a bitwise OR between the result of the AND operation and the value specified by OrData,
+ and writes the result to the 8-bit PCI configuration register specified by Address.
+ The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are serialized.
+
+ If any reserved bits in Address are set, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentAndThenOr8 (
+ IN UINT64 Address,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ return PciSegmentWrite8 (Address, (UINT8)((PciSegmentRead8 (Address) & AndData) | OrData));
+}
+
+/**
+ Reads a bit field of a PCI configuration register.
+
+ Reads the bit field in an 8-bit PCI configuration register. The bit field is
+ specified by the StartBit and the EndBit. The value of the bit field is
+ returned.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param Address PCI configuration register to read.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..7.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..7.
+
+ @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentBitFieldRead8 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit
+ )
+{
+ return BitFieldRead8 (PciSegmentRead8 (Address), StartBit, EndBit);
+}
+
+/**
+ Writes a bit field to a PCI configuration register.
+
+ Writes Value to the bit field of the PCI configuration register. The bit
+ field is specified by the StartBit and the EndBit. All other bits in the
+ destination PCI configuration register are preserved. The new value of the
+ 8-bit register is returned.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..7.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..7.
+ @param Value New value of the bit field.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentBitFieldWrite8 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 Value
+ )
+{
+ return PciSegmentWrite8 (
+ Address,
+ BitFieldWrite8 (PciSegmentRead8 (Address), StartBit, EndBit, Value)
+ );
+}
+
+/**
+ Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and
+ writes the result back to the bit field in the 8-bit port.
+
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise OR between the read result and the value specified by
+ OrData, and writes the result to the 8-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized. Extra left bits in OrData are stripped.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..7.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..7.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentBitFieldOr8 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 OrData
+ )
+{
+ return PciSegmentWrite8 (
+ Address,
+ BitFieldOr8 (PciSegmentRead8 (Address), StartBit, EndBit, OrData)
+ );
+}
+
+/**
+ Reads a bit field in an 8-bit PCI configuration register, performs a bitwise
+ AND, and writes the result back to the bit field in the 8-bit register.
+
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 8-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized. Extra left bits in AndData are stripped.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..7.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..7.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentBitFieldAnd8 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 AndData
+ )
+{
+ return PciSegmentWrite8 (
+ Address,
+ BitFieldAnd8 (PciSegmentRead8 (Address), StartBit, EndBit, AndData)
+ );
+}
+
+/**
+ Reads a bit field in an 8-bit port, performs a bitwise AND followed by a
+ bitwise OR, and writes the result back to the bit field in the 8-bit port.
+
+ Reads the 8-bit PCI configuration register specified by Address, performs a
+ bitwise AND followed by a bitwise OR between the read result and
+ the value specified by AndData, and writes the result to the 8-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized. Extra left bits in both AndData and
+ OrData are stripped.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If StartBit is greater than 7, then ASSERT().
+ If EndBit is greater than 7, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..7.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..7.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the result of the AND operation.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT8
+EFIAPI
+PciSegmentBitFieldAndThenOr8 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ return PciSegmentWrite8 (
+ Address,
+ BitFieldAndThenOr8 (PciSegmentRead8 (Address), StartBit, EndBit, AndData, OrData)
+ );
+}
+
+/**
+ Reads a 16-bit PCI configuration register.
+
+ Reads and returns the 16-bit PCI configuration register specified by Address.
+ This function must guarantee that all PCI read and write operations are serialized.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+ @return The 16-bit PCI configuration register specified by Address.
+
+**/
+UINT16
+EFIAPI
+PciSegmentRead16 (
+ IN UINT64 Address
+ )
+{
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1);
+
+ return PciRead16 (PCI_SEGMENT_TO_PCI_ADDRESS (Address));
+}
+
+/**
+ Writes a 16-bit PCI configuration register.
+
+ Writes the 16-bit PCI configuration register specified by Address with the value specified by Value.
+ Value is returned. This function must guarantee that all PCI read and write operations are serialized.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param Value The value to write.
+
+ @return The parameter of Value.
+
+**/
+UINT16
+EFIAPI
+PciSegmentWrite16 (
+ IN UINT64 Address,
+ IN UINT16 Value
+ )
+{
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 1);
+
+ return PciWrite16 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value);
+}
+
+/**
+ Performs a bitwise OR of a 16-bit PCI configuration register with
+ a 16-bit value.
+
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise OR between the read result and the value specified by OrData, and
+ writes the result to the 16-bit PCI configuration register specified by Address.
+ The value written to the PCI configuration register is returned. This function
+ must guarantee that all PCI read and write operations are serialized.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function and
+ Register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentOr16 (
+ IN UINT64 Address,
+ IN UINT16 OrData
+ )
+{
+ return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 (Address) | OrData));
+}
+
+/**
+ Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value.
+
+ Reads the 16-bit PCI configuration register specified by Address,
+ performs a bitwise AND between the read result and the value specified by AndData,
+ and writes the result to the 16-bit PCI configuration register specified by Address.
+ The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are serialized.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentAnd16 (
+ IN UINT64 Address,
+ IN UINT16 AndData
+ )
+{
+ return PciSegmentWrite16 (Address, (UINT16) (PciSegmentRead16 (Address) & AndData));
+}
+
+/**
+ Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value,
+ followed a bitwise OR with another 16-bit value.
+
+ Reads the 16-bit PCI configuration register specified by Address,
+ performs a bitwise AND between the read result and the value specified by AndData,
+ performs a bitwise OR between the result of the AND operation and the value specified by OrData,
+ and writes the result to the 16-bit PCI configuration register specified by Address.
+ The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are serialized.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentAndThenOr16 (
+ IN UINT64 Address,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ return PciSegmentWrite16 (Address, (UINT16) ((PciSegmentRead16 (Address) & AndData) | OrData));
+}
+
+/**
+ Reads a bit field of a PCI configuration register.
+
+ Reads the bit field in a 16-bit PCI configuration register. The bit field is
+ specified by the StartBit and the EndBit. The value of the bit field is
+ returned.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param Address PCI configuration register to read.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..15.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..15.
+
+ @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentBitFieldRead16 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit
+ )
+{
+ return BitFieldRead16 (PciSegmentRead16 (Address), StartBit, EndBit);
+}
+
+/**
+ Writes a bit field to a PCI configuration register.
+
+ Writes Value to the bit field of the PCI configuration register. The bit
+ field is specified by the StartBit and the EndBit. All other bits in the
+ destination PCI configuration register are preserved. The new value of the
+ 16-bit register is returned.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..15.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..15.
+ @param Value New value of the bit field.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentBitFieldWrite16 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 Value
+ )
+{
+ return PciSegmentWrite16 (
+ Address,
+ BitFieldWrite16 (PciSegmentRead16 (Address), StartBit, EndBit, Value)
+ );
+}
+
+/**
+ Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, writes
+ the result back to the bit field in the 16-bit port.
+
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise OR between the read result and the value specified by
+ OrData, and writes the result to the 16-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized. Extra left bits in OrData are stripped.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..15.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..15.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentBitFieldOr16 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 OrData
+ )
+{
+ return PciSegmentWrite16 (
+ Address,
+ BitFieldOr16 (PciSegmentRead16 (Address), StartBit, EndBit, OrData)
+ );
+}
+
+/**
+ Reads a bit field in a 16-bit PCI configuration register, performs a bitwise
+ AND, writes the result back to the bit field in the 16-bit register.
+
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise AND between the read result and the value specified by AndData, and
+ writes the result to the 16-bit PCI configuration register specified by
+ Address. The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are
+ serialized. Extra left bits in AndData are stripped.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..15.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..15.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentBitFieldAnd16 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 AndData
+ )
+{
+ return PciSegmentWrite16 (
+ Address,
+ BitFieldAnd16 (PciSegmentRead16 (Address), StartBit, EndBit, AndData)
+ );
+}
+
+/**
+ Reads a bit field in a 16-bit port, performs a bitwise AND followed by a
+ bitwise OR, and writes the result back to the bit field in the
+ 16-bit port.
+
+ Reads the 16-bit PCI configuration register specified by Address, performs a
+ bitwise AND followed by a bitwise OR between the read result and
+ the value specified by AndData, and writes the result to the 16-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized. Extra left bits in both AndData and
+ OrData are stripped.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If StartBit is greater than 15, then ASSERT().
+ If EndBit is greater than 15, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..15.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..15.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the result of the AND operation.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT16
+EFIAPI
+PciSegmentBitFieldAndThenOr16 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ return PciSegmentWrite16 (
+ Address,
+ BitFieldAndThenOr16 (PciSegmentRead16 (Address), StartBit, EndBit, AndData, OrData)
+ );
+}
+
+/**
+ Reads a 32-bit PCI configuration register.
+
+ Reads and returns the 32-bit PCI configuration register specified by Address.
+ This function must guarantee that all PCI read and write operations are serialized.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+
+ @return The 32-bit PCI configuration register specified by Address.
+
+**/
+UINT32
+EFIAPI
+PciSegmentRead32 (
+ IN UINT64 Address
+ )
+{
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3);
+
+ return PciRead32 (PCI_SEGMENT_TO_PCI_ADDRESS (Address));
+}
+
+/**
+ Writes a 32-bit PCI configuration register.
+
+ Writes the 32-bit PCI configuration register specified by Address with the value specified by Value.
+ Value is returned. This function must guarantee that all PCI read and write operations are serialized.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param Value The value to write.
+
+ @return The parameter of Value.
+
+**/
+UINT32
+EFIAPI
+PciSegmentWrite32 (
+ IN UINT64 Address,
+ IN UINT32 Value
+ )
+{
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (Address, 3);
+
+ return PciWrite32 (PCI_SEGMENT_TO_PCI_ADDRESS (Address), Value);
+}
+
+/**
+ Performs a bitwise OR of a 32-bit PCI configuration register with a 32-bit value.
+
+ Reads the 32-bit PCI configuration register specified by Address,
+ performs a bitwise OR between the read result and the value specified by OrData,
+ and writes the result to the 32-bit PCI configuration register specified by Address.
+ The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are serialized.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentOr32 (
+ IN UINT64 Address,
+ IN UINT32 OrData
+ )
+{
+ return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) | OrData);
+}
+
+/**
+ Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value.
+
+ Reads the 32-bit PCI configuration register specified by Address,
+ performs a bitwise AND between the read result and the value specified by AndData,
+ and writes the result to the 32-bit PCI configuration register specified by Address.
+ The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are serialized.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentAnd32 (
+ IN UINT64 Address,
+ IN UINT32 AndData
+ )
+{
+ return PciSegmentWrite32 (Address, PciSegmentRead32 (Address) & AndData);
+}
+
+/**
+ Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value,
+ followed a bitwise OR with another 32-bit value.
+
+ Reads the 32-bit PCI configuration register specified by Address,
+ performs a bitwise AND between the read result and the value specified by AndData,
+ performs a bitwise OR between the result of the AND operation and the value specified by OrData,
+ and writes the result to the 32-bit PCI configuration register specified by Address.
+ The value written to the PCI configuration register is returned.
+ This function must guarantee that all PCI read and write operations are serialized.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentAndThenOr32 (
+ IN UINT64 Address,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ return PciSegmentWrite32 (Address, (PciSegmentRead32 (Address) & AndData) | OrData);
+}
+
+/**
+ Reads a bit field of a PCI configuration register.
+
+ Reads the bit field in a 32-bit PCI configuration register. The bit field is
+ specified by the StartBit and the EndBit. The value of the bit field is
+ returned.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+
+ @param Address PCI configuration register to read.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..31.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..31.
+
+ @return The value of the bit field read from the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentBitFieldRead32 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit
+ )
+{
+ return BitFieldRead32 (PciSegmentRead32 (Address), StartBit, EndBit);
+}
+
+/**
+ Writes a bit field to a PCI configuration register.
+
+ Writes Value to the bit field of the PCI configuration register. The bit
+ field is specified by the StartBit and the EndBit. All other bits in the
+ destination PCI configuration register are preserved. The new value of the
+ 32-bit register is returned.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..31.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..31.
+ @param Value New value of the bit field.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentBitFieldWrite32 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 Value
+ )
+{
+ return PciSegmentWrite32 (
+ Address,
+ BitFieldWrite32 (PciSegmentRead32 (Address), StartBit, EndBit, Value)
+ );
+}
+
+/**
+ Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and
+ writes the result back to the bit field in the 32-bit port.
+
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise OR between the read result and the value specified by
+ OrData, and writes the result to the 32-bit PCI configuration register
+ specified by Address. The value written to the PCI configuration register is
+ returned. This function must guarantee that all PCI read and write operations
+ are serialized. Extra left bits in OrData are stripped.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..31.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..31.
+ @param OrData The value to OR with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentBitFieldOr32 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 OrData
+ )
+{
+ return PciSegmentWrite32 (
+ Address,
+ BitFieldOr32 (PciSegmentRead32 (Address), StartBit, EndBit, OrData)
+ );
+}
+
+/**
+ Reads a bit field in a 32-bit PCI configuration register, performs a bitwise
+ AND, and writes the result back to the bit field in the 32-bit register.
+
+
+ Reads the 32-bit PCI configuration register specified by Address, performs a bitwise
+ AND between the read result and the value specified by AndData, and writes the result
+ to the 32-bit PCI configuration register specified by Address. The value written to
+ the PCI configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized. Extra left bits in AndData are stripped.
+ If any reserved bits in Address are set, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..31.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..31.
+ @param AndData The value to AND with the PCI configuration register.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentBitFieldAnd32 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 AndData
+ )
+{
+ return PciSegmentWrite32 (
+ Address,
+ BitFieldAnd32 (PciSegmentRead32 (Address), StartBit, EndBit, AndData)
+ );
+}
+
+/**
+ Reads a bit field in a 32-bit port, performs a bitwise AND followed by a
+ bitwise OR, and writes the result back to the bit field in the
+ 32-bit port.
+
+ Reads the 32-bit PCI configuration register specified by Address, performs a
+ bitwise AND followed by a bitwise OR between the read result and
+ the value specified by AndData, and writes the result to the 32-bit PCI
+ configuration register specified by Address. The value written to the PCI
+ configuration register is returned. This function must guarantee that all PCI
+ read and write operations are serialized. Extra left bits in both AndData and
+ OrData are stripped.
+
+ If any reserved bits in Address are set, then ASSERT().
+ If StartBit is greater than 31, then ASSERT().
+ If EndBit is greater than 31, then ASSERT().
+ If EndBit is less than StartBit, then ASSERT().
+ If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+ If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
+
+ @param Address PCI configuration register to write.
+ @param StartBit The ordinal of the least significant bit in the bit field.
+ Range 0..31.
+ @param EndBit The ordinal of the most significant bit in the bit field.
+ Range 0..31.
+ @param AndData The value to AND with the PCI configuration register.
+ @param OrData The value to OR with the result of the AND operation.
+
+ @return The value written back to the PCI configuration register.
+
+**/
+UINT32
+EFIAPI
+PciSegmentBitFieldAndThenOr32 (
+ IN UINT64 Address,
+ IN UINTN StartBit,
+ IN UINTN EndBit,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ return PciSegmentWrite32 (
+ Address,
+ BitFieldAndThenOr32 (PciSegmentRead32 (Address), StartBit, EndBit, AndData, OrData)
+ );
+}
+
+/**
+ Reads a range of PCI configuration registers into a caller supplied buffer.
+
+ Reads the range of PCI configuration registers specified by StartAddress and
+ Size into the buffer specified by Buffer. This function only allows the PCI
+ configuration registers from a single PCI function to be read. Size is
+ returned. When possible 32-bit PCI configuration read cycles are used to read
+ from StartAddress to StartAddress + Size. Due to alignment restrictions, 8-bit
+ and 16-bit PCI configuration read cycles may be used at the beginning and the
+ end of the range.
+
+ If any reserved bits in StartAddress are set, then ASSERT().
+ If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+ If Size > 0 and Buffer is NULL, then ASSERT().
+
+ @param StartAddress Starting address that encodes the PCI Segment, Bus, Device,
+ Function and Register.
+ @param Size Size in bytes of the transfer.
+ @param Buffer Pointer to a buffer receiving the data read.
+
+ @return Size
+
+**/
+UINTN
+EFIAPI
+PciSegmentReadBuffer (
+ IN UINT64 StartAddress,
+ IN UINTN Size,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0);
+ ASSERT (((StartAddress & 0xFFF) + Size) <= SIZE_4KB);
+
+ if (Size == 0) {
+ return Size;
+ }
+
+ ASSERT (Buffer != NULL);
+
+ Status = Ac01PcieConfigRW (NULL, StartAddress, FALSE, Size, Buffer);
+ ASSERT_EFI_ERROR (Status);
+
+ return Size;
+}
+
+/**
+ Copies the data in a caller supplied buffer to a specified range of PCI
+ configuration space.
+
+ Writes the range of PCI configuration registers specified by StartAddress and
+ Size from the buffer specified by Buffer. This function only allows the PCI
+ configuration registers from a single PCI function to be written. Size is
+ returned. When possible 32-bit PCI configuration write cycles are used to
+ write from StartAddress to StartAddress + Size. Due to alignment restrictions,
+ 8-bit and 16-bit PCI configuration write cycles may be used at the beginning
+ and the end of the range.
+
+ If any reserved bits in StartAddress are set, then ASSERT().
+ If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT().
+ If Size > 0 and Buffer is NULL, then ASSERT().
+
+ @param StartAddress Starting address that encodes the PCI Segment, Bus, Device,
+ Function and Register.
+ @param Size Size in bytes of the transfer.
+ @param Buffer Pointer to a buffer containing the data to write.
+
+ @return The parameter of Size.
+
+**/
+UINTN
+EFIAPI
+PciSegmentWriteBuffer (
+ IN UINT64 StartAddress,
+ IN UINTN Size,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT_INVALID_PCI_SEGMENT_ADDRESS (StartAddress, 0);
+ ASSERT (((StartAddress & 0xFFF) + Size) <= SIZE_4KB);
+
+ if (Size == 0) {
+ return Size;
+ }
+
+ ASSERT (Buffer != NULL);
+
+ Status = Ac01PcieConfigRW (NULL, StartAddress, TRUE, Size, Buffer);
+ ASSERT_EFI_ERROR (Status);
+
+ return Size;
+}
--
2.17.1


Re: [PATCH v3 14/28] Ampere: PCIe: Add PciHostBridgeLib library instance

Ard Biesheuvel
 

On Wed, 15 Sept 2021 at 18:00, Nhi Pham <nhi@os.amperecomputing.com> wrote:

From: Vu Nguyen <vunguyen@os.amperecomputing.com>

Provides the number of supported RootBridges and the resource allocated
for each RootBridge. These information are essential to the HostBridge
driver to initialize the PCIe subsystem.

Cc: Thang Nguyen <thang@os.amperecomputing.com>
Cc: Chuong Tran <chuong@os.amperecomputing.com>
Cc: Phong Vo <phong@os.amperecomputing.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>

Signed-off-by: Vu Nguyen <vunguyen@os.amperecomputing.com>
This looks ok to me, although I will note the code that patches the
_STA methods in the DSDT according to which host bridges actually
exist in the system should not typically live in a library. However,
this particular library is designed to be incorporated only by
PciHostBridgeDxe so in this case, I can live with it.

Reviewed-by: Ard Biesheuvel <ardb@kernel.org>

---
Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc | 1 +
Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf | 48 +++
Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c | 378 ++++++++++++++++++++
3 files changed, 427 insertions(+)

diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
index d4e1b84c0276..dc66b711aba8 100644
--- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
+++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
@@ -228,6 +228,7 @@ [LibraryClasses.common.DXE_DRIVER]
PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
FlashLib|Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf
+ PciHostBridgeLib|Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf

[LibraryClasses.common.UEFI_APPLICATION]
UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiTianoCustomDecompressLib.inf
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
new file mode 100644
index 000000000000..a8ee0c2b9278
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
@@ -0,0 +1,48 @@
+## @file
+#
+# Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = PciHostBridgeLib
+ FILE_GUID = 9D0522E5-B5FD-4E3F-9D10-52AE221FA314
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PciHostBridgeLib|DXE_DRIVER
+ CONSTRUCTOR = HostBridgeConstructor
+
+[Sources]
+ PciHostBridgeLib.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+ Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
+
+[LibraryClasses]
+ Ac01PcieLib
+ AcpiLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ IoLib
+ MemoryAllocationLib
+ PrintLib
+ UefiBootServicesTableLib
+
+[Guids]
+ gEfiEventReadyToBootGuid
+
+[Protocols]
+ gEfiCpuIo2ProtocolGuid ## CONSUMES
+
+[Depex]
+ gEfiCpuIo2ProtocolGuid
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
new file mode 100644
index 000000000000..281f20b4bb63
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
@@ -0,0 +1,378 @@
+/** @file
+ PCI Host Bridge Library instance for Ampere Altra-based platforms.
+
+ Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Guid/EventGroup.h>
+#include <IndustryStandard/Acpi.h>
+#include <Library/Ac01PcieLib.h>
+#include <Library/AcpiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciHostBridgeLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#include <Ac01PcieCommon.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+STATIC CHAR16 CONST * CONST mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
+ L"Mem", L"I/O", L"Bus"
+};
+
+#pragma pack(1)
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+#pragma pack ()
+
+STATIC EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)),
+ (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID (0x0A08), // PCIe
+ 0
+ }, {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+};
+
+STATIC PCI_ROOT_BRIDGE mRootBridgeTemplate = {
+ 0, // Segment
+ 0, // Supports
+ 0, // Attributes
+ TRUE, // DmaAbove4G
+ FALSE, // NoExtendedConfigSpace
+ FALSE, // ResourceAssigned
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
+ {
+ // Bus
+ 0,
+ 0
+ }, {
+ // Io
+ 0,
+ 0,
+ 0
+ }, {
+ // Mem
+ MAX_UINT64,
+ 0,
+ 0
+ }, {
+ // MemAbove4G
+ MAX_UINT64,
+ 0,
+ 0
+ }, {
+ // PMem
+ MAX_UINT64,
+ 0,
+ 0
+ }, {
+ // PMemAbove4G
+ MAX_UINT64,
+ 0,
+ 0
+ },
+ (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath
+};
+
+UINT8 mRootBridgeCount = 0;
+PCI_ROOT_BRIDGE *mRootBridges = NULL;
+
+EFI_STATUS
+UpdateStatusMethodObject (
+ EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol,
+ EFI_ACPI_HANDLE TableHandle,
+ CHAR8 *AsciiObjectPath,
+ CHAR8 ReturnValue
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_HANDLE ObjectHandle;
+ EFI_ACPI_DATA_TYPE DataType;
+ CHAR8 *Buffer;
+ UINTN DataSize;
+
+ Status = AcpiSdtProtocol->FindPath (TableHandle, AsciiObjectPath, &ObjectHandle);
+ if (EFI_ERROR (Status) || ObjectHandle == NULL) {
+ return EFI_SUCCESS;
+ }
+ ASSERT (ObjectHandle != NULL);
+
+ Status = AcpiSdtProtocol->GetOption (ObjectHandle, 2, &DataType, (VOID *)&Buffer, &DataSize);
+ if (!EFI_ERROR (Status) && Buffer[2] == AML_BYTE_PREFIX) {
+ //
+ // Only patch when the initial value is byte object.
+ //
+ Buffer[3] = ReturnValue;
+ }
+
+ AcpiSdtProtocol->Close (ObjectHandle);
+ return Status;
+}
+
+/**
+ This function will be called when ReadyToBoot event is signaled.
+
+ @param Event signaled event
+ @param Context calling context
+
+ @retval VOID
+**/
+VOID
+EFIAPI
+PciHostBridgeReadyToBootEvent (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol;
+ EFI_ACPI_DESCRIPTION_HEADER *Table;
+ UINTN TableKey;
+ UINTN TableIndex;
+ EFI_ACPI_HANDLE TableHandle;
+ CHAR8 NodePath[256];
+ UINTN Count;
+ UINTN Idx1;
+ UINTN Idx2;
+
+ Count = 0;
+
+ Status = gBS->LocateProtocol (
+ &gEfiAcpiSdtProtocolGuid,
+ NULL,
+ (VOID **)&AcpiSdtProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Unable to locate ACPI table protocol\n"));
+ return;
+ }
+
+ TableIndex = 0;
+ Status = AcpiLocateTableBySignature (
+ AcpiSdtProtocol,
+ EFI_ACPI_6_3_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ &TableIndex,
+ &Table,
+ &TableKey
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a %d Status = %r \n", __FUNCTION__, __LINE__, Status));
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+
+ Status = AcpiSdtProtocol->OpenSdt (TableKey, &TableHandle);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ AcpiSdtProtocol->Close (TableHandle);
+ return;
+ }
+
+ for (Idx1 = 0; Idx1 < Ac01PcieGetTotalHBs (); Idx1++) {
+ for (Idx2 = 0; Idx2 < Ac01PcieGetTotalRBsPerHB (Idx1); Idx2++) {
+ AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.PCI%X._STA", Count);
+ if (Ac01PcieCheckRootBridgeDisabled (Idx1, Idx2)) {
+ UpdateStatusMethodObject (AcpiSdtProtocol, TableHandle, NodePath, 0x0);
+ } else {
+ UpdateStatusMethodObject (AcpiSdtProtocol, TableHandle, NodePath, 0xf);
+ }
+ Count++;
+ }
+ }
+
+ AcpiSdtProtocol->Close (TableHandle);
+ AcpiUpdateChecksum ((UINT8 *)Table, Table->Length);
+
+ //
+ // Close the event, so it will not be signalled again.
+ //
+ gBS->CloseEvent (Event);
+}
+
+EFI_STATUS
+HostBridgeConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Index;
+ EFI_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;
+ EFI_EVENT EvtReadyToBoot;
+
+ mRootBridges = AllocatePool (Ac01PcieGetTotalHBs () * sizeof (PCI_ROOT_BRIDGE));
+ if (mRootBridges == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = Ac01PcieSetup ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < Ac01PcieGetTotalHBs (); Index++) {
+ CopyMem (&mRootBridges[mRootBridgeCount], &mRootBridgeTemplate, sizeof (PCI_ROOT_BRIDGE));
+
+ Status = Ac01PcieSetupRootBridge (Index, 0, (VOID *)&mRootBridges[mRootBridgeCount]);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ mRootBridges[mRootBridgeCount].Segment = Ac01PcieGetRootBridgeSegmentNumber (Index, 0);
+
+ DevicePath = AllocateCopyPool (
+ sizeof (EFI_PCI_ROOT_BRIDGE_DEVICE_PATH),
+ (VOID *)&mEfiPciRootBridgeDevicePath
+ );
+ if (DevicePath == NULL) {
+ continue;
+ }
+
+ //
+ // Embedded RC Index to the DevicePath
+ // This will be used later by the platform NotifyPhase()
+ //
+ DevicePath->AcpiDevicePath.UID = Index;
+
+ mRootBridges[mRootBridgeCount].DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
+ mRootBridgeCount++;
+ }
+
+ Ac01PcieEnd ();
+
+ //
+ // Register event to fixup ACPI table
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL, // Type,
+ TPL_NOTIFY, // NotifyTpl
+ PciHostBridgeReadyToBootEvent, // NotifyFunction
+ NULL, // NotifyContext
+ &gEfiEventReadyToBootGuid, // EventGroup
+ &EvtReadyToBoot // Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return all the root bridge instances in an array.
+
+ @param Count Return the count of root bridge instances.
+
+ @return All the root bridge instances in an array.
+ The array should be passed into PciHostBridgeFreeRootBridges()
+ when it's not used.
+**/
+PCI_ROOT_BRIDGE *
+EFIAPI
+PciHostBridgeGetRootBridges (
+ UINTN *Count
+ )
+{
+ *Count = mRootBridgeCount;
+ return mRootBridges;
+}
+
+/**
+ Free the root bridge instances array returned from PciHostBridgeGetRootBridges().
+
+ @param Bridges The root bridge instances array.
+ @param Count The count of the array.
+**/
+VOID
+EFIAPI
+PciHostBridgeFreeRootBridges (
+ PCI_ROOT_BRIDGE *Bridges,
+ UINTN Count
+ )
+{
+ //
+ // Unsupported
+ //
+}
+
+/**
+ Inform the platform that the resource conflict happens.
+
+ @param HostBridgeHandle Handle of the Host Bridge.
+ @param Configuration Pointer to PCI I/O and PCI memory resource
+ descriptors. The Configuration contains the resources
+ for all the root bridges. The resource for each root
+ bridge is terminated with END descriptor and an
+ additional END is appended indicating the end of the
+ entire resources. The resource descriptor field
+ values follow the description in
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ .SubmitResources().
+**/
+VOID
+EFIAPI
+PciHostBridgeResourceConflict (
+ EFI_HANDLE HostBridgeHandle,
+ VOID *Configuration
+ )
+{
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
+ UINTN RootBridgeIndex;
+ DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));
+
+ RootBridgeIndex = 0;
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Configuration;
+ while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
+ for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
+ ASSERT (Descriptor->ResType <
+ (sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr) /
+ sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr[0])
+ )
+ );
+ DEBUG ((DEBUG_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
+ mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
+ Descriptor->AddrLen, Descriptor->AddrRangeMax
+ ));
+ if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
+ DEBUG ((DEBUG_ERROR, " Granularity/SpecificFlag = %ld / %02x%s\n",
+ Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
+ ((Descriptor->SpecificFlag &
+ EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
+ ) != 0) ? L" (Prefetchable)" : L""
+ ));
+ }
+ }
+ //
+ // Skip the END descriptor for root bridge
+ //
+ ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
+ (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
+ );
+ }
+}
--
2.17.1


Re: [PATCH v3 18/28] Ampere: PCIe: Add PciPlatformDxe driver

Leif Lindholm
 

On Wed, Sep 15, 2021 at 22:55:17 +0700, Nhi Pham wrote:
From: Vu Nguyen <vunguyen@os.amperecomputing.com>

Registers the Platform NotifyPhase() to prevent unexpected issues
caused by the enabled PCIe controllers which have unstable link.

Cc: Thang Nguyen <thang@os.amperecomputing.com>
Cc: Chuong Tran <chuong@os.amperecomputing.com>
Cc: Phong Vo <phong@os.amperecomputing.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>

Signed-off-by: Vu Nguyen <vunguyen@os.amperecomputing.com>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>

---
Platform/Ampere/JadePkg/Jade.dsc | 5 +
Platform/Ampere/JadePkg/Jade.fdf | 1 +
Platform/Ampere/JadePkg/Drivers/PciPlatformDxe/PciPlatformDxe.inf | 37 ++++
Platform/Ampere/JadePkg/Drivers/PciPlatformDxe/PciPlatformDxe.c | 212 ++++++++++++++++++++
4 files changed, 255 insertions(+)

diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc
index b733f8430806..ce5f2c0dc4e1 100644
--- a/Platform/Ampere/JadePkg/Jade.dsc
+++ b/Platform/Ampere/JadePkg/Jade.dsc
@@ -148,6 +148,11 @@ [Components.common]
Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/AcpiCommonTables.inf
Platform/Ampere/JadePkg/AcpiTables/AcpiTables.inf

+ #
+ # PCIe
+ #
+ Platform/Ampere/JadePkg/Drivers/PciPlatformDxe/PciPlatformDxe.inf
+
#
# VGA Aspeed
#
diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf
index 195da2d63a7a..8ddfabcdd9a8 100644
--- a/Platform/Ampere/JadePkg/Jade.fdf
+++ b/Platform/Ampere/JadePkg/Jade.fdf
@@ -298,6 +298,7 @@ [FV.FvMain]
#
INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
+ INF Platform/Ampere/JadePkg/Drivers/PciPlatformDxe/PciPlatformDxe.inf

#
# VGA Aspeed
diff --git a/Platform/Ampere/JadePkg/Drivers/PciPlatformDxe/PciPlatformDxe.inf b/Platform/Ampere/JadePkg/Drivers/PciPlatformDxe/PciPlatformDxe.inf
new file mode 100644
index 000000000000..5f5316055217
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Drivers/PciPlatformDxe/PciPlatformDxe.inf
@@ -0,0 +1,37 @@
+## @file
+#
+# Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = PciPlatformDxe
+ FILE_GUID = 73276F3D-DCBC-49B2-9890-7564F917501D
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PciPlatformDriverEntry
+
+[Sources]
+ PciPlatformDxe.c
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+
+[LibraryClasses]
+ Ac01PcieLib
+ DebugLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Protocols]
+ gEfiDevicePathProtocolGuid
+ gEfiPciHostBridgeResourceAllocationProtocolGuid
+ gEfiPciPlatformProtocolGuid
+
+[Depex]
+ TRUE
diff --git a/Platform/Ampere/JadePkg/Drivers/PciPlatformDxe/PciPlatformDxe.c b/Platform/Ampere/JadePkg/Drivers/PciPlatformDxe/PciPlatformDxe.c
new file mode 100644
index 000000000000..196f857175e9
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Drivers/PciPlatformDxe/PciPlatformDxe.c
@@ -0,0 +1,212 @@
+/** @file
+
+ Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/Ac01PcieLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <Protocol/PciPlatform.h>
+
+#pragma pack(1)
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+#pragma pack ()
+
+/**
+
+ Perform initialization by the phase indicated.
+
+ @param This Pointer to the EFI_PCI_PLATFORM_PROTOCOL instance.
+ @param HostBridge The associated PCI host bridge handle.
+ @param Phase The phase of the PCI controller enumeration.
+ @param ChipsetPhase Defines the execution phase of the PCI chipset driver.
+
+ @retval EFI_SUCCESS Must return with success.
+
+**/
+EFI_STATUS
+EFIAPI
+PhaseNotify (
+ IN EFI_PCI_PLATFORM_PROTOCOL *This,
+ IN EFI_HANDLE HostBridge,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase,
+ IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase
+ )
+{
+ EFI_PCI_ROOT_BRIDGE_DEVICE_PATH *RootBridgeDevPath;
+ EFI_HANDLE RootBridgeHandle = NULL;
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *ResAlloc = NULL;
+ EFI_STATUS Status;
+
+ if (ChipsetPhase != ChipsetExit) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Get HostBridgeInstance from HostBridge handle.
+ //
+ Status = gBS->HandleProtocol (
+ HostBridge,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid,
+ (VOID **)&ResAlloc
+ );
+
+ while (TRUE) {
+ Status = ResAlloc->GetNextRootBridge (ResAlloc, &RootBridgeHandle);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ Status = gBS->HandleProtocol (
+ RootBridgeHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **)&RootBridgeDevPath
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a %d: Failed to locate RootBridge DevicePath\n", __FUNCTION__, __LINE__));
+ break;
+ }
+
+ Ac01PcieHostBridgeNotifyPhase (RootBridgeDevPath->AcpiDevicePath.UID, 0, Phase);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ The PlatformPrepController() function can be used to notify the platform driver so that
+ it can perform platform-specific actions. No specific actions are required.
+ Several notification points are defined at this time. More synchronization points may be
+ added as required in the future. The PCI bus driver calls the platform driver twice for
+ every PCI controller-once before the PCI Host Bridge Resource Allocation Protocol driver
+ is notified, and once after the PCI Host Bridge Resource Allocation Protocol driver has
+ been notified.
+ This member function may not perform any error checking on the input parameters. It also
+ does not return any error codes. If this member function detects any error condition, it
+ needs to handle those errors on its own because there is no way to surface any errors to
+ the caller.
+
+ @param This Pointer to the EFI_PCI_PLATFORM_PROTOCOL instance.
+ @param HostBridge The associated PCI host bridge handle.
+ @param RootBridge The associated PCI root bridge handle.
+ @param PciAddress The address of the PCI device on the PCI bus.
+ @param Phase The phase of the PCI controller enumeration.
+ @param ChipsetPhase Defines the execution phase of the PCI chipset driver.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_UNSUPPORTED Not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformPrepController (
+ IN EFI_PCI_PLATFORM_PROTOCOL *This,
+ IN EFI_HANDLE HostBridge,
+ IN EFI_HANDLE RootBridge,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase,
+ IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Set the PciPolicy as EFI_RESERVE_ISA_IO_NO_ALIAS | EFI_RESERVE_VGA_IO_NO_ALIAS.
+
+ @param This The pointer to the Protocol itself.
+ @param PciPolicy The returned Policy.
+
+ @retval EFI_UNSUPPORTED Function not supported.
+ @retval EFI_INVALID_PARAMETER Invalid PciPolicy value.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPlatformPolicy (
+ IN CONST EFI_PCI_PLATFORM_PROTOCOL *This,
+ OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+
+ Return a PCI ROM image for the onboard device represented by PciHandle.
+
+ @param This Protocol instance pointer.
+ @param PciHandle PCI device to return the ROM image for.
+ @param RomImage PCI Rom Image for onboard device.
+ @param RomSize Size of RomImage in bytes.
+
+ @retval EFI_SUCCESS RomImage is valid.
+ @retval EFI_NOT_FOUND No RomImage.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPciRom (
+ IN CONST EFI_PCI_PLATFORM_PROTOCOL *This,
+ IN EFI_HANDLE PciHandle,
+ OUT VOID **RomImage,
+ OUT UINTN *RomSize
+ )
+{
+ return EFI_NOT_FOUND;
+}
+
+//
+// Interface defintion of PCI Platform protocol.
+//
+EFI_PCI_PLATFORM_PROTOCOL mPciPlatformProtocol = {
+ .PlatformNotify = PhaseNotify,
+ .PlatformPrepController = PlatformPrepController,
+ .GetPlatformPolicy = GetPlatformPolicy,
+ .GetPciRom = GetPciRom
+};
+
+/**
+
+ The Entry point of the Pci Platform Driver.
+
+ @param ImageHandle Handle to the image.
+ @param SystemTable Handle to System Table.
+
+ @retval EFI_STATUS Status of the function calling.
+
+**/
+EFI_STATUS
+PciPlatformDriverEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE PciPlatformHandle;
+
+ //
+ // Install on a new handle
+ //
+ PciPlatformHandle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &PciPlatformHandle,
+ &gEfiPciPlatformProtocolGuid,
+ &mPciPlatformProtocol,
+ NULL
+ );
+
+ return Status;
+}
--
2.17.1


Re: [PATCH v3 28/28] AmpereAltraPkg: Add configuration screen for Pcie Devices

Leif Lindholm
 

On Wed, Sep 15, 2021 at 22:55:27 +0700, Nhi Pham wrote:
From: Vu Nguyen <vunguyen@os.amperecomputing.com>

This screen provide menu options to configure Max Payload and Max Read
Request size for each PCIe device under Root Port. PCIe devices which
attach to external switch are not supported yet.

Cc: Thang Nguyen <thang@os.amperecomputing.com>
Cc: Chuong Tran <chuong@os.amperecomputing.com>
Cc: Phong Vo <phong@os.amperecomputing.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>

Signed-off-by: Vu Nguyen <vunguyen@os.amperecomputing.com>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>

---
Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec | 3 +
Platform/Ampere/JadePkg/Jade.dsc | 1 +
Platform/Ampere/JadePkg/Jade.fdf | 1 +
Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.inf | 59 ++
Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.h | 78 ++
Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigVfr.h | 56 ++
Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieHelper.h | 58 ++
Silicon/Ampere/AmpereAltraPkg/Include/Guid/PlatformPcieDeviceConfigHii.h | 19 +
Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigVfr.vfr | 50 +
Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.c | 1045 ++++++++++++++++++++
Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieHelper.c | 191 ++++
Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.uni | 24 +
12 files changed, 1585 insertions(+)

diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
index b0e1f3ec6f2a..6ce545fda8dd 100644
--- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
@@ -59,6 +59,9 @@ [Guids]
# GUID for the Watchdog HII configuration form
gWatchdogConfigFormSetGuid = { 0xC3F8EC6E, 0x95EE, 0x460C, { 0xA4, 0x8D, 0xEA, 0x54, 0x2F, 0xFF, 0x01, 0x61 } }

+ # GUID for the Pcie Device HII configuration form
+ gPlatformPcieDeviceConfigFormSetGuid = { 0xEC7B1D21, 0x9167, 0x4B9D, { 0xF7, 0x94, 0xCD, 0x1A, 0xEB, 0xBC, 0xB7, 0x59 } }
+
## NVParam MM GUID
gNVParamMmGuid = { 0xE4AC5024, 0x29BE, 0x4ADC, { 0x93, 0x36, 0x87, 0xB5, 0xA0, 0x76, 0x23, 0x2D } }

diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc
index b752ea3e5264..9db1cf316249 100644
--- a/Platform/Ampere/JadePkg/Jade.dsc
+++ b/Platform/Ampere/JadePkg/Jade.dsc
@@ -202,3 +202,4 @@ [Components.common]
Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf
Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.inf
Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.inf
+ Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.inf
diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf
index 8f3df6ccf01b..ae444d702bbe 100644
--- a/Platform/Ampere/JadePkg/Jade.fdf
+++ b/Platform/Ampere/JadePkg/Jade.fdf
@@ -360,5 +360,6 @@ [FV.FvMain]
INF Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf
INF Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.inf
INF Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.inf
+ INF Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.inf

!include Platform/Ampere/AmperePlatformPkg/FvRules.fdf.inc
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.inf
new file mode 100644
index 000000000000..79d7bd185b7d
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.inf
@@ -0,0 +1,59 @@
+## @file
+#
+# Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = PlatformPcieDeviceConfigDxe
+ FILE_GUID = 17E9369D-0A1B-45F4-A286-B1DED6D85D33
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PlatformPcieDeviceConfigEntryPoint
+
+[Sources.common]
+ PlatformPcieDeviceConfigDxe.c
+ PlatformPcieDeviceConfigDxe.h
+ PlatformPcieDeviceConfigDxe.uni
+ PlatformPcieDeviceConfigVfr.h
+ PlatformPcieDeviceConfigVfr.vfr
+ PlatformPcieHelper.c
+ PlatformPcieHelper.h
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+ Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ HiiLib
+ MemoryAllocationLib
+ PrintLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+ UefiRuntimeServicesTableLib
+
+[Protocols]
+ gEfiPciIoProtocolGuid
+ gEfiDevicePathProtocolGuid ## CONSUMES
+ gEfiHiiConfigRoutingProtocolGuid ## CONSUMES
+ gEfiHiiConfigAccessProtocolGuid ## PRODUCES
+ gEfiDevicePathToTextProtocolGuid
+
+[Guids]
+ gEfiIfrTianoGuid
+ gPlatformPcieDeviceConfigFormSetGuid
+ gPlatformManagerFormsetGuid
+ gPlatformManagerEntryEventGuid
+
+[Depex]
+ TRUE
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.h
new file mode 100644
index 000000000000..a39257da06ba
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.h
@@ -0,0 +1,78 @@
+/** @file
+
+ Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PLATFORM_PCIE_DEVICE_CONFIG_H_
+#define PLATFORM_PCIE_DEVICE_CONFIG_H_
+
+#include <Uefi.h>
+
+#include <Library/HiiLib.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigKeyword.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
+
+#include "PlatformPcieDeviceConfigVfr.h"
+
+#define MAX_STRING_SIZE 100
+
+#define PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'E', 'D', 'C')
+#define PRIVATE_DATA_FROM_THIS(a) \
+ CR (a, PRIVATE_DATA, ConfigAccess, PRIVATE_DATA_SIGNATURE)
+
+#pragma pack(1)
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+#pragma pack()
+
+//
+// This is the generated IFR binary data for each formset defined in VFR.
+// This data array is ready to be used as input of HiiAddPackages() to
+// create a packagelist (which contains Form packages, String packages, etc).
+//
+extern UINT8 PlatformPcieDeviceConfigVfrBin[];
+
+//
+// This is the generated String package data for all .UNI files.
+// This data array is ready to be used as input of HiiAddPackages() to
+// create a packagelist (which contains Form packages, String packages, etc).
+//
+extern UINT8 PlatformPcieDeviceConfigDxeStrings[];
+
+typedef struct {
+ UINTN Signature;
+
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE HiiHandle;
+ VARSTORE_DATA LastVarStoreConfig;
+ VARSTORE_DATA VarStoreConfig;
+
+ //
+ // Consumed protocol
+ //
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
+ EFI_HII_STRING_PROTOCOL *HiiString;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *HiiKeywordHandler;
+ EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
+
+ //
+ // Produced protocol
+ //
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+} PRIVATE_DATA;
+
+#endif // PLATFORM_PCIE_DEVICE_CONFIG_H_
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigVfr.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigVfr.h
new file mode 100644
index 000000000000..ee4469ea5a2a
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigVfr.h
@@ -0,0 +1,56 @@
+/** @file
+
+ Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PLATFORM_PCIE_DEVICE_CONFIG_VFR_H_
+#define PLATFORM_PCIE_DEVICE_CONFIG_VFR_H_
+
+#include <Guid/PlatformPcieDeviceConfigHii.h>
+
+#define VARSTORE_NAME L"PlatformPcieDeviceConfigNVData"
+
+#define MAIN_FORM_ID 0x01
+#define DEVICE_FORM_ID 0x02
+#define VARSTORE_ID 0x03
+
+#define MAIN_LABEL_UPDATE 0x21
+#define MAIN_LABEL_END 0x22
+#define DEVICE_LABEL_UPDATE 0x31
+#define DEVICE_LABEL_END 0x32
+
+#define DEVICE_KEY 0x6000
+#define MPS_ONE_OF_KEY 0x7000
+#define MRR_ONE_OF_KEY 0x8000
+
+#define MAX_DEVICE 40
+
+#define DEFAULT_MPS 0x00 // Section 7.5.3.4
+#define DEFAULT_MRR 0x02 // Section 7.5.3.4
+
+#define PCIE_ADD(Vid, Did, Seg, Bus, Dev) \
+ (UINT64)(Vid) << 40 | (UINT64)(Did) << 24 | Seg << 16 | Bus << 8 | Dev;
+
+#pragma pack(1)
+
+typedef struct {
+ UINT8 DEV;
+ UINT8 BUS;
+ UINT8 SEG;
+ UINT16 DID;
+ UINT16 VID;
+ UINT8 SlotId;
+} SLOT_INFO;
+
+typedef struct {
+ UINT8 MPS[MAX_DEVICE];
+ UINT8 MRR[MAX_DEVICE];
+ UINT64 SlotInfo[MAX_DEVICE];
+} VARSTORE_DATA;
+
+#pragma pack()
+
+#endif /* PLATFORM_PCIE_DEVICE_CONFIG_VFR_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieHelper.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieHelper.h
new file mode 100644
index 000000000000..56aed0379539
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieHelper.h
@@ -0,0 +1,58 @@
+/** @file
+
+ Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PLATFORM_PCIE_HELPER_H_
+#define PLATFORM_PCIE_HELPER_H_
+
+#define PCIE_MAX_PAYLOAD_MASK 0x07
+#define PCIE_CONTROL_MAX_PAYLOAD_OFF 5
+#define PCIE_MAX_READ_REQUEST_MASK 0x07
+#define PCIE_CONTROL_READ_REQUEST_OFF 12
+
+#define PCI_EXPRESS_CAPABILITY_DEVICE_CAPABILITIES_REG 0x04
+#define PCI_EXPRESS_CAPABILITY_DEVICE_CONTROL_REG 0x08
+
+#define FOR_EACH(Node, Tail, Type) \
+ for (Node = Tail->Type; Node != NULL; Node = Node->Type)
+
+struct _PCIE_NODE {
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 MaxMps;
+ UINT8 PcieCapOffset;
+ UINT16 Vid;
+ UINT16 Did;
+ UINT8 Seg;
+ UINT8 Bus;
+ UINT8 Dev;
+ UINT8 Fun;
+ struct _PCIE_NODE *Parent;
+ struct _PCIE_NODE *Brother;
+};
+
+typedef struct _PCIE_NODE PCIE_NODE;
+
+EFI_STATUS
+WriteMps (
+ PCIE_NODE *Node,
+ UINT8 Value
+ );
+
+EFI_STATUS
+WriteMrr (
+ PCIE_NODE *Node,
+ UINT8 Value
+ );
+
+EFI_STATUS
+FindCapabilityPtr (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 CapabilityId,
+ OUT UINT8 *CapabilityPtr
+ );
+
+#endif // PLATFORM_PCIE_HELPER_H_
diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Guid/PlatformPcieDeviceConfigHii.h b/Silicon/Ampere/AmpereAltraPkg/Include/Guid/PlatformPcieDeviceConfigHii.h
new file mode 100644
index 000000000000..ed592a0027ed
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Include/Guid/PlatformPcieDeviceConfigHii.h
@@ -0,0 +1,19 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PLATFORM_PCIE_DEVICE_CONFIG_HII_H_
+#define PLATFORM_PCIE_DEVICE_CONFIG_HII_H_
+
+#define PLATFORM_PCIE_DEVICE_CONFIG_FORMSET_GUID \
+ { \
+ 0xEC7B1D21, 0x9167, 0x4B9D, { 0xF7, 0x94, 0xCD, 0x1A, 0xEB, 0xBC, 0xB7, 0x59 } \
+ }
+
+extern EFI_GUID gPlatformPcieDeviceConfigFormSetGuid;
+
+#endif /* PLATFORM_PCIE_DEVICE_CONFIG_HII_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigVfr.vfr b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigVfr.vfr
new file mode 100644
index 000000000000..27ca33164e23
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigVfr.vfr
@@ -0,0 +1,50 @@
+/** @file
+
+ Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Guid/PlatformManagerHii.h>
+#include "PlatformPcieDeviceConfigVfr.h"
+
+formset
+ guid = PLATFORM_PCIE_DEVICE_CONFIG_FORMSET_GUID,
+ title = STRING_TOKEN(STR_DEVICE_CONFIG_FORM),
+ help = STRING_TOKEN(STR_DEVICE_CONFIG_HELP),
+ classguid = gPlatformManagerFormsetGuid,
+
+ //
+ // Define a variable Storage
+ //
+ varstore VARSTORE_DATA,
+ varid = VARSTORE_ID,
+ name = PlatformPcieDeviceConfigNVData,
+ guid = PLATFORM_PCIE_DEVICE_CONFIG_FORMSET_GUID;
+
+ form
+ formid = MAIN_FORM_ID,
+ title = STRING_TOKEN(STR_DEVICE_CONFIG_FORM);
+
+ subtitle text = STRING_TOKEN(STR_DEVICE_CONFIG_FORM);
+
+ label MAIN_LABEL_UPDATE;
+ // dynamic content here
+ label MAIN_LABEL_END;
+
+ endform;
+
+ form
+ formid = DEVICE_FORM_ID,
+ title = STRING_TOKEN(STR_DEVICE_FORM);
+
+ subtitle text = STRING_TOKEN(STR_DEVICE_FORM);
+
+ label DEVICE_LABEL_UPDATE;
+ // dynamic content here
+ label DEVICE_LABEL_END;
+
+ endform;
+
+endformset;
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.c
new file mode 100644
index 000000000000..b06014529c7b
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.c
@@ -0,0 +1,1045 @@
+/** @file
+
+ Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Guid/MdeModuleHii.h>
+#include <Guid/PlatformPcieDeviceConfigHii.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/PciIo.h>
+
+#include "PlatformPcieDeviceConfigDxe.h"
+#include "PlatformPcieHelper.h"
+
+VOID *mPciProtocolNotifyRegistration;
+CHAR16 *mVariableName = VARSTORE_NAME;
+PCIE_NODE *mDeviceBuf[MAX_DEVICE] = {NULL};
+
+HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ PLATFORM_PCIE_DEVICE_CONFIG_FORMSET_GUID
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8)(END_DEVICE_PATH_LENGTH),
+ (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
+ }
+ }
+};
+
+VOID
+FlushDeviceData (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ PCIE_NODE *Node;
+ PRIVATE_DATA *PrivateData;
+ UINT8 Index;
+ VARSTORE_DATA *LastVarStoreConfig;
+ VARSTORE_DATA *VarStoreConfig;
+
+ PrivateData = (PRIVATE_DATA *)Context;
+ LastVarStoreConfig = &PrivateData->LastVarStoreConfig;
+ VarStoreConfig = &PrivateData->VarStoreConfig;
+
+ //
+ // If config has changed, update NVRAM
+ //
+ if (CompareMem (VarStoreConfig, LastVarStoreConfig, sizeof (VARSTORE_DATA)) != 0) {
+ DEBUG ((DEBUG_INFO, "%a Update Device Config Variable\n", __FUNCTION__));
+ Status = gRT->SetVariable (
+ mVariableName,
+ &gPlatformPcieDeviceConfigFormSetGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (VARSTORE_DATA),
+ VarStoreConfig
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to set variable status %r",
+ __FUNCTION__,
+ Status
+ ));
+ return;
+ }
+ }
+
+ // Iterate through the list, then write corresponding MPS MRR
+ for (Index = 0; Index < MAX_DEVICE; Index++) {
+ if (mDeviceBuf[Index] == NULL) {
+ continue;
+ }
+
+ // Write MPS value
+ WriteMps (mDeviceBuf[Index], VarStoreConfig->MPS[Index]);
+
+ FOR_EACH (Node, mDeviceBuf[Index], Parent) {
+ WriteMps (Node, VarStoreConfig->MPS[Index]);
+ }
+
+ FOR_EACH (Node, mDeviceBuf[Index], Brother) {
+ WriteMps (Node, VarStoreConfig->MPS[Index]);
+ }
+
+ // Write MRR value
+ // No need to update MRR of parent node
+ WriteMrr (mDeviceBuf[Index], VarStoreConfig->MRR[Index]);
+
+ FOR_EACH (Node, mDeviceBuf[Index], Brother) {
+ WriteMrr (Node, VarStoreConfig->MRR[Index]);
+ }
+ }
+
+ gBS->CloseEvent (Event);
+}
+
+EFI_STATUS
+UpdateDeviceForm (
+ UINT8 Index,
+ PRIVATE_DATA *PrivateData
+ )
+{
+ CHAR16 Str[MAX_STRING_SIZE];
+ UINT8 MaxMps;
+
+ VOID *StartOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *EndLabel;
+ VOID *MpsOpCodeHandle;
+ VOID *MrrOpCodeHandle;
+ PCIE_NODE *Node;
+
+ if (mDeviceBuf[Index] == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MaxMps = mDeviceBuf[Index]->MaxMps;
+ FOR_EACH (Node, mDeviceBuf[Index], Parent) {
+ if (Node->MaxMps < MaxMps) {
+ MaxMps = Node->MaxMps;
+ }
+ }
+
+ UnicodeSPrint (
+ Str,
+ sizeof (Str),
+ L"PCIe Device 0x%04x:0x%04x",
+ mDeviceBuf[Index]->Vid,
+ mDeviceBuf[Index]->Did
+ );
+
+ HiiSetString (
+ PrivateData->HiiHandle,
+ STRING_TOKEN (STR_DEVICE_FORM),
+ Str,
+ NULL
+ );
+
+ //
+ // Initialize the container for dynamic opcodes
+ //
+ StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (StartOpCodeHandle != NULL);
+
+ EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (EndOpCodeHandle != NULL);
+
+ //
+ // Create Hii Extend Label OpCode as the start opcode
+ //
+ StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
+ StartOpCodeHandle,
+ &gEfiIfrTianoGuid,
+ NULL,
+ sizeof (EFI_IFR_GUID_LABEL)
+ );
+ StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ StartLabel->Number = DEVICE_LABEL_UPDATE;
+
+ //
+ // Create Hii Extend Label OpCode as the end opcode
+ //
+ EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
+ EndOpCodeHandle,
+ &gEfiIfrTianoGuid,
+ NULL,
+ sizeof (EFI_IFR_GUID_LABEL)
+ );
+ EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ EndLabel->Number = DEVICE_LABEL_END;
+
+ // Create Option OpCode for MPS selection
+ MpsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (MpsOpCodeHandle != NULL);
+
+ switch (MaxMps) {
+ case 5:
+ HiiCreateOneOfOptionOpCode (
+ MpsOpCodeHandle,
+ STRING_TOKEN (STR_4096),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 5
+ );
+
+ case 4:
+ HiiCreateOneOfOptionOpCode (
+ MpsOpCodeHandle,
+ STRING_TOKEN (STR_2048),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 4
+ );
+
+ case 3:
+ HiiCreateOneOfOptionOpCode (
+ MpsOpCodeHandle,
+ STRING_TOKEN (STR_1024),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 3
+ );
+
+ case 2:
+ HiiCreateOneOfOptionOpCode (
+ MpsOpCodeHandle,
+ STRING_TOKEN (STR_512),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 2
+ );
+
+ case 1:
+ HiiCreateOneOfOptionOpCode (
+ MpsOpCodeHandle,
+ STRING_TOKEN (STR_256),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 1
+ );
+
+ case 0:
+ HiiCreateOneOfOptionOpCode (
+ MpsOpCodeHandle,
+ STRING_TOKEN (STR_128),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 0
+ );
+ }
+
+ // Create MPS OneOf
+ HiiCreateOneOfOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ (MPS_ONE_OF_KEY + Index), // Question ID (or call it "key")
+ VARSTORE_ID, // VarStore ID
+ Index, // Offset in Buffer Storage
+ STRING_TOKEN (STR_PCIE_MPS), // Question prompt text
+ STRING_TOKEN (STR_PCIE_MPS_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value
+ MpsOpCodeHandle, // Option Opcode list
+ NULL // Default Opcode is NULl
+ );
+
+ // Create Option OpCode for MRR selection
+ MrrOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (MrrOpCodeHandle != NULL);
+
+ HiiCreateOneOfOptionOpCode (
+ MrrOpCodeHandle,
+ STRING_TOKEN (STR_4096),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 5
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ MrrOpCodeHandle,
+ STRING_TOKEN (STR_2048),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 4
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ MrrOpCodeHandle,
+ STRING_TOKEN (STR_1024),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 3
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ MrrOpCodeHandle,
+ STRING_TOKEN (STR_512),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 2
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ MrrOpCodeHandle,
+ STRING_TOKEN (STR_256),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 1
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ MrrOpCodeHandle,
+ STRING_TOKEN (STR_128),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 0
+ );
+
+ // Create MRR OneOf
+ HiiCreateOneOfOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ (MRR_ONE_OF_KEY + Index), // Question ID (or call it "key")
+ VARSTORE_ID, // VarStore ID
+ MAX_DEVICE + Index, // Offset in Buffer Storage
+ STRING_TOKEN (STR_PCIE_MRR), // Question prompt text
+ STRING_TOKEN (STR_PCIE_MRR_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value
+ MrrOpCodeHandle, // Option Opcode list
+ NULL // Default Opcode is NULl
+ );
+
+ HiiUpdateForm (
+ PrivateData->HiiHandle, // HII handle
+ &gPlatformPcieDeviceConfigFormSetGuid, // Formset GUID
+ DEVICE_FORM_ID, // Form ID
+ StartOpCodeHandle, // Label for where to insert opcodes
+ EndOpCodeHandle // Insert data
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+ HiiFreeOpCodeHandle (MpsOpCodeHandle);
+ HiiFreeOpCodeHandle (MrrOpCodeHandle);
+ return EFI_SUCCESS;
+}
+
+VOID
+OnPciIoProtocolNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+ EFI_HANDLE HandleBuffer;
+ PCI_TYPE00 Pci;
+
+ UINTN BufferSize;
+ UINTN PciBusNumber;
+ UINTN PciDeviceNumber;
+ UINTN PciFunctionNumber;
+ UINTN PciSegment;
+
+ UINT8 Idx;
+ UINT8 CapabilityPtr;
+ UINT16 TmpValue;
+ UINT64 SlotInfo;
+
+ PCIE_NODE *Node;
+ PRIVATE_DATA *PrivateData;
+ STATIC PCIE_NODE *LastNode;
+ STATIC UINT8 Index;
+ STATIC UINT8 LastBus;
+
+ VARSTORE_DATA *LastVarStoreConfig;
+ VARSTORE_DATA *VarStoreConfig;
+
+ PrivateData = (PRIVATE_DATA *)Context;
+ LastVarStoreConfig = &PrivateData->LastVarStoreConfig;
+ VarStoreConfig = &PrivateData->VarStoreConfig;
+
+ while (TRUE) {
+ BufferSize = sizeof (EFI_HANDLE);
+ Status = gBS->LocateHandle (
+ ByRegisterNotify,
+ NULL,
+ mPciProtocolNotifyRegistration,
+ &BufferSize,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ Status = gBS->HandleProtocol (
+ HandleBuffer,
+ &gEfiPciIoProtocolGuid,
+ (VOID **)&PciIo
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ // Get device bus location
+ Status = PciIo->GetLocation (
+ PciIo,
+ &PciSegment,
+ &PciBusNumber,
+ &PciDeviceNumber,
+ &PciFunctionNumber
+ );
+ if (EFI_ERROR (Status) ||
+ ((PciBusNumber == 0) && (PciDeviceNumber == 0)))
+ {
+ // Filter out Host Bridge
+ DEBUG ((DEBUG_INFO, "Filter out Host Bridge %x\n", PciSegment));
+ continue;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ ">> Dev 0x%04x:0x%02x:0x%02x:0x%02x\n",
+ PciSegment,
+ PciBusNumber,
+ PciDeviceNumber,
+ PciFunctionNumber
+ ));
+
+ Status = FindCapabilityPtr (PciIo, EFI_PCI_CAPABILITY_ID_PCIEXP, &CapabilityPtr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: PCI Express Capability not found\n",
+ __FUNCTION__
+ ));
+ continue;
+ }
+
+ // Get Device's max MPS support
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ CapabilityPtr + PCI_EXPRESS_CAPABILITY_DEVICE_CAPABILITIES_REG,
+ 1,
+ &TmpValue
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ // Read device's VID:PID
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ DEBUG ((
+ DEBUG_INFO,
+ "VendorId 0x%04x - DeviceId 0x%04x\n",
+ Pci.Hdr.VendorId,
+ Pci.Hdr.DeviceId
+ ));
+
+ Node = AllocateZeroPool (sizeof (*Node));
+ Node->MaxMps = TmpValue & PCIE_MAX_PAYLOAD_MASK;
+ Node->PcieCapOffset = CapabilityPtr;
+ Node->PciIo = PciIo;
+ Node->Seg = PciSegment;
+ Node->Bus = PciBusNumber;
+ Node->Dev = PciDeviceNumber;
+ Node->Fun = PciFunctionNumber;
+ Node->Vid = Pci.Hdr.VendorId;
+ Node->Did = Pci.Hdr.DeviceId;
+ SlotInfo = PCIE_ADD (Node->Vid, Node->Did, Node->Seg, Node->Bus, Node->Dev);
+
+ // Presume child devices were registered follow root port
+ if (PciBusNumber != 0) {
+ if (LastBus == 0) {
+ Node->Parent = LastNode;
+ mDeviceBuf[Index] = Node;
+
+ VarStoreConfig->MPS[Index] = DEFAULT_MPS;
+ VarStoreConfig->MRR[Index] = DEFAULT_MRR;
+ VarStoreConfig->SlotInfo[Index] = SlotInfo;
+
+ // Retrieve setting from previous variable
+ for (Idx = 0; Idx < MAX_DEVICE; Idx++) {
+ if (SlotInfo == LastVarStoreConfig->SlotInfo[Idx]) {
+ VarStoreConfig->MPS[Index] = LastVarStoreConfig->MPS[Idx];
+ VarStoreConfig->MRR[Index] = LastVarStoreConfig->MRR[Idx];
+ break;
+ }
+ }
+
+ Index++;
+ } else if (PciBusNumber == LastBus) {
+ LastNode->Brother = Node;
+ } else {
+ // Ignore devices don't stay under root port
+ continue;
+ }
+ }
+
+ LastBus = PciBusNumber;
+ LastNode = Node;
+ }
+}
+
+VOID
+UpdateMainForm (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN Index;
+ EFI_STRING_ID StrId;
+ CHAR16 Str[MAX_STRING_SIZE];
+ VOID *StartOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *EndLabel;
+ PRIVATE_DATA *PrivateData;
+
+ DEBUG ((DEBUG_INFO, "%a Entry ...\n", __FUNCTION__));
+
+ PrivateData = (PRIVATE_DATA *)Context;
+
+ //
+ // Initialize the container for dynamic opcodes
+ //
+ StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (StartOpCodeHandle != NULL);
+
+ EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (EndOpCodeHandle != NULL);
+
+ //
+ // Create Hii Extend Label OpCode as the start opcode
+ //
+ StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
+ StartOpCodeHandle,
+ &gEfiIfrTianoGuid,
+ NULL,
+ sizeof (EFI_IFR_GUID_LABEL)
+ );
+ StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ StartLabel->Number = MAIN_LABEL_UPDATE;
+
+ //
+ // Create Hii Extend Label OpCode as the end opcode
+ //
+ EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
+ EndOpCodeHandle,
+ &gEfiIfrTianoGuid,
+ NULL,
+ sizeof (EFI_IFR_GUID_LABEL)
+ );
+ EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ EndLabel->Number = MAIN_LABEL_END;
+
+ for (Index = 0; Index < MAX_DEVICE; Index++) {
+ if (mDeviceBuf[Index] == NULL) {
+ break;
+ }
+ DEBUG ((DEBUG_INFO, ">> Add item %d\n", Index));
+
+ UnicodeSPrint (
+ Str,
+ sizeof (Str),
+ L"PCIe Device 0x%04x:0x%04x - %04x:%02x:%02x",
+ mDeviceBuf[Index]->Vid,
+ mDeviceBuf[Index]->Did,
+ mDeviceBuf[Index]->Seg,
+ mDeviceBuf[Index]->Bus,
+ mDeviceBuf[Index]->Dev
+ );
+
+ StrId = HiiSetString (PrivateData->HiiHandle, 0, Str, NULL);
+
+ //
+ // Create a Goto OpCode to device configuration
+ //
+ HiiCreateGotoOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ DEVICE_FORM_ID, // Target Form ID
+ StrId, // Prompt text
+ STRING_TOKEN (STR_DEVICE_GOTO_HELP), // Help text
+ EFI_IFR_FLAG_CALLBACK, // Question flag
+ (DEVICE_KEY + Index) // Question ID
+ );
+ }
+
+ HiiUpdateForm (
+ PrivateData->HiiHandle, // HII handle
+ &gPlatformPcieDeviceConfigFormSetGuid, // Formset GUID
+ MAIN_FORM_ID, // Form ID
+ StartOpCodeHandle, // Label for where to insert opcodes
+ EndOpCodeHandle // Insert data
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+
+ gBS->CloseEvent (Event);
+}
+
+EFI_STATUS
+EFIAPI
+ExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ EFI_STRING ConfigRequest;
+ EFI_STRING ConfigRequestHdr;
+ UINTN Size;
+ CHAR16 *StrPointer;
+ BOOLEAN AllocatedRequest;
+ VARSTORE_DATA *VarStoreConfig;
+
+ if (Progress == NULL || Results == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Initialize the local variables.
+ //
+ ConfigRequestHdr = NULL;
+ ConfigRequest = NULL;
+ Size = 0;
+ *Progress = Request;
+ AllocatedRequest = FALSE;
+
+ PrivateData = PRIVATE_DATA_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+ VarStoreConfig = &PrivateData->VarStoreConfig;
+ ASSERT (VarStoreConfig != NULL);
+
+ BufferSize = sizeof (VARSTORE_DATA);
+
+ if (Request == NULL) {
+ //
+ // Request is set to NULL, construct full request string.
+ //
+
+ //
+ // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+ // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a
+ // Null-terminator
+ //
+ ConfigRequestHdr = HiiConstructConfigHdr (
+ &gPlatformPcieDeviceConfigFormSetGuid,
+ mVariableName,
+ PrivateData->DriverHandle
+ );
+ if (ConfigRequestHdr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
+ ConfigRequest = AllocateZeroPool (Size);
+ ASSERT (ConfigRequest != NULL);
+ AllocatedRequest = TRUE;
+ UnicodeSPrint (
+ ConfigRequest,
+ Size,
+ L"%s&OFFSET=0&WIDTH=%016LX",
+ ConfigRequestHdr,
+ (UINT64)BufferSize
+ );
+ FreePool (ConfigRequestHdr);
+ ConfigRequestHdr = NULL;
+ } else {
+ //
+ // Check routing data in <ConfigHdr>.
+ // Note: if only one Storage is used, then this checking could be skipped.
+ //
+ if (!HiiIsConfigHdrMatch (Request, &gPlatformPcieDeviceConfigFormSetGuid, NULL)) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Set Request to the unified request string.
+ //
+ ConfigRequest = Request;
+
+ //
+ // Check whether Request includes Request Element.
+ //
+ if (StrStr (Request, L"OFFSET") == NULL) {
+ //
+ // Check Request Element does exist in Request String
+ //
+ StrPointer = StrStr (Request, L"PATH");
+ if (StrPointer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (StrStr (StrPointer, L"&") == NULL) {
+ Size = (StrLen (Request) + 32 + 1) * sizeof (CHAR16);
+ ConfigRequest = AllocateZeroPool (Size);
+ ASSERT (ConfigRequest != NULL);
+ AllocatedRequest = TRUE;
+ UnicodeSPrint (
+ ConfigRequest,
+ Size,
+ L"%s&OFFSET=0&WIDTH=%016LX",
+ Request,
+ (UINT64)BufferSize
+ );
+ }
+ }
+ }
+ //
+ // Check if requesting Name/Value storage
+ //
+ if (StrStr (ConfigRequest, L"OFFSET") == NULL) {
+ //
+ // Don't have any Name/Value storage names
+ //
+ Status = EFI_SUCCESS;
+ } else {
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ Status = HiiConfigRouting->BlockToConfig (
+ HiiConfigRouting,
+ ConfigRequest,
+ (UINT8 *)VarStoreConfig,
+ BufferSize,
+ Results,
+ Progress
+ );
+ }
+ //
+ // Free the allocated config request string.
+ //
+ if (AllocatedRequest) {
+ FreePool (ConfigRequest);
+ }
+ if (ConfigRequestHdr != NULL) {
+ FreePool (ConfigRequestHdr);
+ }
+ //
+ // Set Progress string to the original request string.
+ //
+ if (Request == NULL) {
+ *Progress = NULL;
+ } else if (StrStr (Request, L"OFFSET") == NULL) {
+ *Progress = Request + StrLen (Request);
+ }
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Configuration A null-terminated Unicode string in <ConfigResp>
+ format.
+ @param Progress A pointer to a string filled in with the offset of
+ the most recent '&' before the first failing
+ name/value pair (or the beginning of the string if
+ the failure is in the first name/value pair) or
+ the terminating NULL if all was successful.
+ @retval EFI_SUCCESS The Results is processed successfully.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+**/
+EFI_STATUS
+EFIAPI
+RouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ VARSTORE_DATA *VarStoreConfig;
+
+ if (Configuration == NULL || Progress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PrivateData = PRIVATE_DATA_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+ *Progress = Configuration;
+ VarStoreConfig = &PrivateData->VarStoreConfig;
+ ASSERT (VarStoreConfig != NULL);
+
+ //
+ // Check routing data in <ConfigHdr>.
+ // Note: if only one Storage is used, then this checking could be skipped.
+ //
+ if (!HiiIsConfigHdrMatch (
+ Configuration,
+ &gPlatformPcieDeviceConfigFormSetGuid,
+ NULL
+ ))
+ {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Check if configuring Name/Value storage
+ //
+ if (StrStr (Configuration, L"OFFSET") == NULL) {
+ //
+ // Don't have any Name/Value storage names
+ //
+ return EFI_SUCCESS;
+ }
+ //
+ // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
+ //
+ BufferSize = sizeof (VARSTORE_DATA);
+ Status = HiiConfigRouting->ConfigToBlock (
+ HiiConfigRouting,
+ Configuration,
+ (UINT8 *)VarStoreConfig,
+ &BufferSize,
+ Progress
+ );
+
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Action Specifies the type of action taken by the browser.
+ @param QuestionId A unique value which is sent to the original
+ exporting driver so that it can identify the type
+ of data to expect.
+ @param Type The type of value for the question.
+ @param Value A pointer to the data being sent to the original
+ exporting driver.
+ @param ActionRequest On return, points to the action requested by the
+ callback function.
+ @retval EFI_SUCCESS The callback successfully handled the action.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_UNSUPPORTED The specified Action is not supported by the
+ callback.
+**/
+EFI_STATUS
+EFIAPI
+DriverCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+{
+ EFI_STATUS Status;
+ PRIVATE_DATA *PrivateData;
+
+ if (((Value == NULL) &&
+ (Action != EFI_BROWSER_ACTION_FORM_OPEN) &&
+ (Action != EFI_BROWSER_ACTION_FORM_CLOSE)) ||
+ (ActionRequest == NULL))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = PRIVATE_DATA_FROM_THIS (This);
+
+ switch (Action) {
+ case EFI_BROWSER_ACTION_CHANGING:
+ if ((QuestionId >= DEVICE_KEY)
+ & (QuestionId <= (DEVICE_KEY + MAX_DEVICE)))
+ {
+ Status = UpdateDeviceForm (QuestionId - DEVICE_KEY, PrivateData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ break;
+
+ case EFI_BROWSER_ACTION_DEFAULT_STANDARD:
+ case EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING:
+ if ((QuestionId >= MPS_ONE_OF_KEY)
+ & (QuestionId <= (MPS_ONE_OF_KEY + MAX_DEVICE)))
+ {
+ Value->u8 = DEFAULT_MPS;
+ }
+
+ if ((QuestionId >= MRR_ONE_OF_KEY)
+ & (QuestionId <= (MRR_ONE_OF_KEY + MAX_DEVICE)))
+ {
+ Value->u8 = DEFAULT_MRR;
+ }
+ break;
+
+ case EFI_BROWSER_ACTION_SUBMITTED:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PlatformPcieDeviceConfigEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_HANDLE DriverHandle;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_STATUS Status;
+ EFI_EVENT PlatformUiEntryEvent;
+ EFI_EVENT FlushDeviceEvent;
+ EFI_EVENT PciProtocolNotifyEvent;
+ PRIVATE_DATA *PrivateData;
+ UINTN BufferSize;
+
+ DriverHandle = NULL;
+ PrivateData = AllocateZeroPool (sizeof (*PrivateData));
+ if (PrivateData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ PrivateData->Signature = PRIVATE_DATA_SIGNATURE;
+
+ PrivateData->ConfigAccess.ExtractConfig = ExtractConfig;
+ PrivateData->ConfigAccess.RouteConfig = RouteConfig;
+ PrivateData->ConfigAccess.Callback = DriverCallback;
+
+ //
+ // Locate ConfigRouting protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiConfigRoutingProtocolGuid,
+ NULL,
+ (VOID **)&HiiConfigRouting
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ PrivateData->HiiConfigRouting = HiiConfigRouting;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &PrivateData->ConfigAccess,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ PrivateData->DriverHandle = DriverHandle;
+
+ //
+ // Publish our HII data
+ //
+ HiiHandle = HiiAddPackages (
+ &gPlatformPcieDeviceConfigFormSetGuid,
+ DriverHandle,
+ PlatformPcieDeviceConfigDxeStrings,
+ PlatformPcieDeviceConfigVfrBin,
+ NULL
+ );
+ if (HiiHandle == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ PrivateData->HiiHandle = HiiHandle;
+
+ // Event to fixup screen
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ UpdateMainForm,
+ (VOID *)PrivateData,
+ &gPlatformManagerEntryEventGuid,
+ &PlatformUiEntryEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ // Event to collect PciIo
+ PciProtocolNotifyEvent = EfiCreateProtocolNotifyEvent (
+ &gEfiPciIoProtocolGuid,
+ TPL_CALLBACK,
+ OnPciIoProtocolNotify,
+ (VOID *)PrivateData,
+ &mPciProtocolNotifyRegistration
+ );
+ ASSERT (PciProtocolNotifyEvent != NULL);
+
+ // Event to flush device data
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ FlushDeviceData,
+ (VOID *)PrivateData,
+ &gEfiEventReadyToBootGuid,
+ &FlushDeviceEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ // Verify varstore
+ BufferSize = sizeof (VARSTORE_DATA);
+ Status = gRT->GetVariable (
+ mVariableName,
+ &gPlatformPcieDeviceConfigFormSetGuid,
+ NULL,
+ &BufferSize,
+ &PrivateData->LastVarStoreConfig
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Last config is not found\n", __FUNCTION__));
+ }
+
+ return EFI_SUCCESS;
+
+Exit:
+ FreePool (PrivateData);
+ return Status;
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieHelper.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieHelper.c
new file mode 100644
index 000000000000..6bd753ef327f
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieHelper.c
@@ -0,0 +1,191 @@
+/** @file
+
+ Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <IndustryStandard/Pci.h>
+#include <Protocol/PciIo.h>
+
+#include "PlatformPcieDeviceConfigDxe.h"
+#include "PlatformPcieHelper.h"
+
+EFI_STATUS
+FindCapabilityPtr (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 CapabilityId,
+ OUT UINT8 *CapabilityPtr
+ )
+{
+ EFI_STATUS Status;
+ UINT8 NextPtr;
+ UINT16 TmpValue;
+
+ ASSERT (PciIo != NULL);
+
+ //
+ // Get pointer to first PCI Capability header
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_CAPBILITY_POINTER_OFFSET,
+ 1,
+ &NextPtr
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ while (TRUE) {
+ if (NextPtr == 0x00) {
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+
+ //
+ // Retrieve PCI Capability header
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ NextPtr,
+ 1,
+ &TmpValue
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ if ((TmpValue & 0xFF) == CapabilityId) {
+ *CapabilityPtr = NextPtr;
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+
+ NextPtr = (TmpValue >> 8) & 0xFF;
+ }
+
+Exit:
+ return Status;
+}
+
+EFI_STATUS
+WriteMps (
+ PCIE_NODE *Node,
+ UINT8 Value
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+ UINT16 TmpValue;
+ UINT8 PcieCapOffset;
+
+ if (Node == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PciIo = Node->PciIo;
+ PcieCapOffset = Node->PcieCapOffset;
+
+ // Get current device control reg
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ PcieCapOffset + PCI_EXPRESS_CAPABILITY_DEVICE_CONTROL_REG,
+ 1,
+ &TmpValue
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Update value and write to device
+ TmpValue = (TmpValue & ~(PCIE_MAX_PAYLOAD_MASK << PCIE_CONTROL_MAX_PAYLOAD_OFF))
+ | Value << PCIE_CONTROL_MAX_PAYLOAD_OFF;
+ Status = PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ PcieCapOffset + PCI_EXPRESS_CAPABILITY_DEVICE_CONTROL_REG,
+ 1,
+ &TmpValue
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: Write MPS %d to device 0x%04x:0x%02x:0x%02x:0x%02x\n",
+ __FUNCTION__,
+ Value,
+ Node->Seg,
+ Node->Bus,
+ Node->Dev,
+ Node->Fun
+ ));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+WriteMrr (
+ PCIE_NODE *Node,
+ UINT8 Value
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+ UINT16 TmpValue;
+ UINT8 PcieCapOffset;
+
+ if (Node == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PciIo = Node->PciIo;
+ PcieCapOffset = Node->PcieCapOffset;
+
+ // Get current device control reg
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ PcieCapOffset + PCI_EXPRESS_CAPABILITY_DEVICE_CONTROL_REG,
+ 1,
+ &TmpValue
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Update value and write to device
+ TmpValue = (TmpValue & ~(PCIE_MAX_READ_REQUEST_MASK << PCIE_CONTROL_READ_REQUEST_OFF))
+ | Value << PCIE_CONTROL_READ_REQUEST_OFF;
+ Status = PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ PcieCapOffset + PCI_EXPRESS_CAPABILITY_DEVICE_CONTROL_REG,
+ 1,
+ &TmpValue
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: Write MRR %d to device 0x%04x:0x%02x:0x%02x:0x%02x\n",
+ __FUNCTION__,
+ Value,
+ Node->Seg,
+ Node->Bus,
+ Node->Dev,
+ Node->Fun
+ ));
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.uni b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.uni
new file mode 100644
index 000000000000..f6cd94ffee36
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformPcieDeviceConfigDxe/PlatformPcieDeviceConfigDxe.uni
@@ -0,0 +1,24 @@
+//
+// Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+#langdef en-US "English" // English
+
+#string STR_DEVICE_CONFIG_FORM #language en-US "PCIE Device Configuration"
+#string STR_DEVICE_CONFIG_HELP #language en-US "PCIE Device Configuration"
+
+#string STR_DEVICE_FORM #language en-US "PCIE Device Form"
+#string STR_DEVICE_GOTO_HELP #language en-US "PCIE Device Configuration"
+
+#string STR_PCIE_MPS #language en-US "Max Payload Size"
+#string STR_PCIE_MPS_HELP #language en-US "Max Payload Size"
+#string STR_PCIE_MRR #language en-US "Max Read Request Size"
+#string STR_PCIE_MRR_HELP #language en-US "Max Read Request Size"
+#string STR_128 #language en-US "128 bytes"
+#string STR_256 #language en-US "256 bytes"
+#string STR_512 #language en-US "512 bytes"
+#string STR_1024 #language en-US "1024 bytes"
+#string STR_2048 #language en-US "2048 bytes"
+#string STR_4096 #language en-US "4096 bytes"
--
2.17.1


Re: [PATCH v3 27/28] AmpereAltraPkg: Add configuration screen for Watchdog timer

Leif Lindholm
 

On Wed, Sep 15, 2021 at 22:55:26 +0700, Nhi Pham wrote:
From: Vu Nguyen <vunguyen@os.amperecomputing.com>

There are secure and non-secure watchdog timers supported in the Mt.
Jade system. They are used to monitor the system booting like system
firmware, UEFI, and OS. The system will be reset if the timer expires.
So, this patch adds the configuration screen for the watchdog timer
which provides options to configure the timeout of these timers.

By default, the values of these options are 5 minutes.

Cc: Thang Nguyen <thang@os.amperecomputing.com>
Cc: Chuong Tran <chuong@os.amperecomputing.com>
Cc: Phong Vo <phong@os.amperecomputing.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>

Signed-off-by: Vu Nguyen <vunguyen@os.amperecomputing.com>
---
Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec | 3 +
Platform/Ampere/JadePkg/Jade.dsc | 1 +
Platform/Ampere/JadePkg/Jade.fdf | 1 +
Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.inf | 50 +++
Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.h | 82 ++++
Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigNVDataStruct.h | 27 ++
Silicon/Ampere/AmpereAltraPkg/Include/Guid/WatchdogConfigHii.h | 19 +
Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigVfr.vfr | 58 +++
Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.c | 460 ++++++++++++++++++++
Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigStrings.uni | 26 ++
10 files changed, 727 insertions(+)

diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
index 196611d67280..b0e1f3ec6f2a 100644
--- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
@@ -56,6 +56,9 @@ [Guids]
# GUID for the ACPI HII configuration form
gAcpiConfigFormSetGuid = { 0x0ceb6764, 0xd415, 0x4b01, { 0xa8, 0x43, 0xd1, 0x01, 0xbc, 0xb0, 0xd8, 0x29 } }

+ # GUID for the Watchdog HII configuration form
+ gWatchdogConfigFormSetGuid = { 0xC3F8EC6E, 0x95EE, 0x460C, { 0xA4, 0x8D, 0xEA, 0x54, 0x2F, 0xFF, 0x01, 0x61 } }
+
## NVParam MM GUID
gNVParamMmGuid = { 0xE4AC5024, 0x29BE, 0x4ADC, { 0x93, 0x36, 0x87, 0xB5, 0xA0, 0x76, 0x23, 0x2D } }

diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc
index b5ac2547c8f8..b752ea3e5264 100644
--- a/Platform/Ampere/JadePkg/Jade.dsc
+++ b/Platform/Ampere/JadePkg/Jade.dsc
@@ -201,3 +201,4 @@ [Components.common]
Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.inf
Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf
Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.inf
+ Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.inf
diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf
index e0d4b049f6bf..8f3df6ccf01b 100644
--- a/Platform/Ampere/JadePkg/Jade.fdf
+++ b/Platform/Ampere/JadePkg/Jade.fdf
@@ -359,5 +359,6 @@ [FV.FvMain]
INF Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.inf
INF Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf
INF Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.inf
+ INF Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.inf

!include Platform/Ampere/AmperePlatformPkg/FvRules.fdf.inc
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.inf
new file mode 100644
index 000000000000..3ed37bfb15da
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.inf
@@ -0,0 +1,50 @@
+## @file
+#
+# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = WatchdogConfigDxe
+ FILE_GUID = 135A0CA5-4851-4EF5-9E1A-C6E4610C39A9
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = WatchdogConfigInitialize
+
+[Sources.common]
+ WatchdogConfigNVDataStruct.h
+ WatchdogConfigVfr.vfr
+ WatchdogConfigStrings.uni
+ WatchdogConfigDxe.c
+ WatchdogConfigDxe.h
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+ Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ DevicePathLib
+ HiiLib
+ NVParamLib
+ PrintLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Guids]
+ gPlatformManagerFormsetGuid
+ gWatchdogConfigFormSetGuid
+
+[Protocols]
+ gEfiDevicePathProtocolGuid ## CONSUMES
+ gEfiHiiConfigRoutingProtocolGuid ## CONSUMES
+ gEfiHiiConfigAccessProtocolGuid ## PRODUCES
+
+[Depex]
+ TRUE
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.h
new file mode 100644
index 000000000000..5f47531c538e
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.h
@@ -0,0 +1,82 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef WATCHDOG_CONFIG_DXE_H_
+#define WATCHDOG_CONFIG_DXE_H_
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NVParamLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <NVParamDef.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigRouting.h>
Should only include files actually required here.

/
Leif

+
+#include "WatchdogConfigNVDataStruct.h"
+
+//
+// This is the generated IFR binary data for each formset defined in VFR.
+//
+extern UINT8 WatchdogConfigVfrBin[];
+
+//
+// This is the generated String package data for all .UNI files.
+//
+extern UINT8 WatchdogConfigDxeStrings[];
+
+#define WATCHDOG_CONFIG_PRIVATE_SIGNATURE SIGNATURE_32 ('W', 'D', 'T', 'C')
+
+typedef struct {
+ UINTN Signature;
+
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE HiiHandle;
+ WATCHDOG_CONFIG_VARSTORE_DATA Configuration;
+
+ //
+ // Consumed protocol
+ //
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ //
+ // Produced protocol
+ //
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+} WATCHDOG_CONFIG_PRIVATE_DATA;
+
+#define WATCHDOG_CONFIG_PRIVATE_FROM_THIS(a) CR (a, WATCHDOG_CONFIG_PRIVATE_DATA, ConfigAccess, WATCHDOG_CONFIG_PRIVATE_SIGNATURE)
+
+#pragma pack(1)
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+#pragma pack()
+
+EFI_STATUS
+WatchdogConfigNvParamSet (
+ IN WATCHDOG_CONFIG_VARSTORE_DATA *VarStoreConfig
+ );
+
+EFI_STATUS
+WatchdogConfigNvParamGet (
+ OUT WATCHDOG_CONFIG_VARSTORE_DATA *VarStoreConfig
+ );
+
+#endif /* WATCHDOG_CONFIG_DXE_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigNVDataStruct.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigNVDataStruct.h
new file mode 100644
index 000000000000..470a2821ffe7
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigNVDataStruct.h
@@ -0,0 +1,27 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef WATCHDOG_CONFIG_NV_DATA_STRUCT_H_
+#define WATCHDOG_CONFIG_NV_DATA_STRUCT_H_
+
+#include <Guid/WatchdogConfigHii.h>
+
+#define WATCHDOG_CONFIG_VARSTORE_ID 0x1234
+#define WATCHDOG_CONFIG_FORM_ID 0x1235
+
+#define NWDT_UEFI_DEFAULT_VALUE 300 // 5 minutes
+#define SWDT_DEFAULT_VALUE 300 // 5 minutes
+
+#pragma pack(1)
+typedef struct {
+ UINT32 WatchdogTimerUEFITimeout;
+ UINT32 SecureWatchdogTimerTimeout;
+} WATCHDOG_CONFIG_VARSTORE_DATA;
+#pragma pack()
+
+#endif /* WATCHDOG_CONFIG_NV_DATA_STRUCT_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Guid/WatchdogConfigHii.h b/Silicon/Ampere/AmpereAltraPkg/Include/Guid/WatchdogConfigHii.h
new file mode 100644
index 000000000000..16319d61a759
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Include/Guid/WatchdogConfigHii.h
@@ -0,0 +1,19 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef WATCHDOG_CONFIG_HII_H_
+#define WATCHDOG_CONFIG_HII_H_
+
+#define WATCHDOG_CONFIG_FORMSET_GUID \
+ { \
+ 0xC3F8EC6E, 0x95EE, 0x460C, { 0xA4, 0x8D, 0xEA, 0x54, 0x2F, 0xFF, 0x01, 0x61 } \
+ }
+
+extern EFI_GUID gWatchdogConfigFormSetGuid;
+
+#endif /* WATCHDOG_CONFIG_HII_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigVfr.vfr b/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigVfr.vfr
new file mode 100644
index 000000000000..48f2aef227f6
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigVfr.vfr
@@ -0,0 +1,58 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "WatchdogConfigNVDataStruct.h"
+
+formset
+ guid = WATCHDOG_CONFIG_FORMSET_GUID,
+ title = STRING_TOKEN(STR_WATCHDOG_CONFIG_FORM),
+ help = STRING_TOKEN(STR_WATCHDOG_CONFIG_FORM_HELP),
+ classguid = gPlatformManagerFormsetGuid,
+
+ //
+ // Define a variable Storage
+ //
+ varstore WATCHDOG_CONFIG_VARSTORE_DATA,
+ varid = WATCHDOG_CONFIG_VARSTORE_ID,
+ name = WatchdogConfigNVData,
+ guid = WATCHDOG_CONFIG_FORMSET_GUID;
+
+ form
+ formid = WATCHDOG_CONFIG_FORM_ID,
+ title = STRING_TOKEN(STR_WATCHDOG_CONFIG_FORM);
+ subtitle text = STRING_TOKEN(STR_WATCHDOG_CONFIG_FORM_HELP);
+
+ oneof varid = WatchdogConfigNVData.WatchdogTimerUEFITimeout,
+ prompt = STRING_TOKEN(STR_NWDT_TIMEOUT_UEFI),
+ help = STRING_TOKEN(STR_NWDT_TIMEOUT_UEFI_HELP),
+ flags = RESET_REQUIRED,
+ option text = STRING_TOKEN (STR_WDT_TIME_DISABLE), value = 0, flags = 0;
+ option text = STRING_TOKEN (STR_WDT_TIME_5MIN), value = 300, flags = 0;
+ option text = STRING_TOKEN (STR_WDT_TIME_6MIN), value = 360, flags = 0;
+ option text = STRING_TOKEN (STR_WDT_TIME_10MIN), value = 600, flags = 0;
+ option text = STRING_TOKEN (STR_WDT_TIME_15MIN), value = 900, flags = 0;
+ option text = STRING_TOKEN (STR_WDT_TIME_20MIN), value = 1200, flags = 0;
+ default = NWDT_UEFI_DEFAULT_VALUE,
+ endoneof;
+
+ oneof varid = WatchdogConfigNVData.SecureWatchdogTimerTimeout,
+ prompt = STRING_TOKEN(STR_SWDT_TIMEOUT),
+ help = STRING_TOKEN(STR_SWDT_TIMEOUT_HELP),
+ flags = RESET_REQUIRED,
+ option text = STRING_TOKEN (STR_WDT_TIME_DISABLE), value = 0, flags = 0;
+ option text = STRING_TOKEN (STR_WDT_TIME_5MIN), value = 300, flags = 0;
+ option text = STRING_TOKEN (STR_WDT_TIME_6MIN), value = 360, flags = 0;
+ option text = STRING_TOKEN (STR_WDT_TIME_10MIN), value = 600, flags = 0;
+ option text = STRING_TOKEN (STR_WDT_TIME_15MIN), value = 900, flags = 0;
+ option text = STRING_TOKEN (STR_WDT_TIME_20MIN), value = 1200, flags = 0;
+ default = SWDT_DEFAULT_VALUE,
+ endoneof;
+
+ endform;
+
+endformset;
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.c
new file mode 100644
index 000000000000..bd7b929dccda
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.c
@@ -0,0 +1,460 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "WatchdogConfigDxe.h"
+
+CHAR16 WatchDogConfigVarstoreDataName[] = L"WatchdogConfigNVData";
+
+EFI_HANDLE mDriverHandle = NULL;
+WATCHDOG_CONFIG_PRIVATE_DATA *mPrivateData = NULL;
+
+HII_VENDOR_DEVICE_PATH mWatchdogConfigHiiVendorDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ WATCHDOG_CONFIG_FORMSET_GUID
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8)(END_DEVICE_PATH_LENGTH),
+ (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
+ }
+ }
+};
+
+EFI_STATUS
+WatchdogConfigNvParamGet (
+ OUT WATCHDOG_CONFIG_VARSTORE_DATA *VarStoreConfig
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Value;
+ BOOLEAN SetDefault;
+
+ SetDefault = FALSE;
+ Status = NVParamGet (
+ NV_SI_WDT_BIOS_EXP_MINS,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ VarStoreConfig->WatchdogTimerUEFITimeout = NWDT_UEFI_DEFAULT_VALUE;
+ if (Status == EFI_NOT_FOUND) {
+ SetDefault = TRUE;
+ } else {
+ ASSERT (FALSE);
+ }
+ } else {
+ VarStoreConfig->WatchdogTimerUEFITimeout = Value * 60;
+ }
+
+ Status = NVParamGet (
+ NV_SI_SEC_WDT_BIOS_EXP_MINS,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ VarStoreConfig->SecureWatchdogTimerTimeout = SWDT_DEFAULT_VALUE;
+ if (Status == EFI_NOT_FOUND) {
+ SetDefault = TRUE;
+ } else {
+ ASSERT (FALSE);
+ }
+ } else {
+ VarStoreConfig->SecureWatchdogTimerTimeout = Value;
+ }
+
+ if (SetDefault) {
+ WatchdogConfigNvParamSet (VarStoreConfig);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+WatchdogConfigNvParamSet (
+ IN WATCHDOG_CONFIG_VARSTORE_DATA *VarStoreConfig
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Value;
+
+ Status = NVParamGet (
+ NV_SI_WDT_BIOS_EXP_MINS,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)
+ || Value != (VarStoreConfig->WatchdogTimerUEFITimeout / 60))
+ {
+ Status = NVParamSet (
+ NV_SI_WDT_BIOS_EXP_MINS,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ (VarStoreConfig->WatchdogTimerUEFITimeout / 60)
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ Status = NVParamGet (
+ NV_SI_SEC_WDT_BIOS_EXP_MINS,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)
+ || Value != VarStoreConfig->SecureWatchdogTimerTimeout)
+ {
+ Status = NVParamSet (
+ NV_SI_SEC_WDT_BIOS_EXP_MINS,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ VarStoreConfig->SecureWatchdogTimerTimeout
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function allows a caller to extract the current configuration for one
+ or more named elements from the target driver.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Request A null-terminated Unicode string in
+ <ConfigRequest> format.
+ @param Progress On return, points to a character in the Request
+ string. Points to the string's null terminator if
+ request was successful. Points to the most recent
+ '&' before the first failing name/value pair (or
+ the beginning of the string if the failure is in
+ the first name/value pair) if the request was not
+ successful.
+ @param Results A null-terminated Unicode string in
+ <ConfigAltResp> format which has all values filled
+ in for the names in the Request string. String to
+ be allocated by the called function.
+
+ @retval EFI_SUCCESS The Results is filled with the requested values.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
+ @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+
+**/
+EFI_STATUS
+EFIAPI
+WatchdogConfigExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ WATCHDOG_CONFIG_PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ EFI_STRING ConfigRequest;
+ EFI_STRING ConfigRequestHdr;
+ UINTN Size;
+ BOOLEAN AllocatedRequest;
+
+ if (Progress == NULL || Results == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Initialize the local variables.
+ //
+ ConfigRequestHdr = NULL;
+ ConfigRequest = NULL;
+ Size = 0;
+ *Progress = Request;
+ AllocatedRequest = FALSE;
+
+ if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gWatchdogConfigFormSetGuid, WatchDogConfigVarstoreDataName)) {
+ return EFI_NOT_FOUND;
+ }
+
+ PrivateData = WATCHDOG_CONFIG_PRIVATE_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+
+ //
+ // Get current setting from NVParam.
+ //
+ Status = WatchdogConfigNvParamGet (&PrivateData->Configuration);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ BufferSize = sizeof (WATCHDOG_CONFIG_VARSTORE_DATA);
+ ConfigRequest = Request;
+ if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
+ //
+ // Request has no request element, construct full request string.
+ // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+ // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
+ //
+ ConfigRequestHdr = HiiConstructConfigHdr (&gWatchdogConfigFormSetGuid, WatchDogConfigVarstoreDataName, PrivateData->DriverHandle);
+ Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
+ ConfigRequest = AllocateZeroPool (Size);
+ ASSERT (ConfigRequest != NULL);
+ if (ConfigRequest == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ AllocatedRequest = TRUE;
+ UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
+ FreePool (ConfigRequestHdr);
+ }
+
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ Status = HiiConfigRouting->BlockToConfig (
+ HiiConfigRouting,
+ ConfigRequest,
+ (UINT8 *)&PrivateData->Configuration,
+ BufferSize,
+ Results,
+ Progress
+ );
+
+ //
+ // Free the allocated config request string.
+ //
+ if (AllocatedRequest) {
+ FreePool (ConfigRequest);
+ ConfigRequest = NULL;
+ }
+
+ //
+ // Set Progress string to the original request string.
+ //
+ if (Request == NULL) {
+ *Progress = NULL;
+ } else if (StrStr (Request, L"OFFSET") == NULL) {
+ *Progress = Request + StrLen (Request);
+ }
+
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Configuration A null-terminated Unicode string in <ConfigResp>
+ format.
+ @param Progress A pointer to a string filled in with the offset of
+ the most recent '&' before the first failing
+ name/value pair (or the beginning of the string if
+ the failure is in the first name/value pair) or
+ the terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The Results is processed successfully.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+
+**/
+EFI_STATUS
+EFIAPI
+WatchdogConfigRouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ WATCHDOG_CONFIG_PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ if (Configuration == NULL || Progress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = WATCHDOG_CONFIG_PRIVATE_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+ *Progress = Configuration;
+
+ //
+ // Check routing data in <ConfigHdr>.
+ // Note: if only one Storage is used, then this checking could be skipped.
+ //
+ if (!HiiIsConfigHdrMatch (Configuration, &gWatchdogConfigFormSetGuid, WatchDogConfigVarstoreDataName)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get configuration data from NVParam
+ //
+ Status = WatchdogConfigNvParamGet (&PrivateData->Configuration);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
+ //
+ BufferSize = sizeof (WATCHDOG_CONFIG_VARSTORE_DATA);
+ Status = HiiConfigRouting->ConfigToBlock (
+ HiiConfigRouting,
+ Configuration,
+ (UINT8 *)&PrivateData->Configuration,
+ &BufferSize,
+ Progress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Store configuration data back to NVParam
+ //
+ Status = WatchdogConfigNvParamSet (&PrivateData->Configuration);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Action Specifies the type of action taken by the browser.
+ @param QuestionId A unique value which is sent to the original
+ exporting driver so that it can identify the type
+ of data to expect.
+ @param Type The type of value for the question.
+ @param Value A pointer to the data being sent to the original
+ exporting driver.
+ @param ActionRequest On return, points to the action requested by the
+ callback function.
+
+ @retval EFI_SUCCESS The callback successfully handled the action.
+ @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
+
+**/
+EFI_STATUS
+EFIAPI
+WatchdogConfigCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+{
+ if (Action != EFI_BROWSER_ACTION_CHANGING) {
+ //
+ // Do nothing for other UEFI Action. Only do call back when data is changed.
+ //
+ return EFI_UNSUPPORTED;
+ }
+ if (((Value == NULL)
+ && (Action != EFI_BROWSER_ACTION_FORM_OPEN)
+ && (Action != EFI_BROWSER_ACTION_FORM_CLOSE))
+ || (ActionRequest == NULL))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+WatchdogConfigInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ //
+ // Initialize driver private data
+ //
+ mPrivateData = AllocateZeroPool (sizeof (WATCHDOG_CONFIG_PRIVATE_DATA));
+ if (mPrivateData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mPrivateData->Signature = WATCHDOG_CONFIG_PRIVATE_SIGNATURE;
+
+ mPrivateData->ConfigAccess.ExtractConfig = WatchdogConfigExtractConfig;
+ mPrivateData->ConfigAccess.RouteConfig = WatchdogConfigRouteConfig;
+ mPrivateData->ConfigAccess.Callback = WatchdogConfigCallback;
+
+ //
+ // Locate ConfigRouting protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&HiiConfigRouting);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mPrivateData->HiiConfigRouting = HiiConfigRouting;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mDriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mWatchdogConfigHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mPrivateData->ConfigAccess,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ mPrivateData->DriverHandle = mDriverHandle;
+
+ //
+ // Publish our HII data
+ //
+ HiiHandle = HiiAddPackages (
+ &gWatchdogConfigFormSetGuid,
+ mDriverHandle,
+ WatchdogConfigDxeStrings,
+ WatchdogConfigVfrBin,
+ NULL
+ );
+ if (HiiHandle == NULL) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ mDriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mWatchdogConfigHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mPrivateData->ConfigAccess,
+ NULL
+ );
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mPrivateData->HiiHandle = HiiHandle;
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigStrings.uni b/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigStrings.uni
new file mode 100644
index 000000000000..1d0f820e456f
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigStrings.uni
@@ -0,0 +1,26 @@
+//
+// Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+#langdef en-US "English"
+
+#string STR_WATCHDOG_CONFIG_FORM #language en-US "Watchdog Configuration"
+#string STR_WATCHDOG_CONFIG_FORM_HELP #language en-US "Watchdog Configuration"
+
+#string STR_WDT_TIME_DISABLE #language en-US "Disabled"
+#string STR_WDT_TIME_3MIN #language en-US "3 minutes"
+#string STR_WDT_TIME_4MIN #language en-US "4 minutes"
+#string STR_WDT_TIME_5MIN #language en-US "5 minutes"
+#string STR_WDT_TIME_6MIN #language en-US "6 minutes"
+#string STR_WDT_TIME_10MIN #language en-US "10 minutes"
+#string STR_WDT_TIME_15MIN #language en-US "15 minutes"
+#string STR_WDT_TIME_20MIN #language en-US "20 minutes"
+
+#string STR_NWDT_TIMEOUT_OS #language en-US "OS Watchdog Timeout"
+#string STR_NWDT_TIMEOUT_OS_HELP #language en-US "Timeout when boot OS."
+#string STR_NWDT_TIMEOUT_UEFI #language en-US "UEFI Watchdog Timeout"
+#string STR_NWDT_TIMEOUT_UEFI_HELP #language en-US "Timeout when boot UEFI"
+#string STR_SWDT_TIMEOUT #language en-US "Secure Watchdog Timeout"
+#string STR_SWDT_TIMEOUT_HELP #language en-US "Timeout when SCP will reset system if it doesn't receive response from ARMv8."
--
2.17.1


Re: [PATCH v3 26/28] AmpereAltraPkg: Add configuration screen for RAS

Leif Lindholm
 

On Wed, Sep 15, 2021 at 22:55:25 +0700, Nhi Pham wrote:
From: Quan Nguyen <quan@os.amperecomputing.com>

This supports user to enable/disable RAS APEI components running in the
system firmware such as HEST, BERT, and EINJ.

Cc: Thang Nguyen <thang@os.amperecomputing.com>
Cc: Chuong Tran <chuong@os.amperecomputing.com>
Cc: Phong Vo <phong@os.amperecomputing.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>

Signed-off-by: Quan Nguyen <quan@os.amperecomputing.com>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>

---
Platform/Ampere/JadePkg/Jade.dsc | 1 +
Platform/Ampere/JadePkg/Jade.fdf | 1 +
Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.inf | 56 ++
Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.h | 61 ++
Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigNVDataStruct.h | 46 ++
Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigVfr.vfr | 95 +++
Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.c | 822 ++++++++++++++++++++
Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigStrings.uni | 38 +
8 files changed, 1120 insertions(+)

diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc
index daac52e84ea2..b5ac2547c8f8 100644
--- a/Platform/Ampere/JadePkg/Jade.dsc
+++ b/Platform/Ampere/JadePkg/Jade.dsc
@@ -200,3 +200,4 @@ [Components.common]
Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.inf
Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf
+ Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.inf
diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf
index 1564e45c30cd..e0d4b049f6bf 100644
--- a/Platform/Ampere/JadePkg/Jade.fdf
+++ b/Platform/Ampere/JadePkg/Jade.fdf
@@ -358,5 +358,6 @@ [FV.FvMain]
INF Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
INF Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.inf
INF Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf
+ INF Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.inf

!include Platform/Ampere/AmperePlatformPkg/FvRules.fdf.inc
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.inf
new file mode 100644
index 000000000000..9b03ed57944f
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.inf
@@ -0,0 +1,56 @@
+## @file
+#
+# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = RasConfigDxe
+ FILE_GUID = 5b5ee6e3-3135-45f7-ad21-46a3f36813cc
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RasConfigEntryPoint
+
+[Sources.common]
+ RasConfigNVDataStruct.h
+ RasConfigDxe.c
+ RasConfigDxe.h
+ RasConfigVfr.vfr
+ RasConfigStrings.uni
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+ Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
+
+[LibraryClasses]
+ AmpereCpuLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ DevicePathLib
+ HiiLib
+ MemoryAllocationLib
+ NVParamLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+ UefiRuntimeServicesTableLib
+
+[Guids]
+ gEfiIfrTianoGuid
+ gPlatformManagerFormsetGuid
+ gAcpiConfigFormSetGuid
+
+[Protocols]
+ gEfiDevicePathProtocolGuid ## CONSUMES
+ gEfiHiiConfigRoutingProtocolGuid ## CONSUMES
+ gEfiHiiConfigAccessProtocolGuid ## PRODUCES
+
+[Depex]
+ TRUE
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.h
new file mode 100644
index 000000000000..1258fbeda6a1
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.h
@@ -0,0 +1,61 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef RAS_CONFIG_DXE_H_
+#define RAS_CONFIG_DXE_H_
+
+#include "RasConfigNVDataStruct.h"
+
+//
+// This is the generated IFR binary data for each formset defined in VFR.
+//
+extern UINT8 RasConfigVfrBin[];
+
+//
+// This is the generated String package data for all .UNI files.
+//
+extern UINT8 RasConfigDxeStrings[];
+
+#define RAS_DDR_CE_THRESHOLD_OFST OFFSET_OF (RAS_CONFIG_VARSTORE_DATA, RasDdrCeThreshold)
+#define RAS_2P_CE_THRESHOLD_OFST OFFSET_OF (RAS_CONFIG_VARSTORE_DATA, Ras2pCeThreshold)
+
+#define RAS_CONFIG_PRIVATE_SIGNATURE SIGNATURE_32 ('R', 'A', 'S', 'C')
+
+typedef struct {
+ UINTN Signature;
+
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE HiiHandle;
+ RAS_CONFIG_VARSTORE_DATA Configuration;
+
+ //
+ // Consumed protocol
+ //
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ //
+ // Produced protocol
+ //
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+} RAS_CONFIG_PRIVATE_DATA;
+
+#define RAS_CONFIG_PRIVATE_FROM_THIS(a) CR (a, RAS_CONFIG_PRIVATE_DATA, ConfigAccess, RAS_CONFIG_PRIVATE_SIGNATURE)
+
+#pragma pack(1)
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+#pragma pack()
+
+#endif /* RAS_CONFIG_DXE_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigNVDataStruct.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigNVDataStruct.h
new file mode 100644
index 000000000000..8c528f043c27
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigNVDataStruct.h
@@ -0,0 +1,46 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef RAS_CONFIG_NV_DATA_STRUCT_H_
+#define RAS_CONFIG_NV_DATA_STRUCT_H_
+
+#define RAS_CONFIG_VARSTORE_ID 0x1234
+#define RAS_CONFIG_FORM_ID 0x1235
+
+#define RAS_VARSTORE_NAME L"RasConfigNVData"
+
+#define RAS_CONFIG_FORMSET_GUID \
+ { \
+ 0x96934cc6, 0xcb15, 0x4d8a, { 0xbe, 0x5f, 0x8e, 0x7d, 0x55, 0x0e, 0xc9, 0xc6 } \
+ }
+
+//
+// Labels definition
+//
+#define LABEL_UPDATE 0x3234
+#define LABEL_END 0xffff
+
+#pragma pack(1)
+
+//
+// Ras Configuration NV data structure definition
+//
+typedef struct {
+ UINT32 RasHardwareEinj;
+ UINT32 RasPcieAerFwFirstEnabled;
+ UINT32 RasBertEnabled;
+ UINT32 RasSdeiEnabled;
+ UINT32 RasDdrCeThreshold;
+ UINT32 Ras2pCeThreshold;
+ UINT32 RasCpmCeThreshold;
+ UINT32 RasLinkErrThreshold;
+} RAS_CONFIG_VARSTORE_DATA;
+
+#pragma pack()
+
+#endif /* RAS_CONFIG_NV_DATA_STRUCT_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigVfr.vfr b/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigVfr.vfr
new file mode 100644
index 000000000000..ec38eb186c1b
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigVfr.vfr
@@ -0,0 +1,95 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RasConfigNVDataStruct.h"
+
+formset
+ guid = RAS_CONFIG_FORMSET_GUID,
+ title = STRING_TOKEN(STR_RAS_FORM),
+ help = STRING_TOKEN(STR_RAS_FORM_HELP),
+ classguid = gPlatformManagerFormsetGuid,
+
+ //
+ // Define a variable Storage
+ //
+ varstore RAS_CONFIG_VARSTORE_DATA,
+ varid = RAS_CONFIG_VARSTORE_ID,
+ name = RasConfigNVData,
+ guid = RAS_CONFIG_FORMSET_GUID;
+
+ form formid = RAS_CONFIG_FORM_ID,
+ title = STRING_TOKEN(STR_RAS_FORM);
+
+ subtitle text = STRING_TOKEN(STR_RAS_FORM);
+
+ oneof varid = RasConfigNVData.RasHardwareEinj,
+ prompt = STRING_TOKEN(STR_RAS_HARDWARE_EINJ_PROMPT),
+ help = STRING_TOKEN(STR_RAS_HARDWARE_EINJ_HELP),
+ flags = NUMERIC_SIZE_4 | RESET_REQUIRED,
+ option text = STRING_TOKEN(STR_RAS_COMMON_ENABLE), value = 1, flags = DEFAULT;
+ option text = STRING_TOKEN(STR_RAS_COMMON_DISABLE), value = 0, flags = 0;
+
+ endoneof;
+
+ oneof varid = RasConfigNVData.RasPcieAerFwFirstEnabled,
+ prompt = STRING_TOKEN(STR_RAS_PCIE_AER_FW_FIRST_PROMPT),
+ help = STRING_TOKEN(STR_RAS_PCIE_AER_FW_FIRST_HELP),
+ flags = NUMERIC_SIZE_4 | RESET_REQUIRED,
+ option text = STRING_TOKEN(STR_RAS_COMMON_ENABLE), value = 1, flags = 0;
+ option text = STRING_TOKEN(STR_RAS_COMMON_DISABLE), value = 0, flags = DEFAULT;
+
+ endoneof;
+
+ oneof varid = RasConfigNVData.RasBertEnabled,
+ prompt = STRING_TOKEN(STR_RAS_BERT_ENABLED_PROMPT),
+ help = STRING_TOKEN(STR_RAS_BERT_ENABLED_HELP),
+ flags = NUMERIC_SIZE_4 | RESET_REQUIRED,
+ option text = STRING_TOKEN(STR_RAS_COMMON_ENABLE), value = 1, flags = DEFAULT;
+ option text = STRING_TOKEN(STR_RAS_COMMON_DISABLE), value = 0, flags = 0;
+
+ endoneof;
+
+ oneof varid = RasConfigNVData.RasSdeiEnabled,
+ prompt = STRING_TOKEN(STR_RAS_SDEI_ENABLED_PROMPT),
+ help = STRING_TOKEN(STR_RAS_SDEI_ENABLED_HELP),
+ flags = NUMERIC_SIZE_4 | RESET_REQUIRED,
+ option text = STRING_TOKEN(STR_RAS_COMMON_ENABLE), value = 1, flags = 0;
+ option text = STRING_TOKEN(STR_RAS_COMMON_DISABLE), value = 0, flags = DEFAULT;
+
+ endoneof;
+
+ label LABEL_UPDATE;
+ //
+ // This is where we will dynamically add other Action type op-code
+ //
+ label LABEL_END;
+
+ numeric varid = RasConfigNVData.RasCpmCeThreshold,
+ prompt = STRING_TOKEN(STR_RAS_CPM_CE_THRESHOLD_PROMPT),
+ help = STRING_TOKEN(STR_RAS_CPM_CE_THRESHOLD_HELP),
+ flags = NUMERIC_SIZE_4 | RESET_REQUIRED,
+ minimum = 1,
+ maximum = 8192,
+ default = 1,
+
+ endnumeric;
+
+ numeric varid = RasConfigNVData.RasLinkErrThreshold,
+ prompt = STRING_TOKEN(STR_RAS_LINK_ERR_THRESHOLD_PROMPT),
+ help = STRING_TOKEN(STR_RAS_LINK_ERR_THRESHOLD_HELP),
+ flags = NUMERIC_SIZE_4 | RESET_REQUIRED,
+ minimum = 1,
+ maximum = 8192,
+ default = 1,
+
+ endnumeric;
+
+
+ endform;
+
+endformset;
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.c
new file mode 100644
index 000000000000..41554775a0b4
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.c
@@ -0,0 +1,822 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Guid/MdeModuleHii.h>
+#include <Library/AmpereCpuLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NVParamLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <NVParamDef.h>
+#include <PlatformInfoHob.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigRouting.h>
+
+#include "RasConfigDxe.h"
+
+CHAR16 RasConfigVarstoreDataName[] = L"RasConfigNVData";
+
+EFI_HANDLE mDriverHandle = NULL;
+RAS_CONFIG_PRIVATE_DATA *mPrivateData = NULL;
+
+EFI_GUID mRasConfigFormSetGuid = RAS_CONFIG_FORMSET_GUID;
+
+//
+// Default RAS Settings
+//
+#define RAS_DEFAULT_HARDWARE_EINJ_SUPPORT 0
+#define RAS_DEFAULT_PCIE_AER_FW_FIRST 0
+#define RAS_DEFAULT_BERT_SUPPORT 1
+#define RAS_DEFAULT_SDEI_SUPPORT 0
+#define RAS_DEFAULT_DDR_CE_THRESHOLD 1
+#define RAS_DEFAULT_2P_CE_THRESHOLD 1
+#define RAS_DEFAULT_PROCESSOR_CE_THRESHOLD 1
+#define RAS_DEFAULT_DDR_LINK_ERROR_THRESHOLD 1
+
+
+HII_VENDOR_DEVICE_PATH mRasConfigHiiVendorDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ RAS_CONFIG_FORMSET_GUID
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8)(END_DEVICE_PATH_LENGTH),
+ (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
+ }
+ }
+};
+
+BOOLEAN
+IsDdrCeWindowEnabled (
+ VOID
+ )
+{
+ UINT32 DdrCeWindow;
+ EFI_STATUS Status;
+
+ Status = NVParamGet (
+ NV_SI_RO_BOARD_RAS_DDR_CE_WINDOW,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &DdrCeWindow
+ );
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ return (DdrCeWindow != 0) ? TRUE : FALSE;
+}
+
+EFI_STATUS
+RasConfigNvParamGet (
+ OUT RAS_CONFIG_VARSTORE_DATA *Configuration
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Value;
+
+ Status = NVParamGet (
+ NV_SI_HARDWARE_EINJ,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ Value = RAS_DEFAULT_HARDWARE_EINJ_SUPPORT;
+ Status = NVParamSet (
+ NV_SI_HARDWARE_EINJ,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Value
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:%d NVParamSet() failed!\n", __FUNCTION__, __LINE__));
+ ASSERT_EFI_ERROR (Status);
+ Value = 0;
+ }
+ }
+ Configuration->RasHardwareEinj = Value;
+
+ Status = NVParamGet (
+ NV_SI_RAS_PCIE_AER_FW_FIRST,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ Value = RAS_DEFAULT_PCIE_AER_FW_FIRST;
+ Status = NVParamSet (
+ NV_SI_RAS_PCIE_AER_FW_FIRST,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Value
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:%d NVParamSet() failed!\n", __FUNCTION__, __LINE__));
+ ASSERT_EFI_ERROR (Status);
+ Value = 0;
+ }
+ }
+ Configuration->RasPcieAerFwFirstEnabled = Value;
+
+ Status = NVParamGet (
+ NV_SI_RAS_BERT_ENABLED,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ Value = RAS_DEFAULT_BERT_SUPPORT;
+ Status = NVParamSet (
+ NV_SI_RAS_BERT_ENABLED,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Value
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:%d NVParamSet() failed!\n", __FUNCTION__, __LINE__));
+ ASSERT_EFI_ERROR (Status);
+ Value = 0;
+ }
+ }
+ Configuration->RasBertEnabled = Value;
+
+ Status = NVParamGet (
+ NV_SI_RAS_SDEI_ENABLED,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ Value = RAS_DEFAULT_SDEI_SUPPORT;
+ Status = NVParamSet (
+ NV_SI_RAS_SDEI_ENABLED,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Value
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:%d NVParamSet() failed!\n", __FUNCTION__, __LINE__));
+ ASSERT_EFI_ERROR (Status);
+ Value = 0;
+ }
+ }
+ Configuration->RasSdeiEnabled = Value;
+
+ Status = NVParamGet (
+ NV_SI_DDR_CE_RAS_THRESHOLD,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ Value = RAS_DEFAULT_DDR_CE_THRESHOLD;
+ Status = NVParamSet (
+ NV_SI_DDR_CE_RAS_THRESHOLD,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Value
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:%d NVParamSet() failed!\n", __FUNCTION__, __LINE__));
+ ASSERT_EFI_ERROR (Status);
+ Value = 0;
+ }
+ }
+ Configuration->RasDdrCeThreshold = Value;
+
+ Status = NVParamGet (
+ NV_SI_2P_CE_RAS_THRESHOLD,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ Value = RAS_DEFAULT_2P_CE_THRESHOLD;
+ Status = NVParamSet (
+ NV_SI_2P_CE_RAS_THRESHOLD,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Value
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:%d NVParamSet() failed!\n", __FUNCTION__, __LINE__));
+ ASSERT_EFI_ERROR (Status);
+ Value = 0;
+ }
+ }
+ Configuration->Ras2pCeThreshold = Value;
+
+ Status = NVParamGet (
+ NV_SI_CPM_CE_RAS_THRESHOLD,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ Value = RAS_DEFAULT_PROCESSOR_CE_THRESHOLD;
+ Status = NVParamSet (
+ NV_SI_CPM_CE_RAS_THRESHOLD,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Value
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:%d NVParamSet() failed!\n", __FUNCTION__, __LINE__));
+ ASSERT_EFI_ERROR (Status);
+ Value = 0;
+ }
+ }
+ Configuration->RasCpmCeThreshold = Value;
+
+ Status = NVParamGet (
+ NV_SI_LINK_ERR_THRESHOLD,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ Value = RAS_DEFAULT_DDR_LINK_ERROR_THRESHOLD;
+ Status = NVParamSet (
+ NV_SI_LINK_ERR_THRESHOLD,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Value
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:%d NVParamSet() failed!\n", __FUNCTION__, __LINE__));
+ ASSERT_EFI_ERROR (Status);
+ Value = 0;
+ }
+ }
+ Configuration->RasLinkErrThreshold = Value;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RasConfigNvParamSet (
+ IN RAS_CONFIG_VARSTORE_DATA *Configuration
+ )
+{
+ EFI_STATUS Status;
+
+ Status = NVParamSet (
+ NV_SI_HARDWARE_EINJ,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Configuration->RasHardwareEinj
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = NVParamSet (
+ NV_SI_RAS_PCIE_AER_FW_FIRST,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Configuration->RasPcieAerFwFirstEnabled
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = NVParamSet (
+ NV_SI_RAS_BERT_ENABLED,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Configuration->RasBertEnabled
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = NVParamSet (
+ NV_SI_RAS_SDEI_ENABLED,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Configuration->RasSdeiEnabled
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = NVParamSet (
+ NV_SI_DDR_CE_RAS_THRESHOLD,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Configuration->RasDdrCeThreshold
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = NVParamSet (
+ NV_SI_2P_CE_RAS_THRESHOLD,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Configuration->Ras2pCeThreshold
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = NVParamSet (
+ NV_SI_CPM_CE_RAS_THRESHOLD,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Configuration->RasCpmCeThreshold
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = NVParamSet (
+ NV_SI_LINK_ERR_THRESHOLD,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Configuration->RasLinkErrThreshold
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function allows a caller to extract the current configuration for one
+ or more named elements from the target driver.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Request A null-terminated Unicode string in
+ <ConfigRequest> format.
+ @param Progress On return, points to a character in the Request
+ string. Points to the string's null terminator if
+ request was successful. Points to the most recent
+ '&' before the first failing name/value pair (or
+ the beginning of the string if the failure is in
+ the first name/value pair) if the request was not
+ successful.
+ @param Results A null-terminated Unicode string in
+ <ConfigAltResp> format which has all values filled
+ in for the names in the Request string. String to
+ be allocated by the called function.
+
+ @retval EFI_SUCCESS The Results is filled with the requested values.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
+ @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+
+**/
+EFI_STATUS
+EFIAPI
+RasConfigExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ RAS_CONFIG_PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ EFI_STRING ConfigRequest;
+ EFI_STRING ConfigRequestHdr;
+ UINTN Size;
+ BOOLEAN AllocatedRequest;
+
+ if (Progress == NULL || Results == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Initialize the local variables.
+ //
+ ConfigRequestHdr = NULL;
+ ConfigRequest = NULL;
+ Size = 0;
+ *Progress = Request;
+ AllocatedRequest = FALSE;
+
+ if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mRasConfigFormSetGuid, RasConfigVarstoreDataName)) {
+ return EFI_NOT_FOUND;
+ }
+
+ PrivateData = RAS_CONFIG_PRIVATE_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+
+ //
+ // Get current setting from NVParam.
+ //
+ Status = RasConfigNvParamGet (&PrivateData->Configuration);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ BufferSize = sizeof (RAS_CONFIG_VARSTORE_DATA);
+ ConfigRequest = Request;
+ if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
+ //
+ // Request has no request element, construct full request string.
+ // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+ // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
+ //
+ ConfigRequestHdr = HiiConstructConfigHdr (&mRasConfigFormSetGuid, RasConfigVarstoreDataName, PrivateData->DriverHandle);
+ Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
+ ConfigRequest = AllocateZeroPool (Size);
+ ASSERT (ConfigRequest != NULL);
+ if (ConfigRequest == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ AllocatedRequest = TRUE;
+ UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
+ FreePool (ConfigRequestHdr);
+ }
+
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ Status = HiiConfigRouting->BlockToConfig (
+ HiiConfigRouting,
+ ConfigRequest,
+ (UINT8 *)&PrivateData->Configuration,
+ BufferSize,
+ Results,
+ Progress
+ );
+
+ //
+ // Free the allocated config request string.
+ //
+ if (AllocatedRequest) {
+ FreePool (ConfigRequest);
+ ConfigRequest = NULL;
+ }
+
+ //
+ // Set Progress string to the original request string.
+ //
+ if (Request == NULL) {
+ *Progress = NULL;
+ } else if (StrStr (Request, L"OFFSET") == NULL) {
+ *Progress = Request + StrLen (Request);
+ }
+
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Configuration A null-terminated Unicode string in <ConfigResp>
+ format.
+ @param Progress A pointer to a string filled in with the offset of
+ the most recent '&' before the first failing
+ name/value pair (or the beginning of the string if
+ the failure is in the first name/value pair) or
+ the terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The Results is processed successfully.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+
+**/
+EFI_STATUS
+EFIAPI
+RasConfigRouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ RAS_CONFIG_PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ if (Configuration == NULL || Progress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = RAS_CONFIG_PRIVATE_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+ *Progress = Configuration;
+
+ //
+ // Check routing data in <ConfigHdr>.
+ // Note: if only one Storage is used, then this checking could be skipped.
+ //
+ if (!HiiIsConfigHdrMatch (Configuration, &mRasConfigFormSetGuid, RasConfigVarstoreDataName)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get configuration data from NVParam
+ //
+ Status = RasConfigNvParamGet (&PrivateData->Configuration);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
+ //
+ BufferSize = sizeof (RAS_CONFIG_VARSTORE_DATA);
+ Status = HiiConfigRouting->ConfigToBlock (
+ HiiConfigRouting,
+ Configuration,
+ (UINT8 *)&PrivateData->Configuration,
+ &BufferSize,
+ Progress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Store configuration data back to NVParam
+ //
+ Status = RasConfigNvParamSet (&PrivateData->Configuration);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Action Specifies the type of action taken by the browser.
+ @param QuestionId A unique value which is sent to the original
+ exporting driver so that it can identify the type
+ of data to expect.
+ @param Type The type of value for the question.
+ @param Value A pointer to the data being sent to the original
+ exporting driver.
+ @param ActionRequest On return, points to the action requested by the
+ callback function.
+
+ @retval EFI_SUCCESS The callback successfully handled the action.
+ @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
+
+**/
+EFI_STATUS
+EFIAPI
+RasConfigCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+{
+ if (Action != EFI_BROWSER_ACTION_CHANGING) {
+ //
+ // Do nothing for other UEFI Action. Only do call back when data is changed.
+ //
+ return EFI_UNSUPPORTED;
+ }
+ if (((Value == NULL)
+ && (Action != EFI_BROWSER_ACTION_FORM_OPEN)
+ && (Action != EFI_BROWSER_ACTION_FORM_CLOSE))
+ || (ActionRequest == NULL))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpdateRasConfigScreen (
+ IN RAS_CONFIG_PRIVATE_DATA *PrivateData
+ )
+{
+ EFI_STATUS Status;
+ VOID *StartOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *EndLabel;
+
+ //
+ // Initialize the container for dynamic opcodes
+ //
+ StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (StartOpCodeHandle != NULL);
+
+ EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (EndOpCodeHandle != NULL);
+
+ //
+ // Create Hii Extend Label OpCode as the start opcode
+ //
+ StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
+ StartOpCodeHandle,
+ &gEfiIfrTianoGuid,
+ NULL,
+ sizeof (EFI_IFR_GUID_LABEL)
+ );
+ if (StartLabel == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeOpCodeBuffer;
+ }
+ StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ StartLabel->Number = LABEL_UPDATE;
+
+ //
+ // Create Hii Extend Label OpCode as the end opcode
+ //
+ EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
+ EndOpCodeHandle,
+ &gEfiIfrTianoGuid,
+ NULL,
+ sizeof (EFI_IFR_GUID_LABEL)
+ );
+ if (EndLabel == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeOpCodeBuffer;
+ }
+ EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ EndLabel->Number = LABEL_END;
+
+ //
+ // Create the numeric for DDR CE threshold
+ //
+ if (!IsDdrCeWindowEnabled ()) {
+ HiiCreateNumericOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ 0x8004, // Question ID
+ RAS_CONFIG_VARSTORE_ID, // VarStore ID
+ (UINT16)RAS_DDR_CE_THRESHOLD_OFST, // Offset in Buffer Storage
+ STRING_TOKEN (STR_RAS_DDR_CE_THRESHOLD_PROMPT), // Question prompt text
+ STRING_TOKEN (STR_RAS_DDR_CE_THRESHOLD_HELP),
+ EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 1,
+ 8192,
+ 1,
+ NULL
+ );
+ }
+
+ //
+ // Create the numeric for 2P CE threshold
+ //
+ if (IsSlaveSocketActive ()) {
+ HiiCreateNumericOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ 0x8005, // Question ID
+ RAS_CONFIG_VARSTORE_ID, // VarStore ID
+ (UINT16)RAS_2P_CE_THRESHOLD_OFST, // Offset in Buffer Storage
+ STRING_TOKEN (STR_RAS_2P_CE_THRESHOLD_PROMPT), // Question prompt text
+ STRING_TOKEN (STR_RAS_2P_CE_THRESHOLD_HELP),
+ EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 1,
+ 8192,
+ 1,
+ NULL
+ );
+ }
+
+ Status = HiiUpdateForm (
+ PrivateData->HiiHandle, // HII handle
+ &mRasConfigFormSetGuid, // Formset GUID
+ RAS_CONFIG_FORM_ID, // Form ID
+ StartOpCodeHandle, // Label for where to insert opcodes
+ EndOpCodeHandle // Insert data
+ );
+
+FreeOpCodeBuffer:
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+RasConfigUnload (
+ VOID
+ )
+{
+ ASSERT (mPrivateData != NULL);
+
+ if (mDriverHandle != NULL) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ mDriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mRasConfigHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mPrivateData->ConfigAccess,
+ NULL
+ );
+ mDriverHandle = NULL;
+ }
+
+ if (mPrivateData->HiiHandle != NULL) {
+ HiiRemovePackages (mPrivateData->HiiHandle);
+ }
+
+ FreePool (mPrivateData);
+ mPrivateData = NULL;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+RasConfigEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ //
+ // Initialize driver private data
+ //
+ mPrivateData = AllocateZeroPool (sizeof (RAS_CONFIG_PRIVATE_DATA));
+ if (mPrivateData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mPrivateData->Signature = RAS_CONFIG_PRIVATE_SIGNATURE;
+
+ mPrivateData->ConfigAccess.ExtractConfig = RasConfigExtractConfig;
+ mPrivateData->ConfigAccess.RouteConfig = RasConfigRouteConfig;
+ mPrivateData->ConfigAccess.Callback = RasConfigCallback;
+
+ //
+ // Locate ConfigRouting protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&HiiConfigRouting);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mPrivateData->HiiConfigRouting = HiiConfigRouting;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mDriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mRasConfigHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mPrivateData->ConfigAccess,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ mPrivateData->DriverHandle = mDriverHandle;
+
+ //
+ // Publish our HII data
+ //
+ HiiHandle = HiiAddPackages (
+ &mRasConfigFormSetGuid,
+ mDriverHandle,
+ RasConfigDxeStrings,
+ RasConfigVfrBin,
+ NULL
+ );
+ if (HiiHandle == NULL) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ mDriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mRasConfigHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mPrivateData->ConfigAccess,
+ NULL
+ );
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mPrivateData->HiiHandle = HiiHandle;
+
+ Status = UpdateRasConfigScreen (mPrivateData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a %d Fail to update Memory Configuration screen \n",
+ __FUNCTION__,
+ __LINE__
+ ));
+ RasConfigUnload ();
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigStrings.uni b/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigStrings.uni
new file mode 100644
index 000000000000..c502093a2bbf
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigStrings.uni
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+#langdef en-US "English"
+
+#string STR_RAS_FORM #language en-US "RAS Configuration"
+#string STR_RAS_FORM_HELP #language en-US "RAS Configuration"
+
+#string STR_RAS_FORM_SEPERATE_LINE #language en-US ""
+#string STR_RAS_COMMON_ENABLE #language en-US "Enabled"
+#string STR_RAS_COMMON_DISABLE #language en-US "Disabled"
+
+#string STR_RAS_HARDWARE_EINJ_PROMPT #language en-US "Hardware EINJ"
+#string STR_RAS_HARDWARE_EINJ_HELP #language en-US "Enable hardware EINJ support, if disabled EINJ is software simulated"
+
+#string STR_RAS_PCIE_AER_FW_FIRST_PROMPT #language en-US "PCIe AER Firmware First"
+#string STR_RAS_PCIE_AER_FW_FIRST_HELP #language en-US "Enable firmware to detect PCIe AER, if disabled OS detects AER"
+
+#string STR_RAS_BERT_ENABLED_PROMPT #language en-US "Enable BERT"
+#string STR_RAS_BERT_ENABLED_HELP #language en-US "Enable Boot Error Record Table, if disabled BERT will not be populated"
+
+#string STR_RAS_SDEI_ENABLED_PROMPT #language en-US "Enable SDEI"
+#string STR_RAS_SDEI_ENABLED_HELP #language en-US "Enable Software Delegated Exception Interface for NMI support"
+
+#string STR_RAS_DDR_CE_THRESHOLD_PROMPT #language en-US "DDR CE Threshold"
+#string STR_RAS_DDR_CE_THRESHOLD_HELP #language en-US "Number of DDR CEs to occur before using SCI notification to OS rather than polled notification"
+
+#string STR_RAS_2P_CE_THRESHOLD_PROMPT #language en-US "2P CE Threshold"
+#string STR_RAS_2P_CE_THRESHOLD_HELP #language en-US "Number of 2P CEs to occur before using SCI notification to OS rather than polled notification"
+
+#string STR_RAS_CPM_CE_THRESHOLD_PROMPT #language en-US "Processor CE Threshold"
+#string STR_RAS_CPM_CE_THRESHOLD_HELP #language en-US "Number of processor CEs to occur before using SCI notification to OS rather than polled notification"
+
+#string STR_RAS_LINK_ERR_THRESHOLD_PROMPT #language en-US "DDR Link Error Threshold"
+#string STR_RAS_LINK_ERR_THRESHOLD_HELP #language en-US "Number of DDR link errors before considering it fatal severity"
--
2.17.1


Re: [PATCH v3 25/28] AmpereAltraPkg: Add configuration screen for ACPI

Leif Lindholm
 

On Wed, Sep 15, 2021 at 22:55:24 +0700, Nhi Pham wrote:
This supports:
* Enable/Disable APEI Support
* Enable/Disable CPPC Support
* Enable/Disable LPI support
* Enable/Disable Max Performance Mode

Cc: Thang Nguyen <thang@os.amperecomputing.com>
Cc: Chuong Tran <chuong@os.amperecomputing.com>
Cc: Phong Vo <phong@os.amperecomputing.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>

Signed-off-by: Nhi Pham <nhi@os.amperecomputing.com>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>

---
Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec | 3 +
Platform/Ampere/JadePkg/Jade.dsc | 1 +
Platform/Ampere/JadePkg/Jade.fdf | 1 +
Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf | 1 +
Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf | 58 ++
Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiApei.h | 7 +-
Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.h | 62 ++
Silicon/Ampere/AmpereAltraPkg/Include/AcpiConfigNVDataStruct.h | 28 +
Silicon/Ampere/AmpereAltraPkg/Include/Guid/AcpiConfigFormSet.h | 19 +
Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigVfr.vfr | 69 ++
Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiApei.c | 25 +-
Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.c | 729 ++++++++++++++++++++
Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigStrings.uni | 27 +
13 files changed, 1026 insertions(+), 4 deletions(-)

diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
index 6ea247c75e87..196611d67280 100644
--- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
@@ -53,6 +53,9 @@ [Guids]
# GUID for the CPU HII configuration form
gCpuConfigFormSetGuid = { 0x43FAA144, 0xA2DF, 0x4050, { 0xA7, 0xFD, 0xEE, 0x17, 0xC9, 0xB8, 0x88, 0x8E } }

+ # GUID for the ACPI HII configuration form
+ gAcpiConfigFormSetGuid = { 0x0ceb6764, 0xd415, 0x4b01, { 0xa8, 0x43, 0xd1, 0x01, 0xbc, 0xb0, 0xd8, 0x29 } }
+
## NVParam MM GUID
gNVParamMmGuid = { 0xE4AC5024, 0x29BE, 0x4ADC, { 0x93, 0x36, 0x87, 0xB5, 0xA0, 0x76, 0x23, 0x2D } }

diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc
index 8ca3a729728f..daac52e84ea2 100644
--- a/Platform/Ampere/JadePkg/Jade.dsc
+++ b/Platform/Ampere/JadePkg/Jade.dsc
@@ -199,3 +199,4 @@ [Components.common]
Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoDxe.inf
Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.inf
+ Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf
diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf
index d9552886fbcf..1564e45c30cd 100644
--- a/Platform/Ampere/JadePkg/Jade.fdf
+++ b/Platform/Ampere/JadePkg/Jade.fdf
@@ -357,5 +357,6 @@ [FV.FvMain]
INF Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoDxe.inf
INF Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
INF Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.inf
+ INF Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf

!include Platform/Ampere/AmperePlatformPkg/FvRules.fdf.inc
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
index 2b2a3728a406..a2b3886a0236 100644
--- a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -66,6 +66,7 @@ [Guids]
gArmMpCoreInfoGuid
gEfiAcpiTableGuid
gEfiEventReadyToBootGuid
+ gAcpiConfigFormSetGuid
gPlatformHobGuid

[Protocols]
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf
new file mode 100644
index 000000000000..075183aa9c58
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf
@@ -0,0 +1,58 @@
+## @file
+#
+# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = AcpiConfigDxe
+ FILE_GUID = F36685AE-2623-4231-ABC0-2C151451E6B7
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = AcpiConfigEntryPoint
+
+[Sources.common]
+ AcpiConfigDxe.c
+ AcpiConfigDxe.h
+ AcpiConfigVfr.vfr
+ AcpiConfigStrings.uni
+
+[Packages]
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+ Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
+
+[LibraryClasses]
+ AcpiLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ HiiLib
+ HobLib
+ MemoryAllocationLib
+ SystemFirmwareInterfaceLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Guids]
+ gPlatformManagerFormsetGuid
+ gAcpiConfigFormSetGuid
+ gEfiEventReadyToBootGuid
+ gPlatformHobGuid
+
+[Protocols]
+ gEfiAcpiSdtProtocolGuid ## COMSUMES
+ gEfiDevicePathProtocolGuid ## CONSUMES
+ gEfiHiiConfigRoutingProtocolGuid ## CONSUMES
+ gEfiHiiConfigAccessProtocolGuid ## PRODUCES
+
+[Depex]
+ gEfiVariableArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiApei.h b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiApei.h
index 2e763422cbc6..035912a1a331 100644
--- a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiApei.h
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiApei.h
@@ -9,7 +9,9 @@
#ifndef ACPI_APEI_H_
#define ACPI_APEI_H_

+#include <AcpiConfigNVDataStruct.h>
#include <Base.h>
+#include <Guid/AcpiConfigFormSet.h>
#include <IndustryStandard/Acpi63.h>
#include <Library/AcpiLib.h>
#include <Library/AmpereCpuLib.h>
@@ -34,9 +36,10 @@
#define PLAT_CRASH_ITERATOR_SIZE 0x398
#define SMPRO_CRASH_SIZE 0x800
#define PMPRO_CRASH_SIZE 0x800
+#define RASIP_CRASH_SIZE 0x1000
#define HEST_NUM_ENTRIES_PER_SOC 3

-#define CURRENT_BERT_VERSION 0x10
+#define CURRENT_BERT_VERSION 0x11
#define BERT_FLASH_OFFSET 0x91B30000ULL
#define BERT_DDR_OFFSET 0x88230000ULL
#define BERT_DDR_LENGTH 0x50000
@@ -53,8 +56,10 @@ typedef struct {
UINT8 BertRev;
UINT8 S0PmproRegisters[PMPRO_CRASH_SIZE];
UINT8 S0SmproRegisters[SMPRO_CRASH_SIZE];
+ UINT8 S0RasIpRegisters[RASIP_CRASH_SIZE];
UINT8 S1PmproRegisters[PMPRO_CRASH_SIZE];
UINT8 S1SmproRegisters[SMPRO_CRASH_SIZE];
+ UINT8 S1RasIpRegisters[RASIP_CRASH_SIZE];
UINT8 AtfDump[PLATFORM_CPU_MAX_NUM_CORES * PLAT_CRASH_ITERATOR_SIZE];
} APEI_CRASH_DUMP_DATA;

diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.h
new file mode 100644
index 000000000000..8a2cc2f5e679
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.h
@@ -0,0 +1,62 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef ACPI_CONFIG_DXE_H_
+#define ACPI_CONFIG_DXE_H_
+
+//
+// This is the generated IFR binary data for each formset defined in VFR.
+//
+extern UINT8 AcpiConfigVfrBin[];
+
+//
+// This is the generated String package data for all .UNI files.
+//
+extern UINT8 AcpiConfigDxeStrings[];
+
+//
+// Signature: Ampere Computing ACPI Configuration
+//
+#define ACPI_CONFIG_PRIVATE_SIGNATURE SIGNATURE_32 ('A', 'C', 'A', 'C')
+
+typedef struct {
+ UINTN Signature;
+
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE HiiHandle;
+ ACPI_CONFIG_VARSTORE_DATA Configuration;
+ PLATFORM_INFO_HOB *PlatformHob;
+ EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol;
+ EFI_ACPI_HANDLE AcpiTableHandle;
+
+ //
+ // Consumed protocol
+ //
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ //
+ // Produced protocol
+ //
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+} ACPI_CONFIG_PRIVATE_DATA;
+
+#define ACPI_CONFIG_PRIVATE_FROM_THIS(a) CR (a, ACPI_CONFIG_PRIVATE_DATA, ConfigAccess, ACPI_CONFIG_PRIVATE_SIGNATURE)
+
+#pragma pack(1)
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+#pragma pack()
+
+#endif
diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/AcpiConfigNVDataStruct.h b/Silicon/Ampere/AmpereAltraPkg/Include/AcpiConfigNVDataStruct.h
new file mode 100644
index 000000000000..a56bfa9aa694
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Include/AcpiConfigNVDataStruct.h
@@ -0,0 +1,28 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef ACPI_CONFIG_NV_DATA_STRUC_H_
+#define ACPI_CONFIG_NV_DATA_STRUC_H_
+
+#pragma pack(1)
+
+//
+// ACPI Configuration NV data structure definition
+//
+typedef struct {
+ UINT32 EnableApeiSupport;
+ UINT32 AcpiCppcEnable;
+ UINT32 AcpiLpiEnable;
+ UINT32 AcpiTurboSupport;
+ UINT32 AcpiTurboMode;
+ UINT32 Reserved[4];
+} ACPI_CONFIG_VARSTORE_DATA;
+
+#pragma pack()
+
+#endif /* ACPI_CONFIG_NV_DATA_STRUC_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Guid/AcpiConfigFormSet.h b/Silicon/Ampere/AmpereAltraPkg/Include/Guid/AcpiConfigFormSet.h
new file mode 100644
index 000000000000..1779a4543769
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Include/Guid/AcpiConfigFormSet.h
@@ -0,0 +1,19 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef ACPI_CONFIG_FORMSET_GUID_H_
+#define ACPI_CONFIG_FORMSET_GUID_H_
+
+#define ACPI_CONFIGURATION_FORMSET_GUID \
+ { \
+ 0x0ceb6764, 0xd415, 0x4b01, { 0xa8, 0x43, 0xd1, 0x01, 0xbc, 0xb0, 0xd8, 0x29 } \
+ }
+
+extern EFI_GUID gAcpiConfigFormSetGuid;
+
+#endif /* ACPI_CONFIG_FORMSET_GUID_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigVfr.vfr b/Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigVfr.vfr
new file mode 100644
index 000000000000..18b44f90ddd9
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigVfr.vfr
@@ -0,0 +1,69 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include <Guid/AcpiConfigFormSet.h>
+#include <AcpiConfigNVDataStruct.h>
+
+#define ACPI_CONFIG_FORM_ID 1
+
+formset
+ guid = ACPI_CONFIGURATION_FORMSET_GUID,
+ title = STRING_TOKEN(STR_ACPI_FORM),
+ help = STRING_TOKEN(STR_ACPI_FORM_HELP),
+ classguid = gPlatformManagerFormsetGuid,
+
+ varstore ACPI_CONFIG_VARSTORE_DATA,
+ name = AcpiConfigNVData,
+ guid = ACPI_CONFIGURATION_FORMSET_GUID;
+
+ form
+ formid = ACPI_CONFIG_FORM_ID,
+ title = STRING_TOKEN(STR_ACPI_FORM);
+ subtitle text = STRING_TOKEN(STR_ACPI_FORM_HELP);
+
+ oneof
+ varid = AcpiConfigNVData.EnableApeiSupport,
+ prompt = STRING_TOKEN(STR_ACPI_APEI_SUPPORT_PROMPT),
+ help = STRING_TOKEN(STR_ACPI_APEI_SUPPORT_HELP),
+ option text = STRING_TOKEN(STR_ACPI_COMMON_DISABLE), value = 0, flags = 0;
+ option text = STRING_TOKEN(STR_ACPI_COMMON_ENABLE), value = 1, flags = DEFAULT;
+ endoneof;
+
+ oneof
+ varid = AcpiConfigNVData.AcpiCppcEnable,
+ prompt = STRING_TOKEN(STR_ACPI_CPPC_PROMPT),
+ help = STRING_TOKEN(STR_ACPI_CPPC_HELP),
+ option text = STRING_TOKEN(STR_ACPI_COMMON_DISABLE), value = 0, flags = 0;
+ option text = STRING_TOKEN(STR_ACPI_COMMON_ENABLE), value = 1, flags = DEFAULT;
+ endoneof;
+
+ oneof
+ varid = AcpiConfigNVData.AcpiLpiEnable,
+ prompt = STRING_TOKEN(STR_ACPI_LPI_PROMPT),
+ help = STRING_TOKEN(STR_ACPI_LPI_HELP),
+ option text = STRING_TOKEN(STR_ACPI_COMMON_DISABLE), value = 0, flags = 0;
+ option text = STRING_TOKEN(STR_ACPI_COMMON_ENABLE), value = 1, flags = DEFAULT;
+ endoneof;
+
+ grayoutif ideqval AcpiConfigNVData.AcpiTurboSupport == 0;
+ oneof
+ varid = AcpiConfigNVData.AcpiTurboMode,
+ prompt = STRING_TOKEN(STR_ACPI_TURBO_PROMPT),
+ help = STRING_TOKEN(STR_ACPI_TURBO_HELP),
+ option text = STRING_TOKEN(STR_ACPI_COMMON_ENABLE), value = 1, flags = DEFAULT;
+ option text = STRING_TOKEN(STR_ACPI_COMMON_DISABLE), value = 0, flags = 0;
+ suppressif ideqval AcpiConfigNVData.AcpiTurboSupport > 0;
+ option text = STRING_TOKEN(STR_ACPI_UNSUPPORTED), value = 2, flags = 0;
+ endif;
+ endoneof;
+ endif;
+
+ endform;
+
+endformset;
diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiApei.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiApei.c
index a216edac60ce..8a46e038c1a7 100644
--- a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiApei.c
+++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiApei.c
@@ -149,7 +149,7 @@ WrapBertErrorData (
CrashSize = PLAT_CRASH_ITERATOR_SIZE *
GetNumberOfSupportedSockets () *
GetMaximumNumberOfCores ();
- CrashSize += 2 * (SMPRO_CRASH_SIZE + PMPRO_CRASH_SIZE);
+ CrashSize += 2 * (SMPRO_CRASH_SIZE + PMPRO_CRASH_SIZE + RASIP_CRASH_SIZE);
CrashSize += sizeof (WrappedError->Bed.Vendor) + sizeof (WrappedError->Bed.BertRev);

WrappedError->Ges.BlockStatus.ErrorDataEntryCount = 1;
@@ -437,8 +437,27 @@ AcpiApeiUpdate (
VOID
)
{
- if (!IsSlaveSocketActive ()) {
- AcpiApeiHestUpdateTable1P ();
+ EFI_STATUS Status;
+ ACPI_CONFIG_VARSTORE_DATA AcpiConfigData;
+ UINTN BufferSize;
+
+ BufferSize = sizeof (ACPI_CONFIG_VARSTORE_DATA);
+ Status = gRT->GetVariable (
+ L"AcpiConfigNVData",
+ &gAcpiConfigFormSetGuid,
+ NULL,
+ &BufferSize,
+ &AcpiConfigData
+ );
+ if (!EFI_ERROR (Status) && (AcpiConfigData.EnableApeiSupport == 0)) {
+ AcpiApeiUninstallTable (EFI_ACPI_6_3_BOOT_ERROR_RECORD_TABLE_SIGNATURE);
+ AcpiApeiUninstallTable (EFI_ACPI_6_3_HARDWARE_ERROR_SOURCE_TABLE_SIGNATURE);
+ AcpiApeiUninstallTable (EFI_ACPI_6_3_SOFTWARE_DELEGATED_EXCEPTIONS_INTERFACE_TABLE_SIGNATURE);
+ AcpiApeiUninstallTable (EFI_ACPI_6_3_ERROR_INJECTION_TABLE_SIGNATURE);
+ } else {
+ if (!IsSlaveSocketActive ()) {
+ AcpiApeiHestUpdateTable1P ();
+ }
}

if (!IsSdeiEnabled ()) {
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.c
new file mode 100644
index 000000000000..d085389d2865
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.c
@@ -0,0 +1,729 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <AcpiConfigNVDataStruct.h>
+#include <Guid/AcpiConfigFormSet.h>
+#include <Guid/MdeModuleHii.h>
+#include <Guid/PlatformInfoHobGuid.h>
+#include <Library/AcpiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/SystemFirmwareInterfaceLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <PlatformInfoHob.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigRouting.h>
+
+#include "AcpiConfigDxe.h"
+
+#define ACPI_VARSTORE_ATTRIBUTES EFI_VARIABLE_BOOTSERVICE_ACCESS | \
+ EFI_VARIABLE_RUNTIME_ACCESS | \
+ EFI_VARIABLE_NON_VOLATILE
+
+CHAR16 AcpiVarstoreDataName[] = L"AcpiConfigNVData";
+
+EFI_HANDLE mDriverHandle = NULL;
+ACPI_CONFIG_PRIVATE_DATA *mPrivateData = NULL;
+
+HII_VENDOR_DEVICE_PATH mAcpiConfigHiiVendorDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ ACPI_CONFIGURATION_FORMSET_GUID
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8)(END_DEVICE_PATH_LENGTH),
+ (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
+ }
+ }
+};
+
+/**
+ This function allows a caller to extract the current configuration for one
+ or more named elements from the target driver.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Request A null-terminated Unicode string in
+ <ConfigRequest> format.
+ @param Progress On return, points to a character in the Request
+ string. Points to the string's null terminator if
+ request was successful. Points to the most recent
+ '&' before the first failing name/value pair (or
+ the beginning of the string if the failure is in
+ the first name/value pair) if the request was not
+ successful.
+ @param Results A null-terminated Unicode string in
+ <ConfigAltResp> format which has all values filled
+ in for the names in the Request string. String to
+ be allocated by the called function.
+
+ @retval EFI_SUCCESS The Results is filled with the requested values.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
+ @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+
+**/
+EFI_STATUS
+EFIAPI
+ExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ ACPI_CONFIG_PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ EFI_STRING ConfigRequest;
+ EFI_STRING ConfigRequestHdr;
+ UINTN Size;
+ BOOLEAN AllocatedRequest;
+
+ if (Progress == NULL || Results == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Initialize the local variables.
+ //
+ ConfigRequestHdr = NULL;
+ ConfigRequest = NULL;
+ Size = 0;
+ *Progress = Request;
+ AllocatedRequest = FALSE;
+
+ if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gAcpiConfigFormSetGuid, AcpiVarstoreDataName)) {
+ return EFI_NOT_FOUND;
+ }
+
+ PrivateData = ACPI_CONFIG_PRIVATE_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+
+ //
+ // Get Buffer Storage data from EFI variable.
+ // Try to get the current setting from variable.
+ //
+ BufferSize = sizeof (ACPI_CONFIG_VARSTORE_DATA);
+ Status = gRT->GetVariable (
+ AcpiVarstoreDataName,
+ &gAcpiConfigFormSetGuid,
+ NULL,
+ &BufferSize,
+ &PrivateData->Configuration
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ BufferSize = sizeof (ACPI_CONFIG_VARSTORE_DATA);
+ ConfigRequest = Request;
+ if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
+ //
+ // Request has no request element, construct full request string.
+ // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+ // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
+ //
+ ConfigRequestHdr = HiiConstructConfigHdr (
+ &gAcpiConfigFormSetGuid,
+ AcpiVarstoreDataName,
+ PrivateData->DriverHandle
+ );
+ Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
+ ConfigRequest = AllocateZeroPool (Size);
+ ASSERT (ConfigRequest != NULL);
+ if (ConfigRequest == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ AllocatedRequest = TRUE;
+ UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
+ FreePool (ConfigRequestHdr);
+ }
+
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ Status = HiiConfigRouting->BlockToConfig (
+ HiiConfigRouting,
+ ConfigRequest,
+ (UINT8 *)&PrivateData->Configuration,
+ BufferSize,
+ Results,
+ Progress
+ );
+
+ //
+ // Free the allocated config request string.
+ //
+ if (AllocatedRequest) {
+ FreePool (ConfigRequest);
+ ConfigRequest = NULL;
+ }
+
+ //
+ // Set Progress string to the original request string.
+ //
+ if (Request == NULL) {
+ *Progress = NULL;
+ } else if (StrStr (Request, L"OFFSET") == NULL) {
+ *Progress = Request + StrLen (Request);
+ }
+
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Configuration A null-terminated Unicode string in <ConfigResp>
+ format.
+ @param Progress A pointer to a string filled in with the offset of
+ the most recent '&' before the first failing
+ name/value pair (or the beginning of the string if
+ the failure is in the first name/value pair) or
+ the terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The Results is processed successfully.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+
+**/
+EFI_STATUS
+EFIAPI
+RouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ ACPI_CONFIG_PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ if (Configuration == NULL || Progress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = ACPI_CONFIG_PRIVATE_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+ *Progress = Configuration;
+
+ //
+ // Check routing data in <ConfigHdr>.
+ // Note: if only one Storage is used, then this checking could be skipped.
+ //
+ if (!HiiIsConfigHdrMatch (Configuration, &gAcpiConfigFormSetGuid, AcpiVarstoreDataName)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get Buffer Storage data from EFI variable
+ //
+ BufferSize = sizeof (ACPI_CONFIG_VARSTORE_DATA);
+ Status = gRT->GetVariable (
+ AcpiVarstoreDataName,
+ &gAcpiConfigFormSetGuid,
+ NULL,
+ &BufferSize,
+ &PrivateData->Configuration
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
+ //
+ BufferSize = sizeof (ACPI_CONFIG_VARSTORE_DATA);
+ Status = HiiConfigRouting->ConfigToBlock (
+ HiiConfigRouting,
+ Configuration,
+ (UINT8 *)&PrivateData->Configuration,
+ &BufferSize,
+ Progress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Store Buffer Storage back to EFI variable
+ //
+ Status = gRT->SetVariable (
+ AcpiVarstoreDataName,
+ &gAcpiConfigFormSetGuid,
+ ACPI_VARSTORE_ATTRIBUTES,
+ sizeof (ACPI_CONFIG_VARSTORE_DATA),
+ &PrivateData->Configuration
+ );
+
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Action Specifies the type of action taken by the browser.
+ @param QuestionId A unique value which is sent to the original
+ exporting driver so that it can identify the type
+ of data to expect.
+ @param Type The type of value for the question.
+ @param Value A pointer to the data being sent to the original
+ exporting driver.
+ @param ActionRequest On return, points to the action requested by the
+ callback function.
+
+ @retval EFI_SUCCESS The callback successfully handled the action.
+ @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+{
+ if (Action != EFI_BROWSER_ACTION_CHANGING) {
+ //
+ // Do nothing for other UEFI Action. Only do call back when data is changed.
+ //
+ return EFI_UNSUPPORTED;
+ }
+ if (((Value == NULL)
+ && (Action != EFI_BROWSER_ACTION_FORM_OPEN)
+ && (Action != EFI_BROWSER_ACTION_FORM_CLOSE))
+ || (ActionRequest == NULL))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+AcpiNVDataUpdate (
+ IN ACPI_CONFIG_PRIVATE_DATA *PrivateData
+ )
+{
+ EFI_STATUS Status;
+ PLATFORM_INFO_HOB *PlatformHob;
+ UINT32 TurboSupport;
+
+ ASSERT (PrivateData != NULL);
+
+ PlatformHob = PrivateData->PlatformHob;
+ TurboSupport = PlatformHob->TurboCapability[0] + PlatformHob->TurboCapability[1];
+
+ if (TurboSupport == 0) {
+ PrivateData->Configuration.AcpiTurboMode = 2; // Unsupported mode
+ PrivateData->Configuration.AcpiTurboSupport = 0;
+ } else {
+ PrivateData->Configuration.AcpiTurboSupport = 1;
+ }
+
+ Status = gRT->SetVariable (
+ AcpiVarstoreDataName,
+ &gAcpiConfigFormSetGuid,
+ ACPI_VARSTORE_ATTRIBUTES,
+ sizeof (ACPI_CONFIG_VARSTORE_DATA),
+ &PrivateData->Configuration
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a %d gRT->SetVariable() failed \n", __FUNCTION__, __LINE__));
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+UpdateTurboModeConfig (
+ IN ACPI_CONFIG_PRIVATE_DATA *PrivateData
+ )
+{
+ EFI_STATUS Status;
+ PLATFORM_INFO_HOB *PlatformHob;
+ BOOLEAN EnableTurbo;
+
+ ASSERT (PrivateData != NULL);
+
+ if (PrivateData->Configuration.AcpiTurboSupport != 0) {
+ PlatformHob = PrivateData->PlatformHob;
+ EnableTurbo = (PrivateData->Configuration.AcpiTurboMode != 0) ? TRUE : FALSE;
+
+ if (PlatformHob->TurboCapability[0] != 0) {
+ Status = MailboxMsgTurboConfig (0, EnableTurbo);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ if (PlatformHob->TurboCapability[1] != 0) {
+ Status = MailboxMsgTurboConfig (1, EnableTurbo);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "%a: Turbo mode is unsupported! \n", __FUNCTION__));
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+UpdateCPPCConfig (
+ IN ACPI_CONFIG_PRIVATE_DATA *PrivateData
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 Buffer[64];
+
+ ASSERT (PrivateData != NULL);
+
+ AsciiSPrint (Buffer, sizeof (Buffer), "\\_SB.CPCE");
+ Status = AcpiAmlObjectUpdateInteger (
+ PrivateData->AcpiSdtProtocol,
+ PrivateData->AcpiTableHandle,
+ Buffer,
+ PrivateData->Configuration.AcpiCppcEnable
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+UpdateLPIConfig (
+ IN ACPI_CONFIG_PRIVATE_DATA *PrivateData
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 Buffer[64];
+
+ ASSERT (PrivateData != NULL);
+
+ AsciiSPrint (Buffer, sizeof (Buffer), "\\_SB.LPIE");
+ Status = AcpiAmlObjectUpdateInteger (
+ PrivateData->AcpiSdtProtocol,
+ PrivateData->AcpiTableHandle,
+ Buffer,
+ PrivateData->Configuration.AcpiLpiEnable
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+STATIC
+VOID
+UpdateAcpiOnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol;
+ EFI_ACPI_DESCRIPTION_HEADER *Table;
+ EFI_ACPI_HANDLE TableHandle;
+ UINTN TableKey;
+ UINTN TableIndex;
+
+ ASSERT (mPrivateData != NULL);
+
+ //
+ // Find the AcpiTable protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiAcpiSdtProtocolGuid,
+ NULL,
+ (VOID **)&AcpiSdtProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Unable to locate ACPI table protocol\n"));
+ return;
+ }
+
+ mPrivateData->AcpiSdtProtocol = AcpiSdtProtocol;
+
+ TableIndex = 0;
+ Status = AcpiLocateTableBySignature (
+ AcpiSdtProtocol,
+ EFI_ACPI_6_3_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ &TableIndex,
+ &Table,
+ &TableKey
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = AcpiSdtProtocol->OpenSdt (TableKey, &TableHandle);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ mPrivateData->AcpiTableHandle = TableHandle;
+
+ Status = UpdateCPPCConfig (mPrivateData);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = UpdateLPIConfig (mPrivateData);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = UpdateTurboModeConfig (mPrivateData);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // Close DSDT Table
+ //
+ AcpiSdtProtocol->Close (TableHandle);
+ AcpiUpdateChecksum ((UINT8 *)Table, Table->Length);
+}
+
+STATIC
+EFI_STATUS
+AcpiConfigUnload (
+ VOID
+ )
+{
+ ASSERT (mPrivateData != NULL);
+
+ if (mDriverHandle != NULL) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ mDriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mAcpiConfigHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mPrivateData->ConfigAccess,
+ NULL
+ );
+ mDriverHandle = NULL;
+ }
+
+ if (mPrivateData->HiiHandle != NULL) {
+ HiiRemovePackages (mPrivateData->HiiHandle);
+ }
+
+ FreePool (mPrivateData);
+ mPrivateData = NULL;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+AcpiConfigEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ UINTN BufferSize;
+ ACPI_CONFIG_VARSTORE_DATA *Configuration;
+ BOOLEAN ActionFlag;
+ EFI_STRING ConfigRequestHdr;
+ EFI_EVENT ReadyToBootEvent;
+ PLATFORM_INFO_HOB *PlatformHob;
+ VOID *Hob;
+
+ //
+ // Initialize the local variables.
+ //
+ ConfigRequestHdr = NULL;
+
+ //
+ // Initialize driver private data
+ //
+ mPrivateData = AllocateZeroPool (sizeof (ACPI_CONFIG_PRIVATE_DATA));
+ if (mPrivateData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mPrivateData->Signature = ACPI_CONFIG_PRIVATE_SIGNATURE;
+
+ mPrivateData->ConfigAccess.ExtractConfig = ExtractConfig;
+ mPrivateData->ConfigAccess.RouteConfig = RouteConfig;
+ mPrivateData->ConfigAccess.Callback = DriverCallback;
+
+ //
+ // Get the Platform HOB
+ //
+ Hob = GetFirstGuidHob (&gPlatformHobGuid);
+ ASSERT (Hob != NULL);
+ if (Hob == NULL) {
+ AcpiConfigUnload ();
+ return EFI_DEVICE_ERROR;
+ }
+ PlatformHob = (PLATFORM_INFO_HOB *)GET_GUID_HOB_DATA (Hob);
+
+ mPrivateData->PlatformHob = PlatformHob;
+
+ //
+ // Locate ConfigRouting protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&HiiConfigRouting);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mPrivateData->HiiConfigRouting = HiiConfigRouting;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mDriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mAcpiConfigHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mPrivateData->ConfigAccess,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ mPrivateData->DriverHandle = mDriverHandle;
+
+ //
+ // Publish our HII data
+ //
+ HiiHandle = HiiAddPackages (
+ &gAcpiConfigFormSetGuid,
+ mDriverHandle,
+ AcpiConfigDxeStrings,
+ AcpiConfigVfrBin,
+ NULL
+ );
+ if (HiiHandle == NULL) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ mDriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mAcpiConfigHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mPrivateData->ConfigAccess,
+ NULL
+ );
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mPrivateData->HiiHandle = HiiHandle;
+
+ //
+ // Initialize configuration data
+ //
+ Configuration = &mPrivateData->Configuration;
+ ZeroMem (Configuration, sizeof (ACPI_CONFIG_VARSTORE_DATA));
+
+ //
+ // Try to read NV config EFI variable first
+ //
+ ConfigRequestHdr = HiiConstructConfigHdr (&gAcpiConfigFormSetGuid, AcpiVarstoreDataName, mDriverHandle);
+ ASSERT (ConfigRequestHdr != NULL);
+
+ BufferSize = sizeof (ACPI_CONFIG_VARSTORE_DATA);
+ Status = gRT->GetVariable (AcpiVarstoreDataName, &gAcpiConfigFormSetGuid, NULL, &BufferSize, Configuration);
+ if (EFI_ERROR (Status)) {
+ //
+ // Store zero data Buffer Storage to EFI variable
+ //
+ Status = gRT->SetVariable (
+ AcpiVarstoreDataName,
+ &gAcpiConfigFormSetGuid,
+ ACPI_VARSTORE_ATTRIBUTES,
+ sizeof (ACPI_CONFIG_VARSTORE_DATA),
+ Configuration
+ );
+ if (EFI_ERROR (Status)) {
+ AcpiConfigUnload ();
+ return Status;
+ }
+ //
+ // EFI variable for NV config doesn't exit, we should build this variable
+ // based on default values stored in IFR
+ //
+ ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
+ if (!ActionFlag) {
+ AcpiConfigUnload ();
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // EFI variable does exist and Validate Current Setting
+ //
+ ActionFlag = HiiValidateSettings (ConfigRequestHdr);
+ if (!ActionFlag) {
+ AcpiConfigUnload ();
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ FreePool (ConfigRequestHdr);
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ UpdateAcpiOnReadyToBoot,
+ NULL,
+ &gEfiEventReadyToBootGuid,
+ &ReadyToBootEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to create ready to boot event %r!\n", Status));
+ return Status;
+ }
+
+ Status = AcpiNVDataUpdate (mPrivateData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigStrings.uni b/Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigStrings.uni
new file mode 100644
index 000000000000..21a6188518fd
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigStrings.uni
@@ -0,0 +1,27 @@
+//
+// Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+#langdef en-US "English"
+
+#string STR_ACPI_FORM #language en-US "ACPI Configuration"
+#string STR_ACPI_FORM_HELP #language en-US "ACPI Configuration"
+
+#string STR_ACPI_FORM_SEPERATE_LINE #language en-US ""
+#string STR_ACPI_COMMON_ENABLE #language en-US "Enabled"
+#string STR_ACPI_COMMON_DISABLE #language en-US "Disabled"
+#string STR_ACPI_UNSUPPORTED #language en-US "Unsupported"
+
+#string STR_ACPI_APEI_SUPPORT_PROMPT #language en-US "APEI Support"
+#string STR_ACPI_APEI_SUPPORT_HELP #language en-US "Enable/Disable ACPI Platform Error Interface support"
+
+#string STR_ACPI_CPPC_PROMPT #language en-US "CPPC Support"
+#string STR_ACPI_CPPC_HELP #language en-US "Enables or Disables System ability to CPPC (Collaborative Processor Performance Control)"
+
+#string STR_ACPI_LPI_PROMPT #language en-US "LPI Support"
+#string STR_ACPI_LPI_HELP #language en-US "Enables or Disables System ability to LPI (Lower Power Idle)"
+
+#string STR_ACPI_TURBO_PROMPT #language en-US "Max Performance"
+#string STR_ACPI_TURBO_HELP #language en-US "Enables or Disables System ability to Max Performance"
--
2.17.1


Re: [PATCH v3 24/28] AmpereAltraPkg: Add configuration screen for CPU

Leif Lindholm
 

On Wed, Sep 15, 2021 at 22:55:23 +0700, Nhi Pham wrote:
From: Vu Nguyen <vunguyen@os.amperecomputing.com>

This screen is to add configuration regarding CPU. Currently, this
screen just adds a option for SubNUMA mode selection.

Cc: Thang Nguyen <thang@os.amperecomputing.com>
Cc: Chuong Tran <chuong@os.amperecomputing.com>
Cc: Phong Vo <phong@os.amperecomputing.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>

Signed-off-by: Vu Nguyen <vunguyen@os.amperecomputing.com>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>


---
Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec | 3 +
Platform/Ampere/JadePkg/Jade.dsc | 1 +
Platform/Ampere/JadePkg/Jade.fdf | 1 +
Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.inf | 58 +++
Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.h | 52 ++
Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigNVDataStruc.h | 19 +
Silicon/Ampere/AmpereAltraPkg/Include/Guid/CpuConfigHii.h | 19 +
Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigVfr.vfr | 43 ++
Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.c | 530 ++++++++++++++++++++
Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigStrings.uni | 17 +
10 files changed, 743 insertions(+)

diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
index 93da9b38def5..6ea247c75e87 100644
--- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
@@ -50,6 +50,9 @@ [LibraryClasses]
TrngLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/TrngLib.h

[Guids]
+ # GUID for the CPU HII configuration form
+ gCpuConfigFormSetGuid = { 0x43FAA144, 0xA2DF, 0x4050, { 0xA7, 0xFD, 0xEE, 0x17, 0xC9, 0xB8, 0x88, 0x8E } }
+
## NVParam MM GUID
gNVParamMmGuid = { 0xE4AC5024, 0x29BE, 0x4ADC, { 0x93, 0x36, 0x87, 0xB5, 0xA0, 0x76, 0x23, 0x2D } }

diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc
index 5fc83745cdbc..8ca3a729728f 100644
--- a/Platform/Ampere/JadePkg/Jade.dsc
+++ b/Platform/Ampere/JadePkg/Jade.dsc
@@ -198,3 +198,4 @@ [Components.common]
#
Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoDxe.inf
Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
+ Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.inf
diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf
index 6fe023025034..d9552886fbcf 100644
--- a/Platform/Ampere/JadePkg/Jade.fdf
+++ b/Platform/Ampere/JadePkg/Jade.fdf
@@ -356,5 +356,6 @@ [FV.FvMain]
#
INF Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoDxe.inf
INF Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
+ INF Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.inf

!include Platform/Ampere/AmperePlatformPkg/FvRules.fdf.inc
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.inf
new file mode 100644
index 000000000000..2b13ef526685
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.inf
@@ -0,0 +1,58 @@
+## @file
+#
+# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = CpuConfigDxe
+ MODULE_UNI_FILE = CpuConfigDxe.uni
+ FILE_GUID = A20D8E6E-EE6C-43C5-809F-19BB930653AE
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = CpuConfigDxeEntryPoint
+
+[Sources.common]
+ CpuConfigDxe.c
+ CpuConfigDxe.h
+ CpuConfigNVDataStruc.h
+ CpuConfigVfr.vfr
+ CpuConfigStrings.uni
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+ Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
+
+[LibraryClasses]
+ ArmLib
+ BaseLib
+ DebugLib
+ DevicePathLib
+ HiiLib
+ HobLib
+ IoLib
+ MemoryAllocationLib
+ NVParamLib
+ PcdLib
+ PrintLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+ UefiRuntimeServicesTableLib
+
+[Protocols]
+ gEfiHiiConfigRoutingProtocolGuid ## CONSUMES
+ gEfiHiiConfigAccessProtocolGuid ## PRODUCES
+ gEfiDevicePathProtocolGuid ## PRODUCES
+
+[Guids]
+ gCpuConfigFormSetGuid
+ gPlatformManagerFormsetGuid
+
+[Depex]
+ TRUE
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.h
new file mode 100644
index 000000000000..b7e74a09da5b
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.h
@@ -0,0 +1,52 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef CPU_CONFIG_H_
+#define CPU_CONFIG_H_
+
+#include "CpuConfigNVDataStruc.h"
+
+//
+// This is the generated IFR binary data for each formset defined in VFR.
+//
+extern UINT8 CpuConfigVfrBin[];
+
+//
+// This is the generated String package data for all .UNI files.
+//
+extern UINT8 CpuConfigDxeStrings[];
+
+#define CPU_CONFIG_PRIVATE_SIGNATURE SIGNATURE_32 ('C', 'P', 'U', '_')
+
+typedef struct {
+ UINTN Signature;
+
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE HiiHandle;
+ CPU_VARSTORE_DATA Configuration;
+
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+} CPU_CONFIG_PRIVATE_DATA;
+
+#define CPU_CONFIG_PRIVATE_FROM_THIS(a) CR (a, CPU_CONFIG_PRIVATE_DATA, ConfigAccess, CPU_CONFIG_PRIVATE_SIGNATURE)
+
+#pragma pack(1)
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+#pragma pack()
+
+#endif /* CPU_CONFIG_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigNVDataStruc.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigNVDataStruc.h
new file mode 100644
index 000000000000..dbcaebded1b7
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigNVDataStruc.h
@@ -0,0 +1,19 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef CPU_CONFIG_NV_DATA_STRUC_H_
+#define CPU_CONFIG_NV_DATA_STRUC_H_
+
+#pragma pack(1)
+typedef struct {
+ UINT32 CpuSubNumaMode;
+} CPU_VARSTORE_DATA;
+
+#pragma pack()
+
+#endif /* CPU_CONFIG_NV_DATA_STRUC_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Guid/CpuConfigHii.h b/Silicon/Ampere/AmpereAltraPkg/Include/Guid/CpuConfigHii.h
new file mode 100644
index 000000000000..71c8492f76a1
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Include/Guid/CpuConfigHii.h
@@ -0,0 +1,19 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef CPU_CONFIG_HII_H_
+#define CPU_CONFIG_HII_H_
+
+#define CPU_CONFIGURATION_FORMSET_GUID \
+ { \
+ 0x43FAA144, 0xA2DF, 0x4050, { 0xA7, 0xFD, 0xEE, 0x17, 0xC9, 0xB8, 0x88, 0x8E } \
+ }
+
+extern EFI_GUID gCpuConfigFormSetGuid;
+
+#endif /* CPU_CONFIG_HII_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigVfr.vfr b/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigVfr.vfr
new file mode 100644
index 000000000000..8e68b1e9dcb7
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigVfr.vfr
@@ -0,0 +1,43 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi/UefiMultiPhase.h>
+#include <Guid/PlatformManagerHii.h>
+#include <Guid/CpuConfigHii.h>
+#include "CpuConfigNVDataStruc.h"
+
+#define SUBNUMA_MODE_FORM_ID 1
+
+formset
+ guid = CPU_CONFIGURATION_FORMSET_GUID,
+ title = STRING_TOKEN(STR_CPU_FORM),
+ help = STRING_TOKEN(STR_CPU_FORM_HELP),
+ classguid = gPlatformManagerFormsetGuid,
+
+ varstore CPU_VARSTORE_DATA,
+ name = CpuConfigNVData,
+ guid = CPU_CONFIGURATION_FORMSET_GUID;
+
+ form
+ formid = SUBNUMA_MODE_FORM_ID,
+ title = STRING_TOKEN(STR_CPU_FORM);
+ subtitle text = STRING_TOKEN(STR_CPU_FORM_HELP);
+
+ oneof
+ varid = CpuConfigNVData.CpuSubNumaMode,
+ prompt = STRING_TOKEN(STR_CPU_SUBNUMA_MODE_PROMPT),
+ help = STRING_TOKEN(STR_CPU_SUBNUMA_MODE_HELP),
+ flags = RESET_REQUIRED,
+ option text = STRING_TOKEN(STR_CPU_SUBNUMA_MODE_MONOLITHIC), value = 0x0, flags = DEFAULT;
+ option text = STRING_TOKEN(STR_CPU_SUBNUMA_MODE_HEMISPHERE), value = 0x1, flags = 0;
+ option text = STRING_TOKEN(STR_CPU_SUBNUMA_MODE_QUADRANT), value = 0x2, flags = 0;
+ endoneof;
+
+ endform;
+
+endformset;
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.c
new file mode 100644
index 000000000000..a5cab9eb8d9a
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.c
@@ -0,0 +1,530 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Guid/CpuConfigHii.h>
+#include <Guid/MdeModuleHii.h>
+#include <Guid/PlatformManagerHii.h>
+#include <Library/AmpereCpuLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NVParamLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <NVParamDef.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigRouting.h>
+
+#include "CpuConfigDxe.h"
+
+//
+// Default settings definitions
+//
+#define NV_SI_SUBNUMA_MODE_DEFAULT 0x00 /* Monolithic mode */
+#define WA_ERRATUM_1542419_DEFAULT 0x00 /* Disable I-Cache coherency */
+#define NEAR_ATOMIC_DISABLE_DEFAULT 0x00 /* Enable Near Atomic */
+#define CPU_SLC_REPLACE_POLICY 0x00 /* eLRU */
+
+CHAR16 CpuVarstoreDataName[] = L"CpuConfigNVData";
+
+EFI_HANDLE mDriverHandle = NULL;
+CPU_CONFIG_PRIVATE_DATA *mPrivateData = NULL;
+
+HII_VENDOR_DEVICE_PATH mCpuConfigHiiVendorDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ CPU_CONFIGURATION_FORMSET_GUID
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8)(END_DEVICE_PATH_LENGTH),
+ (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
+ }
+ }
+};
+
+STATIC
+EFI_STATUS
+CpuNvParamGet (
+ OUT CPU_VARSTORE_DATA *Configuration
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Value;
+
+ ASSERT (Configuration != NULL);
+
+ Status = NVParamGet (
+ NV_SI_SUBNUMA_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a %d Fail to write NVParam \n", __FUNCTION__, __LINE__));
+ Configuration->CpuSubNumaMode = SUBNUMA_MODE_MONOLITHIC;
+ } else {
+ Configuration->CpuSubNumaMode = Value;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+CpuNvParamSet (
+ IN CPU_VARSTORE_DATA *Configuration
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Value;
+
+ ASSERT (Configuration != NULL);
+
+ Status = NVParamGet (
+ NV_SI_SUBNUMA_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (EFI_ERROR (Status) || Value != Configuration->CpuSubNumaMode) {
+ Status = NVParamSet (
+ NV_SI_SUBNUMA_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Configuration->CpuSubNumaMode
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a %d Fail to access NVParam \n", __FUNCTION__, __LINE__));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+SetupDefaultSettings (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Value;
+
+ //
+ // Subnuma Mode
+ //
+ Status = NVParamGet (
+ NV_SI_SUBNUMA_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ Status = NVParamSet (
+ NV_SI_SUBNUMA_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ NV_SI_SUBNUMA_MODE_DEFAULT
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // ARM ERRATA 1542419 workaround
+ //
+ Status = NVParamSet (
+ NV_SI_ERRATUM_1542419_WA,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ WA_ERRATUM_1542419_DEFAULT
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Near atomic
+ //
+ Status = NVParamSet (
+ NV_SI_NEAR_ATOMIC_DISABLE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ NEAR_ATOMIC_DISABLE_DEFAULT
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // SLC Replacement Policy
+ //
+ Status = NVParamSet (
+ NV_SI_HNF_AUX_CTL_32_63,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ CPU_SLC_REPLACE_POLICY
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function allows a caller to extract the current configuration for one
+ or more named elements from the target driver.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Request A null-terminated Unicode string in
+ <ConfigRequest> format.
+ @param Progress On return, points to a character in the Request
+ string. Points to the string's null terminator if
+ request was successful. Points to the most recent
+ '&' before the first failing name/value pair (or
+ the beginning of the string if the failure is in
+ the first name/value pair) if the request was not
+ successful.
+ @param Results A null-terminated Unicode string in
+ <ConfigAltResp> format which has all values filled
+ in for the names in the Request string. String to
+ be allocated by the called function.
+
+ @retval EFI_SUCCESS The Results is filled with the requested values.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
+ @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuConfigExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ CPU_CONFIG_PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ EFI_STRING ConfigRequest;
+ EFI_STRING ConfigRequestHdr;
+ UINTN Size;
+ BOOLEAN AllocatedRequest;
+
+ if (Progress == NULL || Results == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Initialize the local variables.
+ //
+ ConfigRequestHdr = NULL;
+ ConfigRequest = NULL;
+ Size = 0;
+ *Progress = Request;
+ AllocatedRequest = FALSE;
+
+ if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gCpuConfigFormSetGuid, CpuVarstoreDataName)) {
+ return EFI_NOT_FOUND;
+ }
+
+ PrivateData = CPU_CONFIG_PRIVATE_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+
+ //
+ // Get current setting from NVParam.
+ //
+ Status = CpuNvParamGet (&PrivateData->Configuration);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ BufferSize = sizeof (CPU_VARSTORE_DATA);
+ ConfigRequest = Request;
+ if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
+ //
+ // Request has no request element, construct full request string.
+ // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+ // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
+ //
+ ConfigRequestHdr = HiiConstructConfigHdr (&gCpuConfigFormSetGuid, CpuVarstoreDataName, PrivateData->DriverHandle);
+ Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
+ ConfigRequest = AllocateZeroPool (Size);
+ ASSERT (ConfigRequest != NULL);
+ if (ConfigRequest == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ AllocatedRequest = TRUE;
+ UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
+ FreePool (ConfigRequestHdr);
+ }
+
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ Status = HiiConfigRouting->BlockToConfig (
+ HiiConfigRouting,
+ ConfigRequest,
+ (UINT8 *)&PrivateData->Configuration,
+ BufferSize,
+ Results,
+ Progress
+ );
+
+ //
+ // Free the allocated config request string.
+ //
+ if (AllocatedRequest) {
+ FreePool (ConfigRequest);
+ ConfigRequest = NULL;
+ }
+
+ //
+ // Set Progress string to the original request string.
+ //
+ if (Request == NULL) {
+ *Progress = NULL;
+ } else if (StrStr (Request, L"OFFSET") == NULL) {
+ *Progress = Request + StrLen (Request);
+ }
+
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Configuration A null-terminated Unicode string in <ConfigResp>
+ format.
+ @param Progress A pointer to a string filled in with the offset of
+ the most recent '&' before the first failing
+ name/value pair (or the beginning of the string if
+ the failure is in the first name/value pair) or
+ the terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The Results is processed successfully.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuConfigRouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ CPU_CONFIG_PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ if (Configuration == NULL || Progress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = CPU_CONFIG_PRIVATE_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+ *Progress = Configuration;
+
+ //
+ // Check routing data in <ConfigHdr>.
+ // Note: if only one Storage is used, then this checking could be skipped.
+ //
+ if (!HiiIsConfigHdrMatch (Configuration, &gCpuConfigFormSetGuid, CpuVarstoreDataName)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get configuration data from NVParam
+ //
+ Status = CpuNvParamGet (&PrivateData->Configuration);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
+ //
+ BufferSize = sizeof (CPU_VARSTORE_DATA);
+ Status = HiiConfigRouting->ConfigToBlock (
+ HiiConfigRouting,
+ Configuration,
+ (UINT8 *)&PrivateData->Configuration,
+ &BufferSize,
+ Progress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Store configuration data back to NVParam
+ //
+ Status = CpuNvParamSet (&PrivateData->Configuration);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Action Specifies the type of action taken by the browser.
+ @param QuestionId A unique value which is sent to the original
+ exporting driver so that it can identify the type
+ of data to expect.
+ @param Type The type of value for the question.
+ @param Value A pointer to the data being sent to the original
+ exporting driver.
+ @param ActionRequest On return, points to the action requested by the
+ callback function.
+
+ @retval EFI_SUCCESS The callback successfully handled the action.
+ @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuConfigCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+{
+ if (Action != EFI_BROWSER_ACTION_CHANGING) {
+ //
+ // Do nothing for other UEFI Action. Only do call back when data is changed.
+ //
+ return EFI_UNSUPPORTED;
+ }
+ if (((Value == NULL) && (Action != EFI_BROWSER_ACTION_FORM_OPEN) && (Action != EFI_BROWSER_ACTION_FORM_CLOSE))||
+ (ActionRequest == NULL))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CpuConfigDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ //
+ // Initialize driver private data
+ //
+ mPrivateData = AllocateZeroPool (sizeof (CPU_CONFIG_PRIVATE_DATA));
+ if (mPrivateData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mPrivateData->Signature = CPU_CONFIG_PRIVATE_SIGNATURE;
+
+ mPrivateData->ConfigAccess.ExtractConfig = CpuConfigExtractConfig;
+ mPrivateData->ConfigAccess.RouteConfig = CpuConfigRouteConfig;
+ mPrivateData->ConfigAccess.Callback = CpuConfigCallback;
+
+ //
+ // Locate ConfigRouting protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&HiiConfigRouting);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mPrivateData->HiiConfigRouting = HiiConfigRouting;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mDriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mCpuConfigHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mPrivateData->ConfigAccess,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ mPrivateData->DriverHandle = mDriverHandle;
+
+ //
+ // Publish our HII data
+ //
+ HiiHandle = HiiAddPackages (
+ &gCpuConfigFormSetGuid,
+ mDriverHandle,
+ CpuConfigDxeStrings,
+ CpuConfigVfrBin,
+ NULL
+ );
+ if (HiiHandle == NULL) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ mDriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mCpuConfigHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mPrivateData->ConfigAccess,
+ NULL
+ );
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mPrivateData->HiiHandle = HiiHandle;
+
+ //
+ // With the fresh system, the NVParam value is invalid (0xFFFFFFFF).
+ // It causes reading from the NVParam is failed.
+ // So, the NVParam should be setting with default values if any params is invalid.
+ //
+ Status = SetupDefaultSettings ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigStrings.uni b/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigStrings.uni
new file mode 100644
index 000000000000..70c01f65e4b6
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigStrings.uni
@@ -0,0 +1,17 @@
+//
+// Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+#langdef en-US "English"
+
+#string STR_CPU_FORM #language en-US "CPU Configuration"
+#string STR_CPU_FORM_HELP #language en-US "CPU Configuration"
+#string STR_CPU_FORM_SEPERATE_LINE #language en-US ""
+
+#string STR_CPU_SUBNUMA_MODE_PROMPT #language en-US "ANC mode"
+#string STR_CPU_SUBNUMA_MODE_HELP #language en-US "Provides 3 modes: Monolithic, Hemisphere, Quadrant. System with Monolithic mode has single NUMA partition per socket. System with Hemisphere has 2 NUMA partitions per socket. System with Quandrant has 4 NUMA partitions per socket"
+#string STR_CPU_SUBNUMA_MODE_MONOLITHIC #language en-US "Monolithic"
+#string STR_CPU_SUBNUMA_MODE_HEMISPHERE #language en-US "Hemisphere"
+#string STR_CPU_SUBNUMA_MODE_QUADRANT #language en-US "Quadrant"
--
2.17.1


Re: [PATCH v3 23/28] AmpereAltraPkg: Add configuration screen for memory

Leif Lindholm
 

On Wed, Sep 15, 2021 at 22:55:22 +0700, Nhi Pham wrote:
From: Vu Nguyen <vunguyen@os.amperecomputing.com>

Provide memory screen with below info:
* Memory total capacity
* Memory RAS and Performance Configuration
* Per DIMM Information

Cc: Thang Nguyen <thang@os.amperecomputing.com>
Cc: Chuong Tran <chuong@os.amperecomputing.com>
Cc: Phong Vo <phong@os.amperecomputing.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>

Signed-off-by: Vu Nguyen <vunguyen@os.amperecomputing.com>
---
Platform/Ampere/JadePkg/Jade.dsc | 1 +
Platform/Ampere/JadePkg/Jade.fdf | 1 +
Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf | 59 +
Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.h | 170 +++
Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenNVDataStruct.h | 47 +
Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenVfr.vfr | 62 +
Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoNvramLib.c | 394 ++++++
Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.c | 1325 ++++++++++++++++++++
Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.uni | 9 +
Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxeExtra.uni | 9 +
Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenStrings.uni | 64 +
11 files changed, 2141 insertions(+)

diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc
index f723be6997e6..5fc83745cdbc 100644
--- a/Platform/Ampere/JadePkg/Jade.dsc
+++ b/Platform/Ampere/JadePkg/Jade.dsc
@@ -197,3 +197,4 @@ [Components.common]
# HII
#
Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoDxe.inf
+ Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf
index c54b46f95ad5..6fe023025034 100644
--- a/Platform/Ampere/JadePkg/Jade.fdf
+++ b/Platform/Ampere/JadePkg/Jade.fdf
@@ -355,5 +355,6 @@ [FV.FvMain]
# HII
#
INF Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoDxe.inf
+ INF Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf

!include Platform/Ampere/AmperePlatformPkg/FvRules.fdf.inc
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
new file mode 100644
index 000000000000..fbb2ac9dad21
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
@@ -0,0 +1,59 @@
+## @file
+#
+# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = MemInfoDxe
+ MODULE_UNI_FILE = MemInfoDxe.uni
+ FILE_GUID = D9EFCEFE-189B-4599-BB07-04F0A8DF5C2F
+ MODULE_TYPE = DXE_DRIVER
+ ENTRY_POINT = MemInfoScreenInitialize
+
+[Sources]
+ MemInfoNvramLib.c
+ MemInfoScreen.c
+ MemInfoScreen.h
+ MemInfoScreenStrings.uni
+ MemInfoScreenNVDataStruct.h
+ MemInfoScreenVfr.vfr
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+ Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
+
+[LibraryClasses]
+ AmpereCpuLib
+ BaseLib
+ DevicePathLib
+ HiiLib
+ HobLib
+ MemoryAllocationLib
+ NVParamLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Guids]
+ gEfiIfrTianoGuid ## PRODUCES ## UNDEFINED
+ gPlatformManagerFormsetGuid
+ gPlatformHobGuid
+
+[Protocols]
+ gEfiDevicePathProtocolGuid ## CONSUMES
+ gEfiHiiConfigRoutingProtocolGuid ## CONSUMES
+ gEfiHiiConfigAccessProtocolGuid ## PRODUCES
+
+[Depex]
+ TRUE
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ MemInfoDxeExtra.uni
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.h
new file mode 100644
index 000000000000..4b4b498062c8
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.h
@@ -0,0 +1,170 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef MEM_INFO_SCREEN_H_
+#define MEM_INFO_SCREEN_H_
+
+#include <Uefi.h>
+
+#include <Guid/MdeModuleHii.h>
+#include <Guid/PlatformInfoHobGuid.h>
+#include <Library/AmpereCpuLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <PlatformInfoHob.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigKeyword.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
Header file should only include headers they use themselves.

+
+#include "MemInfoScreenNVDataStruct.h"
+
+//
+// This is the generated IFR binary data for each formset defined in VFR.
+// This data array is ready to be used as input of HiiAddPackages() to
+// create a packagelist (which contains Form packages, String packages, etc).
+//
+extern UINT8 MemInfoScreenVfrBin[];
+
+//
+// This is the generated String package data for all .UNI files.
+// This data array is ready to be used as input of HiiAddPackages() to
+// create a packagelist (which contains Form packages, String packages, etc).
+//
+extern UINT8 MemInfoDxeStrings[];
+
+enum DDR_ECC_MODE {
Enum style, as commented for a couple of earlier patches.

+ ECC_DISABLE = 0,
+ ECC_SECDED,
+ SYMBOL_ECC
+};
+
+enum DDR_ERROR_CTRL_MODE_DE {
+ ERRCTLR_DE_DISABLE = 0,
+ ERRCTLR_DE_ENABLE,
+};
+
+enum DDR_ERROR_CTRL_MODE_FI {
+ ERRCTLR_FI_DISABLE = 0,
+ ERRCTLR_FI_ENABLE,
+};
+
+#define MEM_INFO_DDR_SPEED_SEL_OFFSET OFFSET_OF (MEM_INFO_VARSTORE_DATA, DDRSpeedSel)
+#define MEM_INFO_ECC_MODE_SEL_OFFSET OFFSET_OF (MEM_INFO_VARSTORE_DATA, EccMode)
+#define MEM_INFO_ERR_CTRL_DE_MODE_SEL_OFFSET OFFSET_OF (MEM_INFO_VARSTORE_DATA, ErrCtrl_DE)
+#define MEM_INFO_ERR_CTRL_FI_MODE_SEL_OFFSET OFFSET_OF (MEM_INFO_VARSTORE_DATA, ErrCtrl_FI)
+#define MEM_INFO_ERR_SLAVE_32BIT_OFFSET OFFSET_OF (MEM_INFO_VARSTORE_DATA, Slave32bit)
+#define MEM_INFO_DDR_SCRUB_OFFSET OFFSET_OF (MEM_INFO_VARSTORE_DATA, ScrubPatrol)
+#define MEM_INFO_DDR_DEMAND_SCRUB_OFFSET OFFSET_OF (MEM_INFO_VARSTORE_DATA, DemandScrub)
+#define MEM_INFO_DDR_WRITE_CRC_OFFSET OFFSET_OF (MEM_INFO_VARSTORE_DATA, WriteCrc)
+#define MEM_INFO_FGR_MODE_OFFSET OFFSET_OF (MEM_INFO_VARSTORE_DATA, FGRMode)
+#define MEM_INFO_REFRESH2X_MODE_OFFSET OFFSET_OF (MEM_INFO_VARSTORE_DATA, Refresh2x)
+#define MEM_INFO_NVDIMM_MODE_SEL_OFFSET OFFSET_OF (MEM_INFO_VARSTORE_DATA, NvdimmModeSel)
+
+#define MEM_INFO_SCREEN_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('M', 'E', 'M', 'i')
+
+#define MEM_INFO_DDR_SPEED_SEL_QUESTION_ID 0x8001
+#define MEM_INFO_FORM_PERFORMANCE_QUESTION_ID 0x8002
+#define MEM_INFO_FORM_PERFORMANCE_ECC_QUESTION_ID 0x8003
+#define MEM_INFO_FORM_PERFORMANCE_ERR_CTRL_DE_QUESTION_ID 0x8004
+#define MEM_INFO_FORM_PERFORMANCE_ERR_CTRL_FI_QUESTION_ID 0x8005
+#define MEM_INFO_DDR_SLAVE_32BIT_QUESTION_ID 0x8006
+#define MEM_INFO_DDR_SCRUB_PATROL_QUESTION_ID 0x8007
+#define MEM_INFO_DDR_DEMAND_SCRUB_QUESTION_ID 0x8008
+#define MEM_INFO_DDR_WRITE_CRC_QUESTION_ID 0x8009
+#define MEM_INFO_FGR_MODE_QUESTION_ID 0x800A
+#define MEM_INFO_REFRESH2X_MODE_QUESTION_ID 0x800B
+#define MEM_INFO_FORM_NVDIMM_QUESTION_ID 0x800C
+#define MEM_INFO_FORM_NVDIMM_MODE_SEL_QUESTION_ID 0x800D
+
+#define MAX_NUMBER_OF_HOURS_IN_A_DAY 24
+
+#define DDR_DEFAULT_SCRUB_PATROL_DURATION 24
+#define DDR_DEFAULT_DEMAND_SCRUB 1
+#define DDR_DEFAULT_WRITE_CRC 0
+#define DDR_DEFAULT_FGR_MODE 0
+#define DDR_DEFAULT_REFRESH2X_MODE 0
+#define DDR_DEFAULT_NVDIMM_MODE_SEL 3
+
+#define DDR_FGR_MODE_GET(Value) ((Value) & 0x3) /* Bit 0, 1 */
+#define DDR_FGR_MODE_SET(Dst, Src) do { Dst = (((Dst) & ~0x3) | ((Src) & 0x3)); } while (0)
+
+#define DDR_REFRESH_2X_GET(Value) ((Value) & 0x10000) >> 16 /* Bit 16 only */
+#define DDR_REFRESH_2X_SET(Dst, Src) do { Dst = (((Dst) & ~0x10000) | ((Src) & 0x1) << 16); } while (0)
+
+#define DDR_NVDIMM_MODE_SEL_MASK 0x7FFFFFFF
+#define DDR_NVDIMM_MODE_SEL_VALID_BIT BIT31
+
+typedef struct {
+ UINTN Signature;
+
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE HiiHandle;
+ MEM_INFO_VARSTORE_DATA VarStoreConfig;
+
+ //
+ // Consumed protocol
+ //
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
+ EFI_HII_STRING_PROTOCOL *HiiString;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *HiiKeywordHandler;
+ EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
+
+ //
+ // Produced protocol
+ //
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+} MEM_INFO_SCREEN_PRIVATE_DATA;
+
+#define MEM_INFO_SCREEN_PRIVATE_FROM_THIS(a) CR (a, MEM_INFO_SCREEN_PRIVATE_DATA, ConfigAccess, MEM_INFO_SCREEN_PRIVATE_DATA_SIGNATURE)
+
+#pragma pack(1)
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+#pragma pack()
+
+EFI_STATUS
+MemInfoScreenInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+EFI_STATUS
+MemInfoScreenUnload (
+ IN EFI_HANDLE ImageHandle
+ );
+
+EFI_STATUS
+MemInfoNvparamGet (
+ OUT MEM_INFO_VARSTORE_DATA *VarStoreConfig
+ );
+
+EFI_STATUS
+MemInfoNvparamSet (
+ IN MEM_INFO_VARSTORE_DATA *VarStoreConfig
+ );
+
+#endif /* MEM_INFO_SCREEN_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenNVDataStruct.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenNVDataStruct.h
new file mode 100644
index 000000000000..75960c367880
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenNVDataStruct.h
@@ -0,0 +1,47 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef MEM_INFO_SCREEN_NV_DATA_STRUCT_H_
+#define MEM_INFO_SCREEN_NV_DATA_STRUCT_H_
+
+#define MEM_INFO_VARSTORE_NAME L"MemInfoIfrNVData"
+#define MEM_INFO_VARSTORE_ID 0x1234
+#define MEM_INFO_FORM_ID 0x1235
+#define MEM_INFO_FORM_PERFORMANCE_ID 0x1236
+#define MEM_INFO_FORM_NVDIMM_ID 0x1237
+#define MEM_INFO_FORM_SET_GUID { 0xd58338ee, 0xe9f7, 0x4d8d, { 0xa7, 0x08, 0xdf, 0xb2, 0xc6, 0x66, 0x1d, 0x61 } }
+#define MEM_INFO_FORM_SET_PERFORMANCE_GUID { 0x4a072c78, 0x42f9, 0x11ea, { 0xb7, 0x7f, 0x2e, 0x28, 0xce, 0x88, 0x12, 0x62 } }
+
+#pragma pack(1)
+
+//
+// NV data structure definition
+//
+typedef struct {
+ UINT32 DDRSpeedSel;
+ UINT32 EccMode;
+ UINT32 ErrCtrl_DE;
+ UINT32 ErrCtrl_FI;
+ UINT32 Slave32bit;
+ UINT32 ScrubPatrol;
+ UINT32 DemandScrub;
+ UINT32 WriteCrc;
+ UINT32 FGRMode;
+ UINT32 Refresh2x;
+ UINT32 NvdimmModeSel;
+} MEM_INFO_VARSTORE_DATA;
+
+//
+// Labels definition
+//
+#define LABEL_UPDATE 0x2223
+#define LABEL_END 0x2224
+
+#pragma pack()
+
+#endif
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenVfr.vfr b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenVfr.vfr
new file mode 100644
index 000000000000..e3d7aa0c44bd
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenVfr.vfr
@@ -0,0 +1,62 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Guid/PlatformManagerHii.h>
+#include "MemInfoScreenNVDataStruct.h"
+
+formset
+ guid = MEM_INFO_FORM_SET_GUID,
+ title = STRING_TOKEN(STR_MEM_INFO_FORM),
+ help = STRING_TOKEN(STR_MEM_INFO_FORM_HELP),
+ classguid = gPlatformManagerFormsetGuid,
+
+ //
+ // Define a variable Storage
+ //
+ varstore MEM_INFO_VARSTORE_DATA,
+ varid = MEM_INFO_VARSTORE_ID,
+ name = MemInfoIfrNVData,
+ guid = MEM_INFO_FORM_SET_GUID;
+
+ form
+ formid = MEM_INFO_FORM_ID,
+ title = STRING_TOKEN(STR_MEM_INFO_FORM);
+
+ subtitle text = STRING_TOKEN(STR_MEM_INFO_FORM);
+
+ label LABEL_UPDATE;
+ // dynamic content here
+ label LABEL_END;
+
+ endform;
+
+ form
+ formid = MEM_INFO_FORM_PERFORMANCE_ID,
+ title = STRING_TOKEN(STR_MEM_INFO_PERFORMANCE_FORM);
+
+ subtitle text = STRING_TOKEN(STR_MEM_INFO_PERFORMANCE_FORM);
+
+ label LABEL_UPDATE;
+ // dynamic content here
+ label LABEL_END;
+
+ endform;
+
+ form
+ formid = MEM_INFO_FORM_NVDIMM_ID,
+ title = STRING_TOKEN(STR_MEM_INFO_NVDIMM_FORM);
+
+ subtitle text = STRING_TOKEN(STR_MEM_INFO_NVDIMM_FORM);
+
+ label LABEL_UPDATE;
+ // dynamic content here
+ label LABEL_END;
+
+ endform;
+
+endformset;
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoNvramLib.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoNvramLib.c
new file mode 100644
index 000000000000..c83f489f4078
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoNvramLib.c
@@ -0,0 +1,394 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/NVParamLib.h>
+
+#include "MemInfoScreen.h"
+#include "NVParamDef.h"
+
+#define DDR_NVPARAM_ERRCTRL_DE_FIELD_SHIFT 0
+#define DDR_NVPARAM_ERRCTRL_DE_FIELD_MASK 0x1
+
+#define DDR_NVPARAM_ERRCTRL_FI_FIELD_SHIFT 1
+#define DDR_NVPARAM_ERRCTRL_FI_FIELD_MASK 0x2
+
+/**
+ This is function collects meminfo from NVParam
+
+ @param Data The buffer to return the contents.
+
+ @retval EFI_SUCCESS Get response data successfully.
+ @retval Other value Failed to get meminfo from NVParam
+**/
+EFI_STATUS
+MemInfoNvparamGet (
+ OUT MEM_INFO_VARSTORE_DATA *VarStoreConfig
+ )
+{
+ UINT32 Value;
+ EFI_STATUS Status;
+
+ ASSERT (VarStoreConfig != NULL);
+
+ Status = NVParamGet (
+ NV_SI_DDR_SPEED,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ VarStoreConfig->DDRSpeedSel = 0; /* Default auto mode */
+ } else {
+ VarStoreConfig->DDRSpeedSel = Value;
+ }
+
+ Status = NVParamGet (
+ NV_SI_DDR_ECC_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ VarStoreConfig->EccMode = ECC_SECDED; /* Default enable */
+ } else {
+ VarStoreConfig->EccMode = Value;
+ }
+
+ Status = NVParamGet (
+ NV_SI_DDR_ERRCTRL,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ VarStoreConfig->ErrCtrl_DE = ERRCTLR_DE_ENABLE;
+ VarStoreConfig->ErrCtrl_FI = ERRCTLR_FI_ENABLE;
+ } else {
+ VarStoreConfig->ErrCtrl_DE = (Value & DDR_NVPARAM_ERRCTRL_DE_FIELD_MASK) >> DDR_NVPARAM_ERRCTRL_DE_FIELD_SHIFT;
+ VarStoreConfig->ErrCtrl_FI = (Value & DDR_NVPARAM_ERRCTRL_FI_FIELD_MASK) >> DDR_NVPARAM_ERRCTRL_FI_FIELD_SHIFT;
+ }
+
+ Status = NVParamGet (
+ NV_SI_DDR_SLAVE_32BIT_MEM_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ VarStoreConfig->Slave32bit = 0; /* Default disabled */
+ } else {
+ VarStoreConfig->Slave32bit = Value;
+ }
+
+ Status = NVParamGet (
+ NV_SI_DDR_SCRUB_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ VarStoreConfig->ScrubPatrol = DDR_DEFAULT_SCRUB_PATROL_DURATION;
+ } else {
+ VarStoreConfig->ScrubPatrol = Value;
+ }
+
+ Status = NVParamGet (
+ NV_SI_DDR_WR_BACK_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ VarStoreConfig->DemandScrub = DDR_DEFAULT_DEMAND_SCRUB;
+ } else {
+ VarStoreConfig->DemandScrub = Value;
+ }
+
+ Status = NVParamGet (
+ NV_SI_DDR_CRC_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ VarStoreConfig->WriteCrc = DDR_DEFAULT_WRITE_CRC;
+ } else {
+ VarStoreConfig->WriteCrc = Value;
+ }
+
+ Status = NVParamGet (
+ NV_SI_DDR_REFRESH_GRANULARITY,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ VarStoreConfig->FGRMode = DDR_DEFAULT_FGR_MODE;
+ VarStoreConfig->Refresh2x = DDR_DEFAULT_REFRESH2X_MODE;
+ } else {
+ VarStoreConfig->FGRMode = DDR_FGR_MODE_GET (Value);
+ VarStoreConfig->Refresh2x = DDR_REFRESH_2X_GET (Value);
+ }
+
+ Status = NVParamGet (
+ NV_SI_NVDIMM_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status)) {
+ VarStoreConfig->NvdimmModeSel = DDR_DEFAULT_NVDIMM_MODE_SEL;
+ } else {
+ VarStoreConfig->NvdimmModeSel = Value & DDR_NVDIMM_MODE_SEL_MASK; /* Mask out valid bit */
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This is function stores meminfo to corresponding NVParam
+
+ @param VarStoreConfig The contents for the variable.
+
+ @retval EFI_SUCCESS Set data successfully.
+ @retval Other value Failed to set meminfo to NVParam
+
+**/
+EFI_STATUS
+MemInfoNvparamSet (
+ IN MEM_INFO_VARSTORE_DATA *VarStoreConfig
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Value, TmpValue, Value2, Update;
+
+ ASSERT (VarStoreConfig != NULL);
+
+ /* Set DDR speed */
+ Status = NVParamGet (
+ NV_SI_DDR_SPEED,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status) || Value != VarStoreConfig->DDRSpeedSel) {
+ Status = NVParamSet (
+ NV_SI_DDR_SPEED,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ VarStoreConfig->DDRSpeedSel
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ /* Set ECC mode */
+ Status = NVParamGet (
+ NV_SI_DDR_ECC_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status) || Value != VarStoreConfig->EccMode) {
+ Status = NVParamSet (
+ NV_SI_DDR_ECC_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ VarStoreConfig->EccMode
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ /* Set ErrCtrl */
+ TmpValue = (VarStoreConfig->ErrCtrl_DE << DDR_NVPARAM_ERRCTRL_DE_FIELD_SHIFT) |
+ (VarStoreConfig->ErrCtrl_FI << DDR_NVPARAM_ERRCTRL_FI_FIELD_SHIFT);
+ Status = NVParamGet (
+ NV_SI_DDR_ERRCTRL,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status) || Value != TmpValue ) {
+ Status = NVParamSet (
+ NV_SI_DDR_ERRCTRL,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ TmpValue
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ /* Set slave's 32bit region */
+ TmpValue = VarStoreConfig->Slave32bit;
+ Status = NVParamGet (
+ NV_SI_DDR_SLAVE_32BIT_MEM_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status) || Value != TmpValue ) {
+ if (TmpValue == 0) {
+ /* Default is disabled so just clear nvparam */
+ Status = NVParamClr (
+ NV_SI_DDR_SLAVE_32BIT_MEM_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC
+ );
+ } else {
+ Status = NVParamSet (
+ NV_SI_DDR_SLAVE_32BIT_MEM_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ TmpValue
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ /* Set Scrub patrol */
+ TmpValue = VarStoreConfig->ScrubPatrol;
+ Status = NVParamGet (
+ NV_SI_DDR_SCRUB_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status) || Value != TmpValue ) {
+ if (TmpValue == DDR_DEFAULT_SCRUB_PATROL_DURATION) {
+ Status = NVParamClr (
+ NV_SI_DDR_SCRUB_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC
+ );
+ } else {
+ Status = NVParamSet (
+ NV_SI_DDR_SCRUB_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ TmpValue
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ /* Demand Scrub */
+ TmpValue = VarStoreConfig->DemandScrub;
+ Status = NVParamGet (
+ NV_SI_DDR_WR_BACK_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status) || Value != TmpValue ) {
+ if (TmpValue == DDR_DEFAULT_DEMAND_SCRUB) {
+ Status = NVParamClr (
+ NV_SI_DDR_WR_BACK_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC
+ );
+ } else {
+ Status = NVParamSet (
+ NV_SI_DDR_WR_BACK_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU |NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ TmpValue
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ /* Write CRC */
+ TmpValue = VarStoreConfig->WriteCrc;
+ Status = NVParamGet (
+ NV_SI_DDR_CRC_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ if (EFI_ERROR (Status) || Value != TmpValue ) {
+ if (TmpValue == DDR_DEFAULT_WRITE_CRC) {
+ Status = NVParamClr (
+ NV_SI_DDR_CRC_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC
+ );
+ } else {
+ Status = NVParamSet (
+ NV_SI_DDR_CRC_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ TmpValue
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ /* Write FGR/Refresh2X */
+ Value = 0;
+ Update = 0;
+ TmpValue = VarStoreConfig->FGRMode;
+ Status = NVParamGet (
+ NV_SI_DDR_REFRESH_GRANULARITY,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ Value2 = DDR_FGR_MODE_GET (Value);
+ if ((EFI_ERROR (Status) && TmpValue != DDR_DEFAULT_FGR_MODE)
+ || Value2 != TmpValue)
+ {
+ DDR_FGR_MODE_SET (Value, TmpValue);
+ Update = 1;
+ }
+
+ Value2 = DDR_REFRESH_2X_GET (Value);
+ TmpValue = VarStoreConfig->Refresh2x;
+ if ((EFI_ERROR (Status) && TmpValue != DDR_DEFAULT_REFRESH2X_MODE)
+ || Value2 != TmpValue)
+ {
+ DDR_REFRESH_2X_SET (Value, TmpValue);
+ Update = 1;
+ }
+
+ if (Update == 1) {
+ Status = NVParamSet (
+ NV_SI_DDR_REFRESH_GRANULARITY,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Value
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ /* Write NVDIMM-N Mode selection */
+ Value = 0;
+ TmpValue = VarStoreConfig->NvdimmModeSel;
+ Status = NVParamGet (
+ NV_SI_NVDIMM_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ Value2 = Value & DDR_NVDIMM_MODE_SEL_MASK; /* Mask out valid bit */
+ if (EFI_ERROR (Status) || Value2 != TmpValue ) {
+ if (TmpValue == DDR_DEFAULT_NVDIMM_MODE_SEL) {
+ Status = NVParamClr (
+ NV_SI_NVDIMM_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC
+ );
+ } else {
+ Value = TmpValue | DDR_NVDIMM_MODE_SEL_VALID_BIT; /* Add valid bit */
+ Status = NVParamSet (
+ NV_SI_NVDIMM_MODE,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Value
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.c
new file mode 100644
index 000000000000..3a1a5840db9d
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.c
@@ -0,0 +1,1325 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MemInfoScreen.h"
+
+#define MAX_STRING_SIZE 64
+#define GB_SCALE_FACTOR (1024*1024*1024)
+#define MB_SCALE_FACTOR (1024*1024)
+
+EFI_GUID gMemInfoFormSetGuid = MEM_INFO_FORM_SET_GUID;
+
+HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ MEM_INFO_FORM_SET_GUID
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8)(END_DEVICE_PATH_LENGTH),
+ (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
+ }
+ }
+};
+
+EFI_HANDLE DriverHandle = NULL;
+MEM_INFO_SCREEN_PRIVATE_DATA *mPrivateData = NULL;
+
+/**
+ This function allows a caller to extract the current configuration for one
+ or more named elements from the target driver.
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Request A null-terminated Unicode string in
+ <ConfigRequest> format.
+ @param Progress On return, points to a character in the Request
+ string. Points to the string's null terminator if
+ request was successful. Points to the most recent
+ '&' before the first failing name/value pair (or
+ the beginning of the string if the failure is in
+ the first name/value pair) if the request was not
+ successful.
+ @param Results A null-terminated Unicode string in
+ <ConfigAltResp> format which has all values filled
+ in for the names in the Request string. String to
+ be allocated by the called function.
+ @retval EFI_SUCCESS The Results is filled with the requested values.
+ @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+**/
+EFI_STATUS
+EFIAPI
+ExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ MEM_INFO_SCREEN_PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ EFI_STRING ConfigRequest;
+ EFI_STRING ConfigRequestHdr;
+ UINTN Size;
+ CHAR16 *StrPointer;
+ BOOLEAN AllocatedRequest;
+
+ if (Progress == NULL || Results == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Initialize the local variables.
+ //
+ ConfigRequestHdr = NULL;
+ ConfigRequest = NULL;
+ Size = 0;
+ *Progress = Request;
+ AllocatedRequest = FALSE;
+
+ PrivateData = MEM_INFO_SCREEN_PRIVATE_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+
+ //
+ // Get Buffer Storage data from EFI variable.
+ // Try to get the current setting from variable.
+ //
+ BufferSize = sizeof (MEM_INFO_VARSTORE_DATA);
+ Status = MemInfoNvparamGet (&PrivateData->VarStoreConfig);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (Request == NULL) {
+ //
+ // Request is set to NULL, construct full request string.
+ //
+
+ //
+ // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+ // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
+ //
+ ConfigRequestHdr = HiiConstructConfigHdr (&gMemInfoFormSetGuid, MEM_INFO_VARSTORE_NAME, PrivateData->DriverHandle);
+ Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
+ ConfigRequest = AllocateZeroPool (Size);
+ ASSERT (ConfigRequest != NULL);
+ AllocatedRequest = TRUE;
+ UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
+ FreePool (ConfigRequestHdr);
+ ConfigRequestHdr = NULL;
+ } else {
+ //
+ // Check routing data in <ConfigHdr>.
+ // Note: if only one Storage is used, then this checking could be skipped.
+ //
+ if (!HiiIsConfigHdrMatch (Request, &gMemInfoFormSetGuid, NULL)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Set Request to the unified request string.
+ //
+ ConfigRequest = Request;
+
+ //
+ // Check whether Request includes Request Element.
+ //
+ if (StrStr (Request, L"OFFSET") == NULL) {
+ //
+ // Check Request Element does exist in Request String
+ //
+ StrPointer = StrStr (Request, L"PATH");
+ if (StrPointer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (StrStr (StrPointer, L"&") == NULL) {
+ Size = (StrLen (Request) + 32 + 1) * sizeof (CHAR16);
+ ConfigRequest = AllocateZeroPool (Size);
+ ASSERT (ConfigRequest != NULL);
+ AllocatedRequest = TRUE;
+ UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", Request, (UINT64)BufferSize);
+ }
+ }
+ }
+
+ //
+ // Check if requesting Name/Value storage
+ //
+ if (StrStr (ConfigRequest, L"OFFSET") == NULL) {
+ //
+ // Don't have any Name/Value storage names
+ //
+ Status = EFI_SUCCESS;
+ } else {
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ Status = HiiConfigRouting->BlockToConfig (
+ HiiConfigRouting,
+ ConfigRequest,
+ (UINT8 *)&PrivateData->VarStoreConfig,
+ BufferSize,
+ Results,
+ Progress
+ );
+ }
+
+ //
+ // Free the allocated config request string.
+ //
+ if (AllocatedRequest) {
+ FreePool (ConfigRequest);
+ }
+
+ if (ConfigRequestHdr != NULL) {
+ FreePool (ConfigRequestHdr);
+ }
+ //
+ // Set Progress string to the original request string.
+ //
+ if (Request == NULL) {
+ *Progress = NULL;
+ } else if (StrStr (Request, L"OFFSET") == NULL) {
+ *Progress = Request + StrLen (Request);
+ }
+
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Configuration A null-terminated Unicode string in <ConfigResp>
+ format.
+ @param Progress A pointer to a string filled in with the offset of
+ the most recent '&' before the first failing
+ name/value pair (or the beginning of the string if
+ the failure is in the first name/value pair) or
+ the terminating NULL if all was successful.
+ @retval EFI_SUCCESS The Results is processed successfully.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+**/
+EFI_STATUS
+EFIAPI
+RouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ MEM_INFO_SCREEN_PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ if (Configuration == NULL || Progress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = MEM_INFO_SCREEN_PRIVATE_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+ *Progress = Configuration;
+
+ //
+ // Check routing data in <ConfigHdr>.
+ // Note: if only one Storage is used, then this checking could be skipped.
+ //
+ if (!HiiIsConfigHdrMatch (Configuration, &gMemInfoFormSetGuid, NULL)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get Buffer Storage data from NVParam
+ //
+ Status = MemInfoNvparamGet (&PrivateData->VarStoreConfig);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Check if configuring Name/Value storage
+ //
+ if (StrStr (Configuration, L"OFFSET") == NULL) {
+ //
+ // Don't have any Name/Value storage names
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
+ //
+ BufferSize = sizeof (MEM_INFO_VARSTORE_DATA);
+ Status = HiiConfigRouting->ConfigToBlock (
+ HiiConfigRouting,
+ Configuration,
+ (UINT8 *)&PrivateData->VarStoreConfig,
+ &BufferSize,
+ Progress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Store Buffer Storage back to NVParam
+ //
+ Status = MemInfoNvparamSet (&PrivateData->VarStoreConfig);
+
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Action Specifies the type of action taken by the browser.
+ @param QuestionId A unique value which is sent to the original
+ exporting driver so that it can identify the type
+ of data to expect.
+ @param Type The type of value for the question.
+ @param Value A pointer to the data being sent to the original
+ exporting driver.
+ @param ActionRequest On return, points to the action requested by the
+ callback function.
+ @retval EFI_SUCCESS The callback successfully handled the action.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_UNSUPPORTED The specified Action is not supported by the
+ callback.
+**/
+EFI_STATUS
+EFIAPI
+DriverCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+{
+ if (((Value == NULL) && (Action != EFI_BROWSER_ACTION_FORM_OPEN)
+ && (Action != EFI_BROWSER_ACTION_FORM_CLOSE))
+ || (ActionRequest == NULL))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (Action) {
+ case EFI_BROWSER_ACTION_FORM_OPEN:
+ case EFI_BROWSER_ACTION_FORM_CLOSE:
+ break;
+
+ case EFI_BROWSER_ACTION_DEFAULT_STANDARD:
+ case EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING:
+ {
+ switch (QuestionId) {
+ case MEM_INFO_DDR_SPEED_SEL_QUESTION_ID:
+ //
+ // DDR speed selection default to auto
+ //
+ Value->u32 = 0;
+ break;
+
+ case MEM_INFO_FORM_PERFORMANCE_ECC_QUESTION_ID:
+ //
+ // ECC mode default to be enabled
+ //
+ Value->u32 = ECC_SECDED;
+ break;
+
+ case MEM_INFO_FORM_PERFORMANCE_ERR_CTRL_DE_QUESTION_ID:
+ //
+ // ErrCtrl_DE default to be enabled
+ //
+ Value->u32 = ERRCTLR_DE_ENABLE;
+ break;
+
+ case MEM_INFO_FORM_PERFORMANCE_ERR_CTRL_FI_QUESTION_ID:
+ //
+ // ErrCtrl_FI default to be enabled
+ //
+ Value->u32 = ERRCTLR_FI_ENABLE;
+ break;
+
+ case MEM_INFO_DDR_SLAVE_32BIT_QUESTION_ID:
+ //
+ // Slave's 32bit region to be disabled
+ //
+ Value->u32 = 0;
+ break;
+
+ case MEM_INFO_DDR_SCRUB_PATROL_QUESTION_ID:
+ Value->u32 = DDR_DEFAULT_SCRUB_PATROL_DURATION;
+ break;
+
+ case MEM_INFO_DDR_DEMAND_SCRUB_QUESTION_ID:
+ Value->u32 = DDR_DEFAULT_DEMAND_SCRUB;
+ break;
+
+ case MEM_INFO_DDR_WRITE_CRC_QUESTION_ID:
+ Value->u32 = DDR_DEFAULT_WRITE_CRC;
+ break;
+
+ case MEM_INFO_FGR_MODE_QUESTION_ID:
+ Value->u32 = DDR_DEFAULT_FGR_MODE;
+ break;
+
+ case MEM_INFO_REFRESH2X_MODE_QUESTION_ID:
+ Value->u32 = DDR_DEFAULT_REFRESH2X_MODE;
+ break;
+
+ case MEM_INFO_FORM_NVDIMM_MODE_SEL_QUESTION_ID:
+ Value->u32 = DDR_DEFAULT_NVDIMM_MODE_SEL;
+ break;
+ }
+ }
+ break;
+
+ case EFI_BROWSER_ACTION_RETRIEVE:
+ case EFI_BROWSER_ACTION_CHANGING:
+ case EFI_BROWSER_ACTION_SUBMITTED:
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MemInfoMainScreen (
+ PLATFORM_INFO_HOB *PlatformHob
+ )
+{
+ MEM_INFO_SCREEN_PRIVATE_DATA *PrivateData = mPrivateData;
+ EFI_STATUS Status;
+ VOID *StartOpCodeHandle;
+ VOID *OptionsOpCodeHandle;
+ VOID *OptionsOpCodeHandle1;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ EFI_STRING_ID StringId;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *EndLabel;
+ CHAR16 Str[MAX_STRING_SIZE], Str1[MAX_STRING_SIZE];
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResHob;
+ PLATFORM_DIMM_INFO *DimmInfo;
+ UINT64 Size;
+ UINTN Count;
A lot of variables for a single function.

/
Leif

+
+ //
+ // Get Buffer Storage data from EFI variable
+ //
+ Status = MemInfoNvparamGet (&PrivateData->VarStoreConfig);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = EFI_SUCCESS;
+
+ /* Update Total memory */
+ UnicodeSPrint (Str, sizeof (Str), L"%d GB", PlatformHob->DramInfo.TotalSize / GB_SCALE_FACTOR);
+ HiiSetString (
+ PrivateData->HiiHandle,
+ STRING_TOKEN (STR_MEM_INFO_TOTAL_MEM_VALUE),
+ Str,
+ NULL
+ );
+
+ /* Update effective memory */
+ Size = 0;
+ ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
+ while (ResHob != NULL) {
+ if ((ResHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY)) {
+ Size += ResHob->ResourceLength;
+ }
+ ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));
+ }
+ UnicodeSPrint (Str, sizeof (Str), L"%d GB", Size / GB_SCALE_FACTOR);
+ HiiSetString (
+ PrivateData->HiiHandle,
+ STRING_TOKEN (STR_MEM_INFO_EFFECT_MEM_VALUE),
+ Str,
+ NULL
+ );
+
+ /* Update current DDR speed */
+ UnicodeSPrint (Str, sizeof (Str), L"%d MHz", PlatformHob->DramInfo.MaxSpeed);
+ HiiSetString (
+ PrivateData->HiiHandle,
+ STRING_TOKEN (STR_MEM_INFO_CURRENT_SPEED_VALUE),
+ Str,
+ NULL
+ );
+
+ //
+ // Initialize the container for dynamic opcodes
+ //
+ StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (StartOpCodeHandle != NULL);
+
+ EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (EndOpCodeHandle != NULL);
+
+ //
+ // Create Option OpCode to display speed configuration
+ //
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ //
+ // Create Option OpCode to display FGR mode configuration
+ //
+ OptionsOpCodeHandle1 = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle1 != NULL);
+
+ //
+ // Create Hii Extend Label OpCode as the start opcode
+ //
+ StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ StartLabel->Number = LABEL_UPDATE;
+
+ //
+ // Create Hii Extend Label OpCode as the end opcode
+ //
+ EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ EndLabel->Number = LABEL_END;
+
+ //
+ // Create a total mem title
+ //
+ HiiCreateTextOpCode (
+ StartOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_TOTAL_MEM),
+ STRING_TOKEN (STR_MEM_INFO_TOTAL_MEM),
+ STRING_TOKEN (STR_MEM_INFO_TOTAL_MEM_VALUE)
+ );
+
+ //
+ // Create a effective mem title
+ //
+ HiiCreateTextOpCode (
+ StartOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_EFFECT_MEM),
+ STRING_TOKEN (STR_MEM_INFO_EFFECT_MEM),
+ STRING_TOKEN (STR_MEM_INFO_EFFECT_MEM_VALUE)
+ );
+
+ //
+ // Create a current speed title
+ //
+ HiiCreateTextOpCode (
+ StartOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_CURRENT_SPEED),
+ STRING_TOKEN (STR_MEM_INFO_CURRENT_SPEED),
+ STRING_TOKEN (STR_MEM_INFO_CURRENT_SPEED_VALUE)
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_VALUE0),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 0
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_VALUE1),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 2133
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_VALUE2),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 2400
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_VALUE3),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 2666
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_VALUE4),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 2933
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_VALUE5),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 3200
+ );
+
+ HiiCreateOneOfOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ MEM_INFO_DDR_SPEED_SEL_QUESTION_ID, // Question ID (or call it "key")
+ MEM_INFO_VARSTORE_ID, // VarStore ID
+ (UINT16)MEM_INFO_DDR_SPEED_SEL_OFFSET, // Offset in Buffer Storage
+ STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_PROMPT), // Question prompt text
+ STRING_TOKEN (STR_MEM_INFO_SPEED_SELECT_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED, // Question flag
+ EFI_IFR_NUMERIC_SIZE_4, // Data type of Question Value
+ OptionsOpCodeHandle, // Option Opcode list
+ NULL // Default Opcode is NULl
+ );
+
+ if (IsSlaveSocketActive ()) {
+ /* Display enable slave's 32bit region */
+ HiiCreateCheckBoxOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ MEM_INFO_DDR_SLAVE_32BIT_QUESTION_ID, // Question ID
+ MEM_INFO_VARSTORE_ID, // VarStore ID
+ (UINT16)MEM_INFO_ERR_SLAVE_32BIT_OFFSET, // Offset in Buffer Storage
+ STRING_TOKEN (STR_MEM_INFO_ENABLE_32GB_SLAVE_PROMPT), // Question prompt text
+ STRING_TOKEN (STR_MEM_INFO_ENABLE_32GB_SLAVE_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED,
+ 0,
+ NULL
+ );
+ }
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle1,
+ STRING_TOKEN (STR_MEM_INFO_FGR_MODE_VALUE0),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 0
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle1,
+ STRING_TOKEN (STR_MEM_INFO_FGR_MODE_VALUE1),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 1
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle1,
+ STRING_TOKEN (STR_MEM_INFO_FGR_MODE_VALUE2),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 2
+ );
+
+ HiiCreateOneOfOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ MEM_INFO_FGR_MODE_QUESTION_ID, // Question ID (or call it "key")
+ MEM_INFO_VARSTORE_ID, // VarStore ID
+ (UINT16)MEM_INFO_FGR_MODE_OFFSET, // Offset in Buffer Storage
+ STRING_TOKEN (STR_MEM_INFO_FGR_MODE_PROMPT), // Question prompt text
+ STRING_TOKEN (STR_MEM_INFO_FGR_MODE_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED, // Question flag
+ EFI_IFR_NUMERIC_SIZE_4, // Data type of Question Value
+ OptionsOpCodeHandle1, // Option Opcode list
+ NULL // Default Opcode is NULl
+ );
+
+ //
+ // Create a Goto OpCode to ras memory configuration
+ //
+ HiiCreateGotoOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ MEM_INFO_FORM_PERFORMANCE_ID, // Target Form ID
+ STRING_TOKEN (STR_MEM_INFO_PERFORMANCE_FORM), // Prompt text
+ STRING_TOKEN (STR_MEM_INFO_PERFORMANCE_FORM_HELP), // Help text
+ 0, // Question flag
+ MEM_INFO_FORM_PERFORMANCE_QUESTION_ID // Question ID
+ );
+
+ //
+ // Create a Goto OpCode to nvdimm-n configuration
+ //
+ HiiCreateGotoOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ MEM_INFO_FORM_NVDIMM_ID, // Target Form ID
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_FORM), // Prompt text
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_FORM_HELP), // Help text
+ 0, // Question flag
+ MEM_INFO_FORM_NVDIMM_QUESTION_ID // Question ID
+ );
+
+ //
+ // Display DIMM list info
+ //
+ HiiCreateSubTitleOpCode (
+ StartOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_DIMM_INFO),
+ 0,
+ 0,
+ 0
+ );
+
+ for (Count = 0; Count < PlatformHob->DimmList.BoardDimmSlots; Count++) {
+ DimmInfo = &PlatformHob->DimmList.Dimm[Count].Info;
+ switch (DimmInfo->DimmType) {
+ case UDIMM:
+ UnicodeSPrint (Str, sizeof (Str), L"%s", L"UDIMM");
+ break;
+
+ case RDIMM:
+ UnicodeSPrint (Str, sizeof (Str), L"%s", L"RDIMM");
+ break;
+
+ case SODIMM:
+ UnicodeSPrint (Str, sizeof (Str), L"%s", L"SODIMM");
+ break;
+
+ case LRDIMM:
+ UnicodeSPrint (Str, sizeof (Str), L"%s", L"LRDIMM");
+ break;
+
+ case RSODIMM:
+ UnicodeSPrint (Str, sizeof (Str), L"%s", L"RSODIMM");
+ break;
+
+ case NVRDIMM:
+ UnicodeSPrint (Str, sizeof (Str), L"%s", L"NV-RDIMM");
+ break;
+
+ default:
+ UnicodeSPrint (Str, sizeof (Str), L"Unknown Type");
+ }
+ if (DimmInfo->DimmStatus == DIMM_INSTALLED_OPERATIONAL) {
+ UnicodeSPrint (Str1, sizeof (Str1), L"Slot %2d: %d GB %s Installed&Operational", Count + 1, DimmInfo->DimmSize, Str);
+ } else if (DimmInfo->DimmStatus == DIMM_NOT_INSTALLED) {
+ UnicodeSPrint (Str1, sizeof (Str1), L"Slot %2d: Not Installed", Count + 1, PlatformHob->DimmList.Dimm[Count].NodeId);
+ } else if (DimmInfo->DimmStatus == DIMM_INSTALLED_NONOPERATIONAL) {
+ UnicodeSPrint (Str1, sizeof (Str1), L"Slot %2d: Installed&Non-Operational", Count + 1, PlatformHob->DimmList.Dimm[Count].NodeId);
+ } else {
+ UnicodeSPrint (Str1, sizeof (Str1), L"Slot %2d: Installed&Failed", Count + 1, PlatformHob->DimmList.Dimm[Count].NodeId);
+ }
+
+ StringId = HiiSetString (PrivateData->HiiHandle, 0, Str1, NULL);
+
+ HiiCreateSubTitleOpCode (
+ StartOpCodeHandle,
+ StringId,
+ 0,
+ 0,
+ 0
+ );
+ }
+
+ HiiUpdateForm (
+ PrivateData->HiiHandle, // HII handle
+ &gMemInfoFormSetGuid, // Formset GUID
+ MEM_INFO_FORM_ID, // Form ID
+ StartOpCodeHandle, // Label for where to insert opcodes
+ EndOpCodeHandle // Insert data
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+
+ return Status;
+}
+
+EFI_STATUS
+MemInfoMainPerformanceScreen (
+ PLATFORM_INFO_HOB *PlatformHob
+ )
+{
+ EFI_STATUS Status;
+ MEM_INFO_SCREEN_PRIVATE_DATA *PrivateData = mPrivateData;
+ VOID *StartOpCodeHandle;
+ VOID *OptionsEccOpCodeHandle, *OptionsScrubOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *EndLabel;
+ EFI_STRING_ID StringId;
+ CHAR16 Str[MAX_STRING_SIZE];
+ UINTN Idx;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Initialize the container for dynamic opcodes
+ //
+ StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (StartOpCodeHandle != NULL);
+
+ EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (EndOpCodeHandle != NULL);
+
+ //
+ // Create Hii Extend Label OpCode as the start opcode
+ //
+ StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ StartLabel->Number = LABEL_UPDATE;
+
+ //
+ // Create Hii Extend Label OpCode as the end opcode
+ //
+ EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ EndLabel->Number = LABEL_END;
+
+ /* Display ECC mode selection */
+ OptionsEccOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsEccOpCodeHandle != NULL);
+
+ UnicodeSPrint (Str, sizeof (Str), L"Disabled");
+ StringId = HiiSetString (PrivateData->HiiHandle, 0, Str, NULL);
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsEccOpCodeHandle,
+ StringId,
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 0
+ );
+
+ UnicodeSPrint (Str, sizeof (Str), L"SECDED");
+ StringId = HiiSetString (PrivateData->HiiHandle, 0, Str, NULL);
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsEccOpCodeHandle,
+ StringId,
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 1
+ );
+
+ UnicodeSPrint (Str, sizeof (Str), L"Symbol");
+ StringId = HiiSetString (PrivateData->HiiHandle, 0, Str, NULL);
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsEccOpCodeHandle,
+ StringId,
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 2
+ );
+
+ HiiCreateOneOfOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ MEM_INFO_FORM_PERFORMANCE_ECC_QUESTION_ID, // Question ID (or call it "key")
+ MEM_INFO_VARSTORE_ID, // VarStore ID
+ (UINT16)MEM_INFO_ECC_MODE_SEL_OFFSET, // Offset in Buffer Storage
+ STRING_TOKEN (STR_MEM_INFO_ENABLE_ECC_PROMPT), // Question prompt text
+ STRING_TOKEN (STR_MEM_INFO_ENABLE_ECC_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED, // Question flag
+ EFI_IFR_NUMERIC_SIZE_4, // Data type of Question Value
+ OptionsEccOpCodeHandle, // Option Opcode list
+ NULL // Default Opcode is NULl
+ );
+
+ /*
+ * Display ErrCtrl options
+ */
+ HiiCreateCheckBoxOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ MEM_INFO_FORM_PERFORMANCE_ERR_CTRL_DE_QUESTION_ID, // Question ID
+ MEM_INFO_VARSTORE_ID, // VarStore ID
+ (UINT16)MEM_INFO_ERR_CTRL_DE_MODE_SEL_OFFSET, // Offset in Buffer Storage
+ STRING_TOKEN (STR_MEM_INFO_ENABLE_ERRCTRL_DE_PROMPT), // Question prompt text
+ STRING_TOKEN (STR_MEM_INFO_ENABLE_ERRCTRL_DE_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED,
+ 0,
+ NULL
+ );
+
+ HiiCreateCheckBoxOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ MEM_INFO_FORM_PERFORMANCE_ERR_CTRL_FI_QUESTION_ID, // Question ID
+ MEM_INFO_VARSTORE_ID, // VarStore ID
+ (UINT16)MEM_INFO_ERR_CTRL_FI_MODE_SEL_OFFSET, // Offset in Buffer Storage
+ STRING_TOKEN (STR_MEM_INFO_ENABLE_ERRCTRL_FI_PROMPT), // Question prompt text
+ STRING_TOKEN (STR_MEM_INFO_ENABLE_ERRCTRL_FI_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED,
+ 0,
+ NULL
+ );
+
+ /* Display Scrub Patrol selection */
+ OptionsScrubOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsScrubOpCodeHandle != NULL);
+
+ UnicodeSPrint (Str, sizeof (Str), L"Disabled");
+ StringId = HiiSetString (PrivateData->HiiHandle, 0, Str, NULL);
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsScrubOpCodeHandle,
+ StringId,
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 0
+ );
+
+ for (Idx = 1; Idx <= MAX_NUMBER_OF_HOURS_IN_A_DAY; Idx++) {
+ UnicodeSPrint (Str, sizeof (Str), L"%d", Idx);
+ StringId = HiiSetString (
+ PrivateData->HiiHandle,
+ 0,
+ Str,
+ NULL
+ );
+ HiiCreateOneOfOptionOpCode (
+ OptionsScrubOpCodeHandle,
+ StringId,
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ Idx
+ );
+ }
+
+ HiiCreateOneOfOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ MEM_INFO_DDR_SCRUB_PATROL_QUESTION_ID, // Question ID (or call it "key")
+ MEM_INFO_VARSTORE_ID, // VarStore ID
+ (UINT16)MEM_INFO_DDR_SCRUB_OFFSET, // Offset in Buffer Storage
+ STRING_TOKEN (STR_MEM_INFO_ENABLE_SCRUB), // Question prompt text
+ STRING_TOKEN (STR_MEM_INFO_ENABLE_SCRUB_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED, // Question flag
+ EFI_IFR_NUMERIC_SIZE_4, // Data type of Question Value
+ OptionsScrubOpCodeHandle, // Option Opcode list
+ NULL // Default Opcode is NULl
+ );
+
+ /*
+ * Display Demand Scrub options
+ */
+ HiiCreateCheckBoxOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ MEM_INFO_DDR_DEMAND_SCRUB_QUESTION_ID, // Question ID
+ MEM_INFO_VARSTORE_ID, // VarStore ID
+ (UINT16)MEM_INFO_DDR_DEMAND_SCRUB_OFFSET, // Offset in Buffer Storage
+ STRING_TOKEN (STR_MEM_INFO_ENABLE_DEMAND_SCRUB_PROMPT), // Question prompt text
+ STRING_TOKEN (STR_MEM_INFO_ENABLE_DEMAND_SCRUB_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED,
+ 0,
+ NULL
+ );
+
+ /*
+ * Display Write CRC options
+ */
+ HiiCreateCheckBoxOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ MEM_INFO_DDR_WRITE_CRC_QUESTION_ID, // Question ID
+ MEM_INFO_VARSTORE_ID, // VarStore ID
+ (UINT16)MEM_INFO_DDR_WRITE_CRC_OFFSET, // Offset in Buffer Storage
+ STRING_TOKEN (STR_MEM_INFO_ENABLE_WRITE_CRC_PROMPT), // Question prompt text
+ STRING_TOKEN (STR_MEM_INFO_ENABLE_WRITE_CRC_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED,
+ 0,
+ NULL
+ );
+
+ /*
+ * Display CVE-2020-10255 options
+ */
+ HiiCreateCheckBoxOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ MEM_INFO_REFRESH2X_MODE_QUESTION_ID, // Question ID
+ MEM_INFO_VARSTORE_ID, // VarStore ID
+ (UINT16)MEM_INFO_REFRESH2X_MODE_OFFSET, // Offset in Buffer Storage
+ STRING_TOKEN (STR_MEM_INFO_REFRESH2X_MODE_PROMPT), // Question prompt text
+ STRING_TOKEN (STR_MEM_INFO_REFRESH2X_MODE_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED,
+ 0,
+ NULL
+ );
+
+ HiiUpdateForm (
+ PrivateData->HiiHandle, // HII handle
+ &gMemInfoFormSetGuid, // Formset GUID
+ MEM_INFO_FORM_PERFORMANCE_ID, // Form ID
+ StartOpCodeHandle, // Label for where to insert opcodes
+ EndOpCodeHandle // Insert data
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+ HiiFreeOpCodeHandle (OptionsEccOpCodeHandle);
+ HiiFreeOpCodeHandle (OptionsScrubOpCodeHandle);
+
+ return Status;
+}
+
+EFI_STATUS
+MemInfoMainNvdimmScreen (
+ PLATFORM_INFO_HOB *PlatformHob
+ )
+{
+ EFI_STATUS Status;
+ MEM_INFO_SCREEN_PRIVATE_DATA *PrivateData;
+ VOID *StartOpCodeHandle;
+ VOID *OptionsOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *EndLabel;
+ CHAR16 Str[MAX_STRING_SIZE];
+
+ Status = EFI_SUCCESS;
+ PrivateData = mPrivateData;
+
+ if (PlatformHob == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Initialize the container for dynamic opcodes
+ //
+ StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (StartOpCodeHandle != NULL);
+
+ EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (EndOpCodeHandle != NULL);
+
+ //
+ // Create Hii Extend Label OpCode as the start opcode
+ //
+ StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
+ StartOpCodeHandle,
+ &gEfiIfrTianoGuid,
+ NULL,
+ sizeof (EFI_IFR_GUID_LABEL)
+ );
+ StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ StartLabel->Number = LABEL_UPDATE;
+
+ //
+ // Create Hii Extend Label OpCode as the end opcode
+ //
+ EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
+ EndOpCodeHandle,
+ &gEfiIfrTianoGuid,
+ NULL,
+ sizeof (EFI_IFR_GUID_LABEL)
+ );
+ EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ EndLabel->Number = LABEL_END;
+
+ //
+ // Update Current NVDIMM-N Mode title Socket0
+ //
+ switch (PlatformHob->DramInfo.NvdimmMode[0]) {
+ case 0:
+ UnicodeSPrint (Str, sizeof (Str), L"%s", L"Non-NVDIMM");
+ break;
+
+ case 1:
+ UnicodeSPrint (Str, sizeof (Str), L"%s", L"Non-Hashed");
+ break;
+
+ case 2:
+ UnicodeSPrint (Str, sizeof (Str), L"%s", L"Hashed");
+ break;
+
+ default:
+ UnicodeSPrint (Str, sizeof (Str), L"%s", L"Unknown");
+ break;
+ }
+
+ HiiSetString (
+ PrivateData->HiiHandle,
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK0_VALUE),
+ Str,
+ NULL
+ );
+
+ HiiCreateTextOpCode (
+ StartOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK0),
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK0),
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK0_VALUE)
+ );
+
+ //
+ // Update Current NVDIMM-N Mode title Socket1
+ //
+ if (IsSlaveSocketActive ()) {
+ switch (PlatformHob->DramInfo.NvdimmMode[1]) {
+ case 0:
+ UnicodeSPrint (Str, sizeof (Str), L"%s", L"Non-NVDIMM");
+ break;
+
+ case 1:
+ UnicodeSPrint (Str, sizeof (Str), L"%s", L"Non-Hashed");
+ break;
+
+ case 2:
+ UnicodeSPrint (Str, sizeof (Str), L"%s", L"Hashed");
+ break;
+
+ default:
+ UnicodeSPrint (Str, sizeof (Str), L"%s", L"Unknown");
+ break;
+ }
+
+ HiiSetString (
+ PrivateData->HiiHandle,
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK1_VALUE),
+ Str,
+ NULL
+ );
+
+ HiiCreateTextOpCode (
+ StartOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK1),
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK1),
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_CUR_MODE_SK1_VALUE)
+ );
+ }
+ //
+ // Create Option OpCode to NVDIMM-N Mode Selection
+ //
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ //
+ // Create OpCode to NVDIMM-N Mode Selection
+ //
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE0),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 0
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE1),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 1
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE2),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 2
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE3),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_4,
+ 3
+ );
+
+ HiiCreateOneOfOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ MEM_INFO_FORM_NVDIMM_MODE_SEL_QUESTION_ID, // Question ID (or call it "key")
+ MEM_INFO_VARSTORE_ID, // VarStore ID
+ (UINT16)MEM_INFO_NVDIMM_MODE_SEL_OFFSET, // Offset in Buffer Storage
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_MODE_SEL_PROMPT), // Question prompt text
+ STRING_TOKEN (STR_MEM_INFO_NVDIMM_MODE_SEL_HELP), // Question help text
+ EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED, // Question flag
+ EFI_IFR_NUMERIC_SIZE_4, // Data type of Question Value
+ OptionsOpCodeHandle, // Option Opcode list
+ NULL // Default Opcode is NULl
+ );
+
+ HiiUpdateForm (
+ PrivateData->HiiHandle, // HII handle
+ &gMemInfoFormSetGuid, // Formset GUID
+ MEM_INFO_FORM_NVDIMM_ID, // Form ID
+ StartOpCodeHandle, // Label for where to insert opcodes
+ EndOpCodeHandle // Insert data
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+
+ return Status;
+}
+
+/**
+ This function sets up the first elements of the form.
+ @param PrivateData Private data.
+ @retval EFI_SUCCESS The form is set up successfully.
+**/
+EFI_STATUS
+MemInfoScreenSetup (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ VOID *Hob;
+ PLATFORM_INFO_HOB *PlatformHob;
+
+ /* Get the Platform HOB */
+ Hob = GetFirstGuidHob (&gPlatformHobGuid);
+ if (Hob == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ PlatformHob = (PLATFORM_INFO_HOB *)GET_GUID_HOB_DATA (Hob);
+
+ Status = MemInfoMainScreen (PlatformHob);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = MemInfoMainPerformanceScreen (PlatformHob);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = MemInfoMainNvdimmScreen (PlatformHob);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MemInfoScreenInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ BOOLEAN ActionFlag;
+ EFI_STRING ConfigRequestHdr;
+
+ //
+ // Initialize driver private data
+ //
+ mPrivateData = AllocateZeroPool (sizeof (MEM_INFO_SCREEN_PRIVATE_DATA));
+ if (mPrivateData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mPrivateData->Signature = MEM_INFO_SCREEN_PRIVATE_DATA_SIGNATURE;
+
+ mPrivateData->ConfigAccess.ExtractConfig = ExtractConfig;
+ mPrivateData->ConfigAccess.RouteConfig = RouteConfig;
+ mPrivateData->ConfigAccess.Callback = DriverCallback;
+
+ //
+ // Locate ConfigRouting protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&HiiConfigRouting);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mPrivateData->HiiConfigRouting = HiiConfigRouting;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mPrivateData->ConfigAccess,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ mPrivateData->DriverHandle = DriverHandle;
+
+ //
+ // Publish our HII data
+ //
+ HiiHandle = HiiAddPackages (
+ &gMemInfoFormSetGuid,
+ DriverHandle,
+ MemInfoDxeStrings,
+ MemInfoScreenVfrBin,
+ NULL
+ );
+ if (HiiHandle == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mPrivateData->HiiHandle = HiiHandle;
+
+ //
+ // Try to read NV config EFI variable first
+ //
+ ConfigRequestHdr = HiiConstructConfigHdr (
+ &gMemInfoFormSetGuid,
+ MEM_INFO_VARSTORE_NAME,
+ DriverHandle
+ );
+ ASSERT (ConfigRequestHdr != NULL);
+
+ //
+ // Validate Current Setting
+ //
+ ActionFlag = HiiValidateSettings (ConfigRequestHdr);
+ if (!ActionFlag) {
+ MemInfoScreenUnload (ImageHandle);
+ return EFI_INVALID_PARAMETER;
+ }
+ FreePool (ConfigRequestHdr);
+
+ Status = MemInfoScreenSetup ();
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MemInfoScreenUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ ASSERT (mPrivateData != NULL);
+
+ if (DriverHandle != NULL) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mPrivateData->ConfigAccess,
+ NULL
+ );
+ DriverHandle = NULL;
+ }
+
+ if (mPrivateData->HiiHandle != NULL) {
+ HiiRemovePackages (mPrivateData->HiiHandle);
+ }
+
+ FreePool (mPrivateData);
+ mPrivateData = NULL;
+
+ return EFI_SUCCESS;
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.uni b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.uni
new file mode 100644
index 000000000000..a8c7cb99d6a7
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.uni
@@ -0,0 +1,9 @@
+//
+// Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+#string STR_MODULE_ABSTRACT #language en-US "An Altra DDR screen setup driver"
+
+#string STR_MODULE_DESCRIPTION #language en-US "This driver exposes a screen setup for DDR information and configuration."
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxeExtra.uni b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxeExtra.uni
new file mode 100644
index 000000000000..f44f210594be
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxeExtra.uni
@@ -0,0 +1,9 @@
+//
+// Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Ampere Altra MemInfo DXE Driver"
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenStrings.uni b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenStrings.uni
new file mode 100644
index 000000000000..d170f9ee7313
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenStrings.uni
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+#langdef en-US "English" // English
+
+#string STR_MEM_INFO_FORM #language en-US "Memory Configuration"
+#string STR_MEM_INFO_FORM_HELP #language en-US "Memory Configuration"
+#string STR_MEM_INFO_TOTAL_MEM #language en-US "Total Memory"
+#string STR_MEM_INFO_TOTAL_MEM_VALUE #language en-US "0 GB"
+#string STR_MEM_INFO_EFFECT_MEM #language en-US "Effective Memory"
+#string STR_MEM_INFO_EFFECT_MEM_VALUE #language en-US "0 MB"
+#string STR_MEM_INFO_CURRENT_SPEED #language en-US "Memory Speed"
+#string STR_MEM_INFO_CURRENT_SPEED_VALUE #language en-US "0 MHz"
+#string STR_MEM_INFO_SPEED_SELECT_PROMPT #language en-US "Memory Operating Speed Selection"
+#string STR_MEM_INFO_SPEED_SELECT_HELP #language en-US "Force specific Memory Operating Speed or use Auto setting."
+#string STR_MEM_INFO_SPEED_SELECT_VALUE0 #language en-US "Auto"
+#string STR_MEM_INFO_SPEED_SELECT_VALUE1 #language en-US "2133"
+#string STR_MEM_INFO_SPEED_SELECT_VALUE2 #language en-US "2400"
+#string STR_MEM_INFO_SPEED_SELECT_VALUE3 #language en-US "2666"
+#string STR_MEM_INFO_SPEED_SELECT_VALUE4 #language en-US "2933"
+#string STR_MEM_INFO_SPEED_SELECT_VALUE5 #language en-US "3200"
+#string STR_MEM_INFO_DIMM_INFO #language en-US "DIMM Information"
+
+#string STR_MEM_INFO_PERFORMANCE_FORM #language en-US "Memory RAS and Performance Configuration"
+#string STR_MEM_INFO_PERFORMANCE_FORM_HELP #language en-US "Displays and provides options to change the memory RAS and performance Settings"
+#string STR_MEM_INFO_ENABLE_ECC_PROMPT #language en-US "ECC mode"
+#string STR_MEM_INFO_ENABLE_ECC_HELP #language en-US "ECC mode: Disabled, SECDED or Symbol"
+#string STR_MEM_INFO_ENABLE_ERRCTRL_DE_PROMPT #language en-US "Defer uncorrectable read errors"
+#string STR_MEM_INFO_ENABLE_ERRCTRL_DE_HELP #language en-US "When enabled the DMC defers uncorrectable read errors to the consumer by sending an OK response and setting the TXDAT poison flag on the CHI-B interconnect. If this bit is clear the DMC defaults to non-deferred behavior when encountering an unrecoverable error"
+#string STR_MEM_INFO_ENABLE_ERRCTRL_FI_PROMPT #language en-US "Fault handling interrupt"
+#string STR_MEM_INFO_ENABLE_ERRCTRL_FI_HELP #language en-US "Enables fault handling interrupt. The fault handling interrupt is raised to give notice that ECC fault has been recorded"
+#string STR_MEM_INFO_ENABLE_SCRUB #language en-US "Scrub Patrol duration (hour)"
+#string STR_MEM_INFO_ENABLE_SCRUB_HELP #language en-US "Select duration (hour) for Scrub Patrol"
+#string STR_MEM_INFO_ENABLE_DEMAND_SCRUB_PROMPT #language en-US "Demand scrub"
+#string STR_MEM_INFO_ENABLE_DEMAND_SCRUB_HELP #language en-US "Enable/Disable the ability to write corrected data back to the memory once a correctable error is detected"
+#string STR_MEM_INFO_ENABLE_WRITE_CRC_PROMPT #language en-US "Write CRC"
+#string STR_MEM_INFO_ENABLE_WRITE_CRC_HELP #language en-US "Enable/Disable Cyclic Redundancy Check (CRC) functionality on write data. Be noted that enabling CRC will degrade Write bandwidth"
+
+
+#string STR_MEM_INFO_ENABLE_32GB_SLAVE_PROMPT #language en-US "Enable Slave 32bit memory region"
+#string STR_MEM_INFO_ENABLE_32GB_SLAVE_HELP #language en-US "Enables 32bit memory region (2GB) for slave socket"
+#string STR_MEM_INFO_FGR_MODE_PROMPT #language en-US "Fine Granularity Refresh (FGR)"
+#string STR_MEM_INFO_FGR_MODE_VALUE0 #language en-US "1x"
+#string STR_MEM_INFO_FGR_MODE_VALUE1 #language en-US "2x"
+#string STR_MEM_INFO_FGR_MODE_VALUE2 #language en-US "4x"
+#string STR_MEM_INFO_FGR_MODE_HELP #language en-US "Select DDR Fine Granularity Refresh (FGR) mode 1x/2x/4x"
+#string STR_MEM_INFO_REFRESH2X_MODE_PROMPT #language en-US "CVE-2020-10255 mitigation"
+#string STR_MEM_INFO_REFRESH2X_MODE_HELP #language en-US "Enable mitigation for CVE-2020-10255, TRRespass"
+
+#string STR_MEM_INFO_NVDIMM_FORM #language en-US "NVDIMM-N Configuration"
+#string STR_MEM_INFO_NVDIMM_FORM_HELP #language en-US "Displays and provides options to change the NVDIMM-N Settings"
+#string STR_MEM_INFO_NVDIMM_CUR_MODE_SK0 #language en-US "Socket0 Configured Mode"
+#string STR_MEM_INFO_NVDIMM_CUR_MODE_SK1 #language en-US "Socket1 Configured Mode"
+#string STR_MEM_INFO_NVDIMM_CUR_MODE_SK0_VALUE #language en-US "Non-NVDIMM"
+#string STR_MEM_INFO_NVDIMM_CUR_MODE_SK1_VALUE #language en-US "Non-NVDIMM"
+#string STR_MEM_INFO_NVDIMM_MODE_SEL_PROMPT #language en-US "Mode Selection"
+#string STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE0 #language en-US "Non-NVDIMM"
+#string STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE1 #language en-US "Non-Hashed"
+#string STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE2 #language en-US "Hashed"
+#string STR_MEM_INFO_NVDIMM_MODE_SEL_VALUE3 #language en-US "Auto"
+#string STR_MEM_INFO_NVDIMM_MODE_SEL_HELP #language en-US "Select NVDIMM-N Mode (Non-NVDIMM/Non-Hashed/Hashed/Auto)"
--
2.17.1


Re: [PATCH v3 21/28] AmpereAltraPkg: Add DebugInfoPei module

Leif Lindholm
 

On Wed, Sep 15, 2021 at 22:55:20 +0700, Nhi Pham wrote:
From: Vu Nguyen <vunguyen@os.amperecomputing.com>

Helps to show various system information like CPU info and Board Setting
values to UART console during boot process.

Cc: Thang Nguyen <thang@os.amperecomputing.com>
Cc: Chuong Tran <chuong@os.amperecomputing.com>
Cc: Phong Vo <phong@os.amperecomputing.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>

Signed-off-by: Vu Nguyen <vunguyen@os.amperecomputing.com>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>

---
Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc | 4 +
Platform/Ampere/JadePkg/Jade.fdf | 2 +
Silicon/Ampere/AmpereAltraPkg/Drivers/DebugInfoPei/DebugInfoPei.inf | 40 ++++
Silicon/Ampere/AmpereAltraPkg/Drivers/DebugInfoPei/DebugInfoPei.c | 210 ++++++++++++++++++++
4 files changed, 256 insertions(+)

diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
index 459d06c33c02..aadbf6dae83e 100644
--- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
+++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
@@ -543,6 +543,10 @@ [Components.common]
ArmPlatformPkg/PlatformPei/PlatformPeim.inf
Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.inf
Silicon/Ampere/AmpereAltraPkg/Drivers/MemoryInitPeim/MemoryInitPeim.inf
+ Silicon/Ampere/AmpereAltraPkg/Drivers/DebugInfoPei/DebugInfoPei.inf {
+ <LibraryClasses>
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ }
Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf
ArmPkg/Drivers/CpuPei/CpuPei.inf
diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf
index 96213edb2676..56a54b307f04 100644
--- a/Platform/Ampere/JadePkg/Jade.fdf
+++ b/Platform/Ampere/JadePkg/Jade.fdf
@@ -167,6 +167,8 @@ [FV.FVMAIN_COMPACT]
#
# Print platform information before passing control into the Driver Execution Environment (DXE) phase
#
+ INF Silicon/Ampere/AmpereAltraPkg/Drivers/DebugInfoPei/DebugInfoPei.inf
+
INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf

FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/DebugInfoPei/DebugInfoPei.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/DebugInfoPei/DebugInfoPei.inf
new file mode 100644
index 000000000000..1f50f811f273
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/DebugInfoPei/DebugInfoPei.inf
@@ -0,0 +1,40 @@
+## @file
+#
+# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = DebugInfo
+ FILE_GUID = C0571D26-6176-11E9-8647-D663BD873D93
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = DebugInfoPeiEntryPoint
+
+[Sources]
+ DebugInfoPei.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+ Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
+
+[LibraryClasses]
+ AmpereCpuLib
+ ArmLib
+ DebugLib
+ HobLib
+ NVParamLib
+ PeimEntryPoint
+
+[Guids]
+ gPlatformHobGuid
+
+[Depex]
+ TRUE
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/DebugInfoPei/DebugInfoPei.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/DebugInfoPei/DebugInfoPei.c
new file mode 100644
index 000000000000..ece9295864a8
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/DebugInfoPei/DebugInfoPei.c
@@ -0,0 +1,210 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Uefi.h>
+
+#include <Guid/PlatformInfoHobGuid.h>
+#include <Library/AmpereCpuLib.h>
+#include <Library/ArmLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/NVParamLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+
+#include <NVParamDef.h>
+#include <PlatformInfoHob.h>
+
+#define GB_SCALE_FACTOR 1073741824
+#define MB_SCALE_FACTOR 1048576
+#define KB_SCALE_FACTOR 1024
+#define MHZ_SCALE_FACTOR 1000000
+
+/**
+ Print any existence NVRAM.
+**/
+STATIC VOID
+PrintNVRAM (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ NVPARAM Idx;
+ UINT32 Val;
+ UINT16 ACLRd = NV_PERM_ALL;
+ BOOLEAN Flag;
+
+ Flag = FALSE;
+ for (Idx = NV_PREBOOT_PARAM_START; Idx <= NV_PREBOOT_PARAM_MAX; Idx += NVPARAM_SIZE) {
+ Status = NVParamGet (Idx, ACLRd, &Val);
+ if (!EFI_ERROR (Status)) {
+ if (!Flag) {
+ DebugPrint (DEBUG_INIT, "Pre-boot Configuration Setting:\n");
+ Flag = TRUE;
+ }
+ DebugPrint (DEBUG_INIT, " %04X: 0x%X (%d)\n", (UINT32)Idx, Val, Val);
+ }
+ }
+
+ Flag = FALSE;
+ for (Idx = NV_MANU_PARAM_START; Idx <= NV_MANU_PARAM_MAX; Idx += NVPARAM_SIZE) {
+ Status = NVParamGet (Idx, ACLRd, &Val);
+ if (!EFI_ERROR (Status)) {
+ if (!Flag) {
+ DebugPrint (DEBUG_INIT, "Manufacturer Configuration Setting:\n");
+ Flag = TRUE;
+ }
+ DebugPrint (DEBUG_INIT, " %04X: 0x%X (%d)\n", (UINT32)Idx, Val, Val);
+ }
+ }
+
+ Flag = FALSE;
+ for (Idx = NV_USER_PARAM_START; Idx <= NV_USER_PARAM_MAX; Idx += NVPARAM_SIZE) {
+ Status = NVParamGet (Idx, ACLRd, &Val);
+ if (!EFI_ERROR (Status)) {
+ if (!Flag) {
+ DebugPrint (DEBUG_INIT, "User Configuration Setting:\n");
+ Flag = TRUE;
+ }
+ DebugPrint (DEBUG_INIT, " %04X: 0x%X (%d)\n", (UINT32)Idx, Val, Val);
+ }
+ }
+
+ Flag = FALSE;
+ for (Idx = NV_BOARD_PARAM_START; Idx <= NV_BOARD_PARAM_MAX; Idx += NVPARAM_SIZE) {
+ Status = NVParamGet (Idx, ACLRd, &Val);
+ if (!EFI_ERROR (Status)) {
+ if (!Flag) {
+ DebugPrint (DEBUG_INIT, "Board Configuration Setting:\n");
+ Flag = TRUE;
+ }
+ DebugPrint (DEBUG_INIT, " %04X: 0x%X (%d)\n", (UINT32)Idx, Val, Val);
+ }
+ }
+}
+
+STATIC
+CHAR8 *
+GetCCIXLinkSpeed (
+ IN UINTN Speed
+ )
+{
+ switch (Speed) {
+ case 1:
+ return "2.5 GT/s";
+
+ case 2:
+ return "5 GT/s";
+
+ case 3:
+ return "8 GT/s";
+
+ case 4:
+ case 6:
+ return "16 GT/s";
+
+ case 0xa:
+ return "20 GT/s";
+
+ case 0xf:
+ return "25 GT/s";
+ }
+
+ return "Unknown";
+}
+
+/**
+ Print system info
+**/
+STATIC VOID
+PrintSystemInfo (
+ VOID
+ )
+{
+ UINTN Idx;
+ VOID *Hob;
+ PLATFORM_INFO_HOB *PlatformHob;
+
+ Hob = GetFirstGuidHob (&gPlatformHobGuid);
+ if (Hob == NULL) {
+ return;
+ }
+
+ PlatformHob = (PLATFORM_INFO_HOB *)GET_GUID_HOB_DATA (Hob);
+
+ DebugPrint (DEBUG_INIT, "SCP FW version : %a\n", (const CHAR8 *)PlatformHob->SmPmProVer);
+ DebugPrint (DEBUG_INIT, "SCP FW build date : %a\n", (const CHAR8 *)PlatformHob->SmPmProBuild);
+
+ DebugPrint (DEBUG_INIT, "Failsafe status : %d\n", PlatformHob->FailSafeStatus);
+ DebugPrint (DEBUG_INIT, "Reset status : %d\n", PlatformHob->ResetStatus);
+ DebugPrint (DEBUG_INIT, "CPU info\n");
+ DebugPrint (DEBUG_INIT, " CPU ID : %X\n", ArmReadMidr ());
+ DebugPrint (DEBUG_INIT, " CPU Clock : %d MHz\n", PlatformHob->CpuClk / MHZ_SCALE_FACTOR);
+ DebugPrint (DEBUG_INIT, " Number of active sockets : %d\n", GetNumberOfActiveSockets ());
+ DebugPrint (DEBUG_INIT, " Number of active cores : %d\n", GetNumberOfActiveCores ());
+ if (IsSlaveSocketActive ()) {
+ DebugPrint (DEBUG_INIT,
+ " Inter Socket Connection 0 : Width: x%d / Speed %a\n",
+ PlatformHob->Link2PWidth[0],
+ GetCCIXLinkSpeed (PlatformHob->Link2PSpeed[0])
+ );
+ DebugPrint (DEBUG_INIT,
+ " Inter Socket Connection 1 : Width: x%d / Speed %a\n",
+ PlatformHob->Link2PWidth[1],
+ GetCCIXLinkSpeed (PlatformHob->Link2PSpeed[1])
+ );
+ }
+ for (Idx = 0; Idx < GetNumberOfActiveSockets (); Idx++) {
+ DebugPrint (DEBUG_INIT, " Socket[%d]: Core voltage : %d\n", Idx, PlatformHob->CoreVoltage[Idx]);
+ DebugPrint (DEBUG_INIT, " Socket[%d]: SCU ProductID : %X\n", Idx, PlatformHob->ScuProductId[Idx]);
+ DebugPrint (DEBUG_INIT, " Socket[%d]: Max cores : %d\n", Idx, PlatformHob->MaxNumOfCore[Idx]);
+ DebugPrint (DEBUG_INIT, " Socket[%d]: Warranty : %d\n", Idx, PlatformHob->Warranty[Idx]);
+ DebugPrint (DEBUG_INIT, " Socket[%d]: Subnuma : %d\n", Idx, PlatformHob->SubNumaMode[Idx]);
+ DebugPrint (DEBUG_INIT, " Socket[%d]: RC disable mask : %X\n", Idx, PlatformHob->RcDisableMask[Idx]);
+ DebugPrint (DEBUG_INIT, " Socket[%d]: AVS enabled : %d\n", Idx, PlatformHob->AvsEnable[Idx]);
+ DebugPrint (DEBUG_INIT, " Socket[%d]: AVS voltage : %d\n", Idx, PlatformHob->AvsVoltageMV[Idx]);
+ }
+
+ DebugPrint (DEBUG_INIT, "SOC info\n");
+ DebugPrint (DEBUG_INIT, " DDR Frequency : %d MHz\n", PlatformHob->DramInfo.MaxSpeed);
+ for (Idx = 0; Idx < GetNumberOfActiveSockets (); Idx++) {
+ DebugPrint (DEBUG_INIT, " Socket[%d]: Soc voltage : %d\n", Idx, PlatformHob->SocVoltage[Idx]);
+ DebugPrint (DEBUG_INIT, " Socket[%d]: DIMM1 voltage : %d\n", Idx, PlatformHob->Dimm1Voltage[Idx]);
+ DebugPrint (DEBUG_INIT, " Socket[%d]: DIMM2 voltage : %d\n", Idx, PlatformHob->Dimm2Voltage[Idx]);
+ }
+
+ DebugPrint (DEBUG_INIT, " PCP Clock : %d MHz\n", PlatformHob->PcpClk / MHZ_SCALE_FACTOR);
+ DebugPrint (DEBUG_INIT, " SOC Clock : %d MHz\n", PlatformHob->SocClk / MHZ_SCALE_FACTOR);
+ DebugPrint (DEBUG_INIT, " SYS Clock : %d MHz\n", PlatformHob->SysClk / MHZ_SCALE_FACTOR);
+ DebugPrint (DEBUG_INIT, " AHB Clock : %d MHz\n", PlatformHob->AhbClk / MHZ_SCALE_FACTOR);
+}
+
+/**
+ Entry point function for the PEIM
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @return EFI_SUCCESS If we installed our PPI
+
+**/
+EFI_STATUS
+EFIAPI
+DebugInfoPeiEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ PrintSystemInfo ();
+ PrintNVRAM ();
+
+ return EFI_SUCCESS;
+}
--
2.17.1


Re: [PATCH v3 13/28] JadePkg: Add BoardPcieLib library instance

Leif Lindholm
 

On Wed, Sep 15, 2021 at 22:55:12 +0700, Nhi Pham wrote:
From: Vu Nguyen <vunguyen@os.amperecomputing.com>

Provides basic features like:
* Screen menu to change the bifurcation setting of each Root Complex.
Note that we can only make change for the Root Complex which doesn't
come with a default value in the BoardSetting.
* Parsing the BoardSetting and coordinate with saved setting to enable
corresponding PCIe controller of each Root Complex.
* Config speed and lane of enabled controller.

Cc: Thang Nguyen <thang@os.amperecomputing.com>
Cc: Chuong Tran <chuong@os.amperecomputing.com>
Cc: Phong Vo <phong@os.amperecomputing.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>

Signed-off-by: Vu Nguyen <vunguyen@os.amperecomputing.com>
---
Platform/Ampere/JadePkg/Jade.dsc | 7 +-
Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieLib.inf | 59 +
Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcie.h | 45 +
Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieScreen.h | 114 ++
Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieVfr.h | 99 ++
Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieVfr.vfr | 217 ++++
Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcie.c | 436 +++++++
Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieCommon.c | 329 ++++++
Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieScreen.c | 1244 ++++++++++++++++++++
Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieScreen.uni | 102 ++
10 files changed, 2651 insertions(+), 1 deletion(-)

diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc
index 118c03eab42f..afea3407a256 100644
--- a/Platform/Ampere/JadePkg/Jade.dsc
+++ b/Platform/Ampere/JadePkg/Jade.dsc
@@ -52,7 +52,7 @@ [Defines]
DEFINE EDK2_SKIP_PEICORE = TRUE
DEFINE SECURE_BOOT_ENABLE = FALSE
DEFINE INCLUDE_TFTP_COMMAND = TRUE
- DEFINE NVRAM_UUID = 84BC921F-9D4A-4D1D-A1A1-1AE13EDD07E5
+ DEFINE NVRAM_UUID = 27AF4DFF-028B-4237-80B9-828FA74132F4
This shouldn't be changing in the midst of the series - please change
it where it's introduced:
"AmpereAltraPkg: Support UEFI non-volatile variable"


#
# Network definition
@@ -88,6 +88,11 @@ [LibraryClasses]
#
AcpiLib|EmbeddedPkg/Library/AcpiLib/AcpiLib.inf

+ #
+ # Pcie Board
+ #
+ BoardPcieLib|Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieLib.inf
+
################################################################################
#
# Specific Platform Pcds
diff --git a/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieLib.inf b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieLib.inf
new file mode 100644
index 000000000000..75e3560f4fca
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieLib.inf
@@ -0,0 +1,59 @@
+## @file
+#
+# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = BoardPcieLib
+ FILE_GUID = 062191A6-E113-4FD6-84C7-E400B4B34759
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = BoardPcieLib
+
+[Sources]
+ BoardPcie.c
+ BoardPcieCommon.c
+ BoardPcieScreen.c
+ BoardPcieScreen.h
+ BoardPcieScreen.uni
+ BoardPcieVfr.h
+ BoardPcieVfr.vfr
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+ Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
+
+[LibraryClasses]
+ AmpereCpuLib
+ BaseLib
+ DevicePathLib
+ GpioLib
+ HiiLib
+ HobLib
+ MemoryAllocationLib
+ SystemFirmwareInterfaceLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+
+[Protocols]
+ gEfiDevicePathProtocolGuid
+ gEfiHiiStringProtocolGuid ## CONSUMES
+ gEfiHiiConfigRoutingProtocolGuid ## CONSUMES
+ gEfiHiiConfigAccessProtocolGuid ## PRODUCES
+ gEfiHiiDatabaseProtocolGuid ## CONSUMES
+ gEfiConfigKeywordHandlerProtocolGuid ## CONSUMES
+
+[Guids]
+ gEfiIfrTianoGuid ## CONSUMES
+ gPlatformManagerFormsetGuid ## CONSUMES
+ gPlatformHobGuid ## CONSUMES
+
+[Depex]
+ TRUE
diff --git a/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcie.h b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcie.h
new file mode 100644
index 000000000000..73ba3ee83ac2
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcie.h
@@ -0,0 +1,45 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef BOARD_PCIE_H_
+#define BOARD_PCIE_H_
+
+#include <Ac01PcieCommon.h>
+
+#define BITS_PER_BYTE 8
+#define BYTE_MASK 0xFF
+#define PCIE_ERRATA_SPEED1 0x0001 // Limited speed errata
+
+enum DEV_MAP_MODE {
+ DEV_MAP_1_CONTROLLER = 0,
+ DEV_MAP_2_CONTROLLERS,
+ DEV_MAP_3_CONTROLLERS,
+ DEV_MAP_4_CONTROLLERS,
+};
Enum style, as per earlier patches.

+
+BOOLEAN
+IsEmptyRC (
+ IN AC01_RC *RC
+ );
+
+VOID
+BoardPcieSetupDevmap (
+ IN AC01_RC *RC
+ );
+
+VOID
+BoardPcieGetLaneAllocation (
+ IN AC01_RC *RC
+ );
+
+VOID
+BoardPcieGetSpeed (
+ IN AC01_RC *RC
+ );
+
+#endif /* BOARD_PCIE_H_ */
diff --git a/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieScreen.h b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieScreen.h
new file mode 100644
index 000000000000..b95c99588a56
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieScreen.h
@@ -0,0 +1,114 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef BOARD_PCIE_SCREEN_H_
+#define BOARD_PCIE_SCREEN_H_
+
+#include "BoardPcieVfr.h"
+
+//
+// This is the generated IFR binary data for each formset defined in VFR.
+// This data array is ready to be used as input of HiiAddPackages() to
+// create a packagelist (which contains Form packages, String packages, etc).
+//
+extern UINT8 BoardPcieVfrBin[];
+
+//
+// This is the generated String package data for all .UNI files.
+// This data array is ready to be used as input of HiiAddPackages() to
+// create a packagelist (which contains Form packages, String packages, etc).
+//
+extern UINT8 BoardPcieLibStrings[];
+
+#define MAX_EDITABLE_ELEMENTS 3
+#define RC0_STATUS_OFFSET \
+ OFFSET_OF (VARSTORE_DATA, RCStatus[0])
+#define RC0_BIFUR_LO_OFFSET \
+ OFFSET_OF (VARSTORE_DATA, RCBifurcationLow[0])
+#define RC0_BIFUR_HI_OFFSET \
+ OFFSET_OF (VARSTORE_DATA, RCBifurcationHigh[0])
+#define SMMU_PMU_OFFSET \
+ OFFSET_OF (VARSTORE_DATA, SmmuPmu)
+
+#define STRONG_ODERING_OFFSET \
Typo:
ODERING ->
ORDERING

+ OFFSET_OF (NVPARAM_VARSTORE_DATA, PcieStrongOrdering)
+
+//
+// Signature: Ampere Computing PCIe Screen
+//
+#define SCREEN_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('A', 'C', 'P', 'S')
+
+#define MAX_STRING_SIZE 32
+
+#define STRONG_ORDERING_DEFAULT_OPTION_VALUE 1
+#define STRONG_ORDERING_DEFAULT_NVPARAM_VALUE 0xFFFFFFFF
+
+typedef struct {
+ UINTN Signature;
+
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE HiiHandle;
+ VARSTORE_DATA VarStoreConfig;
+ NVPARAM_VARSTORE_DATA NVParamVarStoreConfig;
+
+ //
+ // Consumed protocol
+ //
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
+ EFI_HII_STRING_PROTOCOL *HiiString;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *HiiKeywordHandler;
+
+ //
+ // Produced protocol
+ //
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+} SCREEN_PRIVATE_DATA;
+
+typedef struct {
+ UINTN PciDevIdx;
+ EFI_STRING_ID GotoStringId;
+ EFI_STRING_ID GotoHelpStringId;
+ UINT16 GotoKey;
+ BOOLEAN ShowItem;
+} SETUP_GOTO_DATA;
+
+#define SCREEN_PRIVATE_FROM_THIS(a) \
+ CR (a, SCREEN_PRIVATE_DATA, ConfigAccess, SCREEN_PRIVATE_DATA_SIGNATURE)
+
+#pragma pack(1)
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+#pragma pack()
+
+UINT8
+PcieRCDevMapLowDefaultSetting (
+ IN UINTN RCIndex,
+ IN SCREEN_PRIVATE_DATA *PrivateData
+ );
+
+UINT8
+PcieRCDevMapHighDefaultSetting (
+ IN UINTN RCIndex,
+ IN SCREEN_PRIVATE_DATA *PrivateData
+ );
+
+BOOLEAN
+PcieRCActiveDefaultSetting (
+ IN UINTN RCIndex,
+ IN SCREEN_PRIVATE_DATA *PrivateData
+ );
+
+#endif /* BOARD_PCIE_SCREEN_H_ */
diff --git a/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieVfr.h b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieVfr.h
new file mode 100644
index 000000000000..badb1c80f9ab
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieVfr.h
@@ -0,0 +1,99 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef BOARD_PCIE_VFR_H_
+#define BOARD_PCIE_VFR_H_
+
+#include <Platform/Ac01.h>
+
+#define VARSTORE_NAME L"PcieIfrNVData"
+#define VARSTORE_ID 0x1234
+#define FORM_ID 0x1235
+#define RC0_FORM_ID 0x1236
+#define RC1_FORM_ID 0x1237
+#define RC2_FORM_ID 0x1238
+#define RC3_FORM_ID 0x1239
+#define RC4_FORM_ID 0x123A
+#define RC5_FORM_ID 0x123B
+#define RC6_FORM_ID 0x123C
+#define RC7_FORM_ID 0x123D
+#define RC8_FORM_ID 0x123E
+#define RC9_FORM_ID 0x123F
+#define RC10_FORM_ID 0x1240
+#define RC11_FORM_ID 0x1241
+#define RC12_FORM_ID 0x1242
+#define RC13_FORM_ID 0x1243
+#define RC14_FORM_ID 0x1244
+#define RC15_FORM_ID 0x1245
+#define FORM_SET_GUID { 0xe84e70d6, 0xe4b2, 0x4c6e, { 0x98, 0x51, 0xcb, 0x2b, 0xac, 0x77, 0x7d, 0xbb } }
+
+#define GOTO_ID_BASE 0x8040
+
+#define NVPARAM_VARSTORE_NAME L"PcieIfrNVParamData"
+#define NVPARAM_VARSTORE_ID 0x1233
+
+#pragma pack(1)
+
+//
+// NV data structure definition
+//
+typedef struct {
+ BOOLEAN RCStatus[AC01_MAX_PCIE_ROOT_COMPLEX];
+ UINT8 RCBifurcationLow[AC01_MAX_PCIE_ROOT_COMPLEX];
+ UINT8 RCBifurcationHigh[AC01_MAX_PCIE_ROOT_COMPLEX];
+ UINT32 SmmuPmu;
+} VARSTORE_DATA;
+
+//
+// NVParam data structure definition
+//
+typedef struct {
+ BOOLEAN PcieStrongOrdering;
+} NVPARAM_VARSTORE_DATA;
+
+#pragma pack()
+
+//
+// Labels definition
+//
+#define LABEL_UPDATE 0x2223
+#define LABEL_END 0x2224
+#define LABEL_RC0_UPDATE 0x2225
+#define LABEL_RC0_END 0x2226
+#define LABEL_RC1_UPDATE 0x2227
+#define LABEL_RC1_END 0x2228
+#define LABEL_RC2_UPDATE 0x2229
+#define LABEL_RC2_END 0x222A
+#define LABEL_RC3_UPDATE 0x222B
+#define LABEL_RC3_END 0x222C
+#define LABEL_RC4_UPDATE 0x222D
+#define LABEL_RC4_END 0x222E
+#define LABEL_RC5_UPDATE 0x222F
+#define LABEL_RC5_END 0x2230
+#define LABEL_RC6_UPDATE 0x2231
+#define LABEL_RC6_END 0x2232
+#define LABEL_RC7_UPDATE 0x2233
+#define LABEL_RC7_END 0x2234
+#define LABEL_RC8_UPDATE 0x2235
+#define LABEL_RC8_END 0x2236
+#define LABEL_RC9_UPDATE 0x2237
+#define LABEL_RC9_END 0x2238
+#define LABEL_RC10_UPDATE 0x2239
+#define LABEL_RC10_END 0x223A
+#define LABEL_RC11_UPDATE 0x223B
+#define LABEL_RC11_END 0x223C
+#define LABEL_RC12_UPDATE 0x223D
+#define LABEL_RC12_END 0x223E
+#define LABEL_RC13_UPDATE 0x223F
+#define LABEL_RC13_END 0x2240
+#define LABEL_RC14_UPDATE 0x2241
+#define LABEL_RC14_END 0x2242
+#define LABEL_RC15_UPDATE 0x2243
+#define LABEL_RC15_END 0x2244
+
+#endif /* BOARD_PCIE_VFR_H_ */
diff --git a/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieVfr.vfr b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieVfr.vfr
new file mode 100644
index 000000000000..7fb9adb67030
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieVfr.vfr
@@ -0,0 +1,217 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BoardPcieVfr.h"
+
+formset
+ guid = FORM_SET_GUID,
+ title = STRING_TOKEN(STR_PCIE_FORM),
+ help = STRING_TOKEN(STR_PCIE_FORM_HELP),
+ classguid = gPlatformManagerFormsetGuid,
+
+ //
+ // Define a variable Storage
+ //
+ varstore VARSTORE_DATA,
+ varid = VARSTORE_ID,
+ name = PcieIfrNVData,
+ guid = FORM_SET_GUID;
+
+ varstore NVPARAM_VARSTORE_DATA,
+ varid = NVPARAM_VARSTORE_ID,
+ name = PcieIfrNVParamData,
+ guid = FORM_SET_GUID;
+
+ form
+ formid = FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_FORM);
+
+ label LABEL_UPDATE;
+ // dynamic content here
+ label LABEL_END;
+ endform;
+
+ form
+ formid = RC0_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC0_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC0_FORM);
+
+ label LABEL_RC0_UPDATE;
+ // dynamic content here
+ label LABEL_RC0_END;
+ endform;
+
+ form
+ formid = RC1_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC1_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC1_FORM);
+
+ label LABEL_RC1_UPDATE;
+ // dynamic content here
+ label LABEL_RC1_END;
+ endform;
+
+ form
+ formid = RC2_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC2_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC2_FORM);
+
+ label LABEL_RC2_UPDATE;
+ // dynamic content here
+ label LABEL_RC2_END;
+ endform;
+
+ form
+ formid = RC3_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC3_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC3_FORM);
+
+ label LABEL_RC3_UPDATE;
+ // dynamic content here
+ label LABEL_RC3_END;
+ endform;
+
+ form
+ formid = RC4_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC4_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC4_FORM);
+
+ label LABEL_RC4_UPDATE;
+ // dynamic content here
+ label LABEL_RC4_END;
+ endform;
+
+ form
+ formid = RC5_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC5_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC5_FORM);
+
+ label LABEL_RC5_UPDATE;
+ // dynamic content here
+ label LABEL_RC5_END;
+ endform;
+
+ form
+ formid = RC6_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC6_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC6_FORM);
+
+ label LABEL_RC6_UPDATE;
+ // dynamic content here
+ label LABEL_RC6_END;
+ endform;
+
+ form
+ formid = RC7_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC7_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC7_FORM);
+
+ label LABEL_RC7_UPDATE;
+ // dynamic content here
+ label LABEL_RC7_END;
+ endform;
+
+ form
+ formid = RC8_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC8_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC8_FORM);
+
+ label LABEL_RC8_UPDATE;
+ // dynamic content here
+ label LABEL_RC8_END;
+ endform;
+
+ form
+ formid = RC9_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC9_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC9_FORM);
+
+ label LABEL_RC9_UPDATE;
+ // dynamic content here
+ label LABEL_RC9_END;
+ endform;
+
+ form
+ formid = RC10_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC10_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC10_FORM);
+
+ label LABEL_RC10_UPDATE;
+ // dynamic content here
+ label LABEL_RC10_END;
+ endform;
+
+ form
+ formid = RC11_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC11_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC11_FORM);
+
+ label LABEL_RC11_UPDATE;
+ // dynamic content here
+ label LABEL_RC11_END;
+ endform;
+
+ form
+ formid = RC12_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC12_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC12_FORM);
+
+ label LABEL_RC12_UPDATE;
+ // dynamic content here
+ label LABEL_RC12_END;
+ endform;
+
+ form
+ formid = RC13_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC13_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC13_FORM);
+
+ label LABEL_RC13_UPDATE;
+ // dynamic content here
+ label LABEL_RC13_END;
+ endform;
+
+ form
+ formid = RC14_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC14_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC14_FORM);
+
+ label LABEL_RC14_UPDATE;
+ // dynamic content here
+ label LABEL_RC14_END;
+ endform;
+
+ form
+ formid = RC15_FORM_ID,
+ title = STRING_TOKEN(STR_PCIE_RC15_FORM);
+
+ subtitle text = STRING_TOKEN(STR_PCIE_RC15_FORM);
+
+ label LABEL_RC15_UPDATE;
+ // dynamic content here
+ label LABEL_RC15_END;
+ endform;
+
+endformset;
diff --git a/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcie.c b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcie.c
new file mode 100644
index 000000000000..bb4c1863b54b
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcie.c
@@ -0,0 +1,436 @@
+/** @file
+
+ Pcie board specific driver to handle asserting PERST signal to Endpoint
+ card and parsing NVPARAM board settings for bifurcation programming.
+
+ PERST asserting is via group of GPIO pins to CPLD as Platform Specification.
+
+ NVPARAM board settings is spec-ed within Firmware Interface Requirement.
+ Bifuration devmap is programmed before at SCP following the rule
+
+ Root Complex Type-A devmap settings (RP == Root Port)
+ -----------------------------------------
+ | RP0 | RP1 | RP2 | RP3 | Devmap |
+ | (x16) | (x4) | (x8) | (x4) | (output) |
+ -------------------------------------------
+ | Y | N | N | N | 0 |
+ | Y | N | Y | N | 1 |
+ | Y | N | Y | Y | 2 |
+ | Y | Y | Y | Y | 3 |
+ -----------------------------------------
+
+ Root Complex Type-B LO (aka RCBxA) devmap settings (RP == Root Port)
+ ----------------------------------------
+ | RP0 | RP1 | RP2 | RP3 | Devmap |
+ | (x8) | (x2) | (x4) | (x3) | (output) |
+ ----------------------------------------
+ | Y | N | N | N | 0 |
+ | Y | N | Y | N | 1 |
+ | Y | N | Y | Y | 2 |
+ | Y | Y | Y | Y | 3 |
+ ----------------------------------------
+
+ Root Complex Type-B LO (aka RCBxB) devmap settings (RP == Root Port)
+ ----------------------------------------
+ | RP4 | RP5 | RP6 | RP7 | Devmap |
+ | (x8) | (x2) | (x4) | (x3) | (output) |
+ ----------------------------------------
+ | Y | N | N | N | 0 |
+ | Y | N | Y | N | 1 |
+ | Y | N | Y | Y | 2 |
+ | Y | Y | Y | Y | 3 |
+ ----------------------------------------
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Guid/PlatformInfoHobGuid.h>
+#include <Library/AmpereCpuLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/GpioLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/NVParamLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <NVParamDef.h>
+#include <Platform/Ac01.h>
+#include <PlatformInfoHob.h>
+
+#include "BoardPcie.h"
+#include "BoardPcieVfr.h"
+
+#ifndef BIT
+#define BIT(nr) (1 << (nr))
+#endif
+
+#define RCA_MAX_PERST_GROUPVAL 62
+#define RCB_MAX_PERST_GROUPVAL 46
+
+extern CHAR16 gPcieVarstoreName[];
+extern EFI_GUID gPcieFormSetGuid;
+
+VOID
+EFIAPI
+BoardPcieLoadPreset (
+ IN AC01_RC *RC
RootComplex (search/replace globally).

+ )
+{
+ UINT32 Nv;
Nv what? Even expanded to Non-volatile, this name doesn't describe
what this variable holds. Please use a more descriptive name.

+ INTN NvParam;
+ INTN Ret;
+ INTN Index;
+
+ // Load default value
+ for (Index = 0; Index < MAX_PCIE_B; Index++) {
+ RC->PresetGen3[Index] = PRESET_INVALID;
+ RC->PresetGen4[Index] = PRESET_INVALID;
+ }
+
+ // Load override value
+ if (RC->Socket == 0) {
+ if (RC->Type == RCA) {
+ if (RC->ID < MAX_RCA) {
+ NvParam = NV_SI_RO_BOARD_S0_RCA0_TXRX_G3PRESET + RC->ID * NV_PARAM_ENTRYSIZE;
+ } else {
+ NvParam = NV_SI_RO_BOARD_S0_RCA4_TXRX_G3PRESET + (RC->ID - MAX_RCA) * NV_PARAM_ENTRYSIZE;
+ }
+ } else {
+ //
+ // There're two NVParam entries per RCB
+ //
+ NvParam = NV_SI_RO_BOARD_S0_RCB0A_TXRX_G3PRESET + (RC->ID - MAX_RCA) * (NV_PARAM_ENTRYSIZE * 2);
+ }
+ } else if (RC->Type == RCA) {
+ if (RC->ID < MAX_RCA) {
+ NvParam = NV_SI_RO_BOARD_S1_RCA2_TXRX_G3PRESET + (RC->ID - 2) * NV_PARAM_ENTRYSIZE;
+ } else {
+ NvParam = NV_SI_RO_BOARD_S1_RCA4_TXRX_G3PRESET + (RC->ID - MAX_RCA) * NV_PARAM_ENTRYSIZE;
+ }
+ } else {
+ //
+ // There're two NVParam entries per RCB
+ //
+ NvParam = NV_SI_RO_BOARD_S1_RCB0A_TXRX_G3PRESET + (RC->ID - MAX_RCA) * (NV_PARAM_ENTRYSIZE * 2);
+ }
This 2-level nested conditional serving only to assign a value to
NvParam should be a helpfully named helper function.

+
+ Ret = NVParamGet ((NVPARAM)NvParam, NV_PERM_ALL, &Nv);
+ if (Ret == EFI_SUCCESS) {
+ for (Index = 0; Index < MAX_PCIE_A; Index++) {
+ RC->PresetGen3[Index] = (Nv >> (Index * BITS_PER_BYTE)) & BYTE_MASK;
+ }
+ }
+
+ if (RC->Type == RCB) {
+ NvParam += NV_PARAM_ENTRYSIZE;
+ Ret = NVParamGet ((NVPARAM)NvParam, NV_PERM_ALL, &Nv);
+ if (Ret == EFI_SUCCESS) {
+ for (Index = MAX_PCIE_A; Index < MAX_PCIE; Index++) {
+ RC->PresetGen3[Index] = (Nv >> ((Index - MAX_PCIE_A) * BITS_PER_BYTE)) & BYTE_MASK;
+ }
+ }
+ }
+
+ if (RC->Socket == 0) {
+ if (RC->Type == RCA) {
+ if (RC->ID < MAX_RCA) {
+ NvParam = NV_SI_RO_BOARD_S0_RCA0_TXRX_G4PRESET + RC->ID * NV_PARAM_ENTRYSIZE;
+ } else {
+ NvParam = NV_SI_RO_BOARD_S0_RCA4_TXRX_G4PRESET + (RC->ID - MAX_RCA) * NV_PARAM_ENTRYSIZE;
+ }
+ } else {
+ //
+ // There're two NVParam entries per RCB
+ //
+ NvParam = NV_SI_RO_BOARD_S0_RCB0A_TXRX_G4PRESET + (RC->ID - MAX_RCA) * (NV_PARAM_ENTRYSIZE * 2);
+ }
+ } else if (RC->Type == RCA) {
+ if (RC->ID < MAX_RCA) {
+ NvParam = NV_SI_RO_BOARD_S1_RCA2_TXRX_G4PRESET + (RC->ID - 2) * NV_PARAM_ENTRYSIZE;
+ } else {
+ NvParam = NV_SI_RO_BOARD_S1_RCA4_TXRX_G4PRESET + (RC->ID - MAX_RCA) * NV_PARAM_ENTRYSIZE;
+ }
+ } else {
+ //
+ // There're two NVParam entries per RCB
+ //
+ NvParam = NV_SI_RO_BOARD_S1_RCB0A_TXRX_G4PRESET + (RC->ID - MAX_RCA) * (NV_PARAM_ENTRYSIZE * 2);
+ }
This 2-level nested conditional serving only to assign a value to
NvParam should be a helpfully named helper function.

+
+ Ret = NVParamGet ((NVPARAM)NvParam, NV_PERM_ALL, &Nv);
+ if (Ret == EFI_SUCCESS) {
+ for (Index = 0; Index < MAX_PCIE_A; Index++) {
+ RC->PresetGen4[Index] = (Nv >> (Index * BITS_PER_BYTE)) & BYTE_MASK;
+ }
+ }
+
+ if (RC->Type == RCB) {
+ NvParam += NV_PARAM_ENTRYSIZE;
+ Ret = NVParamGet ((NVPARAM)NvParam, NV_PERM_ALL, &Nv);
+ if (Ret == EFI_SUCCESS) {
+ for (Index = MAX_PCIE_A; Index < MAX_PCIE; Index++) {
+ RC->PresetGen4[Index] = (Nv >> ((Index - MAX_PCIE_A) * BITS_PER_BYTE)) & BYTE_MASK;
+ }
+ }
+ }
+}
+
+/**
+ Parse platform Root Complex information.
+
+ @param[out] RC Root Complex instance to store the platform information.
+
+ @retval EFI_SUCCESS The operation is successful.
+ @retval Others An error occurred.
+**/
+EFI_STATUS
+EFIAPI
+BoardPcieParseRCParams (
+ OUT AC01_RC *RC
+ )
+{
+ UINT32 Efuse;
EFuse would be better coding style conformance.

+ PLATFORM_INFO_HOB *PlatformHob;
+ UINT8 PlatRCId;
+ EFI_STATUS Status;
+ VOID *Hob;
+ UINTN BufferSize;
+ VARSTORE_DATA VarStoreConfig = {
+ .RCStatus = {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
+ TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE},
+ .RCBifurcationLow = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ .RCBifurcationHigh = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ .SmmuPmu = 0
+ };
+
+ DEBUG ((DEBUG_INFO, "%a - Socket%d RC%d\n", __FUNCTION__, RC->Socket, RC->ID));
+
+ PlatRCId = RC->Socket * AC01_MAX_RCS_PER_SOCKET + RC->ID;
+ // Get RC activation status
+ BufferSize = sizeof (VARSTORE_DATA);
+ Status = gRT->GetVariable (
+ gPcieVarstoreName,
+ &gPcieFormSetGuid,
+ NULL,
+ &BufferSize,
+ &VarStoreConfig
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "%a - Failed to read PCIE variable data from config store.\n", __FUNCTION__));
+ }
+
+ RC->Active = VarStoreConfig.RCStatus[PlatRCId];
+ RC->DevMapLow = VarStoreConfig.RCBifurcationLow[PlatRCId];
+ RC->DevMapHigh = VarStoreConfig.RCBifurcationHigh[PlatRCId];
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a - Socket%d RC%d is %s\n",
+ __FUNCTION__,
+ RC->Socket,
+ RC->ID,
+ (RC->Active) ? "ACTIVE" : "INACTIVE"
+ ));
+
+ if (!IsSlaveSocketActive () && RC->Socket == 1) {
+ RC->Active = FALSE;
+ }
+
+ if (RC->Active) {
+ //
+ // Consolidate with E-fuse
+ //
+ Efuse = 0;
+ Hob = GetFirstGuidHob (&gPlatformHobGuid);
+ if (Hob != NULL) {
+ PlatformHob = (PLATFORM_INFO_HOB *)GET_GUID_HOB_DATA (Hob);
+ Efuse = PlatformHob->RcDisableMask[0] | (PlatformHob->RcDisableMask[1] << AC01_MAX_RCS_PER_SOCKET);
Would that test be better as a helpfully named macro?

+ DEBUG ((
+ DEBUG_INFO,
+ "RcDisableMask[0]: 0x%x [1]: 0x%x\n",
+ PlatformHob->RcDisableMask[0],
+ PlatformHob->RcDisableMask[1]
+ ));
+
+ // Update errata flags for Ampere Altra
+ if ((PlatformHob->ScuProductId[0] & 0xff) == 0x01) {
+ if (PlatformHob->AHBCId[0] == 0x20100
+ || PlatformHob->AHBCId[0] == 0x21100
+ || (IsSlaveSocketActive ()
+ && (PlatformHob->AHBCId[1] == 0x20100
+ || PlatformHob->AHBCId[1] == 0x21100)))
+ {
+ RC->Flags |= PCIE_ERRATA_SPEED1;
+ DEBUG ((DEBUG_INFO, "RC[%d]: Flags 0x%x\n", RC->ID, RC->Flags));
+ }
+ }
+ }
+
+ RC->Active = (RC->Active && !(Efuse & BIT (PlatRCId))) ? TRUE : FALSE;
+ }
+
+ /* Load Gen3/Gen4 preset */
+ BoardPcieLoadPreset (RC);
+ BoardPcieGetLaneAllocation (RC);
+ BoardPcieSetupDevmap (RC);
+ BoardPcieGetSpeed (RC);
+
+ return EFI_SUCCESS;
+}
+
+VOID
+EFIAPI
+BoardPcieReleaseAllPerst (
+ IN UINT8 SocketId
+ )
+{
+ UINT32 GpioIndex, GpioPin;
+
+ // Write 1 to all GPIO[16..21] to release all PERST
+ GpioPin = GPIO_DWAPB_PINS_PER_SOCKET * SocketId + 16;
+ for (GpioIndex = 0; GpioIndex < 6; GpioIndex++) {
+ GpioModeConfig (GpioPin + GpioIndex, GPIO_CONFIG_OUT_HI);
+ }
+}
+
+/**
+ Assert PERST of input PCIe controller
+
+ @param[in] RC Root Complex instance.
+ @param[in] PcieIndex PCIe controller index of input Root Complex.
+ @param[in] Bifurcation Bifurcation mode of input Root Complex.
+ @param[in] IsPullToHigh Target status for the PERST.
+
+ @retval EFI_SUCCESS The operation is successful.
+ @retval Others An error occurred.
+**/
+EFI_STATUS
+EFIAPI
+BoardPcieAssertPerst (
+ IN AC01_RC *RC,
+ IN UINT32 PcieIndex,
+ IN UINT8 Bifurcation,
+ IN BOOLEAN IsPullToHigh
+ )
+{
+ UINT32 GpioGroupVal, Val, GpioIndex, GpioPin;
+
+ if (!IsPullToHigh) { // Pull PERST to Low
I agree with the logic of placing that comment on that line, but I
think readability would be improved by placing it on the next line
with a blanke line before the next code line.

+ if (RC->Type == RCA) { // RCA: RC->ID: 0->3 ; PcieIndex: 0->3
+ GpioGroupVal = RCA_MAX_PERST_GROUPVAL - RC->ID * MAX_PCIE_A - PcieIndex;
+ } else { // RCB: RC->ID: 4->7 ; PcieIndex: 0->7
+ GpioGroupVal = RCB_MAX_PERST_GROUPVAL - (RC->ID - MAX_RCA) * MAX_PCIE_B - PcieIndex;
+ }
+
+ // Update the value of GPIO[16..21]. Corresponding PERST line will be decoded by CPLD.
+ GpioPin = GPIO_DWAPB_PINS_PER_SOCKET * RC->Socket + 16;
+ for (GpioIndex = 0; GpioIndex < 6; GpioIndex++) {
+ Val = (GpioGroupVal & 0x3F) & (1 << GpioIndex);
+ if (Val == 0) {
+ GpioModeConfig (GpioPin + GpioIndex, GPIO_CONFIG_OUT_LOW);
+ } else {
+ GpioModeConfig (GpioPin + GpioIndex, GPIO_CONFIG_OUT_HI);
+ }
+ }
+
+ // Keep reset as low as 100 ms as specification
+ MicroSecondDelay (100 * 1000);
+ } else { // Pull PERST to High
Same comment as above.

+ BoardPcieReleaseAllPerst (RC->Socket);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Override the segment number for a root complex with a board specific number.
+
+ @param[in] RC Root Complex instance with properties.
+ @param[out] SegmentNumber Return segment number.
+
+ @retval EFI_SUCCESS The operation is successful.
+ @retval Others An error occurred.
+**/
+EFI_STATUS
+EFIAPI
+BoardPcieGetRCSegmentNumber (
+ IN AC01_RC *RC,
+ OUT UINTN *SegmentNumber
+ )
+{
+ if (RC->Socket == 0) {
+ if (RC->Type == RCA) {
+ switch (RC->ID) {
+ case RCA0:
+ *SegmentNumber = 12;
+ break;
+
+ case RCA1:
+ *SegmentNumber = 13;
+ break;
+
+ case RCA2:
+ *SegmentNumber = 1;
+ break;
+
+ case RCA3:
+ *SegmentNumber = 0;
+ break;
+
+ default:
+ *SegmentNumber = 16;
+ }
+ } else { /* Socket0, CCIX: RCA0 and RCA1 */
+ *SegmentNumber = RC->ID - 2;
This is quite convoluted.

+ }
+ } else { /* Socket1, CCIX: RCA0 and RCA1 */
+ if (RC->ID == RCA0 || RC->ID == RCA1) {
+ *SegmentNumber = 16;
+ } else {
+ *SegmentNumber = 4 + RC->ID;
As is this.
I get that this is just "the way it is", but could there be some
helpful comment about what's going on here? I can't even tell if the
arithmetic is correct with what's here.

+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check if SMM PMU enabled in board screen.
+
+ @param[out] IsSmmuPmuEnabled TRUE if the SMMU PMU enabled, otherwise FALSE.
+
+ @retval EFI_SUCCESS The operation is successful.
+ @retval Others An error occurred.
+**/
+EFI_STATUS
+EFIAPI
+BoardPcieCheckSmmuPmuEnabled (
+ OUT BOOLEAN *IsSmmuPmuEnabled
+ )
+{
+ VARSTORE_DATA VarStoreConfig;
+ UINTN BufferSize;
+ EFI_STATUS Status;
+
+ *IsSmmuPmuEnabled = FALSE;
+
+ // Get Buffer Storage data from EFI variable
+ BufferSize = sizeof (VARSTORE_DATA);
+ Status = gRT->GetVariable (
+ gPcieVarstoreName,
+ &gPcieFormSetGuid,
+ NULL,
+ &BufferSize,
+ &VarStoreConfig
+ );
+ if (!EFI_ERROR (Status)) {
+ *IsSmmuPmuEnabled = VarStoreConfig.SmmuPmu;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieCommon.c b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieCommon.c
new file mode 100644
index 000000000000..05fff88ba601
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieCommon.c
@@ -0,0 +1,329 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/NVParamLib.h>
+#include <Library/SystemFirmwareInterfaceLib.h>
+#include <NVParamDef.h>
+
+#include "BoardPcie.h"
+
+/* Host bridge registers */
+#define RCA_DEV_MAP_OFFSET 0x0
+#define RCB_DEV_MAP_OFFSET 0x4
+
+/* RCA_DEV_MAP_OFFSET */
+#define RCA_DEV_MAP_SET(dst, src) \
+ (((dst) & ~0x7) | (((UINT32)(src)) & 0x7))
+
+/* RCB_DEV_MAP_OFFSET */
+#define RCB_DEV_MAP_LOW_SET(dst, src) \
+ (((dst) & ~0x7) | (((UINT32)(src)) & 0x7))
+#define RCB_DEV_MAP_HIGH_SET(dst, src) \
+ (((dst) & ~0x70) | (((UINT32)(src) << 4) & 0x70))
+
+#define PCIE_GET_MAX_WIDTH(Pcie, Max) \
+ !((Pcie).MaxWidth) ? (Max) : MIN((Pcie).MaxWidth, (Max))
+
+BOOLEAN
+IsEmptyRC (
+ IN AC01_RC *RC
+ )
+{
+ INTN Idx;
+
+ for (Idx = PCIE_0; Idx < MAX_PCIE; Idx++) {
+ if (RC->Pcie[Idx].Active) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+VOID
+BoardPcieSetRCBifurcation (
+ IN AC01_RC *RC,
+ IN UINT8 RPStart,
+ IN UINT8 DevMap
+ )
+{
+ UINT8 MaxWidth;
+
+ if (RPStart != PCIE_0 && RPStart != PCIE_4) {
+ return;
+ }
+
+ if (RC->Type != RCB && RPStart == PCIE_4) {
+ return;
+ }
+
+ if (RC->Type == RCA && RC->Pcie[RPStart].MaxWidth == LNKW_X16) {
+ RC->Pcie[RPStart + 1].MaxWidth = LNKW_X4;
+ RC->Pcie[RPStart + 2].MaxWidth = LNKW_X8;
+ RC->Pcie[RPStart + 3].MaxWidth = LNKW_X4;
+ }
+
+ if (RC->Type == RCB && RC->Pcie[RPStart].MaxWidth == LNKW_X8) {
+ RC->Pcie[RPStart + 1].MaxWidth = LNKW_X2;
+ RC->Pcie[RPStart + 2].MaxWidth = LNKW_X4;
+ RC->Pcie[RPStart + 3].MaxWidth = LNKW_X2;
+ }
+
+ switch (DevMap) {
+ case DEV_MAP_2_CONTROLLERS:
+ MaxWidth = (RC->Type == RCA) ? LNKW_X8 : LNKW_X4;
+ RC->Pcie[RPStart].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart], MaxWidth);
+ RC->Pcie[RPStart + 1].Active = FALSE;
+ RC->Pcie[RPStart + 2].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart + 2], MaxWidth);
+ RC->Pcie[RPStart + 2].Active = TRUE;
+ RC->Pcie[RPStart + 3].Active = FALSE;
+ break;
+
+ case DEV_MAP_3_CONTROLLERS:
+ MaxWidth = (RC->Type == RCA) ? LNKW_X8 : LNKW_X4;
+ RC->Pcie[RPStart].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart], MaxWidth);
+ RC->Pcie[RPStart + 1].Active = FALSE;
+ MaxWidth = (RC->Type == RCA) ? LNKW_X4 : LNKW_X2;
+ RC->Pcie[RPStart + 2].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart + 2], MaxWidth);
+ RC->Pcie[RPStart + 2].Active = TRUE;
+ RC->Pcie[RPStart + 3].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart + 3], MaxWidth);
+ RC->Pcie[RPStart + 3].Active = TRUE;
+ break;
+
+ case DEV_MAP_4_CONTROLLERS:
+ MaxWidth = (RC->Type == RCA) ? LNKW_X4 : LNKW_X2;
+ RC->Pcie[RPStart].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart], MaxWidth);
+ RC->Pcie[RPStart + 1].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart + 1], MaxWidth);
+ RC->Pcie[RPStart + 1].Active = TRUE;
+ RC->Pcie[RPStart + 2].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart + 2], MaxWidth);
+ RC->Pcie[RPStart + 2].Active = TRUE;
+ RC->Pcie[RPStart + 3].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart + 3], MaxWidth);
+ RC->Pcie[RPStart + 3].Active = TRUE;
+ break;
+
+ case DEV_MAP_1_CONTROLLER:
+ default:
+ MaxWidth = (RC->Type == RCA) ? LNKW_X16 : LNKW_X8;
+ RC->Pcie[RPStart].MaxWidth = PCIE_GET_MAX_WIDTH (RC->Pcie[RPStart], MaxWidth);
+ RC->Pcie[RPStart + 1].Active = FALSE;
+ RC->Pcie[RPStart + 2].Active = FALSE;
+ RC->Pcie[RPStart + 3].Active = FALSE;
+ break;
+ }
+}
+
+VOID
+BoardPcieGetLaneAllocation (
+ IN AC01_RC *RC
+ )
+{
+ INTN RPIndex, Ret;
+ UINT32 Nv, Width;
Better name for Nv.

+ NVPARAM NvParam;
+
+ // Retrieve lane allocation and capabilities for each controller
+ if (RC->Type == RCA) {
+ NvParam = ((RC->Socket == 0) ? NV_SI_RO_BOARD_S0_RCA0_CFG : NV_SI_RO_BOARD_S1_RCA0_CFG) +
+ RC->ID * NV_PARAM_ENTRYSIZE;
Ternaries are useful where the help keep the code neat and tidy. This way.
they're basically obfuscating.

NvParam = (RC->Socket == 0) ? NV_SI_RO_BOARD_S0_RCA0_CFG : NV_SI_RO_BOARD_S1_RCA0_CFG;
NvParam += RC->ID * NV_PARAM_ENTRYSIZE;

This also highlights how the enumeration names aren't descriptive
enough. I can't tell what these are referring to.

+ } else {
+ //
+ // There're two NVParam entries per RCB
+ //
+ NvParam = ((RC->Socket == 0) ? NV_SI_RO_BOARD_S0_RCB0_LO_CFG : NV_SI_RO_BOARD_S1_RCB0_LO_CFG) +
+ (RC->ID - MAX_RCA) * (NV_PARAM_ENTRYSIZE * 2);
Same as above.

+ }
+
+ Ret = NVParamGet (NvParam, NV_PERM_ALL, &Nv);
+ Nv = (Ret != EFI_SUCCESS) ? 0 : Nv;
if (EFI_ERROR (Ret)) {
Nv = 0;
}

+
+ for (RPIndex = 0; RPIndex < MAX_PCIE_A; RPIndex++) {
+ Width = (Nv >> (RPIndex * BITS_PER_BYTE)) & BYTE_MASK;
+ switch (Width) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ RC->Pcie[RPIndex].MaxWidth = 1 << Width;
+ RC->Pcie[RPIndex].MaxGen = SPEED_GEN3;
+ RC->Pcie[RPIndex].Active = TRUE;
+ break;
+
+ case 0:
+ default:
+ RC->Pcie[RPIndex].MaxWidth = LNKW_NONE;
+ RC->Pcie[RPIndex].MaxGen = SPEED_NONE;
+ RC->Pcie[RPIndex].Active = FALSE;
+ break;
+ }
+ }
+
+ if (RC->Type == RCB) {
+ NvParam += NV_PARAM_ENTRYSIZE;
+ Ret = NVParamGet (NvParam, NV_PERM_ALL, &Nv);
+ Nv = (Ret != EFI_SUCCESS) ? 0 : Nv;
+
+ for (RPIndex = MAX_PCIE_A; RPIndex < MAX_PCIE; RPIndex++) {
+ Width = (Nv >> ((RPIndex - MAX_PCIE_A) * BITS_PER_BYTE)) & BYTE_MASK;
+ switch (Width) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ RC->Pcie[RPIndex].MaxWidth = 1 << Width;
+ RC->Pcie[RPIndex].MaxGen = SPEED_GEN3;
+ RC->Pcie[RPIndex].Active = TRUE;
+ break;
+
+ case 0:
+ default:
+ RC->Pcie[RPIndex].MaxWidth = LNKW_NONE;
+ RC->Pcie[RPIndex].MaxGen = SPEED_NONE;
+ RC->Pcie[RPIndex].Active = FALSE;
+ break;
+ }
+ }
+ }
+
+ // Do not proceed if no Root Port enabled
+ if (IsEmptyRC (RC)) {
+ RC->Active = FALSE;
+ }
+}
+
+VOID
+BoardPcieSetupDevmap (
+ IN AC01_RC *RC
+ )
+{
+ UINT32 Val;
+
+ if (RC->Pcie[PCIE_0].Active
+ && RC->Pcie[PCIE_1].Active
+ && RC->Pcie[PCIE_2].Active
+ && RC->Pcie[PCIE_3].Active)
+ {
+ RC->DefaultDevMapLow = DEV_MAP_4_CONTROLLERS;
+ } else if (RC->Pcie[PCIE_0].Active
+ && RC->Pcie[PCIE_2].Active
+ && RC->Pcie[PCIE_3].Active)
+ {
+ RC->DefaultDevMapLow = DEV_MAP_3_CONTROLLERS;
+ } else if (RC->Pcie[PCIE_0].Active
+ && RC->Pcie[PCIE_2].Active)
+ {
+ RC->DefaultDevMapLow = DEV_MAP_2_CONTROLLERS;
+ } else {
+ RC->DefaultDevMapLow = DEV_MAP_1_CONTROLLER;
+ }
+
+ if (RC->Pcie[PCIE_4].Active
+ && RC->Pcie[PCIE_5].Active
+ && RC->Pcie[PCIE_6].Active
+ && RC->Pcie[PCIE_7].Active)
+ {
+ RC->DefaultDevMapHigh = DEV_MAP_4_CONTROLLERS;
+ } else if (RC->Pcie[PCIE_4].Active
+ && RC->Pcie[PCIE_6].Active
+ && RC->Pcie[PCIE_7].Active)
+ {
+ RC->DefaultDevMapHigh = DEV_MAP_3_CONTROLLERS;
+ } else if (RC->Pcie[PCIE_4].Active
+ && RC->Pcie[PCIE_6].Active)
+ {
+ RC->DefaultDevMapHigh = DEV_MAP_2_CONTROLLERS;
+ } else {
+ RC->DefaultDevMapHigh = DEV_MAP_1_CONTROLLER;
+ }
+
+ if (RC->DevMapLow == DEV_MAP_1_CONTROLLER) {
+ RC->DevMapLow = RC->DefaultDevMapLow;
+ }
+
+ if (RC->Type == RCB && RC->DevMapHigh == DEV_MAP_1_CONTROLLER) {
+ RC->DevMapHigh = RC->DefaultDevMapHigh;
+ }
+
+ BoardPcieSetRCBifurcation (RC, PCIE_0, RC->DevMapLow);
+ if (RC->Type == RCB) {
+ BoardPcieSetRCBifurcation (RC, PCIE_4, RC->DevMapHigh);
+ }
+
+ if (RC->Active) {
+ if (RC->Type == RCA) {
+ if (!EFI_ERROR (MailboxMsgRegisterRead (RC->Socket, RC->HBAddr + RCA_DEV_MAP_OFFSET, &Val))) {
+ Val = RCA_DEV_MAP_SET (Val, RC->DevMapLow);
+ MailboxMsgRegisterWrite (RC->Socket, RC->HBAddr + RCA_DEV_MAP_OFFSET, Val);
+ }
+ } else {
+ if (!EFI_ERROR (MailboxMsgRegisterRead (RC->Socket, RC->HBAddr + RCB_DEV_MAP_OFFSET, &Val))) {
+ Val = RCB_DEV_MAP_LOW_SET (Val, RC->DevMapLow);
+ Val = RCB_DEV_MAP_HIGH_SET (Val, RC->DevMapHigh);
+ MailboxMsgRegisterWrite (RC->Socket, RC->HBAddr + RCB_DEV_MAP_OFFSET, Val);
+ }
+ }
+ }
+}
+
+VOID
+BoardPcieGetSpeed (
+ IN AC01_RC *RC
+ )
+{
+ UINT8 MaxGenTbl[MAX_PCIE_A] = { SPEED_GEN4, SPEED_GEN4, SPEED_GEN4, SPEED_GEN4 }; // Bifurcation 0: RCA x16 / RCB x8
+ UINT8 MaxGenTblX8X4X4[MAX_PCIE_A] = { SPEED_GEN4, SPEED_GEN4, SPEED_GEN1, SPEED_GEN1 }; // Bifurcation 2: x8 x4 x4 (PCIE_ERRATA_SPEED1)
+ UINT8 MaxGenTblX4X4X4X4[MAX_PCIE_A] = { SPEED_GEN1, SPEED_GEN1, SPEED_GEN1, SPEED_GEN1 }; // Bifurcation 3: x4 x4 x4 x4 (PCIE_ERRATA_SPEED1)
Tbl -> Table.
Please drop the Xs from the variable names.

+ UINT8 MaxGenTblRCB[MAX_PCIE_A] = { SPEED_GEN1, SPEED_GEN1, SPEED_GEN1, SPEED_GEN1 }; // RCB PCIE_ERRATA_SPEED1
RootComplexB (?);


+ INTN RPIdx;
RootPortIdx.

+ UINT8 *MaxGen;
+
+ ASSERT (MAX_PCIE_A == 4);
+ ASSERT (MAX_PCIE == 8);
+
+ //
+ // Due to hardware errata, for A0/A1*
+ // RCB is limited to Gen1 speed.
+ // RCA x16, x8 port supports up to Gen4,
+ // RCA x4 port only supports Gen1.
+ //
+ MaxGen = MaxGenTbl;
+ if (RC->Type == RCB) {
+ if (RC->Flags & PCIE_ERRATA_SPEED1) {
+ MaxGen = MaxGenTblRCB;
+ }
+ } else {
+ switch (RC->DevMapLow) {
+ case DEV_MAP_3_CONTROLLERS: /* x8 x4 x4 */
+ if (RC->Flags & PCIE_ERRATA_SPEED1) {
+ MaxGen = MaxGenTblX8X4X4;
+ }
+ break;
+
+ case DEV_MAP_4_CONTROLLERS: /* X4 x4 x4 x4 */
+ if (RC->Flags & PCIE_ERRATA_SPEED1) {
+ MaxGen = MaxGenTblX4X4X4X4;
+ }
+ break;
+
+ case DEV_MAP_2_CONTROLLERS: /* x8 x8 */
+ default:
+ break;
+ }
+ }
+
+ for (RPIdx = 0; RPIdx < MAX_PCIE_A; RPIdx++) {
+ RC->Pcie[RPIdx].MaxGen = RC->Pcie[RPIdx].Active ? MaxGen[RPIdx] : SPEED_NONE;
+ }
+
+ if (RC->Type == RCB) {
+ for (RPIdx = MAX_PCIE_A; RPIdx < MAX_PCIE; RPIdx++) {
+ RC->Pcie[RPIdx].MaxGen = RC->Pcie[RPIdx].Active ?
+ MaxGen[RPIdx - MAX_PCIE_A] : SPEED_NONE;
+ }
+ }
+}
diff --git a/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieScreen.c b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieScreen.c
new file mode 100644
index 000000000000..eed53c6abed7
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieScreen.c
@@ -0,0 +1,1244 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Guid/MdeModuleHii.h>
+#include <Guid/PlatformInfoHobGuid.h>
+#include <Library/AmpereCpuLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NVParamLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <NVParamDef.h>
+#include <Platform/Ac01.h>
+#include <PlatformInfoHob.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigKeyword.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
+
+#include "BoardPcie.h"
+#include "BoardPcieScreen.h"
+
+#ifndef BIT
+#define BIT(nr) (1 << (nr))
+#endif
+
+BOOLEAN mReadOnlyStrongOrdering;
+CHAR16 mPcieNvparamVarstoreName[] = NVPARAM_VARSTORE_NAME;
+CHAR16 gPcieVarstoreName[] = VARSTORE_NAME;
+EFI_GUID gPcieFormSetGuid = FORM_SET_GUID;
+
+SCREEN_PRIVATE_DATA *mPrivateData = NULL;
+
+AC01_RC RCList[AC01_MAX_PCIE_ROOT_COMPLEX];
mRootComplexList

+
+HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ FORM_SET_GUID
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8)(END_DEVICE_PATH_LENGTH),
+ (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
+ }
+ }
+};
+
+/**
+ This function allows a caller to extract the current configuration for one
+ or more named elements from the target driver.
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Request A null-terminated Unicode string in
+ <ConfigRequest> format.
+ @param Progress On return, points to a character in the Request
+ string. Points to the string's null terminator if
+ request was successful. Points to the most recent
+ '&' before the first failing name/value pair (or
+ the beginning of the string if the failure is in
+ the first name/value pair) if the request was not
+ successful.
+ @param Results A null-terminated Unicode string in
+ <ConfigAltResp> format which has all values filled
+ in for the names in the Request string. String to
+ be allocated by the called function.
+ @retval EFI_SUCCESS The Results is filled with the requested values.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
+ @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+**/
STATIC (address as appropriate through file)

+EFI_STATUS
+EFIAPI
+ExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ SCREEN_PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ EFI_STRING ConfigRequest;
+ UINTN Size;
+ CHAR16 *StrPointer;
+ BOOLEAN AllocatedRequest;
+ UINT8 *VarStoreConfig;
+ UINT32 Value;
Number of variables suggests this function should be split up.

+
+ if (Progress == NULL || Results == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Request == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Initialize the local variables.
+ //
+ ConfigRequest = NULL;
+ Size = 0;
+ *Progress = Request;
+ AllocatedRequest = FALSE;
+
+ PrivateData = SCREEN_PRIVATE_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+
+ //
+ // Check routing data in <ConfigHdr>.
+ // Note: if only one Storage is used, then this checking could be skipped.
+ //
+ if (HiiIsConfigHdrMatch (Request, &gPcieFormSetGuid, mPcieNvparamVarstoreName)) {
+ VarStoreConfig = (UINT8 *)&PrivateData->NVParamVarStoreConfig;
+ ASSERT (VarStoreConfig != NULL);
+
+ Status = NVParamGet (
+ NV_SI_MESH_S0_CXG_RC_STRONG_ORDERING_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (Value != 0) {
+ PrivateData->NVParamVarStoreConfig.PcieStrongOrdering = TRUE;
+ }
+
+ Status = NVParamGet (
+ NV_SI_MESH_S1_CXG_RC_STRONG_ORDERING_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &Value
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (Value != 0) {
+ PrivateData->NVParamVarStoreConfig.PcieStrongOrdering = TRUE;
+ }
+
+ BufferSize = sizeof (NVPARAM_VARSTORE_DATA);
+
+ } else if (HiiIsConfigHdrMatch (Request, &gPcieFormSetGuid, gPcieVarstoreName)) {
+ VarStoreConfig = (UINT8 *)&PrivateData->VarStoreConfig;
+ ASSERT (VarStoreConfig != NULL);
+
+ //
+ // Get Buffer Storage data from EFI variable.
+ // Try to get the current setting from variable.
+ //
+ BufferSize = sizeof (VARSTORE_DATA);
+ Status = gRT->GetVariable (
+ gPcieVarstoreName,
+ &gPcieFormSetGuid,
+ NULL,
+ &BufferSize,
+ VarStoreConfig
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ } else {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Set Request to the unified request string.
+ //
+ ConfigRequest = Request;
+
+ //
+ // Check whether Request includes Request Element.
+ //
+ if (StrStr (Request, L"OFFSET") == NULL) {
+ //
+ // Check Request Element does exist in Request String
+ //
+ StrPointer = StrStr (Request, L"PATH");
+ if (StrPointer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (StrStr (StrPointer, L"&") == NULL) {
+ //
+ // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+ // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
+ //
+ Size = (StrLen (Request) + 32 + 1) * sizeof (CHAR16);
+ ConfigRequest = AllocateZeroPool (Size);
+ ASSERT (ConfigRequest != NULL);
+ AllocatedRequest = TRUE;
+ UnicodeSPrint (
+ ConfigRequest,
+ Size,
+ L"%s&OFFSET=0&WIDTH=%016LX",
+ Request,
+ (UINT64)BufferSize
+ );
+ }
+ }
+
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ Status = HiiConfigRouting->BlockToConfig (
+ HiiConfigRouting,
+ ConfigRequest,
+ VarStoreConfig,
+ BufferSize,
+ Results,
+ Progress
+ );
+
+ //
+ // Free the allocated config request string.
+ //
+ if (AllocatedRequest) {
+ FreePool (ConfigRequest);
+ }
+
+ //
+ // Set Progress string to the original request string.
+ //
+ if (Request == NULL) {
+ *Progress = NULL;
+ } else if (StrStr (Request, L"OFFSET") == NULL) {
+ *Progress = Request + StrLen (Request);
+ }
+
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Configuration A null-terminated Unicode string in <ConfigResp>
+ format.
+ @param Progress A pointer to a string filled in with the offset of
+ the most recent '&' before the first failing
+ name/value pair (or the beginning of the string if
+ the failure is in the first name/value pair) or
+ the terminating NULL if all was successful.
+ @retval EFI_SUCCESS The Results is processed successfully.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+**/
+EFI_STATUS
+EFIAPI
+RouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ SCREEN_PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ UINT8 *VarStoreConfig;
+ UINT32 Value;
+
+ if (Configuration == NULL || Progress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = SCREEN_PRIVATE_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+ *Progress = Configuration;
+
+ if (HiiIsConfigHdrMatch (Configuration, &gPcieFormSetGuid, mPcieNvparamVarstoreName)) {
+ VarStoreConfig = (UINT8 *)&PrivateData->NVParamVarStoreConfig;
+ BufferSize = sizeof (NVPARAM_VARSTORE_DATA);
+ } else if (HiiIsConfigHdrMatch (Configuration, &gPcieFormSetGuid, gPcieVarstoreName)) {
+ BufferSize = sizeof (VARSTORE_DATA);
+ VarStoreConfig = (UINT8 *)&PrivateData->VarStoreConfig;
+ }
+ ASSERT (VarStoreConfig != NULL);
+
+ //
+ // Check if configuring Name/Value storage
+ //
+ if (StrStr (Configuration, L"OFFSET") == NULL) {
+ //
+ // Don't have any Name/Value storage names
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
+ //
+ Status = HiiConfigRouting->ConfigToBlock (
+ HiiConfigRouting,
+ Configuration,
+ (UINT8 *)VarStoreConfig,
+ &BufferSize,
+ Progress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Check routing data in <ConfigHdr>.
+ //
+ if (HiiIsConfigHdrMatch (Configuration, &gPcieFormSetGuid, mPcieNvparamVarstoreName)) {
+ Value = PrivateData->NVParamVarStoreConfig.PcieStrongOrdering ? STRONG_ORDERING_DEFAULT_NVPARAM_VALUE : 0;
Break long line after question mark.

+
+ if (!mReadOnlyStrongOrdering) {
+ //
+ // Update whole 16 RCs.
+ //
+ Status = NVParamSet (
+ NV_SI_MESH_S0_CXG_RC_STRONG_ORDERING_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Value
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // No need to check slave present
+ //
+ Status = NVParamSet (
+ NV_SI_MESH_S1_CXG_RC_STRONG_ORDERING_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ Value
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ } else if (HiiIsConfigHdrMatch (Configuration, &gPcieFormSetGuid, gPcieVarstoreName)) {
+ //
+ // Store Buffer Storage back to variable
+ //
+ Status = gRT->SetVariable (
+ gPcieVarstoreName,
+ &gPcieFormSetGuid,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof (VARSTORE_DATA),
+ (VARSTORE_DATA *)VarStoreConfig
+ );
+ }
+
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Action Specifies the type of action taken by the browser.
+ @param QuestionId A unique value which is sent to the original
+ exporting driver so that it can identify the type
+ of data to expect.
+ @param Type The type of value for the question.
+ @param Value A pointer to the data being sent to the original
+ exporting driver.
+ @param ActionRequest On return, points to the action requested by the
+ callback function.
+ @retval EFI_SUCCESS The callback successfully handled the action.
+ @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
+ variable and its data.
+ @retval EFI_DEVICE_ERROR The variable could not be saved.
+ @retval EFI_UNSUPPORTED The specified Action is not supported by the
+ callback.
+**/
+EFI_STATUS
+EFIAPI
+DriverCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+{
+ SCREEN_PRIVATE_DATA *PrivateData;
+ EFI_STATUS Status;
+
+ if (((Value == NULL) &&
+ (Action != EFI_BROWSER_ACTION_FORM_OPEN) &&
+ (Action != EFI_BROWSER_ACTION_FORM_CLOSE)) ||
+ (ActionRequest == NULL))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = SCREEN_PRIVATE_FROM_THIS (This);
+
+ Status = EFI_SUCCESS;
+
+ switch (Action) {
+ case EFI_BROWSER_ACTION_FORM_OPEN:
+ break;
+
+ case EFI_BROWSER_ACTION_FORM_CLOSE:
+ break;
+
+ case EFI_BROWSER_ACTION_DEFAULT_STANDARD:
+ case EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING:
+ if (QuestionId == 0x9000) {
Please assign #defines for question ids instead of live-coding them in
two places.

+ //
+ // SMMU PMU
+ //
+ Value->u32 = 0;
+ break;
+ }
+
+ if (QuestionId == 0x9001) {
+ //
+ // Strong Ordering
+ //
+ Value->u8 = STRONG_ORDERING_DEFAULT_OPTION_VALUE;
+ break;
+ }
+
+ switch ((QuestionId - 0x8002) % MAX_EDITABLE_ELEMENTS) {
+ case 0:
+ Value->u8 = PcieRCActiveDefaultSetting ((QuestionId - 0x8002) / MAX_EDITABLE_ELEMENTS, PrivateData);
+ break;
+
+ case 1:
+ Value->u8 = PcieRCDevMapLowDefaultSetting ((QuestionId - 0x8002) / MAX_EDITABLE_ELEMENTS, PrivateData);
+ break;
+
+ case 2:
+ Value->u8 = PcieRCDevMapHighDefaultSetting ((QuestionId - 0x8002) / MAX_EDITABLE_ELEMENTS, PrivateData);
+ break;
+ }
+ break;
+
+ case EFI_BROWSER_ACTION_RETRIEVE:
+ case EFI_BROWSER_ACTION_CHANGING:
+ case EFI_BROWSER_ACTION_SUBMITTED:
+ break;
+
+ default:
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ This function return default settings for Dev Map LO.
+ @param RC Root Complex ID.
+ @param PrivateData Private data.
+
+ @retval Default dev settings.
+**/
+UINT8
+PcieRCDevMapLowDefaultSetting (
+ IN UINTN RCIndex,
+ IN SCREEN_PRIVATE_DATA *PrivateData
+ )
+{
+ AC01_RC *RC = &RCList[RCIndex];
+
+ return RC->DefaultDevMapLow;
+}
+
+/**
+ This function return default settings for Dev Map HI.
+ @param RC Root Complex ID.
+ @param PrivateData Private data.
+
+ @retval Default dev settings.
+**/
+UINT8
+PcieRCDevMapHighDefaultSetting (
+ IN UINTN RCIndex,
+ IN SCREEN_PRIVATE_DATA *PrivateData
+ )
+{
+ AC01_RC *RC = &RCList[RCIndex];
+
+ return RC->DefaultDevMapHigh;
+}
+
+BOOLEAN
+PcieRCActiveDefaultSetting (
+ IN UINTN RCIndex,
+ IN SCREEN_PRIVATE_DATA *PrivateData
+ )
+{
+ PLATFORM_INFO_HOB *PlatformHob;
+ VOID *Hob;
+ UINT32 Efuse;
+
+ Hob = GetFirstGuidHob (&gPlatformHobGuid);
+ if (Hob != NULL) {
+ PlatformHob = (PLATFORM_INFO_HOB *)GET_GUID_HOB_DATA (Hob);
+ Efuse = PlatformHob->RcDisableMask[0] | (PlatformHob->RcDisableMask[1] << AC01_MAX_RCS_PER_SOCKET);
+ return (!(Efuse & BIT (RCIndex))) ? TRUE : FALSE;
+ }
+
+ return FALSE;
+}
+
+/**
+ This function sets up the first elements of the form.
+ @param RC Root Complex ID.
+ @param PrivateData Private data.
+ @retval EFI_SUCCESS The form is set up successfully.
+**/
+EFI_STATUS
+PcieRCScreenSetup (
+ IN UINTN RCIndex,
+ IN SCREEN_PRIVATE_DATA *PrivateData
+ )
+{
+ VOID *StartOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *EndLabel;
+ VOID *OptionsOpCodeHandle;
+ VOID *OptionsHiOpCodeHandle;
+ CHAR16 Str[MAX_STRING_SIZE];
+ UINT16 DisabledStatusVarOffset;
+ UINT16 BifurLoVarOffset;
+ UINT16 BifurHiVarOffset;
+ UINT8 QuestionFlags, QuestionFlagsSubItem;
+ AC01_RC *RC;
An awful lot of variables for a single function...

+
+ RC = &RCList[RCIndex];
+
+ // Initialize the container for dynamic opcodes
+ StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (StartOpCodeHandle != NULL);
+ EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (EndOpCodeHandle != NULL);
+
+ // Create Hii Extend Label OpCode as the start opcode
+ StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
+ StartOpCodeHandle,
+ &gEfiIfrTianoGuid,
+ NULL,
+ sizeof (EFI_IFR_GUID_LABEL)
+ );
+ StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ StartLabel->Number = LABEL_RC0_UPDATE + 2 * RCIndex;
+
+ // Create Hii Extend Label OpCode as the end opcode
+ EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
+ EndOpCodeHandle,
+ &gEfiIfrTianoGuid,
+ NULL,
+ sizeof (EFI_IFR_GUID_LABEL)
+ );
+ EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ EndLabel->Number = LABEL_RC0_END + 2 * RCIndex;
+
+ // Create textbox to tell socket
+ HiiCreateTextOpCode (
+ StartOpCodeHandle,
+ STRING_TOKEN (STR_PCIE_SOCKET),
+ STRING_TOKEN (STR_PCIE_SOCKET_HELP),
+ HiiSetString (
+ PrivateData->HiiHandle,
+ 0,
+ (RC->Socket) ? L"1" : L"0",
+ NULL
+ )
+ );
+
+ // Create textbox to tell Root Complex type
+ HiiCreateTextOpCode (
+ StartOpCodeHandle,
+ STRING_TOKEN (STR_PCIE_RC_TYPE),
+ STRING_TOKEN (STR_PCIE_RC_TYPE_HELP),
+ HiiSetString (
+ PrivateData->HiiHandle,
+ 0,
+ (RC->Type == RCA) ? L"Root Complex Type-A" : L"Root Complex Type-B",
+ NULL
+ )
+ );
+
+ UnicodeSPrint (Str, sizeof (Str), L"Root Complex #%2d", RCIndex);
+
+ DisabledStatusVarOffset = (UINT16)RC0_STATUS_OFFSET +
+ sizeof (BOOLEAN) * RCIndex;
+ BifurLoVarOffset = (UINT16)RC0_BIFUR_LO_OFFSET +
+ sizeof (UINT8) * RCIndex;
+ BifurHiVarOffset = (UINT16)RC0_BIFUR_HI_OFFSET +
+ sizeof (UINT8) * RCIndex;
+
+ QuestionFlags = EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_CALLBACK;
+ if (IsEmptyRC (RC)
+ || (GetNumberOfActiveSockets () == 1 && RC->Socket == 1))
+ {
+ //
+ // Do not allow changing if none of Root Port underneath enabled
+ // or slave Root Complex on 1P system.
+ //
+ QuestionFlags |= EFI_IFR_FLAG_READ_ONLY;
+ }
+ // Create the RC disabled checkbox
+ HiiCreateCheckBoxOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ 0x8002 + MAX_EDITABLE_ELEMENTS * RCIndex, // QuestionId (or "key")
+ VARSTORE_ID, // VarStoreId
+ DisabledStatusVarOffset, // VarOffset in Buffer Storage
+ HiiSetString (
+ PrivateData->HiiHandle,
+ 0,
+ Str,
+ NULL
+ ), // Prompt
+ STRING_TOKEN (STR_PCIE_RC_STATUS_HELP), // Help
+ QuestionFlags, // QuestionFlags
+ 0, // CheckBoxFlags
+ NULL // DefaultsOpCodeHandle
+ );
+
+ if (RC->Type == RCA) {
+ // Create Option OpCode to display bifurcation for RCA
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE0),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 0 // Devmap=0
+ );
+
+
+ if (RC->DefaultDevMapLow != 0) {
+ QuestionFlags |= EFI_IFR_FLAG_READ_ONLY;
+ }
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE1),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 1 // Devmap=1
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE2),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 2 // Devmap=2
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE3),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 3 // Devmap=3
+ );
+
+ HiiCreateOneOfOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ 0x8003 + MAX_EDITABLE_ELEMENTS * RCIndex, // Question ID (or call it "key")
+ VARSTORE_ID, // VarStore ID
+ BifurLoVarOffset, // Offset in Buffer Storage
+ STRING_TOKEN (STR_PCIE_RCA_BIFUR), // Question prompt text
+ STRING_TOKEN (STR_PCIE_RCA_BIFUR_HELP), // Question help text
+ QuestionFlags, // Question flag
+ EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value
+ OptionsOpCodeHandle, // Option Opcode list
+ NULL // Default Opcode is NULl
+ );
+ } else {
+ // Create Option OpCode to display bifurcation for RCB-Lo
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE4),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 0 // Devmap=0
+ );
+
+ QuestionFlagsSubItem = QuestionFlags;
+ if (RC->DefaultDevMapLow != 0) {
+ QuestionFlagsSubItem |= EFI_IFR_FLAG_READ_ONLY;
+ }
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE5),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 1 // Devmap=1
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE6),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 2 // Devmap=2
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE7),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 3 // Devmap=3
+ );
+
+ HiiCreateOneOfOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ 0x8003 + MAX_EDITABLE_ELEMENTS * RCIndex, // Question ID (or call it "key")
+ VARSTORE_ID, // VarStore ID
+ BifurLoVarOffset, // Offset in Buffer Storage
+ STRING_TOKEN (STR_PCIE_RCB_LO_BIFUR), // Question prompt text
+ STRING_TOKEN (STR_PCIE_RCB_LO_BIFUR_HELP), // Question help text
+ QuestionFlagsSubItem, // Question flag
+ EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value
+ OptionsOpCodeHandle, // Option Opcode list
+ NULL // Default Opcode is NULl
+ );
+
+ // Create Option OpCode to display bifurcation for RCB-Hi
+ OptionsHiOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsHiOpCodeHandle != NULL);
+
+ QuestionFlagsSubItem = QuestionFlags;
+ if (RC->DefaultDevMapHigh != 0) {
+ QuestionFlagsSubItem |= EFI_IFR_FLAG_READ_ONLY;
+ }
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsHiOpCodeHandle,
+ STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE4),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 0 // Devmap=0
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsHiOpCodeHandle,
+ STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE5),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 1 // Devmap=1
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsHiOpCodeHandle,
+ STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE6),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 2 // Devmap=2
+ );
+
+ HiiCreateOneOfOptionOpCode (
+ OptionsHiOpCodeHandle,
+ STRING_TOKEN (STR_PCIE_BIFUR_SELECT_VALUE7),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 3 // Devmap=3
+ );
+
+ HiiCreateOneOfOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ 0x8004 + MAX_EDITABLE_ELEMENTS * RCIndex, // Question ID (or call it "key")
+ VARSTORE_ID, // VarStore ID
+ BifurHiVarOffset, // Offset in Buffer Storage
+ STRING_TOKEN (STR_PCIE_RCB_HI_BIFUR), // Question prompt text
+ STRING_TOKEN (STR_PCIE_RCB_HI_BIFUR_HELP), // Question help text
+ QuestionFlagsSubItem, // Question flag
+ EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value
+ OptionsHiOpCodeHandle, // Option Opcode list
+ NULL // Default Opcode is NULl
+ );
+ }
+
+ HiiUpdateForm (
+ PrivateData->HiiHandle, // HII handle
+ &gPcieFormSetGuid, // Formset GUID
+ RC0_FORM_ID + RCIndex, // Form ID
+ StartOpCodeHandle, // Label for where to insert opcodes
+ EndOpCodeHandle // Insert data
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function sets up the first elements of the form.
+ @param PrivateData Private data.
+ @retval EFI_SUCCESS The form is set up successfully.
+**/
+EFI_STATUS
+PcieMainScreenSetup (
+ IN SCREEN_PRIVATE_DATA *PrivateData
+ )
+{
+ VOID *StartOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *EndLabel;
+ CHAR16 Str[MAX_STRING_SIZE];
+ UINTN RC;
+ SETUP_GOTO_DATA *GotoItem = NULL;
+ EFI_QUESTION_ID GotoId;
+ UINT8 QuestionFlags;
+
+ // Initialize the container for dynamic opcodes
+ StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (StartOpCodeHandle != NULL);
+ EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (EndOpCodeHandle != NULL);
+
+ // Create Hii Extend Label OpCode as the start opcode
+ StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
+ StartOpCodeHandle,
+ &gEfiIfrTianoGuid,
+ NULL,
+ sizeof (EFI_IFR_GUID_LABEL)
+ );
+ StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ StartLabel->Number = LABEL_UPDATE;
+
+ // Create Hii Extend Label OpCode as the end opcode
+ EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
+ EndOpCodeHandle,
+ &gEfiIfrTianoGuid,
+ NULL,
+ sizeof (EFI_IFR_GUID_LABEL)
+ );
+ EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ EndLabel->Number = LABEL_END;
+
+ QuestionFlags = EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED;
+
+ HiiCreateCheckBoxOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ 0x9000, // Question ID
+ VARSTORE_ID, // VarStore ID
+ (UINT16)SMMU_PMU_OFFSET, // Offset in Buffer Storage
+ STRING_TOKEN (STR_PCIE_SMMU_PMU_PROMPT), // Question prompt text
+ STRING_TOKEN (STR_PCIE_SMMU_PMU_HELP), // Question help text
+ QuestionFlags,
+ 0,
+ NULL
+ );
+
+ if (mReadOnlyStrongOrdering) {
+ QuestionFlags |= EFI_IFR_FLAG_READ_ONLY;
+ }
+
+ HiiCreateCheckBoxOpCode (
+ StartOpCodeHandle, // Container for dynamic created opcodes
+ 0x9001, // Question ID
+ NVPARAM_VARSTORE_ID, // VarStore ID
+ (UINT16)STRONG_ODERING_OFFSET, // Offset in Buffer Storage
+ STRING_TOKEN (STR_PCIE_STRONG_ORDERING_PROMPT), // Question prompt text
+ STRING_TOKEN (STR_PCIE_STRONG_ORDERING_HELP), // Question help text
+ QuestionFlags,
+ STRONG_ORDERING_DEFAULT_OPTION_VALUE,
+ NULL
+ );
+
+ //
+ // Create the a seperated line
+ //
+ HiiCreateTextOpCode (
+ StartOpCodeHandle,
+ STRING_TOKEN (STR_PCIE_FORM_SEPERATE_LINE),
+ STRING_TOKEN (STR_PCIE_FORM_SEPERATE_LINE),
+ STRING_TOKEN (STR_PCIE_FORM_SEPERATE_LINE)
+ );
+
+ // Create Goto form for each RC
+ for (RC = 0; RC < AC01_MAX_PCIE_ROOT_COMPLEX; RC++) {
+
+ GotoItem = AllocateZeroPool (sizeof (SETUP_GOTO_DATA));
+ if (GotoItem == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ GotoItem->PciDevIdx = RC;
+
+ GotoId = GOTO_ID_BASE + (UINT16)RC;
+
+ // Update HII string
+ UnicodeSPrint (Str, sizeof (Str), L"Root Complex #%2d", RC);
+ GotoItem->GotoStringId = HiiSetString (
+ PrivateData->HiiHandle,
+ 0,
+ Str,
+ NULL
+ );
+ GotoItem->GotoHelpStringId = STRING_TOKEN (STR_PCIE_GOTO_HELP);
+ GotoItem->ShowItem = TRUE;
+
+ // Add goto control
+ HiiCreateGotoOpCode (
+ StartOpCodeHandle,
+ RC0_FORM_ID + RC,
+ GotoItem->GotoStringId,
+ GotoItem->GotoHelpStringId,
+ EFI_IFR_FLAG_CALLBACK,
+ GotoId
+ );
+ }
+
+ HiiUpdateForm (
+ PrivateData->HiiHandle, // HII handle
+ &gPcieFormSetGuid, // Formset GUID
+ FORM_ID, // Form ID
+ StartOpCodeHandle, // Label for where to insert opcodes
+ EndOpCodeHandle // Insert data
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+
+ return EFI_SUCCESS;
+}
+
+VOID
+NVParamVarstoreInit (
+ VOID
+ )
+{
+ BOOLEAN BoardSettingValid;
+ BOOLEAN UserSettingValid;
+ BOOLEAN Update;
+ EFI_STATUS Status;
+ UINT32 UserValue;
+ UINT32 InitValue;
+
+ mReadOnlyStrongOrdering = FALSE;
+
+ // S0
+ UserSettingValid = FALSE;
+ Status = NVParamGet (
+ NV_SI_MESH_S0_CXG_RC_STRONG_ORDERING_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &UserValue
+ );
+ if (!EFI_ERROR (Status)) {
+ UserSettingValid = TRUE;
+ }
+
+ //
+ // InitValue will be default value or board setting value.
+ //
+ BoardSettingValid = FALSE;
+ Status = NVParamGet (
+ NV_SI_RO_BOARD_MESH_S0_CXG_RC_STRONG_ORDERING_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &InitValue
+ );
+ if (!EFI_ERROR (Status) && InitValue > 0) {
+ BoardSettingValid = TRUE;
+ mReadOnlyStrongOrdering = TRUE;
+ } else {
+ InitValue = STRONG_ORDERING_DEFAULT_NVPARAM_VALUE;
+ }
+
+ Update = TRUE;
+ if ((UserSettingValid && (UserValue == InitValue))
+ || (!BoardSettingValid && UserSettingValid && (UserValue == 0)))
+ {
Mover brace up.

/
Leif

+ Update = FALSE;
+ }
+
+ if (Update) {
+ Status = NVParamSet (
+ NV_SI_MESH_S0_CXG_RC_STRONG_ORDERING_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ InitValue
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // No need to check slave present.
+ //
+ UserSettingValid = FALSE;
+ Status = NVParamGet (
+ NV_SI_MESH_S1_CXG_RC_STRONG_ORDERING_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &UserValue
+ );
+ if (!EFI_ERROR (Status)) {
+ UserSettingValid = TRUE;
+ }
+
+ //
+ // InitValue will be default value or board setting value.
+ //
+ BoardSettingValid = FALSE;
+ Status = NVParamGet (
+ NV_SI_RO_BOARD_MESH_S1_CXG_RC_STRONG_ORDERING_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ &InitValue
+ );
+ if (!EFI_ERROR (Status) && InitValue > 0) {
+ BoardSettingValid = TRUE;
+ mReadOnlyStrongOrdering = TRUE;
+ } else {
+ InitValue = STRONG_ORDERING_DEFAULT_NVPARAM_VALUE;
+ }
+
+ Update = TRUE;
+ if ((UserSettingValid && (UserValue == InitValue))
+ || (!BoardSettingValid && UserSettingValid && (UserValue == 0)))
+ {
+ Update = FALSE;
+ }
+
+ if (Update) {
+ Status = NVParamSet (
+ NV_SI_MESH_S1_CXG_RC_STRONG_ORDERING_EN,
+ NV_PERM_ATF | NV_PERM_BIOS | NV_PERM_MANU | NV_PERM_BMC,
+ NV_PERM_BIOS | NV_PERM_MANU,
+ InitValue
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+}
+
+/**
+ Build PCIe menu screen.
+
+ @param[in] RCList List of Root Complex with properties.
+
+ @retval EFI_SUCCESS The operation is successful.
+ @retval Others An error occurred.
+**/
+EFI_STATUS
+EFIAPI
+BoardPcieScreenInitialize (
+ IN AC01_RC *NewRCList
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
+ EFI_HII_STRING_PROTOCOL *HiiString;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *HiiKeywordHandler;
+ UINTN BufferSize;
+ BOOLEAN IsUpdated;
+ VARSTORE_DATA *VarStoreConfig;
+ UINT8 RCIndex;
+ AC01_RC *RC;
+
+ //
+ // Initialize driver private data
+ //
+ mPrivateData = AllocateZeroPool (sizeof (SCREEN_PRIVATE_DATA));
+ if (mPrivateData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mPrivateData->Signature = SCREEN_PRIVATE_DATA_SIGNATURE;
+
+ mPrivateData->ConfigAccess.ExtractConfig = ExtractConfig;
+ mPrivateData->ConfigAccess.RouteConfig = RouteConfig;
+ mPrivateData->ConfigAccess.Callback = DriverCallback;
+
+ //
+ // Locate Hii Database protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ (VOID **)&HiiDatabase
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mPrivateData->HiiDatabase = HiiDatabase;
+
+ //
+ // Locate HiiString protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiStringProtocolGuid,
+ NULL,
+ (VOID **)&HiiString
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mPrivateData->HiiString = HiiString;
+
+ //
+ // Locate ConfigRouting protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiConfigRoutingProtocolGuid,
+ NULL,
+ (VOID **)&HiiConfigRouting
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mPrivateData->HiiConfigRouting = HiiConfigRouting;
+
+ //
+ // Locate keyword handler protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiConfigKeywordHandlerProtocolGuid,
+ NULL,
+ (VOID **)&HiiKeywordHandler
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mPrivateData->HiiKeywordHandler = HiiKeywordHandler;
+
+ DriverHandle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mPrivateData->ConfigAccess,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ mPrivateData->DriverHandle = DriverHandle;
+
+ //
+ // Publish our HII data
+ //
+ HiiHandle = HiiAddPackages (
+ &gPcieFormSetGuid,
+ DriverHandle,
+ BoardPcieLibStrings,
+ BoardPcieVfrBin,
+ NULL
+ );
+ if (HiiHandle == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mPrivateData->HiiHandle = HiiHandle;
+
+ // Make a shadow copy all Root Complexes' properties
+ CopyMem ((VOID *)RCList, (VOID *)NewRCList, sizeof (RCList));
+
+ //
+ // Initialize NVParam varstore configuration data
+ //
+ NVParamVarstoreInit ();
+
+ //
+ // Initialize efi varstore configuration data
+ //
+ VarStoreConfig = &mPrivateData->VarStoreConfig;
+ ZeroMem (VarStoreConfig, sizeof (VARSTORE_DATA));
+
+ // Get Buffer Storage data from EFI variable
+ BufferSize = sizeof (VARSTORE_DATA);
+ Status = gRT->GetVariable (
+ gPcieVarstoreName,
+ &gPcieFormSetGuid,
+ NULL,
+ &BufferSize,
+ VarStoreConfig
+ );
+
+ IsUpdated = FALSE;
+
+ if (EFI_ERROR (Status)) {
+ VarStoreConfig->SmmuPmu = 0; /* Disable by default */
+ IsUpdated = TRUE;
+ }
+ // Update board settings to menu
+ for (RCIndex = 0; RCIndex < AC01_MAX_PCIE_ROOT_COMPLEX; RCIndex++) {
+ RC = &RCList[RCIndex];
+
+ if (EFI_ERROR (Status)) {
+ VarStoreConfig->RCBifurcationLow[RCIndex] = RC->DevMapLow;
+ VarStoreConfig->RCBifurcationHigh[RCIndex] = RC->DevMapHigh;
+ VarStoreConfig->RCStatus[RCIndex] = RC->Active;
+ IsUpdated = TRUE;
+ }
+ }
+
+ if (IsUpdated) {
+ // Update Buffer Storage
+ Status = gRT->SetVariable (
+ gPcieVarstoreName,
+ &gPcieFormSetGuid,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof (VARSTORE_DATA),
+ VarStoreConfig
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ Status = PcieMainScreenSetup (mPrivateData);
+ ASSERT_EFI_ERROR (Status);
+
+ for (RCIndex = 0; RCIndex < AC01_MAX_PCIE_ROOT_COMPLEX; RCIndex++) {
+ Status = PcieRCScreenSetup (RCIndex, mPrivateData);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
diff --git a/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieScreen.uni b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieScreen.uni
new file mode 100644
index 000000000000..5739a35b4ee5
--- /dev/null
+++ b/Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieScreen.uni
@@ -0,0 +1,102 @@
+//
+// Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+#langdef en-US "English"
+
+#string STR_PCIE_FORM #language en-US "PCIE Root Complex Configuration"
+#string STR_PCIE_FORM_HELP #language en-US "Configure Root Complex"
+
+#string STR_PCIE_FORM_SEPERATE_LINE #language en-US ""
+
+/////
+
+#string STR_PCIE_GOTO #language en-US ""
+#string STR_PCIE_GOTO_HELP #language en-US "Change On Board Root Complex Settings."
+
+#string STR_PCIE_RC_STATUS #language en-US ""
+#string STR_PCIE_RC_STATUS_HELP #language en-US "Enable / Disable Root Complex"
+
+#string STR_PCIE_RCA_BIFUR #language en-US "Bifurcation x16"
+#string STR_PCIE_RCA_BIFUR_HELP #language en-US "Set bifurcation mode for x16 Root Complex Type-A"
+
+#string STR_PCIE_RCB_LO_BIFUR #language en-US "Bifurcation 1st x8"
+#string STR_PCIE_RCB_LO_BIFUR_HELP #language en-US "Set bifurcation mode for 1st x8 Root Complex Type-B"
+
+#string STR_PCIE_RCB_HI_BIFUR #language en-US "Bifurcation 2nd x8"
+#string STR_PCIE_RCB_HI_BIFUR_HELP #language en-US "Set bifurcation mode for 2nd x8 Root Complex Type-B"
+
+/////
+
+#string STR_PCIE_RC0_FORM #language en-US "Root Complex 0 Configuration"
+#string STR_PCIE_RC0_FORM_HELP #language en-US "Root Complex 0 Configuration"
+
+#string STR_PCIE_RC1_FORM #language en-US "Root Complex 1 Configuration"
+#string STR_PCIE_RC1_FORM_HELP #language en-US "Root Complex 1 Configuration"
+
+#string STR_PCIE_RC2_FORM #language en-US "Root Complex 2 Configuration"
+#string STR_PCIE_RC2_FORM_HELP #language en-US "Root Complex 2 Configuration"
+
+#string STR_PCIE_RC3_FORM #language en-US "Root Complex 3 Configuration"
+#string STR_PCIE_RC3_FORM_HELP #language en-US "Root Complex 3 Configuration"
+
+#string STR_PCIE_RC4_FORM #language en-US "Root Complex 4 Configuration"
+#string STR_PCIE_RC4_FORM_HELP #language en-US "Root Complex 4 Configuration"
+
+#string STR_PCIE_RC5_FORM #language en-US "Root Complex 5 Configuration"
+#string STR_PCIE_RC5_FORM_HELP #language en-US "Root Complex 5 Configuration"
+
+#string STR_PCIE_RC6_FORM #language en-US "Root Complex 6 Configuration"
+#string STR_PCIE_RC6_FORM_HELP #language en-US "Root Complex 6 Configuration"
+
+#string STR_PCIE_RC7_FORM #language en-US "Root Complex 7 Configuration"
+#string STR_PCIE_RC7_FORM_HELP #language en-US "Root Complex 7 Configuration"
+
+#string STR_PCIE_RC8_FORM #language en-US "Root Complex 8 Configuration"
+#string STR_PCIE_RC8_FORM_HELP #language en-US "Root Complex 8 Configuration"
+
+#string STR_PCIE_RC9_FORM #language en-US "Root Complex 9 Configuration"
+#string STR_PCIE_RC9_FORM_HELP #language en-US "Root Complex 9 Configuration"
+
+#string STR_PCIE_RC10_FORM #language en-US "Root Complex 10 Configuration"
+#string STR_PCIE_RC10_FORM_HELP #language en-US "Root Complex 10 Configuration"
+
+#string STR_PCIE_RC11_FORM #language en-US "Root Complex 11 Configuration"
+#string STR_PCIE_RC11_FORM_HELP #language en-US "Root Complex 11 Configuration"
+
+#string STR_PCIE_RC12_FORM #language en-US "Root Complex 12 Configuration"
+#string STR_PCIE_RC12_FORM_HELP #language en-US "Root Complex 12 Configuration"
+
+#string STR_PCIE_RC13_FORM #language en-US "Root Complex 13 Configuration"
+#string STR_PCIE_RC13_FORM_HELP #language en-US "Root Complex 13 Configuration"
+
+#string STR_PCIE_RC14_FORM #language en-US "Root Complex 14 Configuration"
+#string STR_PCIE_RC14_FORM_HELP #language en-US "Root Complex 14 Configuration"
+
+#string STR_PCIE_RC15_FORM #language en-US "Root Complex 15 Configuration"
+#string STR_PCIE_RC15_FORM_HELP #language en-US "Root Complex 15 Configuration"
+
+#string STR_PCIE_BIFUR_SELECT_VALUE0 #language en-US "x16"
+#string STR_PCIE_BIFUR_SELECT_VALUE1 #language en-US "x8+x8"
+#string STR_PCIE_BIFUR_SELECT_VALUE2 #language en-US "x8+x4+x4"
+#string STR_PCIE_BIFUR_SELECT_VALUE3 #language en-US "x4+x4+x4+x4"
+#string STR_PCIE_BIFUR_SELECT_VALUE4 #language en-US "x8"
+#string STR_PCIE_BIFUR_SELECT_VALUE5 #language en-US "x4+x4"
+#string STR_PCIE_BIFUR_SELECT_VALUE6 #language en-US "x4+x2+x2"
+#string STR_PCIE_BIFUR_SELECT_VALUE7 #language en-US "x2+x2+x2+x2"
+
+#string STR_PCIE_SOCKET #language en-US "Socket"
+#string STR_PCIE_SOCKET_HELP #language en-US "Socket 0 - Master; Socket 1 - Slave"
+#string STR_PCIE_SOCKET_VALUE #language en-US ""
+
+#string STR_PCIE_RC_TYPE #language en-US "Type"
+#string STR_PCIE_RC_TYPE_HELP #language en-US "Type-A: x16 lanes bifurcated down to x4; Type-B: 2 of x8 lanes, each bifurcated down to x2"
+#string STR_PCIE_RC_TYPE_VALUE #language en-US ""
+
+#string STR_PCIE_SMMU_PMU_PROMPT #language en-US "SMMU Pmu"
+#string STR_PCIE_SMMU_PMU_HELP #language en-US "Enable/Disable PMU feature for SMMU"
+
+#string STR_PCIE_STRONG_ORDERING_PROMPT #language en-US "PCIe Strong Ordering"
+#string STR_PCIE_STRONG_ORDERING_HELP #language en-US "Enable/disable PCIe Strong Ordering with internal bus"
--
2.17.1


Re: 回复: [PATCH v1 0/4] Set default Makefile name

PierreGondois
 

Hi Liming,

I created: https://bugzilla.tianocore.org/show_bug.cgi?id=3653

Regards,

Pierre

On 9/24/21 1:48 AM, gaoliming wrote:
Pierre:
Can you submit BZ for this change request?

Thanks
Liming
-----邮件原件-----
发件人: Pierre.Gondois@arm.com <Pierre.Gondois@arm.com>
发送时间: 2021年9月23日 16:59
收件人: devel@edk2.groups.io; Bob Feng <bob.c.feng@intel.com>; Liming
Gao <gaoliming@byosoft.com.cn>; Sami Mujawar <sami.mujawar@arm.com>
主题: [PATCH v1 0/4] Set default Makefile name

From: Pierre Gondois <Pierre.Gondois@arm.com>

A Makefile name is not set in BaseTools when only building modules
or libraries. This patch-set sets a default Makefile name for the
"build" command.

The patch-set also:
- Removes unsused Makefile variables
- Removes hard-coded references to "target.txt" and "tools_def.txt"

The changes can be seen at:
https://github.com/PierreARM/edk2/tree/1868_BaseTools_build_py_correcti
ons_v1

Pierre Gondois (4):
BaseTools/GenMake: Use ToolDefinition as fallback option
BaseTools/build: Set MakefileName
BaseTools: Remove Makefile/MakefileName fields
BaseTools: Remove hard-coded strings for target and tools_def

BaseTools/Source/Python/AutoGen/GenMake.py | 8
++++----
BaseTools/Source/Python/AutoGen/ModuleAutoGen.py | 1 -
BaseTools/Source/Python/GenFds/GenFds.py | 4 ++--
.../Source/Python/GenFds/GenFdsGlobalVariable.py | 4 ++--
BaseTools/Source/Python/TargetTool/TargetTool.py | 3 ++-
BaseTools/Source/Python/Workspace/BuildClassObject.py | 2 --
BaseTools/Source/Python/Workspace/DscBuildData.py | 9 ++++-----
BaseTools/Source/Python/build/build.py | 11 ++++-------
8 files changed, 18 insertions(+), 24 deletions(-)

--
2.17.1



[PATCH v7] IntelFsp2WrapperPkg : FSPM/S UPD data address based on Build Type

Ashraf Ali S
 

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3642
when the module is not building in IA32 mode which will lead to
building error. when a module built-in X64 function pointer will be the
size of 64bit width which cannot be fit in 32bit address which will lead
to error. to overcome this issue introducing the 2 new PCD's
for the 64bit modules can consume it.
Creating the API's to support different architecture

Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Kuo Ted <ted.kuo@intel.com>
Cc: Duggapu Chinni B <chinni.b.duggapu@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
Cc: Digant H Solanki <digant.h.solanki@intel.com>
Cc: Sangeetha V <sangeetha.v@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Signed-off-by: Ashraf Ali S <ashraf.ali.s@intel.com>
---
.../FspmWrapperPeim/FspmWrapperPeim.c | 19 +++++++++++---
.../FspmWrapperPeim/FspmWrapperPeim.inf | 16 ++++++++++--
.../FspmWrapperPeim/IA32/FspmHelper.c | 26 +++++++++++++++++++
.../FspmWrapperPeim/X64/FspmHelper.c | 26 +++++++++++++++++++
.../FspsWrapperPeim/FspsWrapperPeim.c | 17 +++++++++---
.../FspsWrapperPeim/FspsWrapperPeim.inf | 14 +++++++++-
.../FspsWrapperPeim/IA32/FspsHelper.c | 26 +++++++++++++++++++
.../FspsWrapperPeim/X64/FspsHelper.c | 26 +++++++++++++++++++
IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec | 2 ++
9 files changed, 162 insertions(+), 10 deletions(-)
create mode 100644 IntelFsp2WrapperPkg/FspmWrapperPeim/IA32/FspmHelper.c
create mode 100644 IntelFsp2WrapperPkg/FspmWrapperPeim/X64/FspmHelper.c
create mode 100644 IntelFsp2WrapperPkg/FspsWrapperPeim/IA32/FspsHelper.c
create mode 100644 IntelFsp2WrapperPkg/FspsWrapperPeim/X64/FspsHelper.c

diff --git a/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c b/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c
index 24ab534620..4a15136c39 100644
--- a/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c
+++ b/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c
@@ -3,7 +3,7 @@
register TemporaryRamDonePpi to call TempRamExit API, and register MemoryDiscoveredPpi
notify to call FspSiliconInit API.

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

**/
@@ -39,6 +39,17 @@

extern EFI_GUID gFspHobGuid;

+/**
+ Get the Fspm Upd Data Address from the PCD
+
+ @return FSPM UPD Data Address
+**/
+UINTN
+EFIAPI
+GetFspmUpdDataAddress (
+ VOID
+ );
+
/**
Call FspMemoryInit API.

@@ -59,7 +70,7 @@ PeiFspMemoryInit (

DEBUG ((DEBUG_INFO, "PeiFspMemoryInit enter\n"));

- FspHobListPtr = NULL;
+ FspHobListPtr = NULL;
FspmUpdDataPtr = NULL;

FspmHeaderPtr = (FSP_INFO_HEADER *) FspFindFspHeader (PcdGet32 (PcdFspmBaseAddress));
@@ -68,7 +79,7 @@ PeiFspMemoryInit (
return EFI_DEVICE_ERROR;
}

- if (PcdGet32 (PcdFspmUpdDataAddress) == 0 && (FspmHeaderPtr->CfgRegionSize != 0) && (FspmHeaderPtr->CfgRegionOffset != 0)) {
+ if (GetFspmUpdDataAddress () == 0 && (FspmHeaderPtr->CfgRegionSize != 0) && (FspmHeaderPtr->CfgRegionOffset != 0)) {
//
// Copy default FSP-M UPD data from Flash
//
@@ -80,7 +91,7 @@ PeiFspMemoryInit (
//
// External UPD is ready, get the buffer from PCD pointer.
//
- FspmUpdDataPtr = (FSPM_UPD_COMMON *)PcdGet32 (PcdFspmUpdDataAddress);
+ FspmUpdDataPtr = (FSPM_UPD_COMMON *) GetFspmUpdDataAddress ();
ASSERT (FspmUpdDataPtr != NULL);
}

diff --git a/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf b/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
index 00166e56a0..5b4ad531e7 100644
--- a/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
+++ b/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
@@ -6,7 +6,7 @@
# register TemporaryRamDonePpi to call TempRamExit API, and register MemoryDiscoveredPpi
# notify to call FspSiliconInit API.
#
-# Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -45,6 +45,7 @@
FspWrapperApiLib
FspWrapperApiTestLib
FspMeasurementLib
+ PcdLib

[Packages]
MdePkg/MdePkg.dec
@@ -56,14 +57,25 @@

[Pcd]
gIntelFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddress ## CONSUMES
- gIntelFsp2WrapperTokenSpaceGuid.PcdFspmUpdDataAddress ## CONSUMES
gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection ## CONSUMES
gIntelFsp2WrapperTokenSpaceGuid.PcdFsptBaseAddress ## CONSUMES
gIntelFsp2WrapperTokenSpaceGuid.PcdFspMeasurementConfig ## CONSUMES

+[Pcd.IA32]
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspmUpdDataAddress ## CONSUMES
+
+[Pcd.X64]
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspmUpdDataAddress64 ## CONSUMES
+
[Sources]
FspmWrapperPeim.c

+[Sources.IA32]
+ IA32/FspmHelper.c
+
+[Sources.X64]
+ X64/FspmHelper.c
+
[Guids]
gFspHobGuid ## PRODUCES ## HOB
gFspApiPerformanceGuid ## SOMETIMES_CONSUMES ## GUID
diff --git a/IntelFsp2WrapperPkg/FspmWrapperPeim/IA32/FspmHelper.c b/IntelFsp2WrapperPkg/FspmWrapperPeim/IA32/FspmHelper.c
new file mode 100644
index 0000000000..cab11173cc
--- /dev/null
+++ b/IntelFsp2WrapperPkg/FspmWrapperPeim/IA32/FspmHelper.c
@@ -0,0 +1,26 @@
+/** @file
+ Sample to provide FSP wrapper related function.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include <Library/PcdLib.h>
+#include <Library/FspWrapperPlatformLib.h>
+#include <Uefi/UefiBaseType.h>
+
+/**
+ Get the Fspm Upd Data Address from the PCD
+
+ @return FSPM UPD Data Address
+**/
+UINTN
+EFIAPI
+GetFspmUpdDataAddress (
+ VOID
+ )
+{
+ return PcdGet32 (PcdFspmUpdDataAddress);
+}
diff --git a/IntelFsp2WrapperPkg/FspmWrapperPeim/X64/FspmHelper.c b/IntelFsp2WrapperPkg/FspmWrapperPeim/X64/FspmHelper.c
new file mode 100644
index 0000000000..25b89ff2e1
--- /dev/null
+++ b/IntelFsp2WrapperPkg/FspmWrapperPeim/X64/FspmHelper.c
@@ -0,0 +1,26 @@
+/** @file
+ Sample to provide FSP wrapper related function.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include <Library/PcdLib.h>
+#include <Library/FspWrapperPlatformLib.h>
+#include <Uefi/UefiBaseType.h>
+
+/**
+ Get the Fspm Upd Data Address from the PCD
+
+ @return FSPM UPD Data Address
+**/
+UINTN
+EFIAPI
+GetFspmUpdDataAddress (
+ VOID
+ )
+{
+ return PcdGet64 (PcdFspmUpdDataAddress64);
+}
diff --git a/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c b/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c
index 9d4f279e81..8bd510502f 100644
--- a/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c
+++ b/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c
@@ -3,7 +3,7 @@
register TemporaryRamDonePpi to call TempRamExit API, and register MemoryDiscoveredPpi
notify to call FspSiliconInit API.

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

**/
@@ -58,6 +58,17 @@ S3EndOfPeiNotify(
IN VOID *Ppi
);

+/**
+ Get the Fsps Upd Data Address from the PCD
+
+ @return FSPS UPD Data Address
+**/
+UINTN
+EFIAPI
+GetFspsUpdDataAddress (
+ VOID
+ );
+
EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc = {
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiEndOfPeiSignalPpiGuid,
@@ -283,7 +294,7 @@ PeiMemoryDiscoveredNotify (
return EFI_DEVICE_ERROR;
}

- if (PcdGet32 (PcdFspsUpdDataAddress) == 0 && (FspsHeaderPtr->CfgRegionSize != 0) && (FspsHeaderPtr->CfgRegionOffset != 0)) {
+ if (GetFspsUpdDataAddress () == 0 && (FspsHeaderPtr->CfgRegionSize != 0) && (FspsHeaderPtr->CfgRegionOffset != 0)) {
//
// Copy default FSP-S UPD data from Flash
//
@@ -292,7 +303,7 @@ PeiMemoryDiscoveredNotify (
SourceData = (UINTN *)((UINTN)FspsHeaderPtr->ImageBase + (UINTN)FspsHeaderPtr->CfgRegionOffset);
CopyMem (FspsUpdDataPtr, SourceData, (UINTN)FspsHeaderPtr->CfgRegionSize);
} else {
- FspsUpdDataPtr = (FSPS_UPD_COMMON *)PcdGet32 (PcdFspsUpdDataAddress);
+ FspsUpdDataPtr = (FSPS_UPD_COMMON *) GetFspsUpdDataAddress ();
ASSERT (FspsUpdDataPtr != NULL);
}

diff --git a/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf b/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
index aeeca58d6d..e988ebab21 100644
--- a/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
+++ b/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
@@ -45,6 +45,7 @@
FspWrapperApiLib
FspWrapperApiTestLib
FspMeasurementLib
+ PcdLib

[Packages]
MdePkg/MdePkg.dec
@@ -65,10 +66,15 @@

[Pcd]
gIntelFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddress ## CONSUMES
- gIntelFsp2WrapperTokenSpaceGuid.PcdFspsUpdDataAddress ## CONSUMES
gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection ## CONSUMES
gIntelFsp2WrapperTokenSpaceGuid.PcdFspMeasurementConfig ## CONSUMES

+[Pcd.IA32]
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspsUpdDataAddress ## CONSUMES
+
+[Pcd.X64]
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspsUpdDataAddress64 ## CONSUMES
+
[Guids]
gFspHobGuid ## CONSUMES ## HOB
gFspApiPerformanceGuid ## SOMETIMES_CONSUMES ## GUID
@@ -76,5 +82,11 @@
[Sources]
FspsWrapperPeim.c

+[Sources.IA32]
+ IA32/FspsHelper.c
+
+[Sources.X64]
+ X64/FspsHelper.c
+
[Depex]
gEfiPeiMemoryDiscoveredPpiGuid
diff --git a/IntelFsp2WrapperPkg/FspsWrapperPeim/IA32/FspsHelper.c b/IntelFsp2WrapperPkg/FspsWrapperPeim/IA32/FspsHelper.c
new file mode 100644
index 0000000000..c4ae292ffb
--- /dev/null
+++ b/IntelFsp2WrapperPkg/FspsWrapperPeim/IA32/FspsHelper.c
@@ -0,0 +1,26 @@
+/** @file
+ Sample to provide FSP wrapper related function.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include <Library/PcdLib.h>
+#include <Library/FspWrapperPlatformLib.h>
+#include <Uefi/UefiBaseType.h>
+
+/**
+ Get the Fsps Upd Data Address from the PCD
+
+ @return FSPS UPD Data Address
+**/
+UINTN
+EFIAPI
+GetFspsUpdDataAddress (
+ VOID
+ )
+{
+ return PcdGet32 (PcdFspsUpdDataAddress);
+}
diff --git a/IntelFsp2WrapperPkg/FspsWrapperPeim/X64/FspsHelper.c b/IntelFsp2WrapperPkg/FspsWrapperPeim/X64/FspsHelper.c
new file mode 100644
index 0000000000..a0d6adb281
--- /dev/null
+++ b/IntelFsp2WrapperPkg/FspsWrapperPeim/X64/FspsHelper.c
@@ -0,0 +1,26 @@
+/** @file
+ Sample to provide FSP wrapper related function.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include <Library/PcdLib.h>
+#include <Library/FspWrapperPlatformLib.h>
+#include <Uefi/UefiBaseType.h>
+
+/**
+ Get the Fsps Upd Data Address from the PCD
+
+ @return FSPS UPD Data Address
+**/
+UINTN
+EFIAPI
+GetFspsUpdDataAddress (
+ VOID
+ )
+{
+ return PcdGet64 (PcdFspsUpdDataAddress64);
+}
diff --git a/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec b/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
index a3b9363779..8c98dbd55d 100644
--- a/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
+++ b/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
@@ -121,3 +121,5 @@
#
gIntelFsp2WrapperTokenSpaceGuid.PcdFspmUpdDataAddress|0x00000000|UINT32|0x50000000
gIntelFsp2WrapperTokenSpaceGuid.PcdFspsUpdDataAddress|0x00000000|UINT32|0x50000001
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspmUpdDataAddress64|0x00000000|UINT64|0x50000002
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspsUpdDataAddress64|0x00000000|UINT64|0x50000003
--
2.30.2.windows.1


[PATCH v4 3/3] ArmVirtPkg: Disable the TPM2 platform hierarchy

Stefan Berger
 

From: Stefan Berger <stefanb@linux.vnet.ibm.com>

Disable the TPM2 platform hierarchy by directly calling
ConfigureTpmPlatformHierarchy().

Per the TCG firmware specification "TCG PC Client Platform Firmware Profile
Specification" the TPM 2 platform hierarchy needs to be disabled or a
random password set and discarded before the firmware passes control to the
next stage bootloader or kernel.

Current specs are here:
https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05=
_v23_pub.pdf

Section 11 states:
"Platform Firmware MUST protect access to the Platform Hierarchy
and prevent access to the platform hierarchy by non-manufacturer-
controlled components."

Link: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3510
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
---
ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c | 6 ++++++
.../PlatformBootManagerLib/PlatformBootManagerLib.inf | 1 +
2 files changed, 7 insertions(+)

diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c b/ArmVi=
rtPkg/Library/PlatformBootManagerLib/PlatformBm.c
index 69448ff65b..1848042f86 100644
--- a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c
+++ b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c
@@ -16,6 +16,7 @@
#include <Library/PcdLib.h>=0D
#include <Library/PlatformBmPrintScLib.h>=0D
#include <Library/QemuBootOrderLib.h>=0D
+#include <Library/TpmPlatformHierarchyLib.h>=0D
#include <Library/UefiBootManagerLib.h>=0D
#include <Protocol/DevicePath.h>=0D
#include <Protocol/FirmwareVolume2.h>=0D
@@ -696,6 +697,11 @@ PlatformBootManagerBeforeConsole (
//=0D
EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);=0D
=0D
+ //=0D
+ // Disable the TPM 2 platform hierarchy=0D
+ //=0D
+ ConfigureTpmPlatformHierarchy ();=0D
+=0D
//=0D
// Dispatch deferred images after EndOfDxe event.=0D
//=0D
diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerL=
ib.inf b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.i=
nf
index 9f54224d3e..997eb1a442 100644
--- a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+++ b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
@@ -48,6 +48,7 @@
QemuBootOrderLib=0D
QemuLoadImageLib=0D
ReportStatusCodeLib=0D
+ TpmPlatformHierarchyLib=0D
UefiBootManagerLib=0D
UefiBootServicesTableLib=0D
UefiLib=0D
--=20
2.31.1


[PATCH v4 1/3] ArmVirtPkg/TPM: Add a NULL implementation of TpmPlatformHierarchyLib

Stefan Berger
 

From: Stefan Berger <stefanb@linux.vnet.ibm.com>

Add a NULL implementation of the library class TpmPlatformHierarchyLib.

Link: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3510
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
---
.../PeiDxeTpmPlatformHierarchyLib.c | 22 +++++++++++++
.../PeiDxeTpmPlatformHierarchyLib.inf | 31 +++++++++++++++++++
SecurityPkg/SecurityPkg.dsc | 1 +
3 files changed, 54 insertions(+)
create mode 100644 SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/P=
eiDxeTpmPlatformHierarchyLib.c
create mode 100644 SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/P=
eiDxeTpmPlatformHierarchyLib.inf

diff --git a/SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTp=
mPlatformHierarchyLib.c b/SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLib=
Null/PeiDxeTpmPlatformHierarchyLib.c
new file mode 100644
index 0000000000..dfc8863830
--- /dev/null
+++ b/SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTpmPlatfo=
rmHierarchyLib.c
@@ -0,0 +1,22 @@
+/** @file=0D
+ Null TPM Platform Hierarchy configuration library.=0D
+=0D
+ This library provides stub functions for customizing the TPM's Platfor=
m Hierarchy.=0D
+=0D
+ Copyright (c) 2021, IBM Corporation.=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <Uefi.h>=0D
+=0D
+/**=0D
+ A NULL implementation of ConfigureTpmPlatformHierarchy.=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+ConfigureTpmPlatformHierarchy (=0D
+ )=0D
+{=0D
+ /* do nothing */=0D
+}=0D
diff --git a/SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTp=
mPlatformHierarchyLib.inf b/SecurityPkg/Library/PeiDxeTpmPlatformHierarchyL=
ibNull/PeiDxeTpmPlatformHierarchyLib.inf
new file mode 100644
index 0000000000..1b1e9ad592
--- /dev/null
+++ b/SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTpmPlatfo=
rmHierarchyLib.inf
@@ -0,0 +1,31 @@
+### @file=0D
+# NULL TPM Platform Hierarchy configuration library.=0D
+#=0D
+# This library provides functions for customizing the TPM's Platform Hie=
rarchy=0D
+# Authorization Value (platformAuth) and Platform Hierarchy Authorizatio=
n=0D
+# Policy (platformPolicy) can be defined through this function.=0D
+#=0D
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>=0D
+# Copyright (c) Microsoft Corporation.<BR>=0D
+#=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+#=0D
+###=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 1.27=0D
+ BASE_NAME =3D BasePlatform=0D
+ FILE_GUID =3D 8947A3F2-BfB4-45EF-968D-5C40C1CE6A58=
=0D
+ MODULE_TYPE =3D BASE=0D
+ VERSION_STRING =3D 1.0=0D
+ LIBRARY_CLASS =3D TpmPlatformHierarchyLib|PEIM DXE_DRIV=
ER=0D
+=0D
+[LibraryClasses]=0D
+ BaseLib=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ SecurityPkg/SecurityPkg.dec=0D
+=0D
+[Sources]=0D
+ PeiDxeTpmPlatformHierarchyLib.c=0D
diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index f1f678c492..37318c64c5 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -232,6 +232,7 @@
SecurityPkg/Library/HashLibTpm2/HashLibTpm2.inf=0D
=0D
SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLib/PeiDxeTpmPlatformHiera=
rchyLib.inf=0D
+ SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTpmPlatformH=
ierarchyLib.inf=0D
=0D
#=0D
# TCG Storage.=0D
--=20
2.31.1


[PATCH v4 0/3] ArmVirtPkg: Disable the TPM 2 platform hierarchy

Stefan Berger
 

This series of patches disables the TPM 2 platform hierarchy.
We just added the same functionality to the OvmfPkg. However, on x86, we
could use the notification mechanism around gEfiDxeSmmReadyToLockProtocolGuid
to indirectly invoke ConfigureTpmPlatformHierarchy(). Since ARM does not
have an SMM mode this series now use direct invocation of this function
at the same place in PlatformBootManagerBeforeConsole() as it is done
on x86.

Regards,
Stefan

v4:
- Added Sami's R-b tag to 1/3

v3:
- Addressed Ard's comments on 1/3

v2:
- Move Null implementation to SecurityPkg
- Added suggested texts to commit messages and added Sami's R-b tags

Stefan Berger (3):
ArmVirtPkg/TPM: Add a NULL implementation of TpmPlatformHierarchyLib
ArmVirtPkg: Reference new TPM classes in the build system for
compilation
ArmVirtPkg: Disable the TPM2 platform hierarchy

ArmVirtPkg/ArmVirtCloudHv.dsc | 1 +
ArmVirtPkg/ArmVirtQemu.dsc | 2 ++
ArmVirtPkg/ArmVirtQemuKernel.dsc | 1 +
ArmVirtPkg/ArmVirtXen.dsc | 1 +
.../PlatformBootManagerLib/PlatformBm.c | 6 ++++
.../PlatformBootManagerLib.inf | 2 ++
.../PeiDxeTpmPlatformHierarchyLib.c | 22 +++++++++++++
.../PeiDxeTpmPlatformHierarchyLib.inf | 31 +++++++++++++++++++
SecurityPkg/SecurityPkg.dsc | 1 +
9 files changed, 67 insertions(+)
create mode 100644 SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTpmPlatformHierarchyLib.c
create mode 100644 SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTpmPlatformHierarchyLib.inf

--
2.31.1


[PATCH v4 2/3] ArmVirtPkg: Reference new TPM classes in the build system for compilation

Stefan Berger
 

From: Stefan Berger <stefanb@linux.vnet.ibm.com>

We just added the same functionality to the OvmfPkg. However, on x86, we
could use the notification mechanism around
gEfiDxeSmmReadyToLockProtocolGuid to indirectly invoke
ConfigureTpmPlatformHierarchy(). Since ARM does not have an SMM mode, we
have to use direct invocation of this function at the same place in
PlatformBootManagerBeforeConsole() as it is called on x86.

Link: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3510
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
---
ArmVirtPkg/ArmVirtCloudHv.dsc | 1 +
ArmVirtPkg/ArmVirtQemu.dsc | 2 ++
ArmVirtPkg/ArmVirtQemuKernel.dsc | 1 +
ArmVirtPkg/ArmVirtXen.dsc | 1 +
.../Library/PlatformBootManagerLib/PlatformBootManagerLib.inf | 1 +
5 files changed, 6 insertions(+)

diff --git a/ArmVirtPkg/ArmVirtCloudHv.dsc b/ArmVirtPkg/ArmVirtCloudHv.dsc
index f292ba6079..3475bb7f0d 100644
--- a/ArmVirtPkg/ArmVirtCloudHv.dsc
+++ b/ArmVirtPkg/ArmVirtCloudHv.dsc
@@ -55,6 +55,7 @@
PciHostBridgeUtilityLib|ArmVirtPkg/Library/ArmVirtPciHostBridgeUtilityLi=
b/ArmVirtPciHostBridgeUtilityLib.inf=0D
=0D
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurem=
entLibNull.inf=0D
+ TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLi=
bNull/PeiDxeTpmPlatformHierarchyLib.inf=0D
=0D
!include MdePkg/MdeLibs.dsc.inc=0D
=0D
diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc
index 97539edef7..35aea68e02 100644
--- a/ArmVirtPkg/ArmVirtQemu.dsc
+++ b/ArmVirtPkg/ArmVirtQemu.dsc
@@ -86,8 +86,10 @@
Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf=0D
Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeT=
cg2PhysicalPresenceLib.inf=0D
TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasure=
mentLib.inf=0D
+ TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLi=
b/PeiDxeTpmPlatformHierarchyLib.inf=0D
!else=0D
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurem=
entLibNull.inf=0D
+ TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLi=
bNull/PeiDxeTpmPlatformHierarchyLib.inf=0D
!endif=0D
=0D
[LibraryClasses.common.PEIM]=0D
diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKerne=
l.dsc
index 28064199c8..19c1908cd9 100644
--- a/ArmVirtPkg/ArmVirtQemuKernel.dsc
+++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc
@@ -80,6 +80,7 @@
PciHostBridgeLib|ArmVirtPkg/Library/FdtPciHostBridgeLib/FdtPciHostBridge=
Lib.inf=0D
PciHostBridgeUtilityLib|OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostB=
ridgeUtilityLib.inf=0D
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurem=
entLibNull.inf=0D
+ TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLi=
bNull/PeiDxeTpmPlatformHierarchyLib.inf=0D
=0D
[LibraryClasses.common.DXE_DRIVER]=0D
ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeRepor=
tStatusCodeLib.inf=0D
diff --git a/ArmVirtPkg/ArmVirtXen.dsc b/ArmVirtPkg/ArmVirtXen.dsc
index 2b07a5ba19..dbc40e854b 100644
--- a/ArmVirtPkg/ArmVirtXen.dsc
+++ b/ArmVirtPkg/ArmVirtXen.dsc
@@ -50,6 +50,7 @@
PlatformBootManagerLib|ArmPkg/Library/PlatformBootManagerLib/PlatformBoo=
tManagerLib.inf=0D
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/Customize=
dDisplayLib.inf=0D
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurem=
entLibNull.inf=0D
+ TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLi=
bNull/PeiDxeTpmPlatformHierarchyLib.inf=0D
=0D
[LibraryClasses.common.UEFI_DRIVER]=0D
UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf=0D
diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerL=
ib.inf b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.i=
nf
index 11f52e019b..9f54224d3e 100644
--- a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+++ b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
@@ -33,6 +33,7 @@
MdeModulePkg/MdeModulePkg.dec=0D
MdePkg/MdePkg.dec=0D
OvmfPkg/OvmfPkg.dec=0D
+ SecurityPkg/SecurityPkg.dec=0D
ShellPkg/ShellPkg.dec=0D
=0D
[LibraryClasses]=0D
--=20
2.31.1

5081 - 5100 of 86113