Date   

Re: [PATCH v1 1/3] AcpiDebugFeaturePkg: Included modules are mutually exclusive

Isaac Oram
 

Reviewed-by: Isaac Oram <isaac.w.oram@...>

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Benjamin Doron
Sent: Monday, July 25, 2022 10:12 AM
To: devel@edk2.groups.io
Cc: Chaganty, Rangasai V <rangasai.v.chaganty@...>; Oram, Isaac W <isaac.w.oram@...>; Desimone, Nathaniel L <nathaniel.l.desimone@...>; Sinha, Ankit <ankit.sinha@...>; Gao, Liming <gaoliming@...>; Dong, Eric <eric.dong@...>
Subject: [edk2-devel] [PATCH v1 1/3] AcpiDebugFeaturePkg: Included modules are mutually exclusive

The DXE and SMM versions of AcpiDebug perform the same task and are therefore mutually exclusive. Including both modules results in a duplicate ACPI table, resulting in the feature not working at all.

Therefore, add a new PCD to determine which module will be included.
Now, either version successfully write to the debug buffer.

Cc: Sai Chaganty <rangasai.v.chaganty@...>
Cc: Isaac Oram <isaac.w.oram@...>
Cc: Nate DeSimone <nathaniel.l.desimone@...>
Cc: Ankit Sinha <ankit.sinha@...>
Cc: Liming Gao <gaoliming@...>
Cc: Eric Dong <eric.dong@...>
Signed-off-by: Benjamin Doron <benjamin.doron00@...>
---
Features/Intel/AdvancedFeaturePkg/AdvancedFeaturePkg.dsc | 1 +
Features/Intel/AdvancedFeaturePkg/Include/AdvancedFeaturesPcd.dsc | 1 +
Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebug.c | 4 ++++
Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.dec | 1 +
Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/AcpiDebugFeature.dsc | 3 +++
Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PostMemory.fdf | 7 +++++--
6 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/Features/Intel/AdvancedFeaturePkg/AdvancedFeaturePkg.dsc b/Features/Intel/AdvancedFeaturePkg/AdvancedFeaturePkg.dsc
index 28530b8c674b..908fe4d1f7a9 100644
--- a/Features/Intel/AdvancedFeaturePkg/AdvancedFeaturePkg.dsc
+++ b/Features/Intel/AdvancedFeaturePkg/AdvancedFeaturePkg.dsc
@@ -48,6 +48,7 @@
# Debugging features # gAcpiDebugFeaturePkgTokenSpaceGuid.PcdAcpiDebugFeatureEnable |TRUE+ gAcpiDebugFeaturePkgTokenSpaceGuid.PcdUseSmmVersion |FALSE gBeepDebugFeaturePkgTokenSpaceGuid.PcdBeepDebugFeatureEnable |TRUE gPostCodeDebugFeaturePkgTokenSpaceGuid.PcdPostCodeDebugFeatureEnable |TRUE gUsb3DebugFeaturePkgTokenSpaceGuid.PcdUsb3DebugFeatureEnable |TRUEdiff --git a/Features/Intel/AdvancedFeaturePkg/Include/AdvancedFeaturesPcd.dsc b/Features/Intel/AdvancedFeaturePkg/Include/AdvancedFeaturesPcd.dsc
index e214175edaf7..d59e3e61b9b9 100644
--- a/Features/Intel/AdvancedFeaturePkg/Include/AdvancedFeaturesPcd.dsc
+++ b/Features/Intel/AdvancedFeaturePkg/Include/AdvancedFeaturesPcd.dsc
@@ -59,6 +59,7 @@
# [PcdsFeatureFlag] gAcpiDebugFeaturePkgTokenSpaceGuid.PcdAcpiDebugFeatureEnable |FALSE+ gAcpiDebugFeaturePkgTokenSpaceGuid.PcdUseSmmVersion |FALSE gBeepDebugFeaturePkgTokenSpaceGuid.PcdBeepDebugFeatureEnable |FALSE gPostCodeDebugFeaturePkgTokenSpaceGuid.PcdPostCodeDebugFeatureEnable |FALSE gUsb3DebugFeaturePkgTokenSpaceGuid.PcdUsb3DebugFeatureEnable |FALSEdiff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebug.c b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebug.c
index 4caeffc7dec9..0b28e2f7a6d5 100644
--- a/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebug.c
+++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiD
+++ ebug.c
@@ -483,6 +483,10 @@ InitializeAcpiDebugSmm (
EFI_SMM_BASE2_PROTOCOL *SmmBase2; BOOLEAN InSmm; + if (!PcdGetBool (PcdAcpiDebugFeatureActive)) {+ return EFI_SUCCESS;+ }+ Status = gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID **) &SmmBase2); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) {diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.dec b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.dec
index 915923100731..1a290bab29d9 100644
--- a/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.dec
+++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/AcpiDebugFeaturePkg.d
+++ ec
@@ -28,6 +28,7 @@
[PcdsFeatureFlag] gAcpiDebugFeaturePkgTokenSpaceGuid.PcdAcpiDebugFeatureEnable|FALSE|BOOLEAN|0xA0000001+ gAcpiDebugFeaturePkgTokenSpaceGuid.PcdUseSmmVersion|FALSE|BOOLEAN|0xA0000002 [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx] ## This PCD specifies the ACPI debug message buffer size.diff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/AcpiDebugFeature.dsc b/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/AcpiDebugFeature.dsc
index f5b8bacee039..684549bbdd78 100644
--- a/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/AcpiDebugFeature.dsc
+++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/AcpiDebugFeat
+++ ure.dsc
@@ -54,5 +54,8 @@
# in the package build. # Add components here that should be included in the package build.+!if gAcpiDebugFeaturePkgTokenSpaceGuid.PcdUseSmmVersion == FALSE AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebugDxe.inf+!else AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebugSmm.inf+!endifdiff --git a/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PostMemory.fdf b/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PostMemory.fdf
index 855826292cb5..e904a2f8fbf2 100644
--- a/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PostMemory.fdf
+++ b/Features/Intel/Debugging/AcpiDebugFeaturePkg/Include/PostMemory.fd
+++ f
@@ -7,5 +7,8 @@
# ## -INF RuleOverride = DRIVER_ACPITABLE AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebugDxe.inf-INF RuleOverride = DRIVER_ACPITABLE AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebugSmm.inf+!if gAcpiDebugFeaturePkgTokenSpaceGuid.PcdUseSmmVersion == FALSE+ INF RuleOverride = DRIVER_ACPITABLE AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebugDxe.inf+!else+ INF RuleOverride = DRIVER_ACPITABLE AcpiDebugFeaturePkg/AcpiDebugDxeSmm/AcpiDebugSmm.inf+!endif--
2.36.1



-=-=-=-=-=-=
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#91815): https://edk2.groups.io/g/devel/message/91815
Mute This Topic: https://groups.io/mt/92609642/1492418
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [isaac.w.oram@...]
-=-=-=-=-=-=


Re: [edk2-platforms][PATCH V2 1/1] Features/Intel/PlatformPayloadPkg: add platform payload FV

Isaac Oram
 

Pushed as 60053f3077..edc718521e

-----Original Message-----
From: Chaganty, Rangasai V <rangasai.v.chaganty@...>
Sent: Wednesday, August 3, 2022 2:57 PM
To: Oram, Isaac W <isaac.w.oram@...>; Dong, Guo <guo.dong@...>; devel@edk2.groups.io
Cc: Kinney, Michael D <michael.d.kinney@...>; Ni, Ray <ray.ni@...>; Rhodes, Sean <sean@...>; Desimone, Nathaniel L <nathaniel.l.desimone@...>; Gao, Liming <gaoliming@...>
Subject: RE: [edk2-devel][edk2-platforms][PATCH V2 1/1] Features/Intel/PlatformPayloadPkg: add platform payload FV

Reviewed-by: Sai Chaganty <rangasai.v.chaganty@...>

-----Original Message-----
From: Oram, Isaac W <isaac.w.oram@...>
Sent: Tuesday, May 10, 2022 4:41 PM
To: Dong, Guo <guo.dong@...>; devel@edk2.groups.io
Cc: Kinney, Michael D <michael.d.kinney@...>; Ni, Ray <ray.ni@...>; Rhodes, Sean <sean@...>; Desimone, Nathaniel L <nathaniel.l.desimone@...>; Chaganty, Rangasai V <rangasai.v.chaganty@...>; Gao, Liming <gaoliming@...>; Oram, Isaac W <isaac.w.oram@...>
Subject: RE: [edk2-devel][edk2-platforms][PATCH V2 1/1] Features/Intel/PlatformPayloadPkg: add platform payload FV

Added Features/Intel maintainers for review.

-----Original Message-----
From: Dong, Guo <guo.dong@...>
Sent: Friday, May 6, 2022 5:49 PM
To: devel@edk2.groups.io
Cc: Dong, Guo <guo.dong@...>; Kinney, Michael D <michael.d.kinney@...>; Ni, Ray <ray.ni@...>; Rhodes, Sean <sean@...>; Oram, Isaac W <isaac.w.oram@...>
Subject: [edk2-devel][edk2-platforms][PATCH V2 1/1] Features/Intel/PlatformPayloadPkg: add platform payload FV

From: Guo Dong <guo.dong@...>

UefiPayloadPkg in EDK2 repo was added SMM variable support for Intel
platform with SPI flash. But some of the modules for SMM variable are
Intel PCH specific (e.g. SPI library, SMM PCH module), so move these
modules into edk2-platforms repo.

A platform payload FV could be built from PlatformPayloadPkg which works
on Intel platforms (e.g.. ICX, APL, CML, CFL, KBL, TGL, ADL, etc.) with
SMM variable. This platform payload FV could be added into universal UEFI
payload built from EDK2 UefiPayloadPkg.

The steps to build a complete payload (use windows host as example):

set WORKSPACE=c:\payload
set PACKAGES_PATH=C:\payload\edk2;C:\payload\edk2-platforms\Platform\Intel;
C:\payload\edk2-platforms\Features\Intel;
edk2\edksetup.bat

python edk2\UefiPayloadPkg\UniversalPayloadBuild.py -t VS2019
-D SMM_SUPPORT=TRUE -DVARIABLE_SUPPORT=NONE

python edk2-platforms\Features\Intel\PlatformPayloadPkg\PlatformPayloadPkg.py
-t VS2019 -D SMM_VARIABLE=TRUE -s

The final UEFI payload generated at Build\UefiPayloadPkgX64\UniversalPayload.elf
if build success.

Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Ray Ni <ray.ni@...>
Cc: Sean Rhodes <sean@...>
Signed-off-by: Guo Dong <guo.dong@...>
Signed-off-by: Isaac Oram <isaac.w.oram@...>
---
Features/Intel/AdvancedFeaturePkg/AdvancedFeaturePkg.dsc | 5 +++++
Features/Intel/AdvancedFeaturePkg/Include/AdvancedFeatures.dsc | 7 ++++++
Features/Intel/AdvancedFeaturePkg/Include/AdvancedFeaturesPcd.dsc | 7 ++++++
Features/Intel/AdvancedFeaturePkg/Include/PostMemory.fdf | 7 ++++++
Features/Intel/AdvancedFeaturePkg/Include/PreMemory.fdf | 7 ++++++
Features/Intel/PlatformPayloadPkg/Fvb/FvbInfo.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Fvb/FvbService.c | 1088 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Fvb/FvbService.h | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Fvb/FvbServiceSmm.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Fvb/FvbSmm.inf | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Fvb/FvbSmmCommon.h | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Include/Guid/NvVariableInfoGuid.h | 24 +++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Include/Guid/SpiFlashInfoGuid.h | 38 ++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Include/Library/FlashDeviceLib.h | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Include/Library/SpiFlashLib.h | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Include/PlatformPayloadFeature.dsc | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Include/PostMemory.fdf | 20 +++++++++++++++++
Features/Intel/PlatformPayloadPkg/Include/PreMemory.fdf | 8 +++++++
Features/Intel/PlatformPayloadPkg/Library/FlashDeviceLib/FlashDeviceLib.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Library/FlashDeviceLib/FlashDeviceLib.inf | 38 ++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Library/PcdInitLib/PcdInitLib.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Library/PcdInitLib/PcdInitLib.inf | 50 +++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/PchSpi.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/RegsSpi.h | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/SpiCommon.h | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/SpiFlashLib.c | 874 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/SpiFlashLib.inf | 48 +++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/PchSmiDispatchSmm/PchSmiDispatchSmm.c | 455 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/PchSmiDispatchSmm/PchSmiDispatchSmm.h | 36 +++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/PchSmiDispatchSmm/PchSmiDispatchSmm.inf | 51 +++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.dec | 49 ++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.dsc | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.fdf | 50 +++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.py | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Features/Intel/PlatformPayloadPkg/Readme.md | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
35 files changed, 4887 insertions(+)

diff --git a/Features/Intel/AdvancedFeaturePkg/AdvancedFeaturePkg.dsc b/Features/Intel/AdvancedFeaturePkg/AdvancedFeaturePkg.dsc
index 28530b8c67..17cc3224b7 100644
--- a/Features/Intel/AdvancedFeaturePkg/AdvancedFeaturePkg.dsc
+++ b/Features/Intel/AdvancedFeaturePkg/AdvancedFeaturePkg.dsc
@@ -80,6 +80,11 @@
gUserAuthFeaturePkgTokenSpaceGuid.PcdUserAuthenticationFeatureEnable |TRUE

gVirtualKeyboardFeaturePkgTokenSpaceGuid.PcdVirtualKeyboardFeatureEnable |TRUE



+ #

+ # Individual features

+ #

+ gPlatformPayloadPkgTokenSpaceGuid.PcdPayloadPackageFeatureEnable |TRUE

+

#

# PCD that are required to be set by the build target should be configured here for test purposes

# These settings are only for the purposes of buildings, boards should follow instructions in Readme files.

diff --git a/Features/Intel/AdvancedFeaturePkg/Include/AdvancedFeatures.dsc b/Features/Intel/AdvancedFeaturePkg/Include/AdvancedFeatures.dsc
index 2b36938df6..2a93ca1ec7 100644
--- a/Features/Intel/AdvancedFeaturePkg/Include/AdvancedFeatures.dsc
+++ b/Features/Intel/AdvancedFeaturePkg/Include/AdvancedFeatures.dsc
@@ -75,3 +75,10 @@
!if gVirtualKeyboardFeaturePkgTokenSpaceGuid.PcdVirtualKeyboardFeatureEnable == TRUE

!include VirtualKeyboardFeaturePkg/Include/VirtualKeyboardFeature.dsc

!endif

+

+#

+# Individual features

+#

+!if gPlatformPayloadPkgTokenSpaceGuid.PcdPayloadPackageFeatureEnable == TRUE

+ !include PlatformPayloadPkg/Include/PlatformPayloadFeature.dsc

+!endif

diff --git a/Features/Intel/AdvancedFeaturePkg/Include/AdvancedFeaturesPcd.dsc b/Features/Intel/AdvancedFeaturePkg/Include/AdvancedFeaturesPcd.dsc
index e214175eda..8e98154f3e 100644
--- a/Features/Intel/AdvancedFeaturePkg/Include/AdvancedFeaturesPcd.dsc
+++ b/Features/Intel/AdvancedFeaturePkg/Include/AdvancedFeaturesPcd.dsc
@@ -53,6 +53,11 @@
UserAuthFeaturePkg/UserAuthFeaturePkg.dec

VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dec



+ #

+ # Individual features

+ #

+ PlatformPayloadPkg/PlatformPayloadPkg.dec

+

#

# The section below sets all PCDs to FALSE in this DSC file so the feature is not enabled by default.

# Board can set PCDs to TRUE in its DSC file to enable a subset of advanced features

@@ -76,6 +81,8 @@
gUserAuthFeaturePkgTokenSpaceGuid.PcdUserAuthenticationFeatureEnable |FALSE

gVirtualKeyboardFeaturePkgTokenSpaceGuid.PcdVirtualKeyboardFeatureEnable |FALSE



+ gPlatformPayloadPkgTokenSpaceGuid.PcdPayloadPackageFeatureEnable |FALSE

+

#

# There seems to be some build parsing odd behavior that requires this PCD to be specified even though

# the *.fdf that consumes it is dependent on the feature flag.

diff --git a/Features/Intel/AdvancedFeaturePkg/Include/PostMemory.fdf b/Features/Intel/AdvancedFeaturePkg/Include/PostMemory.fdf
index 99089f9a7b..a0975d4d43 100644
--- a/Features/Intel/AdvancedFeaturePkg/Include/PostMemory.fdf
+++ b/Features/Intel/AdvancedFeaturePkg/Include/PostMemory.fdf
@@ -76,3 +76,10 @@
!if gVirtualKeyboardFeaturePkgTokenSpaceGuid.PcdVirtualKeyboardFeatureEnable == TRUE

!include VirtualKeyboardFeaturePkg/Include/PostMemory.fdf

!endif

+

+#

+# Individual features

+#

+!if gPlatformPayloadPkgTokenSpaceGuid.PcdPayloadPackageFeatureEnable == TRUE

+ !include PlatformPayloadPkg/Include/PostMemory.fdf

+!endif

diff --git a/Features/Intel/AdvancedFeaturePkg/Include/PreMemory.fdf b/Features/Intel/AdvancedFeaturePkg/Include/PreMemory.fdf
index 1db258446a..b2b821c9c4 100644
--- a/Features/Intel/AdvancedFeaturePkg/Include/PreMemory.fdf
+++ b/Features/Intel/AdvancedFeaturePkg/Include/PreMemory.fdf
@@ -76,3 +76,10 @@
!if gVirtualKeyboardFeaturePkgTokenSpaceGuid.PcdVirtualKeyboardFeatureEnable == TRUE

!include VirtualKeyboardFeaturePkg/Include/PreMemory.fdf

!endif

+

+#

+# Individual features

+#

+!if gPlatformPayloadPkgTokenSpaceGuid.PcdPayloadPackageFeatureEnable == TRUE

+ !include PlatformPayloadPkg/Include/PreMemory.fdf

+!endif

diff --git a/Features/Intel/PlatformPayloadPkg/Fvb/FvbInfo.c b/Features/Intel/PlatformPayloadPkg/Fvb/FvbInfo.c
new file mode 100644
index 0000000000..d6dcfeb4e1
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Fvb/FvbInfo.c
@@ -0,0 +1,77 @@
+/** @file

+

+ Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#include <PiDxe.h>

+#include <Protocol/FirmwareVolumeBlock.h>

+#include <Library/PcdLib.h>

+#include <Library/DebugLib.h>

+#include <Library/BaseLib.h>

+#include <Guid/FirmwareFileSystem2.h>

+#include <Guid/SystemNvDataGuid.h>

+

+#define FVB_MEDIA_BLOCK_SIZE 0x1000

+

+typedef struct {

+ EFI_FIRMWARE_VOLUME_HEADER FvInfo;

+ EFI_FV_BLOCK_MAP_ENTRY End[1];

+} EFI_FVB2_MEDIA_INFO;

+

+//

+// This data structure contains a template of FV header which is used to restore

+// Fv header if it's corrupted.

+//

+EFI_FVB2_MEDIA_INFO mFvbMediaInfo = {

+ {

+ { 0, }, // ZeroVector[16]

+ EFI_SYSTEM_NV_DATA_FV_GUID,

+ 0,

+ EFI_FVH_SIGNATURE,

+ 0x0004feff, // check PiFirmwareVolume.h for details on EFI_FVB_ATTRIBUTES_2

+ sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY),

+ 0, // CheckSum which will be calucated dynamically.

+ 0, // ExtHeaderOffset

+ { 0, },

+ EFI_FVH_REVISION,

+ {

+ {

+ 0,

+ FVB_MEDIA_BLOCK_SIZE,

+ }

+ }

+ },

+ {

+ {

+ 0,

+ 0

+ }

+ }

+};

+

+

+/**

+ Get a heathy FV header used for variable store recovery

+

+ @retval The FV header.

+

+**/

+EFI_FIRMWARE_VOLUME_HEADER *

+GetFvHeaderTemplate (

+ VOID

+ )

+{

+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;

+ UINTN FvSize;

+

+ FvSize = PcdGet32 (PcdFlashNvStorageFtwSpareSize) * 2;

+ FvHeader = &mFvbMediaInfo.FvInfo;

+ FvHeader->FvLength = FvSize;

+ FvHeader->BlockMap[0].NumBlocks = (UINT32)(FvSize / FvHeader->BlockMap[0].Length);

+ FvHeader->Checksum = 0;

+ FvHeader->Checksum = CalculateCheckSum16 ((UINT16 *)FvHeader, FvHeader->HeaderLength);

+

+ return FvHeader;

+}

diff --git a/Features/Intel/PlatformPayloadPkg/Fvb/FvbService.c b/Features/Intel/PlatformPayloadPkg/Fvb/FvbService.c
new file mode 100644
index 0000000000..1d19f3726b
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Fvb/FvbService.c
@@ -0,0 +1,1088 @@
+/** @file

+Firmware Volume Block Driver to provide FVB service.

+

+ Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#include "FvbService.h"

+

+//

+// Global variable for this FVB driver which contains

+// the private data of all firmware volume block instances

+//

+FWB_GLOBAL mFvbModuleGlobal;

+

+FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = {

+ {

+ {

+ HARDWARE_DEVICE_PATH,

+ HW_MEMMAP_DP,

+ {

+ (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),

+ (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8)

+ }

+ },

+ EfiMemoryMappedIO,

+ (EFI_PHYSICAL_ADDRESS)0,

+ (EFI_PHYSICAL_ADDRESS)0,

+ },

+ {

+ END_DEVICE_PATH_TYPE,

+ END_ENTIRE_DEVICE_PATH_SUBTYPE,

+ {

+ END_DEVICE_PATH_LENGTH,

+ 0

+ }

+ }

+};

+

+FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = {

+ {

+ {

+ MEDIA_DEVICE_PATH,

+ MEDIA_PIWG_FW_VOL_DP,

+ {

+ (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)),

+ (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8)

+ }

+ },

+ { 0 }

+ },

+ {

+ END_DEVICE_PATH_TYPE,

+ END_ENTIRE_DEVICE_PATH_SUBTYPE,

+ {

+ END_DEVICE_PATH_LENGTH,

+ 0

+ }

+ }

+};

+

+EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = {

+ FVB_DEVICE_SIGNATURE,

+ NULL,

+ 0, // Instance

+ {

+ FvbProtocolGetAttributes,

+ FvbProtocolSetAttributes,

+ FvbProtocolGetPhysicalAddress,

+ FvbProtocolGetBlockSize,

+ FvbProtocolRead,

+ FvbProtocolWrite,

+ FvbProtocolEraseBlocks,

+ NULL

+ } // FwVolBlockInstance

+};

+

+/**

+ Get the pointer to EFI_FW_VOL_INSTANCE from the buffer pointed

+ by mFvbModuleGlobal.FvInstance based on a index.

+ Each EFI_FW_VOL_INSTANCE is with variable length as

+ we have a block map at the end of the EFI_FIRMWARE_VOLUME_HEADER.

+

+ @param[in] Instance The index of the EFI_FW_VOL_INSTANCE.

+

+ @return A pointer to EFI_FW_VOL_INSTANCE.

+

+**/

+EFI_FW_VOL_INSTANCE *

+GetFvbInstance (

+ IN UINTN Instance

+ )

+{

+ EFI_FW_VOL_INSTANCE *FwhRecord;

+

+ if ( Instance >= mFvbModuleGlobal.NumFv ) {

+ ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);

+ return NULL;

+ }

+

+ //

+ // Find the right instance of the FVB private data

+ //

+ FwhRecord = mFvbModuleGlobal.FvInstance;

+ while ( Instance > 0 ) {

+ FwhRecord = (EFI_FW_VOL_INSTANCE *)((UINTN)((UINT8 *)FwhRecord) +

+ FwhRecord->VolumeHeader.HeaderLength +

+ (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)));

+ Instance--;

+ }

+

+ return FwhRecord;

+}

+

+/**

+ Get the EFI_FVB_ATTRIBUTES_2 of a FV.

+

+ @param[in] Instance The index of the EFI_FW_VOL_INSTANCE.

+

+ @retval EFI_FVB_ATTRIBUTES_2 of the FV identified by Instance.

+

+**/

+STATIC

+EFI_FVB_ATTRIBUTES_2

+FvbGetVolumeAttributes (

+ IN UINTN Instance

+ )

+{

+ EFI_FW_VOL_INSTANCE *FwInstance;

+

+ FwInstance = GetFvbInstance (Instance);

+ ASSERT (FwInstance != NULL);

+

+ if (FwInstance == NULL) {

+ return 0;

+ }

+

+ return FwInstance->VolumeHeader.Attributes;

+}

+

+/**

+ Retrieves the starting address of an LBA in an FV. It also

+ return a few other attribut of the FV.

+

+ @param[in] Instance The index of the EFI_FW_VOL_INSTANCE.

+ @param[in] Lba The logical block address

+ @param[out] LbaAddress On output, contains the physical starting address

+ of the Lba

+ @param[out] LbaLength On output, contains the length of the block

+ @param[out] NumOfBlocks A pointer to a caller allocated UINTN in which the

+ number of consecutive blocks starting with Lba is

+ returned. All blocks in this range have a size of

+ BlockSize

+

+ @retval EFI_SUCCESS Successfully returns

+ @retval EFI_INVALID_PARAMETER Instance not found

+

+**/

+STATIC

+EFI_STATUS

+FvbGetLbaAddress (

+ IN UINTN Instance,

+ IN EFI_LBA Lba,

+ OUT UINTN *LbaAddress,

+ OUT UINTN *LbaLength,

+ OUT UINTN *NumOfBlocks

+ )

+{

+ UINT32 NumBlocks;

+ UINT32 BlockLength;

+ UINTN Offset;

+ EFI_LBA StartLba;

+ EFI_LBA NextLba;

+ EFI_FW_VOL_INSTANCE *FwhInstance;

+ EFI_FV_BLOCK_MAP_ENTRY *BlockMap;

+

+ //

+ // Find the right instance of the FVB private data

+ //

+ FwhInstance = GetFvbInstance (Instance);

+ if (FwhInstance == NULL) {

+ return EFI_INVALID_PARAMETER;

+ }

+

+ StartLba = 0;

+ Offset = 0;

+ BlockMap = &FwhInstance->VolumeHeader.BlockMap[0];

+ ASSERT (BlockMap != NULL);

+

+ //

+ // Parse the blockmap of the FV to find which map entry the Lba belongs to

+ //

+ while (TRUE) {

+ if ( BlockMap != NULL) {

+ NumBlocks = BlockMap->NumBlocks;

+ BlockLength = BlockMap->Length;

+ }

+

+ if ((NumBlocks == 0) || (BlockLength == 0)) {

+ return EFI_INVALID_PARAMETER;

+ }

+

+ NextLba = StartLba + NumBlocks;

+

+ //

+ // The map entry found

+ //

+ if ((Lba >= StartLba) && (Lba < NextLba)) {

+ Offset = Offset + (UINTN)MultU64x32 ((Lba - StartLba), BlockLength);

+ if (LbaAddress != NULL) {

+ *LbaAddress = FwhInstance->FvBase + Offset;

+ }

+

+ if (LbaLength != NULL) {

+ *LbaLength = BlockLength;

+ }

+

+ if (NumOfBlocks != NULL) {

+ *NumOfBlocks = (UINTN)(NextLba - Lba);

+ }

+

+ return EFI_SUCCESS;

+ }

+

+ StartLba = NextLba;

+ Offset = Offset + NumBlocks * BlockLength;

+ BlockMap++;

+ }

+}

+

+/**

+ Reads specified number of bytes into a buffer from the specified block

+

+ @param[in] Instance The FV instance to be read from

+ @param[in] Lba The logical block address to be read from

+ @param[in] BlockOffset Offset into the block at which to begin reading

+ @param[in, out] NumBytes Pointer that on input contains the total size of

+ the buffer. On output, it contains the total number

+ of bytes read

+ @param[in] Buffer Pointer to a caller allocated buffer that will be

+ used to hold the data read

+

+

+ @retval EFI_SUCCESS The firmware volume was read successfully and

+ contents are in Buffer

+ @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. On output,

+ NumBytes contains the total number of bytes returned

+ in Buffer

+ @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state

+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and

+ could not be read

+ @retval EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer are NULL

+

+**/

+STATIC

+EFI_STATUS

+FvbReadBlock (

+ IN UINTN Instance,

+ IN EFI_LBA Lba,

+ IN UINTN BlockOffset,

+ IN OUT UINTN *NumBytes,

+ IN UINT8 *Buffer

+ )

+{

+ EFI_FVB_ATTRIBUTES_2 Attributes;

+ UINTN LbaAddress;

+ UINTN LbaLength;

+ EFI_STATUS Status;

+ EFI_STATUS ReadStatus;

+

+ if ((NumBytes == NULL) || (Buffer == NULL)) {

+ return (EFI_INVALID_PARAMETER);

+ }

+

+ if (*NumBytes == 0) {

+ return (EFI_INVALID_PARAMETER);

+ }

+

+ Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL);

+ if (EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ Attributes = FvbGetVolumeAttributes (Instance);

+

+ if ((Attributes & EFI_FVB2_READ_STATUS) == 0) {

+ return (EFI_ACCESS_DENIED);

+ }

+

+ if (BlockOffset > LbaLength) {

+ return (EFI_INVALID_PARAMETER);

+ }

+

+ if (LbaLength < (*NumBytes + BlockOffset)) {

+ *NumBytes = (UINT32)(LbaLength - BlockOffset);

+ Status = EFI_BAD_BUFFER_SIZE;

+ }

+

+ ReadStatus = LibFvbFlashDeviceRead (LbaAddress + BlockOffset, NumBytes, Buffer);

+ if (EFI_ERROR (ReadStatus)) {

+ return ReadStatus;

+ }

+

+ return Status;

+}

+

+/**

+ Writes specified number of bytes from the input buffer to the block

+

+ @param[in] Instance The FV instance to be written to

+ @param[in] Lba The starting logical block index to write to

+ @param[in] BlockOffset Offset into the block at which to begin writing

+ @param[in, out] NumBytes Pointer that on input contains the total size of

+ the buffer. On output, it contains the total number

+ of bytes actually written

+ @param[in] Buffer Pointer to a caller allocated buffer that contains

+ the source for the write

+ @retval EFI_SUCCESS The firmware volume was written successfully

+ @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. On output,

+ NumBytes contains the total number of bytes

+ actually written

+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state

+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and

+ could not be written

+ @retval EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer are NULL

+

+**/

+EFI_STATUS

+FvbWriteBlock (

+ IN UINTN Instance,

+ IN EFI_LBA Lba,

+ IN UINTN BlockOffset,

+ IN OUT UINTN *NumBytes,

+ IN UINT8 *Buffer

+ )

+{

+ EFI_FVB_ATTRIBUTES_2 Attributes;

+ UINTN LbaAddress;

+ UINTN LbaLength;

+ EFI_STATUS Status;

+

+ if ((NumBytes == NULL) || (Buffer == NULL)) {

+ return (EFI_INVALID_PARAMETER);

+ }

+

+ if (*NumBytes == 0) {

+ return (EFI_INVALID_PARAMETER);

+ }

+

+ Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL);

+ if (EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ //

+ // Check if the FV is write enabled

+ //

+ Attributes = FvbGetVolumeAttributes (Instance);

+ if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) {

+ return EFI_ACCESS_DENIED;

+ }

+

+ //

+ // Perform boundary checks and adjust NumBytes

+ //

+ if (BlockOffset > LbaLength) {

+ return EFI_INVALID_PARAMETER;

+ }

+

+ if ( LbaLength < (*NumBytes + BlockOffset)) {

+ DEBUG ((

+ DEBUG_ERROR,

+ "FvWriteBlock: Reducing Numbytes from 0x%x to 0x%x\n",

+ *NumBytes,

+ (UINT32)(LbaLength - BlockOffset)

+ ));

+ *NumBytes = (UINT32)(LbaLength - BlockOffset);

+ return EFI_BAD_BUFFER_SIZE;

+ }

+

+ LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, FALSE);

+ Status = LibFvbFlashDeviceWrite (LbaAddress + BlockOffset, NumBytes, Buffer);

+

+ LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, TRUE);

+ WriteBackInvalidateDataCacheRange ((VOID *)(LbaAddress + BlockOffset), *NumBytes);

+ return Status;

+}

+

+/**

+ Erases and initializes a firmware volume block

+

+ @param[in] Instance The FV instance to be erased

+ @param[in] Lba The logical block index to be erased

+

+ @retval EFI_SUCCESS The erase request was successfully completed

+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state

+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and

+ could not be written. Firmware device may have been

+ partially erased

+ @retval EFI_INVALID_PARAMETER Instance not found

+

+**/

+EFI_STATUS

+FvbEraseBlock (

+ IN UINTN Instance,

+ IN EFI_LBA Lba

+ )

+{

+ EFI_FVB_ATTRIBUTES_2 Attributes;

+ UINTN LbaAddress;

+ UINTN LbaLength;

+ EFI_STATUS Status;

+

+ //

+ // Check if the FV is write enabled

+ //

+ Attributes = FvbGetVolumeAttributes (Instance);

+

+ if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) {

+ return (EFI_ACCESS_DENIED);

+ }

+

+ //

+ // Get the starting address of the block for erase.

+ //

+ Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL);

+ if (EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, FALSE);

+

+ Status = LibFvbFlashDeviceBlockErase (LbaAddress, LbaLength);

+

+ LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, TRUE);

+

+ WriteBackInvalidateDataCacheRange ((VOID *)LbaAddress, LbaLength);

+

+ return Status;

+}

+

+/**

+ Modifies the current settings of the firmware volume according to the

+ input parameter, and returns the new setting of the volume

+

+ @param[in] Instance The FV instance whose attributes is going to be

+ modified

+ @param[in, out] Attributes On input, it is a pointer to EFI_FVB_ATTRIBUTES_2

+ containing the desired firmware volume settings.

+ On successful return, it contains the new settings

+ of the firmware volume

+

+ @retval EFI_SUCCESS Successfully returns

+ @retval EFI_ACCESS_DENIED The volume setting is locked and cannot be modified

+ @retval EFI_INVALID_PARAMETER Instance not found, or The attributes requested are

+ in conflict with the capabilities as declared in the

+ firmware volume header

+

+**/

+STATIC

+EFI_STATUS

+FvbSetVolumeAttributes (

+ IN UINTN Instance,

+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes

+ )

+{

+ EFI_FW_VOL_INSTANCE *FwhInstance;

+ EFI_FVB_ATTRIBUTES_2 OldAttributes;

+ EFI_FVB_ATTRIBUTES_2 *AttribPtr;

+ EFI_FVB_ATTRIBUTES_2 UnchangedAttributes;

+ UINT32 Capabilities;

+ UINT32 OldStatus;

+ UINT32 NewStatus;

+

+ //

+ // Find the right instance of the FVB private data

+ //

+ FwhInstance = GetFvbInstance (Instance);

+ if (FwhInstance == NULL) {

+ return EFI_INVALID_PARAMETER;

+ }

+

+ AttribPtr = (EFI_FVB_ATTRIBUTES_2 *)&(FwhInstance->VolumeHeader.Attributes);

+ ASSERT (AttribPtr != NULL);

+ if ( AttribPtr == NULL) {

+ return EFI_INVALID_PARAMETER;

+ }

+

+ OldAttributes = *AttribPtr;

+ Capabilities = OldAttributes & EFI_FVB2_CAPABILITIES;

+ OldStatus = OldAttributes & EFI_FVB2_STATUS;

+ NewStatus = *Attributes & EFI_FVB2_STATUS;

+

+ UnchangedAttributes = EFI_FVB2_READ_DISABLED_CAP | \

+ EFI_FVB2_READ_ENABLED_CAP | \

+ EFI_FVB2_WRITE_DISABLED_CAP | \

+ EFI_FVB2_WRITE_ENABLED_CAP | \

+ EFI_FVB2_LOCK_CAP | \

+ EFI_FVB2_STICKY_WRITE | \

+ EFI_FVB2_MEMORY_MAPPED | \

+ EFI_FVB2_ERASE_POLARITY | \

+ EFI_FVB2_READ_LOCK_CAP | \

+ EFI_FVB2_WRITE_LOCK_CAP | \

+ EFI_FVB2_ALIGNMENT;

+

+ //

+ // Some attributes of FV is read only can *not* be set

+ //

+ if ((OldAttributes & UnchangedAttributes) ^ (*Attributes & UnchangedAttributes)) {

+ return EFI_INVALID_PARAMETER;

+ }

+

+ //

+ // If firmware volume is locked, no status bit can be updated

+ //

+ if ((OldAttributes & EFI_FVB2_LOCK_STATUS) != 0) {

+ if ((OldStatus ^ NewStatus) != 0) {

+ return EFI_ACCESS_DENIED;

+ }

+ }

+

+ //

+ // Test read disable

+ //

+ if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) {

+ if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) {

+ return EFI_INVALID_PARAMETER;

+ }

+ }

+

+ //

+ // Test read enable

+ //

+ if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) {

+ if ((NewStatus & EFI_FVB2_READ_STATUS) != 0) {

+ return EFI_INVALID_PARAMETER;

+ }

+ }

+

+ //

+ // Test write disable

+ //

+ if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) {

+ if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) {

+ return EFI_INVALID_PARAMETER;

+ }

+ }

+

+ //

+ // Test write enable

+ //

+ if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) {

+ if ((NewStatus & EFI_FVB2_WRITE_STATUS) != 0) {

+ return EFI_INVALID_PARAMETER;

+ }

+ }

+

+ //

+ // Test lock

+ //

+ if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) {

+ if ((NewStatus & EFI_FVB2_LOCK_STATUS) != 0) {

+ return EFI_INVALID_PARAMETER;

+ }

+ }

+

+ *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS));

+ *AttribPtr = (*AttribPtr) | NewStatus;

+ *Attributes = *AttribPtr;

+

+ return EFI_SUCCESS;

+}

+

+/**

+ Retrieves the physical address of the device.

+

+ @param[in] This A pointer to EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL.

+ @param[out] Address Output buffer containing the address.

+

+ @retval EFI_SUCCESS The function always return successfully.

+ @retval EFI_INVALID_PARAMETER Instance not found.

+

+**/

+EFI_STATUS

+EFIAPI

+FvbProtocolGetPhysicalAddress (

+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,

+ OUT EFI_PHYSICAL_ADDRESS *Address

+ )

+{

+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+ EFI_FW_VOL_INSTANCE *FwhInstance;

+

+ FvbDevice = FVB_DEVICE_FROM_THIS (This);

+ FwhInstance = GetFvbInstance (FvbDevice->Instance);

+ if (FwhInstance == NULL) {

+ return EFI_INVALID_PARAMETER;

+ }

+

+ *Address = FwhInstance->FvBase;

+ return EFI_SUCCESS;

+}

+

+/**

+ Retrieve the size of a logical block

+

+ @param[in] This Calling context

+ @param[in] Lba Indicates which block to return the size for.

+ @param[out] BlockSize A pointer to a caller allocated UINTN in which

+ the size of the block is returned

+ @param[out] NumOfBlocks A pointer to a caller allocated UINTN in which the

+ number of consecutive blocks starting with Lba is

+ returned. All blocks in this range have a size of

+ BlockSize

+

+ @retval EFI_SUCCESS The function always return successfully.

+

+**/

+EFI_STATUS

+EFIAPI

+FvbProtocolGetBlockSize (

+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,

+ IN EFI_LBA Lba,

+ OUT UINTN *BlockSize,

+ OUT UINTN *NumOfBlocks

+ )

+{

+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+

+ FvbDevice = FVB_DEVICE_FROM_THIS (This);

+ return FvbGetLbaAddress (FvbDevice->Instance, Lba, NULL, BlockSize, NumOfBlocks);

+}

+

+/**

+ Retrieves Volume attributes. No polarity translations are done.

+

+ @param[in] This Calling context

+ @param[out] Attributes Output buffer which contains attributes

+

+ @retval EFI_SUCCESS The function always return successfully.

+

+**/

+EFI_STATUS

+EFIAPI

+FvbProtocolGetAttributes (

+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,

+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes

+ )

+{

+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+

+ FvbDevice = FVB_DEVICE_FROM_THIS (This);

+ *Attributes = FvbGetVolumeAttributes (FvbDevice->Instance);

+

+ return EFI_SUCCESS;

+}

+

+/**

+ Sets Volume attributes. No polarity translations are done.

+

+ @param[in] This Calling context

+ @param[in, out] Attributes Output buffer which contains attributes

+

+ @retval EFI_SUCCESS The function always return successfully.

+

+**/

+EFI_STATUS

+EFIAPI

+FvbProtocolSetAttributes (

+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,

+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes

+ )

+{

+ EFI_STATUS Status;

+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+

+ FvbDevice = FVB_DEVICE_FROM_THIS (This);

+ Status = FvbSetVolumeAttributes (FvbDevice->Instance, Attributes);

+ return Status;

+}

+

+/**

+ This function erases one or more blocks as denoted by the

+ variable argument list. The entire parameter list of blocks must be verified

+ prior to erasing any blocks. If a block is requested that does not exist

+ within the associated firmware volume (it has a larger index than the last

+ block of the firmware volume), the EraseBlock() function must return

+ EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.

+

+ @param[in] This Calling context

+ @param[in] ... Starting LBA followed by Number of Lba to erase.

+ a -1 to terminate the list.

+

+ @retval EFI_SUCCESS The erase request was successfully completed

+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state

+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and

+ could not be written. Firmware device may have been

+ partially erased

+

+**/

+EFI_STATUS

+EFIAPI

+FvbProtocolEraseBlocks (

+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,

+ ...

+ )

+{

+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+ EFI_FW_VOL_INSTANCE *FwhInstance;

+ UINTN NumOfBlocks;

+ VA_LIST args;

+ EFI_LBA StartingLba;

+ UINTN NumOfLba;

+ EFI_STATUS Status;

+

+ FvbDevice = FVB_DEVICE_FROM_THIS (This);

+ FwhInstance = GetFvbInstance (FvbDevice->Instance);

+ if (FwhInstance == NULL) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+

+ NumOfBlocks = FwhInstance->NumOfBlocks;

+ VA_START (args, This);

+

+ do {

+ StartingLba = VA_ARG (args, EFI_LBA);

+ if ( StartingLba == EFI_LBA_LIST_TERMINATOR ) {

+ break;

+ }

+

+ NumOfLba = VA_ARG (args, UINT32);

+

+ //

+ // Check input parameters

+ //

+ if (NumOfLba == 0) {

+ VA_END (args);

+ return EFI_INVALID_PARAMETER;

+ }

+

+ if ((StartingLba + NumOfLba) > NumOfBlocks ) {

+ return EFI_INVALID_PARAMETER;

+ }

+ } while (1);

+

+ VA_END (args);

+

+ VA_START (args, This);

+ do {

+ StartingLba = VA_ARG (args, EFI_LBA);

+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {

+ break;

+ }

+

+ NumOfLba = VA_ARG (args, UINT32);

+

+ while ( NumOfLba > 0 ) {

+ Status = FvbEraseBlock (FvbDevice->Instance, StartingLba);

+ if ( EFI_ERROR (Status)) {

+ VA_END (args);

+ return Status;

+ }

+

+ StartingLba++;

+ NumOfLba--;

+ }

+ } while (1);

+

+ VA_END (args);

+

+ return EFI_SUCCESS;

+}

+

+/**

+ Writes data beginning at Lba:Offset from FV. The write terminates either

+ when *NumBytes of data have been written, or when a block boundary is

+ reached. *NumBytes is updated to reflect the actual number of bytes

+ written. The write opertion does not include erase. This routine will

+ attempt to write only the specified bytes. If the writes do not stick,

+ it will return an error.

+

+ @param[in] This Calling context

+ @param[in] Lba Block in which to begin write

+ @param[in] Offset Offset in the block at which to begin write

+ @param[in,out] NumBytes On input, indicates the requested write size. On

+ output, indicates the actual number of bytes written

+ @param[in] Buffer Buffer containing source data for the write.

+

+ @retval EFI_SUCCESS The firmware volume was written successfully

+ @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. On output,

+ NumBytes contains the total number of bytes

+ actually written

+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state

+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and

+ could not be written

+ @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL

+

+**/

+EFI_STATUS

+EFIAPI

+FvbProtocolWrite (

+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,

+ IN EFI_LBA Lba,

+ IN UINTN Offset,

+ IN OUT UINTN *NumBytes,

+ IN UINT8 *Buffer

+ )

+{

+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+ EFI_STATUS Status;

+

+ FvbDevice = FVB_DEVICE_FROM_THIS (This);

+ Status = FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer);

+ DEBUG ((

+ DEBUG_VERBOSE,

+ "FvbWrite: Lba: 0x%lx Offset: 0x%x NumBytes: 0x%x, Buffer: 0x%x Status:%r\n",

+ Lba,

+ Offset,

+ *NumBytes,

+ Buffer,

+ Status

+ ));

+

+ return Status;

+}

+

+/**

+ Reads data beginning at Lba:Offset from FV. The Read terminates either

+ when *NumBytes of data have been read, or when a block boundary is

+ reached. *NumBytes is updated to reflect the actual number of bytes

+ written. The write opertion does not include erase. This routine will

+ attempt to write only the specified bytes. If the writes do not stick,

+ it will return an error.

+

+ @param[in] This Calling context

+ @param[in] Lba Block in which to begin write

+ @param[in] Offset Offset in the block at which to begin write

+ @param[in,out] NumBytes On input, indicates the requested write size. On

+ output, indicates the actual number of bytes written

+ @param[out] Buffer Buffer containing source data for the write.

+

+

+Returns:

+ @retval EFI_SUCCESS The firmware volume was read successfully and

+ contents are in Buffer

+ @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. On output,

+ NumBytes contains the total number of bytes returned

+ in Buffer

+ @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state

+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and

+ could not be read

+ @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL

+

+**/

+EFI_STATUS

+EFIAPI

+FvbProtocolRead (

+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,

+ IN EFI_LBA Lba,

+ IN UINTN Offset,

+ IN OUT UINTN *NumBytes,

+ OUT UINT8 *Buffer

+ )

+{

+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+ EFI_STATUS Status;

+

+ FvbDevice = FVB_DEVICE_FROM_THIS (This);

+ Status = FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer);

+ DEBUG ((

+ DEBUG_VERBOSE,

+ "FvbRead: Lba: 0x%lx Offset: 0x%x NumBytes: 0x%x, Buffer: 0x%x, Status:%r\n",

+ Lba,

+ Offset,

+ *NumBytes,

+ Buffer,

+ Status

+ ));

+

+ return Status;

+}

+

+/**

+ Check the integrity of firmware volume header in FvBase

+

+ @param[in] FvBase A pointer to firmware volume base address.

+

+ @retval TRUE The firmware volume is consistent

+ @retval FALSE The firmware volume has corrupted.

+

+**/

+BOOLEAN

+IsFvHeaderValid (

+ IN EFI_PHYSICAL_ADDRESS FvBase

+ )

+{

+ UINT16 Sum;

+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;

+

+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvBase;

+ if (FvBase == PcdGet32 (PcdFlashNvStorageVariableBase)) {

+ if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid, sizeof (EFI_GUID)) != 0 ) {

+ DEBUG ((DEBUG_INFO, " --FileSystemGuid not match: %g\n", &FwVolHeader->FileSystemGuid));

+ return FALSE;

+ }

+ } else {

+ if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid, sizeof (EFI_GUID)) != 0 ) {

+ DEBUG ((DEBUG_INFO, " --not expected guid.\n"));

+ return FALSE;

+ }

+ }

+

+ if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||

+ (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||

+ (FwVolHeader->FvLength == ((UINTN)-1)) ||

+ ((FwVolHeader->HeaderLength & 0x01) != 0))

+ {

+ DEBUG ((DEBUG_INFO, " -- >Revision = 0x%x, Signature = 0x%x\n", FwVolHeader->Revision, FwVolHeader->Signature));

+ DEBUG ((DEBUG_INFO, " -- >FvLength = 0x%lx, HeaderLength = 0x%x\n", FwVolHeader->FvLength, FwVolHeader->HeaderLength));

+ return FALSE;

+ }

+

+ Sum = CalculateSum16 ((UINT16 *)FwVolHeader, FwVolHeader->HeaderLength);

+ if (Sum != 0) {

+ DEBUG ((DEBUG_INFO, "error: checksum: 0x%04X (expect 0x0)\n", Sum));

+ return FALSE;

+ }

+

+ return TRUE;

+}

+

+/**

+ Get intial variable data.

+

+ @param[out] VarData Valid variable data.

+ @param[out] VarSize Valid variable size.

+

+ @retval RETURN_SUCCESS Successfully found initial variable data.

+ @retval RETURN_NOT_FOUND Failed to find the variable data file from FV.

+ @retval EFI_INVALID_PARAMETER VarData or VarSize is null.

+

+**/

+EFI_STATUS

+GetInitialVariableData (

+ OUT VOID **VarData,

+ OUT UINTN *VarSize

+ )

+{

+ EFI_STATUS Status;

+ VOID *ImageData;

+ UINTN ImageSize;

+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;

+ VARIABLE_STORE_HEADER *VariableStore;

+ AUTHENTICATED_VARIABLE_HEADER *Variable;

+ UINTN VariableSize;

+ UINTN VarEndAddr;

+

+ if ((VarData == NULL) || (VarSize == NULL)) {

+ return EFI_INVALID_PARAMETER;

+ }

+

+ Status = GetSectionFromAnyFv (PcdGetPtr (PcdNvsDataFile), EFI_SECTION_RAW, 0, &ImageData, &ImageSize);

+ if (EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)ImageData;

+ VariableStore = (VARIABLE_STORE_HEADER *)((UINT8 *)ImageData + FvHeader->HeaderLength);

+ VarEndAddr = (UINTN)VariableStore + VariableStore->Size;

+ Variable = (AUTHENTICATED_VARIABLE_HEADER *)HEADER_ALIGN (VariableStore + 1);

+ *VarData = (VOID *)Variable;

+ while (((UINTN)Variable < VarEndAddr)) {

+ if (Variable->StartId != VARIABLE_DATA) {

+ break;

+ }

+

+ VariableSize = sizeof (AUTHENTICATED_VARIABLE_HEADER) + Variable->DataSize + Variable->NameSize;

+ Variable = (AUTHENTICATED_VARIABLE_HEADER *)HEADER_ALIGN ((UINTN)Variable + VariableSize);

+ }

+

+ *VarSize = (UINTN)Variable - HEADER_ALIGN (VariableStore + 1);

+

+ return EFI_SUCCESS;

+}

+

+/**

+ The function does the necessary initialization work for

+ Firmware Volume Block Driver.

+

+ @retval EFI_SUCCESS This funtion always return EFI_SUCCESS.

+ It will ASSERT on errors.

+

+**/

+EFI_STATUS

+FvbInitialize (

+ VOID

+ )

+{

+ EFI_FW_VOL_INSTANCE *FwVolInstance;

+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;

+ EFI_FV_BLOCK_MAP_ENTRY *BlockMap;

+ EFI_PHYSICAL_ADDRESS BaseAddress;

+ UINTN WriteAddr;

+ EFI_STATUS Status;

+ UINTN BufferSize;

+ UINTN Length;

+ VARIABLE_STORE_HEADER VariableStore;

+ VOID *VarData;

+

+ BaseAddress = PcdGet32 (PcdFlashNvStorageVariableBase);

+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;

+

+ //

+ // Check FV header and variable store header

+ //

+ if (!IsFvHeaderValid (BaseAddress)) {

+ //

+ // Write back a healthy FV header

+ //

+ DEBUG ((DEBUG_ERROR, "Fvb: Writing back a healthy FV header: 0x%lx\n", BaseAddress));

+ FvHeader = GetFvHeaderTemplate ();

+ LibFvbFlashDeviceBlockLock ((UINTN)BaseAddress, FvHeader->BlockMap->Length, FALSE);

+

+ Status = LibFvbFlashDeviceBlockErase ((UINTN)BaseAddress, FvHeader->BlockMap->Length);

+ ASSERT_EFI_ERROR (Status);

+

+ Length = FvHeader->HeaderLength;

+ WriteAddr = (UINTN)BaseAddress;

+ Status = LibFvbFlashDeviceWrite (WriteAddr, &Length, (UINT8 *)FvHeader);

+ WriteAddr += Length;

+ ASSERT_EFI_ERROR (Status);

+

+ //

+ // Write back variable store header

+ //

+ VariableStore.Size = PcdGet32 (PcdFlashNvStorageVariableSize) - FvHeader->HeaderLength;

+ VariableStore.Format = VARIABLE_STORE_FORMATTED;

+ VariableStore.State = VARIABLE_STORE_HEALTHY;

+ CopyGuid (&VariableStore.Signature, &gEfiAuthenticatedVariableGuid);

+ BufferSize = sizeof (VARIABLE_STORE_HEADER);

+ Status = LibFvbFlashDeviceWrite (WriteAddr, &BufferSize, (UINT8 *)&VariableStore);

+ WriteAddr += BufferSize;

+ ASSERT_EFI_ERROR (Status);

+

+ //

+ // Write initial variable data if found

+ //

+ Status = GetInitialVariableData (&VarData, &Length);

+ if (!EFI_ERROR (Status)) {

+ Status = LibFvbFlashDeviceWrite (WriteAddr, &Length, (UINT8 *)VarData);

+ ASSERT_EFI_ERROR (Status);

+ }

+

+ LibFvbFlashDeviceBlockLock ((UINTN)BaseAddress, FvHeader->BlockMap->Length, TRUE);

+ WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)BaseAddress, FvHeader->BlockMap->Length);

+ }

+

+ //

+ // Create a new FW volume instance for NVS variable

+ //

+ BufferSize = FvHeader->HeaderLength + sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER);

+ FwVolInstance = (EFI_FW_VOL_INSTANCE *)AllocateRuntimeZeroPool (BufferSize);

+ if (FwVolInstance == NULL) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+

+ FwVolInstance->FvBase = (UINTN)BaseAddress;

+ CopyMem (&FwVolInstance->VolumeHeader, FvHeader, FvHeader->HeaderLength);

+

+ //

+ // Process the block map for each FV. Assume it has same block size.

+ //

+ FwVolInstance->NumOfBlocks = 0;

+ FvHeader = &FwVolInstance->VolumeHeader;

+ for (BlockMap = FvHeader->BlockMap; BlockMap->NumBlocks != 0; BlockMap++) {

+ FwVolInstance->NumOfBlocks += BlockMap->NumBlocks;

+ }

+

+ //

+ // Add a FVB Protocol Instance

+ //

+ Status = InstallFvbProtocol (FwVolInstance, mFvbModuleGlobal.NumFv);

+ mFvbModuleGlobal.NumFv++;

+ mFvbModuleGlobal.FvInstance = FwVolInstance;

+

+ return Status;

+}

diff --git a/Features/Intel/PlatformPayloadPkg/Fvb/FvbService.h b/Features/Intel/PlatformPayloadPkg/Fvb/FvbService.h
new file mode 100644
index 0000000000..54428d8391
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Fvb/FvbService.h
@@ -0,0 +1,185 @@
+/** @file

+The header file for Firmware volume block driver.

+

+Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>

+SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef FW_BLOCK_SERVICE_H_

+#define FW_BLOCK_SERVICE_H_

+

+#include <Guid/EventGroup.h>

+#include <Guid/FirmwareFileSystem2.h>

+#include <Guid/SystemNvDataGuid.h>

+#include <Guid/VariableFormat.h>

+#include <Protocol/DevicePath.h>

+#include <Protocol/FirmwareVolumeBlock.h>

+#include <Library/UefiDriverEntryPoint.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/UefiLib.h>

+#include <Library/BaseLib.h>

+#include <Library/DebugLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/IoLib.h>

+#include <Library/CacheMaintenanceLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/PcdLib.h>

+#include <Library/FlashDeviceLib.h>

+#include <Library/DevicePathLib.h>

+#include <Library/HobLib.h>

+#include <Library/DxeServicesLib.h>

+#include <Guid/NvVariableInfoGuid.h>

+#include <Register/ArchitecturalMsr.h>

+

+//

+// Define two helper macro to extract the Capability field or Status field in FVB

+// bit fields

+//

+#define EFI_FVB2_CAPABILITIES (EFI_FVB2_READ_DISABLED_CAP |\

+ EFI_FVB2_READ_ENABLED_CAP | \

+ EFI_FVB2_WRITE_DISABLED_CAP | \

+ EFI_FVB2_WRITE_ENABLED_CAP | \

+ EFI_FVB2_LOCK_CAP \

+ )

+

+#define EFI_FVB2_STATUS (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS)

+

+typedef struct {

+ UINTN FvBase;

+ UINTN NumOfBlocks;

+ //

+ // Note!!!: VolumeHeader must be the last element

+ // of the structure.

+ //

+ EFI_FIRMWARE_VOLUME_HEADER VolumeHeader;

+} EFI_FW_VOL_INSTANCE;

+

+typedef struct {

+ EFI_FW_VOL_INSTANCE *FvInstance;

+ UINT32 NumFv;

+ UINT32 Flags;

+} FWB_GLOBAL;

+

+//

+// Fvb Protocol instance data

+//

+#define FVB_DEVICE_FROM_THIS(a) CR(a, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance, FVB_DEVICE_SIGNATURE)

+#define FVB_EXTEND_DEVICE_FROM_THIS(a) CR(a, EFI_FW_VOL_BLOCK_DEVICE, FvbExtension, FVB_DEVICE_SIGNATURE)

+#define FVB_DEVICE_SIGNATURE SIGNATURE_32('F','V','B','C')

+

+typedef struct {

+ MEDIA_FW_VOL_DEVICE_PATH FvDevPath;

+ EFI_DEVICE_PATH_PROTOCOL EndDevPath;

+} FV_PIWG_DEVICE_PATH;

+

+typedef struct {

+ MEMMAP_DEVICE_PATH MemMapDevPath;

+ EFI_DEVICE_PATH_PROTOCOL EndDevPath;

+} FV_MEMMAP_DEVICE_PATH;

+

+typedef struct {

+ UINT32 Signature;

+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;

+ UINTN Instance;

+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance;

+} EFI_FW_VOL_BLOCK_DEVICE;

+

+/**

+ Get a heathy FV header used for variable store recovery

+

+ @retval The FV header.

+

+**/

+EFI_FIRMWARE_VOLUME_HEADER *

+GetFvHeaderTemplate (

+ VOID

+ );

+

+EFI_STATUS

+InitVariableStore (

+ VOID

+ );

+

+//

+// Protocol APIs

+//

+EFI_STATUS

+EFIAPI

+FvbProtocolGetAttributes (

+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,

+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes

+ );

+

+EFI_STATUS

+EFIAPI

+FvbProtocolSetAttributes (

+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,

+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes

+ );

+

+EFI_STATUS

+EFIAPI

+FvbProtocolGetPhysicalAddress (

+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,

+ OUT EFI_PHYSICAL_ADDRESS *Address

+ );

+

+EFI_STATUS

+EFIAPI

+FvbProtocolGetBlockSize (

+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,

+ IN EFI_LBA Lba,

+ OUT UINTN *BlockSize,

+ OUT UINTN *NumOfBlocks

+ );

+

+EFI_STATUS

+EFIAPI

+FvbProtocolRead (

+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,

+ IN EFI_LBA Lba,

+ IN UINTN Offset,

+ IN OUT UINTN *NumBytes,

+ OUT UINT8 *Buffer

+ );

+

+EFI_STATUS

+EFIAPI

+FvbProtocolWrite (

+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,

+ IN EFI_LBA Lba,

+ IN UINTN Offset,

+ IN OUT UINTN *NumBytes,

+ IN UINT8 *Buffer

+ );

+

+EFI_STATUS

+EFIAPI

+FvbProtocolEraseBlocks (

+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,

+ ...

+ );

+

+EFI_FW_VOL_INSTANCE *

+GetFvbInstance (

+ IN UINTN Instance

+ );

+

+EFI_STATUS

+InstallFvbProtocol (

+ IN EFI_FW_VOL_INSTANCE *FwhInstance,

+ IN UINTN InstanceNum

+ );

+

+EFI_STATUS

+FvbInitialize (

+ VOID

+ );

+

+extern FWB_GLOBAL mFvbModuleGlobal;

+extern EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate;

+extern FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate;

+extern FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate;

+

+#endif

diff --git a/Features/Intel/PlatformPayloadPkg/Fvb/FvbServiceSmm.c b/Features/Intel/PlatformPayloadPkg/Fvb/FvbServiceSmm.c
new file mode 100644
index 0000000000..e2b87a74d2
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Fvb/FvbServiceSmm.c
@@ -0,0 +1,139 @@
+/** @file

+ SMM Firmware Volume Block Driver.

+

+ Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#include <PiSmm.h>

+#include <Library/SmmServicesTableLib.h>

+#include "FvbSmmCommon.h"

+#include "FvbService.h"

+

+/**

+ The function installs EFI_SMM_FIRMWARE_VOLUME_BLOCK protocol

+ for each FV in the system.

+

+ @param[in] FwhInstance The pointer to a FW volume instance structure,

+ which contains the information about one FV.

+ @param[in] InstanceNum The instance number which can be used as a ID

+ to locate this FwhInstance in other functions.

+

+ @retval EFI_SUCESS Installed successfully.

+ @retval Else Did not install successfully.

+

+**/

+EFI_STATUS

+InstallFvbProtocol (

+ IN EFI_FW_VOL_INSTANCE *FwhInstance,

+ IN UINTN InstanceNum

+ )

+{

+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;

+ EFI_STATUS Status;

+ EFI_HANDLE FvbHandle;

+ FV_MEMMAP_DEVICE_PATH *FvDevicePath;

+ VOID *TempPtr;

+

+ FvbDevice = (EFI_FW_VOL_BLOCK_DEVICE *)AllocateRuntimeCopyPool (

+ sizeof (EFI_FW_VOL_BLOCK_DEVICE),

+ &mFvbDeviceTemplate

+ );

+ if (FvbDevice == NULL) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+

+ FvbDevice->Instance = InstanceNum;

+ FwVolHeader = &FwhInstance->VolumeHeader;

+

+ //

+ // Set up the devicepath

+ //

+ if (FwVolHeader->ExtHeaderOffset == 0) {

+ //

+ // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH

+ //

+ TempPtr = AllocateRuntimeCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), &mFvMemmapDevicePathTemplate);

+ FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)TempPtr;

+ if (FvbDevice->DevicePath == NULL) {

+ ASSERT (FALSE);

+ return EFI_OUT_OF_RESOURCES;

+ }

+

+ FvDevicePath = (FV_MEMMAP_DEVICE_PATH *)FvbDevice->DevicePath;

+ FvDevicePath->MemMapDevPath.StartingAddress = FwhInstance->FvBase;

+ FvDevicePath->MemMapDevPath.EndingAddress = FwhInstance->FvBase + FwVolHeader->FvLength - 1;

+ } else {

+ TempPtr = AllocateRuntimeCopyPool (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate);

+ FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)TempPtr;

+ if (FvbDevice->DevicePath == NULL) {

+ ASSERT (FALSE);

+ return EFI_OUT_OF_RESOURCES;

+ }

+

+ CopyGuid (

+ &((FV_PIWG_DEVICE_PATH *)FvbDevice->DevicePath)->FvDevPath.FvName,

+ (GUID *)(UINTN)(FwhInstance->FvBase + FwVolHeader->ExtHeaderOffset)

+ );

+ }

+

+ //

+ // Install the SMM Firmware Volume Block Protocol and Device Path Protocol

+ //

+ FvbHandle = NULL;

+ Status = gSmst->SmmInstallProtocolInterface (

+ &FvbHandle,

+ &gEfiSmmFirmwareVolumeBlockProtocolGuid,

+ EFI_NATIVE_INTERFACE,

+ &FvbDevice->FwVolBlockInstance

+ );

+ ASSERT_EFI_ERROR (Status);

+

+ Status = gSmst->SmmInstallProtocolInterface (

+ &FvbHandle,

+ &gEfiDevicePathProtocolGuid,

+ EFI_NATIVE_INTERFACE,

+ FvbDevice->DevicePath

+ );

+ ASSERT_EFI_ERROR (Status);

+

+ //

+ // Notify the Fvb wrapper driver SMM fvb is ready

+ //

+ FvbHandle = NULL;

+ Status = gBS->InstallProtocolInterface (

+ &FvbHandle,

+ &gEfiSmmFirmwareVolumeBlockProtocolGuid,

+ EFI_NATIVE_INTERFACE,

+ &FvbDevice->FwVolBlockInstance

+ );

+

+ return Status;

+}

+

+/**

+ The driver entry point for SMM Firmware Volume Block Driver.

+

+ The function does the necessary initialization work

+ Firmware Volume Block Driver.

+

+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.

+ @param[in] SystemTable A pointer to the EFI system table.

+

+ @retval EFI_SUCCESS This funtion always return EFI_SUCCESS.

+ It will ASSERT on errors.

+

+**/

+EFI_STATUS

+EFIAPI

+FvbSmmInitialize (

+ IN EFI_HANDLE ImageHandle,

+ IN EFI_SYSTEM_TABLE *SystemTable

+ )

+{

+ FvbInitialize ();

+

+ return EFI_SUCCESS;

+}

diff --git a/Features/Intel/PlatformPayloadPkg/Fvb/FvbSmm.inf b/Features/Intel/PlatformPayloadPkg/Fvb/FvbSmm.inf
new file mode 100644
index 0000000000..a56654ba09
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Fvb/FvbSmm.inf
@@ -0,0 +1,66 @@
+## @file

+# This driver installs the EFI_SMM_FIRMWARE_VOLUMEN_PROTOCOL.

+#

+#

+# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>

+#

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+ INF_VERSION = 0x00010005

+ BASE_NAME = FvbSmm

+ FILE_GUID = A4EC8ADB-B7A8-47d1-8E52-EC820D0ACF6F

+ MODULE_TYPE = DXE_SMM_DRIVER

+ VERSION_STRING = 1.0

+ PI_SPECIFICATION_VERSION = 0x0001000A

+ ENTRY_POINT = FvbSmmInitialize

+

+[Sources]

+ FvbInfo.c

+ FvbService.h

+ FvbService.c

+ FvbServiceSmm.c

+ FvbSmmCommon.h

+

+[Packages]

+ MdePkg/MdePkg.dec

+ MdeModulePkg/MdeModulePkg.dec

+ UefiCpuPkg/UefiCpuPkg.dec

+ PlatformPayloadPkg/PlatformPayloadPkg.dec

+

+[LibraryClasses]

+ FlashDeviceLib

+ PcdLib

+ MemoryAllocationLib

+ CacheMaintenanceLib

+ IoLib

+ BaseMemoryLib

+ DebugLib

+ BaseLib

+ UefiLib

+ SmmServicesTableLib

+ UefiBootServicesTableLib

+ UefiDriverEntryPoint

+ HobLib

+ DxeServicesLib

+

+[Guids]

+ gEfiFirmwareFileSystem2Guid # ALWAYS_CONSUMED

+ gEfiSystemNvDataFvGuid # ALWAYS_CONSUMED

+ gEfiAuthenticatedVariableGuid

+ gNvVariableInfoGuid

+

+ [Protocols]

+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_PRODUCED

+ gEfiSmmFirmwareVolumeBlockProtocolGuid # PROTOCOL ALWAYS_PRODUCED

+

+[Pcd]

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize

+ gPlatformPayloadPkgTokenSpaceGuid.PcdNvsDataFile

+

+[Depex]

+ TRUE

diff --git a/Features/Intel/PlatformPayloadPkg/Fvb/FvbSmmCommon.h b/Features/Intel/PlatformPayloadPkg/Fvb/FvbSmmCommon.h
new file mode 100644
index 0000000000..0eadabe13f
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Fvb/FvbSmmCommon.h
@@ -0,0 +1,68 @@
+/** @file

+ The common header file for SMM FVB module.

+

+Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>

+SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef SMM_FVB_COMMON_H_

+#define SMM_FVB_COMMON_H_

+

+#include <Protocol/SmmFirmwareVolumeBlock.h>

+

+#define EFI_FUNCTION_GET_ATTRIBUTES 1

+#define EFI_FUNCTION_SET_ATTRIBUTES 2

+#define EFI_FUNCTION_GET_PHYSICAL_ADDRESS 3

+#define EFI_FUNCTION_GET_BLOCK_SIZE 4

+#define EFI_FUNCTION_READ 5

+#define EFI_FUNCTION_WRITE 6

+#define EFI_FUNCTION_ERASE_BLOCKS 7

+

+typedef struct {

+ UINTN Function;

+ EFI_STATUS ReturnStatus;

+ UINT8 Data[1];

+} SMM_FVB_COMMUNICATE_FUNCTION_HEADER;

+

+///

+/// Size of SMM communicate header, without including the payload.

+///

+#define SMM_COMMUNICATE_HEADER_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data))

+

+///

+/// Size of SMM FVB communicate function header, without including the payload.

+///

+#define SMM_FVB_COMMUNICATE_HEADER_SIZE (OFFSET_OF (SMM_FVB_COMMUNICATE_FUNCTION_HEADER, Data))

+

+typedef struct {

+ EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb;

+ EFI_FVB_ATTRIBUTES_2 Attributes;

+} SMM_FVB_ATTRIBUTES_HEADER;

+

+typedef struct {

+ EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb;

+ EFI_PHYSICAL_ADDRESS Address;

+} SMM_FVB_PHYSICAL_ADDRESS_HEADER;

+

+typedef struct {

+ EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb;

+ EFI_LBA Lba;

+ UINTN BlockSize;

+ UINTN NumOfBlocks;

+} SMM_FVB_BLOCK_SIZE_HEADER;

+

+typedef struct {

+ EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb;

+ EFI_LBA Lba;

+ UINTN Offset;

+ UINTN NumBytes;

+} SMM_FVB_READ_WRITE_HEADER;

+

+typedef struct {

+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *SmmFvb;

+ EFI_LBA StartLba;

+ UINTN NumOfLba;

+} SMM_FVB_BLOCKS_HEADER;

+

+#endif

diff --git a/Features/Intel/PlatformPayloadPkg/Include/Guid/NvVariableInfoGuid.h b/Features/Intel/PlatformPayloadPkg/Include/Guid/NvVariableInfoGuid.h
new file mode 100644
index 0000000000..fd0bd73529
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Include/Guid/NvVariableInfoGuid.h
@@ -0,0 +1,24 @@
+/** @file

+ This file defines the hob structure for the SPI flash variable info.

+

+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef NV_VARIABLE_INFO_GUID_H_

+#define NV_VARIABLE_INFO_GUID_H_

+

+//

+// NV variable hob info GUID

+//

+extern EFI_GUID gNvVariableInfoGuid;

+

+typedef struct {

+ UINT8 Revision;

+ UINT8 Reserved[3];

+ UINT32 VariableStoreBase;

+ UINT32 VariableStoreSize;

+} NV_VARIABLE_INFO;

+

+#endif

diff --git a/Features/Intel/PlatformPayloadPkg/Include/Guid/SpiFlashInfoGuid.h b/Features/Intel/PlatformPayloadPkg/Include/Guid/SpiFlashInfoGuid.h
new file mode 100644
index 0000000000..59b81851d5
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Include/Guid/SpiFlashInfoGuid.h
@@ -0,0 +1,38 @@
+/** @file

+ This file defines the hob structure for the SPI flash variable info.

+

+ Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef SPI_FLASH_INFO_GUID_H_

+#define SPI_FLASH_INFO_GUID_H_

+

+#include <IndustryStandard/Acpi.h>

+//

+// SPI Flash infor hob GUID

+//

+extern EFI_GUID gSpiFlashInfoGuid;

+

+//

+// Set this bit if platform need disable SMM write protection when writing flash

+// in SMM mode using this method: -- AsmWriteMsr32 (0x1FE, MmioRead32 (0xFED30880) | BIT0);

+//

+#define FLAGS_SPI_DISABLE_SMM_WRITE_PROTECT BIT0

+

+//

+// Reuse ACPI definition

+//

+typedef EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE PLD_GENERIC_ADDRESS;

+#define SPACE_ID_PCI_CONFIGURATION EFI_ACPI_3_0_PCI_CONFIGURATION_SPACE

+#define REGISTER_BIT_WIDTH_DWORD EFI_ACPI_3_0_DWORD

+

+typedef struct {

+ UINT8 Revision;

+ UINT8 Reserved;

+ UINT16 Flags;

+ PLD_GENERIC_ADDRESS SpiAddress;

+} SPI_FLASH_INFO;

+

+#endif

diff --git a/Features/Intel/PlatformPayloadPkg/Include/Library/FlashDeviceLib.h b/Features/Intel/PlatformPayloadPkg/Include/Library/FlashDeviceLib.h
new file mode 100644
index 0000000000..b5e8be225e
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Include/Library/FlashDeviceLib.h
@@ -0,0 +1,104 @@
+/** @file

+ Flash device library class header file.

+

+ Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef FLASHDEVICE_LIB_H_

+#define FLASHDEVICE_LIB_H_

+

+/**

+ Read NumBytes bytes of data from the address specified by

+ PAddress into Buffer.

+

+ @param[in] PAddress The starting physical address of the read.

+ @param[in,out] NumBytes On input, the number of bytes to read. On output, the number

+ of bytes actually read.

+ @param[out] Buffer The destination data buffer for the read.

+

+ @retval EFI_SUCCESS. Opertion is successful.

+ @retval EFI_DEVICE_ERROR If there is any device errors.

+

+**/

+EFI_STATUS

+EFIAPI

+LibFvbFlashDeviceRead (

+ IN UINTN PAddress,

+ IN OUT UINTN *NumBytes,

+ OUT UINT8 *Buffer

+ );

+

+/**

+ Write NumBytes bytes of data from Buffer to the address specified by

+ PAddresss.

+

+ @param[in] PAddress The starting physical address of the write.

+ @param[in,out] NumBytes On input, the number of bytes to write. On output,

+ the actual number of bytes written.

+ @param[in] Buffer The source data buffer for the write.

+

+ @retval EFI_SUCCESS. Opertion is successful.

+ @retval EFI_DEVICE_ERROR If there is any device errors.

+

+**/

+EFI_STATUS

+EFIAPI

+LibFvbFlashDeviceWrite (

+ IN UINTN PAddress,

+ IN OUT UINTN *NumBytes,

+ IN UINT8 *Buffer

+ );

+

+/**

+ Erase the block starting at PAddress.

+

+ @param[in] PAddress The starting physical address of the region to be erased.

+ @param[in] LbaLength The length of the region to be erased. This parameter is necessary

+ as the physical block size on a flash device could be different than

+ the logical block size of Firmware Volume Block protocol. Erase on

+ flash chip is always performed block by block. Therefore, the ERASE

+ operation to a logical block is converted a number of ERASE operation

+ (or a partial erase) on the hardware.

+

+ @retval EFI_SUCCESS. Opertion is successful.

+ @retval EFI_DEVICE_ERROR If there is any device errors.

+

+**/

+EFI_STATUS

+EFIAPI

+LibFvbFlashDeviceBlockErase (

+ IN UINTN PAddress,

+ IN UINTN LbaLength

+ );

+

+/**

+ Lock or unlock the block starting at PAddress.

+

+ @param[in] PAddress The starting physical address of region to be (un)locked.

+ @param[in] LbaLength The length of the region to be (un)locked. This parameter is necessary

+ as the physical block size on a flash device could be different than

+ the logical block size of Firmware Volume Block protocol. (Un)Lock on

+ flash chip is always performed block by block. Therefore, the (Un)Lock

+ operation to a logical block is converted a number of (Un)Lock operation

+ (or a partial erase) on the hardware.

+ @param[in] Lock TRUE to lock. FALSE to unlock.

+

+ @retval EFI_SUCCESS. Opertion is successful.

+

+**/

+EFI_STATUS

+EFIAPI

+LibFvbFlashDeviceBlockLock (

+ IN UINTN PAddress,

+ IN UINTN LbaLength,

+ IN BOOLEAN Lock

+ );

+

+PHYSICAL_ADDRESS

+EFIAPI

+LibFvbFlashDeviceMemoryMap (

+ );

+

+#endif

diff --git a/Features/Intel/PlatformPayloadPkg/Include/Library/SpiFlashLib.h b/Features/Intel/PlatformPayloadPkg/Include/Library/SpiFlashLib.h
new file mode 100644
index 0000000000..07f40502f2
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Include/Library/SpiFlashLib.h
@@ -0,0 +1,213 @@
+/** @file

+ PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.

+

+ Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef SPI_FLASH_LIB_H_

+#define SPI_FLASH_LIB_H_

+

+/**

+ Flash Region Type

+**/

+typedef enum {

+ FlashRegionDescriptor,

+ FlashRegionBios,

+ FlashRegionMe,

+ FlashRegionGbE,

+ FlashRegionPlatformData,

+ FlashRegionDer,

+ FlashRegionAll,

+ FlashRegionMax

+} FLASH_REGION_TYPE;

+

+/**

+ Read SFDP data from the flash part.

+

+ @param[in] ComponentNumber The Component Number for chip select

+ @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle, the max number is 64

+ @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received

+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiFlashReadSfdp (

+ IN UINT8 ComponentNumber,

+ IN UINT32 ByteCount,

+ OUT UINT8 *SfdpData

+ );

+

+/**

+ Read Jedec Id from the flash part.

+

+ @param[in] ComponentNumber The Component Number for chip select

+ @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically

+ @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received

+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiFlashReadJedecId (

+ IN UINT8 ComponentNumber,

+ IN UINT32 ByteCount,

+ OUT UINT8 *JedecId

+ );

+

+/**

+ Write the status register in the flash part.

+

+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically

+ @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiFlashWriteStatus (

+ IN UINT32 ByteCount,

+ IN UINT8 *StatusValue

+ );

+

+/**

+ Read status register in the flash part.

+

+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically

+ @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received.

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiFlashReadStatus (

+ IN UINT32 ByteCount,

+ OUT UINT8 *StatusValue

+ );

+

+/**

+ Read SC Soft Strap Values

+

+ @param[in] SoftStrapAddr SC Soft Strap address offset from FPSBA.

+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle

+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing SC Soft Strap Value.

+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiReadPchSoftStrap (

+ IN UINT32 SoftStrapAddr,

+ IN UINT32 ByteCount,

+ OUT UINT8 *SoftStrapValue

+ );

+

+/**

+ Read data from the flash part.

+

+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.

+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.

+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.

+ @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received.

+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiFlashRead (

+ IN FLASH_REGION_TYPE FlashRegionType,

+ IN UINT32 Address,

+ IN UINT32 ByteCount,

+ OUT UINT8 *Buffer

+ );

+

+/**

+ Erase some area on the flash part.

+

+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.

+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.

+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiFlashErase (

+ IN FLASH_REGION_TYPE FlashRegionType,

+ IN UINT32 Address,

+ IN UINT32 ByteCount

+ );

+

+/**

+ Write data to the flash part.

+

+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.

+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.

+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.

+ @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle.

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiFlashWrite (

+ IN FLASH_REGION_TYPE FlashRegionType,

+ IN UINT32 Address,

+ IN UINT32 ByteCount,

+ IN UINT8 *Buffer

+ );

+

+/**

+ Initialize an SPI library.

+

+ @retval EFI_SUCCESS The protocol instance was properly initialized

+ @retval EFI_NOT_FOUND The expected SPI info could not be found

+**/

+EFI_STATUS

+EFIAPI

+SpiConstructor (

+ VOID

+ );

+

+/**

+ Get the SPI region base and size, based on the enum type

+

+ @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor.

+ @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base

+ @param[out] RegionSize The size for the Region 'n'

+

+ @retval EFI_SUCCESS Read success

+ @retval EFI_INVALID_PARAMETER Invalid region type given

+ @retval EFI_DEVICE_ERROR The region is not used

+**/

+EFI_STATUS

+EFIAPI

+SpiGetRegionAddress (

+ IN FLASH_REGION_TYPE FlashRegionType,

+ OUT UINT32 *BaseAddress OPTIONAL,

+ OUT UINT32 *RegionSize OPTIONAL

+ );

+

+#endif

diff --git a/Features/Intel/PlatformPayloadPkg/Include/PlatformPayloadFeature.dsc b/Features/Intel/PlatformPayloadPkg/Include/PlatformPayloadFeature.dsc
new file mode 100644
index 0000000000..3003c563c9
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Include/PlatformPayloadFeature.dsc
@@ -0,0 +1,112 @@
+## @file

+# This is a build description file for the Payload Platform advanced feature.

+# This file should be included into another package DSC file to build this feature.

+#

+# Copyright (c) 2022, 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]

+ !ifndef $(DXE_ARCH)

+ !error "DXE_ARCH must be specified to build this feature!"

+ !endif

+

+ DEFINE SMM_VARIABLE = TRUE

+

+

+################################################################################

+#

+# PCD definitions section - list of all PCD definitions needed by this Platform.

+#

+################################################################################

+

+[PcdsPatchableInModule.X64]

+!if $(SMM_VARIABLE) == TRUE

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase |0

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize |0

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize |0

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase |0

+!endif

+

+################################################################################

+#

+# Library Class section - list of all Library Classes needed by this feature.

+#

+################################################################################

+

+[LibraryClasses]

+ !if $(SMM_VARIABLE) == TRUE

+ PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf

+ PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf

+ # (Optional for variable modules debug output

+ PlatformHookLib|UefiPayloadPkg/Library/PlatformHookLib/PlatformHookLib.inf

+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf

+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf

+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf

+ !endif

+

+[LibraryClasses.common.DXE_SMM_DRIVER,LibraryClasses.common.DXE_RUNTIME_DRIVER]

+ !if $(SMM_VARIABLE) == TRUE

+ SpiFlashLib|PlatformPayloadPkg/Library/SpiFlashLib/SpiFlashLib.inf

+ FlashDeviceLib|PlatformPayloadPkg/Library/FlashDeviceLib/FlashDeviceLib.inf

+ DxeHobListLib|UefiPayloadPkg/Library/DxeHobListLib/DxeHobListLib.inf

+ HobLib|UefiPayloadPkg/Library/DxeHobLib/DxeHobLib.inf

+ TimerLib|UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf

+ !endif

+

+################################################################################

+#

+# Component section - list of all components that need built for this feature.

+#

+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed

+# into firmware volume images. This section is just a list of modules to compile from

+# source into UEFI-compliant binaries.

+# It is the FDF file that contains information on combining binary files into firmware

+# volume images, whose concept is beyond UEFI and is described in PI specification.

+# There may also be modules listed in this section that are not required in the FDF file,

+# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be

+# generated for it, but the binary will not be put into any firmware volume.

+#

+################################################################################

+#

+# Feature DXE Components

+#

+

+# @todo: Change below line to [Components.$(DXE_ARCH)] after https://bugzilla.tianocore.org/show_bug.cgi?id=2308

+# is completed.

+[Components.X64]

+ #

+ # SMM Variable Support

+ #

+ !if $(SMM_VARIABLE) == TRUE

+ PlatformPayloadPkg/PchSmiDispatchSmm/PchSmiDispatchSmm.inf

+ PlatformPayloadPkg/Fvb/FvbSmm.inf {

+ <LibraryClasses>

+ NULL|PlatformPayloadPkg/Library/PcdInitLib/PcdInitLib.inf

+ }

+ MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {

+ <LibraryClasses>

+ NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf

+ NULL|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf

+ NULL|MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf

+ NULL|MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf

+ NULL|PlatformPayloadPkg/Library/PcdInitLib/PcdInitLib.inf

+ }

+

+ MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf {

+ <LibraryClasses>

+ NULL|PlatformPayloadPkg/Library/PcdInitLib/PcdInitLib.inf

+ }

+ MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf

+ !endif

diff --git a/Features/Intel/PlatformPayloadPkg/Include/PostMemory.fdf b/Features/Intel/PlatformPayloadPkg/Include/PostMemory.fdf
new file mode 100644
index 0000000000..54800b972c
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Include/PostMemory.fdf
@@ -0,0 +1,20 @@
+## @file

+# FDF file for post-memory ACPI Debug advanced feature modules.

+#

+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

+#

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+#

+# SMM Support

+#

+!if $(SMM_VARIABLE) == TRUE

+ INF PlatformPayloadPkg/PchSmiDispatchSmm/PchSmiDispatchSmm.inf

+ INF PlatformPayloadPkg/Fvb/FvbSmm.inf

+ INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf

+ INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf

+ INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf

+

+!endif

diff --git a/Features/Intel/PlatformPayloadPkg/Include/PreMemory.fdf b/Features/Intel/PlatformPayloadPkg/Include/PreMemory.fdf
new file mode 100644
index 0000000000..003b7a3e56
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Include/PreMemory.fdf
@@ -0,0 +1,8 @@
+## @file

+# FDF file for pre-memory payload platform advanced feature modules.

+#

+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

+#

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

diff --git a/Features/Intel/PlatformPayloadPkg/Library/FlashDeviceLib/FlashDeviceLib.c b/Features/Intel/PlatformPayloadPkg/Library/FlashDeviceLib/FlashDeviceLib.c
new file mode 100644
index 0000000000..5a27043285
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Library/FlashDeviceLib/FlashDeviceLib.c
@@ -0,0 +1,160 @@
+/** @file

+ Flash Device Library based on SPI Flash library.

+

+Copyright (c) 2018 - 2021, Intel Corporation. All rights reserved. <BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#include <PiDxe.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/DebugLib.h>

+#include <Library/SpiFlashLib.h>

+

+/**

+ Initialize spi flash device.

+

+ @retval EFI_SUCCESS The tested spi flash device is supported.

+ @retval EFI_UNSUPPORTED The tested spi flash device is not supported.

+

+**/

+EFI_STATUS

+EFIAPI

+LibFvbFlashDeviceInit (

+ VOID

+ )

+{

+ return SpiConstructor ();

+}

+

+/**

+ Read NumBytes bytes of data from the address specified by

+ PAddress into Buffer.

+

+ @param[in] PAddress The starting physical address of the read.

+ @param[in,out] NumBytes On input, the number of bytes to read. On output, the number

+ of bytes actually read.

+ @param[out] Buffer The destination data buffer for the read.

+

+ @retval EFI_SUCCESS. Opertion is successful.

+ @retval EFI_DEVICE_ERROR If there is any device errors.

+

+**/

+EFI_STATUS

+EFIAPI

+LibFvbFlashDeviceRead (

+ IN UINTN PAddress,

+ IN OUT UINTN *NumBytes,

+ OUT UINT8 *Buffer

+ )

+{

+ EFI_STATUS Status;

+ UINT32 ByteCount;

+ UINT32 RgnSize;

+ UINT32 AddrOffset;

+

+ Status = SpiGetRegionAddress (FlashRegionBios, NULL, &RgnSize);

+ if (EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ // BIOS region offset can be calculated by (PAddress - (0x100000000 - RgnSize))

+ // which equal (PAddress + RgnSize) here.

+ AddrOffset = (UINT32)((UINT32)PAddress + RgnSize);

+ ByteCount = (UINT32)*NumBytes;

+ return SpiFlashRead (FlashRegionBios, AddrOffset, ByteCount, Buffer);

+}

+

+/**

+ Write NumBytes bytes of data from Buffer to the address specified by

+ PAddresss.

+

+ @param[in] PAddress The starting physical address of the write.

+ @param[in,out] NumBytes On input, the number of bytes to write. On output,

+ the actual number of bytes written.

+ @param[in] Buffer The source data buffer for the write.

+

+ @retval EFI_SUCCESS. Opertion is successful.

+ @retval EFI_DEVICE_ERROR If there is any device errors.

+

+**/

+EFI_STATUS

+EFIAPI

+LibFvbFlashDeviceWrite (

+ IN UINTN PAddress,

+ IN OUT UINTN *NumBytes,

+ IN UINT8 *Buffer

+ )

+{

+ EFI_STATUS Status;

+ UINT32 ByteCount;

+ UINT32 RgnSize;

+ UINT32 AddrOffset;

+

+ Status = SpiGetRegionAddress (FlashRegionBios, NULL, &RgnSize);

+ if (EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ // BIOS region offset can be calculated by (PAddress - (0x100000000 - RgnSize))

+ // which equal (PAddress + RgnSize) here.

+ AddrOffset = (UINT32)((UINT32)PAddress + RgnSize);

+ ByteCount = (UINT32)*NumBytes;

+ return SpiFlashWrite (FlashRegionBios, AddrOffset, ByteCount, Buffer);

+}

+

+/**

+ Erase the block starting at PAddress.

+

+ @param[in] PAddress The starting physical address of the block to be erased.

+ This library assume that caller garantee that the PAddress

+ is at the starting address of this block.

+ @param[in] LbaLength The length of the logical block to be erased.

+

+ @retval EFI_SUCCESS. Opertion is successful.

+ @retval EFI_DEVICE_ERROR If there is any device errors.

+

+**/

+EFI_STATUS

+EFIAPI

+LibFvbFlashDeviceBlockErase (

+ IN UINTN PAddress,

+ IN UINTN LbaLength

+ )

+{

+ EFI_STATUS Status;

+ UINT32 RgnSize;

+ UINT32 AddrOffset;

+

+ Status = SpiGetRegionAddress (FlashRegionBios, NULL, &RgnSize);

+ if (EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ // BIOS region offset can be calculated by (PAddress - (0x100000000 - RgnSize))

+ // which equal (PAddress + RgnSize) here.

+ AddrOffset = (UINT32)((UINT32)PAddress + RgnSize);

+ return SpiFlashErase (FlashRegionBios, AddrOffset, (UINT32)LbaLength);

+}

+

+/**

+ Lock or unlock the block starting at PAddress.

+

+ @param[in] PAddress The starting physical address of region to be (un)locked.

+ @param[in] LbaLength The length of the logical block to be erased.

+ @param[in] Lock TRUE to lock. FALSE to unlock.

+

+ @retval EFI_SUCCESS. Opertion is successful.

+ @retval EFI_DEVICE_ERROR If there is any device errors.

+

+**/

+EFI_STATUS

+EFIAPI

+LibFvbFlashDeviceBlockLock (

+ IN UINTN PAddress,

+ IN UINTN LbaLength,

+ IN BOOLEAN Lock

+ )

+{

+ return EFI_SUCCESS;

+}

diff --git a/Features/Intel/PlatformPayloadPkg/Library/FlashDeviceLib/FlashDeviceLib.inf b/Features/Intel/PlatformPayloadPkg/Library/FlashDeviceLib/FlashDeviceLib.inf
new file mode 100644
index 0000000000..7285a37944
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Library/FlashDeviceLib/FlashDeviceLib.inf
@@ -0,0 +1,38 @@
+## @file

+# Library instace of Flash Device Library Class

+#

+# This library implement the flash device library class for the lakeport platform.

+#@copyright

+# Copyright (c) 2014 - 2021 Intel Corporation. All rights reserved

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+ INF_VERSION = 0x00010005

+ BASE_NAME = FlashDeviceLib

+ FILE_GUID = BA7CA537-1C65-4a90-9379-622A24A08141

+ MODULE_TYPE = DXE_DRIVER

+ VERSION_STRING = 1.0

+ LIBRARY_CLASS = FlashDeviceLib | DXE_SMM_DRIVER DXE_RUNTIME_DRIVER

+

+

+#

+# The following information is for reference only and not required by the build tools.

+#

+# VALID_ARCHITECTURES = IA32 X64

+#

+

+[Sources]

+ FlashDeviceLib.c

+

+[Packages]

+ MdePkg/MdePkg.dec

+ MdeModulePkg/MdeModulePkg.dec

+ PlatformPayloadPkg/PlatformPayloadPkg.dec

+

+[LibraryClasses]

+ DebugLib

+ BaseMemoryLib

+ SpiFlashLib

+

diff --git a/Features/Intel/PlatformPayloadPkg/Library/PcdInitLib/PcdInitLib.c b/Features/Intel/PlatformPayloadPkg/Library/PcdInitLib/PcdInitLib.c
new file mode 100644
index 0000000000..4ea89582f3
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Library/PcdInitLib/PcdInitLib.c
@@ -0,0 +1,89 @@
+/** @file

+

+ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#include <PiDxe.h>

+#include <Library/PcdLib.h>

+#include <Library/DebugLib.h>

+#include <Library/BaseLib.h>

+#include <Guid/SystemNvDataGuid.h>

+#include <Guid/NvVariableInfoGuid.h>

+#include <Library/HobLib.h>

+

+

+/**

+ Initialize the variable store

+

+ @retval EFI_SUCCESS if initialize the store success.

+

+**/

+EFI_STATUS

+PcdInitConstructor (

+ VOID

+ )

+{

+ EFI_STATUS Status;

+ UINT32 NvStorageBase;

+ UINT32 NvStorageSize;

+ UINT32 NvVariableSize;

+ UINT32 FtwWorkingSize;

+ UINT32 FtwSpareSize;

+ EFI_HOB_GUID_TYPE *GuidHob;

+ NV_VARIABLE_INFO *NvVariableInfo;

+

+ //

+ // Find SPI flash variable hob

+ //

+ GuidHob = GetFirstGuidHob (&gNvVariableInfoGuid);

+ if (GuidHob == NULL) {

+ ASSERT (FALSE);

+ return EFI_NOT_FOUND;

+ }

+

+ NvVariableInfo = (NV_VARIABLE_INFO *)GET_GUID_HOB_DATA (GuidHob);

+

+ //

+ // Get variable region base and size.

+ //

+ NvStorageSize = NvVariableInfo->VariableStoreSize;

+ NvStorageBase = NvVariableInfo->VariableStoreBase;

+

+ //

+ // NvStorageBase needs to be 4KB aligned, NvStorageSize needs to be 8KB * n

+ //

+ if (((NvStorageBase & (SIZE_4KB - 1)) != 0) || ((NvStorageSize & (SIZE_8KB - 1)) != 0)) {

+ return EFI_INVALID_PARAMETER;

+ }

+

+ FtwSpareSize = NvStorageSize / 2;

+ FtwWorkingSize = 0x2000;

+ NvVariableSize = NvStorageSize / 2 - FtwWorkingSize;

+ DEBUG ((DEBUG_INFO, "NvStorageBase:0x%x, NvStorageSize:0x%x\n", NvStorageBase, NvStorageSize));

+

+ if (NvVariableSize >= 0x80000000) {

+ return EFI_INVALID_PARAMETER;

+ }

+

+ Status = PcdSet32S (PcdFlashNvStorageVariableSize, NvVariableSize);

+ ASSERT_EFI_ERROR (Status);

+ Status = PcdSet32S (PcdFlashNvStorageVariableBase, NvStorageBase);

+ ASSERT_EFI_ERROR (Status);

+ Status = PcdSet64S (PcdFlashNvStorageVariableBase64, NvStorageBase);

+ ASSERT_EFI_ERROR (Status);

+

+ Status = PcdSet32S (PcdFlashNvStorageFtwWorkingSize, FtwWorkingSize);

+ ASSERT_EFI_ERROR (Status);

+ Status = PcdSet32S (PcdFlashNvStorageFtwWorkingBase, NvStorageBase + NvVariableSize);

+ ASSERT_EFI_ERROR (Status);

+

+ Status = PcdSet32S (PcdFlashNvStorageFtwSpareSize, FtwSpareSize);

+ ASSERT_EFI_ERROR (Status);

+ Status = PcdSet32S (PcdFlashNvStorageFtwSpareBase, NvStorageBase + FtwSpareSize);

+ ASSERT_EFI_ERROR (Status);

+

+ return EFI_SUCCESS;

+}

+

diff --git a/Features/Intel/PlatformPayloadPkg/Library/PcdInitLib/PcdInitLib.inf b/Features/Intel/PlatformPayloadPkg/Library/PcdInitLib/PcdInitLib.inf
new file mode 100644
index 0000000000..05411b00d8
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Library/PcdInitLib/PcdInitLib.inf
@@ -0,0 +1,50 @@
+## @file

+# Initialize patchable PCDs using HOB info

+#

+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+ INF_VERSION = 0x00010005

+ BASE_NAME = PcdInitLib

+ FILE_GUID = 2C4A8902-B55A-472E-9845-3B931CE68071

+ MODULE_TYPE = BASE

+ VERSION_STRING = 1.0

+ LIBRARY_CLASS = NULL

+ CONSTRUCTOR = PcdInitConstructor

+

+#

+# The following information is for reference only and not required by the build tools.

+#

+# VALID_ARCHITECTURES = IA32 X64

+#

+

+[Sources]

+ PcdInitLib.c

+

+[Packages]

+ MdePkg/MdePkg.dec

+ MdeModulePkg/MdeModulePkg.dec

+ PlatformPayloadPkg/PlatformPayloadPkg.dec

+

+[LibraryClasses]

+ BaseLib

+ PcdLib

+ PciLib

+ HobLib

+ BaseLib

+

+[Guids]

+ gNvVariableInfoGuid

+

+[Pcd]

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase

+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase

+

diff --git a/Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/PchSpi.c b/Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/PchSpi.c
new file mode 100644
index 0000000000..18f4a0ba3f
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/PchSpi.c
@@ -0,0 +1,170 @@
+/** @file

+

+ Copyright (c) 2017-2021, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+#include "SpiCommon.h"

+

+/**

+ Acquire SPI MMIO BAR.

+

+ @param[in] PchSpiBase PCH SPI PCI Base Address

+

+ @retval Return SPI BAR Address

+

+**/

+UINT32

+AcquireSpiBar0 (

+ IN UINTN PchSpiBase

+ )

+{

+ return MmioRead32 (PchSpiBase + R_SPI_BASE) & ~(B_SPI_BAR0_MASK);

+}

+

+/**

+ Release SPI MMIO BAR. Do nothing.

+

+ @param[in] PchSpiBase PCH SPI PCI Base Address

+

+**/

+VOID

+ReleaseSpiBar0 (

+ IN UINTN PchSpiBase

+ )

+{

+}

+

+/**

+ This function is to enable/disable BIOS Write Protect in SMM phase.

+

+ @param[in] EnableSmmSts Flag to Enable/disable Bios write protect

+

+**/

+VOID

+CpuSmmDisableBiosWriteProtect (

+ IN BOOLEAN EnableSmmSts

+ )

+{

+ UINT32 Data32;

+

+ if (EnableSmmSts) {

+ //

+ // Disable BIOS Write Protect in SMM phase.

+ //

+ Data32 = MmioRead32 ((UINTN)(0xFED30880)) | (UINT32)(BIT0);

+ AsmWriteMsr32 (0x000001FE, Data32);

+ } else {

+ //

+ // Enable BIOS Write Protect in SMM phase

+ //

+ Data32 = MmioRead32 ((UINTN)(0xFED30880)) & (UINT32)(~BIT0);

+ AsmWriteMsr32 (0x000001FE, Data32);

+ }

+

+ //

+ // Read FED30880h back to ensure the setting went through.

+ //

+ Data32 = MmioRead32 (0xFED30880);

+}

+

+/**

+ This function is a hook for Spi to disable BIOS Write Protect.

+

+ @param[in] PchSpiBase PCH SPI PCI Base Address

+ @param[in] CpuSmmBwp Need to disable CPU SMM Bios write protection or not

+

+ @retval EFI_SUCCESS The protocol instance was properly initialized

+ @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase

+

+**/

+EFI_STATUS

+EFIAPI

+DisableBiosWriteProtect (

+ IN UINTN PchSpiBase,

+ IN UINT8 CpuSmmBwp

+ )

+{

+ //

+ // Write clear BC_SYNC_SS prior to change WPD from 0 to 1.

+ //

+ MmioOr8 (PchSpiBase + R_SPI_BCR + 1, (B_SPI_BCR_SYNC_SS >> 8));

+

+ //

+ // Enable the access to the BIOS space for both read and write cycles

+ //

+ MmioOr8 (PchSpiBase + R_SPI_BCR, B_SPI_BCR_BIOSWE);

+

+ if (CpuSmmBwp != 0) {

+ CpuSmmDisableBiosWriteProtect (TRUE);

+ }

+

+ return EFI_SUCCESS;

+}

+

+/**

+ This function is a hook for Spi to enable BIOS Write Protect.

+

+ @param[in] PchSpiBase PCH SPI PCI Base Address

+ @param[in] CpuSmmBwp Need to disable CPU SMM Bios write protection or not

+

+**/

+VOID

+EFIAPI

+EnableBiosWriteProtect (

+ IN UINTN PchSpiBase,

+ IN UINT8 CpuSmmBwp

+ )

+{

+ //

+ // Disable the access to the BIOS space for write cycles

+ //

+ MmioAnd8 (PchSpiBase + R_SPI_BCR, (UINT8)(~B_SPI_BCR_BIOSWE));

+

+ if (CpuSmmBwp != 0) {

+ CpuSmmDisableBiosWriteProtect (FALSE);

+ }

+}

+

+/**

+ This function disables SPI Prefetching and caching,

+ and returns previous BIOS Control Register value before disabling.

+

+ @param[in] PchSpiBase PCH SPI PCI Base Address

+

+ @retval Previous BIOS Control Register value

+

+**/

+UINT8

+SaveAndDisableSpiPrefetchCache (

+ IN UINTN PchSpiBase

+ )

+{

+ UINT8 BiosCtlSave;

+

+ BiosCtlSave = MmioRead8 (PchSpiBase + R_SPI_BCR) & B_SPI_BCR_SRC;

+

+ MmioAndThenOr32 (

+ PchSpiBase + R_SPI_BCR, \

+ (UINT32)(~B_SPI_BCR_SRC), \

+ (UINT32)(V_SPI_BCR_SRC_PREF_DIS_CACHE_DIS << B_SPI_BCR_SRC)

+ );

+

+ return BiosCtlSave;

+}

+

+/**

+ This function updates BIOS Control Register with the given value.

+

+ @param[in] PchSpiBase PCH SPI PCI Base Address

+ @param[in] BiosCtlValue BIOS Control Register Value to be updated

+

+**/

+VOID

+SetSpiBiosControlRegister (

+ IN UINTN PchSpiBase,

+ IN UINT8 BiosCtlValue

+ )

+{

+ MmioAndThenOr8 (PchSpiBase + R_SPI_BCR, (UINT8) ~B_SPI_BCR_SRC, BiosCtlValue);

+}

diff --git a/Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/RegsSpi.h b/Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/RegsSpi.h
new file mode 100644
index 0000000000..b741904143
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/RegsSpi.h
@@ -0,0 +1,120 @@
+/** @file

+ Register names for SPI device.

+

+ Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef REGS_SPI_H_

+#define REGS_SPI_H_

+

+#define R_SPI_BASE 0x10 ///< 32-bit Memory Base Address Register

+#define B_SPI_BAR0_MASK 0x0FFF

+#define R_SPI_BCR 0xDC ///< BIOS Control Register

+#define B_SPI_BCR_SRC (BIT3 | BIT2) ///< SPI Read Configuration (SRC)

+#define V_SPI_BCR_SRC_PREF_DIS_CACHE_DIS 0x04 ///< Prefetch Disable, Cache Disable

+#define B_SPI_BCR_SYNC_SS BIT8

+#define B_SPI_BCR_BIOSWE BIT0 ///< Write Protect Disable (WPD)

+

+///

+/// SPI Host Interface Registers

+#define R_SPI_HSFS 0x04 ///< Hardware Sequencing Flash Status and Control Register(32bits)

+#define B_SPI_HSFS_FDBC_MASK 0x3F000000 ///< Flash Data Byte Count ( <= 64), Count = (Value in this field) + 1.

+#define N_SPI_HSFS_FDBC 24

+#define B_SPI_HSFS_CYCLE_MASK 0x001E0000 ///< Flash Cycle.

+#define N_SPI_HSFS_CYCLE 17

+#define V_SPI_HSFS_CYCLE_READ 0 ///< Flash Cycle Read

+#define V_SPI_HSFS_CYCLE_WRITE 2 ///< Flash Cycle Write

+#define V_SPI_HSFS_CYCLE_4K_ERASE 3 ///< Flash Cycle 4K Block Erase

+#define V_SPI_HSFS_CYCLE_64K_ERASE 4 ///< Flash Cycle 64K Sector Erase

+#define V_SPI_HSFS_CYCLE_READ_SFDP 5 ///< Flash Cycle Read SFDP

+#define V_SPI_HSFS_CYCLE_READ_JEDEC_ID 6 ///< Flash Cycle Read JEDEC ID

+#define V_SPI_HSFS_CYCLE_WRITE_STATUS 7 ///< Flash Cycle Write Status

+#define V_SPI_HSFS_CYCLE_READ_STATUS 8 ///< Flash Cycle Read Status

+#define B_SPI_HSFS_CYCLE_FGO BIT16 ///< Flash Cycle Go.

+#define B_SPI_HSFS_FDV BIT14 ///< Flash Descriptor Valid

+#define B_SPI_HSFS_SCIP BIT5 ///< SPI Cycle in Progress

+#define B_SPI_HSFS_FCERR BIT1 ///< Flash Cycle Error

+#define B_SPI_HSFS_FDONE BIT0 ///< Flash Cycle Done

+

+#define R_SPI_FADDR 0x08 ///< SPI Flash Address

+#define B_SPI_FADDR_MASK 0x07FFFFFF ///< SPI Flash Address Mask (0~26bit)

+

+#define R_SPI_FDATA00 0x10 ///< SPI Data 00 (32 bits)

+

+#define R_SPI_FRAP 0x50 ///< SPI Flash Regions Access Permissions Register

+#define B_SPI_FRAP_BRWA_PLATFORM BIT12 // < Region write access for Region4 PlatformData

+#define B_SPI_FRAP_BRWA_GBE BIT11 // < Region write access for Region3 GbE

+#define B_SPI_FRAP_BRWA_SEC BIT10 ///< Region Write Access for Region2 SEC

+#define B_SPI_FRAP_BRWA_BIOS BIT9 ///< Region Write Access for Region1 BIOS

+#define B_SPI_FRAP_BRWA_FLASHD BIT8 ///< Region Write Access for Region0 Flash Descriptor

+#define B_SPI_FRAP_BRRA_PLATFORM BIT4 ///< Region read access for Region4 PlatformData

+#define B_SPI_FRAP_BRRA_GBE BIT3 ///< Region read access for Region3 GbE

+#define B_SPI_FRAP_BRRA_SEC BIT2 ///< Region Read Access for Region2 SEC

+#define B_SPI_FRAP_BRRA_BIOS BIT1 ///< Region Read Access for Region1 BIOS

+#define B_SPI_FRAP_BRRA_FLASHD BIT0 ///< Region Read Access for Region0 Flash Descriptor

+

+#define R_SPI_FREG0_FLASHD 0x54 ///< Flash Region 0 (Flash Descriptor) (32bits)

+#define B_SPI_FREG0_LIMIT_MASK 0x7FFF0000 ///< Size, [30:16] here represents limit[26:12]

+#define N_SPI_FREG0_LIMIT 4 ///< Bit 30:16 identifies address bits [26:12]

+#define B_SPI_FREG0_BASE_MASK 0x00007FFF ///< Base, [14:0] here represents base [26:12]

+#define N_SPI_FREG0_BASE 12 ///< Bit 14:0 identifies address bits [26:2]

+

+#define R_SPI_FREG1_BIOS 0x58 ///< Flash Region 1 (BIOS) (32bits)

+#define B_SPI_FREG1_LIMIT_MASK 0x7FFF0000 ///< Size, [30:16] here represents limit[26:12]

+#define N_SPI_FREG1_LIMIT 4 ///< Bit 30:16 identifies address bits [26:12]

+#define B_SPI_FREG1_BASE_MASK 0x00007FFF ///< Base, [14:0] here represents base [26:12]

+#define N_SPI_FREG1_BASE 12 ///< Bit 14:0 identifies address bits [26:2]

+

+#define R_SPI_FREG2_SEC 0x5C ///< Flash Region 2 (SEC) (32bits)

+#define B_SPI_FREG2_LIMIT_MASK 0x7FFF0000 ///< Size, [30:16] here represents limit[26:12]

+#define N_SPI_FREG2_LIMIT 4 // < Bit 30:16 identifies address bits [26:12]

+#define B_SPI_FREG2_BASE_MASK 0x00007FFF ///< Base, [14:0] here represents base [26:12]

+#define N_SPI_FREG2_BASE 12 // < Bit 14:0 identifies address bits [26:2]

+

+#define R_SPI_FREG3_GBE 0x60 // < Flash Region 3(GbE)(32bits)

+#define B_SPI_FREG3_LIMIT_MASK 0x7FFF0000 ///< Size, [30:16] here represents limit[26:12]

+#define N_SPI_FREG3_LIMIT 4 // < Bit 30:16 identifies address bits [26:12]

+#define B_SPI_FREG3_BASE_MASK 0x00007FFF ///< Base, [14:0] here represents base [26:12]

+#define N_SPI_FREG3_BASE 12 // < Bit 14:0 identifies address bits [26:2]

+

+#define R_SPI_FREG4_PLATFORM_DATA 0x64 ///< Flash Region 4 (Platform Data) (32bits)

+#define B_SPI_FREG4_LIMIT_MASK 0x7FFF0000 ///< Size, [30:16] here represents limit[26:12]

+#define N_SPI_FREG4_LIMIT 4 ///< Bit 30:16 identifies address bits [26:12]

+#define B_SPI_FREG4_BASE_MASK 0x00007FFF ///< Base, [14:0] here represents base [26:12]

+#define N_SPI_FREG4_BASE 12 ///< Bit 14:0 identifies address bits [26:2]

+

+#define S_SPI_FREGX 4 ///< Size of Flash Region register

+#define B_SPI_FREGX_LIMIT_MASK 0x7FFF0000 ///< Flash Region Limit [30:16] represents [26:12], [11:0] are assumed to be FFFh

+#define N_SPI_FREGX_LIMIT 16 ///< Region limit bit position

+#define N_SPI_FREGX_LIMIT_REPR 12 ///< Region limit bit represents position

+#define B_SPI_FREGX_BASE_MASK 0x00007FFF ///< Flash Region Base, [14:0] represents [26:12]

+

+#define R_SPI_FDOC 0xB4 ///< Flash Descriptor Observability Control Register (32 bits)

+#define B_SPI_FDOC_FDSS_MASK (BIT14 | BIT13 | BIT12) ///< Flash Descriptor Section Select

+#define V_SPI_FDOC_FDSS_FSDM 0x0000 ///< Flash Signature and Descriptor Map

+#define V_SPI_FDOC_FDSS_COMP 0x1000 ///< Component

+#define B_SPI_FDOC_FDSI_MASK 0x0FFC ///< Flash Descriptor Section Index

+

+#define R_SPI_FDOD 0xB8 ///< Flash Descriptor Observability Data Register (32 bits)

+

+#define R_SPI_LVSCC 0xC4 ///< Vendor Specific Component Capabilities for Component 0 (32 bits)

+#define B_SPI_LVSCC_EO_64K BIT29 ///< < 64k Erase valid (EO_64k_valid)

+

+#define R_SPI_UVSCC 0xC8 ///< Vendor Specific Component Capabilities for Component 1 (32 bits)

+

+#define R_SPI_FDBAR_FLASH_MAP0 0x14 ///< Flash MAP 0

+#define N_SPI_FDBAR_NC 8 ///< < Number Of Components

+#define B_SPI_FDBAR_NC 0x00000300 ///< Number Of Components

+

+#define R_SPI_FDBAR_FLASH_MAP1 0x18 ///< Flash MAP 1

+#define B_SPI_FDBAR_FPSBA 0x00FF0000 ///< Flash Strap Base Address

+

+//

+// Flash Component Base Address (FCBA) from Flash Region 0

+//

+#define R_SPI_FCBA_FLCOMP 0x00 ///< Flash Components Register

+#define B_SPI_FLCOMP_COMP1_MASK 0x0F ///< Flash Component 1 Density

+

+#endif

diff --git a/Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/SpiCommon.h b/Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/SpiCommon.h
new file mode 100644
index 0000000000..95e9b9b1e7
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/SpiCommon.h
@@ -0,0 +1,203 @@
+/** @file

+ Header file for the SPI flash module.

+

+ Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef SPI_COMMON_LIB_H_

+#define SPI_COMMON_LIB_H_

+

+#include <PiDxe.h>

+#include <Uefi/UefiBaseType.h>

+#include <IndustryStandard/Pci30.h>

+#include <Library/IoLib.h>

+#include <Library/DebugLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/SpiFlashLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/BaseLib.h>

+#include <Library/HobLib.h>

+#include <Library/TimerLib.h>

+#include <Guid/SpiFlashInfoGuid.h>

+#include "RegsSpi.h"

+

+///

+/// Maximum time allowed while waiting the SPI cycle to complete

+/// Wait Time = 6 seconds = 6000000 microseconds

+/// Wait Period = 10 microseconds

+///

+#define WAIT_TIME 6000000 ///< Wait Time = 6 seconds = 6000000 microseconds

+#define WAIT_PERIOD 10 ///< Wait Period = 10 microseconds

+

+///

+/// Flash cycle Type

+///

+typedef enum {

+ FlashCycleRead,

+ FlashCycleWrite,

+ FlashCycleErase,

+ FlashCycleReadSfdp,

+ FlashCycleReadJedecId,

+ FlashCycleWriteStatus,

+ FlashCycleReadStatus,

+ FlashCycleMax

+} FLASH_CYCLE_TYPE;

+

+///

+/// Flash Component Number

+///

+typedef enum {

+ FlashComponent0,

+ FlashComponent1,

+ FlashComponentMax

+} FLASH_COMPONENT_NUM;

+

+///

+/// Private data structure definitions for the driver

+///

+#define SC_SPI_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'S', 'P', 'I')

+

+typedef struct {

+ UINTN Signature;

+ EFI_HANDLE Handle;

+ UINT32 AcpiTmrReg;

+ UINTN PchSpiBase;

+ UINT16 RegionPermission;

+ UINT32 SfdpVscc0Value;

+ UINT32 SfdpVscc1Value;

+ UINT32 StrapBaseAddress;

+ UINT8 NumberOfComponents;

+ UINT16 Flags;

+ UINT32 Component1StartAddr;

+} SPI_INSTANCE;

+

+/**

+ Acquire SPI MMIO BAR

+

+ @param[in] PchSpiBase PCH SPI PCI Base Address

+

+ @retval Return SPI BAR Address

+

+**/

+UINT32

+AcquireSpiBar0 (

+ IN UINTN PchSpiBase

+ );

+

+/**

+ Release SPI MMIO BAR. Do nothing.

+

+ @param[in] PchSpiBase PCH SPI PCI Base Address

+

+ @retval None

+

+**/

+VOID

+ReleaseSpiBar0 (

+ IN UINTN PchSpiBase

+ );

+

+/**

+ This function is a hook for Spi to disable BIOS Write Protect

+

+ @param[in] PchSpiBase PCH SPI PCI Base Address

+ @param[in] CpuSmmBwp Need to disable CPU SMM Bios write protection or not

+

+ @retval EFI_SUCCESS The protocol instance was properly initialized

+ @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase

+

+**/

+EFI_STATUS

+EFIAPI

+DisableBiosWriteProtect (

+ IN UINTN PchSpiBase,

+ IN UINT8 CpuSmmBwp

+ );

+

+/**

+ This function is a hook for Spi to enable BIOS Write Protect

+

+ @param[in] PchSpiBase PCH SPI PCI Base Address

+ @param[in] CpuSmmBwp Need to disable CPU SMM Bios write protection or not

+

+ @retval None

+

+**/

+VOID

+EFIAPI

+EnableBiosWriteProtect (

+ IN UINTN PchSpiBase,

+ IN UINT8 CpuSmmBwp

+ );

+

+/**

+ This function disables SPI Prefetching and caching,

+ and returns previous BIOS Control Register value before disabling.

+

+ @param[in] PchSpiBase PCH SPI PCI Base Address

+

+ @retval Previous BIOS Control Register value

+

+**/

+UINT8

+SaveAndDisableSpiPrefetchCache (

+ IN UINTN PchSpiBase

+ );

+

+/**

+ This function updates BIOS Control Register with the given value.

+

+ @param[in] PchSpiBase PCH SPI PCI Base Address

+ @param[in] BiosCtlValue BIOS Control Register Value to be updated

+

+ @retval None

+

+**/

+VOID

+SetSpiBiosControlRegister (

+ IN UINTN PchSpiBase,

+ IN UINT8 BiosCtlValue

+ );

+

+/**

+ This function sends the programmed SPI command to the slave device.

+

+ @param[in] SpiRegionType The SPI Region type for flash cycle which is listed in the Descriptor

+ @param[in] FlashCycleType The Flash SPI cycle type list in HSFC (Hardware Sequencing Flash Control Register) register

+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.

+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.

+ @param[in,out] Buffer Pointer to caller-allocated buffer containing the data received or sent during the SPI cycle.

+

+ @retval EFI_SUCCESS SPI command completes successfully.

+ @retval EFI_DEVICE_ERROR Device error, the command aborts abnormally.

+ @retval EFI_ACCESS_DENIED Some unrecognized command encountered in hardware sequencing mode

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+**/

+EFI_STATUS

+SendSpiCmd (

+ IN FLASH_REGION_TYPE FlashRegionType,

+ IN FLASH_CYCLE_TYPE FlashCycleType,

+ IN UINT32 Address,

+ IN UINT32 ByteCount,

+ IN OUT UINT8 *Buffer

+ );

+

+/**

+ Wait execution cycle to complete on the SPI interface.

+

+ @param[in] PchSpiBar0 Spi MMIO base address

+ @param[in] ErrorCheck TRUE if the SpiCycle needs to do the error check

+

+ @retval TRUE SPI cycle completed on the interface.

+ @retval FALSE Time out while waiting the SPI cycle to complete.

+ It's not safe to program the next command on the SPI interface.

+**/

+BOOLEAN

+WaitForSpiCycleComplete (

+ IN UINT32 PchSpiBar0,

+ IN BOOLEAN ErrorCheck

+ );

+

+#endif

diff --git a/Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/SpiFlashLib.c b/Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/SpiFlashLib.c
new file mode 100644
index 0000000000..22639a748c
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/SpiFlashLib.c
@@ -0,0 +1,874 @@
+/** @file

+ Generic driver using Hardware Sequencing registers.

+

+ Copyright (c) 2017-2021, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+#include "SpiCommon.h"

+

+SPI_INSTANCE *mSpiInstance = NULL;

+

+/**

+ Get SPI Instance from library global data..

+

+ @retval SpiInstance Return SPI instance

+**/

+SPI_INSTANCE *

+GetSpiInstance (

+ VOID

+ )

+{

+ if (mSpiInstance == NULL) {

+ mSpiInstance = AllocatePool (sizeof (SPI_INSTANCE));

+ if (mSpiInstance == NULL) {

+ return NULL;

+ }

+

+ ZeroMem (mSpiInstance, sizeof (SPI_INSTANCE));

+ }

+

+ return mSpiInstance;

+}

+

+/**

+ Initialize an SPI library.

+

+ @retval EFI_SUCCESS The protocol instance was properly initialized

+ @retval EFI_NOT_FOUND The expected SPI info could not be found

+**/

+EFI_STATUS

+EFIAPI

+SpiConstructor (

+ VOID

+ )

+{

+ UINT32 ScSpiBar0;

+ UINT8 Comp0Density;

+ SPI_INSTANCE *SpiInstance;

+ EFI_HOB_GUID_TYPE *GuidHob;

+ SPI_FLASH_INFO *SpiFlashInfo;

+

+ //

+ // Find SPI flash hob

+ //

+ GuidHob = GetFirstGuidHob (&gSpiFlashInfoGuid);

+ if (GuidHob == NULL) {

+ ASSERT (FALSE);

+ return EFI_NOT_FOUND;

+ }

+

+ SpiFlashInfo = (SPI_FLASH_INFO *)GET_GUID_HOB_DATA (GuidHob);

+

+ //

+ // Initialize the SPI instance

+ //

+ SpiInstance = GetSpiInstance ();

+ if (SpiInstance == NULL) {

+ return EFI_NOT_FOUND;

+ }

+

+ DEBUG ((DEBUG_INFO, "SpiInstance = %08X\n", SpiInstance));

+

+ SpiInstance->Signature = SC_SPI_PRIVATE_DATA_SIGNATURE;

+ SpiInstance->Handle = NULL;

+

+ //

+ // Check the SPI address

+ //

+ if ((SpiFlashInfo->SpiAddress.AddressSpaceId != EFI_ACPI_3_0_PCI_CONFIGURATION_SPACE) ||

+ (SpiFlashInfo->SpiAddress.RegisterBitWidth != 32) ||

+ (SpiFlashInfo->SpiAddress.RegisterBitOffset != 0) ||

+ (SpiFlashInfo->SpiAddress.AccessSize != EFI_ACPI_3_0_DWORD))

+ {

+ DEBUG ((DEBUG_ERROR, "SPI FLASH HOB is not expected. need check the hob or enhance SPI flash driver.\n"));

+ }

+

+ SpiInstance->PchSpiBase = (UINT32)(UINTN)SpiFlashInfo->SpiAddress.Address;

+ SpiInstance->Flags = SpiFlashInfo->Flags;

+ DEBUG ((DEBUG_INFO, "PchSpiBase at 0x%x\n", SpiInstance->PchSpiBase));

+

+ ScSpiBar0 = AcquireSpiBar0 (SpiInstance->PchSpiBase);

+ DEBUG ((DEBUG_INFO, "ScSpiBar0 at 0x%08X\n", ScSpiBar0));

+

+ if (ScSpiBar0 == 0) {

+ ASSERT (FALSE);

+ }

+

+ if ((MmioRead32 (ScSpiBar0 + R_SPI_HSFS) & B_SPI_HSFS_FDV) == 0) {

+ DEBUG ((DEBUG_ERROR, "SPI Flash descriptor invalid, cannot use Hardware Sequencing registers!\n"));

+ ASSERT (FALSE);

+ }

+

+ MmioOr32 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);

+ SpiInstance->RegionPermission = MmioRead16 (ScSpiBar0 + R_SPI_FRAP);

+ SpiInstance->SfdpVscc0Value = MmioRead32 (ScSpiBar0 + R_SPI_LVSCC);

+ SpiInstance->SfdpVscc1Value = MmioRead32 (ScSpiBar0 + R_SPI_UVSCC);

+

+ //

+ // Select to Flash Map 0 Register to get the number of flash Component

+ //

+ MmioAndThenOr32 (

+ ScSpiBar0 + R_SPI_FDOC,

+ (UINT32)(~(B_SPI_FDOC_FDSS_MASK | B_SPI_FDOC_FDSI_MASK)),

+ (UINT32)(V_SPI_FDOC_FDSS_FSDM | R_SPI_FDBAR_FLASH_MAP0)

+ );

+

+ //

+ // Copy Zero based Number Of Components

+ //

+ SpiInstance->NumberOfComponents = (UINT8)((MmioRead16 (ScSpiBar0 + R_SPI_FDOD) & B_SPI_FDBAR_NC) >> N_SPI_FDBAR_NC);

+

+ MmioAndThenOr32 (

+ ScSpiBar0 + R_SPI_FDOC,

+ (UINT32)(~(B_SPI_FDOC_FDSS_MASK | B_SPI_FDOC_FDSI_MASK)),

+ (UINT32)(V_SPI_FDOC_FDSS_COMP | R_SPI_FCBA_FLCOMP)

+ );

+

+ //

+ // Copy Component 0 Density

+ //

+ Comp0Density = (UINT8)MmioRead32 (ScSpiBar0 + R_SPI_FDOD) & B_SPI_FLCOMP_COMP1_MASK;

+ SpiInstance->Component1StartAddr = (UINT32)(SIZE_512KB << Comp0Density);

+

+ //

+ // Select FLASH_MAP1 to get Flash SC Strap Base Address

+ //

+ MmioAndThenOr32 (

+ (ScSpiBar0 + R_SPI_FDOC),

+ (UINT32)(~(B_SPI_FDOC_FDSS_MASK | B_SPI_FDOC_FDSI_MASK)),

+ (UINT32)(V_SPI_FDOC_FDSS_FSDM | R_SPI_FDBAR_FLASH_MAP1)

+ );

+

+ SpiInstance->StrapBaseAddress = MmioRead32 (ScSpiBar0 + R_SPI_FDOD) & B_SPI_FDBAR_FPSBA;

+

+ //

+ // Align FPSBA with address bits for the SC Strap portion of flash descriptor

+ //

+ SpiInstance->StrapBaseAddress &= B_SPI_FDBAR_FPSBA;

+

+ return EFI_SUCCESS;

+}

+

+/**

+ Read data from the flash part.

+

+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.

+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.

+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.

+ @param[out] Buffer The Pointer to caller-allocated buffer containing the data received.

+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiFlashRead (

+ IN FLASH_REGION_TYPE FlashRegionType,

+ IN UINT32 Address,

+ IN UINT32 ByteCount,

+ OUT UINT8 *Buffer

+ )

+{

+ EFI_STATUS Status;

+

+ Status = SendSpiCmd (FlashRegionType, FlashCycleRead, Address, ByteCount, Buffer);

+ return Status;

+}

+

+/**

+ Write data to the flash part.

+

+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.

+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.

+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.

+ @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle.

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiFlashWrite (

+ IN FLASH_REGION_TYPE FlashRegionType,

+ IN UINT32 Address,

+ IN UINT32 ByteCount,

+ IN UINT8 *Buffer

+ )

+{

+ EFI_STATUS Status;

+

+ Status = SendSpiCmd (FlashRegionType, FlashCycleWrite, Address, ByteCount, Buffer);

+ return Status;

+}

+

+/**

+ Erase some area on the flash part.

+

+ @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor.

+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.

+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiFlashErase (

+ IN FLASH_REGION_TYPE FlashRegionType,

+ IN UINT32 Address,

+ IN UINT32 ByteCount

+ )

+{

+ EFI_STATUS Status;

+

+ Status = SendSpiCmd (FlashRegionType, FlashCycleErase, Address, ByteCount, NULL);

+ return Status;

+}

+

+/**

+ Read SFDP data from the flash part.

+

+ @param[in] ComponentNumber The Component Number for chip select

+ @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle, the max number is 64

+ @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received

+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiFlashReadSfdp (

+ IN UINT8 ComponentNumber,

+ IN UINT32 ByteCount,

+ OUT UINT8 *SfdpData

+ )

+{

+ EFI_STATUS Status;

+ UINT32 Address;

+ SPI_INSTANCE *SpiInstance;

+

+ SpiInstance = GetSpiInstance ();

+ if (SpiInstance == NULL) {

+ return EFI_DEVICE_ERROR;

+ }

+

+ if ((ByteCount > 64) || (ComponentNumber > SpiInstance->NumberOfComponents)) {

+ ASSERT (FALSE);

+ return EFI_INVALID_PARAMETER;

+ }

+

+ Address = 0;

+ if (ComponentNumber == FlashComponent1) {

+ Address = SpiInstance->Component1StartAddr;

+ }

+

+ Status = SendSpiCmd (0, FlashCycleReadSfdp, Address, ByteCount, SfdpData);

+ return Status;

+}

+

+/**

+ Read Jedec Id from the flash part.

+

+ @param[in] ComponentNumber The Component Number for chip select

+ @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically

+ @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received

+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiFlashReadJedecId (

+ IN UINT8 ComponentNumber,

+ IN UINT32 ByteCount,

+ OUT UINT8 *JedecId

+ )

+{

+ EFI_STATUS Status;

+ UINT32 Address;

+ SPI_INSTANCE *SpiInstance;

+

+ SpiInstance = GetSpiInstance ();

+ if (SpiInstance == NULL) {

+ return EFI_DEVICE_ERROR;

+ }

+

+ if (ComponentNumber > SpiInstance->NumberOfComponents) {

+ ASSERT (FALSE);

+ return EFI_INVALID_PARAMETER;

+ }

+

+ Address = 0;

+ if (ComponentNumber == FlashComponent1) {

+ Address = SpiInstance->Component1StartAddr;

+ }

+

+ Status = SendSpiCmd (0, FlashCycleReadJedecId, Address, ByteCount, JedecId);

+ return Status;

+}

+

+/**

+ Write the status register in the flash part.

+

+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically

+ @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiFlashWriteStatus (

+ IN UINT32 ByteCount,

+ IN UINT8 *StatusValue

+ )

+{

+ EFI_STATUS Status;

+

+ Status = SendSpiCmd (0, FlashCycleWriteStatus, 0, ByteCount, StatusValue);

+ return Status;

+}

+

+/**

+ Read status register in the flash part.

+

+ @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically

+ @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received.

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiFlashReadStatus (

+ IN UINT32 ByteCount,

+ OUT UINT8 *StatusValue

+ )

+{

+ EFI_STATUS Status;

+

+ Status = SendSpiCmd (0, FlashCycleReadStatus, 0, ByteCount, StatusValue);

+ return Status;

+}

+

+/**

+ Read SC Soft Strap Values

+

+ @param[in] SoftStrapAddr SC Soft Strap address offset from FPSBA.

+ @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle

+ @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing SC Soft Strap Value.

+ It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.

+

+ @retval EFI_SUCCESS Command succeed.

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.

+**/

+EFI_STATUS

+EFIAPI

+SpiReadPchSoftStrap (

+ IN UINT32 SoftStrapAddr,

+ IN UINT32 ByteCount,

+ OUT UINT8 *SoftStrapValue

+ )

+{

+ UINT32 StrapFlashAddr;

+ EFI_STATUS Status;

+ SPI_INSTANCE *SpiInstance;

+

+ SpiInstance = GetSpiInstance ();

+ if (SpiInstance == NULL) {

+ return EFI_DEVICE_ERROR;

+ }

+

+ ASSERT (SpiInstance->StrapBaseAddress != 0);

+ //

+ // SC Strap Flash Address = FPSBA + RamAddr

+ //

+ StrapFlashAddr = SpiInstance->StrapBaseAddress + SoftStrapAddr;

+

+ Status = SendSpiCmd (FlashRegionDescriptor, FlashCycleRead, StrapFlashAddr, ByteCount, SoftStrapValue);

+ return Status;

+}

+

+/**

+ This function sends the programmed SPI command to the slave device.

+

+ @param[in] FlashRegionType The SPI Region type for flash cycle which is listed in the Descriptor

+ @param[in] FlashCycleType The Flash SPI cycle type list in HSFC (Hardware Sequencing Flash Control Register) register

+ @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions.

+ @param[in] ByteCount Number of bytes in the data portion of the SPI cycle.

+ @param[in,out] Buffer Pointer to caller-allocated buffer containing the data received or sent during the SPI cycle.

+

+ @retval EFI_SUCCESS SPI command completes successfully.

+ @retval EFI_DEVICE_ERROR Device error, the command aborts abnormally.

+ @retval EFI_ACCESS_DENIED Some unrecognized command encountered in hardware sequencing mode

+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.

+**/

+EFI_STATUS

+SendSpiCmd (

+ IN FLASH_REGION_TYPE FlashRegionType,

+ IN FLASH_CYCLE_TYPE FlashCycleType,

+ IN UINT32 Address,

+ IN UINT32 ByteCount,

+ IN OUT UINT8 *Buffer

+ )

+{

+ EFI_STATUS Status;

+ UINT32 Index;

+ UINTN SpiBaseAddress;

+ UINT32 ScSpiBar0;

+ UINT32 LimitAddress;

+ UINT32 HardwareSpiAddr;

+ UINT16 PermissionBit;

+ UINT32 SpiDataCount;

+ UINT32 FlashCycle;

+ UINT8 BiosCtlSave;

+ SPI_INSTANCE *SpiInstance;

+ UINT32 Data32;

+

+ SpiInstance = GetSpiInstance ();

+ if (SpiInstance == NULL) {

+ return EFI_DEVICE_ERROR;

+ }

+

+ Status = EFI_SUCCESS;

+ SpiBaseAddress = SpiInstance->PchSpiBase;

+ ScSpiBar0 = AcquireSpiBar0 (SpiBaseAddress);

+ BiosCtlSave = 0;

+ SpiInstance->RegionPermission = MmioRead16 (ScSpiBar0 + R_SPI_FRAP);

+

+ //

+ // If it's write cycle, disable Prefetching, Caching and disable BIOS Write Protect

+ //

+ if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == FlashCycleErase)) {

+ Status = DisableBiosWriteProtect (SpiBaseAddress, mSpiInstance->Flags & FLAGS_SPI_DISABLE_SMM_WRITE_PROTECT);

+ if (EFI_ERROR (Status)) {

+ goto SendSpiCmdEnd;

+ }

+

+ BiosCtlSave = SaveAndDisableSpiPrefetchCache (SpiBaseAddress);

+ }

+

+ //

+ // Make sure it's safe to program the command.

+ //

+ if (!WaitForSpiCycleComplete (ScSpiBar0, FALSE)) {

+ Status = EFI_DEVICE_ERROR;

+ goto SendSpiCmdEnd;

+ }

+

+ HardwareSpiAddr = Address;

+ if ((FlashCycleType == FlashCycleRead) ||

+ (FlashCycleType == FlashCycleWrite) ||

+ (FlashCycleType == FlashCycleErase))

+ {

+ switch (FlashRegionType) {

+ case FlashRegionDescriptor:

+ if (FlashCycleType == FlashCycleRead) {

+ PermissionBit = B_SPI_FRAP_BRRA_FLASHD;

+ } else {

+ PermissionBit = B_SPI_FRAP_BRWA_FLASHD;

+ }

+

+ Data32 = MmioRead32 (ScSpiBar0 + R_SPI_FREG0_FLASHD);

+ HardwareSpiAddr += (Data32 & B_SPI_FREG0_BASE_MASK) << N_SPI_FREG0_BASE;

+ LimitAddress = (Data32 & B_SPI_FREG0_LIMIT_MASK) >> N_SPI_FREG0_LIMIT;

+ break;

+

+ case FlashRegionBios:

+ if (FlashCycleType == FlashCycleRead) {

+ PermissionBit = B_SPI_FRAP_BRRA_BIOS;

+ } else {

+ PermissionBit = B_SPI_FRAP_BRWA_BIOS;

+ }

+

+ Data32 = MmioRead32 (ScSpiBar0 + R_SPI_FREG1_BIOS);

+ HardwareSpiAddr += (Data32 & B_SPI_FREG1_BASE_MASK) << N_SPI_FREG1_BASE;

+ LimitAddress = (Data32 & B_SPI_FREG1_LIMIT_MASK) >> N_SPI_FREG1_LIMIT;

+ break;

+

+ case FlashRegionMe:

+ if (FlashCycleType == FlashCycleRead) {

+ PermissionBit = B_SPI_FRAP_BRRA_SEC;

+ } else {

+ PermissionBit = B_SPI_FRAP_BRWA_SEC;

+ }

+

+ Data32 = MmioRead32 (ScSpiBar0 + R_SPI_FREG2_SEC);

+ HardwareSpiAddr += (Data32 & B_SPI_FREG2_BASE_MASK) << N_SPI_FREG2_BASE;

+ LimitAddress = (Data32 & B_SPI_FREG2_LIMIT_MASK) >> N_SPI_FREG2_LIMIT;

+ break;

+

+ case FlashRegionGbE:

+ if (FlashCycleType == FlashCycleRead) {

+ PermissionBit = B_SPI_FRAP_BRRA_GBE;

+ } else {

+ PermissionBit = B_SPI_FRAP_BRWA_GBE;

+ }

+

+ Data32 = MmioRead32 (ScSpiBar0 + R_SPI_FREG3_GBE);

+ HardwareSpiAddr += (Data32 & B_SPI_FREG3_BASE_MASK) << N_SPI_FREG3_BASE;

+ LimitAddress = (Data32 & B_SPI_FREG3_LIMIT_MASK) >> N_SPI_FREG3_LIMIT;

+ break;

+

+ case FlashRegionPlatformData:

+ if (FlashCycleType == FlashCycleRead) {

+ PermissionBit = B_SPI_FRAP_BRRA_PLATFORM;

+ } else {

+ PermissionBit = B_SPI_FRAP_BRWA_PLATFORM;

+ }

+

+ Data32 = MmioRead32 (ScSpiBar0 + R_SPI_FREG4_PLATFORM_DATA);

+ HardwareSpiAddr += (Data32 & B_SPI_FREG4_BASE_MASK) << N_SPI_FREG4_BASE;

+ LimitAddress = (Data32 & B_SPI_FREG4_LIMIT_MASK) >> N_SPI_FREG4_LIMIT;

+ break;

+

+ case FlashRegionAll:

+ //

+ // FlashRegionAll indicates address is relative to flash device

+ // No error checking for this case

+ //

+ LimitAddress = 0;

+ PermissionBit = 0;

+ break;

+

+ default:

+ Status = EFI_UNSUPPORTED;

+ goto SendSpiCmdEnd;

+ }

+

+ if ((LimitAddress != 0) && (Address > LimitAddress)) {

+ Status = EFI_INVALID_PARAMETER;

+ goto SendSpiCmdEnd;

+ }

+

+ //

+ // If the operation is read, but the region attribute is not read allowed, return error.

+ // If the operation is write, but the region attribute is not write allowed, return error.

+ //

+ if ((PermissionBit != 0) && ((SpiInstance->RegionPermission & PermissionBit) == 0)) {

+ Status = EFI_ACCESS_DENIED;

+ goto SendSpiCmdEnd;

+ }

+ }

+

+ //

+ // Check for SC SPI hardware sequencing required commands

+ //

+ FlashCycle = 0;

+ switch (FlashCycleType) {

+ case FlashCycleRead:

+ FlashCycle = (UINT32)(V_SPI_HSFS_CYCLE_READ << N_SPI_HSFS_CYCLE);

+ break;

+

+ case FlashCycleWrite:

+ FlashCycle = (UINT32)(V_SPI_HSFS_CYCLE_WRITE << N_SPI_HSFS_CYCLE);

+ break;

+

+ case FlashCycleErase:

+ if (((ByteCount % SIZE_4KB) != 0) || ((HardwareSpiAddr % SIZE_4KB) != 0)) {

+ DEBUG ((DEBUG_ERROR, "Erase and erase size must be 4KB aligned. \n"));

+ ASSERT (FALSE);

+ Status = EFI_INVALID_PARAMETER;

+ goto SendSpiCmdEnd;

+ }

+

+ break;

+

+ case FlashCycleReadSfdp:

+ FlashCycle = (UINT32)(V_SPI_HSFS_CYCLE_READ_SFDP << N_SPI_HSFS_CYCLE);

+ break;

+

+ case FlashCycleReadJedecId:

+ FlashCycle = (UINT32)(V_SPI_HSFS_CYCLE_READ_JEDEC_ID << N_SPI_HSFS_CYCLE);

+ break;

+

+ case FlashCycleWriteStatus:

+ FlashCycle = (UINT32)(V_SPI_HSFS_CYCLE_WRITE_STATUS << N_SPI_HSFS_CYCLE);

+ break;

+

+ case FlashCycleReadStatus:

+ FlashCycle = (UINT32)(V_SPI_HSFS_CYCLE_READ_STATUS << N_SPI_HSFS_CYCLE);

+ break;

+

+ default:

+ //

+ // Unrecognized Operation

+ //

+ ASSERT (FALSE);

+ Status = EFI_INVALID_PARAMETER;

+ goto SendSpiCmdEnd;

+ break;

+ }

+

+ do {

+ SpiDataCount = ByteCount;

+ if ((FlashCycleType == FlashCycleRead) || (FlashCycleType == FlashCycleWrite)) {

+ //

+ // Trim at 256 byte boundary per operation,

+ // - SC SPI controller requires trimming at 4KB boundary

+ // - Some SPI chips require trimming at 256 byte boundary for write operation

+ // - Trimming has limited performance impact as we can read / write at most 64 byte

+ // per operation

+ //

+ if (HardwareSpiAddr + ByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {

+ SpiDataCount = (((UINT32)(HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32)(HardwareSpiAddr);

+ }

+

+ //

+ // Calculate the number of bytes to shift in/out during the SPI data cycle.

+ // Valid settings for the number of bytes during each data portion of the

+ // SC SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64

+ //

+ if (SpiDataCount >= 64) {

+ SpiDataCount = 64;

+ } else if ((SpiDataCount &~0x07) != 0) {

+ SpiDataCount = SpiDataCount &~0x07;

+ }

+ }

+

+ if (FlashCycleType == FlashCycleErase) {

+ if (((ByteCount / SIZE_64KB) != 0) &&

+ ((ByteCount % SIZE_64KB) == 0) &&

+ ((HardwareSpiAddr % SIZE_64KB) == 0))

+ {

+ if (HardwareSpiAddr < SpiInstance->Component1StartAddr) {

+ //

+ // Check whether Component0 support 64k Erase

+ //

+ if ((SpiInstance->SfdpVscc0Value & B_SPI_LVSCC_EO_64K) != 0) {

+ SpiDataCount = SIZE_64KB;

+ } else {

+ SpiDataCount = SIZE_4KB;

+ }

+ } else {

+ //

+ // Check whether Component1 support 64k Erase

+ //

+ if ((SpiInstance->SfdpVscc1Value & B_SPI_LVSCC_EO_64K) != 0) {

+ SpiDataCount = SIZE_64KB;

+ } else {

+ SpiDataCount = SIZE_4KB;

+ }

+ }

+ } else {

+ SpiDataCount = SIZE_4KB;

+ }

+

+ if (SpiDataCount == SIZE_4KB) {

+ FlashCycle = (UINT32)(V_SPI_HSFS_CYCLE_4K_ERASE << N_SPI_HSFS_CYCLE);

+ } else {

+ FlashCycle = (UINT32)(V_SPI_HSFS_CYCLE_64K_ERASE << N_SPI_HSFS_CYCLE);

+ }

+ }

+

+ //

+ // If it's write cycle, load data into the SPI data buffer.

+ //

+ if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == FlashCycleWriteStatus)) {

+ if ((SpiDataCount & 0x07) != 0) {

+ //

+ // Use Byte write if Data Count is 0, 1, 2, 3, 4, 5, 6, 7

+ //

+ for (Index = 0; Index < SpiDataCount; Index++) {

+ MmioWrite8 (ScSpiBar0 + R_SPI_FDATA00 + Index, Buffer[Index]);

+ }

+ } else {

+ //

+ // Use Dword write if Data Count is 8, 16, 24, 32, 40, 48, 56, 64

+ //

+ for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {

+ MmioWrite32 (ScSpiBar0 + R_SPI_FDATA00 + Index, *(UINT32 *)(Buffer + Index));

+ }

+ }

+ }

+

+ //

+ // Set the Flash Address

+ //

+ MmioWrite32 (ScSpiBar0 + R_SPI_FADDR, (UINT32)(HardwareSpiAddr & B_SPI_FADDR_MASK));

+

+ //

+ // Set Data count, Flash cycle, and Set Go bit to start a cycle

+ //

+ MmioAndThenOr32 (

+ ScSpiBar0 + R_SPI_HSFS,

+ (UINT32)(~(B_SPI_HSFS_FDBC_MASK | B_SPI_HSFS_CYCLE_MASK)),

+ (UINT32)(((SpiDataCount - 1) << N_SPI_HSFS_FDBC) | FlashCycle | B_SPI_HSFS_CYCLE_FGO)

+ );

+

+ //

+ // Wait for command execution complete.

+ //

+ if (!WaitForSpiCycleComplete (ScSpiBar0, TRUE)) {

+ Status = EFI_DEVICE_ERROR;

+ goto SendSpiCmdEnd;

+ }

+

+ //

+ // If it's read cycle, load data into the caller's buffer.

+ //

+ if ((FlashCycleType == FlashCycleRead) ||

+ (FlashCycleType == FlashCycleReadSfdp) ||

+ (FlashCycleType == FlashCycleReadJedecId) ||

+ (FlashCycleType == FlashCycleReadStatus))

+ {

+ if ((SpiDataCount & 0x07) != 0) {

+ //

+ // Use Byte read if Data Count is 0, 1, 2, 3, 4, 5, 6, 7

+ //

+ for (Index = 0; Index < SpiDataCount; Index++) {

+ Buffer[Index] = MmioRead8 (ScSpiBar0 + R_SPI_FDATA00 + Index);

+ }

+ } else {

+ //

+ // Use Dword read if Data Count is 8, 16, 24, 32, 40, 48, 56, 64

+ //

+ for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {

+ *(UINT32 *)(Buffer + Index) = MmioRead32 (ScSpiBar0 + R_SPI_FDATA00 + Index);

+ }

+ }

+ }

+

+ HardwareSpiAddr += SpiDataCount;

+ Buffer += SpiDataCount;

+ ByteCount -= SpiDataCount;

+ } while (ByteCount > 0);

+

+SendSpiCmdEnd:

+ ///

+ /// Restore the settings for SPI Prefetching and Caching and enable BIOS Write Protect

+ ///

+ if ((FlashCycleType == FlashCycleWrite) || (FlashCycleType == FlashCycleErase)) {

+ EnableBiosWriteProtect (SpiBaseAddress, mSpiInstance->Flags & FLAGS_SPI_DISABLE_SMM_WRITE_PROTECT);

+ SetSpiBiosControlRegister (SpiBaseAddress, BiosCtlSave);

+ }

+

+ ReleaseSpiBar0 (SpiBaseAddress);

+

+ return Status;

+}

+

+/**

+ Wait execution cycle to complete on the SPI interface.

+

+ @param[in] ScSpiBar0 Spi MMIO base address

+ @param[in] ErrorCheck TRUE if the SpiCycle needs to do the error check

+

+ @retval TRUE SPI cycle completed on the interface.

+ @retval FALSE Time out while waiting the SPI cycle to complete.

+ It's not safe to program the next command on the SPI interface.

+**/

+BOOLEAN

+WaitForSpiCycleComplete (

+ IN UINT32 ScSpiBar0,

+ IN BOOLEAN ErrorCheck

+ )

+{

+ UINT64 WaitTicks;

+ UINT64 WaitCount;

+ UINT32 Data32;

+

+ //

+ // Convert the wait period allowed into to tick count

+ //

+ WaitCount = WAIT_TIME / WAIT_PERIOD;

+ //

+ // Wait for the SPI cycle to complete.

+ //

+ for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {

+ Data32 = MmioRead32 (ScSpiBar0 + R_SPI_HSFS);

+ if ((Data32 & B_SPI_HSFS_SCIP) == 0) {

+ MmioWrite32 (ScSpiBar0 + R_SPI_HSFS, B_SPI_HSFS_FCERR | B_SPI_HSFS_FDONE);

+ if (((Data32 & B_SPI_HSFS_FCERR) != 0) && ErrorCheck) {

+ return FALSE;

+ } else {

+ return TRUE;

+ }

+ }

+

+ MicroSecondDelay (WAIT_PERIOD);

+ }

+

+ return FALSE;

+}

+

+/**

+ Get the SPI region base and size, based on the enum type

+

+ @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor.

+ @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base

+ @param[out] RegionSize The size for the Region 'n'

+

+ @retval EFI_SUCCESS Read success

+ @retval EFI_INVALID_PARAMETER Invalid region type given

+ @retval EFI_DEVICE_ERROR The region is not used

+**/

+EFI_STATUS

+EFIAPI

+SpiGetRegionAddress (

+ IN FLASH_REGION_TYPE FlashRegionType,

+ OUT UINT32 *BaseAddress OPTIONAL,

+ OUT UINT32 *RegionSize OPTIONAL

+ )

+{

+ UINT32 ScSpiBar0;

+ UINT32 ReadValue;

+ UINT32 Base;

+ SPI_INSTANCE *SpiInstance;

+

+ if (FlashRegionType >= FlashRegionMax) {

+ return EFI_INVALID_PARAMETER;

+ }

+

+ SpiInstance = GetSpiInstance ();

+ if (SpiInstance == NULL) {

+ return EFI_DEVICE_ERROR;

+ }

+

+ if (FlashRegionType == FlashRegionAll) {

+ if (BaseAddress != NULL) {

+ *BaseAddress = 0;

+ }

+

+ if (RegionSize != NULL) {

+ *RegionSize = SpiInstance->Component1StartAddr;

+ }

+

+ return EFI_SUCCESS;

+ }

+

+ ScSpiBar0 = AcquireSpiBar0 (SpiInstance->PchSpiBase);

+ ReadValue = MmioRead32 (ScSpiBar0 + R_SPI_FREG0_FLASHD + S_SPI_FREGX * (UINT32)FlashRegionType);

+ ReleaseSpiBar0 (SpiInstance->PchSpiBase);

+

+ //

+ // If the region is not used, the Region Base is 7FFFh and Region Limit is 0000h

+ //

+ if (ReadValue == B_SPI_FREGX_BASE_MASK) {

+ return EFI_DEVICE_ERROR;

+ }

+

+ Base = (ReadValue & B_SPI_FREG1_BASE_MASK) << N_SPI_FREG1_BASE;

+ if (BaseAddress != NULL) {

+ *BaseAddress = Base;

+ }

+

+ if (RegionSize != NULL) {

+ *RegionSize = ((((ReadValue & B_SPI_FREGX_LIMIT_MASK) >> N_SPI_FREGX_LIMIT) + 1) <<

+ N_SPI_FREGX_LIMIT_REPR) - Base;

+ }

+

+ return EFI_SUCCESS;

+}

diff --git a/Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/SpiFlashLib.inf b/Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/SpiFlashLib.inf
new file mode 100644
index 0000000000..fae851c12f
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Library/SpiFlashLib/SpiFlashLib.inf
@@ -0,0 +1,48 @@
+## @file

+# Library instance for SPI flash library using SPI hardware sequence

+#

+# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+ INF_VERSION = 0x00010005

+ BASE_NAME = SpiFlashLib

+ FILE_GUID = 6F96AFCB-DE89-4ca1-A63F-8703EE8FDE50

+ MODULE_TYPE = BASE

+ VERSION_STRING = 1.0

+ LIBRARY_CLASS = SpiFlashLib

+ CONSTRUCTOR = SpiConstructor

+

+#

+# The following information is for reference only and not required by the build tools.

+#

+# VALID_ARCHITECTURES = IA32 X64

+#

+

+[Sources]

+ RegsSpi.h

+ SpiCommon.h

+ PchSpi.c

+ SpiFlashLib.c

+

+[Packages]

+ MdePkg/MdePkg.dec

+ MdeModulePkg/MdeModulePkg.dec

+ PlatformPayloadPkg/PlatformPayloadPkg.dec

+

+[LibraryClasses]

+ BaseLib

+ PcdLib

+ IoLib

+ PciLib

+ HobLib

+ TimerLib

+ BaseLib

+

+[Guids]

+ gSpiFlashInfoGuid

+

+[Pcd]

+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress

diff --git a/Features/Intel/PlatformPayloadPkg/PchSmiDispatchSmm/PchSmiDispatchSmm.c b/Features/Intel/PlatformPayloadPkg/PchSmiDispatchSmm/PchSmiDispatchSmm.c
new file mode 100644
index 0000000000..7fc589303e
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/PchSmiDispatchSmm/PchSmiDispatchSmm.c
@@ -0,0 +1,455 @@
+/** @file

+ SMM SwDispatch2 Protocol.

+

+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+

+

+**/

+

+#include "PchSmiDispatchSmm.h"

+

+typedef struct {

+ UINT8 EosBitOffset;

+ UINT8 ApmBitOffset;

+ UINT32 SmiEosAddr;

+ UINT32 SmiApmStsAddr;

+} SMM_PCH_REGISTER;

+

+SMM_PCH_REGISTER mSmiPchReg;

+

+EFI_SMM_CPU_PROTOCOL *mSmmCpuProtocol;

+LIST_ENTRY mSmmSwDispatch2Queue = INITIALIZE_LIST_HEAD_VARIABLE (mSmmSwDispatch2Queue);

+

+/**

+ Find SmmSwDispatch2Context by SwSmiInputValue.

+

+ @param[in] SwSmiInputValue The value to indentify the SmmSwDispatch2 context

+

+ @return Pointer to EFI_SMM_SW_DISPATCH2_CONTEXT context

+**/

+EFI_SMM_SW_DISPATCH2_CONTEXT *

+FindContextBySwSmiInputValue (

+ IN UINTN SwSmiInputValue

+ )

+{

+ LIST_ENTRY *Node;

+ EFI_SMM_SW_DISPATCH2_CONTEXT *Dispatch2Context;

+

+ Node = mSmmSwDispatch2Queue.ForwardLink;

+ for ( ; Node != &mSmmSwDispatch2Queue; Node = Node->ForwardLink) {

+ Dispatch2Context = BASE_CR (Node, EFI_SMM_SW_DISPATCH2_CONTEXT, Link);

+ if (Dispatch2Context->SwSmiInputValue == SwSmiInputValue) {

+ return Dispatch2Context;

+ }

+ }

+

+ return NULL;

+}

+

+/**

+ Find SmmSwDispatch2Context by DispatchHandle.

+

+ @param DispatchHandle The handle to indentify the SmmSwDispatch2 context

+

+ @return Pointer to EFI_SMM_SW_DISPATCH2_CONTEXT context

+**/

+EFI_SMM_SW_DISPATCH2_CONTEXT *

+FindContextByDispatchHandle (

+ IN EFI_HANDLE DispatchHandle

+ )

+{

+ LIST_ENTRY *Node;

+ EFI_SMM_SW_DISPATCH2_CONTEXT *Dispatch2Context;

+

+ Node = mSmmSwDispatch2Queue.ForwardLink;

+ for ( ; Node != &mSmmSwDispatch2Queue; Node = Node->ForwardLink) {

+ Dispatch2Context = BASE_CR (Node, EFI_SMM_SW_DISPATCH2_CONTEXT, Link);

+ if (Dispatch2Context->DispatchHandle == DispatchHandle) {

+ return Dispatch2Context;

+ }

+ }

+

+ return NULL;

+}

+

+/**

+ Dispatch registered SMM handlers

+

+ @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().

+ @param RegisterContext Points to an optional handler context which was specified when the handler was registered.

+ @param CommBuffer A pointer to a collection of data in memory that will

+ be conveyed from a non-SMM environment into an SMM environment.

+ @param CommBufferSize The size of the CommBuffer.

+

+ @return Status Code

+

+**/

+EFI_STATUS

+SmmSwDispatcher (

+ IN EFI_HANDLE DispatchHandle,

+ IN CONST VOID *RegisterContext,

+ IN OUT VOID *CommBuffer,

+ IN OUT UINTN *CommBufferSize

+ )

+{

+ EFI_STATUS Status;

+ EFI_SMM_SW_CONTEXT SwContext;

+ UINTN Index;

+ EFI_SMM_SW_DISPATCH2_CONTEXT *Context;

+ EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction;

+ EFI_SMM_SW_REGISTER_CONTEXT DispatchContext;

+ UINTN Size;

+ EFI_SMM_SAVE_STATE_IO_INFO IoInfo;

+

+ //

+ // Construct new context

+ //

+ SwContext.SwSmiCpuIndex = 0;

+ SwContext.CommandPort = IoRead8 (SMM_CONTROL_PORT);

+ SwContext.DataPort = IoRead8 (SMM_DATA_PORT);

+

+ //

+ // Try to find which CPU trigger SWSMI

+ //

+ for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {

+ Status = mSmmCpuProtocol->ReadSaveState (

+ mSmmCpuProtocol,

+ sizeof (IoInfo),

+ EFI_SMM_SAVE_STATE_REGISTER_IO,

+ Index,

+ &IoInfo

+ );

+ if (EFI_ERROR (Status)) {

+ continue;

+ }

+

+ if (IoInfo.IoPort == SMM_CONTROL_PORT) {

+ //

+ // Great! Find it.

+ //

+ SwContext.SwSmiCpuIndex = Index;

+ DEBUG ((DEBUG_VERBOSE, "CPU index = 0x%x/0x%x\n", Index, gSmst->NumberOfCpus));

+ break;

+ }

+ }

+

+ if (SwContext.CommandPort == 0) {

+ DEBUG ((DEBUG_VERBOSE, "NOT SW SMI\n"));

+ Status = EFI_SUCCESS;

+ goto End;

+ }

+

+ //

+ // Search context

+ //

+ Context = FindContextBySwSmiInputValue (SwContext.CommandPort);

+ if (Context == NULL) {

+ DEBUG ((DEBUG_INFO, "No handler for SMI value 0x%x\n", SwContext.CommandPort));

+ Status = EFI_SUCCESS;

+ goto End;

+ }

+

+ DEBUG ((DEBUG_VERBOSE, "Prepare to call handler for 0x%x\n", SwContext.CommandPort));

+

+ //

+ // Dispatch

+ //

+ DispatchContext.SwSmiInputValue = SwContext.CommandPort;

+ Size = sizeof (SwContext);

+ DispatchFunction = (EFI_SMM_HANDLER_ENTRY_POINT2)Context->DispatchFunction;

+ Status = DispatchFunction (DispatchHandle, &DispatchContext, &SwContext, &Size);

+

+End:

+ //

+ // Clear SMI APM status

+ //

+ IoOr32 (mSmiPchReg.SmiApmStsAddr, 1 << mSmiPchReg.ApmBitOffset);

+

+ //

+ // Set EOS bit

+ //

+ IoOr32 (mSmiPchReg.SmiEosAddr, 1 << mSmiPchReg.EosBitOffset);

+

+ return Status;

+}

+

+/**

+Check the SwSmiInputValue is already used

+

+@param[in] SwSmiInputValue To indentify the SmmSwDispatch2 context

+

+@retval EFI_SUCCESS SwSmiInputValue could be used.

+@retval EFI_INVALID_PARAMETER SwSmiInputValue is already be used.

+

+**/

+EFI_STATUS

+SmiInputValueCheck (

+ IN UINTN SwSmiInputValue

+ )

+{

+ LIST_ENTRY *Node;

+ EFI_SMM_SW_DISPATCH2_CONTEXT *Dispatch2Context;

+

+ Node = mSmmSwDispatch2Queue.ForwardLink;

+ for ( ; Node != &mSmmSwDispatch2Queue; Node = Node->ForwardLink) {

+ Dispatch2Context = BASE_CR (Node, EFI_SMM_SW_DISPATCH2_CONTEXT, Link);

+ if (Dispatch2Context->SwSmiInputValue == SwSmiInputValue) {

+ return EFI_INVALID_PARAMETER;

+ }

+ }

+

+ return EFI_SUCCESS;

+}

+

+/**

+ Register a child SMI source dispatch function for the specified software SMI.

+

+ This service registers a function (DispatchFunction) which will be called when the software

+ SMI source specified by RegContext->SwSmiCpuIndex is detected. On return, DispatchHandle

+ contains a unique handle which may be used later to unregister the function using UnRegister().

+

+ @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.

+ @param[in] DispatchFunction Function to register for handler when the specified software

+ SMI is generated.

+ @param[in, out] RegContext Pointer to the dispatch function's context.

+ The caller fills this context in before calling

+ the register function to indicate to the register

+ function which Software SMI input value the

+ dispatch function should be invoked for.

+ @param[out] DispatchHandle Handle generated by the dispatcher to track the

+ function instance.

+

+ @retval EFI_SUCCESS The dispatch function has been successfully

+ registered and the SMI source has been enabled.

+ @retval EFI_DEVICE_ERROR The SW driver was unable to enable the SMI source.

+ @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The SW SMI input value

+ is not within valid range.

+ @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or SMM) to manage this

+ child.

+ @retval EFI_OUT_OF_RESOURCES A unique software SMI value could not be assigned

+ for this dispatch.

+**/

+EFI_STATUS

+EFIAPI

+SmmSwDispatch2Register (

+ IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This,

+ IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,

+ IN OUT EFI_SMM_SW_REGISTER_CONTEXT *RegContext,

+ OUT EFI_HANDLE *DispatchHandle

+ )

+{

+ EFI_STATUS Status;

+ UINTN Index;

+ EFI_SMM_SW_DISPATCH2_CONTEXT *Context;

+

+ if (RegContext->SwSmiInputValue == (UINTN)-1) {

+ //

+ // If SwSmiInputValue is set to (UINTN) -1 then a unique value

+ // will be assigned and returned in the structure.

+ //

+ Status = EFI_NOT_FOUND;

+ for (Index = 1; Index < MAXIMUM_SWI_VALUE; Index++) {

+ Status = SmiInputValueCheck (Index);

+ if (!EFI_ERROR (Status)) {

+ RegContext->SwSmiInputValue = Index;

+ break;

+ }

+ }

+

+ if (RegContext->SwSmiInputValue == (UINTN)-1) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+ }

+

+ if ((RegContext->SwSmiInputValue > MAXIMUM_SWI_VALUE) || (RegContext->SwSmiInputValue == 0)) {

+ DEBUG ((DEBUG_ERROR, "ERROR: SMI value range (1 ~ 0x%x)\n", MAXIMUM_SWI_VALUE));

+ return EFI_INVALID_PARAMETER;

+ }

+

+ //

+ // Register

+ //

+ Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (*Context), (VOID **)&Context);

+ ASSERT_EFI_ERROR (Status);

+ if (EFI_ERROR (Status)) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+

+ *DispatchHandle = (EFI_HANDLE)Context;

+ Context->Signature = SMI_SW_HANDLER_SIGNATURE;

+ Context->SwSmiInputValue = RegContext->SwSmiInputValue;

+ Context->DispatchFunction = (UINTN)DispatchFunction;

+ Context->DispatchHandle = *DispatchHandle;

+ InsertTailList (&mSmmSwDispatch2Queue, &Context->Link);

+

+ return Status;

+}

+

+/**

+ Unregister a child SMI source dispatch function for the specified software SMI.

+

+ This service removes the handler associated with DispatchHandle so that it will no longer be

+ called in response to a software SMI.

+

+ @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance.

+ @param[in] DispatchHandle Handle of dispatch function to deregister.

+

+ @retval EFI_SUCCESS The dispatch function has been successfully unregistered.

+ @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid.

+**/

+EFI_STATUS

+EFIAPI

+SmmSwDispatch2UnRegister (

+ IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This,

+ IN EFI_HANDLE DispatchHandle

+ )

+{

+ EFI_SMM_SW_DISPATCH2_CONTEXT *Context;

+

+ //

+ // Unregister

+ //

+ Context = FindContextByDispatchHandle (DispatchHandle);

+ ASSERT (Context != NULL);

+ if (Context != NULL) {

+ RemoveEntryList (&Context->Link);

+ gSmst->SmmFreePool (Context);

+ }

+

+ return EFI_SUCCESS;

+}

+

+EFI_SMM_SW_DISPATCH2_PROTOCOL gSmmSwDispatch2 = {

+ SmmSwDispatch2Register,

+ SmmSwDispatch2UnRegister,

+ MAXIMUM_SWI_VALUE

+};

+

+/**

+ Get specified SMI register based on given register ID

+

+ @param[in] SmmRegister SMI related register array from bootloader

+ @param[in] Id The register ID to get.

+

+ @retval NULL The register is not found or the format is not expected.

+ @return smi register

+

+**/

+PLD_GENERIC_REGISTER *

+GetSmmCtrlRegById (

+ IN PLD_SMM_REGISTERS *SmmRegister,

+ IN UINT32 Id

+ )

+{

+ UINT32 Index;

+ PLD_GENERIC_REGISTER *PldReg;

+

+ PldReg = NULL;

+ for (Index = 0; Index < SmmRegister->Count; Index++) {

+ if (SmmRegister->Registers[Index].Id == Id) {

+ PldReg = &SmmRegister->Registers[Index];

+ break;

+ }

+ }

+

+ if (PldReg == NULL) {

+ DEBUG ((DEBUG_INFO, "Register %d not found.\n", Id));

+ return NULL;

+ }

+

+ //

+ // Checking the register if it is expected.

+ //

+ if ((PldReg->Address.AccessSize != EFI_ACPI_3_0_DWORD) ||

+ (PldReg->Address.Address == 0) ||

+ (PldReg->Address.RegisterBitWidth != 1) ||

+ (PldReg->Address.AddressSpaceId != EFI_ACPI_3_0_SYSTEM_IO) ||

+ (PldReg->Value != 1))

+ {

+ DEBUG ((DEBUG_INFO, "Unexpected SMM register.\n"));

+ DEBUG ((DEBUG_INFO, "AddressSpaceId= 0x%x\n", PldReg->Address.AddressSpaceId));

+ DEBUG ((DEBUG_INFO, "RegBitWidth = 0x%x\n", PldReg->Address.RegisterBitWidth));

+ DEBUG ((DEBUG_INFO, "RegBitOffset = 0x%x\n", PldReg->Address.RegisterBitOffset));

+ DEBUG ((DEBUG_INFO, "AccessSize = 0x%x\n", PldReg->Address.AccessSize));

+ DEBUG ((DEBUG_INFO, "Address = 0x%lx\n", PldReg->Address.Address));

+ return NULL;

+ }

+

+ return PldReg;

+}

+

+/**

+ Entry Point for this driver.

+

+ @param[in] ImageHandle Image handle of this driver.

+ @param[in] SystemTable A Pointer to the EFI System Table.

+

+ @retval EFI_SUCCESS The entry point is executed successfully.

+ @retval other Some error occurred when executing this entry point.

+**/

+EFI_STATUS

+EFIAPI

+PchSmiDispatchEntryPoint (

+ IN EFI_HANDLE ImageHandle,

+ IN EFI_SYSTEM_TABLE *SystemTable

+ )

+{

+ EFI_STATUS Status;

+ EFI_HANDLE DispatchHandle;

+ EFI_HOB_GUID_TYPE *GuidHob;

+ PLD_SMM_REGISTERS *SmmRegister;

+ PLD_GENERIC_REGISTER *SmiEosReg;

+ PLD_GENERIC_REGISTER *SmiApmStsReg;

+

+ GuidHob = GetFirstGuidHob (&gSmmRegisterInfoGuid);

+ if (GuidHob == NULL) {

+ return EFI_UNSUPPORTED;

+ }

+

+ SmmRegister = (PLD_SMM_REGISTERS *)GET_GUID_HOB_DATA (GuidHob);

+ SmiEosReg = GetSmmCtrlRegById (SmmRegister, REGISTER_ID_SMI_EOS);

+ if (SmiEosReg == NULL) {

+ DEBUG ((DEBUG_ERROR, "SMI EOS reg not found.\n"));

+ return EFI_NOT_FOUND;

+ }

+

+ mSmiPchReg.SmiEosAddr = (UINT32)SmiEosReg->Address.Address;

+ mSmiPchReg.EosBitOffset = SmiEosReg->Address.RegisterBitOffset;

+

+ SmiApmStsReg = GetSmmCtrlRegById (SmmRegister, REGISTER_ID_SMI_APM_STS);

+ if (SmiApmStsReg == NULL) {

+ DEBUG ((DEBUG_ERROR, "SMI APM status reg not found.\n"));

+ return EFI_NOT_FOUND;

+ }

+

+ mSmiPchReg.SmiApmStsAddr = (UINT32)SmiApmStsReg->Address.Address;

+ mSmiPchReg.ApmBitOffset = SmiApmStsReg->Address.RegisterBitOffset;

+

+ //

+ // Locate PI SMM CPU protocol

+ //

+ Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **)&mSmmCpuProtocol);

+ ASSERT_EFI_ERROR (Status);

+

+ //

+ // Register a SMM handler to handle subsequent SW SMIs.

+ //

+ Status = gSmst->SmiHandlerRegister ((EFI_MM_HANDLER_ENTRY_POINT)SmmSwDispatcher, NULL, &DispatchHandle);

+ ASSERT_EFI_ERROR (Status);

+

+ //

+ // Publish PI SMM SwDispatch2 Protocol

+ //

+ ImageHandle = NULL;

+ Status = gSmst->SmmInstallProtocolInterface (

+ &ImageHandle,

+ &gEfiSmmSwDispatch2ProtocolGuid,

+ EFI_NATIVE_INTERFACE,

+ &gSmmSwDispatch2

+ );

+ ASSERT_EFI_ERROR (Status);

+

+ return Status;

+}

diff --git a/Features/Intel/PlatformPayloadPkg/PchSmiDispatchSmm/PchSmiDispatchSmm.h b/Features/Intel/PlatformPayloadPkg/PchSmiDispatchSmm/PchSmiDispatchSmm.h
new file mode 100644
index 0000000000..c14fe99929
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/PchSmiDispatchSmm/PchSmiDispatchSmm.h
@@ -0,0 +1,36 @@
+/** @file

+ The header file for SMM SwDispatch2 module.

+

+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef SMM_SW_DISPATCH2_H_

+#define SMM_SW_DISPATCH2_H_

+

+#include <PiDxe.h>

+#include <Protocol/SmmSwDispatch2.h>

+#include <Protocol/SmmCpu.h>

+#include <Library/UefiDriverEntryPoint.h>

+#include <Library/SmmServicesTableLib.h>

+#include <Library/BaseLib.h>

+#include <Library/IoLib.h>

+#include <Library/DebugLib.h>

+#include <Guid/SmmRegisterInfoGuid.h>

+#include <Library/HobLib.h>

+

+#define SMI_SW_HANDLER_SIGNATURE SIGNATURE_32('s','s','w','h')

+#define MAXIMUM_SWI_VALUE 0xFF

+#define SMM_CONTROL_PORT 0xB2

+#define SMM_DATA_PORT 0xB3

+

+typedef struct {

+ UINTN Signature;

+ LIST_ENTRY Link;

+ EFI_HANDLE DispatchHandle;

+ UINTN SwSmiInputValue;

+ UINTN DispatchFunction;

+} EFI_SMM_SW_DISPATCH2_CONTEXT;

+

+#endif

diff --git a/Features/Intel/PlatformPayloadPkg/PchSmiDispatchSmm/PchSmiDispatchSmm.inf b/Features/Intel/PlatformPayloadPkg/PchSmiDispatchSmm/PchSmiDispatchSmm.inf
new file mode 100644
index 0000000000..96a154e888
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/PchSmiDispatchSmm/PchSmiDispatchSmm.inf
@@ -0,0 +1,51 @@
+## @file

+# PCH SMM SMI Software dispatch module.

+#

+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>

+#

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+ INF_VERSION = 0x00010005

+ BASE_NAME = PchSmiDispatchSmm

+ FILE_GUID = 60F343E3-2AE2-4AA7-B01E-BF9BD5C04A3B

+ MODULE_TYPE = DXE_SMM_DRIVER

+ VERSION_STRING = 1.0

+ PI_SPECIFICATION_VERSION = 0x0001000A

+ ENTRY_POINT = PchSmiDispatchEntryPoint

+

+#

+# The following information is for reference only and not required by the build tools.

+#

+# VALID_ARCHITECTURES = IA32 X64

+#

+

+[Sources]

+ PchSmiDispatchSmm.c

+ PchSmiDispatchSmm.h

+

+[Packages]

+ MdePkg/MdePkg.dec

+ UefiPayloadPkg/UefiPayloadPkg.dec

+

+[LibraryClasses]

+ UefiDriverEntryPoint

+ MemoryAllocationLib

+ DebugLib

+ UefiBootServicesTableLib

+ SmmServicesTableLib

+ BaseLib

+ IoLib

+ HobLib

+

+[Protocols]

+ gEfiSmmCpuProtocolGuid # PROTOCOL ALWAYS_CONSUMED

+ gEfiSmmSwDispatch2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED

+

+[Guids]

+ gSmmRegisterInfoGuid

+

+[Depex]

+ gEfiSmmCpuProtocolGuid

diff --git a/Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.dec b/Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.dec
new file mode 100644
index 0000000000..549f96d85f
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.dec
@@ -0,0 +1,49 @@
+## @file

+# Payload Platform Package

+#

+# Provides drivers and definitions to create payload platform FV.

+#

+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+ DEC_SPECIFICATION = 0x00010005

+ PACKAGE_NAME = PlatformPayloadPkg

+ PACKAGE_GUID = 17F3ACAC-079D-4518-9EBF-E33289733E8C

+ PACKAGE_VERSION = 0.1

+

+[Includes]

+ Include

+

+[Guids]

+ #

+ ## Defines the token space for the Payload platform Package PCDs.

+ #

+ gPlatformPayloadPkgTokenSpaceGuid = {0xa375ddc6, 0x74fb, 0x4de1, {0x82, 0x6d, 0xa3, 0x10, 0xa3, 0x3b, 0x89, 0x77}}

+

+ #

+ # SPI variable support

+ #

+ gNvVariableInfoGuid = { 0x7a345dca, 0xc26, 0x4f2a, { 0xa8, 0x9a, 0x57, 0xc0, 0x8d, 0xdd, 0x22, 0xee } }

+ gSpiFlashInfoGuid = { 0x2d4aac1b, 0x91a5, 0x4cd5, { 0x9b, 0x5c, 0xb4, 0x0f, 0x5d, 0x28, 0x51, 0xa1 } }

+

+

+################################################################################

+#

+# PCD Declarations section - list of all PCDs Declared by this Package

+# Only this package should be providing the

+# declaration, other packages should not.

+#

+################################################################################

+

+[PcdsFeatureFlag]

+ ## Feature enabling control

+ # @Prompt Enable payload platform FV common for most Intel platforms

+ gPlatformPayloadPkgTokenSpaceGuid.PcdPayloadPackageFeatureEnable|FALSE|BOOLEAN|0x00000001

+

+[PcdsFixedAtBuild, PcdsPatchableInModule]

+ ## FFS filename to find the default variable initial data file.

+ # @Prompt FFS Name of variable initial data file

+ gPlatformPayloadPkgTokenSpaceGuid.PcdNvsDataFile |{ 0x1a, 0xf1, 0xb1, 0xae, 0x42, 0xcc, 0xcf, 0x4e, 0xac, 0x60, 0xdb, 0xab, 0xf6, 0xca, 0x69, 0xe6 }|VOID*|0x00000025

diff --git a/Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.dsc b/Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.dsc
new file mode 100644
index 0000000000..adf028c511
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.dsc
@@ -0,0 +1,110 @@
+## @file

+# platform Payload Package

+#

+# Provides platform specific drivers and definitions to create a platform FV

+# to work with universal UEFI payload to provide support for common Intel platforms.

+#

+# Copyright (c) 2022, 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]

+ PLATFORM_NAME = PlatformPayloadPkg

+ PLATFORM_GUID = D3C551BE-9BC6-48F5-AA8A-F49425C28CA9

+ PLATFORM_VERSION = 0.1

+ DSC_SPECIFICATION = 0x00010005

+ SUPPORTED_ARCHITECTURES = X64

+ BUILD_TARGETS = DEBUG|RELEASE|NOOPT

+ SKUID_IDENTIFIER = DEFAULT

+ OUTPUT_DIRECTORY = Build/$(PLATFORM_NAME)

+ FLASH_DEFINITION = $(PLATFORM_NAME)/PlatformPayloadPkg.fdf

+ PCD_DYNAMIC_AS_DYNAMICEX = TRUE

+ DXE_ARCH = X64

+

+[Packages]

+ MinPlatformPkg/MinPlatformPkg.dec

+

+################################################################################

+#

+# SKU Identification section - list of all SKU IDs supported by this Platform.

+#

+################################################################################

+[SkuIds]

+ 0|DEFAULT

+

+################################################################################

+#

+# Library Class section - list of all Library Classes needed by this Platform.

+#

+################################################################################

+

+#

+# Since there are no 32b libraries or components in this package, these PCD are specified for 64b only

+#

+[PcdsFeatureFlag]

+ #

+ # PCD needed for MinPlatform build includes

+ #

+ gMinPlatformPkgTokenSpaceGuid.PcdSmiHandlerProfileEnable |FALSE

+ gMinPlatformPkgTokenSpaceGuid.PcdUefiSecureBootEnable |FALSE

+ gMinPlatformPkgTokenSpaceGuid.PcdPerformanceEnable |FALSE

+

+[PcdsPatchableInModule.X64]

+ gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x7

+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F

+!if $(SOURCE_DEBUG_ENABLE)

+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17

+!else

+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F

+!endif

+

+ #

+ # The following parameters are set by Library/PlatformHookLib

+ #

+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio|FALSE

+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0

+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate|115200

+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|1

+

+################################################################################

+#

+# Pcd DynamicEx Section - list of all EDK II PCD Entries defined by this Platform

+#

+################################################################################

+

+[PcdsDynamicExDefault]

+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0

+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseSize|0

+

+

+#

+# Include common libraries

+#

+!include MinPlatformPkg/Include/Dsc/CoreCommonLib.dsc

+!include MinPlatformPkg/Include/Dsc/CorePeiLib.dsc

+!include MinPlatformPkg/Include/Dsc/CoreDxeLib.dsc

+

+#

+# This package always builds the feature.

+#

+!include Include/PlatformPayloadFeature.dsc

+

+[BuildOptions]

+ *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES

+ GCC:*_UNIXGCC_*_CC_FLAGS = -DMDEPKG_NDEBUG

+ GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG

+ INTEL:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG

+ MSFT:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG

+

+[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]

+ GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000

+ XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000

+ XCODE:*_*_*_MTOC_FLAGS = -align 0x1000

+ CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096

+ MSFT:*_*_*_DLINK_FLAGS = /ALIGN:4096

diff --git a/Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.fdf b/Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.fdf
new file mode 100644
index 0000000000..f781a364d7
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.fdf
@@ -0,0 +1,50 @@
+## @file

+# Payload platform Package

+#

+# Provides platform specific drivers and definitions to create a platform FV

+# to work with universal UEF payload.

+#

+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+ DEFINE FD_BASE = 0x00800000

+ DEFINE FD_BLOCK_SIZE = 0x00001000

+

+ !if $(TARGET) == "NOOPT"

+ DEFINE FD_SIZE = 0x00090000

+ DEFINE NUM_BLOCKS = 0x90

+ !else

+ DEFINE FD_SIZE = 0x00050000

+ DEFINE NUM_BLOCKS = 0x50

+ !endif

+

+[FD.PlatformPayload]

+ BaseAddress = $(FD_BASE) | gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase

+ Size = $(FD_SIZE) | gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize

+ ErasePolarity = 1

+ BlockSize = $(FD_BLOCK_SIZE)

+ NumBlocks = $(NUM_BLOCKS)

+

+ 0x00000000 | $(FD_SIZE)

+ FV = PlatformPayload

+

+[FV.PlatformPayload]

+ !include MinPlatformPkg/Include/Fdf/CommonSpiFvHeaderInfo.fdf

+ FvNameGuid = 96E75986-6FDD-491E-9FD5-35E21AC45B45

+ FvForceRebase = FALSE

+

+ !include Include/PostMemory.fdf

+

+################################################################################

+#

+# Rules are use with the [FV] section's module INF type to define

+# how an FFS file is created for a given INF file. The following Rule are the default

+# rules for the different module type. User can add the customized rules to define the

+# content of the FFS file.

+#

+################################################################################

+

+!include MinPlatformPkg/Include/Fdf/RuleInclude.fdf

diff --git a/Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.py b/Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.py
new file mode 100644
index 0000000000..1e3e1cce21
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/PlatformPayloadPkg.py
@@ -0,0 +1,113 @@
+## @file

+# This file contains the script to build UniversalPayload with platform payload

+#

+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+##

+

+import argparse

+import subprocess

+import os

+import shutil

+import sys

+from ctypes import *

+

+sys.dont_write_bytecode = True

+

+def RunCommand(cmd):

+ print(cmd)

+ p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE'])

+ while True:

+ line = p.stdout.readline()

+ if not line:

+ break

+ print(line.strip().decode(errors='ignore'))

+

+ p.communicate()

+ if p.returncode != 0:

+ print("- Failed - error happened when run command: %s"%cmd)

+ raise Exception("ERROR: when run command: %s"%cmd)

+

+def BuildUniversalPayload(Args, MacroList):

+ BuildTarget = Args.Target

+ ToolChain = Args.ToolChain

+ ElfToolChain = 'CLANGDWARF'

+ ObjCopyFlag = "elf64-x86-64" if Args.Arch == 'X64' else "elf32-i386"

+

+ #

+ # Find universal UEFI payload build build script

+ #

+ Edk2PayloadBuildScript = os.path.normpath("UefiPayloadPkg/UniversalPayloadBuild.py")

+ for package_path in os.environ['PACKAGES_PATH'].split(';'):

+ if os.path.exists (os.path.join (package_path, Edk2PayloadBuildScript)):

+ Edk2PayloadBuildScript = os.path.join (package_path, Edk2PayloadBuildScript)

+ break

+ if not os.path.exists (Edk2PayloadBuildScript):

+ raise Exception("Could not find universal UEFI payload build script UniversalPayloadBuild.py")

+

+ PlatformFvDscPath = os.path.normpath("PlatformPayloadPkg/PlatformPayloadPkg.dsc")

+ BuildDir = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/UefiPayloadPkgX64"))

+ PlatformFvReportPath = os.path.join(BuildDir, "PlatformPayloadReport.txt")

+ UniversalUefiPld = os.path.join(BuildDir, 'UniversalPayload.elf')

+ PlatformFv = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/PlatformPayloadPkg"), f"{BuildTarget}_{ToolChain}", os.path.normpath("FV/PlatformPayload.Fv"))

+

+ if "CLANG_BIN" in os.environ:

+ LlvmObjcopyPath = os.path.join(os.environ["CLANG_BIN"], "llvm-objcopy")

+ else:

+ LlvmObjcopyPath = "llvm-objcopy"

+ try:

+ RunCommand('"%s" --version'%LlvmObjcopyPath)

+ except:

+ print("- Failed - Please check if LLVM is installed or if CLANG_BIN is set correctly")

+ sys.exit(1)

+

+ Defines = ""

+ for key in MacroList:

+ Defines +=" -D {0}={1}".format(key, MacroList[key])

+

+ #

+ # Building Universal Payload entry.

+ #

+ if not Args.Skip:

+ BuildPayload = f"python {Edk2PayloadBuildScript} -b {BuildTarget} -t {ToolChain} -a {Args.Arch} {Defines}"

+ RunCommand(BuildPayload)

+

+ #

+ # Building Platform Payload.

+ #

+ BuildPayload = f"build -p {PlatformFvDscPath} -b {BuildTarget} -a X64 -t {ToolChain} -y {PlatformFvReportPath}"

+ BuildPayload += Defines

+ RunCommand(BuildPayload)

+

+ #

+ # Copy the Platform Payload as a section in elf format Universal Payload.

+ #

+ remove_section = f'"{LlvmObjcopyPath}" -I {ObjCopyFlag} -O {ObjCopyFlag} --remove-section .upld.platform_fv {UniversalUefiPld}'

+ add_section = f'"{LlvmObjcopyPath}" -I {ObjCopyFlag} -O {ObjCopyFlag} --add-section .upld.platform_fv={PlatformFv} {UniversalUefiPld}'

+ set_section = f'"{LlvmObjcopyPath}" -I {ObjCopyFlag} -O {ObjCopyFlag} --set-section-alignment .upld.platform_fv=16 {UniversalUefiPld}'

+ RunCommand(remove_section)

+ RunCommand(add_section)

+ RunCommand(set_section)

+

+

+def main():

+ parser = argparse.ArgumentParser(description='Build Platform Payload FV and add it to Universal UEFI Payload')

+ parser.add_argument('-t', '--ToolChain')

+ parser.add_argument('-b', '--Target', default='DEBUG')

+ parser.add_argument('-a', '--Arch', choices=['IA32', 'X64'], help='Specify the ARCH for payload entry module. Default build X64 image.', default ='X64')

+ parser.add_argument("-D", "--Macro", action="append")

+ parser.add_argument('-s', '--Skip', action='store_true', help='Skip Universal UEFI payload build (just build platform FV and add to Universal UEFI payload.')

+ MacroList = {}

+ args = parser.parse_args()

+ if args.Macro is not None:

+ for Argument in args.Macro:

+ if Argument.count('=') != 1:

+ print("Unknown variable passed in: %s"%Argument)

+ raise Exception("ERROR: Unknown variable passed in: %s"%Argument)

+ tokens = Argument.strip().split('=')

+ MacroList[tokens[0].upper()] = tokens[1]

+ BuildUniversalPayload(args, MacroList)

+ print ("Successfully build Universal Payload with platform FV")

+

+if __name__ == '__main__':

+ main()

diff --git a/Features/Intel/PlatformPayloadPkg/Readme.md b/Features/Intel/PlatformPayloadPkg/Readme.md
new file mode 100644
index 0000000000..10e863b5e0
--- /dev/null
+++ b/Features/Intel/PlatformPayloadPkg/Readme.md
@@ -0,0 +1,96 @@
+# Overview

+* **Feature Name:** Platform Payload

+* **PI Phase(s) Supported:** SMM DXE

+

+## Purpose

+This package provides a common platform payload which is expected to work on most

+Intel platforms with a bootloader.

+

+# High-Level Theory of Operation

+Bootloader initialize memory/silicon/platform and payload focus on boot media initializaiton

+and OS boot. Payload is expected to be re-used on different Platforms.

+

+In the reality, some payload modules have platform dependency (e.g. only for Intel PCH)

+or bootloader dependency (only for coreboot). These modules would be located in

+edk2-platform repo.

+

+The generic UEFI payload could be built from EDK2 UefiPayloadPkg in ELF format following

+universal payload specification. And a Platform Payload could be built from PlatformPayloadPkg

+to provide Intel platform specific features (e.g. SPI module, PCH SMM) in FV/FD format.

+This platform payload could be inserted into universal UEFI payload as an ELF section

+to generate a full-feature payload.

+## Firmware Volumes

+* FvPlatformPayload

+

+## Build Flows

+use windows host as example to generate a full-feature payload:

+

+** Setup the build env

+set WORKSPACE=c:\payload

+set PACKAGES_PATH=%WORKSPACE%\edk2;%WORKSPACE%\edk2-platforms\Features\Intel;

+ %WORKSPACE%\edk2-platforms\Platform\Intel

+edk2\edksetup.bat

+

+** Build universal UEFI payload with platform Payload

+python edk2-platforms\Features\Intel\PlatformPayloadPkg\PlatformPayloadPkg.py -t VS2019

+ -D SMM_SUPPORT=TRUE -DVARIABLE_SUPPORT=NONE -D SMM_VARIABLE=TRUE

+or

+python edk2\UefiPayloadPkg\UniversalPayloadBuild.py -t VS2019 -D SMM_SUPPORT=TRUE -DVARIABLE_SUPPORT=NONE

+python edk2-platforms\Features\Intel\PlatformPayloadPkg\PlatformPayloadPkg.py -t VS2019 -D SMM_VARIABLE=TRUE -s

+

+ If build success, the final UEFI payload is at Build\UefiPayloadPkgX64\UniversalPayload.elf.

+

+## Features

+

+1. Modules

+Currently only SMM veriable feature is available.

+Several build macros are used as below for SMM variable feature modules.

+!if $(SMM_VARIABLE) == TRUE

+ ## PchSmiDispatchSmm

+ ## FvbSmm

+ ## FaultTolerantWriteSmm

+ ## VariableSmm

+ ## VariableSmmRuntimeDxe

+!endif

+

+2. Data Flows

+SMM variable:

+The interface with bootloader are defined in PlatformPayloadPkg\Include\Guid

+SpiFlashInfoGuid.h -- SPI related information for SPI flash operation.

+NvVariableInfoGuid.h -- Variable related information for SPI NV variables.

+

+## Control Flows

+EDK2 DXE/SMM core from universal UEFI payload would dispatch all the modules

+from this platform payload.

+

+## Test Point Results

+*_TODO_*

+The test(s) that can verify porting is complete for the feature.

+

+Each feature must describe at least one test point to verify the feature is successful. If the test point is not

+implemented, this should be stated.

+

+## Functional Exit Criteria

+*_TODO_*

+The testable functionality for the feature.

+

+This section should provide an ordered list of criteria that a board integrator can reference to ensure the feature is

+functional on their board.

+

+## Feature Enabling Checklist

+*_TODO_*

+An ordered list of required activities to achieve desired functionality for the feature.

+

+## Performance Impact

+A general expectation for the impact on overall boot performance due to using this feature.

+

+This section is expected to provide guidance on:

+* How to estimate performance impact due to the feature

+* How to measure performance impact of the feature

+* How to manage performance impact of the feature

+

+## Common Optimizations

+*_TODO_*

+Common size or performance tuning options for this feature.

+

+This section is recommended but not required. If not used, the contents should be left empty.

--
2.35.1.windows.2


Re: [edk2-platforms][PATCH v1 1/1] MinPlatformPkg/TestPointCheckLib: Remove unnecessary GetVariable2() call

Isaac Oram
 

Pushed as ea2a520c83..60053f3077

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Oram, Isaac W
Sent: Friday, August 5, 2022 1:40 PM
To: mikuback@...; devel@edk2.groups.io
Cc: Chiu, Chasel <chasel.chiu@...>; Desimone, Nathaniel L <nathaniel.l.desimone@...>; Gao, Liming <gaoliming@...>; Dong, Eric <eric.dong@...>
Subject: Re: [edk2-devel] [edk2-platforms][PATCH v1 1/1] MinPlatformPkg/TestPointCheckLib: Remove unnecessary GetVariable2() call

Reviewed-by: Isaac Oram <isaac.w.oram@...>

-----Original Message-----
From: mikuback@... <mikuback@...>
Sent: Friday, August 5, 2022 11:02 AM
To: devel@edk2.groups.io
Cc: Chiu, Chasel <chasel.chiu@...>; Desimone, Nathaniel L <nathaniel.l.desimone@...>; Oram, Isaac W <isaac.w.oram@...>; Gao, Liming <gaoliming@...>; Dong, Eric <eric.dong@...>
Subject: [edk2-platforms][PATCH v1 1/1] MinPlatformPkg/TestPointCheckLib: Remove unnecessary GetVariable2() call

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

The data buffer returned from the GetVariable2() call in
TestPointCheckMemoryTypeInformation() is not actually used or freed.

This change removes the unnecessary function call.

Cc: Chasel Chiu <chasel.chiu@...>
Cc: Nate DeSimone <nathaniel.l.desimone@...>
Cc: Isaac Oram <isaac.w.oram@...>
Cc: Liming Gao <gaoliming@...>
Cc: Eric Dong <eric.dong@...>
Signed-off-by: Michael Kubacki <michael.kubacki@...>
---
Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/DxeCheckMemoryTypeInformation.c | 8 --------
1 file changed, 8 deletions(-)

diff --git a/Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/DxeCheckMemoryTypeInformation.c b/Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/DxeCheckMemoryTypeInformation.c
index 9ee9dd252c7e..0ff6789ac621 100644
--- a/Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/DxeCheckMemoryTypeInformation.c
+++ b/Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/DxeCheckMemoryTypeInformation.c
@@ -109,7 +109,6 @@ TestPointCheckMemoryTypeInformation (
EFI_HOB_GUID_TYPE *GuidHob;
VOID *CurrentMemoryTypeInformation;
VOID *PreviousMemoryTypeInformation;
- VOID *VariableMemoryTypeInformation;

DEBUG ((DEBUG_INFO, "==== TestPointCheckMemoryTypeInformation - Enter\n"));
CurrentMemoryTypeInformation = NULL;
@@ -128,13 +127,6 @@ TestPointCheckMemoryTypeInformation (
goto Done;
}

- GetVariable2 (
- EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
- &gEfiMemoryTypeInformationGuid,
- &VariableMemoryTypeInformation,
- NULL
- );
-
if ((CurrentMemoryTypeInformation != NULL) && (PreviousMemoryTypeInformation != NULL)) {
DumpMemoryTypeInfoSummary(CurrentMemoryTypeInformation, PreviousMemoryTypeInformation);
}
--
2.28.0.windows.1


Re: [edk2-platforms][PATCH v1 1/1] MinPlatformPkg/TestPointCheckLib: Prevent modification of HOB data

Isaac Oram
 

Pushed as 436a8612ae..ea2a520c83

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Oram, Isaac W
Sent: Friday, August 5, 2022 1:30 PM
To: mikuback@...; devel@edk2.groups.io
Cc: Chiu, Chasel <chasel.chiu@...>; Desimone, Nathaniel L <nathaniel.l.desimone@...>; Gao, Liming <gaoliming@...>; Dong, Eric <eric.dong@...>
Subject: Re: [edk2-devel] [edk2-platforms][PATCH v1 1/1] MinPlatformPkg/TestPointCheckLib: Prevent modification of HOB data

Reviewed-by: Isaac Oram <isaac.w.oram@...>

-----Original Message-----
From: mikuback@... <mikuback@...>
Sent: Friday, August 5, 2022 10:16 AM
To: devel@edk2.groups.io
Cc: Chiu, Chasel <chasel.chiu@...>; Desimone, Nathaniel L <nathaniel.l.desimone@...>; Oram, Isaac W <isaac.w.oram@...>; Gao, Liming <gaoliming@...>; Dong, Eric <eric.dong@...>
Subject: [edk2-platforms][PATCH v1 1/1] MinPlatformPkg/TestPointCheckLib: Prevent modification of HOB data

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

DumpMemoryTypeInfoSummary() is used to dump information about the MemoryTypeInformation HOB. The dump function currently modifies the data which can corrupt the data for later HOB consumers in the DXE phase.

This change makes DumpMemoryTypeInfoSummary() treat the data as read-only.

Cc: Chasel Chiu <chasel.chiu@...>
Cc: Nate DeSimone <nathaniel.l.desimone@...>
Cc: Isaac Oram <isaac.w.oram@...>
Cc: Liming Gao <gaoliming@...>
Cc: Eric Dong <eric.dong@...>
Signed-off-by: Michael Kubacki <michael.kubacki@...>
---
Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/DxeCheckMemoryTypeInformation.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/DxeCheckMemoryTypeInformation.c b/Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/DxeCheckMemoryTypeInformation.c
index 9ee9dd252c7e..a30b69dd787c 100644
--- a/Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/DxeCheckMemoryTypeInformation.c
+++ b/Platform/Intel/MinPlatformPkg/Test/Library/TestPointCheckLib/DxeCh
+++ eckMemoryTypeInformation.c
@@ -22,8 +22,8 @@ ShortNameOfMemoryType(

VOID
DumpMemoryTypeInfoSummary (
- IN EFI_MEMORY_TYPE_INFORMATION *CurrentMemoryTypeInformation,
- IN EFI_MEMORY_TYPE_INFORMATION *PreviousMemoryTypeInformation
+ IN CONST EFI_MEMORY_TYPE_INFORMATION *CurrentMemoryTypeInformation,
+ IN CONST EFI_MEMORY_TYPE_INFORMATION *PreviousMemoryTypeInformation
)
{
UINTN Index;
@@ -83,7 +83,6 @@ DumpMemoryTypeInfoSummary (
}

if (Next != Previous) {
- PreviousMemoryTypeInformation[Index].NumberOfPages = Next;
MemoryTypeInformationModified = TRUE;
}

@@ -110,7 +109,7 @@ TestPointCheckMemoryTypeInformation (
VOID *CurrentMemoryTypeInformation;
VOID *PreviousMemoryTypeInformation;
VOID *VariableMemoryTypeInformation;
-
+
DEBUG ((DEBUG_INFO, "==== TestPointCheckMemoryTypeInformation - Enter\n"));
CurrentMemoryTypeInformation = NULL;
PreviousMemoryTypeInformation = NULL;
--
2.28.0.windows.1


Re: [PATCH 1/1] Ext4Pkg: Sanity check the inode size

Marvin Häuser <mhaeuser@...>
 

Reviewed-by: Marvin Häuser <mhaeuser@...>

On 7. Aug 2022, at 01:39, Pedro Falcato <pedro.falcato@...> wrote:

Check its alignment and value for possible bad values.

Cc: Marvin Häuser <mhaeuser@...>
Signed-off-by: Pedro Falcato <pedro.falcato@...>
---
Features/Ext4Pkg/Ext4Dxe/Superblock.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/Features/Ext4Pkg/Ext4Dxe/Superblock.c b/Features/Ext4Pkg/Ext4Dxe/Superblock.c
index c22155ba11b4..edee051c41e8 100644
--- a/Features/Ext4Pkg/Ext4Dxe/Superblock.c
+++ b/Features/Ext4Pkg/Ext4Dxe/Superblock.c
@@ -189,6 +189,12 @@ Ext4OpenSuperblock (
Partition->FeaturesIncompat = Sb->s_feature_incompat;
Partition->FeaturesRoCompat = Sb->s_feature_ro_compat;
Partition->InodeSize = Sb->s_inode_size;
+
+ // Check for proper alignment of InodeSize and that InodeSize is indeed larger than
+ // the minimum size, 128 bytes.
+ if (((Partition->InodeSize % 4) != 0) || (Partition->InodeSize < EXT4_GOOD_OLD_INODE_SIZE)) {
+ return EFI_VOLUME_CORRUPTED;
+ }
} else {
// GOOD_OLD_REV
Partition->FeaturesCompat = Partition->FeaturesIncompat = Partition->FeaturesRoCompat = 0;
--
2.37.1


[PATCH 1/1] AsfPkg: Add Alert standard format support

CrystalLee [李怡萱] <CrystalLee@...>
 

Hi,

I would like to propose to add Alert standard format support which is based
on ASF2.0 specification(DSP0136).
REF:https://www.dmtf.org/sites/default/files/standards/documents/DSP0136.pdf

Could you suggest which package is suitable for this feature?
Since I'm not sure which package to include this feature, I create a temporarily
Asfpkg to include my patch.
Asf branch in forked edk2 reop
REF:https://github.com/CrystalLee-77/edk2/tree/AlertStandardFormatSupport

Currently, the drivers focus on below features
1. ASF Smbus alert-relate messages (progress logs or error logs)
2. Publish ASF ACPI table for remote control and other information

Drivers description:
Asf Pei driver: send Bios present and memory initial related messages.
Asf Dxe driver:
1. Get boot options from device(DSP0136, ch5.2 boot option messages)
2. Install Asf Acpi table.
3. Register callback function through RscHandler Protocol, the function will
send standard messages base on the reported status code.
4. Register callback function on ready to boot event, this function will send
set system state(S0) message to device.
5. Install Asf protocol, the protocol include the boot options information in
step 1 so other drivers can get the information.


Alert Standard format specification(DSP0136)
REF:https://www.dmtf.org/sites/default/files/standards/documents/DSP0136.pdf

Send standard alert message base on the status code reported by drivers.
Report Asf configuration and capabilities in Asf ACPI table

Signed-off-by: Crystal Lee <CrystalLee@...>
---
AsfPkg/Asf/AsfDxe/AsfDxe.c | 338 +++++++++++++++++
AsfPkg/Asf/AsfDxe/AsfDxeEvent.c | 319 ++++++++++++++++
AsfPkg/Asf/AsfPei/AsfPei.c | 384 ++++++++++++++++++++
AsfPkg/Library/AsfAcpiTableLib/AsfAcpiTableLib.c | 210 +++++++++++
AsfPkg/Asf/AsfDxe/AsfDxe.h | 67 ++++
AsfPkg/Asf/AsfDxe/AsfDxe.inf | 52 +++
AsfPkg/Asf/AsfDxe/AsfDxe.uni | 15 +
AsfPkg/Asf/AsfDxe/AsfDxeExtra.uni | 13 +
AsfPkg/Asf/AsfPei/AsfPei.inf | 57 +++
AsfPkg/Asf/AsfPei/AsfPei.uni | 15 +
AsfPkg/Asf/AsfPei/AsfPeiExtra.uni | 13 +
AsfPkg/AsfPkg.dec | 47 +++
AsfPkg/AsfPkg.dsc | 59 +++
AsfPkg/Include/AsfMessages.h | 104 ++++++
AsfPkg/Include/IndustryStandard/Asf.h | 145 ++++++++
AsfPkg/Include/Library/AsfAcpiTableLib.h | 26 ++
AsfPkg/Include/Protocol/AsfProtocol.h | 57 +++
AsfPkg/Library/AsfAcpiTableLib/AsfAcpiTableLib.inf | 30 ++
AsfPkg/Library/AsfAcpiTableLib/AsfAcpiTableLib.uni | 15 +
19 files changed, 1966 insertions(+)

diff --git a/AsfPkg/Asf/AsfDxe/AsfDxe.c b/AsfPkg/Asf/AsfDxe/AsfDxe.c
new file mode 100644
index 000000000000..1919dec6d095
--- /dev/null
+++ b/AsfPkg/Asf/AsfDxe/AsfDxe.c
@@ -0,0 +1,338 @@
+/** @file

+ Asf Dxe driver which is used for sending event record log to NIC or receiving

+ boot option command from NIC and provide in Asf Dxe protocol.

+

+ Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+**/

+

+#include <AsfDxe.h>

+

+ASF_BOOT_OPTION gAsfBootOption = { 0, 0, 0, 0, 0, 0, 0 };

+ASF_PROTOCOL gAsfProtocol = { AsfPushEvent, NULL };

+EFI_SMBUS_DEVICE_ADDRESS mFixedTargetAddress;

+EFI_SMBUS_HC_PROTOCOL *mSmBus = NULL;

+

+/**

+ Send message through SmBus to lan card.

+

+ @param[in] Command Command of System Firmware Events.

+ @param[in] Length Length of the data in bytes.

+ @param[in] AsfEvent Message data.

+

+ @retval EFI_SUCCESS Push Event successfully.

+ @retval Others Push Event error.

+**/

+EFI_STATUS

+EFIAPI

+AsfPushEvent (

+ IN UINT8 Command,

+ IN UINTN Length,

+ IN UINT8 *AsfEvent

+ )

+{

+ EFI_STATUS Status;

+

+ if (mSmBus == NULL) {

+ return EFI_UNSUPPORTED;

+ }

+

+ Status = mSmBus->Execute (

+ mSmBus,

+ mFixedTargetAddress,

+ Command,

+ EfiSmbusWriteBlock,

+ TRUE,

+ &Length,

+ AsfEvent

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_ERROR, "AsfPushEvent Status = %r\n", Status));

+ }

+

+ return Status;

+}

+

+/**

+ This function pushes the System Firmware State Events.

+

+ @param[in] SystemState System Firmware State.

+

+**/

+VOID

+EFIAPI

+AsfPushSystemState (

+ IN UINT8 SystemState

+ )

+{

+ mAsfSystemState.EventSensorType = SystemState;

+ AsfPushEvent (

+ mAsfSystemState.Command,

+ mAsfSystemState.ByteCount,

+ (UINT8 *)&(mAsfSystemState.SubCommand)

+ );

+ return;

+}

+

+/**

+ This function processes the System Firmware Progress/Error Events.

+

+ @param[in] MessageErrorLevel Progress or error or system management message Type.

+ @param[in] MessageType Specific ASF message type.

+

+**/

+VOID

+EFIAPI

+AsfPushSystemErrorProgressEvent (

+ IN UINT32 MessageErrorLevel,

+ IN ASF_MESSAGE_TYPE MessageType

+ )

+{

+ UINTN i;

+

+ if ((MessageErrorLevel & PcdGet32 (PcdAsfMessageErrorLevel)) ||

+ ((gAsfBootOption.BootOptionBit & ASF_BOP_BIT_FORCE_PROGRESS_EVENT)))

+ {

+ for ( i = 0; i < mAsfMessagesSize; i++ ) {

+ if ( mAsfMessages[i].Type == MessageType ) {

+ AsfPushEvent (

+ mAsfMessages[i].Message.Command,

+ mAsfMessages[i].Message.ByteCount,

+ (UINT8 *)&(mAsfMessages[i].Message.SubCommand)

+ );

+ break;

+ }

+ }

+ }

+

+ return;

+}

+

+/**

+ Send relate progress or error message to lan card

+

+ @param[in] CodeType Indicates the type of status code being reported.

+ @param[in] Value Describes the current status of a hardware or software entity.

+ This included information about the class and subclass that is used to

+ classify the entity as well as an operation.

+ @param[in] Instance The enumeration of a hardware or software entity within

+ the system. Valid instance numbers start with 1.

+ @param[in] CallerId This optional parameter may be used to identify the caller.

+ This parameter allows the status code driver to apply different rules to

+ different callers.

+ @param[in] Data This optional parameter may be used to pass additional data.

+

+ @retval EFI_SUCCESS Reported all the progress and error codes for Asf successfully.

+**/

+EFI_STATUS

+EFIAPI

+AsfRscHandlerCallback (

+ IN EFI_STATUS_CODE_TYPE CodeType,

+ IN EFI_STATUS_CODE_VALUE Value,

+ IN UINT32 Instance,

+ IN EFI_GUID *CallerId,

+ IN EFI_STATUS_CODE_DATA *Data

+ )

+{

+ UINTN Index;

+

+ if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) {

+ for (Index = 0; Index < mMsgProgressMapSize; Index++) {

+ if (mMsgProgressMap[Index].StatusCode == Value) {

+ AsfPushSystemErrorProgressEvent (MESSAGE_ERROR_LEVEL_PROGRESS, mMsgProgressMap[Index].MessageType);

+ break;

+ }

+ }

+ }

+

+ if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) {

+ for ( Index = 0; Index < mMsgErrorMapSize; Index++ ) {

+ if ( mMsgErrorMap[Index].StatusCode == Value ) {

+ AsfPushSystemErrorProgressEvent (MESSAGE_ERROR_LEVEL_ERROR, mMsgErrorMap[Index].MessageType);

+ break;

+ }

+ }

+ }

+

+ return EFI_SUCCESS;

+}

+

+/**

+ This function issues the ASF Get/Clear Boot Option command.

+

+ @retval EFI_SUCCESS Reported all the progress and error codes for Asf successfully.

+ @retval Others Smbus Execute function return error.

+**/

+EFI_STATUS

+EFIAPI

+AsfGetBootOption (

+ IN EFI_SMBUS_DEVICE_ADDRESS AsfSlaveAddress

+ )

+{

+ EFI_STATUS Status;

+ UINTN Length = sizeof (ASF_BOOT_OPTION);

+ ASF_BOOT_OPTION BootOption;

+

+ // Initialize get boot option Buffer.

+ SetMem (&BootOption, sizeof (ASF_BOOT_OPTION), 0);

+

+ // Execute ASFMSG_CMD_CONFIG command.

+ Status = mSmBus->Execute (

+ mSmBus,

+ AsfSlaveAddress,

+ ASFMSG_CMD_CONFIG,

+ EfiSmbusReadBlock,

+ TRUE,

+ &Length,

+ &BootOption

+ );

+ if ( EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ if ( BootOption.SubCommand == ASFMSG_SUBCMD_RET_BOOT_OPTION ) {

+ // copy Return Boot Option to global ASF Boot Option buffer.

+ CopyMem (&gAsfBootOption, &BootOption, sizeof (ASF_BOOT_OPTION));

+ gAsfProtocol.BootOption = &gAsfBootOption;

+ // Execute Clear Boot Option command.

+ BootOption.SubCommand = ASFMSG_SUBCMD_CLR_BOOT_OPTION;

+ BootOption.Version = 0x10;

+ Length = 2;

+ mSmBus->Execute (

+ mSmBus,

+ AsfSlaveAddress,

+ ASFMSG_CMD_CONFIG,

+ EfiSmbusWriteBlock,

+ TRUE,

+ &Length,

+ &BootOption

+ );

+ }

+

+ return Status;

+}

+

+/**

+ This Event Callback processes the requests at EFI Ready to Boot Event triggered.

+

+ @param[in] Event A pointer to the Event that triggered the callback.

+ @param[in] Context A pointer to private data registered with the callback function.

+**/

+VOID

+EFIAPI

+AsfReadyToBootEvent (

+ IN EFI_EVENT Event,

+ IN VOID *Context

+ )

+{

+ // Push System State S0 - "Working".

+ AsfPushSystemState (ASFMSG_SYSTEM_STATE_S0);

+

+ gBS->CloseEvent (Event);

+ return;

+}

+

+/**

+ Register callback if Acpi protocol is not ready, else install ASF acpi table directly.

+

+**/

+VOID

+EFIAPI

+InstallAsfAcpiTable (

+ VOID

+ )

+{

+ EFI_STATUS Status;

+ EFI_EVENT Event;

+ VOID *Registration;

+ EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;

+

+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol);

+ if (!EFI_ERROR (Status)) {

+ InstallAsfAcpiTableEvent (NULL, NULL);

+ } else {

+ Status = gBS->CreateEvent (

+ EVT_NOTIFY_SIGNAL,

+ TPL_CALLBACK,

+ InstallAsfAcpiTableEvent,

+ NULL,

+ &Event

+ );

+

+ if (!EFI_ERROR (Status)) {

+ Status = gBS->RegisterProtocolNotify (

+ &gEfiAcpiTableProtocolGuid,

+ Event,

+ &Registration

+ );

+

+ if (EFI_ERROR (Status)) {

+ gBS->CloseEvent (Event);

+ }

+ }

+ }

+

+ return;

+}

+

+/**

+ This is the standard EFI driver entry point for DXE phase of ASF.

+

+ @param[in] ImageHandle Image handle of the loaded driver

+ @param[in] SystemTable Pointer to the System Table

+

+ @retval EFI_SUCCESS This driver initial correctly

+ @retval Others This driver initial fail

+**/

+EFI_STATUS

+EFIAPI

+AsfDxeEntry (

+ IN EFI_HANDLE ImageHandle,

+ IN EFI_SYSTEM_TABLE *SystemTable

+ )

+{

+ EFI_STATUS Status;

+ EFI_RSC_HANDLER_PROTOCOL *RscHandler;

+ EFI_EVENT AsfEfiReadyToBootEvent;

+

+ Status = gBS->LocateProtocol (&gEfiSmbusHcProtocolGuid, NULL, (VOID **)&mSmBus);

+ if ( EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ mFixedTargetAddress.SmbusDeviceAddress = PcdGet8 (PcdSmbusSlaveAddressForDashLan) >> 1;

+ if (mFixedTargetAddress.SmbusDeviceAddress == 0) {

+ return EFI_UNSUPPORTED;

+ }

+

+ Status = AsfGetBootOption (mFixedTargetAddress);

+ if ( EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ InstallAsfAcpiTable ();

+

+ // Send mother board initialization message.

+ AsfPushSystemErrorProgressEvent (MESSAGE_ERROR_LEVEL_PROGRESS, MsgMotherBoardInit);

+

+ Status = gBS->LocateProtocol (&gEfiRscHandlerProtocolGuid, NULL, (VOID **)&RscHandler);

+ if (!EFI_ERROR (Status)) {

+ RscHandler->Register (AsfRscHandlerCallback, TPL_CALLBACK);

+ }

+

+ EfiCreateEventReadyToBootEx (

+ TPL_CALLBACK,

+ AsfReadyToBootEvent,

+ NULL,

+ &AsfEfiReadyToBootEvent

+ );

+

+ gBS->InstallProtocolInterface (

+ &ImageHandle, \

+ &gAsfProtocolGuid,

+ EFI_NATIVE_INTERFACE,

+ &gAsfProtocol

+ );

+

+ return EFI_SUCCESS;

+}

diff --git a/AsfPkg/Asf/AsfDxe/AsfDxeEvent.c b/AsfPkg/Asf/AsfDxe/AsfDxeEvent.c
new file mode 100644
index 000000000000..64265c6d5c3c
--- /dev/null
+++ b/AsfPkg/Asf/AsfDxe/AsfDxeEvent.c
@@ -0,0 +1,319 @@
+/** @file

+ Asf messages define

+

+ Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+**/

+

+#include <AsfDxe.h>

+

+MESSAGE_DATA_HUB_MAP mMsgProgressMap[] = {

+ { MsgHddInit, EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_PC_ENABLE },

+ { MsgApInit, EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_AP_INIT },

+ { MsgUserInitSetup, EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP },

+ { MsgUsbResourceConfig, EFI_IO_BUS_USB | EFI_P_PC_ENABLE },

+ { MsgPciResourceConfig, EFI_IO_BUS_PCI | EFI_IOB_PCI_BUS_ENUM },

+ { MsgVideoInit, EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE },

+ { MsgKbcInit, EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE },

+ { MsgKbcTest, EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST }

+};

+

+MESSAGE_DATA_HUB_MAP mMsgErrorMap[] = {

+ { MsgNoVideo, EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED },

+ { MsgKbdFailure, EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED },

+ { MsgHddFailure, EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_EC_NOT_DETECTED }

+};

+

+ASF_MESSAGE mAsfMessages[] = {

+ {

+ MsgHddInit,

+ {

+ ASFMSG_COMMAND_MESSAGING,

+ 0x0d, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_PROGRESS_ENTRY,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_CRITICAL,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_DISK,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_HARD_DISK_INITIALIZATION

+ }

+ },

+ {

+ MsgApInit,

+ {

+ ASFMSG_COMMAND_MESSAGING,

+ 0x0d, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_PROGRESS_ENTRY,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_CRITICAL,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_PROCESSOR,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_AP_INITIALIZATION

+ }

+ },

+ {

+ MsgUserInitSetup,

+ {

+ ASFMSG_COMMAND_MESSAGING,

+ 0x0d, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_PROGRESS_ENTRY,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_CRITICAL,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_BIOS,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_SETUP_INITIALIZATION

+ }

+ },

+ {

+ MsgUsbResourceConfig,

+ {

+ ASFMSG_COMMAND_MESSAGING,

+ 0x0d, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_PROGRESS_ENTRY,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_CRITICAL,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_BIOS,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_USB_RESOURCE_CONFIG

+ }

+ },

+ {

+ MsgPciResourceConfig,

+ {

+ ASFMSG_COMMAND_MESSAGING,

+ 0x0d, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_PROGRESS_ENTRY,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_CRITICAL,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_BIOS,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_PCI_RESOURCE_CONFIG

+ }

+ },

+ {

+ MsgVideoInit,

+ {

+ ASFMSG_COMMAND_MESSAGING,

+ 0x0d, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_PROGRESS_ENTRY,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_CRITICAL,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_ADD_IN_CARD,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_VIDEO_INITIALIZATION

+ }

+ },

+ {

+ MsgKbcInit,

+ {

+ ASFMSG_COMMAND_MESSAGING,

+ 0x0d, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_PROGRESS_ENTRY,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_CRITICAL,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_SYSTEM_BOARD,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_KEYBOARD_INITIALIZATION

+ }

+ },

+ {

+ MsgKbcTest,

+ {

+ ASFMSG_COMMAND_MESSAGING,

+ 0x0d, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_PROGRESS_ENTRY,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_CRITICAL,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_SYSTEM_BOARD,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_KEYBOARD_TEST

+ }

+ },

+ {

+ MsgMotherBoardInit,

+ {

+ ASFMSG_COMMAND_MESSAGING,

+ 0x0d, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_PROGRESS_ENTRY,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_MONITOR,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_SYSTEM_BOARD,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_BOARD_INITIALIZATION

+ }

+ },

+ {

+ MsgNoVideo,

+ {

+ ASFMSG_COMMAND_MESSAGING,

+ 0x0d, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_NO_BOOTABLE_MEDIA,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_CRITICAL,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_ADD_IN_CARD,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_NO_VIDEO

+ }

+ },

+ {

+ MsgKbdFailure,

+ {

+ ASFMSG_COMMAND_MESSAGING,

+ 0x0d, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_ERROR,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_CRITICAL,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_SYSTEM_BOARD,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_KEYBOARD_FAILURE

+ }

+ },

+ {

+ MsgHddFailure,

+ {

+ ASFMSG_COMMAND_MESSAGING,

+ 0x0d, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_ERROR,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_RECOVERABLE,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_DISK,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_HARD_DISK_FAILURE

+ }

+ },

+ {

+ MsgChassisIntrusion,

+ {

+ ASFMSG_COMMAND_MESSAGING,

+ 0x0b, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_CHASSIS_INTRUSION,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_CHASSIS_INTRUSION,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_MONITOR,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_SYSTEM_BOARD,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED

+ }

+ },

+ {

+ MsgNoBootMedia,

+ {

+ ASFMSG_COMMAND_MESSAGING,

+ 0x0d, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_BOOT_ERROR,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_ERROR,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_RECOVERABLE,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_UNSPECIFIED,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_UNSPECIFIED

+ }

+ }

+};

+

+UINTN mMsgProgressMapSize = sizeof (mMsgProgressMap) / sizeof (MESSAGE_DATA_HUB_MAP);

+UINTN mMsgErrorMapSize = sizeof (mMsgErrorMap) / sizeof (MESSAGE_DATA_HUB_MAP);

+UINTN mAsfMessagesSize = sizeof (mAsfMessages) / sizeof (ASF_MESSAGE);

+

+ASF_MSG_NORETRANSMIT mAsfSystemState =

+{

+ ASFMSG_COMMAND_SYSTEM_STATE,

+ 0x3, // ByteCount

+ ASFMSG_SUBCOMMAND_SET_SYSTEM_STATE,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_SYSTEM_STATE_S0

+};

diff --git a/AsfPkg/Asf/AsfPei/AsfPei.c b/AsfPkg/Asf/AsfPei/AsfPei.c
new file mode 100644
index 000000000000..8b44cd26e0fe
--- /dev/null
+++ b/AsfPkg/Asf/AsfPei/AsfPei.c
@@ -0,0 +1,384 @@
+/** @file

+ Asf Pei Initialization Driver.

+

+ Follow Asf spec to send progress or error message to Smbus device

+

+ Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+**/

+

+#include <AsfMessages.h>

+#include <Base.h>

+#include <Ppi/ReportStatusCodeHandler.h>

+#include <Ppi/MemoryDiscovered.h>

+#include <Ppi/Smbus2.h>

+#include <Library/DebugLib.h>

+#include <Library/PeiServicesLib.h>

+#include <Pi/PiStatusCode.h>

+

+/**

+ This Event Notify processes the ASF request at Memory Initial Completed.

+

+ @param[in] PeiServices General purpose services available to every PEIM.

+ @param[in] NotifyDescriptor The notification structure this PEIM registered on install.

+ @param[in] Ppi The memory discovered PPI. Not used.

+

+ @retval EFI_SUCCESS Succeeds.

+ @retval EFI_UNSUPPORTED Push Event error.

+

+**/

+EFI_STATUS

+EFIAPI

+MsgMemoryInitCompleted (

+ IN EFI_PEI_SERVICES **PeiServices,

+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,

+ IN VOID *Ppi

+ );

+

+STATIC EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyDes = {

+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,

+ &gEfiPeiMemoryDiscoveredPpiGuid,

+ MsgMemoryInitCompleted

+};

+

+ASF_MSG_NORETRANSMIT mAsfSystemStateWorking = \

+{

+ ASFMSG_COMMAND_SYSTEM_STATE,

+ 0x3, // ByteCount

+ ASFMSG_SUBCOMMAND_SET_SYSTEM_STATE,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_SYSTEM_STATE_S0

+};

+

+ASF_MSG_NORETRANSMIT mMsgStopTimer =

+{

+ ASFMSG_COMMAND_MANAGEMENT_CONTROL,

+ 0x2, // ByteCount

+ ASFMSG_SUBCOMMAND_STOP_WATCH_DOG,

+ ASFMSG_VERSION_NUMBER_10

+};

+

+// 3.1.5.3 System Firmware Progress Events

+ASF_MSG_NORETRANSMIT mMsgBiosPresent =

+{

+ ASFMSG_COMMAND_MESSAGING,

+ 0xd, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_ENTITY_PRESENCE,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_ENTITY_PRESENT,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_CRITICAL,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_BIOS,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_UNSPECIFIED

+};

+

+// Starting memory initialization and test.

+ASF_MSG_NORETRANSMIT mMsgMemoryInit =

+{

+ ASFMSG_COMMAND_MESSAGING,

+ 0xd, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_PROGRESS_ENTRY,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_CRITICAL,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_MEMORY_DEVICE,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_MEMORY_INITIALIZATION

+};

+

+// Memory initialized and tested.

+ASF_MSG_NORETRANSMIT mMsgMemoryInitialized =

+{

+ ASFMSG_COMMAND_MESSAGING,

+ 0xd, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_PROGRESS_EXIT,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_CRITICAL,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_MEMORY_DEVICE,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_MEMORY_INITIALIZATION

+};

+

+ASF_MSG_NORETRANSMIT mAsfmsgCacheInit =

+{

+ ASFMSG_COMMAND_MESSAGING,

+ 0xd, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_PROGRESS_ENTRY,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_MONITOR,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_PROCESSOR,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_CACHE_INITIALIZATION

+};

+

+ASF_MSG_NORETRANSMIT mAsfmsgMemoryMissing =

+{

+ ASFMSG_COMMAND_MESSAGING,

+ 0xd, // ByteCount

+ ASFMSG_SUBCOMMAND_NO_RETRANSMIT,

+ ASFMSG_VERSION_NUMBER_10,

+ ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS,

+ ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC,

+ ASFMSG_EVENT_OFFSET_SYS_FW_ERROR,

+ ASFMSG_EVENT_SOURCE_TYPE_ASF10,

+ ASFMSG_EVENT_SEVERITY_NON_CRITICAL,

+ ASFMSG_SENSOR_DEVICE_UNSPECIFIED,

+ ASFMSG_SENSOR_NUMBER_UNSPECIFIED,

+ ASFMSG_ENTITY_MEMORY_DEVICE,

+ ASFMSG_ENTITY_INSTANCE_UNSPECIFIED,

+ ASFMSG_EVENT_DATA1,

+ ASFMSG_EVENT_DATA_NO_MEMORY

+};

+

+/**

+ This function pushes the PEI System Firmware Progress Events.

+

+ @param[in] SmBus Pointer to the SmBus PPI.

+ @param[in] FixedTargetAddress Device address

+ @param[in] MessageErrorLevel Progress or error or system management message Type.

+ @param[in] MessageBuffer Pointer to the Event Data Buffer.

+

+**/

+VOID

+EFIAPI

+AsfPushProgressMessage (

+ IN EFI_PEI_SMBUS2_PPI *SmBus,

+ IN EFI_SMBUS_DEVICE_ADDRESS FixedTargetAddress,

+ IN UINT32 MessageErrorLevel,

+ IN UINT8 *MessageBuffer

+ )

+{

+ EFI_STATUS Status;

+ UINTN Length;

+

+ if (MessageErrorLevel & PcdGet32 (PcdAsfMessageErrorLevel)) {

+ Length = ((ASF_MSG_NORETRANSMIT *)MessageBuffer)->ByteCount;

+ Status = SmBus->Execute (

+ SmBus,

+ FixedTargetAddress,

+ ((ASF_MSG_NORETRANSMIT *)MessageBuffer)->Command,

+ EfiSmbusWriteBlock,

+ TRUE,

+ &Length,

+ (UINT8 *)(MessageBuffer+2)

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_ERROR, "Push alert message fail, status = %r\n", Status));

+ }

+ }

+

+ return;

+}

+

+/**

+ This callback registered by Report Status Code Ppi for Memory Missing PET.

+

+ @param[in] PeiServices General purpose services available to every PEIM.

+ @param[in] Type Indicates the type of status code being reported.

+ @param[in] Value Describes the current status of a hardware or software entity.

+ This included information about the class and subclass that is

+ used to classify the entity as well as an operation.

+ @param[in] Instance The enumeration of a hardware or software entity within the system.

+ Valid instance numbers start with 1.

+ @param[in] CallerId This optional parameter may be used to identify the caller.

+ This parameter allows the status code driver to apply different

+ rules to different callers.

+ @param[in] Data This optional parameter may be used to pass additional data.

+

+ @retval EFI_SUCCESS Always return EFI_SUCCESS

+

+**/

+EFI_STATUS

+EFIAPI

+AsfPeiStatusCodeCallBack (

+ IN EFI_PEI_SERVICES **PeiServices,

+ IN EFI_STATUS_CODE_TYPE Type,

+ IN EFI_STATUS_CODE_VALUE Value,

+ IN UINT32 Instance,

+ IN EFI_GUID *CallerId,

+ IN EFI_STATUS_CODE_DATA *Data

+ )

+{

+ EFI_STATUS Status;

+ EFI_PEI_SMBUS2_PPI *SmBus;

+ EFI_SMBUS_DEVICE_ADDRESS FixedTargetAddress;

+

+ FixedTargetAddress.SmbusDeviceAddress = PcdGet8 (PcdSmbusSlaveAddressForDashLan) >> 1;

+ if (FixedTargetAddress.SmbusDeviceAddress == 0) {

+ return EFI_SUCCESS;

+ }

+

+ Status = PeiServicesLocatePpi (

+ &gEfiPeiSmbus2PpiGuid,

+ 0,

+ NULL,

+ (VOID **)&SmBus

+ );

+ if ( EFI_ERROR (Status)) {

+ return EFI_SUCCESS;

+ }

+

+ if ((Type & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) {

+ if ((Value == (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_EC_MEMORY_NOT_INSTALLED)) ||

+ (Value == (EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_EC_NONE_DETECTED)))

+ {

+ // Error message - Memory Missing.

+ AsfPushProgressMessage (SmBus, FixedTargetAddress, MESSAGE_ERROR_LEVEL_ERROR, (UINT8 *)&mAsfmsgMemoryMissing);

+ }

+ }

+

+ if (((Type & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) &&

+ (Value == (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_CACHE_INIT)))

+ {

+ // Progress message - Cache initialization.

+ AsfPushProgressMessage (SmBus, FixedTargetAddress, MESSAGE_ERROR_LEVEL_PROGRESS, (UINT8 *)&mAsfmsgCacheInit);

+ }

+

+ return EFI_SUCCESS;

+}

+

+/**

+ This send memory initialized message after memory discovered.

+

+ @param[in] PeiServices General purpose services available to every PEIM.

+ @param[in] NotifyDescriptor The notification structure this PEIM registered on install.

+ @param[in] Ppi The memory discovered PPI.

+

+ @retval EFI_SUCCESS Always return EFI_SUCCESS

+

+**/

+EFI_STATUS

+EFIAPI

+MsgMemoryInitCompleted (

+ IN EFI_PEI_SERVICES **PeiServices,

+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,

+ IN VOID *Ppi

+ )

+{

+ EFI_STATUS Status;

+ EFI_PEI_SMBUS2_PPI *SmBus;

+ EFI_BOOT_MODE BootMode;

+ EFI_SMBUS_DEVICE_ADDRESS FixedTargetAddress;

+

+ FixedTargetAddress.SmbusDeviceAddress = PcdGet8 (PcdSmbusSlaveAddressForDashLan) >> 1;

+ if (FixedTargetAddress.SmbusDeviceAddress == 0) {

+ return EFI_SUCCESS;

+ }

+

+ Status = PeiServicesLocatePpi (

+ &gEfiPeiSmbus2PpiGuid,

+ 0,

+ NULL,

+ (VOID **)&SmBus

+ );

+ if ( EFI_ERROR (Status)) {

+ return EFI_SUCCESS;

+ }

+

+ // Progress message - Completed memory initialization and test.

+ AsfPushProgressMessage (SmBus, FixedTargetAddress, MESSAGE_ERROR_LEVEL_PROGRESS, (UINT8 *)&mMsgMemoryInitialized);

+

+ // Get Boot Path.

+ Status = PeiServicesGetBootMode (&BootMode);

+ if (!EFI_ERROR (Status) && (BootMode == BOOT_ON_S3_RESUME)) {

+ // Push System State Working if S3 resuming.

+ AsfPushProgressMessage (

+ SmBus,

+ FixedTargetAddress,

+ MESSAGE_ERROR_LEVEL_SYSTEM_MANAGEMENT,

+ (UINT8 *)&mAsfSystemStateWorking

+ );

+ }

+

+ return EFI_SUCCESS;

+}

+

+/**

+ Asf PEI module entry point

+

+ @param[in] FileHandle FileHandle Handle of the file being invoked.

+ @param[in] PeiServices Describes the list of possible PEI Services.

+

+ @retval EFI_SUCCESS The PEIM initialized successfully.

+

+**/

+EFI_STATUS

+EFIAPI

+AsfPeiEntry (

+ IN EFI_PEI_FILE_HANDLE FileHandle,

+ IN CONST EFI_PEI_SERVICES **PeiServices

+ )

+{

+ EFI_STATUS Status;

+ EFI_PEI_SMBUS2_PPI *SmBus;

+ EFI_PEI_RSC_HANDLER_PPI *RscHndrPpi;

+ EFI_SMBUS_DEVICE_ADDRESS FixedTargetAddress;

+

+ FixedTargetAddress.SmbusDeviceAddress = PcdGet8 (PcdSmbusSlaveAddressForDashLan) >> 1;

+ if (FixedTargetAddress.SmbusDeviceAddress == 0) {

+ return EFI_UNSUPPORTED;

+ }

+

+ Status = PeiServicesLocatePpi (

+ &gEfiPeiSmbus2PpiGuid,

+ 0,

+ NULL,

+ (VOID **)&SmBus

+ );

+ if (EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ //

+ // If the managed client's firmware supports a system boot-failure watchdog timer,

+ // the firmware issues the Stop Watchdog Timer command to stop the timer that is

+ // automatically started by the alert-sending device at power-on reset.

+ //

+ AsfPushProgressMessage (SmBus, FixedTargetAddress, MESSAGE_ERROR_LEVEL_SYSTEM_MANAGEMENT, (UINT8 *)&mMsgStopTimer);

+

+ // Progress message - BIOS Present.

+ AsfPushProgressMessage (SmBus, FixedTargetAddress, MESSAGE_ERROR_LEVEL_PROGRESS, (UINT8 *)&mMsgBiosPresent);

+

+ // Progress message - Started memory initialization and test.

+ AsfPushProgressMessage (SmBus, FixedTargetAddress, MESSAGE_ERROR_LEVEL_PROGRESS, (UINT8 *)&mMsgMemoryInit);

+

+ PeiServicesNotifyPpi (&mMemoryDiscoveredNotifyDes);

+

+ Status = PeiServicesLocatePpi (

+ &gEfiPeiRscHandlerPpiGuid,

+ 0,

+ NULL,

+ (VOID **)&RscHndrPpi

+ );

+ if (!EFI_ERROR (Status)) {

+ RscHndrPpi->Register ((EFI_PEI_RSC_HANDLER_CALLBACK)AsfPeiStatusCodeCallBack);

+ }

+

+ return EFI_SUCCESS;

+}

diff --git a/AsfPkg/Library/AsfAcpiTableLib/AsfAcpiTableLib.c b/AsfPkg/Library/AsfAcpiTableLib/AsfAcpiTableLib.c
new file mode 100644
index 000000000000..7476dbf52752
--- /dev/null
+++ b/AsfPkg/Library/AsfAcpiTableLib/AsfAcpiTableLib.c
@@ -0,0 +1,210 @@
+/** @file

+ Asf Acpi table

+

+ Install Asf Acpi table

+

+ Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+**/

+

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/DebugLib.h>

+#include <Protocol/AcpiSystemDescriptionTable.h>

+#include <IndustryStandard/AlertStandardFormatTable.h>

+#include <IndustryStandard/Acpi.h>

+#include <Protocol/AcpiTable.h>

+

+// ASF Table Definitions

+// Below array size define should follow AsfAcpiTable setting

+#define ASF_RCTL_DEVICES_ARRAY_LENGTH 4

+#define ASF_ADDR_DEVICE_ARRAY_LENGTH 11

+

+#pragma pack(push,1)

+

+//

+// Alert Remote Control System Actions.

+//

+typedef struct {

+ EFI_ACPI_ASF_RCTL AsfRctl;

+ EFI_ACPI_ASF_CONTROLDATA ControlDataArray[ASF_RCTL_DEVICES_ARRAY_LENGTH];

+} ACPI_ASF_RCTL_ALL;

+

+//

+// SmBus Devices with fixed addresses.

+//

+typedef struct {

+ EFI_ACPI_ASF_ADDR AsfAddr;

+ UINT8 FixedSmBusAddresses[ASF_ADDR_DEVICE_ARRAY_LENGTH];

+} ACPI_ASF_ADDR_ALL;

+

+//

+// ACPI 1.0 Structure for ASF Descriptor Table.

+//

+typedef struct {

+ EFI_ACPI_SDT_HEADER Header;

+ EFI_ACPI_ASF_INFO AsfInfo;

+ ACPI_ASF_RCTL_ALL AsfRctlAll;

+ EFI_ACPI_ASF_RMCP AsfRmcp;

+ ACPI_ASF_ADDR_ALL AsfAddrAll;

+} ASF_DESCRIPTION_TABLE;

+

+#pragma pack(pop)

+

+#define EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE_REVISION 0x20

+

+ASF_DESCRIPTION_TABLE AsfAcpiTable = {

+ {

+ EFI_ACPI_ASF_DESCRIPTION_TABLE_SIGNATURE,

+ sizeof (ASF_DESCRIPTION_TABLE),

+ EFI_ACPI_1_0_ASF_DESCRIPTION_TABLE_REVISION,

+ 0, // Checksum

+

+ // OEM identification

+ { 'O', 'E', 'M', '_', 'I', 'D' },

+

+ // OEM table identification

+ { 'D', '8', '6', '5', 'G', 'C', 'H', ' '}, // OEM table identification

+

+ 1, // OEM revision number

+ ((((('M' << 8) + 'S') << 8) + 'F') << 8) + 'T', // ASL compiler vendor ID

+ 1000000 // ASL compiler revision number

+ },

+ {

+ //

+ // EFI_ACPI_ASF_INFO

+ //

+ {

+ 0x00, // Type "ASF_INFO"

+ 0x00, // Reserved

+ sizeof (EFI_ACPI_ASF_INFO) // Length

+ },

+ 0x05, // Min Watchdog Reset Value

+ 0xFF, // Min ASF Sensor poll Wait Time

+ 0x0001, // System ID

+ 0x57010000, // IANA Manufacture ID for Intel

+ 0x00, // Feature Flag

+ {

+ 0x00, // Reserved

+ 0x00,

+ 0x00

+ } // Reserved

+ },

+ {

+ //

+ // ACPI_ASF_RCTL_ALL

+ //

+ {

+ //

+ // EFI_ACPI_ASF_RCTL

+ //

+ {

+ 0x02, // Type "ASF_RCTL"

+ 0x00, // Reserved

+ sizeof (ACPI_ASF_RCTL_ALL) // Length

+ },

+ 0x04, // Number of Controls

+ 0x04, // Array Element Length

+ 0x0000 // Reserved

+ },

+ {

+ //

+ // EFI_ACPI_ASF_CONTROLDATA

+ //

+ { 0x00, 0x88, 0x00, 0x03 }, // Control 0 --> Reset system

+ { 0x01, 0x88, 0x00, 0x02 }, // Control 1 --> Power Off system

+ { 0x02, 0x88, 0x00, 0x01 }, // Control 2 --> Power On system

+ { 0x03, 0x88, 0x00, 0x04 } // Control 3 --> Power Cycle Reset (off then on)

+ }

+ },

+ {

+ //

+ // EFI_ACPI_ASF_RMCP

+ //

+ {

+ 0x03, // Type "ASF_RMCP"

+ 0x00, // Reserved

+ sizeof (EFI_ACPI_ASF_RMCP) // Length

+ },

+ {

+ // Remote Control Capabilities supported Bit Masks

+ 0x00, // System Firmware Capabilities Bit Mask byte 1

+ 0x00, // System Firmware Capabilities Bit Mask byte 2

+ 0x00, // System Firmware Capabilities Bit Mask byte 3

+ 0x00, // System Firmware Capabilities Bit Mask byte 4

+ 0x00, // Special Commands Bit Mask byte 1

+ 0x00, // Special Commands Bit Mask byte 2

+ 0xF0 // System Capabilities Bit Mask (Supports Reset,

+ // Power-Up, Power-Down, Power-Cycle Reset for

+ // compat and secure port.

+ },

+ 0x00, // Boot Option Complete Code

+ 0x57010000, // IANA ID for Intel Manufacturer

+ 0x00, // Special Command

+ { 0x00, 0x00 }, // Special Command Parameter

+ { 0x00, 0x00 }, // Boot Options

+ { 0x00, 0x00 } // OEM Parameters

+ },

+ {

+ //

+ // ACPI_ASF_ADDR_ALL

+ //

+ {

+ //

+ // EFI_ACPI_ASF_ADDR

+ //

+ {

+ 0x84, // Type "ASF_ADDR", last record

+ 0x00, // Reserved

+ sizeof (ACPI_ASF_ADDR_ALL) // Length

+ },

+ 0x00, // SEEPROM Address

+ ASF_ADDR_DEVICE_ARRAY_LENGTH // Number Of Devices

+ },

+ //

+ // Fixed SMBus Address

+ //

+ {

+ 0x5C, 0x68, 0x88, 0xC2, 0xD2,

+ 0xDC, 0xA0, 0xA2, 0xA4, 0xA6,

+ 0xC8

+ }

+ }

+};

+

+/**

+ This function install the ASF acpi Table.

+

+ @param[in] Event A pointer to the Event that triggered the callback.

+ @param[in] Context A pointer to private data registered with the callback function.

+**/

+VOID

+EFIAPI

+InstallAsfAcpiTableEvent (

+ IN EFI_EVENT Event,

+ IN VOID *Context

+ )

+{

+ EFI_STATUS Status;

+ UINTN TableHandle = 0;

+ EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;

+

+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol);

+

+ if ( EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_ERROR, "Locate Acpi protocol %r Error\n", Status));

+ return;

+ }

+

+ if (Event != NULL) {

+ gBS->CloseEvent (Event);

+ }

+

+ AcpiTableProtocol->InstallAcpiTable (

+ AcpiTableProtocol,

+ &AsfAcpiTable,

+ AsfAcpiTable.Header.Length,

+ &TableHandle

+ );

+

+ return;

+}

diff --git a/AsfPkg/Asf/AsfDxe/AsfDxe.h b/AsfPkg/Asf/AsfDxe/AsfDxe.h
new file mode 100644
index 000000000000..7f59fc27d86d
--- /dev/null
+++ b/AsfPkg/Asf/AsfDxe/AsfDxe.h
@@ -0,0 +1,67 @@
+/** @file

+ Asf Dxe driver which is used for sending event record log to NIC or receiving

+ boot option command from NIC and provide in Asf Dxe protocol.

+

+ Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+**/

+

+#ifndef __ASF_DXE_H__

+#define __ASF_DXE_H__

+

+#include <Pi/PiStatusCode.h>

+#include <Protocol/AsfProtocol.h>

+#include <IndustryStandard/SmBus.h>

+#include <Protocol/SmbusHc.h>

+#include <Protocol/ReportStatusCodeHandler.h>

+#include <Library/BaseLib.h>

+#include <Library/UefiLib.h>

+#include <Library/DebugLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/UefiRuntimeServicesTableLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/PrintLib.h>

+#include <Protocol/AcpiTable.h>

+#include <Library/AsfAcpiTableLib.h>

+#include <AsfMessages.h>

+

+extern MESSAGE_DATA_HUB_MAP mMsgProgressMap[];

+extern MESSAGE_DATA_HUB_MAP mMsgErrorMap[];

+extern ASF_MESSAGE mAsfMessages[];

+extern UINTN mMsgProgressMapSize;

+extern UINTN mMsgErrorMapSize;

+extern UINTN mAsfMessagesSize;

+extern ASF_MSG_NORETRANSMIT mAsfSystemState;

+

+/**

+ This function pushes the DXE System Firmware Events.

+

+ @param[in] Command Command of System Firmware Events.

+ @param[in] Length Length of the data in bytes.

+ @param[in] AsfEvent System Firmware Events Command.

+

+ @retval EFI_SUCCESS Push Event successfully.

+ @retval EFI_UNSUPPORTED Push Event error.

+**/

+EFI_STATUS

+EFIAPI

+AsfPushEvent (

+ IN UINT8 Command,

+ IN UINTN Length,

+ IN UINT8 *AsfEvent

+ );

+

+/**

+ This function install the ASF acpi Table.

+

+ @param[in] Event A pointer to the Event that triggered the callback.

+ @param[in] Context A pointer to private data registered with the callback function.

+**/

+VOID

+EFIAPI

+InstallAsfAcpiTableEvent (

+ IN EFI_EVENT Event,

+ IN VOID *Context

+ );

+

+#endif //__ASF_DXE_H__

diff --git a/AsfPkg/Asf/AsfDxe/AsfDxe.inf b/AsfPkg/Asf/AsfDxe/AsfDxe.inf
new file mode 100644
index 000000000000..247fc6ca9da6
--- /dev/null
+++ b/AsfPkg/Asf/AsfDxe/AsfDxe.inf
@@ -0,0 +1,52 @@
+## @file

+# Asf Dxe driver which is used for sending event record log to NIC or receiving

+# boot option command from NIC and provide in Asf Dxe protocol.

+#

+# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+##

+

+[Defines]

+ INF_VERSION = 0x00010005

+ BASE_NAME = AsfDxe

+ MODULE_UNI_FILE = AsfDxe.uni

+ FILE_GUID = ED7AD1A2-1427-41EC-A71E-32EC9A1549E8

+ MODULE_TYPE = DXE_DRIVER

+ VERSION_STRING = 1.0

+ ENTRY_POINT = AsfDxeEntry

+

+[Sources]

+ AsfDxe.c

+ AsfDxe.h

+ AsfDxeEvent.c

+

+[Packages]

+ MdePkg/MdePkg.dec

+ AsfPkg/AsfPkg.dec

+

+[LibraryClasses]

+ UefiDriverEntryPoint

+ UefiRuntimeServicesTableLib

+ DebugLib

+ BaseMemoryLib

+ PrintLib

+ AsfAcpiTableLib

+ UefiLib

+

+[Protocols]

+ gEfiRscHandlerProtocolGuid

+ gAsfProtocolGuid # Produce

+ gEfiAcpiTableProtocolGuid

+ gEfiSmbusHcProtocolGuid

+

+[Guids]

+

+[FixedPcd]

+ gAsfPkgTokenSpaceGuid.PcdSmbusSlaveAddressForDashLan

+ gAsfPkgTokenSpaceGuid.PcdAsfMessageErrorLevel

+

+[Depex]

+ TRUE

+

+[UserExtensions.TianoCore."ExtraFiles"]

+ AsfDxeExtra.uni

diff --git a/AsfPkg/Asf/AsfDxe/AsfDxe.uni b/AsfPkg/Asf/AsfDxe/AsfDxe.uni
new file mode 100644
index 000000000000..02ff1f72931d
--- /dev/null
+++ b/AsfPkg/Asf/AsfDxe/AsfDxe.uni
@@ -0,0 +1,15 @@
+// /** @file

+// Asf DXE Module

+//

+// Follow Asf spec to send progress or error message to Smbus device

+//

+// Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+// SPDX-License-Identifier: BSD-2-Clause-Patent

+//

+// **/

+

+

+#string STR_MODULE_ABSTRACT #language en-US "Asf DXE Module"

+

+#string STR_MODULE_DESCRIPTION #language en-US "Follow Asf spec to send progress or error message to Smbus device."

+

diff --git a/AsfPkg/Asf/AsfDxe/AsfDxeExtra.uni b/AsfPkg/Asf/AsfDxe/AsfDxeExtra.uni
new file mode 100644
index 000000000000..dbc747257c85
--- /dev/null
+++ b/AsfPkg/Asf/AsfDxe/AsfDxeExtra.uni
@@ -0,0 +1,13 @@
+// /** @file

+// Asf Dxe Module

+//

+// Follow Asf spec to send progress or error message to Smbus device

+//

+// Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+// SPDX-License-Identifier: BSD-2-Clause-Patent

+//

+// **/

+

+#string STR_PROPERTIES_MODULE_NAME

+#language en-US

+"Asf DXE"

diff --git a/AsfPkg/Asf/AsfPei/AsfPei.inf b/AsfPkg/Asf/AsfPei/AsfPei.inf
new file mode 100644
index 000000000000..0569a86e0925
--- /dev/null
+++ b/AsfPkg/Asf/AsfPei/AsfPei.inf
@@ -0,0 +1,57 @@
+## @file

+# Asf PEIM

+#

+# Follow Asf spec to send progress or error message to Smbus device

+#

+# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+##

+

+[Defines]

+ INF_VERSION = 0x00010005

+ BASE_NAME = AsfPei

+ MODULE_UNI_FILE = AsfPei.uni

+ FILE_GUID = D2603B09-B8A2-4837-AA1E-EAE8E4DF78E7

+ MODULE_TYPE = PEIM

+ VERSION_STRING = 1.0

+ ENTRY_POINT = AsfPeiEntry

+

+#

+# The following information is for reference only and not required by the build tools.

+#

+# VALID_ARCHITECTURES = IA32 X64 EBC

+#

+

+[Sources]

+ AsfPei.c

+

+[Packages]

+ MdePkg/MdePkg.dec

+ AsfPkg/AsfPkg.dec

+

+[LibraryClasses]

+ PeimEntryPoint

+ PeiServicesLib

+ DebugLib

+

+[Guids]

+

+[Ppis]

+ gEfiPeiRscHandlerPpiGuid

+ gEfiPeiMemoryDiscoveredPpiGuid

+ gEfiPeiSmbus2PpiGuid

+

+[FeaturePcd]

+

+[Pcd]

+

+[FixedPcd]

+ gAsfPkgTokenSpaceGuid.PcdSmbusSlaveAddressForDashLan

+ gAsfPkgTokenSpaceGuid.PcdAsfMessageErrorLevel

+

+[Depex]

+ gEfiPeiSmbus2PpiGuid

+

+[UserExtensions.TianoCore."ExtraFiles"]

+ AsfPeiExtra.uni

+

diff --git a/AsfPkg/Asf/AsfPei/AsfPei.uni b/AsfPkg/Asf/AsfPei/AsfPei.uni
new file mode 100644
index 000000000000..646712917e12
--- /dev/null
+++ b/AsfPkg/Asf/AsfPei/AsfPei.uni
@@ -0,0 +1,15 @@
+// /** @file

+// Asf PEI Module

+//

+// Follow Asf spec to send progress or error message to Smbus device

+//

+// Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+// SPDX-License-Identifier: BSD-2-Clause-Patent

+//

+// **/

+

+

+#string STR_MODULE_ABSTRACT #language en-US "Asf PEI Module"

+

+#string STR_MODULE_DESCRIPTION #language en-US "Follow Asf spec to send progress or error message to Smbus device."

+

diff --git a/AsfPkg/Asf/AsfPei/AsfPeiExtra.uni b/AsfPkg/Asf/AsfPei/AsfPeiExtra.uni
new file mode 100644
index 000000000000..72819f49862c
--- /dev/null
+++ b/AsfPkg/Asf/AsfPei/AsfPeiExtra.uni
@@ -0,0 +1,13 @@
+// /** @file

+// Asf PEI Module

+//

+// Follow Asf spec to send progress or error message to Smbus device

+//

+// Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+// SPDX-License-Identifier: BSD-2-Clause-Patent

+//

+// **/

+

+#string STR_PROPERTIES_MODULE_NAME

+#language en-US

+"Asf PEI"

diff --git a/AsfPkg/AsfPkg.dec b/AsfPkg/AsfPkg.dec
new file mode 100644
index 000000000000..b7bca0ac2231
--- /dev/null
+++ b/AsfPkg/AsfPkg.dec
@@ -0,0 +1,47 @@
+## @file

+# This package defines Asf specific interfaces and library classes.

+#

+# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+##

+

+[Defines]

+ DEC_SPECIFICATION = 0x00010005

+ PACKAGE_NAME = AsfPkg

+ PACKAGE_GUID = 025BE9BD-50B3-4139-9A70-4336E277339A

+ PACKAGE_VERSION = 1.0

+

+[Includes]

+ Include

+

+[LibraryClasses]

+ ## @libraryclass Install Asf Acpi table

+ ##

+ AsfAcpiTableLib|AsfPkg\Library\AsfAcpiTableLib\AsfAcpiTableLib.inf

+

+[Guids]

+ gAsfPkgTokenSpaceGuid = { 0xa12d9aa4, 0xe69b, 0x425c, { 0x96, 0xc5, 0x41, 0x8d, 0xb1, 0xd0, 0xb9, 0x4f }}

+

+[Ppis]

+

+[Protocols]

+ ## Asf protocol GUID

+ # Include/Protocol/AmiAsfProtocol.h

+ gAsfProtocolGuid = { 0xdec89827, 0x8a7e, 0x45e0, { 0xbc, 0xb5, 0xd5, 0x3b, 0x46, 0x14, 0xad, 0xb8 } }

+

+[PcdsFeatureFlag]

+

+[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]

+ ## Specify the Dash lan SmBus slave address.

+ # @Prompt Slave address of Dash lan

+ gAsfPkgTokenSpaceGuid.PcdSmbusSlaveAddressForDashLan|0x0|UINT8|0x00000001

+

+ ## This flag is used to control which message would be send.

+ # If enabled, Asf driver will send message to device.<BR><BR>

+ # BIT0 - Progress message is enabled.<BR>

+ # BIT1 - Error message is enabled.<BR>

+ # BIT2 - System menagement message is enabled.<BR>

+ # Other - reserved

+ # @Prompt Message level

+ gAsfPkgTokenSpaceGuid.PcdAsfMessageErrorLevel|0x7|UINT32|0x00000002

+

diff --git a/AsfPkg/AsfPkg.dsc b/AsfPkg/AsfPkg.dsc
new file mode 100644
index 000000000000..acbede1ca02d
--- /dev/null
+++ b/AsfPkg/AsfPkg.dsc
@@ -0,0 +1,59 @@
+## @file

+# Asf Package

+#

+# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+##

+

+[Defines]

+ PLATFORM_NAME = AsfPkg

+ PLATFORM_GUID = 79D22E13-3F30-470A-AF9D-B80CB4324379

+ PLATFORM_VERSION = 0.10

+ DSC_SPECIFICATION = 0x00010005

+ OUTPUT_DIRECTORY = Build/AsfPkg

+ SUPPORTED_ARCHITECTURES = IA32|X64

+ BUILD_TARGETS = DEBUG|RELEASE|NOOPT

+

+

+[LibraryClasses]

+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf

+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf

+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf

+ SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf

+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf

+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf

+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf

+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf

+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf

+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf

+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf

+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf

+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf

+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf

+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf

+ ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf

+ RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf

+

+

+[LibraryClasses.common.SEC]

+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf

+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf

+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf

+

+[LibraryClasses.common.PEIM]

+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf

+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf

+

+[LibraryClasses.IA32.PEIM, LibraryClasses.X64.PEIM]

+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf

+

+[LibraryClasses.common.DXE_DRIVER]

+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf

+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf

+ AsfAcpiTableLib|AsfPkg\Library\AsfAcpiTableLib\AsfAcpiTableLib.inf

+

+[Components]

+

+[Components.IA32, Components.X64]

+ AsfPkg/Asf/AsfPei/AsfPei.inf

+ AsfPkg/Asf/AsfDxe/AsfDxe.inf

diff --git a/AsfPkg/Include/AsfMessages.h b/AsfPkg/Include/AsfMessages.h
new file mode 100644
index 000000000000..6e79f4993f33
--- /dev/null
+++ b/AsfPkg/Include/AsfMessages.h
@@ -0,0 +1,104 @@
+/** @file

+ Asf message format define.

+

+ Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+ @par Revision Reference:

+ Format defined in Asf 2.0 Specification.

+**/

+

+#ifndef __ASF_MESSAGES_H__

+#define __ASF_MESSAGES_H__

+

+#include <Base.h>

+#include <IndustryStandard/Asf.h>

+

+#define MESSAGE_ERROR_LEVEL_PROGRESS BIT0

+#define MESSAGE_ERROR_LEVEL_ERROR BIT1

+#define MESSAGE_ERROR_LEVEL_SYSTEM_MANAGEMENT BIT2

+

+#pragma pack(push,1)

+

+/**

+ This message causes the alert-sending device to transmit a single,

+ un-retransmitted PET frame. If the alert-sending device is either temporarily

+ unable to handle the message or unable to send the requested PET frame

+ because the device's transport media is down, the device must NACK the message

+ according to SMBUS_2.0 definitions; otherwise, the device sends the

+ single-frame transmission.

+**/

+typedef struct {

+ UINT8 Command; ///< Message Command.

+ UINT8 ByteCount; ///< Length of the data in bytes.

+ UINT8 SubCommand; ///< SubCommand No Retransmit.

+ UINT8 Version; ///< Version Number.

+ UINT8 EventSensorType; ///< Event Sensor Type.

+ UINT8 EventType; ///< Event Type.

+ UINT8 EventOffset; ///< Event Offset.

+ UINT8 EventSourceType; ///< Describes the originator of the event.

+ UINT8 EventSeverity; ///< The severity of the event

+ UINT8 SensorDevice; ///< The Sensor Device that caused the event

+ UINT8 SensorNumber; ///< Identify a given instance of a sensor relative to the Sensor Device.

+ UINT8 Entity; ///< Indicates the platform device or subsystem associated with the event.

+ UINT8 EntityInstance; ///< Identifies which unique device is associated with the event.

+ UINT8 EventData1;

+ UINT8 EventData2;

+ UINT8 EventData3;

+ UINT8 EventData4;

+ UINT8 EventData5;

+} ASF_MSG_NORETRANSMIT;

+

+/**

+ This is the ASF START WatchDog Timer Data structure.

+

+**/

+typedef struct {

+ UINT8 Command;

+ UINT8 ByteCount;

+ UINT8 SubCommand;

+ UINT8 Version;

+} ASF_STOP_WATCHDOG;

+

+/**

+ This is the ASF Message Type structure.

+

+**/

+typedef enum {

+ MsgHddInit,

+ MsgApInit,

+ MsgUserInitSetup,

+ MsgUsbResourceConfig,

+ MsgPciResourceConfig,

+ MsgVideoInit,

+ MsgKbcInit,

+ MsgKbcTest,

+ MsgMotherBoardInit,

+ MsgNoVideo,

+ MsgKbdFailure,

+ MsgHddFailure,

+ MsgChassisIntrusion,

+ MsgNoBootMedia

+} ASF_MESSAGE_TYPE;

+

+/**

+ This is the Message Data Hub Map Structure.

+

+**/

+typedef struct {

+ ASF_MESSAGE_TYPE MessageType;

+ EFI_STATUS_CODE_VALUE StatusCode;

+} MESSAGE_DATA_HUB_MAP;

+

+/**

+ This is the ASF System Firmware Event Structure.

+

+**/

+typedef struct {

+ ASF_MESSAGE_TYPE Type;

+ ASF_MSG_NORETRANSMIT Message;

+} ASF_MESSAGE;

+

+#pragma pack(pop)

+

+#endif //__ASF_MESSAGES_H__

diff --git a/AsfPkg/Include/IndustryStandard/Asf.h b/AsfPkg/Include/IndustryStandard/Asf.h
new file mode 100644
index 000000000000..69b6a0230d4f
--- /dev/null
+++ b/AsfPkg/Include/IndustryStandard/Asf.h
@@ -0,0 +1,145 @@
+/** @file

+ Asf message commands byte define.

+

+ Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+ @par Revision Reference:

+ Data defined in Asf 2.0 Specification.

+**/

+

+#ifndef __ASF_H__

+#define __ASF_H__

+

+#include <Base.h>

+

+//

+// Boot option messages

+//

+#define ASFMSG_CMD_CONFIG 0x3 // ASF Configuration

+#define ASFMSG_SUBCMD_CLR_BOOT_OPTION 0x15 // Clear Boot Options

+#define ASFMSG_SUBCMD_RET_BOOT_OPTION 0x16 // Return Boot Options

+#define ASFMSG_SUBCMD_NO_BOOT_OPTION 0x17 // No Boot Options

+

+//

+// System states

+//

+#define ASFMSG_SYSTEM_STATE_S0 0 // S0/G0 "Working"

+#define ASFMSG_SYSTEM_STATE_S1 1 // S1

+#define ASFMSG_SYSTEM_STATE_S2 2 // S2

+#define ASFMSG_SYSTEM_STATE_S3 3 // S3

+#define ASFMSG_SYSTEM_STATE_S4 4 // S4

+#define ASFMSG_SYSTEM_STATE_S5 5 // S5/G2 "Soft-off"

+

+//

+// Asf version

+//

+#define ASFMSG_VERSION_NUMBER_10 0x10

+

+//

+// System firmware capabilities Bit

+//

+#define ASF_BOP_BIT_FORCE_PROGRESS_EVENT BIT12

+

+//

+// Asf message command

+//

+#define ASFMSG_COMMAND_SYSTEM_STATE 0x1

+#define ASFMSG_COMMAND_MANAGEMENT_CONTROL 0x2

+#define ASFMSG_COMMAND_MESSAGING 0x4

+

+//

+// Asf message subcommand

+//

+#define ASFMSG_SUBCOMMAND_STOP_WATCH_DOG 0x14

+#define ASFMSG_SUBCOMMAND_NO_RETRANSMIT 0x16

+#define ASFMSG_SUBCOMMAND_SET_SYSTEM_STATE 0x18

+

+//

+// Asf message event sensor type

+//

+#define ASFMSG_EVENT_SENSOR_TYPE_CHASSIS_INTRUSION 0x5

+#define ASFMSG_EVENT_SENSOR_TYPE_FW_ERROR_PROGRESS 0xF

+#define ASFMSG_EVENT_SENSOR_TYPE_BOOT_ERROR 0x1E

+#define ASFMSG_EVENT_SENSOR_TYPE_ENTITY_PRESENCE 0x25

+

+//

+// Asf message event type

+//

+#define ASFMSG_EVENT_TYPE_SENSOR_SPECIFIC 0x6F

+

+//

+// Asf message event offset

+//

+#define ASFMSG_EVENT_OFFSET_ENTITY_PRESENT 0x0

+

+#define ASFMSG_EVENT_OFFSET_SYS_FW_PROGRESS_ENTRY 0x2

+#define ASFMSG_EVENT_OFFSET_SYS_FW_PROGRESS_EXIT 0x82

+#define ASFMSG_EVENT_OFFSET_SYS_FW_ERROR 0x0

+

+#define ASFMSG_EVENT_OFFSET_NO_BOOTABLE_MEDIA 0x0

+#define ASFMSG_EVENT_OFFSET_CHASSIS_INTRUSION 0x0

+

+//

+// Asf message event source type

+//

+#define ASFMSG_EVENT_SOURCE_TYPE_ASF10 0x68

+

+//

+// Asf message event severity

+//

+#define ASFMSG_EVENT_SEVERITY_MONITOR 0x1

+#define ASFMSG_EVENT_SEVERITY_NON_CRITICAL 0x8

+#define ASFMSG_EVENT_SEVERITY_CRITICAL 0x10

+#define ASFMSG_EVENT_SEVERITY_NON_RECOVERABLE 0x20

+

+//

+// Asf message sensor device

+//

+#define ASFMSG_SENSOR_DEVICE_UNSPECIFIED 0xFF

+

+//

+// Asf message sensor number

+//

+#define ASFMSG_SENSOR_NUMBER_UNSPECIFIED 0xFF

+

+//

+// Asf message Entity

+//

+

+#define ASFMSG_ENTITY_UNSPECIFIED 0x0

+#define ASFMSG_ENTITY_PROCESSOR 0x3

+#define ASFMSG_ENTITY_DISK 0x4

+#define ASFMSG_ENTITY_SYSTEM_BOARD 0x7

+#define ASFMSG_ENTITY_ADD_IN_CARD 0xB

+#define ASFMSG_ENTITY_BIOS 0x22

+#define ASFMSG_ENTITY_MEMORY_DEVICE 0x20

+

+//

+// Asf message entity instance

+//

+#define ASFMSG_ENTITY_INSTANCE_UNSPECIFIED 0x0

+

+//

+// Asf message event data

+//

+#define ASFMSG_EVENT_DATA1 0x40

+#define ASFMSG_EVENT_DATA_UNSPECIFIED 0x0

+#define ASFMSG_EVENT_DATA_MEMORY_INITIALIZATION 0x1

+#define ASFMSG_EVENT_DATA_HARD_DISK_INITIALIZATION 0x2

+#define ASFMSG_EVENT_DATA_AP_INITIALIZATION 0x3

+#define ASFMSG_EVENT_DATA_SETUP_INITIALIZATION 0x5

+#define ASFMSG_EVENT_DATA_USB_RESOURCE_CONFIG 0x6

+#define ASFMSG_EVENT_DATA_PCI_RESOURCE_CONFIG 0x7

+#define ASFMSG_EVENT_DATA_VIDEO_INITIALIZATION 0x9

+#define ASFMSG_EVENT_DATA_CACHE_INITIALIZATION 0xA

+#define ASFMSG_EVENT_DATA_KEYBOARD_INITIALIZATION 0xC

+#define ASFMSG_EVENT_DATA_BOARD_INITIALIZATION 0x14

+#define ASFMSG_EVENT_DATA_KEYBOARD_TEST 0x17

+

+#define ASFMSG_EVENT_DATA_NO_MEMORY 0x1

+#define ASFMSG_EVENT_DATA_HARD_DISK_FAILURE 0x3

+#define ASFMSG_EVENT_DATA_KEYBOARD_FAILURE 0x7

+#define ASFMSG_EVENT_DATA_NO_VIDEO 0xA

+

+#endif //__ASF_H__

diff --git a/AsfPkg/Include/Library/AsfAcpiTableLib.h b/AsfPkg/Include/Library/AsfAcpiTableLib.h
new file mode 100644
index 000000000000..4b1d687825ff
--- /dev/null
+++ b/AsfPkg/Include/Library/AsfAcpiTableLib.h
@@ -0,0 +1,26 @@
+/** @file

+ Provides services to create Asf Acpi table.

+

+ Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+**/

+

+#ifndef __ASF_ACPI_TABLE_LIB_H__

+#define __ASF_ACPI_TABLE_LIB_H__

+

+#include <Uefi.h>

+

+/**

+ This function install the ASF acpi Table.

+

+ @param[in] Event A pointer to the Event that triggered the callback.

+ @param[in] Context A pointer to private data registered with the callback function.

+**/

+VOID

+EFIAPI

+InstallAsfAcpiTableEvent (

+ IN EFI_EVENT Event,

+ IN VOID *Context

+ );

+

+#endif

diff --git a/AsfPkg/Include/Protocol/AsfProtocol.h b/AsfPkg/Include/Protocol/AsfProtocol.h
new file mode 100644
index 000000000000..d3af0fba73bd
--- /dev/null
+++ b/AsfPkg/Include/Protocol/AsfProtocol.h
@@ -0,0 +1,57 @@
+/** @file

+ Asf protocol define.

+

+ Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+**/

+

+#ifndef __ASF_PROTOCOL_H__

+#define __ASF_PROTOCOL_H__

+

+#include <IndustryStandard/SmBus.h>

+

+#define ASF_PROTOCOL_GUID \

+ { \

+ 0xdec89827, 0x8a7e, 0x45e0, { 0xbc, 0xb5, 0xd5, 0x3b, 0x46, 0x14, 0xad, 0xb8 } \

+ }

+

+#pragma pack(push, 1)

+

+/**

+ This is the ASF Boot Option data structure.

+

+**/

+typedef struct {

+ UINT8 SubCommand;

+ UINT8 Version;

+ UINT32 IanaId;

+ UINT8 SpecialCommand;

+ UINT16 SpecCmdParameter;

+ UINT16 BootOptionBit;

+ UINT16 OemParameter;

+} ASF_BOOT_OPTION;

+

+/**

+ This is the ASF PUSH EVENT Structure.

+

+**/

+typedef EFI_STATUS (EFIAPI *ASF_PUSH_EVENT)(

+ IN UINT8 Command,

+ IN UINTN Length,

+ IN UINT8 *ASFEvent

+ );

+

+/**

+ This is the AMI ASF Protocol Structure.

+

+**/

+typedef struct {

+ ASF_PUSH_EVENT PushEvent;

+ ASF_BOOT_OPTION *BootOption;

+} ASF_PROTOCOL;

+

+#pragma pack(pop)

+

+extern EFI_GUID gAsfProtocolGuid;

+

+#endif //__ASF_PROTOCOL_H__

diff --git a/AsfPkg/Library/AsfAcpiTableLib/AsfAcpiTableLib.inf b/AsfPkg/Library/AsfAcpiTableLib/AsfAcpiTableLib.inf
new file mode 100644
index 000000000000..ca90d02f005b
--- /dev/null
+++ b/AsfPkg/Library/AsfAcpiTableLib/AsfAcpiTableLib.inf
@@ -0,0 +1,30 @@
+## @file

+# Asf Acpi table Library instance that create Asf Acpi table

+#

+# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+##

+

+[Defines]

+ INF_VERSION = 0x00010005

+ BASE_NAME = AsfAcpiTableLib

+ MODULE_UNI_FILE = AsfAcpiTableLib.uni

+ FILE_GUID = 9A0EC995-0F1A-444C-BA02-8C3F0482AE8C

+ MODULE_TYPE = DXE_DRIVER

+ VERSION_STRING = 1.0

+ LIBRARY_CLASS = AsfAcpiTableLib | DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER

+

+[Sources]

+ AsfAcpiTableLib.c

+

+[Packages]

+ MdePkg/MdePkg.dec

+ MdeModulePkg/MdeModulePkg.dec

+

+[Protocols]

+ gEfiAcpiTableProtocolGuid ## CONSUMES

+

+[LibraryClasses]

+ BaseLib

+ DebugLib

+

diff --git a/AsfPkg/Library/AsfAcpiTableLib/AsfAcpiTableLib.uni b/AsfPkg/Library/AsfAcpiTableLib/AsfAcpiTableLib.uni
new file mode 100644
index 000000000000..681458140452
--- /dev/null
+++ b/AsfPkg/Library/AsfAcpiTableLib/AsfAcpiTableLib.uni
@@ -0,0 +1,15 @@
+// /** @file

+// Asf Acpi table

+//

+// Install Asf Acpi table

+//

+// Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+// SPDX-License-Identifier: BSD-2-Clause-Patent

+//

+// **/

+

+

+#string STR_MODULE_ABSTRACT #language en-US "Asf Acpi table"

+

+#string STR_MODULE_DESCRIPTION #language en-US "Install Asf Acpi table."

+

--
2.36.0.windows.1
-The information contained in this message may be confidential and proprietary to American Megatrends (AMI). This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited. Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.


[edk2-platform][PATCH] Silicon/NXP: avoid integer overflow when computing Serdes protocol map

Dan Callaghan
 

SerDesProtocolMap is a UINT64, but BIT0 is an unadorned int. Shifting
BIT0 left by more than 31 bits is undefined behaviour. This would cause
SerDesProtocolMap to be filled with incorrect values when using Serdes
protocols numbered 32 and above, such as the SGMII protocols.

This fixes a hang at boot time on the Solidrun Honeycomb with SERDES
configuration 4_5_2.

Signed-off-by: Dan Callaghan <djc@...>
---
Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c | 2 +-
Silicon/NXP/Library/SerDesHelperLib/SerDesHelperLib.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Sili=
con/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
index 7f11d7a602..127eb3e175 100644
--- a/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
+++ b/Silicon/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.c
@@ -748,7 +748,7 @@ IsPcieNumEnabled(
// Reading serdes protocol map=0D
GetSerDesProtocolMap (&SerDesProtocolMap);=0D
=0D
- return (SerDesProtocolMap & (BIT0 << (PcieNum))) !=3D 0;=0D
+ return (SerDesProtocolMap & ((UINT64) BIT0 << (PcieNum))) !=3D 0;=0D
}=0D
=0D
/**=0D
diff --git a/Silicon/NXP/Library/SerDesHelperLib/SerDesHelperLib.c b/Silico=
n/NXP/Library/SerDesHelperLib/SerDesHelperLib.c
index 1e8158541c..62a32d5caf 100644
--- a/Silicon/NXP/Library/SerDesHelperLib/SerDesHelperLib.c
+++ b/Silicon/NXP/Library/SerDesHelperLib/SerDesHelperLib.c
@@ -157,7 +157,7 @@ GetSerDesMap (
DEBUG ((DEBUG_ERROR, "Unknown SerDes lane protocol %d\n", LaneProtoc=
ol));=0D
return EFI_NO_MAPPING;=0D
}=0D
- *SerDesProtocolMap |=3D (BIT0 << (LaneProtocol));=0D
+ *SerDesProtocolMap |=3D ((UINT64) BIT0 << (LaneProtocol));=0D
}=0D
=0D
return EFI_SUCCESS;=0D
--=20
2.36.0


[PATCH] ShellPkg/SmbiosView: Smbiosview tool is not show Extended Speed and Extended Configured Memory Speed in type 17.

xueshengfeng <xueshengfeng@...>
 

From: Shengfengx Xue <shengfengx.xue@...>

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

if Configured Memory Speed is 65,535 MT/s or greater,
and the actual speed is stored in the Extended Configured Memory Speed
field. but current Smbiosview have no this logic.

Signed-off-by: Shengfengx Xue <shengfengx.xue@...>
---
.../UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/Print=
Info.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo=
.c
index a0ee286c9a..0ab9f5063a 100644
--- a/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c
@@ -878,6 +878,11 @@ SmbiosPrintStructure (
}
}
=20
+ if (AE_SMBIOS_VERSION (0x3, 0x3) && (Struct->Hdr->Length > 0x54)) =
{
+ PRINT_STRUCT_VALUE_H (Struct, Type17, ExtendedSpeed);
+ PRINT_STRUCT_VALUE_H (Struct, Type17, ExtendedConfiguredMemorySp=
eed);
+ }
+
break;
=20
//
--=20
2.26.2.windows.1


[PATCH] Local Buffer allocated for Copy of data, is not freed in ShellPkg for CP command

Prarthana Sagar V <prarthanasv@...>
 

---
ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c
index c3927ca35b..2d7e7d0bb4 100644
--- a/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c
@@ -246,6 +246,7 @@ CopySingleFile (
break;

}

}

+ SHELL_FREE_NON_NULL (Buffer);

}



SHELL_FREE_NON_NULL (DestVolumeInfo);

--
2.26.0.windows.1
-The information contained in this message may be confidential and proprietary to American Megatrends (AMI). This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited. Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.


Re: [PATCH v3 0/6] Enhance DynamicTablesPkg modules

Sami Mujawar
 

Hi Kun,

I have just replied to your patch series. I think patches 4 & 5 may need some adjustment.

Can you look into those, please?

Regards,

Sami Mujawar

On 08/08/2022, 16:34, "Kun Qin" <kuqin12@...> wrote:

Hi DynamicTablePkg maintainers,

Just a gentle ping on this patch series. If there is no further
feedback, can we merge
them into the mainline? Otherwise, any feedback is appreciated.

Regards,
Kun

On 8/3/2022 9:57 AM, Kun Qin wrote:
> Hi DynamicTablePkg maintainers,
>
> Do you have any further feedback on this patch series? Any input is
> appreciated.
>
> Thanks,
> Kun
>
> On 7/30/2022 10:37 PM, Kun Qin via groups.io wrote:
>> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3996
>> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3997
>> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3998
>>
>> This patch series is a follow-up of previous submission:
>> https://edk2.groups.io/g/devel/message/91926
>>
>> The main changes between v2 and v3 patches are:
>> - Added reviewed-by collected from previous iteration
>> - Added descriptions for newly introduced structures
>> - Updated functions names
>>
>> Current DynamicTablesPkg provide great support for creating dynamic ACPI
>> tables during boot time.
>>
>> However, there are some modules needs minor tweaks to expand support and
>> compatibility for OS requirements and platform needs.
>>
>> This patch series proposes a few fixes to resolve minor issues
>> discovered
>> in DynamicPlatRepoLib, AcpiSsdtPcieLibArm and DynamicTableManagerDxe.
>>
>> Patch v3 branch: https://github.com/kuqin12/edk2/tree/dynamic_update_v3
>>
>> Cc: Sami Mujawar <Sami.Mujawar@...>
>> Cc: Alexei Fedorov <Alexei.Fedorov@...>
>> Cc: Pierre Gondois <pierre.gondois@...>
>>
>> Kun Qin (6):
>> DynamicTablesPkg: DynamicPlatRepoLib: Added MemoryAllocationLib to
>> inf
>> DynamicTablesPkg: DynamicPlatRepoLib: Fix incorrect dereferencing
>> DynamicTablesPkg: DynamicPlatRepoLib: Adding more token fixers
>> DynamicTablesPkg: DynamicTableManagerDxe: Added check for installed
>> tables
>> DynamicTablesPkg: AcpiSsdtPcieLibArm: Added function to reserve ECAM
>> space
>> DynamicTablesPkg: AcpiSsdtPcieLibArm: Added case handling for PCI
>> config
>>
>> DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c
>> | 214 ++++++++++++--------
>> DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
>> | 176 ++++++++++++++++
>> DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer.c
>> | 80 +++++++-
>> DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
>> | 4 +
>> DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib.inf
>> | 1 +
>> 5 files changed, 391 insertions(+), 84 deletions(-)
>>

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


Re: [PATCH v3 4/6] DynamicTablesPkg: DynamicTableManagerDxe: Added check for installed tables

Sami Mujawar
 

Hi Kun,

Please find my response inline marked [SAMI].

Regards,

Sami Mujawar

On 08/08/2022 02:05 pm, Sami Mujawar wrote:
Hi Kun,

Thank you for this patch.

Please find my response inline marked [SAMI].

Regards,

Sami Mujawar

On 31/07/2022 06:37 am, Kun Qin wrote:
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3997

This change added an extra step to allow check for installed ACPI tables.

For FADT, MADT, GTDT, DSDT, DBG2 and SPCR tables, either pre-installed or
supplied through AcpiTableInfo can be accepted.

An extra check for FADT ACPI table existence during installation step is
also added.

Cc: Sami Mujawar <Sami.Mujawar@...>
Cc: Alexei Fedorov <Alexei.Fedorov@...>

Co-authored-by: Joe Lopez <joelopez@...>
Signed-off-by: Kun Qin <kuqin12@...>
Reviewed-by: Pierre Gondois <pierre.gondois@...>
---

Notes:
     v2:
     - Function description updates [Sami]
     - Refactorized the table verification [Pierre]
          v3:
     - Added descriptions for new structures [Pierre]
     - Added check for SDT protocol PCD before using it [Pierre]

DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c | 214 ++++++++++++--------
DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf |   4 +
  2 files changed, 138 insertions(+), 80 deletions(-)

diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c
index ed62299f9bbd..7f3deef08a66 100644
---
a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c
+++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c
@@ -10,6 +10,7 @@
  #include <Library/DebugLib.h>

  #include <Library/PcdLib.h>

  #include <Library/UefiBootServicesTableLib.h>

+#include <Protocol/AcpiSystemDescriptionTable.h>

  #include <Protocol/AcpiTable.h>


  // Module specific include files.

@@ -22,6 +23,58 @@
  #include <Protocol/DynamicTableFactoryProtocol.h>

  #include <SmbiosTableGenerator.h>


+///

+/// Bit definitions for acceptable ACPI table presence formats.

+/// Currently only ACPI tables present in the ACPI info list and

+/// already installed will count towards "Table Present" during

+/// verification routine.

+///

+#define ACPI_TABLE_PRESENT_INFO_LIST  BIT0

+#define ACPI_TABLE_PRESENT_INSTALLED  BIT1

+

+///

+/// Order of ACPI table being verified during presence inspection.

+///

+#define ACPI_TABLE_VERIFY_FADT   0

+#define ACPI_TABLE_VERIFY_MADT   1

+#define ACPI_TABLE_VERIFY_GTDT   2

+#define ACPI_TABLE_VERIFY_DSDT   3

+#define ACPI_TABLE_VERIFY_DBG2   4

+#define ACPI_TABLE_VERIFY_SPCR   5

+#define ACPI_TABLE_VERIFY_COUNT  6

+

+///

+/// Private data structure to verify the presence of mandatory

+/// or optional ACPI tables.

+///

+typedef struct {

+  /// ESTD ID for the ACPI table of interest.

+  ESTD_ACPI_TABLE_ID    EstdTableId;

+  /// Standard UINT32 ACPI signature.

+  UINT32                AcpiTableSignature;

+  /// 4 character ACPI table name (the 5th char8 is for null terminator).

+  CHAR8                 AcpiTableName[sizeof (UINT32) + 1];

+  /// Indicator on whether the ACPI table is required.

+  BOOLEAN               IsMandatory;

+  /// Formats of verified presences, as defined by ACPI_TABLE_PRESENT_*

+  /// This field should be initialized to 0 and will be populated during

+  /// verification routine.

+  UINT16                Presence;

+} ACPI_TABLE_PRESENCE_INFO;

+

+///

+/// We require the FADT, MADT, GTDT and the DSDT tables to boot.

+/// This list also include optional ACPI tables: DBG2, SPCR.

+///

+ACPI_TABLE_PRESENCE_INFO mAcpiVerifyTables[ACPI_TABLE_VERIFY_COUNT] = {

+  { EStdAcpiTableIdFadt, EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, "FADT", TRUE,  0 },

+  { EStdAcpiTableIdMadt, EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, "MADT", TRUE,  0 },

+  { EStdAcpiTableIdGtdt, EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE, "GTDT", TRUE,  0 },

+  { EStdAcpiTableIdDsdt, EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, "DSDT", TRUE,  0 },

+  { EStdAcpiTableIdDbg2, EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE, "DBG2", FALSE, 0 },

+  { EStdAcpiTableIdSpcr, EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, "SPCR", FALSE, 0 },

+};

+

  /** This macro expands to a function that retrieves the ACPI Table

      List from the Configuration Manager.

  */

@@ -395,6 +448,7 @@ BuildAndInstallAcpiTable (

    @retval EFI_SUCCESS           Success.

    @retval EFI_NOT_FOUND         If mandatory table is not found.

+  @retval EFI_ALREADY_STARTED   If mandatory table found in AcpiTableInfo is already installed.

  **/

  STATIC

  EFI_STATUS

@@ -404,75 +458,71 @@ VerifyMandatoryTablesArePresent (
    IN       UINT32                              AcpiTableCount

    )

  {

-  EFI_STATUS  Status;

-  BOOLEAN     FadtFound;

-  BOOLEAN     MadtFound;

-  BOOLEAN     GtdtFound;

-  BOOLEAN     DsdtFound;

-  BOOLEAN     Dbg2Found;

-  BOOLEAN     SpcrFound;

+  EFI_STATUS                   Status;

+  UINTN                        Handle;

+  UINTN                        Index;

+  UINTN                        InstalledTableIndex;

+  EFI_ACPI_DESCRIPTION_HEADER  *DescHeader;

+  EFI_ACPI_TABLE_VERSION       Version;

+  EFI_ACPI_SDT_PROTOCOL        *AcpiSdt;


-  Status    = EFI_SUCCESS;

-  FadtFound = FALSE;

-  MadtFound = FALSE;

-  GtdtFound = FALSE;

-  DsdtFound = FALSE;

-  Dbg2Found = FALSE;

-  SpcrFound = FALSE;

    ASSERT (AcpiTableInfo != NULL);


+  Status = EFI_SUCCESS;

+

+  // Check against the statically initialized ACPI tables to see if they are in ACPI info list

    while (AcpiTableCount-- != 0) {

-    switch (AcpiTableInfo[AcpiTableCount].AcpiTableSignature) {

-      case EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:

-        FadtFound = TRUE;

-        break;

-      case EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:

-        MadtFound = TRUE;

-        break;

-      case EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE:

-        GtdtFound = TRUE;

-        break;

-      case EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:

-        DsdtFound = TRUE;

-        break;

-      case EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE:

-        Dbg2Found = TRUE;

-        break;

-      case EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:

-        SpcrFound = TRUE;

-        break;

-      default:

+    for (Index = 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {

+      if (AcpiTableInfo[AcpiTableCount].AcpiTableSignature == mAcpiVerifyTables[Index].AcpiTableSignature) {

+        mAcpiVerifyTables[Index].Presence |= ACPI_TABLE_PRESENT_INFO_LIST;

+        // Found this table, skip the rest.

          break;

+      }

      }

    }


-  // We need at least the FADT, MADT, GTDT and the DSDT tables to boot

-  if (!FadtFound) {

-    DEBUG ((DEBUG_ERROR, "ERROR: FADT Table not found\n"));

-    Status = EFI_NOT_FOUND;

-  }

+  // They also might be published already, so we can search from there

+  if (FeaturePcdGet (PcdInstallAcpiSdtProtocol)) {

+    AcpiSdt = NULL;

+    Status  = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&AcpiSdt);


-  if (!MadtFound) {

-    DEBUG ((DEBUG_ERROR, "ERROR: MADT Table not found.\n"));

-    Status = EFI_NOT_FOUND;

-  }

+    if (EFI_ERROR (Status) || (AcpiSdt == NULL)) {

+      DEBUG ((DEBUG_ERROR, "ERROR: Failed to locate ACPI SDT protocol (0x%p) - %r\n", AcpiSdt, Status));

+      return Status;

+    }


-  if (!GtdtFound) {

-    DEBUG ((DEBUG_ERROR, "ERROR: GTDT Table not found.\n"));

-    Status = EFI_NOT_FOUND;

-  }

+    for (Index = 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {

+      Handle              = 0;

+      InstalledTableIndex = 0;

+      do {

+        Status = AcpiSdt->GetAcpiTable (InstalledTableIndex, (EFI_ACPI_SDT_HEADER **)&DescHeader, &Version, &Handle);

+        if (EFI_ERROR (Status)) {
[SAMI] When running Kvmtool guest firmware I break from here with EFI_NOT_FOUND. The problem is PcdInstallAcpiSdtProtocol is set to TRUE in ArmVirt.dsc.inc and the Kvmtool guest firmware does not have any preinstalled tables (i.e. all tables are generated using DynamicTablesFramework).

This means platforms that use only Dynamic Tables Framework would all need to define PcdInstallAcpiSdtProtocol to FALSE. Is it possible to rework this logic so that the existing platform code does not need updating, please?

[/SAMI]


+          break;

+        }


-  if (!DsdtFound) {

-    DEBUG ((DEBUG_ERROR, "ERROR: DSDT Table not found.\n"));

-    Status = EFI_NOT_FOUND;

-  }

+        InstalledTableIndex++;

+      } while (DescHeader->Signature != mAcpiVerifyTables[Index].AcpiTableSignature);


-  if (!Dbg2Found) {

-    DEBUG ((DEBUG_WARN, "WARNING: DBG2 Table not found.\n"));

+      if (!EFI_ERROR (Status)) {

+        mAcpiVerifyTables[Index].Presence |= ACPI_TABLE_PRESENT_INSTALLED;

+      }

+    }

    }


-  if (!SpcrFound) {

-    DEBUG ((DEBUG_WARN, "WARNING: SPCR Table not found.\n"));

+  for (Index = 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {

+    if (mAcpiVerifyTables[Index].Presence == 0) {

+      if (mAcpiVerifyTables[Index].IsMandatory) {

+        DEBUG ((DEBUG_ERROR, "ERROR: %a Table not found.\n", mAcpiVerifyTables[Index].AcpiTableName));

+        Status = EFI_NOT_FOUND;

+      } else {

+        DEBUG ((DEBUG_WARN, "WARNING: %a Table not found.\n", mAcpiVerifyTables[Index].AcpiTableName));

+      }

+    } else if (mAcpiVerifyTables[Index].Presence ==

+               (ACPI_TABLE_PRESENT_INFO_LIST | ACPI_TABLE_PRESENT_INSTALLED))

+    {

+      DEBUG ((DEBUG_ERROR, "ERROR: %a Table found while already published.\n", mAcpiVerifyTables[Index].AcpiTableName));

+      Status = EFI_ALREADY_STARTED;

+    }

    }


    return Status;

@@ -489,8 +539,9 @@ VerifyMandatoryTablesArePresent (
    @param [in]  CfgMgrProtocol       Pointer to the Configuration Manager

                                      Protocol Interface.


-  @retval EFI_SUCCESS   Success.

-  @retval EFI_NOT_FOUND If a mandatory table or a generator is not found.

+  @retval EFI_SUCCESS           Success.

+  @retval EFI_NOT_FOUND         If a mandatory table or a generator is not found.

+  @retval EFI_ALREADY_STARTED   If mandatory table found in AcpiTableInfo is already installed.

  **/

  STATIC

  EFI_STATUS

@@ -562,7 +613,7 @@ ProcessAcpiTables (
    if (EFI_ERROR (Status)) {

      DEBUG ((

        DEBUG_ERROR,

-      "ERROR: Failed to find mandatory ACPI Table(s)."

+      "ERROR: Failed to verify mandatory ACPI Table(s) presence."

        " Status = %r\n",

        Status

        ));

@@ -570,29 +621,32 @@ ProcessAcpiTables (
    }


    // Add the FADT Table first.

-  for (Idx = 0; Idx < AcpiTableCount; Idx++) {

-    if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) ==

-        AcpiTableInfo[Idx].TableGeneratorId)

-    {

-      Status = BuildAndInstallAcpiTable (

-                 TableFactoryProtocol,

-                 CfgMgrProtocol,

-                 AcpiTableProtocol,

-                 &AcpiTableInfo[Idx]

-                 );

-      if (EFI_ERROR (Status)) {

-        DEBUG ((

-          DEBUG_ERROR,

-          "ERROR: Failed to find build and install ACPI FADT Table." \

-          " Status = %r\n",

-          Status

-          ));

-        return Status;

-      }

+  if ((mAcpiVerifyTables[ACPI_TABLE_VERIFY_FADT].Presence & ACPI_TABLE_PRESENT_INSTALLED) == 0) {
[SAMI] If I understand correctly, the mAcpiVerifyTables[x].Presence filed cannot be ACPI_TABLE_PRESENT_INFO_LIST and ACPI_TABLE_PRESENT_INSTALLED at the same time. Otherwise we would have returned EFI_ALREADY_STARTED from VerifyMandatoryTablesArePresent().

Since FADT is mandatory, the only valid conditions are:

1. ACPI_TABLE_PRESENT_INFO_LIST and !ACPI_TABLE_PRESENT_INSTALLED

2. !ACPI_TABLE_PRESENT_INFO_LIST & ACPI_TABLE_PRESENT_INSTALLED

Therefore, I think the above check is not required. What do you think?

[/SAMI]


+    // FADT is not yet installed

+    for (Idx = 0; Idx < AcpiTableCount; Idx++) {

+      if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) ==

+          AcpiTableInfo[Idx].TableGeneratorId)

+      {

+        Status = BuildAndInstallAcpiTable (

+                   TableFactoryProtocol,

+                   CfgMgrProtocol,

+                   AcpiTableProtocol,

+                   &AcpiTableInfo[Idx]

+                   );

+        if (EFI_ERROR (Status)) {

+          DEBUG ((

+            DEBUG_ERROR,

+            "ERROR: Failed to find build and install ACPI FADT Table." \

+            " Status = %r\n",

+            Status

+            ));

+          return Status;

+        }


-      break;

-    }

-  } // for

+        break;

+      }

+    } // for

+  }


    // Add remaining ACPI Tables

    for (Idx = 0; Idx < AcpiTableCount; Idx++) {

diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
index 028c3d413cf8..ad8b3d037c16 100644
---
a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
+++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
@@ -34,8 +34,12 @@ [LibraryClasses]
    UefiBootServicesTableLib

    UefiDriverEntryPoint


+[FeaturePcd]

+  gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol  ## CONSUMES

+

  [Protocols]

    gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED

+  gEfiAcpiSdtProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED


    gEdkiiConfigurationManagerProtocolGuid        # PROTOCOL ALWAYS_CONSUMED

    gEdkiiDynamicTableFactoryProtocolGuid         # PROTOCOL ALWAYS_CONSUMED


Re: [PATCH v3 5/6] DynamicTablesPkg: AcpiSsdtPcieLibArm: Added function to reserve ECAM space

Sami Mujawar
 

Hi Kun,

I have just tried testing your patch with Kvmtool guest firmware and think this patch may need some modifications.

Also, the patch 4/6 may need some adjustment, which I will reply back on that patch separately.

Regards,

Sami Mujawar

On 08/08/2022 02:22 pm, Sami Mujawar wrote:
Hi Kun,

Thank you for this patch.

These changes look good to me.

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

Regards,

Sami Mujawar

On 31/07/2022 06:37 am, Kun Qin via groups.io wrote:
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3998

Certain OSes will complain if the ECAM config space is not reserved in
the ACPI namespace.

This change adds a function to reserve PNP motherboard resources for a
given PCI node.

Co-authored-by: Joe Lopez <joelopez@...>
Signed-off-by: Kun Qin <kuqin12@...>
Reviewed-by: Pierre Gondois <pierre.gondois@...>
---

Notes:
     v2:
     - Only create RES0 after config space checking [Pierre]
          v3:
     - Updated function names and descriptions [Pierre]
     - Moved translation calculation to CONFIG case [Pierre]

  DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c | 171 ++++++++++++++++++++
  1 file changed, 171 insertions(+)

diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
index ceffe2838c03..658a089c8f1f 100644
--- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
@@ -616,6 +616,169 @@ GeneratePciCrs (
    return Status;

  }

 
+/** Generate a RES0 device node to reserve PNP motherboard resources

+  for a given PCI node.

+

+  @param [in]   PciNode       Parent PCI node handle of the generated

+                              resource object.

+  @param [out]  CrsNode       CRS node of the AML tree to populate.

+

+  @retval EFI_SUCCESS             The function completed successfully.

+  @retval EFI_INVALID_PARAMETER   Invalid input parameter.

+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.

+**/

+STATIC

+EFI_STATUS

+EFIAPI

+GenerateMotherboardDevice (

+  IN  AML_OBJECT_NODE_HANDLE  PciNode,

+  OUT AML_OBJECT_NODE_HANDLE  *CrsNode

+  )

+{

+  EFI_STATUS              Status;

+  UINT32                  EisaId;

+  AML_OBJECT_NODE_HANDLE  ResNode;

+

+  if (CrsNode == NULL) {

+    ASSERT (0);

+    return EFI_INVALID_PARAMETER;

+  }

+

+  // ASL: Device (RES0) {}

+  Status = AmlCodeGenDevice ("RES0", PciNode, &ResNode);

+  if (EFI_ERROR (Status)) {

+    ASSERT (0);

+    return Status;

+  }

+

+  // ASL: Name (_HID, EISAID ("PNP0C02"))

+  Status = AmlGetEisaIdFromString ("PNP0C02", &EisaId); /* PNP Motherboard Resources */

+  if (EFI_ERROR (Status)) {

+    ASSERT (0);

+    return Status;

+  }

+

+  Status = AmlCodeGenNameInteger ("_HID", EisaId, ResNode, NULL);

+  if (EFI_ERROR (Status)) {

+    ASSERT (0);

+    return Status;

+  }

+

+  // ASL: Name (_CRS, ResourceTemplate () {})

+  Status = AmlCodeGenNameResourceTemplate ("_CRS", ResNode, CrsNode);

+  if (EFI_ERROR (Status)) {

+    ASSERT (0);

+    return Status;

+  }

+

+  return Status;

+}

+

+/** Reserves ECAM space for PCI config space

+

+  @param [in]       Generator       The SSDT Pci generator.

+  @param [in]       CfgMgrProtocol  Pointer to the Configuration Manager

+                                    Protocol interface.

+  @param [in]       PciInfo         Pci device information.

+  @param [in, out]  PciNode         RootNode of the AML tree to populate.

+

+  @retval EFI_SUCCESS             The function completed successfully.

+  @retval EFI_INVALID_PARAMETER   Invalid parameter.

+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.

+**/

+STATIC

+EFI_STATUS

+EFIAPI

+ReserveEcamSpace (

+  IN            ACPI_PCI_GENERATOR                            *Generator,

+  IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,

+  IN      CONST CM_ARM_PCI_CONFIG_SPACE_INFO                  *PciInfo,

+  IN  OUT       AML_OBJECT_NODE_HANDLE                        PciNode

+  )

+{

+  EFI_STATUS                   Status;

+  AML_OBJECT_NODE_HANDLE       CrsNode;

+  BOOLEAN                      Translation;

+  UINT32                       Index;

+  CM_ARM_OBJ_REF               *RefInfo;

+  UINT32                       RefCount;

+  CM_ARM_PCI_ADDRESS_MAP_INFO  *AddrMapInfo;

+  BOOLEAN                      IsPosDecode;

+

+  // Get the array of CM_ARM_OBJ_REF referencing the

+  // CM_ARM_PCI_ADDRESS_MAP_INFO objects.

+  Status = GetEArmObjCmRef (

+             CfgMgrProtocol,

+             PciInfo->AddressMapToken,

+             &RefInfo,

+             &RefCount

+             );

+  if (EFI_ERROR (Status)) {

+    ASSERT (0);

+    return Status;

+  }

+

+  for (Index = 0; Index < RefCount; Index++) {

+    // Get CM_ARM_PCI_ADDRESS_MAP_INFO structures one by one.

+    Status = GetEArmObjPciAddressMapInfo (

+               CfgMgrProtocol,

+               RefInfo[Index].ReferenceToken,

+               &AddrMapInfo,

+               NULL

+               );

+    if (EFI_ERROR (Status)) {

+      ASSERT (0);

+      return Status;

+    }

[SAMI] Sorry for missing this earlier in the review. However, the ECAM memory space is described by CM_ARM_PCI_CONFIG_SPACE_INFO. So, I think that needs to be used here.

The CM_ARM_PCI_CONFIG_SPACE_INFO structure does not include the length of the configuration space and would probably need to be updated.

Which platform are you testing these changes on? I would like to understand more about your use case. Is it possible to share some more details, please?

[/SAMI]

+

+    switch (AddrMapInfo->SpaceCode) {

+      case PCI_SS_CONFIG:

+        Translation = (AddrMapInfo->CpuAddress != AddrMapInfo->PciAddress);

+        if (AddrMapInfo->CpuAddress >= AddrMapInfo->PciAddress) {

+          IsPosDecode = TRUE;

+        } else {

+          IsPosDecode = FALSE;

+        }

+

+        Status = GenerateMotherboardDevice (PciNode, &CrsNode);

+        if (EFI_ERROR (Status)) {

+          ASSERT (0);

+          break;

+        }

+

+        Status = AmlCodeGenRdQWordMemory (

+                   FALSE,

+                   IsPosDecode,

+                   TRUE,

+                   TRUE,

+                   FALSE, // non-cacheable

+                   TRUE,

+                   0,

+                   AddrMapInfo->PciAddress,

+                   AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,

+                   Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,

+                   AddrMapInfo->AddressSize,

+                   0,

+                   NULL,

+                   0,

+                   TRUE,

+                   CrsNode,

+                   NULL

+                   );

+        break;

+      default:

+        break;

+    } // switch

+

+    if (EFI_ERROR (Status)) {

+      ASSERT (0);

+      return Status;

+    }

+  }

+

+  return Status;

+}

+

  /** Generate a Pci device.

 
    @param [in]       Generator       The SSDT Pci generator.

@@ -702,9 +865,17 @@ GeneratePciDevice (
      return Status;

    }

 
+  // Add the PNP Motherboard Resources Device to reserve ECAM space

+  Status = ReserveEcamSpace (Generator, CfgMgrProtocol, PciInfo, PciNode);

+  if (EFI_ERROR (Status)) {

+    ASSERT (0);

+    return Status;

+  }

+

    // Add the template _OSC method.

    Status = AddOscMethod (PciInfo, PciNode);

    ASSERT_EFI_ERROR (Status);

+

    return Status;

  }

 


Re: [PATCH v3 0/6] Enhance DynamicTablesPkg modules

Kun Qin
 

Hi DynamicTablePkg maintainers,

Just a gentle ping on this patch series. If there is no further feedback, can we merge
them into the mainline? Otherwise, any feedback is appreciated.

Regards,
Kun

On 8/3/2022 9:57 AM, Kun Qin wrote:
Hi DynamicTablePkg maintainers,

Do you have any further feedback on this patch series? Any input is appreciated.

Thanks,
Kun

On 7/30/2022 10:37 PM, Kun Qin via groups.io wrote:
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3996
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3997
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3998

This patch series is a follow-up of previous submission:
https://edk2.groups.io/g/devel/message/91926

The main changes between v2 and v3 patches are:
   - Added reviewed-by collected from previous iteration
   - Added descriptions for newly introduced structures
   - Updated functions names

Current DynamicTablesPkg provide great support for creating dynamic ACPI
tables during boot time.

However, there are some modules needs minor tweaks to expand support and
compatibility for OS requirements and platform needs.

This patch series proposes a few fixes to resolve minor issues discovered
in DynamicPlatRepoLib, AcpiSsdtPcieLibArm and DynamicTableManagerDxe.

Patch v3 branch: https://github.com/kuqin12/edk2/tree/dynamic_update_v3

Cc: Sami Mujawar <Sami.Mujawar@...>
Cc: Alexei Fedorov <Alexei.Fedorov@...>
Cc: Pierre Gondois <pierre.gondois@...>

Kun Qin (6):
   DynamicTablesPkg: DynamicPlatRepoLib: Added MemoryAllocationLib to inf
   DynamicTablesPkg: DynamicPlatRepoLib: Fix incorrect dereferencing
   DynamicTablesPkg: DynamicPlatRepoLib: Adding more token fixers
   DynamicTablesPkg: DynamicTableManagerDxe: Added check for installed
     tables
   DynamicTablesPkg: AcpiSsdtPcieLibArm: Added function to reserve ECAM
     space
   DynamicTablesPkg: AcpiSsdtPcieLibArm: Added case handling for PCI
     config

DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c | 214 ++++++++++++--------
DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c | 176 ++++++++++++++++
DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer.c |  80 +++++++-
DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf |   4 +
DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib.inf |   1 +
  5 files changed, 391 insertions(+), 84 deletions(-)


Re: [PATCH v3 6/6] DynamicTablesPkg: AcpiSsdtPcieLibArm: Added case handling for PCI config

Sami Mujawar
 

Hi Kun,

Thank you for this patch.

This change looks good to me.

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

Regards,

Sami Mujawar

On 31/07/2022 06:37 am, Kun Qin wrote:
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3998

This change added a switch case handling for PCI_SS_CONFIG during SSDT
generation. This will allow PCI config case return EFI_SUCCESS instead of
EFI_INVALID_PARAMETER.

Cc: Sami Mujawar <Sami.Mujawar@...>
Cc: Alexei Fedorov <Alexei.Fedorov@...>

Co-authored-by: Joe Lopez <joelopez@...>
Signed-off-by: Kun Qin <kuqin12@...>
Reviewed-by: Pierre Gondois <pierre.gondois@...>
---

Notes:
v2:
- Added Reviewed-by tag [Pierre]
v3:
- No change

DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
index 658a089c8f1f..740271b504ca 100644
--- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
@@ -603,6 +603,11 @@ GeneratePciCrs (
);

break;


+ case PCI_SS_CONFIG:

+ // Do nothing

+ Status = EFI_SUCCESS;

+ break;

+

default:

Status = EFI_INVALID_PARAMETER;

} // switch


Re: [PATCH v3 5/6] DynamicTablesPkg: AcpiSsdtPcieLibArm: Added function to reserve ECAM space

Sami Mujawar
 

Hi Kun,

Thank you for this patch.

These changes look good to me.

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

Regards,

Sami Mujawar

On 31/07/2022 06:37 am, Kun Qin via groups.io wrote:
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3998

Certain OSes will complain if the ECAM config space is not reserved in
the ACPI namespace.

This change adds a function to reserve PNP motherboard resources for a
given PCI node.

Co-authored-by: Joe Lopez <joelopez@...>
Signed-off-by: Kun Qin <kuqin12@...>
Reviewed-by: Pierre Gondois <pierre.gondois@...>
---

Notes:
v2:
- Only create RES0 after config space checking [Pierre]
v3:
- Updated function names and descriptions [Pierre]
- Moved translation calculation to CONFIG case [Pierre]

DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c | 171 ++++++++++++++++++++
1 file changed, 171 insertions(+)

diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
index ceffe2838c03..658a089c8f1f 100644
--- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
@@ -616,6 +616,169 @@ GeneratePciCrs (
return Status;

}


+/** Generate a RES0 device node to reserve PNP motherboard resources

+ for a given PCI node.

+

+ @param [in] PciNode Parent PCI node handle of the generated

+ resource object.

+ @param [out] CrsNode CRS node of the AML tree to populate.

+

+ @retval EFI_SUCCESS The function completed successfully.

+ @retval EFI_INVALID_PARAMETER Invalid input parameter.

+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.

+**/

+STATIC

+EFI_STATUS

+EFIAPI

+GenerateMotherboardDevice (

+ IN AML_OBJECT_NODE_HANDLE PciNode,

+ OUT AML_OBJECT_NODE_HANDLE *CrsNode

+ )

+{

+ EFI_STATUS Status;

+ UINT32 EisaId;

+ AML_OBJECT_NODE_HANDLE ResNode;

+

+ if (CrsNode == NULL) {

+ ASSERT (0);

+ return EFI_INVALID_PARAMETER;

+ }

+

+ // ASL: Device (RES0) {}

+ Status = AmlCodeGenDevice ("RES0", PciNode, &ResNode);

+ if (EFI_ERROR (Status)) {

+ ASSERT (0);

+ return Status;

+ }

+

+ // ASL: Name (_HID, EISAID ("PNP0C02"))

+ Status = AmlGetEisaIdFromString ("PNP0C02", &EisaId); /* PNP Motherboard Resources */

+ if (EFI_ERROR (Status)) {

+ ASSERT (0);

+ return Status;

+ }

+

+ Status = AmlCodeGenNameInteger ("_HID", EisaId, ResNode, NULL);

+ if (EFI_ERROR (Status)) {

+ ASSERT (0);

+ return Status;

+ }

+

+ // ASL: Name (_CRS, ResourceTemplate () {})

+ Status = AmlCodeGenNameResourceTemplate ("_CRS", ResNode, CrsNode);

+ if (EFI_ERROR (Status)) {

+ ASSERT (0);

+ return Status;

+ }

+

+ return Status;

+}

+

+/** Reserves ECAM space for PCI config space

+

+ @param [in] Generator The SSDT Pci generator.

+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager

+ Protocol interface.

+ @param [in] PciInfo Pci device information.

+ @param [in, out] PciNode RootNode of the AML tree to populate.

+

+ @retval EFI_SUCCESS The function completed successfully.

+ @retval EFI_INVALID_PARAMETER Invalid parameter.

+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.

+**/

+STATIC

+EFI_STATUS

+EFIAPI

+ReserveEcamSpace (

+ IN ACPI_PCI_GENERATOR *Generator,

+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,

+ IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,

+ IN OUT AML_OBJECT_NODE_HANDLE PciNode

+ )

+{

+ EFI_STATUS Status;

+ AML_OBJECT_NODE_HANDLE CrsNode;

+ BOOLEAN Translation;

+ UINT32 Index;

+ CM_ARM_OBJ_REF *RefInfo;

+ UINT32 RefCount;

+ CM_ARM_PCI_ADDRESS_MAP_INFO *AddrMapInfo;

+ BOOLEAN IsPosDecode;

+

+ // Get the array of CM_ARM_OBJ_REF referencing the

+ // CM_ARM_PCI_ADDRESS_MAP_INFO objects.

+ Status = GetEArmObjCmRef (

+ CfgMgrProtocol,

+ PciInfo->AddressMapToken,

+ &RefInfo,

+ &RefCount

+ );

+ if (EFI_ERROR (Status)) {

+ ASSERT (0);

+ return Status;

+ }

+

+ for (Index = 0; Index < RefCount; Index++) {

+ // Get CM_ARM_PCI_ADDRESS_MAP_INFO structures one by one.

+ Status = GetEArmObjPciAddressMapInfo (

+ CfgMgrProtocol,

+ RefInfo[Index].ReferenceToken,

+ &AddrMapInfo,

+ NULL

+ );

+ if (EFI_ERROR (Status)) {

+ ASSERT (0);

+ return Status;

+ }

+

+ switch (AddrMapInfo->SpaceCode) {

+ case PCI_SS_CONFIG:

+ Translation = (AddrMapInfo->CpuAddress != AddrMapInfo->PciAddress);

+ if (AddrMapInfo->CpuAddress >= AddrMapInfo->PciAddress) {

+ IsPosDecode = TRUE;

+ } else {

+ IsPosDecode = FALSE;

+ }

+

+ Status = GenerateMotherboardDevice (PciNode, &CrsNode);

+ if (EFI_ERROR (Status)) {

+ ASSERT (0);

+ break;

+ }

+

+ Status = AmlCodeGenRdQWordMemory (

+ FALSE,

+ IsPosDecode,

+ TRUE,

+ TRUE,

+ FALSE, // non-cacheable

+ TRUE,

+ 0,

+ AddrMapInfo->PciAddress,

+ AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,

+ Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,

+ AddrMapInfo->AddressSize,

+ 0,

+ NULL,

+ 0,

+ TRUE,

+ CrsNode,

+ NULL

+ );

+ break;

+ default:

+ break;

+ } // switch

+

+ if (EFI_ERROR (Status)) {

+ ASSERT (0);

+ return Status;

+ }

+ }

+

+ return Status;

+}

+

/** Generate a Pci device.


@param [in] Generator The SSDT Pci generator.

@@ -702,9 +865,17 @@ GeneratePciDevice (
return Status;

}


+ // Add the PNP Motherboard Resources Device to reserve ECAM space

+ Status = ReserveEcamSpace (Generator, CfgMgrProtocol, PciInfo, PciNode);

+ if (EFI_ERROR (Status)) {

+ ASSERT (0);

+ return Status;

+ }

+

// Add the template _OSC method.

Status = AddOscMethod (PciInfo, PciNode);

ASSERT_EFI_ERROR (Status);

+

return Status;

}


Re: [PATCH v3 4/6] DynamicTablesPkg: DynamicTableManagerDxe: Added check for installed tables

Sami Mujawar
 

Hi Kun,

Thank you for this patch.

Please find my response inline marked [SAMI].

Regards,

Sami Mujawar

On 31/07/2022 06:37 am, Kun Qin wrote:
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3997

This change added an extra step to allow check for installed ACPI tables.

For FADT, MADT, GTDT, DSDT, DBG2 and SPCR tables, either pre-installed or
supplied through AcpiTableInfo can be accepted.

An extra check for FADT ACPI table existence during installation step is
also added.

Cc: Sami Mujawar <Sami.Mujawar@...>
Cc: Alexei Fedorov <Alexei.Fedorov@...>

Co-authored-by: Joe Lopez <joelopez@...>
Signed-off-by: Kun Qin <kuqin12@...>
Reviewed-by: Pierre Gondois <pierre.gondois@...>
---

Notes:
v2:
- Function description updates [Sami]
- Refactorized the table verification [Pierre]
v3:
- Added descriptions for new structures [Pierre]
- Added check for SDT protocol PCD before using it [Pierre]

DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c | 214 ++++++++++++--------
DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf | 4 +
2 files changed, 138 insertions(+), 80 deletions(-)

diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c
index ed62299f9bbd..7f3deef08a66 100644
--- a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c
+++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c
@@ -10,6 +10,7 @@
#include <Library/DebugLib.h>

#include <Library/PcdLib.h>

#include <Library/UefiBootServicesTableLib.h>

+#include <Protocol/AcpiSystemDescriptionTable.h>

#include <Protocol/AcpiTable.h>


// Module specific include files.

@@ -22,6 +23,58 @@
#include <Protocol/DynamicTableFactoryProtocol.h>

#include <SmbiosTableGenerator.h>


+///

+/// Bit definitions for acceptable ACPI table presence formats.

+/// Currently only ACPI tables present in the ACPI info list and

+/// already installed will count towards "Table Present" during

+/// verification routine.

+///

+#define ACPI_TABLE_PRESENT_INFO_LIST BIT0

+#define ACPI_TABLE_PRESENT_INSTALLED BIT1

+

+///

+/// Order of ACPI table being verified during presence inspection.

+///

+#define ACPI_TABLE_VERIFY_FADT 0

+#define ACPI_TABLE_VERIFY_MADT 1

+#define ACPI_TABLE_VERIFY_GTDT 2

+#define ACPI_TABLE_VERIFY_DSDT 3

+#define ACPI_TABLE_VERIFY_DBG2 4

+#define ACPI_TABLE_VERIFY_SPCR 5

+#define ACPI_TABLE_VERIFY_COUNT 6

+

+///

+/// Private data structure to verify the presence of mandatory

+/// or optional ACPI tables.

+///

+typedef struct {

+ /// ESTD ID for the ACPI table of interest.

+ ESTD_ACPI_TABLE_ID EstdTableId;

+ /// Standard UINT32 ACPI signature.

+ UINT32 AcpiTableSignature;

+ /// 4 character ACPI table name (the 5th char8 is for null terminator).

+ CHAR8 AcpiTableName[sizeof (UINT32) + 1];

+ /// Indicator on whether the ACPI table is required.

+ BOOLEAN IsMandatory;

+ /// Formats of verified presences, as defined by ACPI_TABLE_PRESENT_*

+ /// This field should be initialized to 0 and will be populated during

+ /// verification routine.

+ UINT16 Presence;

+} ACPI_TABLE_PRESENCE_INFO;

+

+///

+/// We require the FADT, MADT, GTDT and the DSDT tables to boot.

+/// This list also include optional ACPI tables: DBG2, SPCR.

+///

+ACPI_TABLE_PRESENCE_INFO mAcpiVerifyTables[ACPI_TABLE_VERIFY_COUNT] = {

+ { EStdAcpiTableIdFadt, EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, "FADT", TRUE, 0 },

+ { EStdAcpiTableIdMadt, EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, "MADT", TRUE, 0 },

+ { EStdAcpiTableIdGtdt, EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE, "GTDT", TRUE, 0 },

+ { EStdAcpiTableIdDsdt, EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, "DSDT", TRUE, 0 },

+ { EStdAcpiTableIdDbg2, EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE, "DBG2", FALSE, 0 },

+ { EStdAcpiTableIdSpcr, EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, "SPCR", FALSE, 0 },

+};

+

/** This macro expands to a function that retrieves the ACPI Table

List from the Configuration Manager.

*/

@@ -395,6 +448,7 @@ BuildAndInstallAcpiTable (

@retval EFI_SUCCESS Success.

@retval EFI_NOT_FOUND If mandatory table is not found.

+ @retval EFI_ALREADY_STARTED If mandatory table found in AcpiTableInfo is already installed.

**/

STATIC

EFI_STATUS

@@ -404,75 +458,71 @@ VerifyMandatoryTablesArePresent (
IN UINT32 AcpiTableCount

)

{

- EFI_STATUS Status;

- BOOLEAN FadtFound;

- BOOLEAN MadtFound;

- BOOLEAN GtdtFound;

- BOOLEAN DsdtFound;

- BOOLEAN Dbg2Found;

- BOOLEAN SpcrFound;

+ EFI_STATUS Status;

+ UINTN Handle;

+ UINTN Index;

+ UINTN InstalledTableIndex;

+ EFI_ACPI_DESCRIPTION_HEADER *DescHeader;

+ EFI_ACPI_TABLE_VERSION Version;

+ EFI_ACPI_SDT_PROTOCOL *AcpiSdt;


- Status = EFI_SUCCESS;

- FadtFound = FALSE;

- MadtFound = FALSE;

- GtdtFound = FALSE;

- DsdtFound = FALSE;

- Dbg2Found = FALSE;

- SpcrFound = FALSE;

ASSERT (AcpiTableInfo != NULL);


+ Status = EFI_SUCCESS;

+

+ // Check against the statically initialized ACPI tables to see if they are in ACPI info list

while (AcpiTableCount-- != 0) {

- switch (AcpiTableInfo[AcpiTableCount].AcpiTableSignature) {

- case EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:

- FadtFound = TRUE;

- break;

- case EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:

- MadtFound = TRUE;

- break;

- case EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE:

- GtdtFound = TRUE;

- break;

- case EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:

- DsdtFound = TRUE;

- break;

- case EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE:

- Dbg2Found = TRUE;

- break;

- case EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:

- SpcrFound = TRUE;

- break;

- default:

+ for (Index = 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {

+ if (AcpiTableInfo[AcpiTableCount].AcpiTableSignature == mAcpiVerifyTables[Index].AcpiTableSignature) {

+ mAcpiVerifyTables[Index].Presence |= ACPI_TABLE_PRESENT_INFO_LIST;

+ // Found this table, skip the rest.

break;

+ }

}

}


- // We need at least the FADT, MADT, GTDT and the DSDT tables to boot

- if (!FadtFound) {

- DEBUG ((DEBUG_ERROR, "ERROR: FADT Table not found\n"));

- Status = EFI_NOT_FOUND;

- }

+ // They also might be published already, so we can search from there

+ if (FeaturePcdGet (PcdInstallAcpiSdtProtocol)) {

+ AcpiSdt = NULL;

+ Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&AcpiSdt);


- if (!MadtFound) {

- DEBUG ((DEBUG_ERROR, "ERROR: MADT Table not found.\n"));

- Status = EFI_NOT_FOUND;

- }

+ if (EFI_ERROR (Status) || (AcpiSdt == NULL)) {

+ DEBUG ((DEBUG_ERROR, "ERROR: Failed to locate ACPI SDT protocol (0x%p) - %r\n", AcpiSdt, Status));

+ return Status;

+ }


- if (!GtdtFound) {

- DEBUG ((DEBUG_ERROR, "ERROR: GTDT Table not found.\n"));

- Status = EFI_NOT_FOUND;

- }

+ for (Index = 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {

+ Handle = 0;

+ InstalledTableIndex = 0;

+ do {

+ Status = AcpiSdt->GetAcpiTable (InstalledTableIndex, (EFI_ACPI_SDT_HEADER **)&DescHeader, &Version, &Handle);

+ if (EFI_ERROR (Status)) {

+ break;

+ }


- if (!DsdtFound) {

- DEBUG ((DEBUG_ERROR, "ERROR: DSDT Table not found.\n"));

- Status = EFI_NOT_FOUND;

- }

+ InstalledTableIndex++;

+ } while (DescHeader->Signature != mAcpiVerifyTables[Index].AcpiTableSignature);


- if (!Dbg2Found) {

- DEBUG ((DEBUG_WARN, "WARNING: DBG2 Table not found.\n"));

+ if (!EFI_ERROR (Status)) {

+ mAcpiVerifyTables[Index].Presence |= ACPI_TABLE_PRESENT_INSTALLED;

+ }

+ }

}


- if (!SpcrFound) {

- DEBUG ((DEBUG_WARN, "WARNING: SPCR Table not found.\n"));

+ for (Index = 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {

+ if (mAcpiVerifyTables[Index].Presence == 0) {

+ if (mAcpiVerifyTables[Index].IsMandatory) {

+ DEBUG ((DEBUG_ERROR, "ERROR: %a Table not found.\n", mAcpiVerifyTables[Index].AcpiTableName));

+ Status = EFI_NOT_FOUND;

+ } else {

+ DEBUG ((DEBUG_WARN, "WARNING: %a Table not found.\n", mAcpiVerifyTables[Index].AcpiTableName));

+ }

+ } else if (mAcpiVerifyTables[Index].Presence ==

+ (ACPI_TABLE_PRESENT_INFO_LIST | ACPI_TABLE_PRESENT_INSTALLED))

+ {

+ DEBUG ((DEBUG_ERROR, "ERROR: %a Table found while already published.\n", mAcpiVerifyTables[Index].AcpiTableName));

+ Status = EFI_ALREADY_STARTED;

+ }

}


return Status;

@@ -489,8 +539,9 @@ VerifyMandatoryTablesArePresent (
@param [in] CfgMgrProtocol Pointer to the Configuration Manager

Protocol Interface.


- @retval EFI_SUCCESS Success.

- @retval EFI_NOT_FOUND If a mandatory table or a generator is not found.

+ @retval EFI_SUCCESS Success.

+ @retval EFI_NOT_FOUND If a mandatory table or a generator is not found.

+ @retval EFI_ALREADY_STARTED If mandatory table found in AcpiTableInfo is already installed.

**/

STATIC

EFI_STATUS

@@ -562,7 +613,7 @@ ProcessAcpiTables (
if (EFI_ERROR (Status)) {

DEBUG ((

DEBUG_ERROR,

- "ERROR: Failed to find mandatory ACPI Table(s)."

+ "ERROR: Failed to verify mandatory ACPI Table(s) presence."

" Status = %r\n",

Status

));

@@ -570,29 +621,32 @@ ProcessAcpiTables (
}


// Add the FADT Table first.

- for (Idx = 0; Idx < AcpiTableCount; Idx++) {

- if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) ==

- AcpiTableInfo[Idx].TableGeneratorId)

- {

- Status = BuildAndInstallAcpiTable (

- TableFactoryProtocol,

- CfgMgrProtocol,

- AcpiTableProtocol,

- &AcpiTableInfo[Idx]

- );

- if (EFI_ERROR (Status)) {

- DEBUG ((

- DEBUG_ERROR,

- "ERROR: Failed to find build and install ACPI FADT Table." \

- " Status = %r\n",

- Status

- ));

- return Status;

- }

+ if ((mAcpiVerifyTables[ACPI_TABLE_VERIFY_FADT].Presence & ACPI_TABLE_PRESENT_INSTALLED) == 0) {
[SAMI] If I understand correctly, the mAcpiVerifyTables[x].Presence filed cannot be ACPI_TABLE_PRESENT_INFO_LIST and ACPI_TABLE_PRESENT_INSTALLED at the same time. Otherwise we would have returned EFI_ALREADY_STARTED from VerifyMandatoryTablesArePresent().

Since FADT is mandatory, the only valid conditions are:

1. ACPI_TABLE_PRESENT_INFO_LIST and !ACPI_TABLE_PRESENT_INSTALLED

2. !ACPI_TABLE_PRESENT_INFO_LIST & ACPI_TABLE_PRESENT_INSTALLED

Therefore, I think the above check is not required. What do you think?

[/SAMI]


+ // FADT is not yet installed

+ for (Idx = 0; Idx < AcpiTableCount; Idx++) {

+ if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) ==

+ AcpiTableInfo[Idx].TableGeneratorId)

+ {

+ Status = BuildAndInstallAcpiTable (

+ TableFactoryProtocol,

+ CfgMgrProtocol,

+ AcpiTableProtocol,

+ &AcpiTableInfo[Idx]

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((

+ DEBUG_ERROR,

+ "ERROR: Failed to find build and install ACPI FADT Table." \

+ " Status = %r\n",

+ Status

+ ));

+ return Status;

+ }


- break;

- }

- } // for

+ break;

+ }

+ } // for

+ }


// Add remaining ACPI Tables

for (Idx = 0; Idx < AcpiTableCount; Idx++) {

diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
index 028c3d413cf8..ad8b3d037c16 100644
--- a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
+++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf
@@ -34,8 +34,12 @@ [LibraryClasses]
UefiBootServicesTableLib

UefiDriverEntryPoint


+[FeaturePcd]

+ gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol ## CONSUMES

+

[Protocols]

gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED

+ gEfiAcpiSdtProtocolGuid # PROTOCOL ALWAYS_CONSUMED


gEdkiiConfigurationManagerProtocolGuid # PROTOCOL ALWAYS_CONSUMED

gEdkiiDynamicTableFactoryProtocolGuid # PROTOCOL ALWAYS_CONSUMED


Re: [PATCH 2/2] CloudHv/arm: switch PeiMemLib to its own

Sami Mujawar
 

Hi Jianyong,

Thank you for this patch.

This change looks good to me.

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

Regards,

Sami Mujawar

On 29/07/2022 08:21 am, Jianyong Wu wrote:
As Cloud Hypervisor has its own PeiMemLib, change it in dsc file
accordingly.

Signed-off-by: Jianyong Wu <jianyong.wu@...>
---
ArmVirtPkg/ArmVirtCloudHv.dsc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ArmVirtPkg/ArmVirtCloudHv.dsc b/ArmVirtPkg/ArmVirtCloudHv.dsc
index 7559386a1d..7ca7a391d9 100644
--- a/ArmVirtPkg/ArmVirtCloudHv.dsc
+++ b/ArmVirtPkg/ArmVirtCloudHv.dsc
@@ -60,7 +60,7 @@
!include MdePkg/MdeLibs.dsc.inc
[LibraryClasses.common.PEIM]
- ArmVirtMemInfoLib|ArmVirtPkg/Library/QemuVirtMemInfoLib/QemuVirtMemInfoPeiLib.inf
+ ArmVirtMemInfoLib|ArmVirtPkg/Library/CloudHvVirtMemInfoLib/CloudHvVirtMemInfoPeiLib.inf
[LibraryClasses.common.DXE_DRIVER]
ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf


Re: [PATCH 1/2] CloudHv/arm: add PeiMemInfoLib

Sami Mujawar
 

Hi Jianyong,

Thank you for this patch.

Please find my response inline marked [SAMI].

Regards,

Sami Mujawar

On 29/07/2022 08:21 am, Jianyong Wu wrote:
Memory layout in CLoud Hypervisor for arm is changed and is different
with Qemu, thus we should build its own PeiMemInfoLib.
The main change in the memory layout is that normal ram may not contiguous
under 4G. The top 64M under 4G is reserved for 32bit device.

What this patch does:
1. get all of the memory node from DT;
2. Init page table for each memory node;
3. Add all of the memory nodes to Hob;

Signed-off-by: Jianyong Wu <jianyong.wu@...>
---
 .../CloudHvVirtMemInfoLib.c                   | 251 ++++++++++++++++++
 .../CloudHvVirtMemInfoPeiLib.inf              |  46 ++++
 2 files changed, 297 insertions(+)
 create mode 100755 ArmVirtPkg/Library/CloudHvVirtMemInfoLib/CloudHvVirtMemInfoLib.c
 create mode 100755 ArmVirtPkg/Library/CloudHvVirtMemInfoLib/CloudHvVirtMemInfoPeiLib.inf

diff --git a/ArmVirtPkg/Library/CloudHvVirtMemInfoLib/CloudHvVirtMemInfoLib.c b/ArmVirtPkg/Library/CloudHvVirtMemInfoLib/CloudHvVirtMemInfoLib.c
new file mode 100755
index 0000000000..7ae24641d3
--- /dev/null
+++ b/ArmVirtPkg/Library/CloudHvVirtMemInfoLib/CloudHvVirtMemInfoLib.c
@@ -0,0 +1,251 @@
+/** @file
+
+  Copyright (c) 2022, Arm Limited. All rights reserved.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+#include <Base.h>
+#include <libfdt.h>
+#include <Library/ArmLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+
+#include<Library/PrePiLib.h>
+
+// The first memnory node is the one whose base address is the lowest.
+UINT64 FirMemNodeBase = 0, FirMemNodeSize = 0;
[SAMI] Is it possible to move the above variables within the scope of CloudHvVirtMemInfoPeiLibConstructor() ?
+//
+// Cloud Hypervisor may have more than one memory nodes. Even there is no limit for that,
+// I think 10 is enough in general.
+//
+#define CLOUDHV_MAX_MEM_NODE_NUM 10
+
+// Record memory node info (base address and size)
+struct CloudHvMemNodeInfo {
+  UINT64 Base;
+  UINT64 Size;
+};

[SAMI] The edk2 coding guidelines require definition of a typedef for structures, see section 5.6.3.[1,2,3] at https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specification/5_source_files/56_declarations_and_types#5.6.3.1-structures-shall-not-be-directly-declared.

+
+struct CloudHvMemNodeInfo CloudHvMemNode[CLOUDHV_MAX_MEM_NODE_NUM];
+
+RETURN_STATUS
+EFIAPI
+CloudHvVirtMemInfoPeiLibConstructor (
+  VOID
+  )
+{
+  VOID           *DeviceTreeBase;
+  EFI_RESOURCE_ATTRIBUTE_TYPE  ResourceAttributes;
+  INT32          Node, Prev;
+  UINT64         CurBase, MemBase;
+  UINT64         CurSize;
+  CONST CHAR8    *Type;
+  INT32          Len;
+  CONST UINT64   *RegProp;
+  RETURN_STATUS  PcdStatus;
+  UINT8          Index;
+
+  ZeroMem (CloudHvMemNode, sizeof(CloudHvMemNode[0]) * CLOUDHV_MAX_MEM_NODE_NUM);
[SAMI] Will sizeof (CloudHvMemNode) should be sufficient above? Also can you run uncrustify on your patches, please?
+
+  Index = 0;
+  MemBase = FixedPcdGet64 (PcdSystemMemoryBase);
+  ResourceAttributes = (
+                        EFI_RESOURCE_ATTRIBUTE_PRESENT |
+                        EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+                        EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+                        EFI_RESOURCE_ATTRIBUTE_TESTED
+                        );
+  DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
+  ASSERT (DeviceTreeBase != NULL);
+
+  //
+  // Make sure we have a valid device tree blob
+  //
+  ASSERT (fdt_check_header (DeviceTreeBase) == 0);
[SAMI] I think the two ASSERTs above must return an error, otherwise they would result in a crash in release builds.
+
+  //
+  // Look for the lowest memory node
+  //
+  for (Prev = 0; ; Prev = Node) {
+    Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
+    if (Node < 0) {
+      break;
+    }
+
+    //
+    // Check for memory node
+    //
+    Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len);
+    if (Type && (AsciiStrnCmp (Type, "memory", Len) == 0)) {
+      //
+      // Get the 'reg' property of this node. For now, we will assume
+      // two 8 byte quantities for base and size, respectively.
+      //
+      RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
+      if ((RegProp != 0) && (Len == (2 * sizeof (UINT64)))) {
+        CurBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
+        CurSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1));
+
+        DEBUG ((
+          DEBUG_INFO,
+          "%a: System RAM @ 0x%lx - 0x%lx\n",
+          __FUNCTION__,
+          CurBase,
+          CurBase + CurSize - 1
+          ));
+
+        if (CurBase == MemBase) {
+            FirMemNodeBase = CurBase;
+            FirMemNodeSize = CurSize;
+        }
+
+        CloudHvMemNode[Index].Base = CurBase;
+        CloudHvMemNode[Index].Size = CurSize;
+        Index++;
+        // We should build Hob seperately for the memory node except the first one
+        if (CurBase != MemBase) {
[SAMI] Can this be made an else statement of the previous 'if (CurBase == MemBase)' statement  by reordeing the few statements above?
+          BuildResourceDescriptorHob (
+            EFI_RESOURCE_SYSTEM_MEMORY,
+            ResourceAttributes,
+            CurBase,
+            CurSize
+            );
+        }
+        if (Index >= CLOUDHV_MAX_MEM_NODE_NUM) {
+          DEBUG ((
+            DEBUG_WARN,
+            "%a: memory node larger than %d will not be included into Memory System\n",
+            __FUNCTION__,
+            CLOUDHV_MAX_MEM_NODE_NUM
+            ));
+          break;
+        }
+      } else {
+        DEBUG ((
+          DEBUG_ERROR,
+          "%a: Failed to parse FDT memory node\n",
+          __FUNCTION__
+          ));
+      }
+    }
+  }
+
+  //
+  // Make sure the start of DRAM matches our expectation
+  //
+  ASSERT (FixedPcdGet64 (PcdSystemMemoryBase) == FirMemNodeBase);
[SAMI] This assert is checking that the a memory node with PcdSystemMemoryBasehas been found in the DT. If not found an error must be returned.
+  PcdStatus = PcdSet64S (PcdSystemMemorySize, FirMemNodeSize);
+  ASSERT_RETURN_ERROR (PcdStatus);
+  ASSERT (
+    (((UINT64)PcdGet64 (PcdFdBaseAddress) +
+      (UINT64)PcdGet32 (PcdFdSize)) <= FirMemNodeBase) ||
+    ((UINT64)PcdGet64 (PcdFdBaseAddress) >= (FirMemNodeBase + FirMemNodeSize))
+    );
+
+  return RETURN_SUCCESS;
+}
+
+// Number of Virtual Memory Map Descriptors
+#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS  (4 + CLOUDHV_MAX_MEM_NODE_NUM)
+
+//
+// Core peripherals such as the UART, the GIC and the RTC are
+// all mapped in the 'miscellaneous device I/O' region, which we just map
+// in its entirety rather than device by device. Note that it does not
+// cover any of the NOR flash banks or PCI resource windows.
+//
+#define MACH_VIRT_PERIPH_BASE  0x00400000
+#define MACH_VIRT_PERIPH_SIZE  0x0FC00000
+
+//
+// The top of the 64M memory region under 4GB reserved for device
+//
+#define TOP_32BIT_DEVICE_BASE  0xFC000000
+#define TOP_32BIT_DEVICE_SIZE  0x04000000
+
[SAMI] Is it possible to move the all the defines in this file and the structure definition to a separate header file, please?
+/**
+  Return the Virtual Memory Map of your platform
+
+  This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU
+  on your platform.
+
+  @param[out]   VirtualMemoryMap    Array of ARM_MEMORY_REGION_DESCRIPTOR
+                                    describing a Physical-to-Virtual Memory
+                                    mapping. This array must be ended by a
+                                    zero-filled entry. The allocated memory
+                                    will not be freed.
+
+**/
+VOID
+ArmVirtGetMemoryMap (
+  OUT ARM_MEMORY_REGION_DESCRIPTOR  **VirtualMemoryMap
+  )
+{
+  ARM_MEMORY_REGION_DESCRIPTOR  *VirtualMemoryTable;
+  UINT8 Index = 0, i = 0;
[SAMI] Please change variable name 'i' to MemNodeIndex.
+
+  ASSERT (VirtualMemoryMap != NULL);
+
+  VirtualMemoryTable = AllocatePool (
+                         sizeof (ARM_MEMORY_REGION_DESCRIPTOR) *
+                         MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS
+                         );
+
+  if (VirtualMemoryTable == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: Error: Failed AllocatePool()\n", __FUNCTION__));
+    return;
+  }
+    // System DRAM
+  while (CloudHvMemNode[i].Size != 0) {
+    VirtualMemoryTable[Index].PhysicalBase = CloudHvMemNode[i].Base;
+    VirtualMemoryTable[Index].VirtualBase  = CloudHvMemNode[i].Base;
+    VirtualMemoryTable[Index].Length       = CloudHvMemNode[i].Size;
+    VirtualMemoryTable[Index].Attributes   = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;
+
+    DEBUG ((
+      DEBUG_INFO,
+      "%a: Dumping System DRAM Memory Node%d Map:\n"
+      "\tPhysicalBase: 0x%lX\n"
+      "\tVirtualBase: 0x%lX\n"
+      "\tLength: 0x%lX\n",
+      __FUNCTION__,
+      i,
+      VirtualMemoryTable[Index].PhysicalBase,
+      VirtualMemoryTable[Index].VirtualBase,
+      VirtualMemoryTable[Index].Length
+      ));
+    Index++;
+    i++;
+  }
+  // Memory mapped peripherals (UART, RTC, GIC, virtio-mmio, etc)
+  VirtualMemoryTable[Index].PhysicalBase = MACH_VIRT_PERIPH_BASE;
+  VirtualMemoryTable[Index].VirtualBase  = MACH_VIRT_PERIPH_BASE;
+  VirtualMemoryTable[Index].Length       = MACH_VIRT_PERIPH_SIZE;
+  VirtualMemoryTable[Index].Attributes   = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+  Index++;
+
+  // Map the FV region as normal executable memory
+  VirtualMemoryTable[Index].PhysicalBase = PcdGet64 (PcdFvBaseAddress);
+  VirtualMemoryTable[Index].VirtualBase  = VirtualMemoryTable[Index].PhysicalBase;
+  VirtualMemoryTable[Index].Length       = FixedPcdGet32 (PcdFvSize);
+  VirtualMemoryTable[Index].Attributes   = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;
+  Index++;
+
+  // Memory mapped for 32bit device (like TPM)
+  VirtualMemoryTable[Index].PhysicalBase = TOP_32BIT_DEVICE_BASE;
+  VirtualMemoryTable[Index].VirtualBase  = TOP_32BIT_DEVICE_BASE;
+  VirtualMemoryTable[Index].Length       = TOP_32BIT_DEVICE_SIZE;
+  VirtualMemoryTable[Index].Attributes   = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
+  Index++;
+
+  // End of Table
+  ZeroMem (&VirtualMemoryTable[Index], sizeof (ARM_MEMORY_REGION_DESCRIPTOR));
+
+  *VirtualMemoryMap = VirtualMemoryTable;
+}
diff --git a/ArmVirtPkg/Library/CloudHvVirtMemInfoLib/CloudHvVirtMemInfoPeiLib.inf b/ArmVirtPkg/Library/CloudHvVirtMemInfoLib/CloudHvVirtMemInfoPeiLib.inf
new file mode 100755
index 0000000000..5dd96faadd
--- /dev/null
+++ b/ArmVirtPkg/Library/CloudHvVirtMemInfoLib/CloudHvVirtMemInfoPeiLib.inf
@@ -0,0 +1,46 @@
+#/* @file
+#
+#  Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+#  Copyright (c) 2014-2017, Linaro Limited. All rights reserved.
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#*/
+
+[Defines]
+  INF_VERSION                    = 0x0001001A
[SAMI] Please set version as 0x0001001B.
+  BASE_NAME                      = QemuVirtMemInfoPeiLib
+  FILE_GUID                      = 0c4d10cf-d949-49b4-bd13-47a4ae22efce
[SAMI] This GUID is conflicting with ArmVirtPkg/Library/QemuVirtMemInfoLib/QemuVirtMemInfoPeiLib.inf. Please define a new GUID.
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ArmVirtMemInfoLib|PEIM
+  CONSTRUCTOR                    = CloudHvVirtMemInfoPeiLibConstructor
+
+[Sources]
+  CloudHvVirtMemInfoLib.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmVirtPkg/ArmVirtPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  ArmLib
+  BaseMemoryLib
+  DebugLib
+  FdtLib
+  PcdLib
+  MemoryAllocationLib
[SAMI] Please sort in alphabetical order.
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdFdBaseAddress
+  gArmTokenSpaceGuid.PcdFvBaseAddress
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdSystemMemorySize
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdFdSize
+  gArmTokenSpaceGuid.PcdFvSize
+  gArmVirtTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress


Soft Feature Freeze start on 2022-08-08 for edk2-stable202208

gaoliming
 

Hi, all

 

We enter into Soft Feature Freeze phase on 2022-08-08. In this phase, the feature under review will not be allowed to be pushed. The feature passed review can still be merged.

 

The patch review can continue without break in edk2 community. If the patch is sent before Soft Feature Freeze, and plans to catch this stable tag, the patch contributor need reply to his patch and notify edk2 community. If the patch is sent after Soft Feature Freeze, and plans to catch this stable tag, please add edk2-stable202208 key words in the patch title and BZ, so the community know this patch target and give the feedback.

 

Below is edk2-stable202208 tag planning Proposed Schedule

https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-Release-Planning

 

Date (00:00:00 UTC-8) Description

2022-05-27  Beginning of development

2022-08-08  Soft Feature Freeze

2022-08-12  Hard Feature Freeze

2022-08-26  Release

 

Thanks

Liming

 


Re: [PATCH v1 0/5] Add support to build PRM for AARCH64 using GCC

Sami Mujawar
 

Hi Michael,

Please find my response inline marked [SAMI].

Regards,

Sami Mujawar

On 04/08/2022 05:09 am, Michael Kubacki wrote:
For the series: Reviewed-by: Michael Kubacki <michael.kubacki@...>

The patch formatting seems a little strange:

1. The patches don't have "Cc" lines.
[SAMI] I have not been following the convention to add Cc lines to the patches. However, I will start from the next patch series.
2. What is this GUID message at the bottom of each patch?

   'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'
[SAMI] I have added this so that I can easily search my patches. It does not affect the patch though.

By the way, I tested the AARCH64 PRM build with sample modules on VS2019 a while back, so I see that you mentioned only testing GCC (thanks for helping get the functions in the export table there) but it should work in VS as well.
[SAMI] I have tried building PrmPkg with VS2019 and found that the AARCH64 builds do not work.

        "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.28.29910\bin\Hostx86\arm64\armasm64.exe" /Fow:\edk2-exports\Build\Prm\DEBUG_VS2019\AARCH64\MdePkg\Library\BaseMemoryLibOptDxe\BaseMemoryLibOptDxe\OUTPUT\AArch64\CompareGuid.obj /nologo /g /Iw:\edk2-exports\edk2\MdePkg\Library\BaseMemoryLibOptDxe\AArch64 /Iw:\edk2-exports\edk2\MdePkg\Library\BaseMemoryLibOptDxe\Arm /Iw:\edk2-exports\edk2\MdePkg\Library\BaseMemoryLibOptDxe\AArch64 /Iw:\edk2-exports\edk2\MdePkg\Library\BaseMemoryLibOptDxe /Iw:\edk2-exports\Build\Prm\DEBUG_VS2019\AARCH64\MdePkg\Library\BaseMemoryLibOptDxe\BaseMemoryLibOptDxe\DEBUG /Iw:\edk2-exports\edk2\MdePkg /Iw:\edk2-exports\edk2\MdePkg\Include /Iw:\edk2-exports\edk2\MdePkg\Test\UnitTest\Include /Iw:\edk2-exports\edk2\MdePkg\Include\AArch64 w:\edk2-exports\Build\Prm\DEBUG_VS2019\AARCH64\MdePkg\Library\BaseMemoryLibOptDxe\BaseMemoryLibOptDxe\OUTPUT\AArch64\CompareGuid.iiii
w:\edk2-exports\Build\Prm\DEBUG_VS2019\AARCH64\MdePkg\Library\BaseMemoryLibOptDxe\BaseMemoryLibOptDxe\OUTPUT\AArch64\CompareGuid.iiii(7) : error A2034: unknown opcode: .
    .text
w:\edk2-exports\Build\Prm\DEBUG_VS2019\AARCH64\MdePkg\Library\BaseMemoryLibOptDxe\BaseMemoryLibOptDxe\OUTPUT\AArch64\CompareGuid.iiii(8) : error A2034: unknown opcode: .
    .align  5
w:\edk2-exports\Build\Prm\DEBUG_VS2019\AARCH64\MdePkg\Library\BaseMemoryLibOptDxe\BaseMemoryLibOptDxe\OUTPUT\AArch64\CompareGuid.iiii(9) : error A2034: unknown opcode: InternalMemCompareGuid
ASM_GLOBAL InternalMemCompareGuid
w:\edk2-exports\Build\Prm\DEBUG_VS2019\AARCH64\MdePkg\Library\BaseMemoryLibOptDxe\BaseMemoryLibOptDxe\OUTPUT\AArch64\CompareGuid.iiii(13) : error A2173: syntax error in expression
    cbz     x1, 0f
w:\edk2-exports\Build\Prm\DEBUG_VS2019\AARCH64\MdePkg\Library\BaseMemoryLibOptDxe\BaseMemoryLibOptDxe\OUTPUT\AArch64\CompareGuid.iiii(19) : warning A4045: missing END directive
    ret
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.28.29910\bin\Hostx86\arm64\armasm64.exe"' : return code '0x1'
Stop.

Can you please let me know if this is a configuration/environment issue or the AARCH64 assembly files need to be ported for Visual Studio?

I have tried building other Arm packages and though the assembler files need porting, which I believe has been done as part of ProjectMu (https://github.com/microsoft/mu_silicon_arm_tiano).

It would be good to have AARCH64 builds of edk2 with Visual Studio as this would allow to use the VS static analysis tool.

Can you let me know if you have any plans to enable this support in Tianocore\edk2 project, please?

[/SAMI]

Regards,
Michael

On 8/3/2022 10:35 AM, Sami Mujawar wrote:
This patch series adds support to build PRM for AARCH64 using GCC.

The changes can be seen at:
https://github.com/samimujawar/edk2/tree/2238_aarch64_prm_support_v1

Jose Marinho (5):
   Basetools/GenFw: Allow AARCH64 builds to use the --prm flag
   PrmPkg: Enable external visibility on PRM symbols
   PrmPkg: Build Prm Samples with GCC for AARCH64
   PrmPkg: Support AArch64 builds using GCC
   PrmPkg: Add details on AArch64 build to the Readme.

BaseTools/Source/C/GenFw/Elf64Convert.c |  6 ++---
PrmPkg/Include/Prm.h |  3 +++
PrmPkg/PrmPkg.ci.yaml |  1 +
PrmPkg/PrmPkg.dsc | 24 +++++++++++++++++---
PrmPkg/Readme.md | 11 +++++++++
PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.inf |  4 ++++
PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf |  4 ++++
  7 files changed, 47 insertions(+), 6 deletions(-)

4521 - 4540 of 96644