Date   

Re: [PATCH v3 0/7] New MM Communicate header and interfaces

Kun Qin
 

Hi EDK2 maintainers,

It has been a while since this v3 patch series were sent. May I please have some feedback on the proposed PI spec change? Any input is appreciated.

Regards,
Kun


Re: RFC: Add BaseLib/QuickSort in MdePkg

Andrew Fish
 



On Sep 15, 2021, at 6:26 PM, gaoliming <gaoliming@...> wrote:

Ray:
 SortLib has been added since 2015. I would suggest to still keep this library class. To resolve the package dependency, my proposal is to move the library class header file SortLib.h from MdeModulePkg to MdePkg, and still keep the library instance in MdeModulePkg. This proposal has no impact on the existing platform. 
 

If we add QuickSort() API to the BaseLib can we not just port the existing MdeModulePkg/SortLib to use QuickSort() in the implementation? Or is there some other way to add the new thing in a backward compatible way.

Thanks,

Andrew Fish

Thanks
Liming
发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Ni, Ray
发送时间: 2021914 14:15
收件人: Kinney, Michael D <michael.d.kinney@...>; Gao, Liming <liming.gao@...>; Liu, Zhiguang <zhiguang.liu@...>; Wang, Jian J <jian.j.wang@...>; Gao, Zhichao <zhichao.gao@...>
抄送: devel@edk2.groups.io; Chan, Amy <amy.chan@...>
主题: [edk2-devel] RFC: Add BaseLib/QuickSort in MdePkg
 
Hi package maintainers of MdePkg, MdeModulePkg and ShellPkg, community,
 
A commit (UefiCpuPkg/CpuCacheInfoLib: Sort CpuCacheInfo array) to UefiCpuPkg let
UefiCpuPkg depend on MdeModulePkg because the SortLib class and instances are all in MdeModulePkg.
 
UefiCpuPkg depending on MdeModulePkg breaks the rule that “UefiCpuPkg should ONLY depend on MdePkg”.
 
To address this issue, there are two approaches:
  1. Duplicate the sort logic in UefiCpuPkg to not depend on MdeModulePkg/SortLib
  2. Add QuickSort() API to BaseLib in MdePkg.
 
Approach #2 (MdePkg/BaseLib/QuickSort) makes more sense because quick sort is a standard algorithm.
We encourage consumers to update their code to use the quick sort in MdePkg and gradually deprecate today’s MdeModulePkg/SortLib.
 
If you don’t have concerns, I plan to:
  1. “Add QuickSort() to BaseLib” and update all existing consumers to use this API instead.
VOID
EFIAPI
QuickSort (
  IN OUT VOID                   *BufferToSort,
  IN CONST UINTN                Count,
  IN CONST UINTN                ElementSize,
  IN       SORT_COMPARE         CompareFunction
  );
 
  1. “Add new ShellPkg/SortCompareLib”
Background: ShellPkg requires to sort devicepath/string so 3 APIs in UefiSortLib (DevicePathCompare, StringNoCaseCompare, StringCompare) are provided for Shell usage. we can move the 3 APIs to the SortCompareLib and update Shell code to use BaseLib/QuickSort directly, with the sort compare function from SortCompareLib.
 
Any concerns?
 
Thanks,
Ray



[PATCH v1 1/2] UefiCpuPkg: Refactor initialization of CPU features during S3 resume

Jason Lou
 

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

Refactor initialization of CPU features during S3 resume.

In addition, the macro ACPI_CPU_DATA_STRUCTURE_UPDATE is used to fix
incompatibility issue caused by ACPI_CPU_DATA structure update. It will
be removed after all the platform code uses new ACPI_CPU_DATA structure.

Signed-off-by: Jason Lou <yun.lou@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
---
OvmfPkg/CpuS3DataDxe/CpuS3Data.c | 7 +-
UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c | 7 +-
UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c | 12 +-
UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c | 18 +=
--
UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c | 163 +=
+++++++++++--------
UefiCpuPkg/Include/AcpiCpuData.h | 91 +=
+++++-----
6 files changed, 170 insertions(+), 128 deletions(-)

diff --git a/OvmfPkg/CpuS3DataDxe/CpuS3Data.c b/OvmfPkg/CpuS3DataDxe/CpuS3D=
ata.c
index 5ffe1f3cd7..de20d87567 100644
--- a/OvmfPkg/CpuS3DataDxe/CpuS3Data.c
+++ b/OvmfPkg/CpuS3DataDxe/CpuS3Data.c
@@ -9,7 +9,7 @@ number of CPUs reported by the MP Services Protocol, so thi=
s module does not
support hot plug CPUs. This module can be copied into a CPU specific pack=
age=0D
and customized if these additional features are required.=0D
=0D
-Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved.<BR>=0D
+Copyright (c) 2013 - 2021, Intel Corporation. All rights reserved.<BR>=0D
Copyright (c) 2015 - 2020, Red Hat, Inc.=0D
=0D
SPDX-License-Identifier: BSD-2-Clause-Patent=0D
@@ -252,10 +252,7 @@ CpuS3DataInitialize (
AcpiCpuDataEx->IdtrProfile.Base =3D (UINTN)Idt;=0D
=0D
if (OldAcpiCpuData !=3D NULL) {=0D
- AcpiCpuData->RegisterTable =3D OldAcpiCpuData->RegisterTable=
;=0D
- AcpiCpuData->PreSmmInitRegisterTable =3D OldAcpiCpuData->PreSmmInitReg=
isterTable;=0D
- AcpiCpuData->ApLocation =3D OldAcpiCpuData->ApLocation;=0D
- CopyMem (&AcpiCpuData->CpuStatus, &OldAcpiCpuData->CpuStatus, sizeof (=
CPU_STATUS_INFORMATION));=0D
+ CopyMem (&AcpiCpuData->CpuFeatureInitData, &OldAcpiCpuData->CpuFeature=
InitData, sizeof (CPU_FEATURE_INIT_DATA));=0D
}=0D
=0D
//=0D
diff --git a/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c b/UefiCpuPkg/CpuS3DataDxe/=
CpuS3Data.c
index 078af36cfb..61ec7c44b2 100644
--- a/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c
+++ b/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c
@@ -9,7 +9,7 @@ number of CPUs reported by the MP Services Protocol, so thi=
s module does not
support hot plug CPUs. This module can be copied into a CPU specific pack=
age=0D
and customized if these additional features are required.=0D
=0D
-Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved.<BR>=0D
+Copyright (c) 2013 - 2021, Intel Corporation. All rights reserved.<BR>=0D
Copyright (c) 2015, Red Hat, Inc.=0D
=0D
SPDX-License-Identifier: BSD-2-Clause-Patent=0D
@@ -247,10 +247,7 @@ CpuS3DataInitialize (
AcpiCpuDataEx->IdtrProfile.Base =3D (UINTN)Idt;=0D
=0D
if (OldAcpiCpuData !=3D NULL) {=0D
- AcpiCpuData->RegisterTable =3D OldAcpiCpuData->RegisterTable=
;=0D
- AcpiCpuData->PreSmmInitRegisterTable =3D OldAcpiCpuData->PreSmmInitReg=
isterTable;=0D
- AcpiCpuData->ApLocation =3D OldAcpiCpuData->ApLocation;=0D
- CopyMem (&AcpiCpuData->CpuStatus, &OldAcpiCpuData->CpuStatus, sizeof (=
CPU_STATUS_INFORMATION));=0D
+ CopyMem (&AcpiCpuData->CpuFeatureInitData, &OldAcpiCpuData->CpuFeature=
InitData, sizeof (CPU_FEATURE_INIT_DATA));=0D
}=0D
=0D
//=0D
diff --git a/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitializ=
e.c b/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
index 57511c4efa..6e2ab79518 100644
--- a/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
+++ b/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
@@ -1,7 +1,7 @@
/** @file=0D
CPU Features Initialize functions.=0D
=0D
- Copyright (c) 2017 - 2020, Intel Corporation. All rights reserved.<BR>=0D
+ Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>=0D
SPDX-License-Identifier: BSD-2-Clause-Patent=0D
=0D
**/=0D
@@ -152,10 +152,10 @@ CpuInitDataInitialize (
ASSERT (AcpiCpuData !=3D NULL);=0D
CpuFeaturesData->AcpiCpuData=3D AcpiCpuData;=0D
=0D
- CpuStatus =3D &AcpiCpuData->CpuStatus;=0D
+ CpuStatus =3D &AcpiCpuData->CpuFeatureInitData.CpuStatus;=0D
Location =3D AllocateZeroPool (sizeof (EFI_CPU_PHYSICAL_LOCATION) * Numb=
erOfCpus);=0D
ASSERT (Location !=3D NULL);=0D
- AcpiCpuData->ApLocation =3D (EFI_PHYSICAL_ADDRESS)(UINTN)Location;=0D
+ AcpiCpuData->CpuFeatureInitData.ApLocation =3D (EFI_PHYSICAL_ADDRESS)(UI=
NTN)Location;=0D
=0D
for (ProcessorNumber =3D 0; ProcessorNumber < NumberOfCpus; ProcessorNum=
ber++) {=0D
InitOrder =3D &CpuFeaturesData->InitOrder[ProcessorNumber];=0D
@@ -1131,7 +1131,7 @@ SetProcessorRegister (
CpuFeaturesData =3D (CPU_FEATURES_DATA *) Buffer;=0D
AcpiCpuData =3D CpuFeaturesData->AcpiCpuData;=0D
=0D
- RegisterTables =3D (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->RegisterTab=
le;=0D
+ RegisterTables =3D (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->CpuFeatureI=
nitData.RegisterTable;=0D
=0D
InitApicId =3D GetInitialApicId ();=0D
RegisterTable =3D NULL;=0D
@@ -1147,8 +1147,8 @@ SetProcessorRegister (
=0D
ProgramProcessorRegister (=0D
RegisterTable,=0D
- (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)AcpiCpuData->ApLocation + ProcInde=
x,=0D
- &AcpiCpuData->CpuStatus,=0D
+ (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)AcpiCpuData->CpuFeatureInitData.Ap=
Location + ProcIndex,=0D
+ &AcpiCpuData->CpuFeatureInitData.CpuStatus,=0D
&CpuFeaturesData->CpuFlags=0D
);=0D
}=0D
diff --git a/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesL=
ib.c b/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c
index 60daa5cc87..e6ef9c602d 100644
--- a/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c
+++ b/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c
@@ -952,8 +952,8 @@ GetAcpiCpuData (
AcpiCpuData->NumberOfCpus =3D (UINT32)NumberOfCpus;=0D
}=0D
=0D
- if (AcpiCpuData->RegisterTable =3D=3D 0 ||=0D
- AcpiCpuData->PreSmmInitRegisterTable =3D=3D 0) {=0D
+ if (AcpiCpuData->CpuFeatureInitData.RegisterTable =3D=3D 0 ||=0D
+ AcpiCpuData->CpuFeatureInitData.PreSmmInitRegisterTable =3D=3D 0) {=
=0D
//=0D
// Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable=
for all CPUs=0D
//=0D
@@ -976,11 +976,11 @@ GetAcpiCpuData (
RegisterTable[NumberOfCpus + Index].AllocatedSize =3D 0;=0D
RegisterTable[NumberOfCpus + Index].RegisterTableEntry =3D 0;=0D
}=0D
- if (AcpiCpuData->RegisterTable =3D=3D 0) {=0D
- AcpiCpuData->RegisterTable =3D (EFI_PHYSICAL_ADDRESS)(UINTN)Register=
Table;=0D
+ if (AcpiCpuData->CpuFeatureInitData.RegisterTable =3D=3D 0) {=0D
+ AcpiCpuData->CpuFeatureInitData.RegisterTable =3D (EFI_PHYSICAL_ADDR=
ESS)(UINTN)RegisterTable;=0D
}=0D
- if (AcpiCpuData->PreSmmInitRegisterTable =3D=3D 0) {=0D
- AcpiCpuData->PreSmmInitRegisterTable =3D (EFI_PHYSICAL_ADDRESS)(UINT=
N)(RegisterTable + NumberOfCpus);=0D
+ if (AcpiCpuData->CpuFeatureInitData.PreSmmInitRegisterTable =3D=3D 0) =
{=0D
+ AcpiCpuData->CpuFeatureInitData.PreSmmInitRegisterTable =3D (EFI_PHY=
SICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);=0D
}=0D
}=0D
=0D
@@ -1063,9 +1063,9 @@ CpuRegisterTableWriteWorker (
CpuFeaturesData =3D GetCpuFeaturesData ();=0D
if (CpuFeaturesData->RegisterTable =3D=3D NULL) {=0D
AcpiCpuData =3D GetAcpiCpuData ();=0D
- ASSERT ((AcpiCpuData !=3D NULL) && (AcpiCpuData->RegisterTable !=3D 0)=
);=0D
- CpuFeaturesData->RegisterTable =3D (CPU_REGISTER_TABLE *) (UINTN) Acpi=
CpuData->RegisterTable;=0D
- CpuFeaturesData->PreSmmRegisterTable =3D (CPU_REGISTER_TABLE *) (UINTN=
) AcpiCpuData->PreSmmInitRegisterTable;=0D
+ ASSERT ((AcpiCpuData !=3D NULL) && (AcpiCpuData->CpuFeatureInitData.Re=
gisterTable !=3D 0));=0D
+ CpuFeaturesData->RegisterTable =3D (CPU_REGISTER_TABLE *) (UINTN) Acpi=
CpuData->CpuFeatureInitData.RegisterTable;=0D
+ CpuFeaturesData->PreSmmRegisterTable =3D (CPU_REGISTER_TABLE *) (UINTN=
) AcpiCpuData->CpuFeatureInitData.PreSmmInitRegisterTable;=0D
}=0D
=0D
if (PreSmmFlag) {=0D
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c b/UefiCpuPkg/PiSmmCpuDxeSmm/=
CpuS3.c
index ab7f39aa2b..1270992f38 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
@@ -476,16 +476,22 @@ SetRegister (
IN BOOLEAN PreSmmRegisterTable=0D
)=0D
{=0D
+ CPU_FEATURE_INIT_DATA *FeatureInitData;=0D
CPU_REGISTER_TABLE *RegisterTable;=0D
CPU_REGISTER_TABLE *RegisterTables;=0D
UINT32 InitApicId;=0D
UINTN ProcIndex;=0D
UINTN Index;=0D
=0D
+ FeatureInitData =3D &mAcpiCpuData.CpuFeatureInitData;=0D
+ if (FeatureInitData =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
if (PreSmmRegisterTable) {=0D
- RegisterTables =3D (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.PreSmmIni=
tRegisterTable;=0D
+ RegisterTables =3D (CPU_REGISTER_TABLE *)(UINTN)FeatureInitData->PreSm=
mInitRegisterTable;=0D
} else {=0D
- RegisterTables =3D (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.RegisterT=
able;=0D
+ RegisterTables =3D (CPU_REGISTER_TABLE *)(UINTN)FeatureInitData->Regis=
terTable;=0D
}=0D
if (RegisterTables =3D=3D NULL) {=0D
return;=0D
@@ -503,18 +509,18 @@ SetRegister (
}=0D
ASSERT (RegisterTable !=3D NULL);=0D
=0D
- if (mAcpiCpuData.ApLocation !=3D 0) {=0D
+ if (FeatureInitData->ApLocation !=3D 0) {=0D
ProgramProcessorRegister (=0D
RegisterTable,=0D
- (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)mAcpiCpuData.ApLocation + ProcIn=
dex,=0D
- &mAcpiCpuData.CpuStatus,=0D
+ (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)FeatureInitData->ApLocation + Pr=
ocIndex,=0D
+ &FeatureInitData->CpuStatus,=0D
&mCpuFlags=0D
);=0D
} else {=0D
ProgramProcessorRegister (=0D
RegisterTable,=0D
NULL,=0D
- &mAcpiCpuData.CpuStatus,=0D
+ &FeatureInitData->CpuStatus,=0D
&mCpuFlags=0D
);=0D
}=0D
@@ -1010,6 +1016,71 @@ IsRegisterTableEmpty (
return TRUE;=0D
}=0D
=0D
+/**=0D
+ Copy the data used to initialize processor register into SMRAM.=0D
+=0D
+ @param[in,out] CpuFeatureInitDataDst Pointer to the destination CPU_F=
EATURE_INIT_DATA structure.=0D
+ @param[in] CpuFeatureInitDataSrc Pointer to the source CPU_FEATUR=
E_INIT_DATA structure.=0D
+=0D
+**/=0D
+VOID=0D
+CopyCpuFeatureInitDatatoSmram (=0D
+ IN OUT CPU_FEATURE_INIT_DATA *CpuFeatureInitDataDst,=0D
+ IN CPU_FEATURE_INIT_DATA *CpuFeatureInitDataSrc=0D
+ )=0D
+{=0D
+ CPU_STATUS_INFORMATION *CpuStatus;=0D
+=0D
+ if (!IsRegisterTableEmpty ((CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDa=
taSrc->PreSmmInitRegisterTable, mAcpiCpuData.NumberOfCpus)) {=0D
+ CpuFeatureInitDataDst->PreSmmInitRegisterTable =3D (EFI_PHYSICAL_ADDRE=
SS)(UINTN)AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TA=
BLE));=0D
+ ASSERT (CpuFeatureInitDataDst->PreSmmInitRegisterTable !=3D 0);=0D
+=0D
+ CopyRegisterTable (=0D
+ (CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataDst->PreSmmInitRegist=
erTable,=0D
+ (CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataSrc->PreSmmInitRegist=
erTable,=0D
+ mAcpiCpuData.NumberOfCpus=0D
+ );=0D
+ }=0D
+=0D
+ if (!IsRegisterTableEmpty ((CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDa=
taSrc->RegisterTable, mAcpiCpuData.NumberOfCpus)) {=0D
+ CpuFeatureInitDataDst->RegisterTable =3D (EFI_PHYSICAL_ADDRESS)(UINTN)=
AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));=0D
+ ASSERT (CpuFeatureInitDataDst->RegisterTable !=3D 0);=0D
+=0D
+ CopyRegisterTable (=0D
+ (CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataDst->RegisterTable,=0D
+ (CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataSrc->RegisterTable,=0D
+ mAcpiCpuData.NumberOfCpus=0D
+ );=0D
+ }=0D
+=0D
+ CpuStatus =3D &CpuFeatureInitDataDst->CpuStatus;=0D
+ CopyMem (CpuStatus, &CpuFeatureInitDataSrc->CpuStatus, sizeof (CPU_STATU=
S_INFORMATION));=0D
+=0D
+ if (CpuFeatureInitDataSrc->CpuStatus.ThreadCountPerPackage !=3D 0) {=0D
+ CpuStatus->ThreadCountPerPackage =3D (EFI_PHYSICAL_ADDRESS)(UINTN)Allo=
cateCopyPool (=0D
+ sizeof (UINT32) * CpuStatus->P=
ackageCount,=0D
+ (UINT32 *)(UINTN)CpuFeatureIni=
tDataSrc->CpuStatus.ThreadCountPerPackage=0D
+ );=0D
+ ASSERT (CpuStatus->ThreadCountPerPackage !=3D 0);=0D
+ }=0D
+=0D
+ if (CpuFeatureInitDataSrc->CpuStatus.ThreadCountPerCore !=3D 0) {=0D
+ CpuStatus->ThreadCountPerCore =3D (EFI_PHYSICAL_ADDRESS)(UINTN)Allocat=
eCopyPool (=0D
+ sizeof (UINT8) * (CpuStatus->P=
ackageCount * CpuStatus->MaxCoreCount),=0D
+ (UINT32 *)(UINTN)CpuFeatureIni=
tDataSrc->CpuStatus.ThreadCountPerCore=0D
+ );=0D
+ ASSERT (CpuStatus->ThreadCountPerCore !=3D 0);=0D
+ }=0D
+=0D
+ if (CpuFeatureInitDataSrc->ApLocation !=3D 0) {=0D
+ CpuFeatureInitDataDst->ApLocation =3D (EFI_PHYSICAL_ADDRESS)(UINTN)All=
ocateCopyPool (=0D
+ mAcpiCpuData.NumberOfCpus * sizeof (EFI_CP=
U_PHYSICAL_LOCATION),=0D
+ (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)CpuFea=
tureInitDataSrc->ApLocation=0D
+ );=0D
+ ASSERT (CpuFeatureInitDataDst->ApLocation !=3D 0);=0D
+ }=0D
+}=0D
+=0D
/**=0D
Get ACPI CPU data.=0D
=0D
@@ -1064,39 +1135,13 @@ GetAcpiCpuData (
=0D
CopyMem ((VOID *)(UINTN)mAcpiCpuData.IdtrProfile, (VOID *)(UINTN)AcpiCpu=
Data->IdtrProfile, sizeof (IA32_DESCRIPTOR));=0D
=0D
- if (!IsRegisterTableEmpty ((CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->Pre=
SmmInitRegisterTable, mAcpiCpuData.NumberOfCpus)) {=0D
- mAcpiCpuData.PreSmmInitRegisterTable =3D (EFI_PHYSICAL_ADDRESS)(UINTN)=
AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));=0D
- ASSERT (mAcpiCpuData.PreSmmInitRegisterTable !=3D 0);=0D
-=0D
- CopyRegisterTable (=0D
- (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.PreSmmInitRegisterTable,=0D
- (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->PreSmmInitRegisterTable,=0D
- mAcpiCpuData.NumberOfCpus=0D
- );=0D
- } else {=0D
- mAcpiCpuData.PreSmmInitRegisterTable =3D 0;=0D
- }=0D
-=0D
- if (!IsRegisterTableEmpty ((CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->Reg=
isterTable, mAcpiCpuData.NumberOfCpus)) {=0D
- mAcpiCpuData.RegisterTable =3D (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePo=
ol (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));=0D
- ASSERT (mAcpiCpuData.RegisterTable !=3D 0);=0D
-=0D
- CopyRegisterTable (=0D
- (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.RegisterTable,=0D
- (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->RegisterTable,=0D
- mAcpiCpuData.NumberOfCpus=0D
- );=0D
- } else {=0D
- mAcpiCpuData.RegisterTable =3D 0;=0D
- }=0D
-=0D
//=0D
// Copy AP's GDT, IDT and Machine Check handler into SMRAM.=0D
//=0D
Gdtr =3D (IA32_DESCRIPTOR *)(UINTN)mAcpiCpuData.GdtrProfile;=0D
Idtr =3D (IA32_DESCRIPTOR *)(UINTN)mAcpiCpuData.IdtrProfile;=0D
=0D
- GdtForAp =3D AllocatePool ((Gdtr->Limit + 1) + (Idtr->Limit + 1) + mAcp=
iCpuData.ApMachineCheckHandlerSize);=0D
+ GdtForAp =3D AllocatePool ((Gdtr->Limit + 1) + (Idtr->Limit + 1) + mAcpi=
CpuData.ApMachineCheckHandlerSize);=0D
ASSERT (GdtForAp !=3D NULL);=0D
IdtForAp =3D (VOID *) ((UINTN)GdtForAp + (Gdtr->Limit + 1));=0D
MachineCheckHandlerForAp =3D (VOID *) ((UINTN)IdtForAp + (Idtr->Limit + =
1));=0D
@@ -1109,41 +1154,23 @@ GetAcpiCpuData (
Idtr->Base =3D (UINTN)IdtForAp;=0D
mAcpiCpuData.ApMachineCheckHandlerBase =3D (EFI_PHYSICAL_ADDRESS)(UINTN)=
MachineCheckHandlerForAp;=0D
=0D
- CpuStatus =3D &mAcpiCpuData.CpuStatus;=0D
- CopyMem (CpuStatus, &AcpiCpuData->CpuStatus, sizeof (CPU_STATUS_INFORMAT=
ION));=0D
- if (AcpiCpuData->CpuStatus.ThreadCountPerPackage !=3D 0) {=0D
- CpuStatus->ThreadCountPerPackage =3D (EFI_PHYSICAL_ADDRESS)(UINTN)Allo=
cateCopyPool (=0D
- sizeof (UINT32) * CpuStatus->P=
ackageCount,=0D
- (UINT32 *)(UINTN)AcpiCpuData->=
CpuStatus.ThreadCountPerPackage=0D
- );=0D
- ASSERT (CpuStatus->ThreadCountPerPackage !=3D 0);=0D
- }=0D
- if (AcpiCpuData->CpuStatus.ThreadCountPerCore !=3D 0) {=0D
- CpuStatus->ThreadCountPerCore =3D (EFI_PHYSICAL_ADDRESS)(UINTN)Allocat=
eCopyPool (=0D
- sizeof (UINT8) * (CpuStatus->P=
ackageCount * CpuStatus->MaxCoreCount),=0D
- (UINT32 *)(UINTN)AcpiCpuData->=
CpuStatus.ThreadCountPerCore=0D
- );=0D
- ASSERT (CpuStatus->ThreadCountPerCore !=3D 0);=0D
- }=0D
- if (AcpiCpuData->ApLocation !=3D 0) {=0D
- mAcpiCpuData.ApLocation =3D (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyP=
ool (=0D
- mAcpiCpuData.NumberOfCpus * sizeof (EFI_CP=
U_PHYSICAL_LOCATION),=0D
- (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)AcpiCp=
uData->ApLocation=0D
- );=0D
- ASSERT (mAcpiCpuData.ApLocation !=3D 0);=0D
- }=0D
- if (CpuStatus->PackageCount !=3D 0) {=0D
- mCpuFlags.CoreSemaphoreCount =3D AllocateZeroPool (=0D
- sizeof (UINT32) * CpuStatus->PackageC=
ount *=0D
- CpuStatus->MaxCoreCount * CpuStatus->=
MaxThreadCount=0D
- );=0D
- ASSERT (mCpuFlags.CoreSemaphoreCount !=3D NULL);=0D
- mCpuFlags.PackageSemaphoreCount =3D AllocateZeroPool (=0D
- sizeof (UINT32) * CpuStatus->Packa=
geCount *=0D
- CpuStatus->MaxCoreCount * CpuStatu=
s->MaxThreadCount=0D
- );=0D
- ASSERT (mCpuFlags.PackageSemaphoreCount !=3D NULL);=0D
- }=0D
+ ZeroMem (&mAcpiCpuData.CpuFeatureInitData, sizeof (CPU_FEATURE_INIT_DATA=
));=0D
+ CopyCpuFeatureInitDatatoSmram (&mAcpiCpuData.CpuFeatureInitData, &AcpiCp=
uData->CpuFeatureInitData);=0D
+=0D
+ CpuStatus =3D &mAcpiCpuData.CpuFeatureInitData.CpuStatus;=0D
+=0D
+ mCpuFlags.CoreSemaphoreCount =3D AllocateZeroPool (=0D
+ sizeof (UINT32) * CpuStatus->PackageCou=
nt *=0D
+ CpuStatus->MaxCoreCount * CpuStatus->Ma=
xThreadCount=0D
+ );=0D
+ ASSERT (mCpuFlags.CoreSemaphoreCount !=3D NULL);=0D
+=0D
+ mCpuFlags.PackageSemaphoreCount =3D AllocateZeroPool (=0D
+ sizeof (UINT32) * CpuStatus->Package=
Count *=0D
+ CpuStatus->MaxCoreCount * CpuStatus-=
MaxThreadCount=0D
+ );=0D
+ ASSERT (mCpuFlags.PackageSemaphoreCount !=3D NULL);=0D
+=0D
InitializeSpinLock((SPIN_LOCK*) &mCpuFlags.MemoryMappedLock);=0D
}=0D
=0D
diff --git a/UefiCpuPkg/Include/AcpiCpuData.h b/UefiCpuPkg/Include/AcpiCpuD=
ata.h
index 62a01b2c6b..2fa8801d1f 100644
--- a/UefiCpuPkg/Include/AcpiCpuData.h
+++ b/UefiCpuPkg/Include/AcpiCpuData.h
@@ -1,7 +1,7 @@
/** @file=0D
Definitions for CPU S3 data.=0D
=0D
-Copyright (c) 2013 - 2020, Intel Corporation. All rights reserved.<BR>=0D
+Copyright (c) 2013 - 2021, Intel Corporation. All rights reserved.<BR>=0D
SPDX-License-Identifier: BSD-2-Clause-Patent=0D
=0D
**/=0D
@@ -9,6 +9,15 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#ifndef _ACPI_CPU_DATA_H_=0D
#define _ACPI_CPU_DATA_H_=0D
=0D
+//=0D
+// This macro definition is used to fix incompatibility issue caused by=0D
+// ACPI_CPU_DATA structure update. It will be removed after all the platfo=
rm=0D
+// code uses new ACPI_CPU_DATA structure.=0D
+//=0D
+#ifndef ACPI_CPU_DATA_STRUCTURE_UPDATE=0D
+#define ACPI_CPU_DATA_STRUCTURE_UPDATE=0D
+#endif=0D
+=0D
//=0D
// Register types in register table=0D
//=0D
@@ -118,6 +127,49 @@ typedef struct {
EFI_PHYSICAL_ADDRESS RegisterTableEntry;=0D
} CPU_REGISTER_TABLE;=0D
=0D
+//=0D
+// Data structure that is used for CPU feature initialization during ACPI =
S3=0D
+// resume.=0D
+//=0D
+typedef struct {=0D
+ //=0D
+ // Physical address of an array of CPU_REGISTER_TABLE structures, with=0D
+ // NumberOfCpus entries. If a register table is not required, then the=
=0D
+ // TableLength and AllocatedSize fields of CPU_REGISTER_TABLE are set to=
0.=0D
+ // If TableLength is > 0, then elements of RegisterTableEntry are used t=
o=0D
+ // initialize the CPU that matches InitialApicId, during an ACPI S3 resu=
me,=0D
+ // before SMBASE relocation is performed.=0D
+ // If a register table is not required for any one of the CPUs, then=0D
+ // PreSmmInitRegisterTable may be set to 0.=0D
+ //=0D
+ EFI_PHYSICAL_ADDRESS PreSmmInitRegisterTable;=0D
+ //=0D
+ // Physical address of an array of CPU_REGISTER_TABLE structures, with=0D
+ // NumberOfCpus entries. If a register table is not required, then the=
=0D
+ // TableLength and AllocatedSize fields of CPU_REGISTER_TABLE are set to=
0.=0D
+ // If TableLength is > 0, then elements of RegisterTableEntry are used t=
o=0D
+ // initialize the CPU that matches InitialApicId, during an ACPI S3 resu=
me,=0D
+ // after SMBASE relocation is performed.=0D
+ // If a register table is not required for any one of the CPUs, then=0D
+ // RegisterTable may be set to 0.=0D
+ //=0D
+ EFI_PHYSICAL_ADDRESS RegisterTable;=0D
+ //=0D
+ // CPU information which is required when set the register table.=0D
+ //=0D
+ CPU_STATUS_INFORMATION CpuStatus;=0D
+ //=0D
+ // Location info for each AP.=0D
+ // It points to an array which saves all APs location info.=0D
+ // The array count is the AP count in this CPU.=0D
+ //=0D
+ // If the platform does not support MSR setting at S3 resume, and=0D
+ // therefore it doesn't need the dependency semaphores, it should set=0D
+ // this field to 0.=0D
+ //=0D
+ EFI_PHYSICAL_ADDRESS ApLocation;=0D
+} CPU_FEATURE_INIT_DATA;=0D
+=0D
//=0D
// Data structure that is required for ACPI S3 resume. The PCD=0D
// PcdCpuS3DataAddress must be set to the physical address where this stru=
cture=0D
@@ -172,28 +224,6 @@ typedef struct {
//=0D
EFI_PHYSICAL_ADDRESS MtrrTable;=0D
//=0D
- // Physical address of an array of CPU_REGISTER_TABLE structures, with=0D
- // NumberOfCpus entries. If a register table is not required, then the=
=0D
- // TableLength and AllocatedSize fields of CPU_REGISTER_TABLE are set to=
0.=0D
- // If TableLength is > 0, then elements of RegisterTableEntry are used t=
o=0D
- // initialize the CPU that matches InitialApicId, during an ACPI S3 resu=
me,=0D
- // before SMBASE relocation is performed.=0D
- // If a register table is not required for any one of the CPUs, then=0D
- // PreSmmInitRegisterTable may be set to 0.=0D
- //=0D
- EFI_PHYSICAL_ADDRESS PreSmmInitRegisterTable;=0D
- //=0D
- // Physical address of an array of CPU_REGISTER_TABLE structures, with=0D
- // NumberOfCpus entries. If a register table is not required, then the=
=0D
- // TableLength and AllocatedSize fields of CPU_REGISTER_TABLE are set to=
0.=0D
- // If TableLength is > 0, then elements of RegisterTableEntry are used t=
o=0D
- // initialize the CPU that matches InitialApicId, during an ACPI S3 resu=
me,=0D
- // after SMBASE relocation is performed.=0D
- // If a register table is not required for any one of the CPUs, then=0D
- // RegisterTable may be set to 0.=0D
- //=0D
- EFI_PHYSICAL_ADDRESS RegisterTable;=0D
- //=0D
// Physical address of a buffer that contains the machine check handler =
that=0D
// is used during an ACPI S3 Resume. In order for this machine check=0D
// handler to be active on an AP during an ACPI S3 resume, the machine c=
heck=0D
@@ -208,19 +238,10 @@ typedef struct {
//=0D
UINT32 ApMachineCheckHandlerSize;=0D
//=0D
- // CPU information which is required when set the register table.=0D
- //=0D
- CPU_STATUS_INFORMATION CpuStatus;=0D
- //=0D
- // Location info for each AP.=0D
- // It points to an array which saves all APs location info.=0D
- // The array count is the AP count in this CPU.=0D
- //=0D
- // If the platform does not support MSR setting at S3 resume, and=0D
- // therefore it doesn't need the dependency semaphores, it should set=0D
- // this field to 0.=0D
+ // Data structure that is used for CPU feature initialization during ACP=
I S3=0D
+ // resume.=0D
//=0D
- EFI_PHYSICAL_ADDRESS ApLocation;=0D
+ CPU_FEATURE_INIT_DATA CpuFeatureInitData;=0D
} ACPI_CPU_DATA;=0D
=0D
#endif=0D
--=20
2.28.0.windows.1


[PATCH v1 2/2] UefiCpuPkg: Prevent from re-initializing CPU features during S3 resume

Jason Lou
 

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

Current CPU feature initialization design:
During normal boot, CpuFeaturesPei module (inside FSP) initializes the
CPU features. During S3 boot, CpuFeaturesPei module does nothing, and
CpuSmm driver (in SMRAM) initializes CPU features instead.

This code change prevents CpuSmm driver from re-initializing CPU
features during S3 resume if CpuFeaturesPei module has done the same
initialization.

In addition, EDK2 contains DxeIpl PEIM that calls S3RestoreConfig2 PPI
during S3 boot and this PPI eventually calls CpuSmm driver (in SMRAM) to
initialize the CPU features, so "EDK2 + FSP" does not have the CPU
feature initialization issue during S3 boot. But "coreboot" does not
contain DxeIpl PEIM and the issue appears, unless
"PcdCpuFeaturesInitOnS3Resume" is set to TRUE.

Signed-off-by: Jason Lou <yun.lou@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
---
UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c | 34 ++++++++++++--------
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf | 3 +-
2 files changed, 23 insertions(+), 14 deletions(-)

diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c b/UefiCpuPkg/PiSmmCpuDxeSmm/=
CpuS3.c
index 1270992f38..fece75266d 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
@@ -1155,23 +1155,31 @@ GetAcpiCpuData (
mAcpiCpuData.ApMachineCheckHandlerBase =3D (EFI_PHYSICAL_ADDRESS)(UINTN)=
MachineCheckHandlerForAp;=0D
=0D
ZeroMem (&mAcpiCpuData.CpuFeatureInitData, sizeof (CPU_FEATURE_INIT_DATA=
));=0D
- CopyCpuFeatureInitDatatoSmram (&mAcpiCpuData.CpuFeatureInitData, &AcpiCp=
uData->CpuFeatureInitData);=0D
=0D
- CpuStatus =3D &mAcpiCpuData.CpuFeatureInitData.CpuStatus;=0D
+ if (!PcdGetBool (PcdCpuFeaturesInitOnS3Resume)) {=0D
+ //=0D
+ // If the CPU features will not be initialized by CpuFeaturesPei modul=
e during=0D
+ // next ACPI S3 resume, copy the CPU features initialization data into=
SMRAM,=0D
+ // which will be consumed in SmmRestoreCpu during next S3 resume.=0D
+ //=0D
+ CopyCpuFeatureInitDatatoSmram (&mAcpiCpuData.CpuFeatureInitData, &Acpi=
CpuData->CpuFeatureInitData);=0D
=0D
- mCpuFlags.CoreSemaphoreCount =3D AllocateZeroPool (=0D
- sizeof (UINT32) * CpuStatus->PackageCou=
nt *=0D
- CpuStatus->MaxCoreCount * CpuStatus->Ma=
xThreadCount=0D
- );=0D
- ASSERT (mCpuFlags.CoreSemaphoreCount !=3D NULL);=0D
+ CpuStatus =3D &mAcpiCpuData.CpuFeatureInitData.CpuStatus;=0D
=0D
- mCpuFlags.PackageSemaphoreCount =3D AllocateZeroPool (=0D
- sizeof (UINT32) * CpuStatus->Package=
Count *=0D
- CpuStatus->MaxCoreCount * CpuStatus-=
MaxThreadCount=0D
- );=0D
- ASSERT (mCpuFlags.PackageSemaphoreCount !=3D NULL);=0D
+ mCpuFlags.CoreSemaphoreCount =3D AllocateZeroPool (=0D
+ sizeof (UINT32) * CpuStatus->PackageC=
ount *=0D
+ CpuStatus->MaxCoreCount * CpuStatus->=
MaxThreadCount=0D
+ );=0D
+ ASSERT (mCpuFlags.CoreSemaphoreCount !=3D NULL);=0D
=0D
- InitializeSpinLock((SPIN_LOCK*) &mCpuFlags.MemoryMappedLock);=0D
+ mCpuFlags.PackageSemaphoreCount =3D AllocateZeroPool (=0D
+ sizeof (UINT32) * CpuStatus->Packa=
geCount *=0D
+ CpuStatus->MaxCoreCount * CpuStatu=
s->MaxThreadCount=0D
+ );=0D
+ ASSERT (mCpuFlags.PackageSemaphoreCount !=3D NULL);=0D
+=0D
+ InitializeSpinLock((SPIN_LOCK*) &mCpuFlags.MemoryMappedLock);=0D
+ }=0D
}=0D
=0D
/**=0D
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf b/UefiCpuPkg/PiSm=
mCpuDxeSmm/PiSmmCpuDxeSmm.inf
index 76b1462996..0e88071c70 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
@@ -4,7 +4,7 @@
# This SMM driver performs SMM initialization, deploy SMM Entry Vector,=0D
# provides CPU specific services in SMM.=0D
#=0D
-# Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>=0D
+# Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>=0D
# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>=0D
#=0D
# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
@@ -134,6 +134,7 @@
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmCodeAccessCheckEnable ## CONS=
UMES=0D
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmSyncMode ## CONS=
UMES=0D
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmShadowStackSize ## SOME=
TIMES_CONSUMES=0D
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume ## CONS=
UMES=0D
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable ## CONS=
UMES=0D
gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ##=
CONSUMES=0D
gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ##=
CONSUMES=0D
--=20
2.28.0.windows.1


回复: [edk2-devel] [PATCH v1 0/3] MdeModulePkg/Core/Pei: Migration improvements and fixes

gaoliming
 

-----邮件原件-----
发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 gaoliming
发送时间: 2021年9月10日 12:52
收件人: devel@edk2.groups.io; mikuback@linux.microsoft.com
抄送: 'Jian J Wang' <jian.j.wang@intel.com>; 'Dandan Bi'
<dandan.bi@intel.com>
主题: 回复: [edk2-devel] [PATCH v1 0/3] MdeModulePkg/Core/Pei:
Migration improvements and fixes

Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>

-----邮件原件-----
发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Michael
Kubacki
发送时间: 2021年9月9日 11:46
收件人: devel@edk2.groups.io
抄送: Jian J Wang <jian.j.wang@intel.com>; Liming Gao
<gaoliming@byosoft.com.cn>; Dandan Bi <dandan.bi@intel.com>
主题: [edk2-devel] [PATCH v1 0/3] MdeModulePkg/Core/Pei: Migration
improvements and fixes

From: Michael Kubacki <michael.kubacki@microsoft.com>

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

This patch series contains three patches. The first two are for
relatively minor improvments - a typo fix in function descriptions
and changing the error level of a debug print. The third patch
fixes a pointer size mismatch.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Dandan Bi <dandan.bi@intel.com>
Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>

Michael Kubacki (3):
MdeModulePkg/Core/Pei: Fix typo in function descriptions
MdeModulePkg/Core/Pei: Make migrated PEIM message verbose
MdeModulePkg/Core/Pei: Fix pointer size mismatch in
EvacuateTempRam()

MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c | 13 ++++++++-----
MdeModulePkg/Core/Pei/PeiMain.h | 2 +-
2 files changed, 9 insertions(+), 6 deletions(-)

--
2.28.0.windows.1



-=-=-=-=-=-=
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#80399):
https://edk2.groups.io/g/devel/message/80399
Mute This Topic: https://groups.io/mt/85477360/4905953
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub
[gaoliming@byosoft.com.cn]
-=-=-=-=-=-=






回复: [edk2-devel] RFC: Add BaseLib/QuickSort in MdePkg

gaoliming
 

Ray:

 SortLib has been added since 2015. I would suggest to still keep this library class. To resolve the package dependency, my proposal is to move the library class header file SortLib.h from MdeModulePkg to MdePkg, and still keep the library instance in MdeModulePkg. This proposal has no impact on the existing platform.

 

Thanks

Liming

发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Ni, Ray
发送时间: 2021914 14:15
收件人: Kinney, Michael D <michael.d.kinney@...>; Gao, Liming <liming.gao@...>; Liu, Zhiguang <zhiguang.liu@...>; Wang, Jian J <jian.j.wang@...>; Gao, Zhichao <zhichao.gao@...>
抄送: devel@edk2.groups.io; Chan, Amy <amy.chan@...>
主题: [edk2-devel] RFC: Add BaseLib/QuickSort in MdePkg

 

Hi package maintainers of MdePkg, MdeModulePkg and ShellPkg, community,

 

A commit (UefiCpuPkg/CpuCacheInfoLib: Sort CpuCacheInfo array) to UefiCpuPkg let
UefiCpuPkg depend on MdeModulePkg because the SortLib class and instances are all in MdeModulePkg.

 

UefiCpuPkg depending on MdeModulePkg breaks the rule that “UefiCpuPkg should ONLY depend on MdePkg”.

 

To address this issue, there are two approaches:

  1. Duplicate the sort logic in UefiCpuPkg to not depend on MdeModulePkg/SortLib
  2. Add QuickSort() API to BaseLib in MdePkg.

 

Approach #2 (MdePkg/BaseLib/QuickSort) makes more sense because quick sort is a standard algorithm.

We encourage consumers to update their code to use the quick sort in MdePkg and gradually deprecate today’s MdeModulePkg/SortLib.

 

If you don’t have concerns, I plan to:

  1. “Add QuickSort() to BaseLib” and update all existing consumers to use this API instead.

VOID

EFIAPI

QuickSort (

  IN OUT VOID                   *BufferToSort,

  IN CONST UINTN                Count,

  IN CONST UINTN                ElementSize,

  IN       SORT_COMPARE         CompareFunction

  );

 

  1. “Add new ShellPkg/SortCompareLib”

Background: ShellPkg requires to sort devicepath/string so 3 APIs in UefiSortLib (DevicePathCompare, StringNoCaseCompare, StringCompare) are provided for Shell usage. we can move the 3 APIs to the SortCompareLib and update Shell code to use BaseLib/QuickSort directly, with the sort compare function from SortCompareLib.

 

Any concerns?

 

Thanks,

Ray


[PATCH v1 3/3] MdeModulePkg: CI YAML: Added new GUID to ignore duplicate list

Kun Qin
 

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

SMM Communication PPI GUID from MdeModulePkg is defined the same as MM
Communication PPI GUID from MdePkg, according to PI Spec v1.5 and onward.

After introduction of MM Communication PPI definitions, an update in the
ignore duplicate list is needed to avoid breaking CI build.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>

Signed-off-by: Kun Qin <kuqin12@gmail.com>
---
MdeModulePkg/MdeModulePkg.ci.yaml | 1 +
1 file changed, 1 insertion(+)

diff --git a/MdeModulePkg/MdeModulePkg.ci.yaml b/MdeModulePkg/MdeModulePkg.ci.yaml
index aa304f2ccd5c..b8d15a3e952e 100644
--- a/MdeModulePkg/MdeModulePkg.ci.yaml
+++ b/MdeModulePkg/MdeModulePkg.ci.yaml
@@ -84,6 +84,7 @@
"IgnoreDuplicates": [
"gEfiPeiMmAccessPpiGuid=gPeiSmmAccessPpiGuid",
"gPeiSmmControlPpiGuid=gEfiPeiMmControlPpiGuid",
+ "gEfiPeiMmCommunicationPpiGuid=gEfiPeiSmmCommunicationPpiGuid",
]
},

--
2.32.0.windows.1


[PATCH v1 2/3] MdePkg: CI YAML: Added new GUID to ignore duplicate list

Kun Qin
 

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

SMM Communication PPI GUID from MdeModulePkg is defined the same as MM
Communication PPI GUID from MdePkg, according to PI Spec v1.5 and onward.

After introduction of MM Communication PPI definitions, an update in the
ignore duplicate list is needed to avoid breaking CI build.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>

Signed-off-by: Kun Qin <kuqin12@gmail.com>
---
MdePkg/MdePkg.ci.yaml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/MdePkg/MdePkg.ci.yaml b/MdePkg/MdePkg.ci.yaml
index 98eaea1c8248..3ea8eec33152 100644
--- a/MdePkg/MdePkg.ci.yaml
+++ b/MdePkg/MdePkg.ci.yaml
@@ -100,7 +100,8 @@
"gEfiProcessorSpecificErrorSectionGuid=gEfiIa32X64ProcessorErrorSectionGuid", ## is this a bug
"gEfiSmmPeriodicTimerDispatch2ProtocolGuid=gEfiMmPeriodicTimerDispatchProtocolGuid",
"gEfiPeiMmAccessPpiGuid=gPeiSmmAccessPpiGuid",
- "gPeiSmmControlPpiGuid=gEfiPeiMmControlPpiGuid"
+ "gPeiSmmControlPpiGuid=gEfiPeiMmControlPpiGuid",
+ "gEfiPeiMmCommunicationPpiGuid=gEfiPeiSmmCommunicationPpiGuid",
]
},

--
2.32.0.windows.1


[PATCH v1 1/3] MdePkg: MmCommunication: Added definition of MM Communication PPI

Kun Qin
 

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

MM Communication PPI was defined in PI Specification since v1.5. This
change added definition of such PPI and related GUIDs into MdePkg.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>

Signed-off-by: Kun Qin <kuqin12@gmail.com>
---
MdePkg/Include/Ppi/MmCommunication.h | 72 ++++++++++++++++++++
MdePkg/MdePkg.dec | 3 +
2 files changed, 75 insertions(+)

diff --git a/MdePkg/Include/Ppi/MmCommunication.h b/MdePkg/Include/Ppi/MmCommunication.h
new file mode 100644
index 000000000000..7e06da2ec088
--- /dev/null
+++ b/MdePkg/Include/Ppi/MmCommunication.h
@@ -0,0 +1,72 @@
+/** @file
+ EFI MM Communication PPI definition.
+
+ This PPI provides a means of communicating between drivers outside
+ of MM and MMI handlers inside of MM in PEI phase.
+
+ Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#ifndef MM_COMMUNICATION_PPI_H_
+#define MM_COMMUNICATION_PPI_H_
+
+#define EFI_PEI_MM_COMMUNICATION_PPI_GUID \
+ { \
+ 0xae933e1c, 0xcc47, 0x4e38, { 0x8f, 0xe, 0xe2, 0xf6, 0x1d, 0x26, 0x5, 0xdf } \
+ }
+
+typedef struct _EFI_PEI_MM_COMMUNICATION_PPI EFI_PEI_MM_COMMUNICATION_PPI;
+
+/**
+ Communicates with a registered handler.
+
+ This function provides a service to send and receive messages from a registered PEI service.
+ The EFI_PEI_MM_COMMUNICATION_PPI driver is responsible for doing any of the copies such that
+ the data lives in PEI-service-accessible RAM.
+
+ A given implementation of the EFI_PEI_MM_COMMUNICATION_PPI may choose to use the
+ EFI_MM_CONTROL_PPI for effecting the mode transition, or it may use some other method.
+
+ The agent invoking the communication interface must be physical/virtually 1:1 mapped.
+
+ To avoid confusion in interpreting frames, the CommBuffer parameter should always begin with
+ EFI_MM_COMMUNICATE_HEADER. The header data is mandatory for messages sent into the MM agent.
+
+ Once inside of MM, the MM infrastructure will call all registered handlers with the same
+ HandlerType as the GUID specified by HeaderGuid and the CommBuffer pointing to Data.
+
+ This function is not reentrant.
+
+ @param[in] This The EFI_PEI_MM_COMMUNICATION_PPI instance.
+ @param[in] CommBuffer Pointer to the buffer to convey into MMRAM.
+ @param[in] CommSize The size of the data buffer being passed in. On exit, the
+ size of data being returned. Zero if the handler does not
+ wish to reply with any data.
+
+ @retval EFI_SUCCESS The message was successfully posted.
+ @retval EFI_INVALID_PARAMETER The buffer was NULL.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PEI_MM_COMMUNICATE)(
+ IN CONST EFI_PEI_MM_COMMUNICATION_PPI *This,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommSize
+ );
+
+///
+/// EFI MM Communication PPI provides services for communicating between PEIM and a registered
+/// MMI handler.
+///
+struct _EFI_PEI_MM_COMMUNICATION_PPI {
+ EFI_PEI_MM_COMMUNICATE Communicate;
+};
+
+extern EFI_GUID gEfiPeiMmCommunicationPpiGuid;
+
+#endif
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
index a28a2daaffa8..9cdc915ebae9 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -991,6 +991,9 @@ [Ppis]
## Include/Ppi/MmConfiguration.h
gEfiPeiMmConfigurationPpi = { 0xc109319, 0xc149, 0x450e, { 0xa3, 0xe3, 0xb9, 0xba, 0xdd, 0x9d, 0xc3, 0xa4 } }

+ ## Include/Ppi/MmCommunication.h
+ gEfiPeiMmCommunicationPpiGuid = { 0xae933e1c, 0xcc47, 0x4e38, { 0x8f, 0xe, 0xe2, 0xf6, 0x1d, 0x26, 0x5, 0xdf } }
+
#
# PPIs defined in PI 1.7.
#
--
2.32.0.windows.1


[PATCH v1 0/3] Add MM Communication PPI definition to MdePkg

Kun Qin
 

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

EFI_PEI_MM_COMMUNICATION_PPI is defined since PI spec v1.5. This patch
series added the interface definition and related GUIDs into MdePkg.

Given gEfiPeiSmmCommunicationPpiGuid and gEfiPeiMmCommunicationPpiGuid
have the same value, CI build files are also updated accordingly to avoid
build failure caused by duplicate GUIDs.

Patch v1 branch: https://github.com/kuqin12/edk2/tree/mm_communicate_ppi

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Jian J Wang <jian.j.wang@intel.com>

Kun Qin (3):
MdePkg: MmCommunication: Added definition of MM Communication PPI
MdePkg: CI YAML: Added new GUID to ignore duplicate list
MdeModulePkg: CI YAML: Added new GUID to ignore duplicate list

MdeModulePkg/MdeModulePkg.ci.yaml | 1 +
MdePkg/Include/Ppi/MmCommunication.h | 72 ++++++++++++++++++++
MdePkg/MdePkg.ci.yaml | 3 +-
MdePkg/MdePkg.dec | 3 +
4 files changed, 78 insertions(+), 1 deletion(-)
create mode 100644 MdePkg/Include/Ppi/MmCommunication.h

--
2.32.0.windows.1


[edk2-platforms][PATCH V1 2/2] WhitleyOpenBoardPkg/SecCore: Add SecCore source code support

Oram, Isaac W
 

Add PlatformSecLib
so that we can build SecCore.
This uses FSP TempRamInit API in dispatch mode, but directly
tears down NEM as a workaround because the current FSP binaries
do not properly produce the TEMP_RAM_EXIT_PPI.

Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Signed-off-by: Isaac Oram <isaac.w.oram@intel.com>
---
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/FspWrapperPlatformSecLib.c | 159 +++++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/Fsp.h | 43 +++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/PeiCoreEntry.nasm | 124 +++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/SecEntry.nasm | 338 ++++++++++++++++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/Stack.nasm | 71 ++++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/PlatformInit.c | 48 +++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecFspWrapperPlatformSecLib.inf | 103 ++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecGetPerformance.c | 90 ++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecPlatformInformation.c | 79 +++++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecRamInitData.c | 29 ++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecTempRamDone.c | 130 ++++++++
Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc | 30 +-
Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf | 30 +-
Silicon/Intel/WhitleySiliconPkg/SiliconPkg.dec | 2 -
14 files changed, 1248 insertions(+), 28 deletions(-)

diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/FspWrapperPlatformSecLib.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/FspWrapperPlatformSecLib.c
new file mode 100644
index 0000000000..5e0f2ff1ac
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/FspWrapperPlatformSecLib.c
@@ -0,0 +1,159 @@
+/** @file
+ Sample to provide FSP wrapper platform sec related function.
+
+ @copyright
+ Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+
+#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/SecPerformance.h>
+#include <Ppi/PeiCoreFvLocation.h>
+
+#include <Library/LocalApicLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+
+/**
+ This interface conveys state information out of the Security (SEC) phase into PEI.
+
+ @param[in] PeiServices Pointer to the PEI Services Table.
+ @param[in,out] StructureSize Pointer to the variable describing size of the input buffer.
+ @param[out] PlatformInformationRecord Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_BUFFER_TOO_SMALL The buffer was too small.
+
+**/
+EFI_STATUS
+EFIAPI
+SecPlatformInformation (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN OUT UINT64 *StructureSize,
+ OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord
+ );
+
+/**
+ This interface conveys performance information out of the Security (SEC) phase into PEI.
+
+ This service is published by the SEC phase. The SEC phase handoff has an optional
+ EFI_PEI_PPI_DESCRIPTOR list as its final argument when control is passed from SEC into the
+ PEI Foundation. As such, if the platform supports collecting performance data in SEC,
+ this information is encapsulated into the data structure abstracted by this service.
+ This information is collected for the boot-strap processor (BSP) on IA-32.
+
+ @param[in] PeiServices The pointer to the PEI Services Table.
+ @param[in] This The pointer to this instance of the PEI_SEC_PERFORMANCE_PPI.
+ @param[out] Performance The pointer to performance data collected in SEC phase.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+
+**/
+EFI_STATUS
+EFIAPI
+SecGetPerformance (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SEC_PERFORMANCE_PPI *This,
+ OUT FIRMWARE_SEC_PERFORMANCE *Performance
+ );
+
+PEI_SEC_PERFORMANCE_PPI mSecPerformancePpi = {
+ SecGetPerformance
+};
+
+EFI_PEI_CORE_FV_LOCATION_PPI mPeiCoreFvLocationPpi = {
+ (VOID *) (UINTN) FixedPcdGet32 (PcdFlashFvPreMemoryBase)
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPeiCoreFvLocationPpiList[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gEfiPeiCoreFvLocationPpiGuid,
+ &mPeiCoreFvLocationPpi
+ }
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformPpi[] = {
+ //
+ // This must be the first PPI in the list because it will be patched in SecPlatformMain ();
+ //
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gTopOfTemporaryRamPpiGuid,
+ NULL
+ }
+};
+
+/**
+ A developer supplied function to perform platform specific operations.
+
+ It's a developer supplied function to perform any operations appropriate to a
+ given platform. It's invoked just before passing control to PEI core by SEC
+ core. Platform developer may modify the SecCoreData passed to PEI Core.
+ It returns a platform specific PPI list that platform wishes to pass to PEI core.
+ The Generic SEC core module will merge this list to join the final list passed to
+ PEI core.
+
+ @param[in,out] SecCoreData The same parameter as passing to PEI core. It
+ could be overridden by this function.
+
+ @return The platform specific PPI list to be passed to PEI core or
+ NULL if there is no need of such platform specific PPI list.
+
+**/
+EFI_PEI_PPI_DESCRIPTOR *
+EFIAPI
+SecPlatformMain (
+ IN OUT EFI_SEC_PEI_HAND_OFF *SecCoreData
+ )
+{
+ EFI_PEI_PPI_DESCRIPTOR *PpiList;
+ UINT8 TopOfTemporaryRamPpiIndex;
+ UINT8 *CopyDestinationPointer;
+ UINTN ReservedSize;
+
+ DEBUG((DEBUG_INFO, "SecPlatformMain\n"));
+
+ ReservedSize = ALIGN_VALUE (PcdGet32 (PcdPeiTemporaryRamRcHeapSize), SIZE_4KB);
+ ReservedSize += ALIGN_VALUE (PcdGet32 (PcdFspTemporaryRamSize), SIZE_4KB);
+
+ SecCoreData->PeiTemporaryRamBase = (UINT8 *) SecCoreData->PeiTemporaryRamBase + ReservedSize;
+ SecCoreData->PeiTemporaryRamSize -= ReservedSize;
+
+ DEBUG ((DEBUG_INFO, "FSP Wrapper BootFirmwareVolumeBase - 0x%x\n", SecCoreData->BootFirmwareVolumeBase));
+ DEBUG ((DEBUG_INFO, "FSP Wrapper BootFirmwareVolumeSize - 0x%x\n", SecCoreData->BootFirmwareVolumeSize));
+ DEBUG ((DEBUG_INFO, "FSP Wrapper TemporaryRamBase - 0x%x\n", SecCoreData->TemporaryRamBase));
+ DEBUG ((DEBUG_INFO, "FSP Wrapper TemporaryRamSize - 0x%x\n", SecCoreData->TemporaryRamSize));
+ DEBUG ((DEBUG_INFO, "FSP Wrapper PeiTemporaryRamBase - 0x%x\n", SecCoreData->PeiTemporaryRamBase));
+ DEBUG ((DEBUG_INFO, "FSP Wrapper PeiTemporaryRamSize - 0x%x\n", SecCoreData->PeiTemporaryRamSize));
+ DEBUG ((DEBUG_INFO, "FSP Wrapper StackBase - 0x%x\n", SecCoreData->StackBase));
+ DEBUG ((DEBUG_INFO, "FSP Wrapper StackSize - 0x%x\n", SecCoreData->StackSize));
+
+ InitializeApicTimer (0, (UINT32) -1, TRUE, 5);
+
+ //
+ // Use middle of Heap as temp buffer, it will be copied by caller.
+ // Do not use Stack, because it will cause wrong calculation on stack by PeiCore
+ //
+ PpiList = (VOID *)((UINTN) SecCoreData->PeiTemporaryRamBase + (UINTN) SecCoreData->PeiTemporaryRamSize/2);
+ CopyDestinationPointer = (UINT8 *) PpiList;
+ TopOfTemporaryRamPpiIndex = 0;
+ if ((PcdGet8 (PcdFspModeSelection) == 0) && PcdGetBool (PcdFspDispatchModeUseFspPeiMain)) {
+ //
+ // In Dispatch mode, wrapper should provide PeiCoreFvLocationPpi.
+ //
+ CopyMem (CopyDestinationPointer, mPeiCoreFvLocationPpiList, sizeof (mPeiCoreFvLocationPpiList));
+ TopOfTemporaryRamPpiIndex = 1;
+ CopyDestinationPointer += sizeof (mPeiCoreFvLocationPpiList);
+ }
+ CopyMem (CopyDestinationPointer, mPeiSecPlatformPpi, sizeof (mPeiSecPlatformPpi));
+ //
+ // Patch TopOfTemporaryRamPpi
+ //
+ PpiList[TopOfTemporaryRamPpiIndex].Ppi = (VOID *)((UINTN) SecCoreData->TemporaryRamBase + SecCoreData->TemporaryRamSize);
+
+ return PpiList;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/Fsp.h b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/Fsp.h
new file mode 100644
index 0000000000..0a8d9bf74a
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/Fsp.h
@@ -0,0 +1,43 @@
+/** @file
+ Fsp related definitions
+
+ @copyright
+ Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __FSP_H__
+#define __FSP_H__
+
+//
+// Fv Header
+//
+#define FVH_SIGINATURE_OFFSET 0x28
+#define FVH_SIGINATURE_VALID_VALUE 0x4856465F // valid signature:_FVH
+#define FVH_HEADER_LENGTH_OFFSET 0x30
+#define FVH_EXTHEADER_OFFSET_OFFSET 0x34
+#define FVH_EXTHEADER_SIZE_OFFSET 0x10
+
+//
+// Ffs Header
+//
+#define FSP_HEADER_GUID_DWORD1 0x912740BE
+#define FSP_HEADER_GUID_DWORD2 0x47342284
+#define FSP_HEADER_GUID_DWORD3 0xB08471B9
+#define FSP_HEADER_GUID_DWORD4 0x0C3F3527
+#define FFS_HEADER_SIZE_VALUE 0x18
+
+//
+// Section Header
+//
+#define SECTION_HEADER_TYPE_OFFSET 0x03
+#define RAW_SECTION_HEADER_SIZE_VALUE 0x04
+
+//
+// Fsp Header
+//
+#define FSP_HEADER_IMAGEBASE_OFFSET 0x1C
+#define FSP_HEADER_TEMPRAMINIT_OFFSET 0x30
+
+#endif
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/PeiCoreEntry.nasm b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/PeiCoreEntry.nasm
new file mode 100644
index 0000000000..917411cac2
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/PeiCoreEntry.nasm
@@ -0,0 +1,124 @@
+;------------------------------------------------------------------------------
+; @file PeiCoreEntry.nasm
+; Find and call SecStartup
+;
+; @copyright
+; Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;------------------------------------------------------------------------------
+
+SECTION .text
+
+extern ASM_PFX(SecStartup)
+extern ASM_PFX(PlatformInit)
+
+global ASM_PFX(CallPeiCoreEntryPoint)
+ASM_PFX(CallPeiCoreEntryPoint):
+ ;
+ ; Obtain the hob list pointer
+ ;
+ mov eax, [esp+4]
+ ;
+ ; Obtain the stack information
+ ; ECX: start of range
+ ; EDX: end of range
+ ;
+ mov ecx, [esp+8]
+ mov edx, [esp+0xC]
+
+ ;
+ ; Platform init
+ ;
+ pushad
+ push edx
+ push ecx
+ push eax
+ call ASM_PFX(PlatformInit)
+ pop eax
+ pop eax
+ pop eax
+ popad
+
+ ;
+ ; Set stack top pointer
+ ;
+ mov esp, edx
+
+ ;
+ ; Push the hob list pointer
+ ;
+ push eax
+
+ ;
+ ; Save the value
+ ; ECX: start of range
+ ; EDX: end of range
+ ;
+ mov ebp, esp
+ push ecx
+ push edx
+
+ ;
+ ; Push processor count to stack first, then BIST status (AP then BSP)
+ ;
+ mov eax, 1
+ cpuid
+ shr ebx, 16
+ and ebx, 0xFF
+ cmp bl, 1
+ jae PushProcessorCount
+
+ ;
+ ; Some processors report 0 logical processors. Effectively 0 = 1.
+ ; So we fix up the processor count
+ ;
+ inc ebx
+
+PushProcessorCount:
+ push ebx
+
+ ;
+ ; We need to implement a long-term solution for BIST capture. For now, we just copy BSP BIST
+ ; for all processor threads
+ ;
+ xor ecx, ecx
+ mov cl, bl
+PushBist:
+ movd eax, mm0
+ push eax
+ loop PushBist
+
+ ; Save Time-Stamp Counter
+ movd eax, mm5
+ push eax
+
+ movd eax, mm6
+ push eax
+
+ ;
+ ; Pass entry point of the PEI core
+ ;
+ mov edi, 0xFFFFFFE0
+ push DWORD [edi]
+
+ ;
+ ; Pass BFV into the PEI Core
+ ;
+ mov edi, 0xFFFFFFFC
+ push DWORD [edi]
+
+ ;
+ ; Pass stack size into the PEI Core
+ ;
+ mov ecx, [ebp - 4]
+ mov edx, [ebp - 8]
+ push ecx ; RamBase
+
+ sub edx, ecx
+ push edx ; RamSize
+
+ ;
+ ; Pass Control into the PEI Core
+ ;
+ call ASM_PFX(SecStartup)
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/SecEntry.nasm b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/SecEntry.nasm
new file mode 100644
index 0000000000..091990d627
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/SecEntry.nasm
@@ -0,0 +1,338 @@
+;------------------------------------------------------------------------------
+; @file SecEntry.nasm
+; This is the code that goes from real-mode to protected mode.
+; It consumes the reset vector, calls TempRamInit API from FSP binary.
+;
+; @copyright
+; Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;------------------------------------------------------------------------------
+
+#include "Fsp.h"
+
+SECTION .text
+
+extern ASM_PFX(CallPeiCoreEntryPoint)
+extern ASM_PFX(FsptUpdDataPtr)
+extern ASM_PFX(BoardBeforeTempRamInit)
+
+; Pcds
+extern ASM_PFX(PcdGet32 (PcdFlashFvFspTBase))
+
+;----------------------------------------------------------------------------
+;
+; Procedure: _ModuleEntryPoint
+;
+; Input: None
+;
+; Output: None
+;
+; Destroys: Assume all registers
+;
+; Description:
+;
+; Transition to non-paged flat-model protected mode from a
+; hard-coded GDT that provides exactly two descriptors.
+; This is a bare bones transition to protected mode only
+; used for a while in PEI and possibly DXE.
+;
+; After enabling protected mode, a far jump is executed to
+; transfer to PEI using the newly loaded GDT.
+;
+; Return: None
+;
+; MMX Usage:
+; MM0 = BIST State
+; MM5 = Save time-stamp counter value high32bit
+; MM6 = Save time-stamp counter value low32bit.
+;
+;----------------------------------------------------------------------------
+
+BITS 16
+align 4
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+ fninit ; clear any pending Floating point exceptions
+ ;
+ ; Store the BIST value in mm0
+ ;
+ movd mm0, eax
+
+ ;
+ ; Save time-stamp counter value
+ ; rdtsc load 64bit time-stamp counter to EDX:EAX
+ ;
+ rdtsc
+ movd mm5, edx
+ movd mm6, eax
+
+ ;
+ ; Load the GDT table in GdtDesc
+ ;
+ mov esi, GdtDesc
+ DB 66h
+ lgdt [cs:si]
+
+ ;
+ ; Transition to 16 bit protected mode
+ ;
+ mov eax, cr0 ; Get control register 0
+ or eax, 00000003h ; Set PE bit (bit #0) & MP bit (bit #1)
+ mov cr0, eax ; Activate protected mode
+
+ mov eax, cr4 ; Get control register 4
+ or eax, 00000600h ; Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
+ mov cr4, eax
+
+ ;
+ ; Now we're in 16 bit protected mode
+ ; Set up the selectors for 32 bit protected mode entry
+ ;
+ mov ax, SYS_DATA_SEL
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ ;
+ ; Transition to Flat 32 bit protected mode
+ ; The jump to a far pointer causes the transition to 32 bit mode
+ ;
+ mov esi, ProtectedModeEntryLinearAddress
+ jmp dword far [cs:si]
+
+;----------------------------------------------------------------------------
+;
+; Procedure: ProtectedModeEntryPoint
+;
+; Input: None
+;
+; Output: None
+;
+; Destroys: Assume all registers
+;
+; Description:
+;
+; This function handles:
+; Call two basic APIs from FSP binary
+; Initializes stack with some early data (BIST, PEI entry, etc)
+;
+; Return: None
+;
+;----------------------------------------------------------------------------
+
+BITS 32
+align 4
+ProtectedModeEntryPoint:
+ ;
+ ; Early board hooks
+ ;
+ mov esp, BoardBeforeTempRamInitRet
+ jmp ASM_PFX(BoardBeforeTempRamInit)
+
+BoardBeforeTempRamInitRet:
+
+ ; Find the fsp info header
+ mov edi, [ASM_PFX(PcdGet32 (PcdFlashFvFspTBase))]
+
+ mov eax, dword [edi + FVH_SIGINATURE_OFFSET]
+ cmp eax, FVH_SIGINATURE_VALID_VALUE
+ jnz FspHeaderNotFound
+
+ xor eax, eax
+ mov ax, word [edi + FVH_EXTHEADER_OFFSET_OFFSET]
+ cmp ax, 0
+ jnz FspFvExtHeaderExist
+
+ xor eax, eax
+ mov ax, word [edi + FVH_HEADER_LENGTH_OFFSET] ; Bypass Fv Header
+ add edi, eax
+ jmp FspCheckFfsHeader
+
+FspFvExtHeaderExist:
+ add edi, eax
+ mov eax, dword [edi + FVH_EXTHEADER_SIZE_OFFSET] ; Bypass Ext Fv Header
+ add edi, eax
+
+ ; Round up to 8 byte alignment
+ mov eax, edi
+ and al, 07h
+ jz FspCheckFfsHeader
+
+ and edi, 0FFFFFFF8h
+ add edi, 08h
+
+FspCheckFfsHeader:
+ ; Check the ffs guid
+ mov eax, dword [edi]
+ cmp eax, FSP_HEADER_GUID_DWORD1
+ jnz FspHeaderNotFound
+
+ mov eax, dword [edi + 4]
+ cmp eax, FSP_HEADER_GUID_DWORD2
+ jnz FspHeaderNotFound
+
+ mov eax, dword [edi + 8]
+ cmp eax, FSP_HEADER_GUID_DWORD3
+ jnz FspHeaderNotFound
+
+ mov eax, dword [edi + 0Ch]
+ cmp eax, FSP_HEADER_GUID_DWORD4
+ jnz FspHeaderNotFound
+
+ add edi, FFS_HEADER_SIZE_VALUE ; Bypass the ffs header
+
+ ; Check the section type as raw section
+ mov al, byte [edi + SECTION_HEADER_TYPE_OFFSET]
+ cmp al, 019h
+ jnz FspHeaderNotFound
+
+ add edi, RAW_SECTION_HEADER_SIZE_VALUE ; Bypass the section header
+ jmp FspHeaderFound
+
+FspHeaderNotFound:
+ jmp $
+
+FspHeaderFound:
+ ; Get the fsp TempRamInit Api address
+ mov eax, dword [edi + FSP_HEADER_IMAGEBASE_OFFSET]
+ add eax, dword [edi + FSP_HEADER_TEMPRAMINIT_OFFSET]
+
+ ; Setup the hardcode stack
+ mov esp, TempRamInitStack
+
+ ; Call the fsp TempRamInit Api
+ jmp eax
+
+TempRamInitDone:
+ cmp eax, 8000000Eh ;Check if EFI_NOT_FOUND returned. Error code for Microcode Update not found.
+ je CallSecFspInit ;If microcode not found, don't hang, but continue.
+
+ cmp eax, 0 ;Check if EFI_SUCCESS retuned.
+ jnz FspApiFailed
+
+ ; ECX: start of range
+ ; EDX: end of range
+CallSecFspInit:
+ xor eax, eax
+ mov esp, edx
+
+ ; Align the stack at DWORD
+ add esp, 3
+ and esp, 0FFFFFFFCh
+
+ push edx
+ push ecx
+ push eax ; zero - no hob list yet
+ call ASM_PFX(CallPeiCoreEntryPoint)
+
+FspApiFailed:
+ jmp $
+
+align 10h
+TempRamInitStack:
+ DD TempRamInitDone
+ DD ASM_PFX(FsptUpdDataPtr); TempRamInitParams
+
+;
+; ROM-based Global-Descriptor Table for the Tiano PEI Phase
+;
+align 16
+global ASM_PFX(BootGdtTable)
+
+;
+; GDT[0]: 0x00: Null entry, never used.
+;
+NULL_SEL EQU $ - GDT_BASE ; Selector [0]
+GDT_BASE:
+ASM_PFX(BootGdtTable):
+ DD 0
+ DD 0
+;
+; Linear data segment descriptor
+;
+LINEAR_SEL EQU $ - GDT_BASE ; Selector [0x8]
+ DW 0FFFFh ; limit 0xFFFFF
+ DW 0 ; base 0
+ DB 0
+ DB 092h ; present, ring 0, data, expand-up, writable
+ DB 0CFh ; page-granular, 32-bit
+ DB 0
+;
+; Linear code segment descriptor
+;
+LINEAR_CODE_SEL EQU $ - GDT_BASE ; Selector [0x10]
+ DW 0FFFFh ; limit 0xFFFFF
+ DW 0 ; base 0
+ DB 0
+ DB 09Bh ; present, ring 0, data, expand-up, not-writable
+ DB 0CFh ; page-granular, 32-bit
+ DB 0
+;
+; System data segment descriptor
+;
+SYS_DATA_SEL EQU $ - GDT_BASE ; Selector [0x18]
+ DW 0FFFFh ; limit 0xFFFFF
+ DW 0 ; base 0
+ DB 0
+ DB 093h ; present, ring 0, data, expand-up, not-writable
+ DB 0CFh ; page-granular, 32-bit
+ DB 0
+
+;
+; System code segment descriptor
+;
+SYS_CODE_SEL EQU $ - GDT_BASE ; Selector [0x20]
+ DW 0FFFFh ; limit 0xFFFFF
+ DW 0 ; base 0
+ DB 0
+ DB 09Ah ; present, ring 0, data, expand-up, writable
+ DB 0CFh ; page-granular, 32-bit
+ DB 0
+;
+; Spare segment descriptor
+;
+SYS16_CODE_SEL EQU $ - GDT_BASE ; Selector [0x28]
+ DW 0FFFFh ; limit 0xFFFFF
+ DW 0 ; base 0
+ DB 0Eh ; Changed from F000 to E000.
+ DB 09Bh ; present, ring 0, code, expand-up, writable
+ DB 00h ; byte-granular, 16-bit
+ DB 0
+;
+; Spare segment descriptor
+;
+SYS16_DATA_SEL EQU $ - GDT_BASE ; Selector [0x30]
+ DW 0FFFFh ; limit 0xFFFF
+ DW 0 ; base 0
+ DB 0
+ DB 093h ; present, ring 0, data, expand-up, not-writable
+ DB 00h ; byte-granular, 16-bit
+ DB 0
+
+;
+; Spare segment descriptor
+;
+SPARE5_SEL EQU $ - GDT_BASE ; Selector [0x38]
+ DW 0 ; limit 0
+ DW 0 ; base 0
+ DB 0
+ DB 0 ; present, ring 0, data, expand-up, writable
+ DB 0 ; page-granular, 32-bit
+ DB 0
+GDT_SIZE EQU $ - GDT_BASE ; Size, in bytes
+
+;
+; GDT Descriptor
+;
+GdtDesc: ; GDT descriptor
+ DW GDT_SIZE - 1 ; GDT limit
+ DD GDT_BASE ; GDT base address
+
+
+ProtectedModeEntryLinearAddress:
+ProtectedModeEntryLinear:
+ DD ProtectedModeEntryPoint ; Offset of our 32 bit code
+ DW LINEAR_CODE_SEL
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/Stack.nasm b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/Stack.nasm
new file mode 100644
index 0000000000..80a7a67ecf
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/Stack.nasm
@@ -0,0 +1,71 @@
+;------------------------------------------------------------------------------
+; @file Stack.nasm
+; Switch the stack from temporary memory to permenent memory.
+;
+; @copyright
+; Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;------------------------------------------------------------------------------
+
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; SecSwitchStack (
+; UINT32 TemporaryMemoryBase,
+; UINT32 PermanentMemoryBase
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(SecSwitchStack)
+ASM_PFX(SecSwitchStack):
+ ;
+ ; Save three register: eax, ebx, ecx
+ ;
+ push eax
+ push ebx
+ push ecx
+ push edx
+
+ ;
+ ; !!CAUTION!! this function address's is pushed into stack after
+ ; migration of whole temporary memory, so need save it to permanent
+ ; memory at first!
+ ;
+
+ mov ebx, [esp + 20] ; Save the first parameter
+ mov ecx, [esp + 24] ; Save the second parameter
+
+ ;
+ ; Save this function's return address into permanent memory at first.
+ ; Then, Fixup the esp point to permanent memory
+ ;
+ mov eax, esp
+ sub eax, ebx
+ add eax, ecx
+ mov edx, dword [esp] ; copy pushed register's value to permanent memory
+ mov dword [eax], edx
+ mov edx, dword [esp + 4]
+ mov dword [eax + 4], edx
+ mov edx, dword [esp + 8]
+ mov dword [eax + 8], edx
+ mov edx, dword [esp + 12]
+ mov dword [eax + 12], edx
+ mov edx, dword [esp + 16] ; Update this function's return address into permanent memory
+ mov dword [eax + 16], edx
+ mov esp, eax ; From now, esp is pointed to permanent memory
+
+ ;
+ ; Fixup the ebp point to permanent memory
+ ;
+ mov eax, ebp
+ sub eax, ebx
+ add eax, ecx
+ mov ebp, eax ; From now, ebp is pointed to permanent memory
+
+ pop edx
+ pop ecx
+ pop ebx
+ pop eax
+ ret
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/PlatformInit.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/PlatformInit.c
new file mode 100644
index 0000000000..546b13f8a3
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/PlatformInit.c
@@ -0,0 +1,48 @@
+/** @file
+ Sample to provide platform init function.
+
+ @copyright
+ Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+
+#include <PiPei.h>
+#include <Library/DebugLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/SecBoardInitLib.h>
+#include <Library/TestPointCheckLib.h>
+
+/**
+ Platform initialization.
+
+ @param[in] FspHobList HobList produced by FSP.
+ @param[in] StartOfRange Start of temporary RAM.
+ @param[in] EndOfRange End of temporary RAM.
+**/
+VOID
+EFIAPI
+PlatformInit (
+ IN VOID *FspHobList,
+ IN VOID *StartOfRange,
+ IN VOID *EndOfRange
+ )
+{
+ //
+ // Platform initialization
+ // Enable Serial port here
+ //
+ if (PcdGetBool(PcdSecSerialPortDebugEnable)) {
+ SerialPortInitialize ();
+ }
+
+ DEBUG ((DEBUG_INFO, "PrintPeiCoreEntryPointParam in PlatformInit\n"));
+ DEBUG ((DEBUG_INFO, "FspHobList - 0x%x\n", FspHobList));
+ DEBUG ((DEBUG_INFO, "StartOfRange - 0x%x\n", StartOfRange));
+ DEBUG ((DEBUG_INFO, "EndOfRange - 0x%x\n", EndOfRange));
+
+ BoardAfterTempRamInit ();
+
+ TestPointTempMemoryFunction (StartOfRange, EndOfRange);
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecFspWrapperPlatformSecLib.inf b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecFspWrapperPlatformSecLib.inf
new file mode 100644
index 0000000000..37e0a5cb63
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecFspWrapperPlatformSecLib.inf
@@ -0,0 +1,103 @@
+## @file
+# Provide FSP wrapper platform sec related function.
+#
+# @copyright
+# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecFspWrapperPlatformSecLib
+ FILE_GUID = 8F1AC44A-CE7E-4E29-95BB-92E321BB1573
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformSecLib
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources]
+ FspWrapperPlatformSecLib.c
+ SecRamInitData.c
+ SecPlatformInformation.c
+ SecGetPerformance.c
+ SecTempRamDone.c
+ PlatformInit.c
+
+[Sources.IA32]
+ Ia32/SecEntry.nasm
+ Ia32/PeiCoreEntry.nasm
+ Ia32/Stack.nasm
+ Ia32/Fsp.h
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+ IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
+ WhitleySiliconPkg/CpRcPkg.dec
+ WhitleySiliconPkg/SiliconPkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
+ WhitleyFspBinPkg/WhitleyFspBinPkg.dec
+
+[LibraryClasses]
+ LocalApicLib
+ SerialPortLib
+ DebugLib
+ BaseMemoryLib
+ FspWrapperPlatformLib
+ FspWrapperApiLib
+ SecBoardInitLib
+ TestPointCheckLib
+ PeiServicesTablePointerLib
+
+[Ppis]
+ gEfiSecPlatformInformationPpiGuid ## CONSUMES
+ gPeiSecPerformancePpiGuid ## CONSUMES
+ gTopOfTemporaryRamPpiGuid ## PRODUCES
+ gEfiPeiFirmwareVolumeInfoPpiGuid ## PRODUCES
+ gPlatformInitTempRamExitPpiGuid ## CONSUMES
+
+[Pcd]
+ gEfiCpRcPkgTokenSpaceGuid.PcdPeiTemporaryRamRcHeapSize ## CONSUMES
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashFvFspTBase ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashFvFspMBase ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdSecSerialPortDebugEnable ## CONSUMES
+
+[FixedPcd]
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashFvMicrocodeBase ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashFvMicrocodeSize ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdMicrocodeOffsetInFv ## CONSUMES
+ gCpuUncoreTokenSpaceGuid.PcdFlashSecCacheRegionBase ## CONSUMES
+ gCpuUncoreTokenSpaceGuid.PcdFlashSecCacheRegionSize ## CONSUMES
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFlashFvPreMemoryBase ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdFspDispatchModeUseFspPeiMain ## CONSUMES
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecGetPerformance.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecGetPerformance.c
new file mode 100644
index 0000000000..977212737e
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecGetPerformance.c
@@ -0,0 +1,90 @@
+/** @file
+ Sample to provide SecGetPerformance function.
+
+ @copyright
+ Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+
+#include <Ppi/SecPerformance.h>
+#include <Ppi/TopOfTemporaryRam.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/TimerLib.h>
+#include <Library/DebugLib.h>
+
+/**
+ This interface conveys performance information out of the Security (SEC) phase into PEI.
+
+ This service is published by the SEC phase. The SEC phase handoff has an optional
+ EFI_PEI_PPI_DESCRIPTOR list as its final argument when control is passed from SEC into the
+ PEI Foundation. As such, if the platform supports collecting performance data in SEC,
+ this information is encapsulated into the data structure abstracted by this service.
+ This information is collected for the boot-strap processor (BSP) on IA-32.
+
+ @param[in] PeiServices The pointer to the PEI Services Table.
+ @param[in] This The pointer to this instance of the PEI_SEC_PERFORMANCE_PPI.
+ @param[out] Performance The pointer to performance data collected in SEC phase.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+
+**/
+EFI_STATUS
+EFIAPI
+SecGetPerformance (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SEC_PERFORMANCE_PPI *This,
+ OUT FIRMWARE_SEC_PERFORMANCE *Performance
+ )
+{
+ UINT32 Size;
+ UINT32 Count;
+ UINTN TopOfTemporaryRam;
+ UINT64 Ticker;
+ VOID *TopOfTemporaryRamPpi;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "SecGetPerformance\n"));
+
+ Status = (*PeiServices)->LocatePpi (
+ PeiServices,
+ &gTopOfTemporaryRamPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &TopOfTemporaryRamPpi
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // |--------------| <- TopOfTemporaryRam - BL
+ // | List Ptr |
+ // |--------------|
+ // | BL RAM Start |
+ // |--------------|
+ // | BL RAM End |
+ // |--------------|
+ // |Number of BSPs|
+ // |--------------|
+ // | BIST |
+ // |--------------|
+ // | .... |
+ // |--------------|
+ // | TSC[63:32] |
+ // |--------------|
+ // | TSC[31:00] |
+ // |--------------|
+ //
+ TopOfTemporaryRam = (UINTN) TopOfTemporaryRamPpi - sizeof (UINT32);
+ TopOfTemporaryRam -= sizeof (UINT32) * 2;
+ Count = *(UINT32 *)(TopOfTemporaryRam - sizeof (UINT32));
+ Size = Count * sizeof (UINT32);
+
+ Ticker = *(UINT64 *) (TopOfTemporaryRam - sizeof (UINT32) - Size - sizeof (UINT32) * 2);
+ Performance->ResetEnd = GetTimeInNanoSecond (Ticker);
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecPlatformInformation.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecPlatformInformation.c
new file mode 100644
index 0000000000..3d1b9be21c
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecPlatformInformation.c
@@ -0,0 +1,79 @@
+/** @file
+ Sample to provide SecPlatformInformation function.
+
+ @copyright
+ Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+
+#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/TopOfTemporaryRam.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+
+/**
+ This interface conveys state information out of the Security (SEC) phase into PEI.
+
+ @param[in] PeiServices Pointer to the PEI Services Table.
+ @param[in,out] StructureSize Pointer to the variable describing size of the input buffer.
+ @param[out] PlatformInformationRecord Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_BUFFER_TOO_SMALL The buffer was too small.
+
+**/
+EFI_STATUS
+EFIAPI
+SecPlatformInformation (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN OUT UINT64 *StructureSize,
+ OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord
+ )
+{
+ UINT32 *Bist;
+ UINT32 Size;
+ UINT32 Count;
+ UINTN TopOfTemporaryRam;
+ VOID *TopOfTemporaryRamPpi;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "SecPlatformInformation\n"));
+
+ Status = (*PeiServices)->LocatePpi (
+ PeiServices,
+ &gTopOfTemporaryRamPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &TopOfTemporaryRamPpi
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // The entries of BIST information, together with the number of them,
+ // reside in the bottom of stack, left untouched by normal stack operation.
+ // This routine copies the BIST information to the buffer pointed by
+ // PlatformInformationRecord for output.
+ //
+ TopOfTemporaryRam = (UINTN) TopOfTemporaryRamPpi - sizeof (UINT32);
+ TopOfTemporaryRam -= sizeof (UINT32) * 2;
+ Count = *((UINT32 *)(TopOfTemporaryRam - sizeof (UINT32)));
+ Size = Count * sizeof (IA32_HANDOFF_STATUS);
+
+ if ((*StructureSize) < (UINT64) Size) {
+ *StructureSize = Size;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *StructureSize = Size;
+ Bist = (UINT32 *) (TopOfTemporaryRam - sizeof (UINT32) - Size);
+
+ CopyMem (PlatformInformationRecord, Bist, Size);
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecRamInitData.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecRamInitData.c
new file mode 100644
index 0000000000..a6c7a53d33
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecRamInitData.c
@@ -0,0 +1,29 @@
+/** @file
+ Sample to provide TempRamInitParams data.
+
+ @copyright
+ Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/PcdLib.h>
+#include <FspEas.h>
+#include <FsptUpd.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST FSPT_UPD FsptUpdDataPtr = {
+ {
+ FSPT_UPD_SIGNATURE,
+ 0x00,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ }
+ },
+ {
+ FixedPcdGet32 (PcdFlashFvMicrocodeBase) + FixedPcdGet32 (PcdMicrocodeOffsetInFv),
+ FixedPcdGet32 (PcdFlashFvMicrocodeSize) - FixedPcdGet32 (PcdMicrocodeOffsetInFv),
+ FixedPcdGet32 (PcdFlashSecCacheRegionBase),
+ FixedPcdGet32 (PcdFlashSecCacheRegionSize),
+ }
+};
+
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecTempRamDone.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecTempRamDone.c
new file mode 100644
index 0000000000..e6f2c1c4d6
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecTempRamDone.c
@@ -0,0 +1,130 @@
+/** @file
+ Sample to provide SecTemporaryRamDone function.
+
+ @copyright
+ Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+
+#include <Ppi/TemporaryRamDone.h>
+#include <Ppi/PlatformInitTempRamExitPpi.h>
+
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/FspWrapperPlatformLib.h>
+#include <Library/FspWrapperApiLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+
+#include <Guid/FspHeaderFile.h>
+
+#include <Register/ArchitecturalMsr.h>
+
+#define MSR_NEM 0x000002E0
+
+/**
+This interface disables temporary memory in SEC Phase.
+This is for dispatch mode use. We should properly produce the FSP_TEMP_RAM_EXIT_PPI and then call
+that instead, but the FSP does not produce that PPI
+**/
+VOID
+EFIAPI
+SecPlatformDisableTemporaryMemoryDispatchHack (
+ VOID
+ )
+{
+ UINT64 MsrValue;
+ UINT64 MtrrDefaultType;
+ MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType;
+
+ //
+ // Force and INVD.
+ //
+ AsmInvd ();
+
+ //
+ // Disable MTRRs.
+ //
+ DefType.Uint64 = AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE);
+ MtrrDefaultType = DefType.Uint64;
+ DefType.Bits.E = 0;
+ AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE, DefType.Uint64);
+
+ //
+ // Force and INVD to prevent MCA error.
+ //
+ AsmInvd ();
+
+ //
+ // Clear NEM Run and NEM Setup bits individually.
+ //
+ MsrValue = AsmReadMsr64 (MSR_NEM);
+ MsrValue &= ~((UINT64) BIT1);
+ AsmWriteMsr64 (MSR_NEM, MsrValue);
+ MsrValue &= ~((UINT64) BIT0);
+ AsmWriteMsr64 (MSR_NEM, MsrValue);
+
+ //
+ // Restore MTRR default setting
+ //
+ AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE, MtrrDefaultType);
+}
+
+/**
+This interface disables temporary memory in SEC Phase.
+**/
+VOID
+EFIAPI
+SecPlatformDisableTemporaryMemory (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ VOID *TempRamExitParam;
+ CONST EFI_PEI_SERVICES **PeiServices;
+ PLATFORM_INIT_TEMP_RAM_EXIT_PPI *PlatformInitTempRamExitPpi;
+
+ DEBUG ((DEBUG_INFO, "SecPlatformDisableTemporaryMemory enter\n"));
+ PeiServices = GetPeiServicesTablePointer ();
+ ASSERT (PeiServices != NULL);
+ if (PeiServices == NULL) {
+ return ;
+ }
+ ASSERT ((*PeiServices) != NULL);
+ if ((*PeiServices) == NULL) {
+ return;
+ }
+ Status = (*PeiServices)->LocatePpi (
+ PeiServices,
+ &gPlatformInitTempRamExitPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &PlatformInitTempRamExitPpi
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = PlatformInitTempRamExitPpi->PlatformInitBeforeTempRamExit ();
+ ASSERT_EFI_ERROR (Status);
+
+ if (PcdGet8 (PcdFspModeSelection) == 1) {
+ //
+ // FSP API mode
+ //
+ TempRamExitParam = UpdateTempRamExitParam ();
+ Status = CallTempRamExit (TempRamExitParam);
+ DEBUG ((DEBUG_INFO, "TempRamExit status: 0x%x\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ SecPlatformDisableTemporaryMemoryDispatchHack ();
+ }
+
+ Status = PlatformInitTempRamExitPpi->PlatformInitAfterTempRamExit ();
+ ASSERT_EFI_ERROR(Status);
+
+ return ;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc
index fa41ae923d..dc3dd0e026 100644
--- a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc
+++ b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc
@@ -48,6 +48,9 @@
#
!include $(SILICON_PKG)/MrcCommonConfig.dsc

+[Packages]
+ IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
+
!include $(FSP_BIN_PKG)/DynamicExPcd.dsc
!include $(FSP_BIN_PKG)/DynamicExPcdFvLateSilicon.dsc
!include $(RP_PKG)/DynamicExPcd.dsc
@@ -192,8 +195,17 @@
gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase|0x00FE800000
gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize|0x0000200000

+ #
+ # Mode | FSP_MODE | PcdFspModeSelection
+ # ------------------|----------|--------------------
+ # FSP Dispatch Mode | 1 | 0
+ # FSP API Mode | 0 | 1
+ #
!if ($(FSP_MODE) == 0)
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection|1
gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize|0x00070000
+!else
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection|0
!endif
gUefiCpuPkgTokenSpaceGuid.PcdPeiTemporaryRamStackSize|0x20000

@@ -310,6 +322,12 @@
!include $(SILICON_PKG)/Product/Whitley/SiliconPkg10nmPcds.dsc

[PcdsFixedAtBuild.IA32]
+ #
+ # FSP Base address PCD will be updated in FDF basing on flash map.
+ #
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFsptBaseAddress|0
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddress|0
+
!if ($(FSP_MODE) == 0)
gMinPlatformPkgTokenSpaceGuid.PcdFspWrapperBootMode|TRUE
gIntelFsp2WrapperTokenSpaceGuid.PcdPeiMinMemSize|0x4000000
@@ -543,12 +561,11 @@
VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf

[LibraryClasses.Common.SEC, LibraryClasses.Common.PEI_CORE, LibraryClasses.Common.PEIM]
-!if ($(FSP_MODE) == 0)
FspWrapperApiLib|IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
FspWrapperApiTestLib|IntelFsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/PeiFspWrapperApiTestLib.inf
FspWrapperPlatformLib|WhitleySiliconPkg/Library/FspWrapperPlatformLib/FspWrapperPlatformLib.inf
FspWrapperHobProcessLib|WhitleyOpenBoardPkg/Library/PeiFspWrapperHobProcessLib/PeiFspWrapperHobProcessLib.inf
-!endif
+
FspSwitchStackLib|IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf
FspCommonLib|IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf
FspPlatformLib|IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf
@@ -559,6 +576,11 @@
#
TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf

+ PlatformSecLib|$(RP_PKG)/Library/SecFspWrapperPlatformSecLib/SecFspWrapperPlatformSecLib.inf
+ SecBoardInitLib|MinPlatformPkg/PlatformInit/Library/SecBoardInitLibNull/SecBoardInitLibNull.inf
+ TestPointCheckLib|MinPlatformPkg/Test/Library/TestPointCheckLib/SecTestPointCheckLib.inf
+ VariableReadLib|MinPlatformPkg/Library/BaseVariableReadLibNull/BaseVariableReadLibNull.inf
+
[LibraryClasses.Common.PEI_CORE, LibraryClasses.Common.PEIM]
#
# ToDo: Can we remove
@@ -617,6 +639,8 @@
DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf

[Components.IA32]
+ UefiCpuPkg/SecCore/SecCore.inf
+
!include MinPlatformPkg/Include/Dsc/CorePeiInclude.dsc

MdeModulePkg/Universal/PCD/Pei/Pcd.inf {
@@ -653,8 +677,8 @@
BoardInitLib|$(PLATFORM_PKG)/PlatformInit/Library/BoardInitLibNull/BoardInitLibNull.inf
}

-!if ($(FSP_MODE) == 0)
IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
+!if ($(FSP_MODE) == 0)
IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
$(RP_PKG)/Platform/Pei/DummyPchSpi/DummyPchSpi.inf
!endif
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf
index 927db9e210..d128f61b9d 100644
--- a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf
+++ b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf
@@ -14,7 +14,7 @@ DEFINE PLATFORM_PKG = MinPlatformPkg
# 0x00000060 = (EFI_FIRMWARE_VOLUME_HEADER. HeaderLength + sizeof (EFI_FFS_FILE_HEADER))
DEFINE FDF_FIRMWARE_HEADER_SIZE = 0x00000060

-DEFINE MICROCODE_HEADER_SIZE = 0x00000090
+SET gMinPlatformPkgTokenSpaceGuid.PcdMicrocodeOffsetInFv = 0x90 # FV Header plus FFS header

DEFINE VPD_HEADER_SIZE = 0x00000090

@@ -153,24 +153,12 @@ SET gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaSize = 0x01000000
SET gCpPlatFlashTokenSpaceGuid.PcdFlashFvSecPeiBase = gMinPlatformPkgTokenSpaceGuid.PcdFlashFvPreMemoryBase
SET gCpPlatFlashTokenSpaceGuid.PcdFlashFvSecPeiSize = gMinPlatformPkgTokenSpaceGuid.PcdFlashFvPreMemorySize

- #
- # For FSP Dispatch Mode, specify the FV containing the PEI core.
- #
- !if $(FSP_MODE) == 1
- #
- # Tell SEC to use PEI Core from outside FSP for additional debug message control.
- #
- SET gSiPkgTokenSpaceGuid.PcdPeiCoreFv = gMinPlatformPkgTokenSpaceGuid.PcdFlashFvPreMemoryBase
- !endif
-
#
# For API mode, wrappers have some duplicate PCD as well
#
- !if $(FSP_MODE) == 0
- SET gIntelFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddress = gMinPlatformPkgTokenSpaceGuid.PcdFlashFvFspMBase
- SET gIntelFsp2WrapperTokenSpaceGuid.PcdFsptBaseAddress = gMinPlatformPkgTokenSpaceGuid.PcdFlashFvFspTBase
- SET gIntelFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddress = gMinPlatformPkgTokenSpaceGuid.PcdFlashFvFspSBase
- !endif
+ SET gIntelFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddress = gMinPlatformPkgTokenSpaceGuid.PcdFlashFvFspSBase
+ SET gIntelFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddress = gMinPlatformPkgTokenSpaceGuid.PcdFlashFvFspMBase
+ SET gIntelFsp2WrapperTokenSpaceGuid.PcdFsptBaseAddress = gMinPlatformPkgTokenSpaceGuid.PcdFlashFvFspTBase

################################################################################
#
@@ -311,7 +299,8 @@ SET gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaSize = 0x01000000
#
# Set gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress dynamically
#
- SET gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress = gCpPlatFlashTokenSpaceGuid.PcdFlashFvBinaryBase + gMinPlatformPkgTokenSpaceGuid.PcdFlashFvMicrocodeOffset + $(MICROCODE_HEADER_SIZE)
+ SET gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress = gCpPlatFlashTokenSpaceGuid.PcdFlashFvBinaryBase + gMinPlatformPkgTokenSpaceGuid.PcdFlashFvMicrocodeOffset + gMinPlatformPkgTokenSpaceGuid.PcdMicrocodeOffsetInFv
+ SET gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize = gMinPlatformPkgTokenSpaceGuid.PcdFlashFvMicrocodeSize - gMinPlatformPkgTokenSpaceGuid.PcdMicrocodeOffsetInFv

#
# FV Layout (You should not need to modify this section)
@@ -410,12 +399,7 @@ SET gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaSize = 0x01000000
!include WhitleyOpenBoardPkg/Include/Fdf/CommonSpiFvHeaderInfo.fdf
FvNameGuid = 6522280D-28F9-4131-ADC4-F40EBFA45864

- FILE SEC = 1BA0062E-C779-4582-8566-336AE8F78F09 {
- SECTION UI = "SecCore"
- SECTION VERSION = "1.0"
- SECTION Align = 16 PE32 = $(FSP_BIN_PKG)/UefiDrivers/$(FSP_BIN_DIR)/1BA0062E-C779-4582-8566-336AE8F78F09SecCore.efi
- SECTION Align = 16 RAW = $(FSP_BIN_PKG)/UefiDrivers/$(FSP_BIN_DIR)/ResetVec.bin
- }
+ INF UefiCpuPkg/SecCore/SecCore.inf
INF MdeModulePkg/Core/Pei/PeiMain.inf

INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
diff --git a/Silicon/Intel/WhitleySiliconPkg/SiliconPkg.dec b/Silicon/Intel/WhitleySiliconPkg/SiliconPkg.dec
index d7039f65c4..ea8fd0a49b 100644
--- a/Silicon/Intel/WhitleySiliconPkg/SiliconPkg.dec
+++ b/Silicon/Intel/WhitleySiliconPkg/SiliconPkg.dec
@@ -905,8 +905,6 @@ gPeiSmmControlPpiGuid = {0x61c68702, 0x4d7e, 0x4f43, {0x8d, 0xef, 0xa7, 0x43,
gSiPkgTokenSpaceGuid.PcdCpgcGlobalSyncCtrlSupported |FALSE|BOOLEAN|0xF0000030
gSiPkgTokenSpaceGuid.PcdCpgcGlobalSyncCtrlEnableDefault |FALSE|BOOLEAN|0xF0000031

- gSiPkgTokenSpaceGuid.PcdPeiCoreFv |0x00000000|UINT32|0xF0000032
-
gSiPkgTokenSpaceGuid.ReservedN|TRUE|BOOLEAN|0xF0000033

#
--
2.27.0.windows.1


[edk2-platforms][PATCH V1 1/2] WhitleySiliconPkg/FspWrapperPlatformLib: Update for large variables

Oram, Isaac W
 

Update to utilize the larger variables.

Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Signed-off-by: Isaac Oram <isaac.w.oram@intel.com>
---
Silicon/Intel/WhitleySiliconPkg/Library/FspWrapperPlatformLib/FspWrapperPlatformLib.c | 83 +++++++-------------
Silicon/Intel/WhitleySiliconPkg/Library/FspWrapperPlatformLib/FspWrapperPlatformLib.inf | 12 +--
2 files changed, 35 insertions(+), 60 deletions(-)

diff --git a/Silicon/Intel/WhitleySiliconPkg/Library/FspWrapperPlatformLib/FspWrapperPlatformLib.c b/Silicon/Intel/WhitleySiliconPkg/Library/FspWrapperPlatformLib/FspWrapperPlatformLib.c
index 453e409523..a6196a78b0 100644
--- a/Silicon/Intel/WhitleySiliconPkg/Library/FspWrapperPlatformLib/FspWrapperPlatformLib.c
+++ b/Silicon/Intel/WhitleySiliconPkg/Library/FspWrapperPlatformLib/FspWrapperPlatformLib.c
@@ -10,76 +10,52 @@
#include <PiPei.h>
#include <Library/PeiServicesLib.h>
#include <Library/DebugLib.h>
-#include <FspmUpd.h>
-#include <Ppi/UpiPolicyPpi.h>
-#include <Guid/PlatformInfo.h>
#include <Library/HobLib.h>
-#include <Ppi/ReadOnlyVariable2.h>
#include <Library/MemoryAllocationLib.h>
+#include <Library/LargeVariableReadLib.h>
+
+#include <FspmUpd.h>
+#include <Guid/PlatformInfo.h>
+#include <Ppi/UpiPolicyPpi.h>

VOID *
-GetPlatformNvs(
+GetFspNvsBuffer (
+ VOID
)
{
EFI_STATUS Status;
- EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiVariable;
- VOID *DataBuffer;
- UINT32 DataBufferSize;
- UINTN VarAttrib;
- CHAR16 EfiMemoryConfigVariable[] = L"MemoryConfig";
+ UINTN FspNvsBufferSize;
+ VOID *FspNvsBufferPtr;

- DEBUG ((EFI_D_INFO, "Start PlatformGetNvs\n"));
-
- Status = PeiServicesLocatePpi (
- &gEfiPeiReadOnlyVariable2PpiGuid,
- 0,
- NULL,
- (VOID **) &PeiVariable
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "PlatformGetNvs: PeiServicesLocatePpi not found\n"));
+ FspNvsBufferPtr = NULL;
+ FspNvsBufferSize = 0;
+ Status = GetLargeVariable (L"FspNvsBuffer", &gFspNonVolatileStorageHobGuid, &FspNvsBufferSize, NULL);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ DEBUG ((DEBUG_INFO, "FspNvsBuffer Size = %d\n", FspNvsBufferSize));
+ FspNvsBufferPtr = AllocateZeroPool (FspNvsBufferSize);
+ if (FspNvsBufferPtr == NULL) {
+ DEBUG ((DEBUG_ERROR, "Error: Cannot create FspNvsBuffer, out of memory!\n"));
ASSERT (FALSE);
return NULL;
}
-
- VarAttrib = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS;
- DataBufferSize = 0;
- DataBuffer = NULL;
-
- Status = PeiVariable->GetVariable (
- PeiVariable,
- EfiMemoryConfigVariable,
- &gFspNonVolatileStorageHobGuid,
- (UINT32*)&VarAttrib,
- &DataBufferSize,
- NULL
- );
- if (Status == EFI_NOT_FOUND) {
- DEBUG ((EFI_D_ERROR, "PlatformGetNvs: gEfiMemoryConfigDataGuid Variable not found\n"));
+ Status = GetLargeVariable (L"FspNvsBuffer", &gFspNonVolatileStorageHobGuid, &FspNvsBufferSize, FspNvsBufferPtr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Error: Unable to read FspNvsBuffer UEFI variable Status: %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
return NULL;
}

- if (Status != EFI_BUFFER_TOO_SMALL) {
- DEBUG ((EFI_D_ERROR, "PlatformGetNvs: gEfiMemoryConfigDataGuid Get Error %r\n", Status));
- ASSERT (FALSE);
+ return FspNvsBufferPtr;
+
+ } else if (Status == EFI_NOT_FOUND) {
+ DEBUG ((DEBUG_INFO, "Cannot create FSP NVS Buffer, UEFI variable does not exist (this is likely a first boot)\n"));
+ } else {
+ DEBUG ((DEBUG_ERROR, "Error: Unable to read FspNvsBuffer UEFI variable Status: %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
}

- DataBuffer = AllocateZeroPool(DataBufferSize);
- Status = PeiVariable->GetVariable (
- PeiVariable,
- EfiMemoryConfigVariable,
- &gFspNonVolatileStorageHobGuid,
- (UINT32*)&VarAttrib,
- &DataBufferSize,
- DataBuffer
- );
- if (EFI_ERROR(Status)) {
- DEBUG ((EFI_D_ERROR, "PlatformGetNvs: gEfiMemoryConfigDataGuid Variable Error %r\n", Status));
return NULL;
}
- DEBUG ((EFI_D_INFO, "PlatformGetNvs: GetNVS %x %x\n", DataBuffer, DataBufferSize));
- return DataBuffer;
-}

VOID
EFIAPI
@@ -164,11 +140,10 @@ UpdateFspmUpdData (
FspmUpd->FspmConfig.AllLanesSizeOfTable = Upi->AllLanesSizeOfTable;
FspmUpd->FspmConfig.PerLaneSizeOfTable = Upi->PerLaneSizeOfTable;
FspmUpd->FspmConfig.WaitTimeForPSBP = Upi->WaitTimeForPSBP;
- FspmUpd->FspmConfig.IsKtiNvramDataReady = Upi->IsKtiNvramDataReady;
FspmUpd->FspmConfig.WaSerializationEn = Upi->WaSerializationEn;
FspmUpd->FspmConfig.KtiInEnableMktme = Upi->KtiInEnableMktme;
FspmUpd->FspmConfig.BoardId = PlatformInfo->BoardId;
- FspmUpd->FspmArchUpd.NvsBufferPtr = GetPlatformNvs();
+ FspmUpd->FspmArchUpd.NvsBufferPtr = GetFspNvsBuffer ();
}

/**
diff --git a/Silicon/Intel/WhitleySiliconPkg/Library/FspWrapperPlatformLib/FspWrapperPlatformLib.inf b/Silicon/Intel/WhitleySiliconPkg/Library/FspWrapperPlatformLib/FspWrapperPlatformLib.inf
index 625337c453..3e80ea670c 100644
--- a/Silicon/Intel/WhitleySiliconPkg/Library/FspWrapperPlatformLib/FspWrapperPlatformLib.inf
+++ b/Silicon/Intel/WhitleySiliconPkg/Library/FspWrapperPlatformLib/FspWrapperPlatformLib.inf
@@ -35,7 +35,6 @@
[Sources]
FspWrapperPlatformLib.c

-
################################################################################
#
# Package Dependency Section - list of Package files that are required for
@@ -47,11 +46,11 @@
MdePkg/MdePkg.dec
IntelFsp2Pkg/IntelFsp2Pkg.dec
IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
- WhitleySiliconPkg/WhitleySiliconPkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
WhitleySiliconPkg/SiliconPkg.dec
WhitleySiliconPkg/CpRcPkg.dec
- WhitleyOpenBoardPkg/PlatformPkg.dec
- CedarIslandFspBinPkg/CedarIslandFspBinPkg.dec
+ WhitleyOpenBoardPkg/PlatformPkg.dec # For LargeVariableReadLib
+ WhitleyFspBinPkg/WhitleyFspBinPkg.dec

[Ppis]
gUpiSiPolicyPpiGuid
@@ -63,9 +62,10 @@

[LibraryClasses]
PeiServicesLib
+ LargeVariableReadLib

[Pcd]
gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase ## CONSUMES
- gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize
- gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize
+ gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize ## CONSUMES
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize ## CONSUMES
gEfiCpRcPkgTokenSpaceGuid.PcdPeiTemporaryRamRcHeapSize ## CONSUMES
--
2.27.0.windows.1


[edk2-platforms][PATCH V1 0/2] Whitley SEC support

Oram, Isaac W
 

This series replaces the binary version of the SEC component with a buildable version.
The missing PlatformSecLib instance is implemented allowing the common SecCore component to be built. The resulting SecCore supports both Whitley and CedarIsland platforms in both API and Dispatch FSP modes though the WhitleyOpenBoardPkg does not currently support Whitley FSP API mode.

Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Signed-off-by: Isaac Oram <isaac.w.oram@intel.com>

Isaac Oram (2):
WhitleySiliconPkg/FspWrapperPlatformLib: Update for large variables
WhitleyOpenBoardPkg/SecCore: Add SecCore source code support

Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/FspWrapperPlatformSecLib.c | 159 +++++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/Fsp.h | 43 +++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/PeiCoreEntry.nasm | 124 +++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/SecEntry.nasm | 338 ++++++++++++++++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/Stack.nasm | 71 ++++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/PlatformInit.c | 48 +++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecFspWrapperPlatformSecLib.inf | 103 ++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecGetPerformance.c | 90 ++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecPlatformInformation.c | 79 +++++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecRamInitData.c | 29 ++
Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecTempRamDone.c | 130 ++++++++
Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc | 30 +-
Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf | 30 +-
Silicon/Intel/WhitleySiliconPkg/Library/FspWrapperPlatformLib/FspWrapperPlatformLib.c | 83 ++---
Silicon/Intel/WhitleySiliconPkg/Library/FspWrapperPlatformLib/FspWrapperPlatformLib.inf | 12 +-
Silicon/Intel/WhitleySiliconPkg/SiliconPkg.dec | 2 -
16 files changed, 1283 insertions(+), 88 deletions(-)
create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/FspWrapperPlatformSecLib.c
create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/Fsp.h
create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/PeiCoreEntry.nasm
create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/SecEntry.nasm
create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/Ia32/Stack.nasm
create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/PlatformInit.c
create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecFspWrapperPlatformSecLib.inf
create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecGetPerformance.c
create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecPlatformInformation.c
create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecRamInitData.c
create mode 100644 Platform/Intel/WhitleyOpenBoardPkg/Library/SecFspWrapperPlatformSecLib/SecTempRamDone.c

--
2.27.0.windows.1


Re: [PATCH v7 09/31] OvmfPkg/SecMain: register GHCB gpa for the SEV-SNP guest

Brijesh Singh
 

On 9/15/21 12:08 PM, Erdem Aktas wrote:
On Mon, Sep 13, 2021 at 9:20 PM Brijesh Singh <brijesh.singh@amd.com> wrote:
+*/
+STATIC
+VOID
+SevSnpGhcbRegister (
+ UINTN Address
+ )
+{
+ MSR_SEV_ES_GHCB_REGISTER Msr;
+ MSR_SEV_ES_GHCB_REGISTER CurrentMsr;
+ EFI_PHYSICAL_ADDRESS GuestFrameNumber;
+
+ GuestFrameNumber = Address >> EFI_PAGE_SHIFT;
+
+ //
+ // Save the current MSR Value
+ //
+ CurrentMsr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
We are backing the current MSR value but when was it initialized
before ? Also is not this function supposed to set the Address as the
GHCB address? If it is, do we care about the old value?
Good point, there is no reason to read and restore the old GHCB, I will remove it in next version. The function does not set this as a GHCB address, it send request to hypervisor saying that it would like to use this address. If hypervisor is not okay with the address then it may recommend something else. We don't support working with the hypervisor preferred address. Setting the GHCB address code is common between Snp and Es but checking with hypervisor whether its okay to use is new in the GHCBv2 and is SNP specific.



+ // Restore the MSR
+ //
+ AsmWriteMsr64 (MSR_SEV_ES_GHCB, CurrentMsr.GhcbPhysicalAddress);
Why are we restoring the old value? I may have misunderstood but I
thought this function will set Address as the new GHCB address?
Thanks
-Erdem


Re: [edk2-libc Patch 1/1] AppPkg/Applications/Python/Python3.6.8: add support for atexit builtin module in py 3.6.8

Rebecca Cran
 

Reviewed-by: Rebecca Cran <rebecca@nuviainc.com>


Pushed as 60added7a61075607080ff718d7fa5e764a37044.


--
Rebecca Cran

On 9/14/21 9:28 AM, Jayaprakash, N wrote:
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3626

This commit adds support for the atexit a builtin module
in standard python 3.6.8 to it's UEFI port. There are tools
like Chipsec which are dependent on it but it can be used by
other python scripts running on UEFI shell with the help of
py 3.6.8 interpreter. Tested the changes on IA32 and X64 emulators
and it is working good.

Cc: Rebecca Cran <rebecca@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Signed-off-by: Jayaprakash N <n.jayaprakash@intel.com>
---
AppPkg/Applications/Python/Python-3.6.8/Py368ReadMe.txt | 1 +
.../Python/Python-3.6.8/PyMod-3.6.8/Modules/config.c | 2 ++
AppPkg/Applications/Python/Python-3.6.8/Python368.inf | 1 +
3 files changed, 4 insertions(+)

diff --git a/AppPkg/Applications/Python/Python-3.6.8/Py368ReadMe.txt b/AppPkg/Applications/Python/Python-3.6.8/Py368ReadMe.txt
index 69bb6bd..fb81228 100644
--- a/AppPkg/Applications/Python/Python-3.6.8/Py368ReadMe.txt
+++ b/AppPkg/Applications/Python/Python-3.6.8/Py368ReadMe.txt
@@ -175,6 +175,7 @@ system as follows:
_symtable Modules/symtablemodule.c
_weakref Modules/_weakref.c
array Modules/arraymodule.c
+ atexit Modules/atexitmodule.c
binascii Modules/binascii.c
cmath Modules/cmathmodule.c
datetime Modules/_datetimemodule.c
diff --git a/AppPkg/Applications/Python/Python-3.6.8/PyMod-3.6.8/Modules/config.c b/AppPkg/Applications/Python/Python-3.6.8/PyMod-3.6.8/Modules/config.c
index 4b1eb0f..5ee42d8 100644
--- a/AppPkg/Applications/Python/Python-3.6.8/PyMod-3.6.8/Modules/config.c
+++ b/AppPkg/Applications/Python/Python-3.6.8/PyMod-3.6.8/Modules/config.c
@@ -65,6 +65,7 @@ extern PyObject* PyInit__weakref(void);
extern PyObject* init_winreg(void);
extern PyObject* PyInit_zlib(void);
extern PyObject* initbz2(void);
+extern PyObject* PyInit_atexit(void);
extern PyObject* PyMarshal_Init(void);
extern PyObject* _PyWarnings_Init(void);
@@ -111,6 +112,7 @@ struct _inittab _PyImport_Inittab[] = {
{"gc", PyInit_gc},
{"math", PyInit_math},
{"array", PyInit_array},
+ {"atexit", PyInit_atexit},
{"_datetime", PyInit__datetime},
{"parser", PyInit_parser},
{"pyexpat", PyInit_pyexpat},
diff --git a/AppPkg/Applications/Python/Python-3.6.8/Python368.inf b/AppPkg/Applications/Python/Python-3.6.8/Python368.inf
index d2e6e73..b98b4a7 100644
--- a/AppPkg/Applications/Python/Python-3.6.8/Python368.inf
+++ b/AppPkg/Applications/Python/Python-3.6.8/Python368.inf
@@ -215,6 +215,7 @@
Modules/_io/iobase.c #
Modules/_io/stringio.c #
Modules/_io/textio.c #
+ Modules/atexitmodule.c #
#Modules/cjkcodecs
Modules/cjkcodecs/multibytecodec.c #


Re: [PATCH v7 09/31] OvmfPkg/SecMain: register GHCB gpa for the SEV-SNP guest

Erdem Aktas
 

On Mon, Sep 13, 2021 at 9:20 PM Brijesh Singh <brijesh.singh@amd.com> wrote:
+*/
+STATIC
+VOID
+SevSnpGhcbRegister (
+ UINTN Address
+ )
+{
+ MSR_SEV_ES_GHCB_REGISTER Msr;
+ MSR_SEV_ES_GHCB_REGISTER CurrentMsr;
+ EFI_PHYSICAL_ADDRESS GuestFrameNumber;
+
+ GuestFrameNumber = Address >> EFI_PAGE_SHIFT;
+
+ //
+ // Save the current MSR Value
+ //
+ CurrentMsr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
We are backing the current MSR value but when was it initialized
before ? Also is not this function supposed to set the Address as the
GHCB address? If it is, do we care about the old value?


+ // Restore the MSR
+ //
+ AsmWriteMsr64 (MSR_SEV_ES_GHCB, CurrentMsr.GhcbPhysicalAddress);
Why are we restoring the old value? I may have misunderstood but I
thought this function will set Address as the new GHCB address?

Thanks
-Erdem


Re: [edk2-libc Patch 1/1] AppPkg/Applications/Python/Python3.6.8: add support for atexit builtin module in py 3.6.8

Jayaprakash, N
 

Hi Rebecca,

This another patch submitted to add support for a built-in module "atexit" in Py 3.6.8 UEFI port.

Would you be able to review and merge this change?

Regards,
JP

-----Original Message-----
From: Jayaprakash, N <n.jayaprakash@intel.com>
Sent: 14 September 2021 20:58
To: devel@edk2.groups.io
Cc: Rebecca Cran <rebecca@nuviainc.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Jayaprakash, N <n.jayaprakash@intel.com>
Subject: [edk2-libc Patch 1/1] AppPkg/Applications/Python/Python3.6.8: add support for atexit builtin module in py 3.6.8

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

This commit adds support for the atexit a builtin module in standard python 3.6.8 to it's UEFI port. There are tools like Chipsec which are dependent on it but it can be used by other python scripts running on UEFI shell with the help of py 3.6.8 interpreter. Tested the changes on IA32 and X64 emulators and it is working good.

Cc: Rebecca Cran <rebecca@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Signed-off-by: Jayaprakash N <n.jayaprakash@intel.com>
---
AppPkg/Applications/Python/Python-3.6.8/Py368ReadMe.txt | 1 +
.../Python/Python-3.6.8/PyMod-3.6.8/Modules/config.c | 2 ++
AppPkg/Applications/Python/Python-3.6.8/Python368.inf | 1 +
3 files changed, 4 insertions(+)

diff --git a/AppPkg/Applications/Python/Python-3.6.8/Py368ReadMe.txt b/AppPkg/Applications/Python/Python-3.6.8/Py368ReadMe.txt
index 69bb6bd..fb81228 100644
--- a/AppPkg/Applications/Python/Python-3.6.8/Py368ReadMe.txt
+++ b/AppPkg/Applications/Python/Python-3.6.8/Py368ReadMe.txt
@@ -175,6 +175,7 @@ system as follows:
_symtable Modules/symtablemodule.c
_weakref Modules/_weakref.c
array Modules/arraymodule.c
+ atexit Modules/atexitmodule.c
binascii Modules/binascii.c
cmath Modules/cmathmodule.c
datetime Modules/_datetimemodule.c
diff --git a/AppPkg/Applications/Python/Python-3.6.8/PyMod-3.6.8/Modules/config.c b/AppPkg/Applications/Python/Python-3.6.8/PyMod-3.6.8/Modules/config.c
index 4b1eb0f..5ee42d8 100644
--- a/AppPkg/Applications/Python/Python-3.6.8/PyMod-3.6.8/Modules/config.c
+++ b/AppPkg/Applications/Python/Python-3.6.8/PyMod-3.6.8/Modules/config
+++ .c
@@ -65,6 +65,7 @@ extern PyObject* PyInit__weakref(void); extern PyObject* init_winreg(void); extern PyObject* PyInit_zlib(void); extern PyObject* initbz2(void);
+extern PyObject* PyInit_atexit(void);

extern PyObject* PyMarshal_Init(void);
extern PyObject* _PyWarnings_Init(void); @@ -111,6 +112,7 @@ struct _inittab _PyImport_Inittab[] = {
{"gc", PyInit_gc},
{"math", PyInit_math},
{"array", PyInit_array},
+ {"atexit", PyInit_atexit},
{"_datetime", PyInit__datetime},
{"parser", PyInit_parser},
{"pyexpat", PyInit_pyexpat},
diff --git a/AppPkg/Applications/Python/Python-3.6.8/Python368.inf b/AppPkg/Applications/Python/Python-3.6.8/Python368.inf
index d2e6e73..b98b4a7 100644
--- a/AppPkg/Applications/Python/Python-3.6.8/Python368.inf
+++ b/AppPkg/Applications/Python/Python-3.6.8/Python368.inf
@@ -215,6 +215,7 @@
Modules/_io/iobase.c #
Modules/_io/stringio.c #
Modules/_io/textio.c #
+ Modules/atexitmodule.c #

#Modules/cjkcodecs
Modules/cjkcodecs/multibytecodec.c #
--
2.32.0.windows.2


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

Nhi Pham
 

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>
---
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


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

Nhi Pham
 

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>
+
+#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


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

Nhi Pham
 

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>
+
+#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 {
+ 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;
+
+ //
+ // 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

3361 - 3380 of 84031