public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Chiu, Chasel" <chasel.chiu@intel.com>
To: "Kubacki, Michael A" <michael.a.kubacki@intel.com>,
	"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Chaganty, Rangasai V" <rangasai.v.chaganty@intel.com>,
	"Desimone, Nathaniel L" <nathaniel.l.desimone@intel.com>,
	"Gao, Liming" <liming.gao@intel.com>,
	"Kinney, Michael D" <michael.d.kinney@intel.com>,
	"Sinha, Ankit" <ankit.sinha@intel.com>
Subject: Re: [edk2-platforms][PATCH V1 26/37] CoffeelakeSiliconPkg/Pch: Add modules
Date: Sat, 17 Aug 2019 01:14:40 +0000	[thread overview]
Message-ID: <3C3EFB470A303B4AB093197B6777CCEC504623AC@PGSMSX111.gar.corp.intel.com> (raw)
In-Reply-To: <20190817001603.30632-27-michael.a.kubacki@intel.com>

Reviewed-by: Chasel Chiu <chasel.chiu@intel.com>


> -----Original Message-----
> From: Kubacki, Michael A
> Sent: Saturday, August 17, 2019 8:16 AM
> To: devel@edk2.groups.io
> Cc: Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Chiu, Chasel
> <chasel.chiu@intel.com>; Desimone, Nathaniel L
> <nathaniel.l.desimone@intel.com>; Gao, Liming <liming.gao@intel.com>;
> Kinney, Michael D <michael.d.kinney@intel.com>; Sinha, Ankit
> <ankit.sinha@intel.com>
> Subject: [edk2-platforms][PATCH V1 26/37] CoffeelakeSiliconPkg/Pch: Add
> modules
> 
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2082
> 
> * PchInitDxeCnl - Generic DXE PCH initialization.
> * PchInitDxeFspCnl - Generic DXE PCH FSP initialization.
> * PchInitSmm - Generic SMM PCH initialization.
> * SmmControl - Produces an instance of EFI_SMM_CONTROL2_PROTOCOL.
> 
> Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
> Cc: Chasel Chiu <chasel.chiu@intel.com>
> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Ankit Sinha <ankit.sinha@intel.com>
> Signed-off-by: Michael Kubacki <michael.a.kubacki@intel.com>
> ---
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeCnl.inf
> |  99 ++++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeFspCnl.inf
> |  77 +++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf
> | 101 ++++
> 
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmContr
> ol.inf     |  54 ++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/Spi/Smm/PchSpiSmm.inf
> |  45 ++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h                    |
> 223 ++++++++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h
> | 187 +++++++
> 
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmContr
> olDriver.h | 132 +++++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c                    |
> 451 ++++++++++++++++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchCnviAcpi.c
> |  33 ++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c
> | 323 ++++++++++++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c                    |
> 554 ++++++++++++++++++++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c
> | 382 ++++++++++++++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitFsp.c                 |
> 85 +++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c                    |
> 89 ++++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c                |
> 57 ++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c
> | 156 ++++++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c
> | 156 ++++++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c
> | 179 +++++++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchLanSxSmm.c
> | 298 +++++++++++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c
> | 436 +++++++++++++++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c
> |  69 +++
> 
> Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmContr
> olDriver.c | 399 ++++++++++++++
>  Silicon/Intel/CoffeelakeSiliconPkg/Pch/Spi/Smm/PchSpi.c                         |
> 310 +++++++++++
>  24 files changed, 4895 insertions(+)
> 
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeCnl.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeCnl.inf
> new file mode 100644
> index 0000000000..5e0cf06cb6
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeCnl.inf
> @@ -0,0 +1,99 @@
> +## @file
> +# Component description file for Pch Initialization driver
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PchInitDxe
> +FILE_GUID = DE23ACEE-CF55-4fb6-AA77-984AB53DE823
> +VERSION_STRING = 1.0
> +MODULE_TYPE = DXE_DRIVER
> +ENTRY_POINT = PchInitEntryPointDxe
> +
> +
> +[LibraryClasses]
> +S3BootScriptLib
> +PchCycleDecodingLib
> +PchPcieRpLib
> +PchPcrLib
> +PchInfoLib
> +PchPciExpressHelpersLib
> +UefiBootServicesTableLib
> +DebugLib
> +IoLib
> +TimerLib
> +HobLib
> +BaseMemoryLib
> +MemoryAllocationLib
> +UefiLib
> +DxeServicesTableLib
> +UefiDriverEntryPoint
> +UefiRuntimeServicesTableLib
> +AslUpdateLib
> +CpuPlatformLib
> +GpioLib
> +PchSerialIoLib
> +PchHdaLib
> +PchInitCommonLib
> +ConfigBlockLib
> +PmcLib
> +PmcPrivateLib
> +PmcPrivateLibWithS3
> +SataLib
> +PchDmiWithS3Lib
> +PchGbeLib
> +SiScheduleResetLib
> +BiosLockLib
> +DxeSaPolicyLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Pcd]
> +gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
> +gSiPkgTokenSpaceGuid.PcdSiliconInitTempMemBaseAddr
> +
> +
> +[Sources]
> +PchInitDxe.c
> +PchInit.h
> +PchInit.c
> +PchSata.c
> +PchSerialIo.c
> +PchSerialIoDxe.c
> +PchHdaAcpi.c
> +PchCnviAcpi.c
> +PchAcpi.c
> +
> +[Protocols]
> +gPchNvsAreaProtocolGuid ## PRODUCES
> +gPchEmmcTuningProtocolGuid ## PRODUCES
> +gEfiPciIoProtocolGuid ## CONSUMES
> +gEfiAcpiTableProtocolGuid ## CONSUMES
> +gEfiBlockIoProtocolGuid ## CONSUMES
> +gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES
> +gPchPcieIoTrapProtocolGuid ## CONSUMES
> +gPchPolicyProtocolGuid ## CONSUMES
> +
> +
> +[Guids]
> +gEfiEndOfDxeEventGroupGuid
> +gEfiAcpiTableGuid
> +gSiConfigHobGuid                 ## CONSUMES
> +gPchConfigHobGuid                ## CONSUMES
> +gPchRstHobGuid                   ## CONSUMES
> +gHdAudioDxeConfigGuid            ## CONSUMES
> +gGpioDxeConfigGuid               ## CONSUMES
> +
> +
> +[Depex]
> +gEfiPciHostBridgeResourceAllocationProtocolGuid ## This is to ensure that
> PCI MMIO and IO resource has been prepared and available for this driver to
> allocate.
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeFspCnl.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeFspCnl.inf
> new file mode 100644
> index 0000000000..528cfd0296
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeFspCnl.inf
> @@ -0,0 +1,77 @@
> +## @file
> +#  Component description file for Pch Initialization driver for FSP package
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION          = 0x00010005
> +BASE_NAME            = PchInitDxe
> +FILE_GUID            = 5AA5031E-4CB6-43D4-B219-FE50FF5D116C
> +MODULE_TYPE          = PEIM
> +VERSION_STRING       = 1.0
> +ENTRY_POINT          = PchInitEntryPointFsp
> +
> +
> +[LibraryClasses]
> +PeimEntryPoint
> +PchCycleDecodingLib
> +PchPcieRpLib
> +PchPcrLib
> +PchInfoLib
> +PchPciExpressHelpersLib
> +DebugLib
> +IoLib
> +TimerLib
> +HobLib
> +BaseMemoryLib
> +MemoryAllocationLib
> +CpuPlatformLib
> +GpioLib
> +PchSerialIoLib
> +PchInitCommonLib
> +S3BootScriptLib  # NULL library
> +ConfigBlockLib
> +PmcLib
> +PmcPrivateLib
> +PmcPrivateLibWithS3
> +UsbInitLib
> +PchDmiWithS3Lib
> +PchGbeLib
> +SiScheduleResetLib
> +BiosLockLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Pcd]
> +gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
> +
> +
> +[Sources]
> +PchInitFsp.c
> +PchInit.h
> +PchInit.c
> +PchSata.c
> +PchSerialIo.c
> +
> +
> +[Protocols]
> +gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES
> +
> +
> +[Guids]
> +gEfiEventReadyToBootGuid
> +gSiConfigHobGuid                 ## CONSUMES
> +gPchConfigHobGuid                ## CONSUMES
> +
> +
> +[Depex]
> +  gEfiPeiMemoryDiscoveredPpiGuid
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf
> new file mode 100644
> index 0000000000..308da65385
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf
> @@ -0,0 +1,101 @@
> +## @file
> +# Component description file for PchInitSmm driver
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PchInitSmm
> +FILE_GUID = D7B10D4E-67E6-4C74-83E9-F9AF0ACC33CC
> +VERSION_STRING = 1.0
> +MODULE_TYPE = DXE_SMM_DRIVER
> +PI_SPECIFICATION_VERSION = 1.10
> +ENTRY_POINT = PchInitSmmEntryPoint
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +# VALID_ARCHITECTURES = IA32 X64
> +#
> +
> +
> +[LibraryClasses]
> +UefiBootServicesTableLib
> +UefiDriverEntryPoint
> +DxeServicesTableLib
> +IoLib
> +DebugLib
> +BaseLib
> +BaseMemoryLib
> +S3BootScriptLib
> +PchPciExpressHelpersLib
> +SmmServicesTableLib
> +PciSegmentLib
> +HobLib
> +GpioLib
> +GpioPrivateLib
> +ReportStatusCodeLib
> +DevicePathLib
> +PmcLib
> +PchPcieRpLib
> +PchInfoLib
> +TimerLib
> +ConfigBlockLib
> +PmcPrivateLib
> +SataLib
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Pcd]
> +gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
> +gSiPkgTokenSpaceGuid.PcdSiliconInitTempPciBusMin
> +gSiPkgTokenSpaceGuid.PcdSiliconInitTempPciBusMax
> +gSiPkgTokenSpaceGuid.PcdSiliconInitTempMemBaseAddr
> +gSiPkgTokenSpaceGuid.PcdSiliconInitTempMemSize
> +
> +
> +[Sources]
> +PchInitSmm.c
> +PchPcieSmm.c
> +PchLanSxSmm.c
> +PchInitSmm.h
> +PchBiosWriteProtect.c
> +PchSpiAsync.c
> +
> +
> +[Protocols]
> +gEfiSmmIoTrapDispatch2ProtocolGuid ## CONSUMES
> +gEfiSmmSxDispatch2ProtocolGuid ## CONSUMES
> +gPchSmmIoTrapControlGuid ## CONSUMES
> +gEfiSmmCpuProtocolGuid ## CONSUMES
> +gPchNvsAreaProtocolGuid ## CONSUMES
> +gPchPcieSmiDispatchProtocolGuid ## CONSUMES
> +gPchTcoSmiDispatchProtocolGuid ## CONSUMES
> +gPchSmiDispatchProtocolGuid ## CONSUMES
> +gPchEspiSmiDispatchProtocolGuid ## CONSUMES
> +gPchPcieIoTrapProtocolGuid ## PRODUCES
> +
> +
> +[Guids]
> +gSiConfigHobGuid             ## CONSUMES
> +gPchConfigHobGuid            ## CONSUMES
> +gPchDeviceTableHobGuid
> +
> +
> +[Depex]
> +gEfiSmmIoTrapDispatch2ProtocolGuid AND
> +gEfiSmmSxDispatch2ProtocolGuid AND
> +gPchSmmIoTrapControlGuid AND
> +gPchPcieSmiDispatchProtocolGuid AND
> +gPchTcoSmiDispatchProtocolGuid AND
> +gEfiSmmCpuProtocolGuid AND
> +gPchNvsAreaProtocolGuid AND
> +gEfiPciHostBridgeResourceAllocationProtocolGuid AND # This is to ensure
> that PCI MMIO resource has been prepared and available for this driver to
> allocate.
> +gEfiSmmBase2ProtocolGuid # This is for SmmServicesTableLib
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmCon
> trol.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmCon
> trol.inf
> new file mode 100644
> index 0000000000..ff712f8635
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmCon
> trol.inf
> @@ -0,0 +1,54 @@
> +## @file
> +# Component description file for SmmControl module
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = SmmControl
> +FILE_GUID = A0BAD9F7-AB78-491b-B583-C52B7F84B9E0
> +VERSION_STRING = 1.0
> +MODULE_TYPE = DXE_RUNTIME_DRIVER
> +ENTRY_POINT = SmmControlDriverEntryInit
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +# VALID_ARCHITECTURES = IA32 X64
> +#
> +
> +
> +
> +[LibraryClasses]
> +IoLib
> +UefiDriverEntryPoint
> +DebugLib
> +UefiBootServicesTableLib
> +UefiRuntimeServicesTableLib
> +PmcLib
> +GpioLib
> +
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +SmmControlDriver.h
> +SmmControlDriver.c
> +
> +
> +[Protocols]
> +gEfiSmmControl2ProtocolGuid ## PRODUCES
> +
> +
> +[Guids]
> +gEfiEventVirtualAddressChangeGuid
> +
> +
> +[Depex]
> +TRUE
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Spi/Smm/PchSpiSmm.inf
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Spi/Smm/PchSpiSmm.inf
> new file mode 100644
> index 0000000000..77bd3ad72b
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Spi/Smm/PchSpiSmm.inf
> @@ -0,0 +1,45 @@
> +## @file
> +# Component description file for the SPI SMM driver.
> +#
> +# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +INF_VERSION = 0x00010017
> +BASE_NAME = PchSpiSmm
> +FILE_GUID = 27F4917B-A707-4aad-9676-26DF168CBF0D
> +VERSION_STRING = 1.0
> +MODULE_TYPE = DXE_SMM_DRIVER
> +PI_SPECIFICATION_VERSION = 1.10
> +ENTRY_POINT = InstallPchSpi
> +
> +
> +[LibraryClasses]
> +DebugLib
> +IoLib
> +UefiDriverEntryPoint
> +UefiBootServicesTableLib
> +BaseLib
> +SmmServicesTableLib
> +PchSpiCommonLib
> +SmmPchPrivateLib
> +
> +[Packages]
> +MdePkg/MdePkg.dec
> +CoffeelakeSiliconPkg/SiPkg.dec
> +
> +
> +[Sources]
> +PchSpi.c
> +
> +
> +[Protocols]
> +gPchSmmSpiProtocolGuid ## PRODUCES
> +gEfiSmmCpuProtocolGuid ## CONSUMES
> +
> +[Depex]
> +gEfiSmmBase2ProtocolGuid AND # This is for SmmServicesTableLib
> +gEfiSmmCpuProtocolGuid # This is for CpuSmmDisableBiosWriteProtect()
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h
> new file mode 100644
> index 0000000000..b84c574a2e
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInit.h
> @@ -0,0 +1,223 @@
> +/** @file
> +  Header file for PCH Initialization Driver.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _PCH_INIT_DXE_H_
> +#define _PCH_INIT_DXE_H_
> +
> +#include <Protocol/PchEmmcTuning.h>
> +#include <SiConfigHob.h>
> +#include <Private/PchConfigHob.h>
> +#include <Private/Protocol/PchNvsArea.h>
> +
> +//
> +// Data definitions
> +//
> +extern EFI_HANDLE               mImageHandle;
> +
> +//
> +// Pch NVS area definition
> +//
> +extern PCH_NVS_AREA_PROTOCOL    mPchNvsAreaProtocol;
> +
> +extern PCH_CONFIG_HOB           *mPchConfigHob;
> +extern SI_CONFIG_HOB_DATA       *mSiConfigHobData;
> +
> +//
> +// Function Prototype
> +//
> +
> +//
> +// Local function prototypes
> +//
> +/**
> +  Initialize the PCH device according to the PCH Policy HOB
> +  and install PCH info instance.
> +
> +**/
> +VOID
> +InitializePchDevice (
> +  VOID
> +  );
> +
> +/**
> +  Common PchInit Module Entry Point
> +**/
> +VOID
> +PchInitEntryPointCommon (
> +  VOID
> +  );
> +
> +/**
> +  Common PCH initialization on PCI enumeration complete.
> +**/
> +VOID
> +PchOnPciEnumCompleteCommon (
> +  VOID
> +  );
> +
> +/**
> +  Configures Serial IO Controllers
> +
> +**/
> +EFI_STATUS
> +ConfigureSerialIoAtBoot (
> +  VOID
> +  );
> +
> +/**
> +  Creates device handles for SerialIo devices in ACPI mode
> +
> +**/
> +VOID
> +CreateSerialIoHandles (
> +  VOID
> +  );
> +
> +/**
> +  Mark memory used by SerialIo devices in ACPI mode as allocated
> +
> +  @retval EFI_SUCCESS             The function completed successfully
> +**/
> +EFI_STATUS
> +AllocateSerialIoMemory (
> +  VOID
> +  );
> +
> +/**
> +  Puts all SerialIo controllers (except UARTs in debug mode) in D3.
> +  Clears MemoryEnable for all PCI-mode controllers on S3 resume
> +**/
> +VOID
> +ConfigureSerialIoAtS3Resume (
> +  VOID
> +  );
> +
> +/**
> +  Update ASL definitions for SerialIo devices.
> +
> +  @retval EFI_SUCCESS             The function completed successfully
> +**/
> +EFI_STATUS
> +UpdateSerialIoAcpiData (
> +  VOID
> +  );
> +
> +/**
> +  Initialize PCIE SRC clocks in ICC subsystem
> +
> +  @param[in] GbePortNumber        Number of PCIE rootport assigned to
> GbE adapter
> +
> +**/
> +VOID
> +ConfigurePchPcieClocks (
> +  IN UINTN                        GbePortNumber
> +  );
> +
> +/**
> +  Initialize Intel High Definition Audio ACPI Tables
> +
> +  @retval EFI_SUCCESS             The function completed successfully
> +  @retval EFI_LOAD_ERROR          ACPI table cannot be installed
> +  @retval EFI_UNSUPPORTED         ACPI table not set because DSP is
> disabled
> +**/
> +EFI_STATUS
> +PchHdAudioAcpiInit (
> +  VOID
> +  );
> +
> +/**
> +  Configure eMMC in HS400 Mode
> +
> +  @param[in] This                         A pointer to
> PCH_EMMC_TUNING_PROTOCOL structure
> +  @param[in] Revision                     Revision parameter used to verify the
> layout of EMMC_INFO and TUNINGDATA.
> +  @param[in] EmmcInfo                     A pointer to EMMC_INFO structure
> +  @param[out] EmmcTuningData              A pointer to
> EMMC_TUNING_DATA structure
> +
> +  @retval EFI_SUCCESS                     The function completed successfully
> +  @retval EFI_NOT_FOUND                   The item was not found
> +  @retval EFI_OUT_OF_RESOURCES            The request could not be
> completed due to a lack of resources.
> +  @retval EFI_INVALID_PARAMETER           A parameter was incorrect.
> +  @retval EFI_DEVICE_ERROR                Hardware Error
> +  @retval EFI_NO_MEDIA                    No media
> +  @retval EFI_MEDIA_CHANGED               Media Change
> +  @retval EFI_BAD_BUFFER_SIZE             Buffer size is bad
> +  @retval EFI_CRC_ERROR                   Command or Data CRC Error
> +**/
> +EFI_STATUS
> +EFIAPI
> +ConfigureEmmcHs400Mode (
> +  IN  PCH_EMMC_TUNING_PROTOCOL          *This,
> +  IN  UINT8                             Revision,
> +  IN  EMMC_INFO                         *EmmcInfo,
> +  OUT EMMC_TUNING_DATA                  *EmmcTuningData
> +  );
> +
> +/**
> +  Get eMMC PCI cfg space address
> +
> +  @return UINT64  PCI base address
> +**/
> +UINT64
> +ScsGetEmmcBaseAddress (
> +  VOID
> +  );
> +
> +/**
> +  Perform the remaining configuration on PCH SATA to perform device
> detection,
> +  then set the SATA SPD and PxE corresponding, and set the Register Lock on
> PCH SATA
> +
> +  @retval None
> +**/
> +VOID
> +ConfigurePchSataOnEndOfDxe (
> +  VOID
> +  );
> +
> +/**
> +  Update ASL data for CNVI Device.
> +
> +  @retval EFI_SUCCESS             The function completed successfully
> +**/
> +EFI_STATUS
> +UpdateCnviAcpiData (
> +   VOID
> +   );
> +
> +/**
> +  Initialize Pch acpi
> +  @param[in] ImageHandle          Handle for the image of this driver
> +
> +  @retval EFI_SUCCESS             The function completed successfully
> +  @retval EFI_OUT_OF_RESOURCES    Do not have enough resources to
> initialize the driver
> +**/
> +EFI_STATUS
> +PchAcpiInit (
> +  IN EFI_HANDLE         ImageHandle
> +  );
> +
> +/**
> +  Update ASL object before Boot
> +
> +  @retval EFI_STATUS
> +  @retval EFI_NOT_READY         The Acpi protocols are not ready.
> +**/
> +EFI_STATUS
> +PchUpdateNvsArea (
> +  VOID
> +  );
> +
> +/**
> +  Initialize PCH Nvs Area opeartion region.
> +
> +**/
> +VOID
> +PatchPchNvsAreaAddress (
> +  VOID
> +  );
> +
> +#endif // _PCH_INIT_DXE_H_
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h
> new file mode 100644
> index 0000000000..693c5d3f50
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.h
> @@ -0,0 +1,187 @@
> +/** @file
> +  Header file for PCH Init SMM Handler
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _PCH_INIT_SMM_H_
> +#define _PCH_INIT_SMM_H_
> +
> +#include <PiDxe.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/UefiDriverEntryPoint.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/SmmServicesTableLib.h>
> +#include <Library/DxeServicesTableLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Protocol/SmmSxDispatch2.h>
> +#include <Protocol/SmmIoTrapDispatch2.h>
> +#include <Library/S3BootScriptLib.h>
> +#include <Library/HobLib.h>
> +#include <Protocol/SmmCpu.h>
> +#include <Library/TimerLib.h>
> +
> +#include <IndustryStandard/Pci30.h>
> +#include <Library/PmcLib.h>
> +#include <Library/PchPcieRpLib.h>
> +#include <Library/PchInfoLib.h>
> +#include <Library/SataLib.h>
> +#include <Library/GpioLib.h>
> +#include <Library/GpioNativeLib.h>
> +#include <Library/PchEspiLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/ConfigBlockLib.h>
> +#include <Private/Library/PchPciExpressHelpersLib.h>
> +#include <Protocol/PchPcieSmiDispatch.h>
> +#include <Protocol/PchTcoSmiDispatch.h>
> +#include <Protocol/PchSmiDispatch.h>
> +#include <Protocol/PchEspiSmiDispatch.h>
> +#include <Protocol/PchSmmIoTrapControl.h>
> +#include <Private/Protocol/PchNvsArea.h>
> +#include <Private/Protocol/PcieIoTrap.h>
> +#include <SiConfigHob.h>
> +#include <Private/PchConfigHob.h>
> +#include <Private/Library/PmcPrivateLib.h>
> +
> +extern EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL        *mPchIoTrap;
> +extern EFI_SMM_SX_DISPATCH2_PROTOCOL             *mSxDispatch;
> +
> +extern PCH_NVS_AREA                              *mPchNvsArea;
> +extern UINT16                                    mAcpiBaseAddr;
> +
> +extern EFI_PHYSICAL_ADDRESS                      mResvMmioBaseAddr;
> +extern UINTN                                     mResvMmioSize;
> +
> +//
> +// NOTE: The module variables of policy here are only valid in post time, but
> not runtime time.
> +//
> +extern PCH_CONFIG_HOB                            *mPchConfigHob;
> +extern SI_CONFIG_HOB_DATA                        *mSiConfigHobData;
> +
> +/**
> +  Register PCIE Hotplug SMI dispatch function to handle Hotplug enabling
> +
> +  @param[in] ImageHandle          The image handle of this module
> +  @param[in] SystemTable          The EFI System Table
> +
> +  @retval EFI_SUCCESS             The function completes successfully
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitializePchPcieSmm (
> +  IN      EFI_HANDLE            ImageHandle,
> +  IN      EFI_SYSTEM_TABLE      *SystemTable
> +  );
> +
> +/**
> +  PCIE Hotplug SMI call back function for each Root port
> +
> +  @param[in] DispatchHandle             Handle of this dispatch function
> +  @param[in] RpContext                  Rootport context, which contains
> RootPort Index,
> +                                        and RootPort PCI BDF.
> +**/
> +VOID
> +EFIAPI
> +PchPcieSmiRpHandlerFunction (
> +  IN  EFI_HANDLE                        DispatchHandle,
> +  IN  PCH_PCIE_SMI_RP_CONTEXT           *RpContext
> +  );
> +
> +/**
> +  PCIE Link Active State Change Hotplug SMI call back function for all Root
> ports
> +
> +  @param[in] DispatchHandle             Handle of this dispatch function
> +  @param[in] RpContext                  Rootport context, which contains
> RootPort Index,
> +                                        and RootPort PCI BDF.
> +**/
> +VOID
> +EFIAPI
> +PchPcieLinkActiveStateChange (
> +  IN  EFI_HANDLE                        DispatchHandle,
> +  IN  PCH_PCIE_SMI_RP_CONTEXT           *RpContext
> +  );
> +
> +/**
> +  PCIE Link Equalization Request SMI call back function for all Root ports
> +
> +  @param[in] DispatchHandle             Handle of this dispatch function
> +  @param[in] RpContext                  Rootport context, which contains
> RootPort Index,
> +                                        and RootPort PCI BDF.
> +**/
> +VOID
> +EFIAPI
> +PchPcieLinkEqHandlerFunction (
> +  IN  EFI_HANDLE                        DispatchHandle,
> +  IN  PCH_PCIE_SMI_RP_CONTEXT           *RpContext
> +  );
> +
> +/**
> +  An IoTrap callback to config PCIE power management settings
> +
> +  @param[in] DispatchHandle  - The handle of this callback, obtained when
> registering
> +  @param[in] DispatchContext - Pointer to the
> EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT
> +
> +**/
> +VOID
> +EFIAPI
> +PchPcieIoTrapSmiCallback (
> +  IN     EFI_HANDLE                     DispatchHandle,
> +  IN     EFI_SMM_IO_TRAP_CONTEXT        *CallbackContext,
> +  IN OUT VOID                           *CommBuffer,
> +  IN OUT UINTN                          *CommBufferSize
> +  );
> +
> +/**
> +  Initializes the PCH SMM handler for PCH save and restore
> +
> +  @param[in] ImageHandle - Handle for the image of this driver
> +  @param[in] SystemTable - Pointer to the EFI System Table
> +
> +  @retval EFI_SUCCESS    - PCH SMM handler was installed
> +**/
> +EFI_STATUS
> +EFIAPI
> +PchInitLateSmm (
> +  IN      EFI_HANDLE            ImageHandle,
> +  IN      EFI_SYSTEM_TABLE      *SystemTable
> +  );
> +
> +/**
> +  Register dispatch function to handle GPIO pads Sx isolation
> +**/
> +VOID
> +InitializeGpioSxIsolationSmm (
> +  VOID
> +  );
> +
> +/**
> +  Entry point for Pch Bios Write Protect driver.
> +
> +  @param[in] ImageHandle          Image handle of this driver.
> +  @param[in] SystemTable          Global system service table.
> +
> +  @retval EFI_SUCCESS             Initialization complete.
> +**/
> +EFI_STATUS
> +EFIAPI
> +InstallPchBiosWriteProtect (
> +  IN EFI_HANDLE            ImageHandle,
> +  IN EFI_SYSTEM_TABLE      *SystemTable
> +  );
> +
> +/**
> +  This fuction install SPI ASYNC SMI handler.
> +
> +  @retval EFI_SUCCESS             Initialization complete.
> +**/
> +EFI_STATUS
> +EFIAPI
> +InstallPchSpiAsyncSmiHandler (
> +  VOID
> +  );
> +
> +#endif
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmCon
> trolDriver.h
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmCon
> trolDriver.h
> new file mode 100644
> index 0000000000..08e64fa5a7
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmCon
> trolDriver.h
> @@ -0,0 +1,132 @@
> +/** @file
> +  Header file for SMM Control Driver.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef _SMM_CONTROL_DRIVER_H_
> +#define _SMM_CONTROL_DRIVER_H_
> +
> +#include <Protocol/SmmControl2.h>
> +
> +
> +#define SMM_CONTROL_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('i', '4',
> 's', 'c')
> +
> +typedef struct {
> +  UINTN                           Signature;
> +  EFI_HANDLE                      Handle;
> +  EFI_SMM_CONTROL2_PROTOCOL       SmmControl;
> +} SMM_CONTROL_PRIVATE_DATA;
> +
> +#define SMM_CONTROL_PRIVATE_DATA_FROM_THIS(a) CR (a,
> SMM_CONTROL_PRIVATE_DATA, SmmControl,
> SMM_CONTROL_DEV_SIGNATURE)
> +
> +//
> +// Prototypes
> +//
> +
> +/**
> +  <b>SmmControl DXE RUNTIME Module Entry Point</b>\n
> +  - <b>Introduction</b>\n
> +    The SmmControl module is a DXE RUNTIME driver that provides a standard
> way
> +    for other drivers to trigger software SMIs.
> +
> +  - @pre
> +    - PCH Power Management I/O space base address has already been
> programmed.
> +      If SmmControl Runtime DXE driver is run before Status Code Runtime
> Protocol
> +      is installed and there is the need to use Status code in the driver, it will
> +      be necessary to add EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID to
> the dependency file.
> +    - EFI_SMM_BASE2_PROTOCOL
> +      - Documented in the System Management Mode Core Interface
> Specification.
> +
> +  - @result
> +    The SmmControl driver produces the EFI_SMM_CONTROL_PROTOCOL
> documented in
> +    System Management Mode Core Interface Specification.
> +
> +  @param[in] ImageHandle          Handle for the image of this driver
> +  @param[in] SystemTable          Pointer to the EFI System Table
> +
> +  @retval EFI_STATUS              Results of the installation of the SMM Control
> Protocol
> +**/
> +EFI_STATUS
> +EFIAPI
> +SmmControlDriverEntryInit (
> +  IN EFI_HANDLE         ImageHandle,
> +  IN EFI_SYSTEM_TABLE   *SystemTable
> +  );
> +
> +/**
> +  Trigger the software SMI
> +
> +  @param[in] Data                 The value to be set on the software SMI data
> port
> +
> +  @retval EFI_SUCCESS             Function completes successfully
> +**/
> +EFI_STATUS
> +EFIAPI
> +SmmTrigger (
> +  UINT8   Data
> +  );
> +
> +/**
> +  Clear the SMI status
> +
> +
> +  @retval EFI_SUCCESS             The function completes successfully
> +  @retval EFI_DEVICE_ERROR        Something error occurred
> +**/
> +EFI_STATUS
> +EFIAPI
> +SmmClear (
> +  VOID
> +  );
> +
> +/**
> +  This routine generates an SMI
> +
> +  @param[in] This                       The EFI SMM Control protocol instance
> +  @param[in, out] ArgumentBuffer        The buffer of argument
> +  @param[in, out] ArgumentBufferSize    The size of the argument buffer
> +  @param[in] Periodic                   Periodic or not
> +  @param[in] ActivationInterval         Interval of periodic SMI
> +
> +  @retval EFI Status                    Describing the result of the operation
> +  @retval EFI_INVALID_PARAMETER         Some parameter value passed is
> not supported
> +**/
> +EFI_STATUS
> +EFIAPI
> +Activate (
> +  IN CONST EFI_SMM_CONTROL2_PROTOCOL    *This,
> +  IN OUT  UINT8                         *ArgumentBuffer OPTIONAL,
> +  IN OUT  UINT8                         *ArgumentBufferSize OPTIONAL,
> +  IN      BOOLEAN                       Periodic OPTIONAL,
> +  IN      UINTN                         ActivationInterval OPTIONAL
> +  );
> +
> +/**
> +  This routine clears an SMI
> +
> +  @param[in] This                 The EFI SMM Control protocol instance
> +  @param[in] Periodic             Periodic or not
> +
> +  @retval EFI Status              Describing the result of the operation
> +  @retval EFI_INVALID_PARAMETER   Some parameter value passed is not
> supported
> +**/
> +EFI_STATUS
> +EFIAPI
> +Deactivate (
> +  IN CONST EFI_SMM_CONTROL2_PROTOCOL    *This,
> +  IN       BOOLEAN                      Periodic OPTIONAL
> +  );
> +/**
> +  Disable all pending SMIs
> +
> +**/
> +VOID
> +EFIAPI
> +DisablePendingSmis (
> +  VOID
> +  );
> +
> +#endif
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c
> new file mode 100644
> index 0000000000..bcbdb12dc3
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchAcpi.c
> @@ -0,0 +1,451 @@
> +/** @file
> +  This is the driver that initializes the Intel PCH.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <IndustryStandard/Pci.h>
> +
> +#include "PchInit.h"
> +#include <Protocol/PchPolicy.h>
> +#include <ConfigBlock/GpioDevConfig.h>
> +#include <ConfigBlock/ScsConfig.h>
> +#include <Library/AslUpdateLib.h>
> +#include <Library/PchInfoLib.h>
> +#include <Library/GpioLib.h>
> +#include <Library/GpioNativeLib.h>
> +#include <Library/PchCycleDecodingLib.h>
> +#include <Library/PmcLib.h>
> +#include <Library/PchSerialIoLib.h>
> +#include <Library/PchGbeLib.h>
> +#include <Private/PchRstHob.h>
> +#include <Library/PchPcieRpLib.h>
> +#include <Library/CpuPlatformLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/SataLib.h>
> +#include <Register/PchRegsSata.h>
> +#include <TraceHubCommonConfig.h>
> +#include <PchReservedResources.h>
> +#include <Register/PchRegsTraceHub.h>
> +
> +//
> +// Module variables
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED PCH_NVS_AREA_PROTOCOL
> mPchNvsAreaProtocol;
> +
> +/**
> +  Retrieve interrupt information about a PCH device from policy
> +
> +  @param[in] Device                     PCI device number
> +
> +  @retval PCH_DEVICE_INTERRUPT_CONFIG   structure with device's
> interrupt information
> +**/
> +PCH_DEVICE_INTERRUPT_CONFIG
> +GetInterruptPolicy (
> +  IN PCH_SERIAL_IO_CONTROLLER  Device
> +  )
> +{
> +  PCH_DEVICE_INTERRUPT_CONFIG EmptyRecord;
> +  UINT8                       DevNum;
> +  UINT8                       FuncNum;
> +  UINT8                       Index;
> +
> +  ZeroMem (&EmptyRecord, sizeof (PCH_DEVICE_INTERRUPT_CONFIG));
> +  DevNum  = GetSerialIoDeviceNumber (Device);
> +  FuncNum = GetSerialIoFunctionNumber (Device);
> +
> +  for (Index = 0; Index < mPchConfigHob->Interrupt.NumOfDevIntConfig;
> Index++) {
> +    if ((mPchConfigHob->Interrupt.DevIntConfig[Index].Device == DevNum)
> &&
> +        (mPchConfigHob->Interrupt.DevIntConfig[Index].Function ==
> FuncNum)) {
> +      return mPchConfigHob->Interrupt.DevIntConfig[Index];
> +    }
> +  }
> +  return EmptyRecord;
> +}
> +
> +/**
> +  Update ASL definitions for SerialIo devices.
> +
> +  @retval EFI_SUCCESS                   The function completed successfully
> +**/
> +EFI_STATUS
> +UpdateSerialIoAcpiData (
> +  VOID
> +  )
> +{
> +  PCH_SERIAL_IO_CONTROLLER Index;
> +
> +  for (Index = 0; Index < GetPchMaxSerialIoControllersNum (); Index++) {
> +    mPchNvsAreaProtocol.Area->SMD[Index] =
> mPchConfigHob->SerialIo.DevMode[Index];
> +    mPchNvsAreaProtocol.Area->SIR[Index] = (GetInterruptPolicy (Index)).Irq;
> +    mPchNvsAreaProtocol.Area->SB0[Index] = (UINT32) FindSerialIoBar (Index,
> 0);
> +    mPchNvsAreaProtocol.Area->SB1[Index] = (UINT32) FindSerialIoBar (Index,
> 1);
> +  }
> +  if (IsPchH ()) {
> +    mPchNvsAreaProtocol.Area->SMD[PchSerialIoIndexI2C4] =
> PchSerialIoDisabled;
> +    mPchNvsAreaProtocol.Area->SMD[PchSerialIoIndexI2C5] =
> PchSerialIoDisabled;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Update NVS Area after RST PCIe Storage Remapping and before Boot
> +**/
> +VOID
> +PchUpdateNvsAreaAfterRemapping (
> +  VOID
> +  )
> +{
> +  UINTN                 Index;
> +  VOID                  *Hob;
> +  PCH_RST_HOB           *RstHob;
> +
> +  Hob = GetFirstGuidHob (&gPchRstHobGuid);
> +  if (Hob == NULL) {
> +    DEBUG (( DEBUG_INFO , "PchUpdateNvsAreaAfterRemapping: cannot
> fetch RstHob" ));
> +    return;
> +  }
> +
> +  RstHob = (PCH_RST_HOB *) GET_GUID_HOB_DATA (Hob);
> +
> +  for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
> +    mPchNvsAreaProtocol.Area->RstPcieStorageInterfaceType[Index]        =
> RstHob->RstCrConfiguration[Index].DeviceInterface;
> +    mPchNvsAreaProtocol.Area->RstPcieStoragePmCapPtr[Index]             =
> RstHob->SavedRemapedDeviceConfigSpace[Index].PmCapPtr;
> +    mPchNvsAreaProtocol.Area->RstPcieStoragePcieCapPtr[Index]           =
> RstHob->SavedRemapedDeviceConfigSpace[Index].PcieCapPtr;
> +    mPchNvsAreaProtocol.Area->RstPcieStorageL1ssCapPtr[Index]           =
> RstHob->SavedRemapedDeviceConfigSpace[Index].L1ssCapPtr;
> +    mPchNvsAreaProtocol.Area->RstPcieStorageEpL1ssControl2[Index]       =
> RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointL1ssControl2;
> +    mPchNvsAreaProtocol.Area->RstPcieStorageEpL1ssControl1[Index]       =
> RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointL1ssControl1;
> +    mPchNvsAreaProtocol.Area->RstPcieStorageLtrCapPtr[Index]            =
> RstHob->SavedRemapedDeviceConfigSpace[Index].LtrCapPtr;
> +    mPchNvsAreaProtocol.Area->RstPcieStorageEpLtrData[Index]            =
> RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointLtrData;
> +    mPchNvsAreaProtocol.Area->RstPcieStorageEpLctlData16[Index]         =
> RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointLctlData16;
> +    mPchNvsAreaProtocol.Area->RstPcieStorageEpDctlData16[Index]         =
> RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointDctlData16;
> +    mPchNvsAreaProtocol.Area->RstPcieStorageEpDctl2Data16[Index]        =
> RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointDctl2Data16;
> +    mPchNvsAreaProtocol.Area->RstPcieStorageRpDctl2Data16[Index]        =
> RstHob->SavedRemapedDeviceConfigSpace[Index].RootPortDctl2Data16;
> +    mPchNvsAreaProtocol.Area->RstPcieStorageUniqueTableBar[Index]
> = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixTableBar;
> +    mPchNvsAreaProtocol.Area->RstPcieStorageUniqueTableBarValue[Index]
> = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixTableBarValue;
> +    mPchNvsAreaProtocol.Area->RstPcieStorageUniquePbaBar[Index]
> = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixPbaBar;
> +    mPchNvsAreaProtocol.Area->RstPcieStorageUniquePbaBarValue[Index]
> = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixPbaBarValue;
> +    mPchNvsAreaProtocol.Area->RstPcieStorageRootPortNum[Index]
> = RstHob->RstCrConfiguration[Index].RootPortNum;
> +  }
> +}
> +
> +/**
> +  PCH ACPI initialization before Boot Sript Table is closed
> +  It update ACPI table and ACPI NVS area.
> +
> +  @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
> +PchAcpiOnEndOfDxe (
> +  IN EFI_EVENT    Event,
> +  IN VOID         *Context
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  DEBUG ((DEBUG_INFO, "PchAcpiOnEndOfDxe() Start\n"));
> +
> +  ///
> +  /// Closed the event to avoid call twice when launch shell
> +  ///
> +  gBS->CloseEvent (Event);
> +
> +  //
> +  // Init HDA Audio ACPI tables
> +  //
> +  PchHdAudioAcpiInit ();
> +
> +  //
> +  // Update ASL definitions for SerialIo devices.
> +  //
> +  UpdateSerialIoAcpiData ();
> +  UpdateCnviAcpiData ();
> +
> +  //
> +  // Update Pch Nvs Area
> +  //
> +  Status = PchUpdateNvsArea ();
> +  if (EFI_ERROR (Status)) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "PchAcpiOnEndOfDxe() End\n"));
> +
> +  return;
> +}
> +
> +/**
> +  Initialize Pch acpi
> +  @param[in] ImageHandle          Handle for the image of this driver
> +
> +  @retval EFI_SUCCESS             The function completed successfully
> +  @retval EFI_OUT_OF_RESOURCES    Do not have enough resources to
> initialize the driver
> +**/
> +EFI_STATUS
> +PchAcpiInit (
> +  IN EFI_HANDLE         ImageHandle
> +  )
> +{
> +  EFI_STATUS  Status;
> +  EFI_EVENT   EndOfDxeEvent;
> +
> +  DEBUG ((DEBUG_INFO, "Install PCH NVS protocol\n"));
> +
> +  Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (PCH_NVS_AREA),
> (VOID **) &mPchNvsAreaProtocol.Area);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  ZeroMem ((VOID *) mPchNvsAreaProtocol.Area, sizeof (PCH_NVS_AREA));
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &ImageHandle,
> +                  &gPchNvsAreaProtocolGuid,
> +                  &mPchNvsAreaProtocol,
> +                  NULL
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  ///
> +  /// Update the NVS Area after RST PCIe Storage Remapping
> +  ///
> +  PchUpdateNvsAreaAfterRemapping ();
> +
> +  //
> +  // Register an end of DXE event for PCH ACPI to do tasks before invoking any
> UEFI drivers,
> +  // applications, or connecting consoles,...
> +  //
> +  Status = gBS->CreateEventEx (
> +                  EVT_NOTIFY_SIGNAL,
> +                  TPL_CALLBACK,
> +                  PchAcpiOnEndOfDxe,
> +                  NULL,
> +                  &gEfiEndOfDxeEventGroupGuid,
> +                  &EndOfDxeEvent
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return Status;
> +}
> +
> +/**
> +  Update ASL object before Boot
> +
> +  @retval EFI_STATUS
> +  @retval EFI_NOT_READY         The Acpi protocols are not ready.
> +**/
> +EFI_STATUS
> +PchUpdateNvsArea (
> +  VOID
> +  )
> +{
> +  EFI_STATUS            Status;
> +  UINTN                 Index;
> +  UINT32                HpetBaseAdress;
> +  GPIO_GROUP            GroupToGpeDwX[3];
> +  UINT32                GroupDw[3];
> +  UINTN                 RpDev;
> +  UINTN                 RpFun;
> +  UINT32                Data32;
> +  PCH_POLICY_PROTOCOL   *PchPolicy;
> +  PCH_GPIO_DXE_CONFIG   *GpioDxeConfig;
> +
> +  ///
> +  /// Get PCH Policy Protocol
> +  ///
> +  Status = gBS->LocateProtocol (&gPchPolicyProtocolGuid, NULL, (VOID
> **)&PchPolicy);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  ///
> +  /// Get GPIO DXE Config Block
> +  ///
> +  Status = GetConfigBlock ((VOID *)PchPolicy, &gGpioDxeConfigGuid, (VOID
> *)&GpioDxeConfig);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Update ASL PCIE port address according to root port device and function
> +  //
> +  for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
> +    Status = GetPchPcieRpDevFun (Index, &RpDev, &RpFun);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    Data32 = ((UINT8) RpDev << 16) | (UINT8) RpFun;
> +    mPchNvsAreaProtocol.Area->RpAddress[Index] = Data32;
> +
> +    //
> +    // Update Maximum Snoop Latency and Maximum No-Snoop Latency
> values for PCIE
> +    //
> +    mPchNvsAreaProtocol.Area->PcieLtrMaxSnoopLatency[Index]   =
> mPchConfigHob->PcieRp.RootPort[Index].LtrMaxSnoopLatency;
> +    mPchNvsAreaProtocol.Area->PcieLtrMaxNoSnoopLatency[Index] =
> mPchConfigHob->PcieRp.RootPort[Index].LtrMaxNoSnoopLatency;
> +  }
> +
> +  //
> +  // Update PCHS.
> +  //
> +  mPchNvsAreaProtocol.Area->PchSeries     = PchSeries ();
> +  //
> +  // Update PCHG.
> +  //
> +  mPchNvsAreaProtocol.Area->PchGeneration = (UINT16) PchGeneration ();
> +  //
> +  // Update PSTP.
> +  //
> +  mPchNvsAreaProtocol.Area->PchStepping = (UINT16) PchStepping ();
> +  //
> +  // Update HPET base address.
> +  //
> +  PchHpetBaseGet (&HpetBaseAdress);
> +  mPchNvsAreaProtocol.Area->HPTE          = TRUE;  // @todo remove the
> NVS, since it's always enabled.
> +  mPchNvsAreaProtocol.Area->HPTB          = HpetBaseAdress;
> +  //
> +  // Update SBREG_BAR.
> +  //
> +  mPchNvsAreaProtocol.Area->SBRG          = PCH_PCR_BASE_ADDRESS;
> +
> +  //
> +  // Update PMC ACPIBASE and PWRMBASE
> +  //
> +  mPchNvsAreaProtocol.Area->PMBS = PmcGetAcpiBase ();
> +
> +  mPchNvsAreaProtocol.Area->PWRM = PmcGetPwrmBase ();
> +
> +  //
> +  // Update GPIO device ACPI variables
> +  //
> +  mPchNvsAreaProtocol.Area->SGIR =
> mPchConfigHob->Interrupt.GpioIrqRoute;
> +  mPchNvsAreaProtocol.Area->GPHD =
> (UINT8)GpioDxeConfig->HideGpioAcpiDevice;
> +
> +  //
> +  // Update GPP_X to GPE_DWX mapping.
> +  //
> +  GpioGetGroupDwToGpeDwX (
> +    &GroupToGpeDwX[0], &GroupDw[0],
> +    &GroupToGpeDwX[1], &GroupDw[1],
> +    &GroupToGpeDwX[2], &GroupDw[2]
> +    );
> +
> +  //
> +  // GEI0/1/2 and GED0/1/2 are objects for informing how GPIO groups are
> mapped to GPE0.
> +  // If Group is mapped to 1-Tier GPE information is also stored on what
> Group DW
> +  // is mapped to GPE_DWx. Because GPE_DWx register is 32 bits large if
> groups have more than
> +  // 32 pads only part of it can be mapped.
> +  //
> +  //  GEIx - GroupIndex mapped to GPE0_DWx
> +  //  GEDx - DoubleWorld part of Group: 0 - pins 31-0, 1 - pins 63-32, ...
> +  //
> +  mPchNvsAreaProtocol.Area->GEI0 = (UINT8)
> GpioGetGroupIndexFromGroup (GroupToGpeDwX[0]);
> +  mPchNvsAreaProtocol.Area->GEI1 = (UINT8)
> GpioGetGroupIndexFromGroup (GroupToGpeDwX[1]);
> +  mPchNvsAreaProtocol.Area->GEI2 = (UINT8)
> GpioGetGroupIndexFromGroup (GroupToGpeDwX[2]);
> +  mPchNvsAreaProtocol.Area->GED0 = (UINT8) GroupDw[0];
> +  mPchNvsAreaProtocol.Area->GED1 = (UINT8) GroupDw[1];
> +  mPchNvsAreaProtocol.Area->GED2 = (UINT8) GroupDw[2];
> +
> +  //
> +  // SCS Configuration
> +  //
> +  // Update eMMC HS400 mode enablement
> +  //
> +  mPchNvsAreaProtocol.Area->EMH4 = (UINT8)
> mPchConfigHob->Scs.ScsEmmcHs400Enabled;
> +  mPchNvsAreaProtocol.Area->EmmcEnabled = (UINT8)
> mPchConfigHob->Scs.ScsEmmcEnabled;
> +
> +  //
> +  // Update eMMC Driver Strength
> +  // Per eMMC 5.01 JEDEC Specification (JESD84-B50.1, Table 186)
> +  // Nominal Impedance - Driver Type Values:
> +  // 50 Ohm              0x0
> +  // 33 Ohm              0x1
> +  // 40 Ohm              0x4
> +  //
> +  switch (mPchConfigHob->Scs.ScsEmmcHs400DriverStrength) {
> +    case DriverStrength33Ohm:
> +      mPchNvsAreaProtocol.Area->EMDS = 0x1;
> +      break;
> +    case DriverStrength40Ohm:
> +      mPchNvsAreaProtocol.Area->EMDS = 0x4;
> +      break;
> +    case DriverStrength50Ohm:
> +    default:
> +      mPchNvsAreaProtocol.Area->EMDS = 0x0;
> +  }
> +
> +  mPchNvsAreaProtocol.Area->SdPowerEnableActiveHigh = (UINT8)
> mPchConfigHob->Scs.ScsSdPowerEnableActiveHigh;
> +  mPchNvsAreaProtocol.Area->SdCardEnabled           = (UINT8)
> mPchConfigHob->Scs.ScsSdCardEnabled;
> +
> +  //
> +  // SATA configuration.
> +  //
> +  if (PciSegmentRead16 (GetSataRegBase (SATA_1_CONTROLLER_INDEX) +
> PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
> +    mPchNvsAreaProtocol.Area->SataPortPresence = 0;
> +  } else {
> +    mPchNvsAreaProtocol.Area->SataPortPresence = PciSegmentRead8
> (GetSataRegBase (SATA_1_CONTROLLER_INDEX) + R_SATA_CFG_PCS + 2);
> +  }
> +
> +  //
> +  // CPU SKU
> +  //
> +  mPchNvsAreaProtocol.Area->CpuSku = GetCpuSku ();
> +
> +  mPchNvsAreaProtocol.Area->SlpS0VmRuntimeControl =
> (UINT8)mPchConfigHob->Pm.SlpS0VmRuntimeControl;
> +  mPchNvsAreaProtocol.Area->SlpS0Vm070VSupport    =
> (UINT8)mPchConfigHob->Pm.SlpS0Vm070VSupport;
> +  mPchNvsAreaProtocol.Area->SlpS0Vm075VSupport    =
> (UINT8)mPchConfigHob->Pm.SlpS0Vm075VSupport;
> +  mPchNvsAreaProtocol.Area->PsOnEnable            =
> (UINT8)mPchConfigHob->Pm.PsOnEnable;
> +
> +  for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
> +    mPchNvsAreaProtocol.Area->LtrEnable[Index]  =
> (UINT8)mPchConfigHob->PcieRp.RootPort[Index].LtrEnable;
> +  }
> +
> +  mPchNvsAreaProtocol.Area->GBES = PchIsGbePresent ();
> +
> +  //
> +  // Update PCH Trace Hub Mode
> +  //
> +  mPchNvsAreaProtocol.Area->PchTraceHubMode     = (UINT8)
> mPchConfigHob->PchTraceHub.PchTraceHubMode;
> +  //
> +  // if SCRPD0[24] is set, force TH to be host debugger mode.
> +  //
> +  if (MmioRead32 (PCH_TRACE_HUB_MTB_BASE_ADDRESS) != 0xFFFFFFFF) {
> +    if (MmioRead32 (PCH_TRACE_HUB_MTB_BASE_ADDRESS +
> R_TRACE_HUB_MEM_CSR_MTB_SCRATCHPAD0) & BIT24) {
> +      mPchNvsAreaProtocol.Area->PchTraceHubMode =
> TraceHubModeHostDebugger;
> +    }
> +  }
> +
> +  //
> +  // Update TWMB, Temp memory base address
> +  //
> +  mPchNvsAreaProtocol.Area->TempRsvdMemBase = (UINT32) PcdGet32
> (PcdSiliconInitTempMemBaseAddr);
> +
> +  return Status;
> +}
> +
> +/**
> +  Initialize PCH Nvs Area opeartion region.
> +
> +**/
> +VOID
> +PatchPchNvsAreaAddress (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                            Status;
> +  UINT32                                Address;
> +  UINT16                                Length;
> +
> +  Status = InitializeAslUpdateLib ();
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Address = (UINT32) (UINTN) mPchNvsAreaProtocol.Area;
> +  Length  = (UINT16) sizeof (PCH_NVS_AREA);
> +  DEBUG ((DEBUG_INFO, "PatchPchNvsAreaAddress: PCH NVS Address %x
> Length %x\n", Address, Length));
> +  Status  = UpdateNameAslCode (SIGNATURE_32 ('P','N','V','B'), &Address,
> sizeof (Address));
> +  ASSERT_EFI_ERROR (Status);
> +  Status  = UpdateNameAslCode (SIGNATURE_32 ('P','N','V','L'), &Length,
> sizeof (Length));
> +  ASSERT_EFI_ERROR (Status);
> +}
> +
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchCnviAcpi.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchCnviAcpi.c
> new file mode 100644
> index 0000000000..4e38db1027
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchCnviAcpi.c
> @@ -0,0 +1,33 @@
> +/** @file
> +  Initializes PCH CNVi device ACPI data.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include "PchInit.h"
> +#include <Library/DxeSaPolicyLib.h>
> +
> +/**
> +  Update ASL definitions for CNVi device.
> +
> +  @retval EFI_SUCCESS         The function completed successfully
> +**/
> +EFI_STATUS
> +UpdateCnviAcpiData (
> +  VOID
> +  )
> +{
> +
> +  DEBUG ((DEBUG_INFO, "UpdateCnviAcpiData() Start\n"));
> +
> +  mPchNvsAreaProtocol.Area->CnviMode = (UINT8)
> mPchConfigHob->Cnvi.Mode;
> +
> +  DEBUG ((DEBUG_INFO, "UpdateCnviAcpiData() End\n"));
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c
> new file mode 100644
> index 0000000000..57f2e1dca0
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchHdaAcpi.c
> @@ -0,0 +1,323 @@
> +/** @file
> +  Initializes the PCH HD Audio ACPI Tables.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Protocol/AcpiTable.h>
> +
> +#include "PchInit.h"
> +#include <Protocol/PchPolicy.h>
> +#include <ConfigBlock/HdAudioConfig.h>
> +#include <Private/PchConfigHob.h>
> +#include <Library/PchInfoLib.h>
> +#include <Private/Library/PchHdaLib.h>
> +#include <IndustryStandard/Pci30.h>
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsHda.h>
> +
> +PCH_HDA_NHLT_ENDPOINTS mPchHdaNhltEndpoints[HdaEndpointMax] =
> +{
> +  {HdaDmicX1,     B_HDA_DMIC_1CH_48KHZ_16BIT_FORMAT,
> 0, FALSE},
> +  {HdaDmicX2,     (B_HDA_DMIC_2CH_48KHZ_16BIT_FORMAT |
> B_HDA_DMIC_2CH_48KHZ_32BIT_FORMAT),        0, FALSE},
> +  {HdaDmicX4,     (B_HDA_DMIC_4CH_48KHZ_16BIT_FORMAT |
> B_HDA_DMIC_4CH_48KHZ_32BIT_FORMAT),        0, FALSE},
> +  {HdaBtRender,   (B_HDA_BT_NARROWBAND_FORMAT |
> B_HDA_BT_WIDEBAND_FORMAT | B_HDA_BT_A2DP_FORMAT), 0, FALSE},
> +  {HdaBtCapture,  (B_HDA_BT_NARROWBAND_FORMAT |
> B_HDA_BT_WIDEBAND_FORMAT),                        0, FALSE},
> +  {HdaI2sRender1,
> B_HDA_I2S_RTK274_RENDER_4CH_48KHZ_24BIT_FORMAT,
> B_HDA_I2S_RENDER_DEVICE_INFO,      FALSE},
> +  {HdaI2sRender2,
> B_HDA_I2S_RTK274_RENDER_4CH_48KHZ_24BIT_FORMAT,
> B_HDA_I2S_RENDER_DEVICE_INFO,      FALSE},
> +  {HdaI2sCapture,
> B_HDA_I2S_RTK274_CAPTURE_4CH_48KHZ_24BIT_FORMAT,
> B_HDA_I2S_CAPTURE_DEVICE_INFO,    FALSE}
> +};
> +
> +#define DSP_FW_STOLEN_MEMORY_SIZE 0x400000 //4MB
> +/**
> +  Allocates 4MB of memory for DSP FW usage.
> +
> +  @retval EFI_PHYSICAL_ADDRESS  Allocated memory address
> +**/
> +EFI_PHYSICAL_ADDRESS
> +AllocateAudioDspStolenMemory (
> +  )
> +{
> +  EFI_STATUS           Status;
> +  EFI_PHYSICAL_ADDRESS DspStolenMemBaseAddress;
> +
> +  DspStolenMemBaseAddress = 0;
> +
> +  DEBUG ((DEBUG_INFO, "AllocateAudioDspStolenMemory()\n"));
> +
> +  //
> +  // Reserve memory to store Acpi Debug data.
> +  //
> +  DspStolenMemBaseAddress = 0xFFFFFFFF;
> +  Status = gBS->AllocatePages (
> +                  AllocateMaxAddress,
> +                  EfiReservedMemoryType,
> +                  EFI_SIZE_TO_PAGES (DSP_FW_STOLEN_MEMORY_SIZE),
> +                  &DspStolenMemBaseAddress
> +                  );
> +  ASSERT_EFI_ERROR(Status);
> +
> +  ZeroMem ((VOID *) (UINTN) DspStolenMemBaseAddress,
> DSP_FW_STOLEN_MEMORY_SIZE);
> +
> +  mPchNvsAreaProtocol.Area->DSPM = (UINT32)
> DspStolenMemBaseAddress;
> +  DEBUG ((DEBUG_INFO, "mPchNvsAreaProtocol.Area->DSPM = 0x%016x\n",
> mPchNvsAreaProtocol.Area->DSPM));
> +
> +  return DspStolenMemBaseAddress;
> +}
> +
> +/**
> +  Retrieves address of NHLT table from XSDT/RSDT.
> +
> +  @retval NHLT_ACPI_TABLE*  Pointer to NHLT table if found
> +  @retval NULL              NHLT could not be found
> +**/
> +NHLT_ACPI_TABLE *
> +LocateNhltAcpiTable (
> +  VOID
> +  )
> +{
> +  EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *Rsdp;
> +  EFI_ACPI_DESCRIPTION_HEADER                   *Xsdt;
> +  NHLT_ACPI_TABLE                               *Nhlt;
> +  UINTN                                         Index;
> +  UINT64                                        Data64;
> +  EFI_STATUS                                    Status;
> +  Rsdp  = NULL;
> +  Xsdt  = NULL;
> +  Nhlt  = NULL;
> +
> +  ///
> +  /// Find the AcpiSupport protocol returns RSDP (or RSD PTR) address.
> +  ///
> +  DEBUG ((DEBUG_INFO, "LocateNhltAcpiTable() Start\n"));
> +
> +  Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID *)
> &Rsdp);
> +  if (EFI_ERROR (Status) || (Rsdp == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "EFI_ERROR or Rsdp == NULL\n"));
> +    return NULL;
> +  }
> +
> +  Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress;
> +  if (Xsdt == NULL || Xsdt->Signature !=
> EFI_ACPI_5_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
> +    // If XSDT has not been found, check RSDT
> +    Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;
> +    if (Xsdt == NULL || Xsdt->Signature !=
> EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
> +      DEBUG ((DEBUG_ERROR, "XSDT/RSDT == NULL or wrong signature\n"));
> +      return NULL;
> +    }
> +  }
> +
> +  for (Index = sizeof (EFI_ACPI_DESCRIPTION_HEADER); Index < Xsdt->Length;
> Index = Index + sizeof (UINT64)) {
> +    Data64  = *(UINT64 *) ((UINT8 *) Xsdt + Index);
> +    Nhlt    = (NHLT_ACPI_TABLE *) (UINTN) Data64;
> +    if (Nhlt->Header.Signature == NHLT_ACPI_TABLE_SIGNATURE) {
> +      break;
> +    }
> +  }
> +
> +  if (Nhlt == NULL || Nhlt->Header.Signature !=
> NHLT_ACPI_TABLE_SIGNATURE) {
> +    DEBUG ((DEBUG_ERROR, "Nhlt == NULL or wrong signature\n"));
> +    return NULL;
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Found NhltTable, Address = 0x%016x\n", Nhlt));
> +
> +  return Nhlt;
> +}
> +
> +/**
> +  Constructs and installs NHLT table.
> +
> +  @retval EFI_SUCCESS       ACPI Table installed successfully
> +  @retval EFI_UNSUPPORTED   ACPI Table protocol not found
> +**/
> +EFI_STATUS
> +PublishNhltAcpiTable (
> +  VOID
> +  )
> +{
> +  UINTN                                     AcpiTableKey;
> +  EFI_ACPI_TABLE_PROTOCOL                   *AcpiTable;
> +  NHLT_ACPI_TABLE                           *NhltTable;
> +  UINT32                                    TableLength;
> +  EFI_STATUS                                Status;
> +
> +  AcpiTable = NULL;
> +  NhltTable = NULL;
> +  AcpiTableKey = 0;
> +
> +  DEBUG ((DEBUG_INFO, "PublishNhltAcpiTable() Start\n"));
> +
> +  //
> +  // Locate ACPI support protocol
> +  //
> +  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)
> &AcpiTable);
> +  if ( EFI_ERROR (Status) || AcpiTable == NULL) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  NhltConstructor (mPchHdaNhltEndpoints, &NhltTable, &TableLength);
> +  NhltAcpiHeaderConstructor (NhltTable, TableLength);
> +
> +  Status = AcpiTable->InstallAcpiTable (AcpiTable, NhltTable,
> NhltTable->Header.Length, &AcpiTableKey);
> +
> +  DEBUG ((DEBUG_INFO, "PublishNhltAcpiTable() End\n"));
> +  return Status;
> +}
> +
> +/**
> +  Sets NVS ACPI variables for HDAS._DSM and SNDW._DSD accordingly to
> policy.
> +
> +  @param[in]                NhltAcpiTableAddress
> +  @param[in]                NhltAcpiTableLength
> +  @param[in]                *HdAudioConfigHob
> +  @param[in]                *HdAudioDxeConfig
> +**/
> +VOID
> +UpdateHdaAcpiData (
> +  IN       UINT64                 NhltAcpiTableAddress,
> +  IN       UINT32                 NhltAcpiTableLength,
> +  IN CONST HDAUDIO_HOB            *HdAudioConfigHob,
> +  IN CONST PCH_HDAUDIO_DXE_CONFIG *HdAudioDxeConfig
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "UpdateHdaAcpiData():\n NHLT Address = 0x%016x,
> Length = 0x%08x\n", NhltAcpiTableAddress, NhltAcpiTableLength));
> +  DEBUG ((DEBUG_INFO, " FeatureMask = 0x%08x\n",
> HdAudioDxeConfig->DspFeatureMask));
> +
> +  mPchNvsAreaProtocol.Area->NHLA = NhltAcpiTableAddress;
> +  mPchNvsAreaProtocol.Area->NHLL = NhltAcpiTableLength;
> +  mPchNvsAreaProtocol.Area->ADFM =
> HdAudioDxeConfig->DspFeatureMask;
> +  mPchNvsAreaProtocol.Area->SWQ0 =
> HdAudioConfigHob->AudioLinkSndw1 ? 0 : BIT1;
> +  mPchNvsAreaProtocol.Area->SWQ1 =
> HdAudioConfigHob->AudioLinkSndw2 ? 0 : BIT1;
> +  mPchNvsAreaProtocol.Area->SWQ2 =
> HdAudioConfigHob->AudioLinkSndw3 ? 0 : BIT1;
> +  mPchNvsAreaProtocol.Area->SWQ3 =
> HdAudioConfigHob->AudioLinkSndw4 ? 0 : BIT1;
> +}
> +
> +/**
> +  Initialize and publish NHLT (Non-HDA Link Table), update NVS variables.
> +
> +  @param[in]                *HdAudioConfigHob
> +  @param[in]                *HdAudioDxeConfig
> +
> +  @retval EFI_SUCCESS    The function completed successfully
> +**/
> +EFI_STATUS
> +SetHdaAcpiTable (
> +  IN CONST HDAUDIO_HOB            *HdAudioConfigHob,
> +  IN CONST PCH_HDAUDIO_DXE_CONFIG *HdAudioDxeConfig
> +  )
> +{
> +  NHLT_ACPI_TABLE     *NhltTable;
> +  EFI_STATUS          Status;
> +  NhltTable = NULL;
> +
> +  Status = EFI_SUCCESS;
> +
> +  if (HdAudioDxeConfig->NhltDefaultFlow == TRUE) {
> +    switch (HdAudioDxeConfig->DspEndpointDmic) {
> +      case PchHdaDmic1chArray:
> +        mPchHdaNhltEndpoints[HdaDmicX1].Enable   = TRUE;
> +        break;
> +      case PchHdaDmic2chArray:
> +        mPchHdaNhltEndpoints[HdaDmicX2].Enable   = TRUE;
> +        break;
> +      case PchHdaDmic4chArray:
> +        mPchHdaNhltEndpoints[HdaDmicX4].Enable   = TRUE;
> +        break;
> +      case PchHdaDmicDisabled:
> +      default:
> +        mPchHdaNhltEndpoints[HdaDmicX2].Enable   = FALSE;
> +        mPchHdaNhltEndpoints[HdaDmicX4].Enable   = FALSE;
> +    }
> +
> +    if (HdAudioDxeConfig->DspEndpointBluetooth) {
> +      mPchHdaNhltEndpoints[HdaBtRender].Enable   = TRUE;
> +      mPchHdaNhltEndpoints[HdaBtCapture].Enable  = TRUE;
> +    }
> +
> +    if (HdAudioDxeConfig->DspEndpointI2s) {
> +      mPchHdaNhltEndpoints[HdaI2sRender1].Enable = TRUE;
> +      mPchHdaNhltEndpoints[HdaI2sRender2].Enable = TRUE;
> +      mPchHdaNhltEndpoints[HdaI2sCapture].Enable = TRUE;
> +    }
> +
> +    Status    = PublishNhltAcpiTable ();
> +  }
> +  NhltTable = LocateNhltAcpiTable ();
> +  if (NhltTable == NULL) {
> +    return EFI_LOAD_ERROR;
> +  }
> +
> +  UpdateHdaAcpiData ((UINT64) (UINTN) NhltTable, (UINT32)
> (NhltTable->Header.Length), HdAudioConfigHob, HdAudioDxeConfig);
> +
> +  if (IsPchLp () && (PchStepping () < PCH_B0)) {
> +    AllocateAudioDspStolenMemory ();
> +  }
> +
> +  DEBUG_CODE ( NhltAcpiTableDump (NhltTable); );
> +  return Status;
> +}
> +
> +/**
> +  Initialize Intel High Definition Audio ACPI Tables
> +
> +  @retval EFI_SUCCESS             The function completed successfully
> +  @retval EFI_LOAD_ERROR          ACPI table cannot be installed
> +  @retval EFI_UNSUPPORTED         ACPI table not set because DSP is
> disabled
> +**/
> +EFI_STATUS
> +PchHdAudioAcpiInit (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINT64                        HdaPciBase;
> +  CONST HDAUDIO_HOB             *HdAudioConfigHob;
> +  PCH_POLICY_PROTOCOL           *PchPolicy;
> +  PCH_HDAUDIO_DXE_CONFIG        *HdAudioDxeConfig;
> +
> +
> +  DEBUG ((DEBUG_INFO, "PchHdAudioAcpiInit() Start\n"));
> +
> +  HdAudioConfigHob = &mPchConfigHob->HdAudio;
> +
> +  ///
> +  /// Get PCH Policy Protocol
> +  ///
> +  Status = gBS->LocateProtocol (&gPchPolicyProtocolGuid, NULL, (VOID
> **)&PchPolicy);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  ///
> +  /// Get HD Audio DXE Config Block
> +  ///
> +  Status = GetConfigBlock ((VOID *)PchPolicy, &gHdAudioDxeConfigGuid,
> (VOID *)&HdAudioDxeConfig);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  HdaPciBase = PCI_SEGMENT_LIB_ADDRESS (
> +                 DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +                 DEFAULT_PCI_BUS_NUMBER_PCH,
> +                 PCI_DEVICE_NUMBER_PCH_HDA,
> +                 PCI_FUNCTION_NUMBER_PCH_HDA,
> +                 0
> +                 );
> +
> +  if ((PciSegmentRead16 (HdaPciBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF)
> || (HdAudioConfigHob->DspEnable == FALSE)) {
> +    // Do not set ACPI tables if HDAudio is Function disabled or DSP is disabled
> +    DEBUG ((DEBUG_INFO, "AudioDSP: Non-HDAudio ACPI Table (NHLT) not
> set!\n"));
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  Status = SetHdaAcpiTable (HdAudioConfigHob, HdAudioDxeConfig);
> +
> +  DEBUG ((DEBUG_INFO, "PchHdAudioAcpiInit() End - Status = %r\n", Status));
> +  return Status;
> +}
> +
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c
> new file mode 100644
> index 0000000000..55f1e086fb
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInit.c
> @@ -0,0 +1,554 @@
> +/** @file
> +  This is the Common driver that initializes the Intel PCH.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/TimerLib.h>
> +#include <Library/S3BootScriptLib.h>
> +#include <Library/HobLib.h>
> +
> +#include "PchInit.h"
> +#include <PchPolicyCommon.h>
> +#include <Private/Library/PchSpiCommonLib.h>
> +#include <Private/Library/PmcPrivateLib.h>
> +#include <Private/Library/PchDmiLib.h>
> +#include <Private/Library/SiScheduleResetLib.h>
> +#include <Library/PchCycleDecodingLib.h>
> +#include <Library/BiosLockLib.h>
> +#include <Library/PchPcrLib.h>
> +#include <IndustryStandard/Pci30.h>
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsPcr.h>
> +#include <Register/PchRegsLpc.h>
> +#include <Register/PchRegsSpi.h>
> +#include <Register/PchRegsPsth.h>
> +#include <Register/PchRegsPmc.h>
> +
> +//
> +// Module variables
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED PCH_CONFIG_HOB
> *mPchConfigHob;
> +GLOBAL_REMOVE_IF_UNREFERENCED SI_CONFIG_HOB_DATA
> *mSiConfigHobData;
> +
> +//
> +// EFI_EVENT
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_EVENT mHeciEvent;
> +
> +/**
> +  Common PchInit Module Entry Point
> +**/
> +VOID
> +PchInitEntryPointCommon (
> +  VOID
> +  )
> +{
> +  EFI_PEI_HOB_POINTERS  HobPtr;
> +
> +  DEBUG ((DEBUG_INFO, "PchInitEntryPointCommon() Start\n"));
> +
> +  //
> +  // Get PCH Config HOB.
> +  //
> +  HobPtr.Guid   = GetFirstGuidHob (&gPchConfigHobGuid);
> +  ASSERT (HobPtr.Guid != NULL);
> +  mPchConfigHob = (PCH_CONFIG_HOB *) GET_GUID_HOB_DATA
> (HobPtr.Guid);
> +
> +  //
> +  // Get Silicon Config data HOB
> +  //
> +  HobPtr.Guid   = GetFirstGuidHob (&gSiConfigHobGuid);
> +  ASSERT (HobPtr.Guid != NULL);
> +  mSiConfigHobData = (SI_CONFIG_HOB_DATA *) GET_GUID_HOB_DATA
> (HobPtr.Guid);
> +
> +  DEBUG ((DEBUG_INFO, "PchInitEntryPointCommon() End\n"));
> +
> +  return;
> +}
> +
> +/**
> +  Lock SPI register before boot
> +**/
> +VOID
> +LockSpiConfiguration (
> +  VOID
> +  )
> +{
> +  UINTN         Index;
> +  UINT16        Data16;
> +  UINT16        Data16And;
> +  UINT16        Data16Or;
> +  UINT32        Data32;
> +  UINT32        DlockValue;
> +  UINT64        PciSpiRegBase;
> +  UINT32        PchSpiBar0;
> +  UINT32        Timer;
> +
> +  PciSpiRegBase   = PCI_SEGMENT_LIB_ADDRESS (
> +                      DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +                      DEFAULT_PCI_BUS_NUMBER_PCH,
> +                      PCI_DEVICE_NUMBER_PCH_SPI,
> +                      PCI_FUNCTION_NUMBER_PCH_SPI,
> +                      0
> +                      );
> +
> +  //
> +  // Check for SPI controller presence before programming
> +  //
> +  if (PciSegmentRead32 (PciSpiRegBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF)
> {
> +    return;
> +  }
> +
> +  //
> +  // Make sure SPI BAR0 has fixed address before writing to boot script.
> +  // The same base address is set in PEI and will be used during resume.
> +  //
> +  PchSpiBar0 = PCH_SPI_BASE_ADDRESS;
> +
> +  PciSegmentAnd8    (PciSpiRegBase + PCI_COMMAND_OFFSET, (UINT8)
> ~EFI_PCI_COMMAND_MEMORY_SPACE);
> +  PciSegmentWrite32 (PciSpiRegBase + R_SPI_CFG_BAR0, PchSpiBar0);
> +  PciSegmentOr8     (PciSpiRegBase + PCI_COMMAND_OFFSET,
> EFI_PCI_COMMAND_MEMORY_SPACE);
> +
> +  //
> +  // Program the Flash Protection Range Register based on policy
> +  //
> +  DlockValue = MmioRead32 (PchSpiBar0 + R_SPI_MEM_DLOCK);
> +  for (Index = 0; Index < PCH_FLASH_PROTECTED_RANGES; ++Index) {
> +    if ((mPchConfigHob->ProtectRange[Index].WriteProtectionEnable ||
> +         mPchConfigHob->ProtectRange[Index].ReadProtectionEnable) !=
> TRUE) {
> +      continue;
> +    }
> +
> +    //
> +    // Proceed to program the register after ensure it is enabled
> +    //
> +    Data32 = 0;
> +    Data32 |= (mPchConfigHob->ProtectRange[Index].WriteProtectionEnable
> == TRUE) ? B_SPI_MEM_PRX_WPE : 0;
> +    Data32 |= (mPchConfigHob->ProtectRange[Index].ReadProtectionEnable
> == TRUE) ? B_SPI_MEM_PRX_RPE : 0;
> +    Data32 |= ((UINT32)
> mPchConfigHob->ProtectRange[Index].ProtectedRangeLimit <<
> N_SPI_MEM_PRX_PRL) & B_SPI_MEM_PRX_PRL_MASK;
> +    Data32 |= ((UINT32)
> mPchConfigHob->ProtectRange[Index].ProtectedRangeBase <<
> N_SPI_MEM_PRX_PRB) & B_SPI_MEM_PRX_PRB_MASK;
> +    DEBUG ((DEBUG_INFO, "Protected range %d: 0x%08x \n", Index, Data32));
> +
> +    DlockValue |= (UINT32) (B_SPI_MEM_DLOCK_PR0LOCKDN << Index);
> +    MmioWrite32 ((UINTN) (PchSpiBar0 + (R_SPI_MEM_PR0 + (Index *
> S_SPI_MEM_PRX))), Data32);
> +    S3BootScriptSaveMemWrite (
> +      S3BootScriptWidthUint32,
> +      (UINTN) (PchSpiBar0 + (R_SPI_MEM_PR0 + (Index * S_SPI_MEM_PRX))),
> +      1,
> +      (VOID *) (UINTN) (PchSpiBar0 + (R_SPI_MEM_PR0 + (Index *
> S_SPI_MEM_PRX)))
> +      );
> +  }
> +  //
> +  // Program DLOCK register
> +  //
> +  MmioWrite32 ((UINTN) (PchSpiBar0 + R_SPI_MEM_DLOCK), DlockValue);
> +  S3BootScriptSaveMemWrite (
> +    S3BootScriptWidthUint32,
> +    (UINTN) (PchSpiBar0 + R_SPI_MEM_DLOCK),
> +    1,
> +    (VOID *) (UINTN) (PchSpiBar0 + R_SPI_MEM_DLOCK)
> +    );
> +
> +  ///
> +  /// PCH BIOS Spec Section 3.6 Flash Security Recommendation
> +  /// In PCH SPI controller the BIOS should set the Flash Configuration
> Lock-Down bit
> +  /// (SPI_BAR0 + 04[15]) at end of post.  When set to 1, those Flash Program
> Registers
> +  /// that are locked down by this FLOCKDN bit cannot be written.
> +  /// Please refer to the EDS for which program registers are impacted.
> +  /// Additionally BIOS must program SPI_BAR0 + 0x04 BIT11 (WRSDIS) to
> disable Write Status in HW sequencing
> +  ///
> +
> +  //
> +  // Ensure there is no pending SPI trasaction before setting lock bits
> +  //
> +  Timer = 0;
> +  while (MmioRead16 (PchSpiBar0 + R_SPI_MEM_HSFSC) &
> B_SPI_MEM_HSFSC_SCIP) {
> +    if (Timer > SPI_WAIT_TIME) {
> +      //
> +      // SPI transaction is pending too long at this point, exit with error.
> +      //
> +      DEBUG ((DEBUG_ERROR, "SPI Cycle timeout\n"));
> +      ASSERT (FALSE);
> +      break;
> +    }
> +    MicroSecondDelay (SPI_WAIT_PERIOD);
> +    Timer += SPI_WAIT_PERIOD;
> +  }
> +
> +  Data16And = B_SPI_MEM_HSFSC_SCIP;
> +  Data16    = 0;
> +  S3BootScriptSaveMemPoll (
> +    S3BootScriptWidthUint16,
> +    PchSpiBar0 + R_SPI_MEM_HSFSC,
> +    &Data16And,
> +    &Data16,
> +    SPI_WAIT_PERIOD,
> +    SPI_WAIT_TIME / SPI_WAIT_PERIOD
> +    );
> +
> +  //
> +  // Clear any outstanding status
> +  //
> +  Data16Or  = B_SPI_MEM_HSFSC_SAF_DLE
> +            | B_SPI_MEM_HSFSC_SAF_ERROR
> +            | B_SPI_MEM_HSFSC_AEL
> +            | B_SPI_MEM_HSFSC_FCERR
> +            | B_SPI_MEM_HSFSC_FDONE;
> +  Data16And = 0xFFFF;
> +  MmioAndThenOr16 (PchSpiBar0 + R_SPI_MEM_HSFSC, Data16And,
> Data16Or);
> +  S3BootScriptSaveMemReadWrite (
> +    S3BootScriptWidthUint16,
> +    PchSpiBar0 + R_SPI_MEM_HSFSC,
> +    &Data16Or,
> +    &Data16And
> +    );
> +
> +  //
> +  // Set WRSDIS
> +  //
> +  Data16Or  = B_SPI_MEM_HSFSC_WRSDIS;
> +  Data16And = 0xFFFF;
> +  MmioAndThenOr16 (PchSpiBar0 + R_SPI_MEM_HSFSC, Data16And,
> Data16Or);
> +  S3BootScriptSaveMemReadWrite (
> +    S3BootScriptWidthUint16,
> +    PchSpiBar0 + R_SPI_MEM_HSFSC,
> +    &Data16Or,
> +    &Data16And
> +    );
> +
> +  //
> +  // Set FLOCKDN
> +  //
> +  Data16Or  = B_SPI_MEM_HSFSC_FLOCKDN;
> +  Data16And = 0xFFFF;
> +  MmioAndThenOr16 (PchSpiBar0 + R_SPI_MEM_HSFSC, Data16And,
> Data16Or);
> +  S3BootScriptSaveMemReadWrite (
> +    S3BootScriptWidthUint16,
> +    PchSpiBar0 + R_SPI_MEM_HSFSC,
> +    &Data16Or,
> +    &Data16And
> +    );
> +
> +  ///
> +  /// SPI Flash Programming Guide Section 5.5.2 Vendor Component Lock
> +  /// It is strongly recommended that BIOS sets the Vendor Component Lock
> (VCL) bits. VCL applies
> +  /// the lock to both VSCC0 and VSCC1 even if VSCC0 is not used. Without the
> VCL bits set, it is
> +  /// possible to make Host/GbE VSCC register(s) changes in that can cause
> undesired host and
> +  /// integrated GbE Serial Flash functionality.
> +  ///
> +  MmioOr32 ((UINTN) (PchSpiBar0 + R_SPI_MEM_SFDP0_VSCC0),
> B_SPI_MEM_SFDP0_VSCC0_VCL);
> +  S3BootScriptSaveMemWrite (
> +    S3BootScriptWidthUint32,
> +    (UINTN) (PchSpiBar0 + R_SPI_MEM_SFDP0_VSCC0),
> +    1,
> +    (VOID *) (UINTN) (PchSpiBar0 + R_SPI_MEM_SFDP0_VSCC0)
> +    );
> +}
> +
> +/**
> +  Process all the lock downs
> +**/
> +VOID
> +ProcessAllLocks (
> +  VOID
> +  )
> +{
> +  UINT8         Data8;
> +  UINT16        Data16And;
> +  UINT16        Data16Or;
> +  UINT32        Data32And;
> +  UINT32        Data32Or;
> +  UINT64        PciLpcRegBase;
> +  UINT16        TcoBase;
> +  UINT64        PciSpiRegBase;
> +
> +  PciLpcRegBase   = PCI_SEGMENT_LIB_ADDRESS (
> +                      DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +                      DEFAULT_PCI_BUS_NUMBER_PCH,
> +                      PCI_DEVICE_NUMBER_PCH_LPC,
> +                      PCI_FUNCTION_NUMBER_PCH_LPC,
> +                      0
> +                      );
> +  PciSpiRegBase   = PCI_SEGMENT_LIB_ADDRESS (
> +                      DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +                      DEFAULT_PCI_BUS_NUMBER_PCH,
> +                      PCI_DEVICE_NUMBER_PCH_SPI,
> +                      PCI_FUNCTION_NUMBER_PCH_SPI,
> +                      0
> +                      );
> +
> +  PchTcoBaseGet (&TcoBase);
> +
> +  //
> +  // Lock function disable (ST and NST PG) register fields.
> +  //
> +  PmcLockFunctionDisableConfigWithS3BootScript ();
> +
> +  ///
> +  /// PCH BWG Additional PCH DMI and OP-DMI Programming Steps
> +  /// Lock DMI.
> +  ///
> +    PchDmiSetLockWithS3BootScript ();
> +
> +  //
> +  // Lock SPI register before boot.
> +  //
> +  LockSpiConfiguration ();
> +
> +  ///
> +  /// Additional Power Management Programming
> +  /// Step 3
> +  /// Lock configuration after stretch and ACPI base programming completed.
> +  ///
> +  PmcLockSlpSxStretchingPolicyWithS3BootScript ();
> +
> +  //
> +  // Set BiosLock.
> +  //
> +  if (mPchConfigHob->LockDown.BiosLock == TRUE) {
> +    BiosLockEnable ();
> +  }
> +
> +  ///
> +  /// PCH BIOS Spec Section 3.6 Flash Security Recommendation
> +  /// BIOS also needs to set the BIOS Interface Lock Down bit in multiple
> locations
> +  /// (PCR[DMI] + 274Ch[0], LPC/eSPI PCI offset DCh[7] and SPI PCI offset
> DCh[7]).
> +  /// Setting these bits will prevent writes to the Top Swap bit (under their
> respective locations)
> +  /// and the Boot BIOS Straps. Enabling this bit will mitigate malicious
> software
> +  /// attempts to replace the system BIOS option ROM with its own code.
> +  ///
> +  if (mPchConfigHob->LockDown.BiosInterface == TRUE) {
> +    //
> +    // LPC
> +    //
> +    PciSegmentOr8 ((UINT64) (PciLpcRegBase + R_LPC_CFG_BC), (UINT32)
> B_LPC_CFG_BC_BILD);
> +    S3BootScriptSaveMemWrite (
> +      S3BootScriptWidthUint8,
> +      PcdGet64 (PcdPciExpressBaseAddress) + PciLpcRegBase +
> R_LPC_CFG_BC,
> +      1,
> +      (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) + PciLpcRegBase
> + R_LPC_CFG_BC)
> +      );
> +
> +    //
> +    // Reads back for posted write to take effect
> +    //
> +    Data8 = PciSegmentRead8 ((UINTN) (PciLpcRegBase + R_LPC_CFG_BC));
> +    S3BootScriptSaveMemPoll  (
> +      S3BootScriptWidthUint8,
> +      PcdGet64 (PcdPciExpressBaseAddress) + PciLpcRegBase +
> R_LPC_CFG_BC,
> +      &Data8,  // BitMask
> +      &Data8,  // BitValue
> +      1,       // Duration
> +      1        // LoopTimes
> +      );
> +
> +    //
> +    // SPI
> +    //
> +    PciSegmentOr8 ((UINT64) (PciSpiRegBase + R_SPI_CFG_BC), (UINT32)
> B_SPI_CFG_BC_BILD);
> +    S3BootScriptSaveMemWrite (
> +      S3BootScriptWidthUint8,
> +      PcdGet64 (PcdPciExpressBaseAddress) + PciSpiRegBase + R_SPI_CFG_BC,
> +      1,
> +      (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) + PciSpiRegBase
> + R_SPI_CFG_BC)
> +      );
> +
> +    //
> +    // Reads back for posted write to take effect
> +    //
> +    Data8 = PciSegmentRead8 ((UINT64) (PciSpiRegBase + R_SPI_CFG_BC));
> +    S3BootScriptSaveMemPoll  (
> +      S3BootScriptWidthUint8,
> +      PcdGet64 (PcdPciExpressBaseAddress) + PciSpiRegBase + R_SPI_CFG_BC,
> +      &Data8,     // BitMask
> +      &Data8,     // BitValue
> +      1,          // Duration
> +      1           // LoopTimes
> +      );
> +
> +    ///
> +    /// Set BIOS interface Lock-Down
> +    ///
> +    PchDmiSetBiosLockDownWithS3BootScript ();
> +  }
> +
> +  ///
> +  /// PCH BIOS Spec on using RTC RAM
> +  /// Regardless of BUC.TS being updated or not, BIOS must set RC.BILD bit
> PCR[RTC] + 3400h[31] before exit
> +  /// For Data integrity protection, set RTC Memory locks (Upper 128 Byte Lock
> and
> +  /// Lower 128 Byte Lock) at PCR[RTC] + 3400h[4] and PCR[RTC] + 3400h[3].
> +  /// Note once locked bytes 0x38 - 0x3F in each of the Upper and Lower Byte
> blocks, respectively,
> +  /// cannot be unlocked until next reset.
> +  ///
> +  Data32And = 0xFFFFFFFF;
> +  Data32Or = 0x0;
> +
> +  if (mPchConfigHob->LockDown.BiosInterface == TRUE) {
> +    Data32Or  = B_RTC_PCR_CONF_BILD;
> +  }
> +  if (mPchConfigHob->LockDown.RtcMemoryLock == TRUE) {
> +    Data32Or |= (B_RTC_PCR_CONF_UCMOS_LOCK |
> B_RTC_PCR_CONF_LCMOS_LOCK);
> +  }
> +  PchPcrAndThenOr32 (
> +    PID_RTC_HOST, R_RTC_PCR_CONF,
> +    Data32And,
> +    Data32Or
> +    );
> +  PCH_PCR_BOOT_SCRIPT_READ_WRITE (
> +    S3BootScriptWidthUint32,
> +    PID_RTC_HOST, R_RTC_PCR_CONF,
> +    &Data32Or,
> +    &Data32And
> +    );
> +
> +  ///
> +  ///  Remove access to RTC PCRs
> +  ///
> +  Data32And = (UINT32)~(BIT0);
> +  Data32Or  = 0;
> +  PchPcrAndThenOr32 (
> +    PID_RTC_HOST, R_RTC_PCR_PG1_AC_LO,
> +    Data32And,
> +    Data32Or
> +    );
> +  PCH_PCR_BOOT_SCRIPT_READ_WRITE (
> +    S3BootScriptWidthUint32,
> +    PID_RTC_HOST, R_RTC_PCR_PG1_AC_LO,
> +    &Data32Or,
> +    &Data32And
> +    );
> +  PchPcrAndThenOr32 (
> +    PID_RTC_HOST, R_RTC_PCR_PG1_CP_LO,
> +    Data32And,
> +    Data32Or
> +    );
> +  PCH_PCR_BOOT_SCRIPT_READ_WRITE (
> +    S3BootScriptWidthUint32,
> +    PID_RTC_HOST, R_RTC_PCR_PG1_CP_LO,
> +    &Data32Or,
> +    &Data32And
> +    );
> +
> +  //
> +  // Lock Down TCO
> +  //
> +  Data16And = 0xFFFF;
> +  Data16Or  = B_TCO_IO_TCO1_CNT_LOCK;
> +  IoOr16 (TcoBase + R_TCO_IO_TCO1_CNT, Data16Or);
> +  S3BootScriptSaveIoReadWrite (
> +    S3BootScriptWidthUint16,
> +    (UINTN) (TcoBase + R_TCO_IO_TCO1_CNT),
> +    &Data16Or,  // Data to be ORed
> +    &Data16And  // Data to be ANDed
> +    );
> +
> +  ///
> +  /// PCH BIOS Spec Section 5.15.1 Additional Chipset Initialization
> +  /// Step 1
> +  /// Lock PMC Set Strap Message Interface
> +  ///
> +  PmcLockSetStrapMsgInterfaceWithS3BootScript ();
> +  //
> +  // Lock Down PMC
> +  //
> +  PmcLockWithS3BootScript ();
> +}
> +
> +/**
> +  Set eSPI BME bit
> +**/
> +VOID
> +ConfigureEspiBme (
> +  VOID
> +  )
> +{
> +  UINT64 EspiPciBase;
> +
> +  EspiPciBase = PCI_SEGMENT_LIB_ADDRESS (
> +                  DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +                  DEFAULT_PCI_BUS_NUMBER_PCH,
> +                  PCI_DEVICE_NUMBER_PCH_LPC,
> +                  PCI_FUNCTION_NUMBER_PCH_LPC,
> +                  0
> +                  );
> +
> +  if (PciSegmentRead16 (EspiPciBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
> +    return;
> +  }
> +  if ((PciSegmentRead32 (EspiPciBase + R_ESPI_CFG_PCBC) &
> B_ESPI_CFG_PCBC_ESPI_EN) == 0) {
> +    return;
> +  }
> +
> +  //
> +  // Refer to PCH BWG.
> +  // To enable eSPI bus mastering BIOS must enable BME in eSPI controller
> +  // and also set BME bit in the respective slave devices through Configuration
> +  // and Capabilities register of each slave using Get_Configuration and
> Set_Configuration functionality.
> +  //
> +  // NOTE: The setting is also done in PEI, but might be cleared by PCI bus
> during PCI enumeration.
> +  //       Therefore, reeable it after PCI enumeration done.
> +  //
> +  if (mPchConfigHob->Espi.BmeMasterSlaveEnabled == TRUE) {
> +    PciSegmentOr8 (EspiPciBase + PCI_COMMAND_OFFSET,
> EFI_PCI_COMMAND_BUS_MASTER);
> +  }
> +}
> +
> +/**
> +  Common PCH initialization before Boot Sript Table is closed
> +
> +**/
> +VOID
> +PchOnPciEnumCompleteCommon (
> +  VOID
> +  )
> +{
> +  UINT32                                    Data32Or;
> +  UINT32                                    Data32And;
> +  BOOLEAN                                   ResetStatus;
> +
> +  DEBUG ((DEBUG_INFO, "PchOnPciEnumCompleteCommon() Start\n"));
> +
> +  if (SiScheduleResetIsRequired ()) {
> +    ResetStatus = SiScheduleResetPerformReset ();
> +    ASSERT (!ResetStatus);
> +  }
> +
> +  ProcessAllLocks ();
> +
> +  //
> +  // Perform remaining configuration for PCH SATA on End of DXE
> +  //
> +  ConfigurePchSataOnEndOfDxe ();
> +  //
> +  // PSTHCTL (0xD00h[2]) = 1, PSTH IOSF Primary Trunk Clock Gating Enable
> (PSTHIOSFPTCGE)
> +  //
> +  Data32And = 0xFFFFFFFF;
> +  Data32Or =  B_PSTH_PCR_PSTHIOSFPTCGE;
> +  PchPcrAndThenOr32 (PID_PSTH, R_PSTH_PCR_PSTHCTL, Data32And,
> Data32Or);
> +  PCH_PCR_BOOT_SCRIPT_READ_WRITE (
> +    S3BootScriptWidthUint32,
> +    PID_PSTH, R_PSTH_PCR_PSTHCTL,
> +    &Data32Or,
> +    &Data32And
> +    );
> +
> +  //
> +  // Set eSPI BME after PCI enumeration
> +  //
> +  ConfigureEspiBme ();
> +
> +  ///
> +  /// Clear Global Reset Status, Power Failure and Host Reset Status bits
> +  ///
> +  PmcClearGlobalResetStatus ();
> +  PmcClearPowerFailureStatus ();
> +  PmcClearHostResetStatus ();
> +
> +  DEBUG ((DEBUG_INFO, "PchOnPciEnumCompleteCommon() End\n"));
> +}
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c
> new file mode 100644
> index 0000000000..b106c849e9
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxe.c
> @@ -0,0 +1,382 @@
> +/** @file
> +  This is the Uefi driver that initializes the Intel PCH.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/S3BootScriptLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +
> +#include "PchInit.h"
> +#include <PchPolicyCommon.h>
> +#include <Private/Protocol/PcieIoTrap.h>
> +#include <Library/PchInfoLib.h>
> +#include <Library/PmcLib.h>
> +#include <Library/PchPcieRpLib.h>
> +#include <Private/Library/PmcPrivateLib.h>
> +#include <Private/Library/PchPciExpressHelpersLib.h>
> +#include <PcieRegs.h>
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsPcie.h>
> +#include <Register/PchRegsPmc.h>
> +#include <Register/PchRegsThermalCnl.h>
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_HANDLE
> mImageHandle;
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT16
> mPcieIoTrapAddress;
> +
> +VOID
> +EFIAPI
> +PchOnBootToOs (
> +  IN EFI_EVENT    Event,
> +  IN VOID         *Context
> +  );
> +
> +
> +VOID
> +EFIAPI
> +PchOnExitBootServices (
> +  IN EFI_EVENT    Event,
> +  IN VOID         *Context
> +  );
> +
> +
> +VOID
> +EFIAPI
> +PchOnReadyToBoot (
> +  IN EFI_EVENT    Event,
> +  IN VOID         *Context
> +  );
> +
> +/**
> +  Process all the lock downs
> +**/
> +VOID
> +ProcessSmiLocks (
> +  VOID
> +  )
> +{
> +  UINT32        Data32And;
> +  UINT32        Data32Or;
> +  UINT16        ABase;
> +
> +  ///
> +  /// PCH BIOS Spec Section 3.6 Flash Security Recommendation
> +  /// BIOS needs to enables SMI_LOCK (PMC PCI offset A0h[4] = 1b) which
> prevent writes
> +  /// to the Global SMI Enable bit (GLB_SMI_EN ABASE + 30h[0]). Enabling this
> bit will
> +  /// mitigate malicious software attempts to gain system management mode
> privileges.
> +  ///
> +  if (mPchConfigHob->LockDown.GlobalSmi == TRUE) {
> +    ///
> +    /// Save Global SMI Enable bit setting before BIOS enables SMI_LOCK
> during S3 resume
> +    ///
> +    ABase = PmcGetAcpiBase ();
> +    Data32Or = IoRead32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN));
> +    if ((Data32Or & B_ACPI_IO_SMI_EN_GBL_SMI) != 0) {
> +      Data32And = 0xFFFFFFFF;
> +      Data32Or |= B_ACPI_IO_SMI_EN_GBL_SMI;
> +      S3BootScriptSaveIoReadWrite (
> +        S3BootScriptWidthUint32,
> +        (UINTN) (ABase + R_ACPI_IO_SMI_EN),
> +        &Data32Or,  // Data to be ORed
> +        &Data32And  // Data to be ANDed
> +        );
> +    }
> +      PmcLockSmiWithS3BootScript ();
> +  }
> +}
> +
> +/**
> +  Do PCIE power management while resume from S3
> +**/
> +VOID
> +ReconfigurePciePowerManagementForS3 (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                            Status;
> +  UINT32                                Data32;
> +  PCH_PCIE_IOTRAP_PROTOCOL              *PchPcieIoTrapProtocol;
> +
> +  Status = gBS->LocateProtocol (&gPchPcieIoTrapProtocolGuid, NULL, (VOID
> **) &PchPcieIoTrapProtocol);
> +  if (EFI_ERROR (Status)) {
> +    return;
> +  }
> +  mPcieIoTrapAddress = PchPcieIoTrapProtocol->PcieTrapAddress;
> +  DEBUG ((DEBUG_INFO, "PcieIoTrapAddress: %0x\n", mPcieIoTrapAddress));
> +
> +  if (mPcieIoTrapAddress != 0) {
> +    //
> +    // Save PCH PCIE IoTrap address to re-config PCIE power management
> setting after resume from S3
> +    //
> +    Data32 = PciePmTrap;
> +    S3BootScriptSaveIoWrite (
> +      S3BootScriptWidthUint32,
> +      (UINTN) (mPcieIoTrapAddress),
> +      1,
> +      &Data32
> +      );
> +  } else {
> +    ASSERT (FALSE);
> +  }
> +}
> +
> +/**
> +  This is the callback function for PCI ENUMERATION COMPLETE.
> +**/
> +VOID
> +EFIAPI
> +PchOnPciEnumComplete (
> +  IN EFI_EVENT    Event,
> +  IN VOID         *Context
> +  )
> +{
> +  EFI_STATUS          Status;
> +  VOID                *ProtocolPointer;
> +  UINT64              ThermalPciBase;
> +
> +  ///
> +  /// Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
> +  /// if it is, we will skip it until real event is triggered
> +  ///
> +  Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid,
> NULL, (VOID **) &ProtocolPointer);
> +  if (EFI_SUCCESS != Status) {
> +    return;
> +  }
> +  gBS->CloseEvent (Event);
> +
> +  //
> +  // Enable Thermal MSE
> +  //
> +  ThermalPciBase = PCI_SEGMENT_LIB_ADDRESS (
> +                     DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +                     DEFAULT_PCI_BUS_NUMBER_PCH,
> +                     PCI_DEVICE_NUMBER_PCH_THERMAL,
> +                     PCI_FUNCTION_NUMBER_PCH_THERMAL,
> +                     0
> +                     );
> +  if (PciSegmentRead16 (ThermalPciBase + PCI_VENDOR_ID_OFFSET) !=
> 0xFFFF) {
> +    if (((PciSegmentRead32 (ThermalPciBase + R_THERMAL_CFG_MEM_TBAR)
> & B_THERMAL_CFG_MEM_TBAR_MASK) != 0) ||
> +        ((PciSegmentRead32 (ThermalPciBase +
> R_THERMAL_CFG_MEM_TBARH) != 0))) {
> +      PciSegmentOr8 (ThermalPciBase + PCI_COMMAND_OFFSET,
> EFI_PCI_COMMAND_MEMORY_SPACE);
> +    }
> +  }
> +
> +  ReconfigurePciePowerManagementForS3 ();
> +  ProcessSmiLocks ();
> +#ifndef FSP_WRAPPER_FLAG
> +  PchOnPciEnumCompleteCommon ();
> +#endif
> +  ConfigureSerialIoAtS3Resume ();
> +}
> +
> +/**
> +  Register callback functions for PCH DXE.
> +**/
> +VOID
> +PchRegisterNotifications (
> +  VOID
> +  )
> +{
> +  EFI_STATUS  Status;
> +  EFI_EVENT   LegacyBootEvent;
> +  EFI_EVENT   ExitBootServicesEvent;
> +  VOID        *Registration;
> +
> +  ///
> +  /// Create PCI Enumeration Completed callback for PCH
> +  ///
> +  EfiCreateProtocolNotifyEvent (
> +    &gEfiPciEnumerationCompleteProtocolGuid,
> +    TPL_CALLBACK,
> +    PchOnPciEnumComplete,
> +    NULL,
> +    &Registration
> +    );
> +
> +  //
> +  // Create events for PCH to do the task before ExitBootServices/LegacyBoot.
> +  // It is guaranteed that only one of two events below will be signalled
> +  //
> +  Status = gBS->CreateEvent (
> +                  EVT_SIGNAL_EXIT_BOOT_SERVICES,
> +                  TPL_CALLBACK,
> +                  PchOnExitBootServices,
> +                  NULL,
> +                  &ExitBootServicesEvent
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = EfiCreateEventLegacyBootEx (
> +             TPL_CALLBACK,
> +             PchOnBootToOs,
> +             NULL,
> +             &LegacyBootEvent
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +}
> +
> +/**
> +  Initialize the PCH device according to the PCH Policy HOB
> +  and install PCH info instance.
> +**/
> +VOID
> +InitializePchDevice (
> +  VOID
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "InitializePchDevice() Start\n"));
> +
> +  DEBUG ((DEBUG_INFO, "InitializePchDevice() End\n"));
> +}
> +/**
> +  <b>PchInit DXE Module Entry Point</b>\n
> +  - <b>Introduction</b>\n
> +      The PchInit module is a DXE driver that initializes the Intel Platform
> Controller Hub
> +      following the PCH BIOS specification and EDS requirements and
> recommendations. It consumes
> +      the PCH_POLICY_HOB SI_POLICY_HOB for expected configurations per
> policy.
> +      This is the standard EFI driver point that detects whether there is an
> supported PCH in
> +      the system and if so, initializes the chipset.
> +
> +  - <b>Details</b>\n
> +    This module is required for initializing the Intel Platform Controller Hub to
> +    follow the PCH BIOS specification and EDS.
> +    This includes some initialization sequences, enabling and disabling PCH
> devices,
> +    configuring clock gating, RST PCIe Storage Remapping, SATA controller,
> ASPM of PCIE devices. Right before end of DXE,
> +    it's responsible to lock down registers for security requirement.
> +
> +  - @pre
> +    - PCH PCR base address configured
> +    - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
> +      - This is to ensure that PCI MMIO and IO resource has been prepared and
> available for this driver to allocate.
> +
> +  - @result
> +    - Publishes the @link _PCH_INFO_PROTOCOL PCH_INFO_PROTOCOL
> @endlink
> +    - Publishes the @link _PCH_EMMC_TUNING_PROTOCOL
> PCH_EMMC_TUNING_PROTOCOL @endlink
> +
> +  - <b>References</b>\n
> +    - @link _PCH_POLICY PCH_POLICY_HOB @endlink.
> +    - @link _SI_POLICY_STRUCT SI_POLICY_HOB @endlink.
> +
> +  - <b>Integration Checklists</b>\n
> +    - Verify prerequisites are met. Porting Recommendations.
> +    - No modification of this module should be necessary
> +    - Any modification of this module should follow the PCH BIOS Specification
> and EDS
> +
> +  @param[in] ImageHandle          Handle for the image of this driver
> +  @param[in] SystemTable          Pointer to the EFI System Table
> +
> +  @retval EFI_SUCCESS             The function completed successfully
> +  @retval EFI_OUT_OF_RESOURCES    Do not have enough resources to
> initialize the driver
> +**/
> +EFI_STATUS
> +EFIAPI
> +PchInitEntryPointDxe (
> +  IN EFI_HANDLE         ImageHandle,
> +  IN EFI_SYSTEM_TABLE   *SystemTable
> +  )
> +{
> +  EFI_STATUS            Status;
> +
> +  DEBUG ((DEBUG_INFO, "PchInitEntryPointDxe() Start\n"));
> +
> +  mImageHandle = ImageHandle;
> +
> +  PchInitEntryPointCommon ();
> +
> +  InitializePchDevice ();
> +
> +  Status = PchAcpiInit (ImageHandle);
> +
> +  CreateSerialIoHandles ();
> +
> +  PchRegisterNotifications ();
> +
> +  DEBUG ((DEBUG_INFO, "PchInitEntryPointDxe() End\n"));
> +
> +  return Status;
> +}
> +
> +/**
> +  PCH initialization before ExitBootServices / LegacyBoot events
> +  Useful for operations which must happen later than at EndOfPost event
> +
> +  @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
> +PchOnBootToOs (
> +  IN EFI_EVENT    Event,
> +  IN VOID         *Context
> +  )
> +{
> +  ///
> +  /// Closed the event to avoid call twice
> +  ///
> +  if (Event != NULL) {
> +    gBS->CloseEvent (Event);
> +  }
> +
> +  ConfigureSerialIoAtBoot ();
> +
> +  return;
> +}
> +
> +/**
> +  PCH initialization on ExitBootService. This event is used if only
> ExitBootService is used
> +  and not in legacy boot
> +
> +  @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.
> +
> +  @retval None
> +**/
> +VOID
> +EFIAPI
> +PchOnExitBootServices (
> +  IN EFI_EVENT    Event,
> +  IN VOID         *Context
> +  )
> +{
> +  PchOnBootToOs (NULL, NULL);
> +
> +  return;
> +}
> +
> +/**
> +  PCH initialization before boot to OS
> +
> +  @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
> +PchOnReadyToBoot (
> +  IN EFI_EVENT    Event,
> +  IN VOID         *Context
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "Uefi PchOnReadyToBoot() Start\n"));
> +
> +  if (Event != NULL) {
> +    gBS->CloseEvent (Event);
> +  }
> +
> +  //
> +  // Trigger an Iotrap SMI to config PCIE power management setting after PCI
> enumrate is done
> +  //
> +  if (mPcieIoTrapAddress != 0) {
> +    IoWrite32 ((UINTN) mPcieIoTrapAddress, PciePmTrap);
> +  } else {
> +    ASSERT (FALSE);
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "Uefi PchOnReadyToBoot() End\n"));
> +}
> +
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitFsp.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitFsp.c
> new file mode 100644
> index 0000000000..15fe4628fb
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitFsp.c
> @@ -0,0 +1,85 @@
> +/** @file
> +  This is the FSP driver that initializes the Intel PCH.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/PeiServicesLib.h>
> +#include "PchInit.h"
> +
> +EFI_STATUS
> +EFIAPI
> +PchOnPciEnumCompleteFsp (
> +  IN  EFI_PEI_SERVICES            **PeiServices,
> +  IN  EFI_PEI_NOTIFY_DESCRIPTOR   *NotifyDescriptor,
> +  IN  VOID                        *Ppi
> +  );
> +
> +STATIC
> +EFI_PEI_NOTIFY_DESCRIPTOR  mPchOnPciEnumCompleteNotifyList[] = {
> +  {
> +    (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK  |
> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> +    &gEfiPciEnumerationCompleteProtocolGuid,
> +    PchOnPciEnumCompleteFsp
> +  }
> +};
> +
> +/**
> +  <b>FSP PchInit Module Entry Point for FSP</b>\n
> +
> +  @param[in] FileHandle      PEIM's file handle
> +  @param[in] PeiServices     An indirect pointer to the EFI_PEI_SERVICES
> table published by the PEI Foundation
> +
> +  @retval EFI_SUCCESS             The function completed successfully
> +  @retval EFI_OUT_OF_RESOURCES    Do not have enough resources to
> initialize the driver
> +**/
> +EFI_STATUS
> +EFIAPI
> +PchInitEntryPointFsp (
> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
> +  IN CONST EFI_PEI_SERVICES     **PeiServices
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  DEBUG ((DEBUG_INFO, "PchInitEntryPointFsp() Start\n"));
> +
> +  PchInitEntryPointCommon ();
> +
> +  Status = PeiServicesNotifyPpi (mPchOnPciEnumCompleteNotifyList);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  DEBUG ((DEBUG_INFO, "PchInitEntryPointFsp() End\n"));
> +
> +  return Status;
> +}
> +
> +/**
> +  Fsp PCH initialization on PCI enumeration complete
> +
> +  @param[in]  PeiServices       An indirect pointer to the EFI_PEI_SERVICES
> table published by the PEI Foundation
> +  @param[in]  NotifyDescriptor  Address of the notification descriptor data
> structure.
> +  @param[in]  Ppi               Address of the PPI that was installed.
> +
> +  @retval EFI_SUCCESS             The function completed successfully
> +  @retval EFI_OUT_OF_RESOURCES    Do not have enough resources to
> initialize the driver
> +**/
> +EFI_STATUS
> +EFIAPI
> +PchOnPciEnumCompleteFsp (
> +  IN  EFI_PEI_SERVICES            **PeiServices,
> +  IN  EFI_PEI_NOTIFY_DESCRIPTOR   *NotifyDescriptor,
> +  IN  VOID                        *Ppi
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "PchOnPciEnumCompleteFsp() Start\n"));
> +
> +  PchOnPciEnumCompleteCommon ();
> +
> +  DEBUG ((DEBUG_INFO, "PchOnPciEnumCompleteFsp() End\n"));
> +
> +  return EFI_SUCCESS;
> +}
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c
> new file mode 100644
> index 0000000000..6e30280fa7
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchSata.c
> @@ -0,0 +1,89 @@
> +/** @file
> +  Perform related functions for PCH Sata in DXE phase
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Library/S3BootScriptLib.h>
> +
> +#include "PchInit.h"
> +#include <Library/SataLib.h>
> +#include <Register/PchRegsSata.h>
> +
> +/**
> +  Perform the remaining configuration on PCH SATA to perform device
> detection,
> +  then set the SATA SPD and PxE corresponding, and set the Register Lock on
> PCH SATA
> +
> +  @retval None
> +**/
> +VOID
> +ConfigurePchSataOnEndOfDxe (
> +  VOID
> +  )
> +{
> +  UINT64        PciSataRegBase;
> +  UINT16        SataPortsEnabled;
> +  UINT32        DwordReg;
> +  UINTN         Index;
> +  UINT32        SataCtrlIndex;
> +
> +  for (SataCtrlIndex = 0; SataCtrlIndex < GetPchMaxSataControllerNum ();
> SataCtrlIndex++) {
> +    ///
> +    /// SATA PCS: Enable the port in any of below condition:
> +    /// i.)   Hot plug is enabled
> +    /// ii.)  A device is attached
> +    /// iii.) Test mode is enabled
> +    /// iv.)  Configured as eSATA port
> +    ///
> +    PciSataRegBase    = GetSataRegBase (SataCtrlIndex);
> +    SataPortsEnabled  = 0;
> +
> +    DwordReg = PciSegmentRead32 (PciSataRegBase + R_SATA_CFG_PCS);
> +    for (Index = 0; Index < GetPchMaxSataPortNum (SataCtrlIndex); Index++) {
> +      if ((mPchConfigHob->Sata[SataCtrlIndex].PortSettings[Index].HotPlug ==
> TRUE) ||
> +          (DwordReg & (B_SATA_CFG_PCS_P0P << Index)) ||
> +            (mPchConfigHob->Sata[SataCtrlIndex].TestMode == TRUE) ||
> +            (mPchConfigHob->Sata[SataCtrlIndex].PortSettings[Index].External
> == TRUE)) {
> +          SataPortsEnabled |=
> (mPchConfigHob->Sata[SataCtrlIndex].PortSettings[Index].Enable << Index);
> +      }
> +    }
> +
> +    ///
> +    /// Set MAP."Sata PortX Disable", SATA PCI offset 90h[23:16] to 1b if SATA
> Port 0/1/2/3/4/5/6/7 is disabled
> +    ///
> +    PciSegmentOr32 (PciSataRegBase + R_SATA_CFG_MAP,
> (~SataPortsEnabled << N_SATA_CFG_MAP_SPD));
> +    S3BootScriptSaveMemWrite (
> +      S3BootScriptWidthUint32,
> +      PcdGet64 (PcdPciExpressBaseAddress) + PciSataRegBase +
> R_SATA_CFG_MAP,
> +      1,
> +      (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) +
> PciSataRegBase + R_SATA_CFG_MAP)
> +      );
> +
> +    ///
> +    /// Program PCS "Port X Enabled", SATA PCI offset 94h[7:0] = Port 0~7
> Enabled bit as per SataPortsEnabled value.
> +    ///
> +    PciSegmentOr16 (PciSataRegBase + R_SATA_CFG_PCS, SataPortsEnabled);
> +    S3BootScriptSaveMemWrite (
> +      S3BootScriptWidthUint16,
> +      PcdGet64 (PcdPciExpressBaseAddress) + PciSataRegBase +
> R_SATA_CFG_PCS,
> +      1,
> +      (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) +
> PciSataRegBase + R_SATA_CFG_PCS)
> +      );
> +
> +    ///
> +    /// Step 14
> +    /// Program SATA PCI offset 9Ch [31] to 1b
> +    ///
> +    PciSegmentOr32 ((UINTN) (PciSataRegBase + R_SATA_CFG_SATAGC),
> BIT31);
> +    S3BootScriptSaveMemWrite (
> +      S3BootScriptWidthUint32,
> +      PcdGet64 (PcdPciExpressBaseAddress) + PciSataRegBase +
> R_SATA_CFG_SATAGC,
> +      1,
> +      (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) +
> PciSataRegBase + R_SATA_CFG_SATAGC)
> +      );
> +  }
> +}
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c
> new file mode 100644
> index 0000000000..d0f4b4fa56
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIo.c
> @@ -0,0 +1,57 @@
> +/** @file
> +  Initializes Serial IO Controllers.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include "PchInit.h"
> +#include <Library/PchSerialIoLib.h>
> +#include <IndustryStandard/Pci30.h>
> +#include <Register/PchRegsSerialIo.h>
> +
> +/**
> +  Puts all SerialIo controllers (except UARTs in debug mode) in D3
> +  Clears MemoryEnable for all PCI-mode controllers
> +**/
> +EFI_STATUS
> +ConfigureSerialIoAtBoot (
> +  VOID
> +  )
> +{
> +  PCH_SERIAL_IO_CONTROLLER Index;
> +  UINTN                    PciCfgBase;
> +
> +  for (Index = 0; Index < PchSerialIoIndexMax; Index++) {
> +    if (mPchConfigHob->SerialIo.DevMode[Index] == PchSerialIoDisabled) {
> +      if (IsSerialIoFunctionZero (Index)) {
> +        if (IsSerialIoDeviceEnabled (GetSerialIoDeviceNumber (Index),
> GetSerialIoFunctionNumber (Index))) {
> +          PciCfgBase = FindSerialIoBar (Index,1);
> +          MmioOr32 (PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS,
> B_SERIAL_IO_CFG_PME_CTRL_STS_PWR_ST);
> +        }
> +      }
> +      continue;
> +    }
> +    if ((Index >= PchSerialIoIndexUart0) &&
> +        (mPchConfigHob->SerialIo.EnableDebugUartAfterPost) &&
> +        (mPchConfigHob->SerialIo.DebugUartNumber == (UINT32) (Index -
> PchSerialIoIndexUart0))) {
> +      continue;
> +    }
> +    PciCfgBase = FindSerialIoBar (Index,1);
> +    MmioOr32 (PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS,
> B_SERIAL_IO_CFG_PME_CTRL_STS_PWR_ST);
> +    MmioRead32 (PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS);
> +    if (mPchConfigHob->SerialIo.DevMode[Index] == PchSerialIoPci) {
> +      MmioAnd32 (PciCfgBase + PCI_COMMAND_OFFSET,
> (UINT32)~(EFI_PCI_COMMAND_MEMORY_SPACE |
> EFI_PCI_COMMAND_BUS_MASTER) );
> +      if (mPchConfigHob->SerialIo.DebugUartNumber == (UINT32) (Index -
> PchSerialIoIndexUart0)) {
> +        continue;
> +      }
> +      MmioWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR0_LOW, 0);
> +      MmioWrite32 (PciCfgBase + R_SERIAL_IO_CFG_BAR0_HIGH, 0);
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c
> new file mode 100644
> index 0000000000..5563d82076
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchSerialIoDxe.c
> @@ -0,0 +1,156 @@
> +/** @file
> +  Initializes Serial IO Controllers.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/S3BootScriptLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/DxeServicesTableLib.h>
> +
> +#include "PchInit.h"
> +#include <Library/PchSerialIoLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <IndustryStandard/Pci30.h>
> +#include <Register/PchRegsSerialIo.h>
> +
> +typedef struct {
> +  ACPI_HID_DEVICE_PATH          RootPort;
> +  ACPI_EXTENDED_HID_DEVICE_PATH AcpiDev;
> +  CHAR8                         HidString[8];
> +  CHAR8                         UidString;
> +  CHAR8                         CidString;
> +  EFI_DEVICE_PATH_PROTOCOL      End;
> +} SERIALIO_DEVICE_PATH;
> +
> +#define gPciRootBridge {{ACPI_DEVICE_PATH, ACPI_DP,
> {(UINT8)(sizeof(ACPI_HID_DEVICE_PATH)), 0}}, EISA_PNP_ID (0x0A03), 0}
> +#define gAcpiDev
> {{ACPI_DEVICE_PATH,ACPI_EXTENDED_DP,{(UINT8)(sizeof(ACPI_EXTENDED_HI
> D_DEVICE_PATH)+SERIALIO_TOTAL_ID_LENGTH),0}},0,0,0}
> +#define gEndEntire
> {END_DEVICE_PATH_TYPE,END_ENTIRE_DEVICE_PATH_SUBTYPE,{END_DEVICE
> _PATH_LENGTH,0}}
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED SERIALIO_DEVICE_PATH gSerialIoPath
> = {
> +  gPciRootBridge,
> +  gAcpiDev,
> +  "\0\0\0\0\0\0\0",
> +  '\0',
> +  '\0',
> +  gEndEntire
> +};
> +
> +/**
> +Mark memory used by SerialIo devices in ACPI mode as allocated
> +
> +@retval EFI_SUCCESS             The function completed successfully
> +**/
> +EFI_STATUS
> +AllocateSerialIoMemory (
> +  VOID
> +  )
> +{
> +  PCH_SERIAL_IO_CONTROLLER i;
> +  UINT8                    BarNumber;
> +  UINTN                    Bar;
> +  EFI_STATUS               Status;
> +
> +  for (i=0; i<PchSerialIoIndexMax; i++) {
> +    if (mPchConfigHob->SerialIo.DevMode[i] == PchSerialIoHidden ||
> +        mPchConfigHob->SerialIo.DevMode[i] == PchSerialIoAcpi) {
> +      for (BarNumber = 0; BarNumber<=1; BarNumber++) {
> +        Bar = FindSerialIoBar (i,BarNumber);
> +        Status = gDS->AddMemorySpace (
> +                        EfiGcdMemoryTypeReserved,
> +                        Bar,
> +                        V_SERIAL_IO_CFG_BAR_SIZE,
> +                        0
> +                        );
> +        ASSERT_EFI_ERROR (Status);
> +        if (EFI_ERROR (Status)) {
> +          return Status;
> +        }
> +        Status = gDS->AllocateMemorySpace (
> +                        EfiGcdAllocateAddress,
> +                        EfiGcdMemoryTypeReserved,
> +                        N_SERIAL_IO_CFG_BAR_ALIGNMENT,
> +                        V_SERIAL_IO_CFG_BAR_SIZE,
> +                        &Bar,
> +                        mImageHandle,
> +                        NULL
> +                        );
> +        ASSERT_EFI_ERROR (Status);
> +        if (EFI_ERROR (Status)) {
> +          return Status;
> +        }
> +      }
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +VOID
> +CreateSerialIoHandles (
> +  VOID
> +  )
> +{
> +  EFI_HANDLE NewHandle;
> +  EFI_DEVICE_PATH_PROTOCOL *NewPath;
> +  UINT32 Controller;
> +
> +  for (Controller = 0; Controller < PchSerialIoIndexMax; Controller++) {
> +    if (mPchConfigHob->SerialIo.DevMode[Controller] == PchSerialIoAcpi) {
> +      NewHandle = NULL;
> +      CopyMem (gSerialIoPath.HidString, GetSerialIoAcpiHid (Controller),
> SERIALIO_HID_LENGTH);
> +      NewPath = DuplicateDevicePath
> ((EFI_DEVICE_PATH_PROTOCOL*)&gSerialIoPath);
> +      gBS->InstallMultipleProtocolInterfaces (
> +             &NewHandle,
> +             &gEfiDevicePathProtocolGuid,
> +             NewPath,
> +             NULL );
> +    }
> +  }
> +}
> +
> +/**
> +  Puts all SerialIo controllers (except UARTs in debug mode) in D3.
> +  Clears MemoryEnable for all PCI-mode controllers on S3 resume
> +**/
> +VOID
> +ConfigureSerialIoAtS3Resume (
> +  VOID
> +  )
> +{
> +  PCH_SERIAL_IO_CONTROLLER Index;
> +  UINTN                    PciCfgBase;
> +  UINT32                   Data32;
> +
> +  for (Index = 0; Index < PchSerialIoIndexMax; Index++) {
> +    if (mPchConfigHob->SerialIo.DevMode[Index] == PchSerialIoDisabled) {
> +      if (IsSerialIoFunctionZero (Index)) {
> +        if (IsSerialIoDeviceEnabled (GetSerialIoDeviceNumber (Index),
> GetSerialIoFunctionNumber (Index))) {
> +          PciCfgBase = FindSerialIoBar (Index,1);
> +          Data32 = MmioRead32 (PciCfgBase +
> R_SERIAL_IO_CFG_PME_CTRL_STS);
> +          Data32 |= B_SERIAL_IO_CFG_PME_CTRL_STS_PWR_ST;
> +          S3BootScriptSaveMemWrite (S3BootScriptWidthUint32, PciCfgBase +
> R_SERIAL_IO_CFG_PME_CTRL_STS, 1, &Data32);
> +        }
> +      }
> +      continue;
> +    }
> +    if ((Index >= PchSerialIoIndexUart0) &&
> +        (mPchConfigHob->SerialIo.EnableDebugUartAfterPost) &&
> +        (mPchConfigHob->SerialIo.DebugUartNumber == (UINT32) (Index -
> PchSerialIoIndexUart0))) {
> +      continue;
> +    }
> +    PciCfgBase = FindSerialIoBar (Index,1);
> +    Data32 = MmioRead32 (PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS);
> +    Data32 |= B_SERIAL_IO_CFG_PME_CTRL_STS_PWR_ST;
> +    S3BootScriptSaveMemWrite (S3BootScriptWidthUint32, PciCfgBase +
> R_SERIAL_IO_CFG_PME_CTRL_STS, 1, &Data32);
> +    if (mPchConfigHob->SerialIo.DevMode[Index] == PchSerialIoPci) {
> +      Data32 = MmioRead32 (PciCfgBase + PCI_COMMAND_OFFSET);
> +      Data32 &= (UINT32)~(EFI_PCI_COMMAND_MEMORY_SPACE |
> EFI_PCI_COMMAND_BUS_MASTER);
> +      S3BootScriptSaveMemWrite (S3BootScriptWidthUint32, PciCfgBase +
> PCI_COMMAND_OFFSET, 1, &Data32);
> +    }
> +  }
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c
> new file mode 100644
> index 0000000000..7fe1567c9f
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtect.c
> @@ -0,0 +1,156 @@
> +/** @file
> +  PCH BIOS Write Protect Driver.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "PchInitSmm.h"
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsLpc.h>
> +#include <Register/PchRegsSpi.h>
> +
> +//
> +// Global variables
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED PCH_TCO_SMI_DISPATCH_PROTOCOL
> *mPchTcoSmiDispatchProtocol;
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT64
> mSpiRegBase;
> +GLOBAL_REMOVE_IF_UNREFERENCED PCH_ESPI_SMI_DISPATCH_PROTOCOL
> *mEspiSmmDispatchProtocol;
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT64
> mLpcRegBase;
> +
> +/**
> +  This hardware SMI handler will be run every time the BIOS Write Enable bit
> is set.
> +
> +  @param[in] DispatchHandle       Not used
> +
> +**/
> +VOID
> +EFIAPI
> +PchSpiBiosWpCallback (
> +  IN  EFI_HANDLE                              DispatchHandle
> +  )
> +{
> +  //
> +  // Disable BIOSWE bit to protect BIOS
> +  //
> +  PciSegmentAnd8 ((UINTN) (mSpiRegBase + R_SPI_CFG_BC), (UINT8)
> ~B_SPI_CFG_BC_WPD);
> +}
> +
> +/**
> +  This hardware SMI handler will be run every time the BIOS Write Enable bit
> is set.
> +
> +  @param[in] DispatchHandle       Not used
> +
> +**/
> +VOID
> +EFIAPI
> +PchLpcBiosWpCallback (
> +  IN  EFI_HANDLE                              DispatchHandle
> +  )
> +{
> +  //
> +  // Disable BIOSWE bit to protect BIOS
> +  //
> +  PciSegmentAnd8 ((UINTN) (mLpcRegBase + R_LPC_CFG_BC), (UINT8)
> ~B_LPC_CFG_BC_WPD);
> +}
> +
> +/**
> +  Entry point for Pch Bios Write Protect driver.
> +
> +  @param[in] ImageHandle          Image handle of this driver.
> +  @param[in] SystemTable          Global system service table.
> +
> +  @retval EFI_SUCCESS             Initialization complete.
> +**/
> +EFI_STATUS
> +EFIAPI
> +InstallPchBiosWriteProtect (
> +  IN EFI_HANDLE            ImageHandle,
> +  IN EFI_SYSTEM_TABLE      *SystemTable
> +  )
> +{
> +  EFI_STATUS              Status;
> +  EFI_HANDLE              Handle;
> +
> +  DEBUG ((DEBUG_INFO, "InstallPchBiosWriteProtect()\n"));
> +
> +  if (mPchConfigHob->LockDown.BiosLock != TRUE) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  mSpiRegBase = PCI_SEGMENT_LIB_ADDRESS (
> +                  DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +                  DEFAULT_PCI_BUS_NUMBER_PCH,
> +                  PCI_DEVICE_NUMBER_PCH_SPI,
> +                  PCI_FUNCTION_NUMBER_PCH_SPI,
> +                  0
> +                  );
> +
> +  mLpcRegBase = PCI_SEGMENT_LIB_ADDRESS (
> +                   DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +                   DEFAULT_PCI_BUS_NUMBER_PCH,
> +                   PCI_DEVICE_NUMBER_PCH_LPC,
> +                   PCI_FUNCTION_NUMBER_PCH_LPC,
> +                   0
> +                   );
> +
> +  DEBUG ((DEBUG_INFO, "Installing BIOS Write Protect SMI handler\n"));
> +  //
> +  // Get the PCH TCO SMM dispatch protocol
> +  //
> +  mPchTcoSmiDispatchProtocol = NULL;
> +  Status = gSmst->SmmLocateProtocol (&gPchTcoSmiDispatchProtocolGuid,
> NULL, (VOID **) &mPchTcoSmiDispatchProtocol);
> +  ASSERT_EFI_ERROR (Status);
> +  //
> +  // Always register an SPI BiosWp callback function to handle TCO BIOSWR
> SMI
> +  // NOTE: No matter the BIOS resides behind SPI or not, it needs to handle the
> SPI BIOS WP SMI
> +  //       to avoid SMI deadloop on SPI WPD write.
> +  //
> +  Handle = NULL;
> +  Status = mPchTcoSmiDispatchProtocol->SpiBiosWpRegister (
> +                                         mPchTcoSmiDispatchProtocol,
> +                                         PchSpiBiosWpCallback,
> +                                         &Handle
> +                                         );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Always register an LPC/eSPI BiosWp callback function to handle TCO
> BIOSWR SMI
> +  // NOTE: No matter the BIOS resides behind LPC/eSPI or not, it needs to
> handle the BIOS WP SMI
> +  //       to avoid SMI deadloop on LPC/eSPI WPD write.
> +  //
> +  if (IsEspiEnabled ()) {
> +    //
> +    // Get the PCH ESPI SMM dispatch protocol
> +    //
> +    mEspiSmmDispatchProtocol = NULL;
> +    Status = gSmst->SmmLocateProtocol (&gPchEspiSmiDispatchProtocolGuid,
> NULL, (VOID **) &mEspiSmmDispatchProtocol);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    //
> +    // Register an ESpiBiosWp callback function to handle BIOSWR SMI
> +    //
> +    Handle = NULL;
> +    Status = mEspiSmmDispatchProtocol->BiosWrProtectRegister (
> +                                         mEspiSmmDispatchProtocol,
> +                                         PchLpcBiosWpCallback,
> +                                         &Handle
> +                                         );
> +    ASSERT_EFI_ERROR (Status);
> +  } else {
> +    //
> +    // Register an LPC BiosWp callback function to handle TCO BIOSWR SMI
> +    //
> +    Handle = NULL;
> +    Status = mPchTcoSmiDispatchProtocol->LpcBiosWpRegister (
> +                                           mPchTcoSmiDispatchProtocol,
> +                                           PchLpcBiosWpCallback,
> +                                           &Handle
> +                                           );
> +    ASSERT_EFI_ERROR (Status);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c
> new file mode 100644
> index 0000000000..e9f4c91ed4
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.c
> @@ -0,0 +1,179 @@
> +/** @file
> +  PCH Init Smm module for PCH specific SMI handlers.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "PchInitSmm.h"
> +#include <Register/PchRegs.h>
> +#include <Register/RegsUsb.h>
> +#include <Register/PchRegsSmbus.h>
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED
> EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL        *mPchIoTrap;
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_SX_DISPATCH2_PROTOCOL
> *mSxDispatch;
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED PCH_NVS_AREA
> *mPchNvsArea;
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT16
> mAcpiBaseAddr;
> +
> +//
> +// NOTE: The module variables of policy here are only valid in post time, but
> not runtime time.
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED PCH_CONFIG_HOB
> *mPchConfigHob;
> +GLOBAL_REMOVE_IF_UNREFERENCED SI_CONFIG_HOB_DATA
> *mSiConfigHobData;
> +
> +//
> +// The reserved MMIO range to be used in Sx handler
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS
> mResvMmioBaseAddr;
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN
> mResvMmioSize;
> +
> +/**
> +  SMBUS Sx entry SMI handler.
> +**/
> +VOID
> +SmbusSxCallback (
> +  VOID
> +  )
> +{
> +  UINT64                      SmbusRegBase;
> +  UINT16                      SmbusIoBase;
> +
> +  SmbusRegBase = PCI_SEGMENT_LIB_ADDRESS (
> +                   DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +                   DEFAULT_PCI_BUS_NUMBER_PCH,
> +                   PCI_DEVICE_NUMBER_PCH_SMBUS,
> +                   PCI_FUNCTION_NUMBER_PCH_SMBUS,
> +                   0
> +                   );
> +
> +  if (PciSegmentRead32 (SmbusRegBase) == 0xFFFFFFFF) {
> +    return;
> +  }
> +
> +  SmbusIoBase = PciSegmentRead16 (SmbusRegBase + R_SMBUS_CFG_BASE)
> & B_SMBUS_CFG_BASE_BAR;
> +  if (SmbusIoBase == 0) {
> +    return;
> +  }
> +
> +  PciSegmentOr8 (SmbusRegBase + PCI_COMMAND_OFFSET,
> EFI_PCI_COMMAND_IO_SPACE);
> +  //
> +  // Clear SMBUS status and SMB_WAK_STS of GPE0
> +  //
> +  IoWrite8 (SmbusIoBase + R_SMBUS_IO_HSTS,
> B_SMBUS_IO_SMBALERT_STS);
> +  IoWrite32 (mAcpiBaseAddr + R_ACPI_IO_GPE0_STS_127_96,
> B_ACPI_IO_GPE0_STS_127_96_SMB_WAK);
> +}
> +
> +/**
> +  Allocates reserved MMIO for Sx SMI handler use.
> +**/
> +VOID
> +AllocateReservedMmio (
> +  VOID
> +  )
> +{
> +  mResvMmioBaseAddr = PcdGet32 (PcdSiliconInitTempMemBaseAddr);
> +  mResvMmioSize     = PcdGet32 (PcdSiliconInitTempMemSize);
> +  DEBUG ((DEBUG_INFO, "mResvMmioBaseAddr %x, mResvMmioSize %x\n",
> mResvMmioBaseAddr, mResvMmioSize));
> +}
> +
> +/**
> +  Initializes the PCH SMM handler for for PCIE hot plug support
> +  <b>PchInit SMM Module Entry Point</b>\n
> +  - <b>Introduction</b>\n
> +      The PchInitSmm module is a SMM driver that initializes the Intel Platform
> Controller Hub
> +      SMM requirements and services. It consumes the PCH_POLICY_HOB and
> SI_POLICY_HOB for expected
> +      configurations per policy.
> +
> +  - <b>Details</b>\n
> +    This module provides SMI handlers to services PCIE HotPlug SMI,
> LinkActive SMI, and LinkEq SMI.
> +    And also provides port 0x61 emulation support, registers BIOS WP handler
> to process BIOSWP status,
> +    and registers SPI Async SMI handler to handler SPI Async SMI.
> +    This module also registers Sx SMI callback function to detail with GPIO Sx
> Isolation and LAN requirement.
> +
> +  - @pre
> +    - PCH PCR base address configured
> +    - EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
> +      - This is to ensure that PCI MMIO and IO resource has been prepared and
> available for this driver to allocate.
> +    - EFI_SMM_BASE2_PROTOCOL
> +    - EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL
> +    - EFI_SMM_SX_DISPATCH2_PROTOCOL
> +    - EFI_SMM_CPU_PROTOCOL
> +    - @link _PCH_SMM_IO_TRAP_CONTROL_PROTOCOL
> PCH_SMM_IO_TRAP_CONTROL_PROTOCOL @endlink
> +    - @link _PCH_SMI_DISPATCH_PROTOCOL PCH_SMI_DISPATCH_PROTOCOL
> @endlink
> +    - @link _PCH_PCIE_SMI_DISPATCH_PROTOCOL
> PCH_PCIE_SMI_DISPATCH_PROTOCOL @endlink
> +    - @link _PCH_TCO_SMI_DISPATCH_PROTOCOL
> PCH_TCO_SMI_DISPATCH_PROTOCOL @endlink
> +    - @link _PCH_ESPI_SMI_DISPATCH_PROTOCOL
> PCH_ESPI_SMI_DISPATCH_PROTOCOL @endlink
> +
> +  - <b>References</b>\n
> +    - @link _PCH_POLICY PCH_POLICY_HOB @endlink.
> +    - @link _SI_POLICY_STRUCT SI_POLICY_HOB @endlink.
> +
> +  - <b>Integration Checklists</b>\n
> +    - Verify prerequisites are met. Porting Recommendations.
> +    - No modification of this module should be necessary
> +    - Any modification of this module should follow the PCH BIOS Specification
> and EDS
> +
> +  @param[in] ImageHandle - Handle for the image of this driver
> +  @param[in] SystemTable - Pointer to the EFI System Table
> +
> +  @retval EFI_SUCCESS    - PCH SMM handler was installed
> +**/
> +EFI_STATUS
> +EFIAPI
> +PchInitSmmEntryPoint (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                                Status;
> +  PCH_NVS_AREA_PROTOCOL                     *PchNvsAreaProtocol;
> +  EFI_PEI_HOB_POINTERS                      HobPtr;
> +
> +  DEBUG ((DEBUG_INFO, "PchInitSmmEntryPoint()\n"));
> +
> +  Status = gSmst->SmmLocateProtocol (
> +                    &gEfiSmmIoTrapDispatch2ProtocolGuid,
> +                    NULL,
> +                    (VOID **) &mPchIoTrap
> +                    );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gSmst->SmmLocateProtocol (
> +                    &gEfiSmmSxDispatch2ProtocolGuid,
> +                    NULL,
> +                    (VOID**) &mSxDispatch
> +                    );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->LocateProtocol (&gPchNvsAreaProtocolGuid, NULL, (VOID **)
> &PchNvsAreaProtocol);
> +  ASSERT_EFI_ERROR (Status);
> +  mPchNvsArea = PchNvsAreaProtocol->Area;
> +
> +  //
> +  // Get PCH Data HOB.
> +  //
> +  HobPtr.Guid   = GetFirstGuidHob (&gPchConfigHobGuid);
> +  ASSERT (HobPtr.Guid != NULL);
> +  mPchConfigHob = (PCH_CONFIG_HOB *) GET_GUID_HOB_DATA
> (HobPtr.Guid);
> +
> +  HobPtr.Guid   = GetFirstGuidHob (&gSiConfigHobGuid);
> +  ASSERT (HobPtr.Guid != NULL);
> +  mSiConfigHobData = (SI_CONFIG_HOB_DATA *) GET_GUID_HOB_DATA
> (HobPtr.Guid);
> +
> +  mAcpiBaseAddr = PmcGetAcpiBase ();
> +
> +  AllocateReservedMmio ();
> +
> +  Status = InitializePchPcieSmm (ImageHandle, SystemTable);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = InstallPchBiosWriteProtect (ImageHandle, SystemTable);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = InstallPchSpiAsyncSmiHandler ();
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return EFI_SUCCESS;
> +}
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchLanSxSmm.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchLanSxSmm.c
> new file mode 100644
> index 0000000000..4a2d1f9cea
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchLanSxSmm.c
> @@ -0,0 +1,298 @@
> +/** @file
> +  PCH LAN Sx handler implementation.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/TimerLib.h>
> +#include "PchInitSmm.h"
> +#include <Private/Library/PmcPrivateLib.h>
> +#include <Library/GbeMdiLib.h>
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsLan.h>
> +
> +/**
> +  Checks if Lan is Enabled or Disabled
> +
> +  @retval  BOOLEAN    TRUE if device is enabled, FALSE otherwise.
> +**/
> +BOOLEAN
> +IsGbeEnabled (
> +  VOID
> +  )
> +{
> +  UINT64  GbePciBase;
> +
> +  GbePciBase = PCI_SEGMENT_LIB_ADDRESS (
> +                 DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +                 DEFAULT_PCI_BUS_NUMBER_PCH,
> +                 PCI_DEVICE_NUMBER_PCH_LAN,
> +                 PCI_FUNCTION_NUMBER_PCH_LAN,
> +                 0
> +                 );
> +
> +  if (PciSegmentRead32 (GbePciBase) != 0xFFFFFFFF) {
> +    return TRUE;
> +  }
> +
> +  return FALSE;
> +}
> +
> +
> +/**
> +  Configure WOL during Sx entry.
> +
> +  @param [in]  GbeBar   GbE MMIO space
> +**/
> +VOID
> +GbeWolWorkaround (
> +  IN      UINT32  GbeBar
> +  )
> +{
> +  UINT32      RAL0;
> +  UINT32      RAH0;
> +  UINT16      WUC;
> +  EFI_STATUS  Status;
> +  UINT16      Data16;
> +
> +  //
> +  // 1. Set page to 769 Port Control Registers
> +  // 2. Wait 4 mSec
> +  //
> +  Status = GbeMdiSetPage (GbeBar,
> PHY_MDI_PAGE_769_PORT_CONTROL_REGISTERS);
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 3. Set registry to 17 Port General Configuration
> +  // 4. Copy all settings from Port General Configuration
> +  //
> +  Status = GbeMdiRead (GbeBar, B_PHY_MDI_PHY_ADDRESS_01,
> MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_17_PGC), &Data16);
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 5. Modify BIT 4 and BIT 2 to disable host wake up and set MACPD
> +  //
> +  Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01,
> MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_17_PGC), (Data16 |
> B_PHY_MDI_PAGE_769_REGISETER_17_PGC_MACPD_ENABLE) &
> (~B_PHY_MDI_PAGE_769_REGISETER_17_PGC_HOST_WAKE_UP));
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 6. Read Receive Address Low and Receive Address High from MMIO
> +  //
> +  RAL0 = MmioRead32 (GbeBar + R_LAN_MEM_CSR_RAL);
> +  RAH0 = MmioRead32 (GbeBar + R_LAN_MEM_CSR_RAH);
> +
> +  //
> +  // 7. Set page to 800 Wake Up Registers
> +  // 8. Wait 4 mSec
> +  //
> +  Status = GbeMdiSetPage (GbeBar,
> PHY_MDI_PAGE_800_WAKE_UP_REGISTERS);
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 9. Set registry to 16 Receive Address Low 1/2
> +  //
> +  Status = GbeMdiSetRegister (GbeBar,
> R_PHY_MDI_PAGE_800_REGISETER_16_RAL0);
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 10. Program first 16 bits [0:15] out of 48 in Receive Address Low 1/2
> +  //
> +  Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01,
> R_PHY_MDI_PHY_REG_DATA_READ_WRITE, (RAL0 & 0xFFFF));
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 11. Set registry to 17 Receive Address Low 2/2
> +  //
> +  Status = GbeMdiSetRegister (GbeBar,
> R_PHY_MDI_PAGE_800_REGISETER_17_RAL1);
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 12. Program second 16 bits [16:31] out of 48 in Receive Address Low 2/2
> +  //
> +  Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01,
> R_PHY_MDI_PHY_REG_DATA_READ_WRITE, (RAL0 >> 16));
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 13. Set registry to 18 Receive Address High 1/2
> +  //
> +  Status = GbeMdiSetRegister (GbeBar,
> R_PHY_MDI_PAGE_800_REGISETER_18_RAH0);
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 14. Program last 16 bits [32:47] out of 48
> +  //
> +  Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01,
> R_PHY_MDI_PHY_REG_DATA_READ_WRITE, (RAH0 &
> B_LAN_MEM_CSR_RAH_RAH));
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 15. Set registry to 19 Receive Address High 2/2
> +  //
> +  Status = GbeMdiSetRegister (GbeBar,
> R_PHY_MDI_PAGE_800_REGISETER_19_RAH1);
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 16. Set Address Valid
> +  //
> +  Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01,
> R_PHY_MDI_PHY_REG_DATA_READ_WRITE,
> B_PHY_MDI_PAGE_800_REGISETER_19_RAH1_ADDRESS_VALID);
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 17. Set Wake Up Control Register 1
> +  //
> +  Status = GbeMdiSetRegister (GbeBar,
> R_PHY_MDI_PAGE_800_REGISETER_1_WUC);
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 18. Copy WakeUp Control from MAC MMIO
> +  //
> +  WUC = (UINT16) MmioRead32 (GbeBar + R_LAN_MEM_CSR_WUC);
> +
> +  //
> +  // 19. Store WakeUp Contorl into LCD
> +  // Modify APME bit to enable APM wake up
> +  //
> +  Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01,
> R_PHY_MDI_PHY_REG_DATA_READ_WRITE, (WUC & 0xFFFF));
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 20. Set page to 803 Host Wol Packet
> +  // 21. Wait 4 mSec
> +  //
> +  Status = GbeMdiSetPage (GbeBar,
> PHY_MDI_PAGE_803_HOST_WOL_PACKET);
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 22. Set registry to 66 Host WoL Packet Clear
> +  //
> +  Status = GbeMdiSetRegister (GbeBar,
> R_PHY_MDI_PAGE_803_REGISETER_66_HWPC);
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 23. Clear WOL Packet
> +  //
> +  Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01,
> R_PHY_MDI_PHY_REG_DATA_READ_WRITE, 0);
> +  if (EFI_ERROR (Status)) return;
> +  //
> +  // 24. Set page to 769 Port Control Registers
> +  // 25. Wait 4 mSec
> +  //
> +  Status = GbeMdiSetPage (GbeBar,
> PHY_MDI_PAGE_769_PORT_CONTROL_REGISTERS);
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 26. Set registry to 17 Port General Configuration
> +  //
> +  Status = GbeMdiSetRegister (GbeBar,
> R_PHY_MDI_PAGE_769_REGISETER_17_PGC);
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 27. Copy all settings from Port General Configuration
> +  //
> +  Status = GbeMdiRead (GbeBar, B_PHY_MDI_PHY_ADDRESS_01,
> MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_17_PGC), &Data16);
> +  if (EFI_ERROR (Status)) return;
> +
> +  //
> +  // 28. Modify BIT 4 and BIT 2 to enable host wake up and clear MACPD
> +  //
> +  Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01,
> MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_17_PGC), (Data16 |
> B_PHY_MDI_PAGE_769_REGISETER_17_PGC_HOST_WAKE_UP) &
> (~B_PHY_MDI_PAGE_769_REGISETER_17_PGC_MACPD_ENABLE));
> +  if (EFI_ERROR (Status)) return;
> +}
> +
> +/**
> +  Additional Internal GbE Controller special cases WOL Support.
> +
> +  System BIOS is required perform additional steps upon S0 to S3,4,5
> transition
> +  when ME is off and GbE device in D0. This is needed to enable LAN wake
> +  in particular when platform is shut-down from EFI.
> +**/
> +VOID
> +GbeSxWorkaround (
> +  VOID
> +  )
> +{
> +  UINT64      LanRegBase;
> +  UINT32      GbeBar;
> +  EFI_STATUS  Status;
> +
> +  LanRegBase = PCI_SEGMENT_LIB_ADDRESS (
> +                 DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +                 DEFAULT_PCI_BUS_NUMBER_PCH,
> +                 PCI_DEVICE_NUMBER_PCH_LAN,
> +                 PCI_FUNCTION_NUMBER_PCH_LAN,
> +                 0
> +                 );
> +
> +  if (PciSegmentRead16 (LanRegBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
> +    return;
> +  }
> +
> +  //
> +  // Check if GbE device is in D0
> +  //
> +  if ((PciSegmentRead16 (LanRegBase + R_LAN_CFG_PMCS) &
> B_LAN_CFG_PMCS_PS) != V_LAN_CFG_PMCS_PS0) {
> +    return;
> +  }
> +
> +  ASSERT (mResvMmioSize >= (1 << N_LAN_CFG_MBARA_ALIGN));
> +  GbeBar = (UINT32) mResvMmioBaseAddr;
> +  if (GbeBar == 0) {
> +    ASSERT (FALSE);
> +    return;
> +  }
> +
> +  //
> +  // Enable MMIO decode using reserved range.
> +  //
> +  PciSegmentAnd16 (LanRegBase + PCI_COMMAND_OFFSET, (UINT16)
> ~EFI_PCI_COMMAND_MEMORY_SPACE);
> +  PciSegmentWrite32 (LanRegBase + R_LAN_CFG_MBARA, GbeBar);
> +  PciSegmentOr16 (LanRegBase + PCI_COMMAND_OFFSET,
> EFI_PCI_COMMAND_MEMORY_SPACE);
> +
> +  //
> +  // If MBARA offset 5800h [0] = 1b then proceed with the w/a
> +  //
> +  if (MmioRead32 (GbeBar + R_LAN_MEM_CSR_WUC) &
> B_LAN_MEM_CSR_WUC_APME) {
> +    Status = GbeMdiAcquireMdio (GbeBar);
> +    ASSERT_EFI_ERROR (Status);
> +    if (!EFI_ERROR (Status)) {
> +      GbeWolWorkaround (GbeBar);
> +      GbeMdiReleaseMdio (GbeBar);
> +    }
> +  }
> +
> +  //
> +  // Disable MMIO decode.
> +  //
> +  PciSegmentAnd16 (LanRegBase + PCI_COMMAND_OFFSET, (UINT16)
> ~EFI_PCI_COMMAND_MEMORY_SPACE);
> +  PciSegmentWrite32 (LanRegBase + R_LAN_CFG_MBARA, 0);
> +}
> +
> +/**
> +  Enable platform wake from LAN when in DeepSx if platform supports it.
> +  Called upon Sx entry.
> +**/
> +VOID
> +GbeConfigureDeepSxWake (
> +  VOID
> +  )
> +{
> +  if (PmcIsLanDeepSxWakeEnabled ()) {
> +    IoOr32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_GPE0_EN_127_96),
> (UINT32) B_ACPI_IO_GPE0_EN_127_96_LAN_WAKE);
> +  }
> +}
> +
> +/**
> +  GbE Sx entry handler
> +**/
> +VOID
> +PchLanSxCallback (
> +  VOID
> +  )
> +{
> +  if (IsGbeEnabled ()) {
> +    GbeSxWorkaround ();
> +    GbeConfigureDeepSxWake ();
> +
> +  }
> +}
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c
> new file mode 100644
> index 0000000000..eac2e1c3ec
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchPcieSmm.c
> @@ -0,0 +1,436 @@
> +/** @file
> +  PCH Pcie SMM Driver Entry
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "PchInitSmm.h"
> +#include <PcieRegs.h>
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsPcie.h>
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED PCH_PCIE_DEVICE_OVERRIDE
> *mDevAspmOverride;
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT32
> mNumOfDevAspmOverride;
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT8
> mPchBusNumber;
> +//
> +// @note:
> +// These temp bus numbers cannot be used in runtime (hot-plug).
> +// These can be used only during boot.
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT8
> mTempRootPortBusNumMin;
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT8
> mTempRootPortBusNumMax;
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED PCH_PCIE_ROOT_PORT_CONFIG
> mPcieRootPortConfig[PCH_MAX_PCIE_ROOT_PORTS];
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN
> mPciePmTrapExecuted = FALSE;
> +
> +extern EFI_GUID gPchDeviceTableHobGuid;
> +
> +/**
> +  Program Common Clock and ASPM of Downstream Devices
> +
> +  @param[in] PortIndex                  Pcie Root Port Number
> +  @param[in] RpDevice                   Pcie Root Pci Device Number
> +  @param[in] RpFunction                 Pcie Root Pci Function Number
> +**/
> +STATIC
> +VOID
> +PchPcieSmi (
> +  IN  UINT8                             PortIndex,
> +  IN  UINT8                             RpDevice,
> +  IN  UINT8                             RpFunction
> +  )
> +{
> +  UINT8                 SecBus;
> +  UINT8                 SubBus;
> +  UINT64                RpBase;
> +  UINT64                EpBase;
> +  UINT8                 EpPcieCapPtr;
> +  UINT8                 EpMaxSpeed;
> +  BOOLEAN               DownstreamDevicePresent;
> +  UINT32                Timeout;
> +
> +  RpBase   = PCI_SEGMENT_LIB_ADDRESS (
> +               DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +               mPchBusNumber,
> +               (UINT32) RpDevice,
> +               (UINT32) RpFunction,
> +               0
> +               );
> +
> +  if (PciSegmentRead16 (RpBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
> +    return;
> +  }
> +  //
> +  // Check presence detect state. Here the endpoint must be detected using
> PDS rather than
> +  // the usual LinkActive check, because PDS changes immediately and LA
> takes a few milliseconds to stabilize
> +  //
> +  DownstreamDevicePresent = !!(PciSegmentRead16 (RpBase +
> R_PCH_PCIE_CFG_SLSTS) & B_PCIE_SLSTS_PDS);
> +
> +  if (DownstreamDevicePresent) {
> +    ///
> +    /// Make sure the link is active before trying to talk to device behind it
> +    /// Wait up to 100ms, according to PCIE spec chapter 6.7.3.3
> +    ///
> +    Timeout = 100 * 1000;
> +    while ((PciSegmentRead16 (RpBase + R_PCH_PCIE_CFG_LSTS) &
> B_PCIE_LSTS_LA) == 0 ) {
> +      MicroSecondDelay (10);
> +      Timeout-=10;
> +      if (Timeout == 0) {
> +        return;
> +      }
> +    }
> +    SecBus  = PciSegmentRead8 (RpBase +
> PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
> +    SubBus  = PciSegmentRead8 (RpBase +
> PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
> +    ASSERT (SecBus != 0 && SubBus != 0);
> +    RootportDownstreamConfiguration (
> +      DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +      DEFAULT_PCI_BUS_NUMBER_PCH,
> +      RpDevice,
> +      RpFunction,
> +      mTempRootPortBusNumMin,
> +      mTempRootPortBusNumMax
> +      );
> +    RootportDownstreamPmConfiguration (
> +      DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +      DEFAULT_PCI_BUS_NUMBER_PCH,
> +      RpDevice,
> +      RpFunction,
> +      mTempRootPortBusNumMin,
> +      mTempRootPortBusNumMax,
> +      &mPcieRootPortConfig[PortIndex],
> +      mNumOfDevAspmOverride,
> +      mDevAspmOverride
> +    );
> +    //
> +    // Perform Equalization
> +    //
> +    EpBase = PCI_SEGMENT_LIB_ADDRESS
> (DEFAULT_PCI_SEGMENT_NUMBER_PCH, SecBus, 0, 0, 0);
> +    EpPcieCapPtr = PcieFindCapId (DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> SecBus, 0, 0, EFI_PCI_CAPABILITY_ID_PCIEXP);
> +    EpMaxSpeed = PciSegmentRead8 (EpBase + EpPcieCapPtr +
> R_PCIE_LCAP_OFFSET) & B_PCIE_LCAP_MLS;
> +    if (EpMaxSpeed >= 3) {
> +      PciSegmentOr32 (RpBase + R_PCH_PCIE_CFG_EX_LCTL3,
> B_PCIE_EX_LCTL3_PE);
> +      PciSegmentOr32 (RpBase + R_PCH_PCIE_CFG_LCTL, B_PCIE_LCTL_RL);
> +    }
> +  }
> +}
> +
> +/**
> +  PCIE Hotplug SMI call back function for each Root port
> +
> +  @param[in] DispatchHandle             Handle of this dispatch function
> +  @param[in] RpContext                  Rootport context, which contains
> RootPort Index,
> +                                        and RootPort PCI BDF.
> +**/
> +VOID
> +EFIAPI
> +PchPcieSmiRpHandlerFunction (
> +  IN  EFI_HANDLE                        DispatchHandle,
> +  IN  PCH_PCIE_SMI_RP_CONTEXT           *RpContext
> +  )
> +{
> +  PchPcieSmi (RpContext->RpIndex, RpContext->DevNum,
> RpContext->FuncNum);
> +}
> +
> +/**
> +  PCIE Link Active State Change Hotplug SMI call back function for all Root
> ports
> +
> +  @param[in] DispatchHandle             Handle of this dispatch function
> +  @param[in] RpContext                  Rootport context, which contains
> RootPort Index,
> +                                        and RootPort PCI BDF.
> +**/
> +VOID
> +EFIAPI
> +PchPcieLinkActiveStateChange (
> +  IN  EFI_HANDLE                        DispatchHandle,
> +  IN  PCH_PCIE_SMI_RP_CONTEXT           *RpContext
> +  )
> +{
> +  return;
> +}
> +
> +/**
> +  PCIE Link Equalization Request SMI call back function for all Root ports
> +
> +  @param[in] DispatchHandle             Handle of this dispatch function
> +  @param[in] RpContext                  Rootport context, which contains
> RootPort Index,
> +                                        and RootPort PCI BDF.
> +**/
> +VOID
> +EFIAPI
> +PchPcieLinkEqHandlerFunction (
> +  IN  EFI_HANDLE                        DispatchHandle,
> +  IN  PCH_PCIE_SMI_RP_CONTEXT           *RpContext
> +  )
> +{
> +  ///
> +  /// From PCI Express specification, the PCIe device can request for Link
> Equalization. When the
> +  /// Link Equalization is requested by the device, an SMI will be generated
> by PCIe RP when
> +  /// enabled and the SMI subroutine would invoke the Software
> Preset/Coefficient Search
> +  /// software to re-equalize the link.
> +  ///
> +
> +  return;
> +
> +}
> +
> +/**
> +  An IoTrap callback to config PCIE power management settings
> +**/
> +VOID
> +PchPciePmIoTrapSmiCallback (
> +  VOID
> +  )
> +{
> +  UINT32                                    PortIndex;
> +  UINT64                                    RpBase;
> +  UINT8                                     MaxPciePortNum;
> +  UINTN                                     RpDevice;
> +  UINTN                                     RpFunction;
> +
> +  MaxPciePortNum                   = GetPchMaxPciePortNum ();
> +
> +  for (PortIndex = 0; PortIndex < MaxPciePortNum; PortIndex++) {
> +    GetPchPcieRpDevFun (PortIndex, &RpDevice, &RpFunction);
> +    RpBase = PCI_SEGMENT_LIB_ADDRESS
> (DEFAULT_PCI_SEGMENT_NUMBER_PCH, DEFAULT_PCI_BUS_NUMBER_PCH,
> (UINT32) RpDevice, (UINT32) RpFunction, 0);
> +
> +    if (PciSegmentRead16 (RpBase) != 0xFFFF) {
> +      RootportDownstreamPmConfiguration (
> +        DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +        DEFAULT_PCI_BUS_NUMBER_PCH,
> +        (UINT8)RpDevice,
> +        (UINT8)RpFunction,
> +        mTempRootPortBusNumMin,
> +        mTempRootPortBusNumMax,
> +        &mPcieRootPortConfig[PortIndex],
> +        mNumOfDevAspmOverride,
> +        mDevAspmOverride
> +      );
> +
> +    }
> +  }
> +}
> +
> +/**
> +  An IoTrap callback to config PCIE power management settings
> +
> +  @param[in] DispatchHandle  - The handle of this callback, obtained when
> registering
> +  @param[in] DispatchContext - Pointer to the
> EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT
> +
> +**/
> +VOID
> +EFIAPI
> +PchPcieIoTrapSmiCallback (
> +  IN  EFI_HANDLE                            DispatchHandle,
> +  IN  EFI_SMM_IO_TRAP_CONTEXT                *CallbackContext,
> +  IN OUT VOID                               *CommBuffer,
> +  IN OUT UINTN                              *CommBufferSize
> +  )
> +{
> +  if (CallbackContext->WriteData == PciePmTrap) {
> +    if (mPciePmTrapExecuted == FALSE) {
> +      PchPciePmIoTrapSmiCallback ();
> +      mPciePmTrapExecuted = TRUE;
> +    }
> +  } else {
> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
> +  }
> +}
> +
> +/**
> +  This function clear the Io trap executed flag before enter S3
> +
> +  @param[in] Handle    Handle of the callback
> +  @param[in] Context   The dispatch context
> +
> +  @retval EFI_SUCCESS  PCH register saved
> +**/
> +EFI_STATUS
> +EFIAPI
> +PchPcieS3EntryCallBack (
> +  IN  EFI_HANDLE                        Handle,
> +  IN CONST VOID                    *Context OPTIONAL,
> +  IN OUT VOID                      *CommBuffer OPTIONAL,
> +  IN OUT UINTN                     *CommBufferSize OPTIONAL
> +  )
> +{
> +  mPciePmTrapExecuted = FALSE;
> +  return EFI_SUCCESS;
> +}
> +/**
> +  Register PCIE Hotplug SMI dispatch function to handle Hotplug enabling
> +
> +  @param[in] ImageHandle          The image handle of this module
> +  @param[in] SystemTable          The EFI System Table
> +
> +  @retval EFI_SUCCESS             The function completes successfully
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitializePchPcieSmm (
> +  IN      EFI_HANDLE            ImageHandle,
> +  IN      EFI_SYSTEM_TABLE      *SystemTable
> +  )
> +{
> +  EFI_STATUS                            Status;
> +  UINT8                                 PortIndex;
> +  UINT8                                 Data8;
> +  UINT32                                Data32Or;
> +  UINT32                                Data32And;
> +  UINT64                                RpBase;
> +  UINTN                                 RpDevice;
> +  UINTN                                 RpFunction;
> +  EFI_HANDLE                            PcieHandle;
> +  PCH_PCIE_SMI_DISPATCH_PROTOCOL        *PchPcieSmiDispatchProtocol;
> +  EFI_HOB_GUID_TYPE*                    Hob;
> +  UINT32                                DevTableSize;
> +  EFI_HANDLE                            PchIoTrapHandle;
> +  EFI_SMM_IO_TRAP_REGISTER_CONTEXT      PchIoTrapContext;
> +  EFI_SMM_SX_REGISTER_CONTEXT           SxDispatchContext;
> +  PCH_PCIE_IOTRAP_PROTOCOL              *PchPcieIoTrapProtocol;
> +  EFI_HANDLE                            SxDispatchHandle;
> +  UINT8                                 MaxPciePortNum;
> +
> +  DEBUG ((DEBUG_INFO, "InitializePchPcieSmm () Start\n"));
> +
> +  MaxPciePortNum    = GetPchMaxPciePortNum ();
> +
> +  //
> +  // Locate Pch Pcie Smi Dispatch Protocol
> +  //
> +  Status = gSmst->SmmLocateProtocol (&gPchPcieSmiDispatchProtocolGuid,
> NULL, (VOID**)&PchPcieSmiDispatchProtocol);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  mPchBusNumber = DEFAULT_PCI_BUS_NUMBER_PCH;
> +  mTempRootPortBusNumMin = PcdGet8 (PcdSiliconInitTempPciBusMin);
> +  mTempRootPortBusNumMax = PcdGet8 (PcdSiliconInitTempPciBusMax);
> +
> +  ASSERT (sizeof mPcieRootPortConfig == sizeof
> mPchConfigHob->PcieRp.RootPort);
> +  CopyMem (
> +    mPcieRootPortConfig,
> +    &(mPchConfigHob->PcieRp.RootPort),
> +    sizeof (mPcieRootPortConfig)
> +    );
> +
> +  mDevAspmOverride                  = NULL;
> +  mNumOfDevAspmOverride             = 0;
> +
> +  Hob = GetFirstGuidHob (&gPchDeviceTableHobGuid);
> +  if (Hob != NULL) {
> +    DevTableSize = GET_GUID_HOB_DATA_SIZE (Hob);
> +    ASSERT ((DevTableSize % sizeof (PCH_PCIE_DEVICE_OVERRIDE)) == 0);
> +    mNumOfDevAspmOverride = DevTableSize / sizeof
> (PCH_PCIE_DEVICE_OVERRIDE);
> +    DEBUG ((DEBUG_INFO, "Found PcieDeviceTable HOB (%d entries)\n",
> mNumOfDevAspmOverride));
> +    Status = gSmst->SmmAllocatePool (
> +                      EfiRuntimeServicesData,
> +                      DevTableSize,
> +                      (VOID **) &mDevAspmOverride
> +                      );
> +    CopyMem (mDevAspmOverride, GET_GUID_HOB_DATA (Hob),
> DevTableSize);
> +  }
> +
> +  //
> +  // Throught all PCIE root port function and register the SMI Handler for
> enabled ports.
> +  //
> +  for (PortIndex = 0; PortIndex < MaxPciePortNum; PortIndex++) {
> +    GetPchPcieRpDevFun (PortIndex, &RpDevice, &RpFunction);
> +    RpBase = PCI_SEGMENT_LIB_ADDRESS
> (DEFAULT_PCI_SEGMENT_NUMBER_PCH, DEFAULT_PCI_BUS_NUMBER_PCH,
> (UINT32) RpDevice, (UINT32) RpFunction, 0);
> +    //
> +    // Skip the root port function which is not enabled
> +    //
> +    if (PciSegmentRead32 (RpBase) == 0xFFFFFFFF) {
> +      continue;
> +    }
> +
> +    //
> +    // Register SMI Handlers for Hot Plug and Link Active State Change
> +    //
> +    Data8 = PciSegmentRead8 (RpBase + R_PCH_PCIE_CFG_SLCAP);
> +    if (Data8 & B_PCIE_SLCAP_HPC) {
> +      PcieHandle = NULL;
> +      Status = PchPcieSmiDispatchProtocol->HotPlugRegister (
> +                                             PchPcieSmiDispatchProtocol,
> +                                             PchPcieSmiRpHandlerFunction,
> +                                             PortIndex,
> +                                             &PcieHandle
> +                                             );
> +      ASSERT_EFI_ERROR (Status);
> +
> +      Status = PchPcieSmiDispatchProtocol->LinkActiveRegister (
> +                                             PchPcieSmiDispatchProtocol,
> +                                             PchPcieLinkActiveStateChange,
> +                                             PortIndex,
> +                                             &PcieHandle
> +                                             );
> +      ASSERT_EFI_ERROR (Status);
> +
> +      Data32Or  = B_PCH_PCIE_CFG_MPC_HPME;
> +      Data32And = (UINT32) ~B_PCH_PCIE_CFG_MPC_HPME;
> +      S3BootScriptSaveMemReadWrite (
> +        S3BootScriptWidthUint32,
> +        PcdGet64 (PcdPciExpressBaseAddress) + RpBase +
> R_PCH_PCIE_CFG_MPC,
> +        &Data32Or,  /// Data to be ORed
> +        &Data32And  /// Data to be ANDed
> +        );
> +    }
> +
> +    //
> +    // Register SMI Handler for Link Equalization Request from Gen 3 Devices.
> +    //
> +    Data8 = PciSegmentRead8 (RpBase + R_PCH_PCIE_CFG_LCAP);
> +    if ((Data8 & B_PCIE_LCAP_MLS) == V_PCIE_LCAP_MLS_GEN3) {
> +      Status = PchPcieSmiDispatchProtocol->LinkEqRegister (
> +                                             PchPcieSmiDispatchProtocol,
> +                                             PchPcieLinkEqHandlerFunction,
> +                                             PortIndex,
> +                                             &PcieHandle
> +                                             );
> +      ASSERT_EFI_ERROR (Status);
> +    }
> +  }
> +
> +  ASSERT_EFI_ERROR (Status);
> +
> +  PchIoTrapContext.Type     = WriteTrap;
> +  PchIoTrapContext.Length   = 4;
> +  PchIoTrapContext.Address  = 0;
> +  Status = mPchIoTrap->Register (
> +                         mPchIoTrap,
> +                         (EFI_SMM_HANDLER_ENTRY_POINT2)
> PchPcieIoTrapSmiCallback,
> +                         &PchIoTrapContext,
> +                         &PchIoTrapHandle
> +                         );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Install the PCH Pcie IoTrap protocol
> +  //
> +  (gBS->AllocatePool) (EfiBootServicesData, sizeof
> (PCH_PCIE_IOTRAP_PROTOCOL), (VOID **)&PchPcieIoTrapProtocol);
> +  PchPcieIoTrapProtocol->PcieTrapAddress = PchIoTrapContext.Address;
> +
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &ImageHandle,
> +                  &gPchPcieIoTrapProtocolGuid,
> +                  PchPcieIoTrapProtocol,
> +                  NULL
> +                  );
> +
> +  //
> +  // Register the callback for S3 entry
> +  //
> +  SxDispatchContext.Type  = SxS3;
> +  SxDispatchContext.Phase = SxEntry;
> +  Status = mSxDispatch->Register (
> +                          mSxDispatch,
> +                          PchPcieS3EntryCallBack,
> +                          &SxDispatchContext,
> +                          &SxDispatchHandle
> +                          );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  DEBUG ((DEBUG_INFO, "InitializePchPcieSmm, IoTrap @ %x () End\n",
> PchIoTrapContext.Address));
> +
> +  return EFI_SUCCESS;
> +}
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c
> new file mode 100644
> index 0000000000..3c843616e4
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchSpiAsync.c
> @@ -0,0 +1,69 @@
> +/** @file
> +  PCH SPI Async SMI handler.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include "PchInitSmm.h"
> +
> +///
> +/// Global variables
> +///
> +GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMI_DISPATCH_PROTOCOL
> *mPchSmiDispatchProtocol;
> +
> +/**
> +  This hardware SMI handler will be run every time the flash write/earse
> happens.
> +
> +  @param[in] DispatchHandle       Not used
> +
> +**/
> +VOID
> +EFIAPI
> +PchSpiAsyncCallback (
> +  IN  EFI_HANDLE                              DispatchHandle
> +  )
> +{
> +  //
> +  // Dummy SMI handler
> +  //
> +}
> +
> +/**
> +  This fuction install SPI ASYNC SMI handler.
> +
> +  @retval EFI_SUCCESS             Initialization complete.
> +**/
> +EFI_STATUS
> +EFIAPI
> +InstallPchSpiAsyncSmiHandler (
> +  VOID
> +  )
> +{
> +  EFI_STATUS              Status;
> +  EFI_HANDLE              Handle;
> +
> +  DEBUG ((DEBUG_INFO, "InstallPchSpiAsyncSmiHandler()\n"));
> +
> +  ///
> +  /// Get the PCH SMM dispatch protocol
> +  ///
> +  mPchSmiDispatchProtocol = NULL;
> +  Status = gSmst->SmmLocateProtocol (&gPchSmiDispatchProtocolGuid,
> NULL, (VOID **) &mPchSmiDispatchProtocol);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  ///
> +  /// Register an SpiAsync callback function
> +  ///
> +  Handle = NULL;
> +  Status = mPchSmiDispatchProtocol->SpiAsyncRegister (
> +                                      mPchSmiDispatchProtocol,
> +                                      PchSpiAsyncCallback,
> +                                      &Handle
> +                                      );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git
> a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmCon
> trolDriver.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmCon
> trolDriver.c
> new file mode 100644
> index 0000000000..d843de3ad8
> --- /dev/null
> +++
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmCon
> trolDriver.c
> @@ -0,0 +1,399 @@
> +/** @file
> +  This is the driver that publishes the SMM Control Protocol.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/UefiDriverEntryPoint.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Guid/EventGroup.h>
> +#include <Library/PmcLib.h>
> +#include <Library/GpioLib.h>
> +#include <IndustryStandard/Pci30.h>
> +#include <Register/PchRegsLpc.h>
> +#include <Register/PchRegsSpi.h>
> +#include <Register/PchRegsPmc.h>
> +#include "SmmControlDriver.h"
> +
> +STATIC SMM_CONTROL_PRIVATE_DATA mSmmControl;
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT16                          mABase;
> +
> +VOID
> +EFIAPI
> +DisablePendingSmis (
> +  VOID
> +  );
> +
> +/**
> +  Fixup internal data pointers so that the services can be called in virtual
> mode.
> +
> +  @param[in] Event                The event registered.
> +  @param[in] Context              Event context.
> +
> +**/
> +VOID
> +EFIAPI
> +SmmControlVirtualAddressChangeEvent (
> +  IN EFI_EVENT                  Event,
> +  IN VOID                       *Context
> +  )
> +{
> +  gRT->ConvertPointer (0, (VOID *) &(mSmmControl.SmmControl.Trigger));
> +  gRT->ConvertPointer (0, (VOID *) &(mSmmControl.SmmControl.Clear));
> +}
> +
> +/**
> +  <b>SmmControl DXE RUNTIME Module Entry Point</b>\n
> +  - <b>Introduction</b>\n
> +    The SmmControl module is a DXE RUNTIME driver that provides a standard
> way
> +    for other drivers to trigger software SMIs.
> +
> +  - @pre
> +    - PCH Power Management I/O space base address has already been
> programmed.
> +      If SmmControl Runtime DXE driver is run before Status Code Runtime
> Protocol
> +      is installed and there is the need to use Status code in the driver, it will
> +      be necessary to add EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID to
> the dependency file.
> +    - EFI_SMM_BASE2_PROTOCOL
> +      - Documented in the System Management Mode Core Interface
> Specification.
> +
> +  - @result
> +    The SmmControl driver produces the EFI_SMM_CONTROL_PROTOCOL
> documented in
> +    System Management Mode Core Interface Specification.
> +
> +  @param[in] ImageHandle          Handle for the image of this driver
> +  @param[in] SystemTable          Pointer to the EFI System Table
> +
> +  @retval EFI_STATUS              Results of the installation of the SMM Control
> Protocol
> +**/
> +EFI_STATUS
> +EFIAPI
> +SmmControlDriverEntryInit (
> +  IN EFI_HANDLE         ImageHandle,
> +  IN EFI_SYSTEM_TABLE   *SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +  EFI_EVENT   Event;
> +
> +  DEBUG ((DEBUG_INFO, "SmmControlDriverEntryInit() Start\n"));
> +
> +  //
> +  // Get the Power Management I/O space base address. We assume that
> +  // this base address has already been programmed if this driver is
> +  // being run.
> +  //
> +  mABase = PmcGetAcpiBase ();
> +
> +  Status = EFI_SUCCESS;
> +  if (mABase != 0) {
> +    //
> +    // Install the instance of the protocol
> +    //
> +    mSmmControl.Signature                       =
> SMM_CONTROL_PRIVATE_DATA_SIGNATURE;
> +    mSmmControl.Handle                          = ImageHandle;
> +
> +    mSmmControl.SmmControl.Trigger              = Activate;
> +    mSmmControl.SmmControl.Clear                = Deactivate;
> +    mSmmControl.SmmControl.MinimumTriggerPeriod = 0;
> +
> +    //
> +    // Install our protocol interfaces on the device's handle
> +    //
> +    Status = gBS->InstallMultipleProtocolInterfaces (
> +                    &mSmmControl.Handle,
> +                    &gEfiSmmControl2ProtocolGuid,
> +                    &mSmmControl.SmmControl,
> +                    NULL
> +                    );
> +  } else {
> +    Status = EFI_DEVICE_ERROR;
> +    return Status;
> +  }
> +
> +  Status = gBS->CreateEventEx (
> +                  EVT_NOTIFY_SIGNAL,
> +                  TPL_NOTIFY,
> +                  SmmControlVirtualAddressChangeEvent,
> +                  NULL,
> +                  &gEfiEventVirtualAddressChangeGuid,
> +                  &Event
> +                  );
> +  //
> +  // Disable any PCH SMIs that, for whatever reason, are asserted after the
> boot.
> +  //
> +  DisablePendingSmis ();
> +
> +  DEBUG ((DEBUG_INFO, "SmmControlDriverEntryInit() End\n"));
> +
> +  return Status;
> +}
> +
> +/**
> +  Trigger the software SMI
> +
> +  @param[in] Data                 The value to be set on the software SMI data
> port
> +
> +  @retval EFI_SUCCESS             Function completes successfully
> +**/
> +EFI_STATUS
> +EFIAPI
> +SmmTrigger (
> +  IN UINT8   Data
> +  )
> +{
> +  UINT32  OutputData;
> +  UINT32  OutputPort;
> +
> +  //
> +  // Enable the APMC SMI
> +  //
> +  OutputPort  = mABase + R_ACPI_IO_SMI_EN;
> +  OutputData  = IoRead32 ((UINTN) OutputPort);
> +  OutputData |= (B_ACPI_IO_SMI_EN_APMC |
> B_ACPI_IO_SMI_EN_GBL_SMI);
> +  DEBUG (
> +    (DEBUG_EVENT,
> +     "The SMI Control Port at address %x will be written to %x.\n",
> +     OutputPort,
> +     OutputData)
> +    );
> +  IoWrite32 (
> +    (UINTN) OutputPort,
> +    (UINT32) (OutputData)
> +    );
> +
> +  OutputPort  = R_PCH_IO_APM_CNT;
> +  OutputData  = Data;
> +
> +  //
> +  // Generate the APMC SMI
> +  //
> +  IoWrite8 (
> +    (UINTN) OutputPort,
> +    (UINT8) (OutputData)
> +    );
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Clear the SMI status
> +
> +
> +  @retval EFI_SUCCESS             The function completes successfully
> +  @retval EFI_DEVICE_ERROR        Something error occurred
> +**/
> +EFI_STATUS
> +EFIAPI
> +SmmClear (
> +  VOID
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINT32      OutputData;
> +  UINT32      OutputPort;
> +
> +  Status = EFI_SUCCESS;
> +
> +  //
> +  // Clear the Power Button Override Status Bit, it gates EOS from being set.
> +  //
> +  OutputPort  = mABase + R_ACPI_IO_PM1_STS;
> +  OutputData  = B_ACPI_IO_PM1_STS_PRBTNOR;
> +  DEBUG (
> +    (DEBUG_EVENT,
> +     "The PM1 Status Port at address %x will be written to %x.\n",
> +     OutputPort,
> +     OutputData)
> +    );
> +  IoWrite16 (
> +    (UINTN) OutputPort,
> +    (UINT16) (OutputData)
> +    );
> +
> +  //
> +  // Clear the APM SMI Status Bit
> +  //
> +  OutputPort  = mABase + R_ACPI_IO_SMI_STS;
> +  OutputData  = B_ACPI_IO_SMI_STS_APM;
> +  DEBUG (
> +    (DEBUG_EVENT,
> +     "The SMI Status Port at address %x will be written to %x.\n",
> +     OutputPort,
> +     OutputData)
> +    );
> +  IoWrite32 (
> +    (UINTN) OutputPort,
> +    (UINT32) (OutputData)
> +    );
> +
> +  //
> +  // Set the EOS Bit
> +  //
> +  OutputPort  = mABase + R_ACPI_IO_SMI_EN;
> +  OutputData  = IoRead32 ((UINTN) OutputPort);
> +  OutputData |= B_ACPI_IO_SMI_EN_EOS;
> +  DEBUG (
> +    (DEBUG_EVENT,
> +     "The SMI Control Port at address %x will be written to %x.\n",
> +     OutputPort,
> +     OutputData)
> +    );
> +  IoWrite32 (
> +    (UINTN) OutputPort,
> +    (UINT32) (OutputData)
> +    );
> +
> +  //
> +  // There is no need to read EOS back and check if it is set.
> +  // This can lead to a reading of zero if an SMI occurs right after the SMI_EN
> port read
> +  // but before the data is returned to the CPU.
> +  // SMM Dispatcher should make sure that EOS is set after all SMI sources are
> processed.
> +  //
> +  return Status;
> +}
> +
> +/**
> +  This routine generates an SMI
> +
> +  @param[in] This                       The EFI SMM Control protocol instance
> +  @param[in, out] CommandPort           The buffer contains data to the
> command port
> +  @param[in, out] DataPort              The buffer contains data to the data
> port
> +  @param[in] Periodic                   Periodic or not
> +  @param[in] ActivationInterval         Interval of periodic SMI
> +
> +  @retval EFI Status                    Describing the result of the operation
> +  @retval EFI_INVALID_PARAMETER         Some parameter value passed is
> not supported
> +**/
> +EFI_STATUS
> +EFIAPI
> +Activate (
> +  IN CONST EFI_SMM_CONTROL2_PROTOCOL                    * This,
> +  IN OUT  UINT8                                         *CommandPort
> OPTIONAL,
> +  IN OUT  UINT8                                         *DataPort          OPTIONAL,
> +  IN      BOOLEAN                                       Periodic           OPTIONAL,
> +  IN      UINTN                                         ActivationInterval OPTIONAL
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINT8       Data;
> +
> +  if (Periodic) {
> +    DEBUG ((DEBUG_WARN, "Invalid parameter\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (CommandPort == NULL) {
> +    Data = 0xFF;
> +  } else {
> +    Data = *CommandPort;
> +  }
> +  //
> +  // Clear any pending the APM SMI
> +  //
> +  Status = SmmClear ();
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  return SmmTrigger (Data);
> +}
> +
> +/**
> +  This routine clears an SMI
> +
> +  @param[in] This                 The EFI SMM Control protocol instance
> +  @param[in] Periodic             Periodic or not
> +
> +  @retval EFI Status              Describing the result of the operation
> +  @retval EFI_INVALID_PARAMETER   Some parameter value passed is not
> supported
> +**/
> +EFI_STATUS
> +EFIAPI
> +Deactivate (
> +  IN CONST EFI_SMM_CONTROL2_PROTOCOL       *This,
> +  IN  BOOLEAN                              Periodic OPTIONAL
> +  )
> +{
> +  if (Periodic) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  return SmmClear ();
> +}
> +/**
> +  Disable all pending SMIs
> +
> +**/
> +VOID
> +EFIAPI
> +DisablePendingSmis (
> +  VOID
> +  )
> +{
> +  UINT32               Data;
> +  BOOLEAN              SciEn;
> +
> +  //
> +  // Determine whether an ACPI OS is present (via the SCI_EN bit)
> +  //
> +  Data      = IoRead16 ((UINTN) mABase + R_ACPI_IO_PM1_CNT);
> +  SciEn     = (BOOLEAN) ((Data & B_ACPI_IO_PM1_CNT_SCI_EN) ==
> B_ACPI_IO_PM1_CNT_SCI_EN);
> +
> +  if (!SciEn) {
> +    //
> +    // Clear any SMIs that double as SCIs (when SCI_EN==0)
> +    //
> +    IoWrite16 ((UINTN) mABase + R_ACPI_IO_PM1_STS, 0xFFFF);
> +    IoWrite16 ((UINTN) mABase + R_ACPI_IO_PM1_EN, 0);
> +    IoWrite16 ((UINTN) mABase + R_ACPI_IO_PM1_CNT, 0);
> +    IoWrite32 (
> +      (UINTN) mABase + R_ACPI_IO_GPE0_STS_127_96,
> +      (UINT32)( B_ACPI_IO_GPE0_STS_127_96_USB_CON_DSX_STS |
> +                B_ACPI_IO_GPE0_STS_127_96_LAN_WAKE |
> +                B_ACPI_IO_GPE0_STS_127_96_PME_B0 |
> +                B_ACPI_IO_GPE0_STS_127_96_PME |
> +                B_ACPI_IO_GPE0_STS_127_96_BATLOW |
> +                B_ACPI_IO_GPE0_STS_127_96_RI |
> +                B_ACPI_IO_GPE0_STS_127_96_SWGPE)
> +      );
> +    //
> +    // Disable WADT_EN by default can avoid the WADT SMI during POST time
> when the WADT_STS is set as a wake source.
> +    // BIOS disable WADT_EN and keep WADT_STS into OS so OS can be aware
> of the wake source.
> +    //
> +    IoAnd32 ((UINTN) mABase + R_ACPI_IO_GPE0_EN_127_96, (UINT32)
> ~B_ACPI_IO_GPE0_EN_127_96_WADT);
> +  }
> +  //
> +  // Clear and disable all SMIs that are unaffected by SCI_EN
> +  //
> +  GpioDisableAllGpiSmi ();
> +
> +  GpioClearAllGpiSmiSts ();
> +
> +  IoWrite32 ((UINTN) mABase + R_ACPI_IO_DEVACT_STS, 0x0000FFFF);
> +
> +  IoWrite32 ((UINTN) mABase + R_ACPI_IO_SMI_STS, ~0u);
> +
> +  //
> +  // (Make sure to write this register last -- EOS re-enables SMIs for the PCH)
> +  //
> +  Data  = IoRead32 ((UINTN) mABase + R_ACPI_IO_SMI_EN);
> +  //
> +  // clear all bits except those tied to SCI_EN
> +  //
> +  Data &= B_ACPI_IO_SMI_EN_BIOS_RLS;
> +  //
> +  // enable SMIs and specifically enable writes to APM_CNT.
> +  //
> +  Data |= B_ACPI_IO_SMI_EN_GBL_SMI | B_ACPI_IO_SMI_EN_APMC;
> +  //
> +  //  NOTE: Default value of EOS is set in PCH, it will be automatically cleared
> Once the PCH asserts SMI# low,
> +  //  we don't need to do anything to clear it
> +  //
> +  IoWrite32 ((UINTN) mABase + R_ACPI_IO_SMI_EN, Data);
> +}
> +
> diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Spi/Smm/PchSpi.c
> b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Spi/Smm/PchSpi.c
> new file mode 100644
> index 0000000000..458d137e4f
> --- /dev/null
> +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Spi/Smm/PchSpi.c
> @@ -0,0 +1,310 @@
> +/** @file
> +  PCH SPI SMM Driver implements the SPI Host Controller Compatibility
> Interface.
> +
> +  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/IoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/UefiDriverEntryPoint.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/SmmServicesTableLib.h>
> +#include <Library/PciSegmentLib.h>
> +#include <Protocol/Spi.h>
> +#include <Protocol/SmmCpu.h>
> +#include <Private/Library/PchSpiCommonLib.h>
> +#include <Private/Library/SmmPchPrivateLib.h>
> +#include <PchReservedResources.h>
> +#include <IndustryStandard/Pci30.h>
> +#include <Register/PchRegs.h>
> +#include <Register/PchRegsSpi.h>
> +
> +//
> +// Global variables
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED SPI_INSTANCE          *mSpiInstance;
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_CPU_PROTOCOL
> *mSmmCpuProtocol;
> +//
> +// mPchSpiResvMmioAddr keeps the reserved MMIO range assiged to SPI.
> +// In SMM it always set back the reserved MMIO address to SPI BAR0 to ensure
> the MMIO range
> +// won't overlap with SMRAM range, and trusted.
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED UINT32
> mSpiResvMmioAddr;
> +
> +/**
> +  <b>SPI Runtime SMM Module Entry Point</b>\n
> +  - <b>Introduction</b>\n
> +    The SPI SMM module provide a standard way for other modules to use the
> PCH SPI Interface in SMM.
> +
> +  - @pre
> +    - EFI_SMM_BASE2_PROTOCOL
> +      - Documented in System Management Mode Core Interface
> Specification .
> +
> +  - @result
> +    The SPI SMM driver produces @link _PCH_SPI_PROTOCOL
> PCH_SPI_PROTOCOL @endlink with GUID
> +    gPchSmmSpiProtocolGuid which is different from SPI RUNTIME driver.
> +
> +  - <b>Integration Check List</b>\n
> +    - This driver supports Descriptor Mode only.
> +    - This driver supports Hardware Sequence only.
> +    - When using SMM SPI Protocol to perform flash access in an SMI handler,
> +      and the SMI occurrence is asynchronous to normal mode code execution,
> +      proper synchronization mechanism must be applied, e.g. disable SMI
> before
> +      the normal mode SendSpiCmd() starts and re-enable SMI after
> +      the normal mode SendSpiCmd() completes.
> +      @note The implementation of SendSpiCmd() uses GBL_SMI_EN in
> +      SMI_EN register (ABase + 30h) to disable and enable SMIs. But this may
> +      not be effective as platform may well set the SMI_LOCK bit (i.e., PMC PCI
> Offset A0h [4]).
> +      So the synchronization at caller level is likely needed.
> +
> +  @param[in] ImageHandle          Image handle of this driver.
> +  @param[in] SystemTable          Global system service table.
> +
> +  @retval EFI_SUCCESS             Initialization complete.
> +  @exception EFI_UNSUPPORTED      The chipset is unsupported by this
> driver.
> +  @retval EFI_OUT_OF_RESOURCES    Do not have enough resources to
> initialize the driver.
> +  @retval EFI_DEVICE_ERROR        Device error, driver exits abnormally.
> +**/
> +EFI_STATUS
> +EFIAPI
> +InstallPchSpi (
> +  IN EFI_HANDLE            ImageHandle,
> +  IN EFI_SYSTEM_TABLE      *SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  //
> +  // Init PCH spi reserved MMIO address.
> +  //
> +  mSpiResvMmioAddr = PCH_SPI_BASE_ADDRESS;
> +
> +  ///
> +  /// Allocate pool for SPI protocol instance
> +  ///
> +  Status = gSmst->SmmAllocatePool (
> +                    EfiRuntimeServicesData, /// MemoryType don't care
> +                    sizeof (SPI_INSTANCE),
> +                    (VOID **) &mSpiInstance
> +                    );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  if (mSpiInstance == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  ZeroMem ((VOID *) mSpiInstance, sizeof (SPI_INSTANCE));
> +  ///
> +  /// Initialize the SPI protocol instance
> +  ///
> +  Status = SpiProtocolConstructor (mSpiInstance);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +  ///
> +  /// Install the SMM PCH_SPI_PROTOCOL interface
> +  ///
> +  Status = gSmst->SmmInstallProtocolInterface (
> +                    &(mSpiInstance->Handle),
> +                    &gPchSmmSpiProtocolGuid,
> +                    EFI_NATIVE_INTERFACE,
> +                    &(mSpiInstance->SpiProtocol)
> +                    );
> +  if (EFI_ERROR (Status)) {
> +    gSmst->SmmFreePool (mSpiInstance);
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Acquire PCH spi mmio address.
> +  If it is ever different from the preallocated address, reassign it back.
> +  In SMM, it always override the BAR0 and returns the reserved MMIO range
> for SPI.
> +
> +  @param[in] SpiInstance          Pointer to SpiInstance to initialize
> +
> +  @retval PchSpiBar0              return SPI MMIO address
> +**/
> +UINTN
> +AcquireSpiBar0 (
> +  IN  SPI_INSTANCE                *SpiInstance
> +  )
> +{
> +  UINT32                          SpiBar0;
> +  //
> +  // Save original SPI physical MMIO address
> +  //
> +  SpiBar0 = PciSegmentRead32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0)
> & ~(B_SPI_CFG_BAR0_MASK);
> +
> +  if (SpiBar0 != mSpiResvMmioAddr) {
> +    //
> +    // Temporary disable MSE, and override with SPI reserved MMIO address,
> then enable MSE.
> +    //
> +    PciSegmentAnd8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET,
> (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
> +    PciSegmentWrite32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0,
> mSpiResvMmioAddr);
> +    PciSegmentOr8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET,
> EFI_PCI_COMMAND_MEMORY_SPACE);
> +  }
> +  //
> +  // SPIBAR0 will be different before and after PCI enum so need to get it from
> SPI BAR0 reg.
> +  //
> +  return mSpiResvMmioAddr;
> +}
> +
> +/**
> +  Release pch spi mmio address. Do nothing.
> +
> +  @param[in] SpiInstance          Pointer to SpiInstance to initialize
> +
> +  @retval None
> +**/
> +VOID
> +ReleaseSpiBar0 (
> +  IN  SPI_INSTANCE                *SpiInstance
> +  )
> +{
> +}
> +
> +/**
> +  This function is a hook for Spi to disable BIOS Write Protect
> +
> +  @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 (
> +  VOID
> +  )
> +{
> +  UINT64     SpiBaseAddress;
> +
> +  SpiBaseAddress = PCI_SEGMENT_LIB_ADDRESS (
> +                     DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +                     DEFAULT_PCI_BUS_NUMBER_PCH,
> +                     PCI_DEVICE_NUMBER_PCH_SPI,
> +                     PCI_FUNCTION_NUMBER_PCH_SPI,
> +                     0
> +                     );
> +  // Write clear BC_SYNC_SS prior to change WPD from 0 to 1.
> +  //
> +  PciSegmentOr8 (
> +    SpiBaseAddress + R_SPI_CFG_BC + 1,
> +    (B_SPI_CFG_BC_SYNC_SS >> 8)
> +    );
> +  ///
> +  /// Set BIOSWE bit (SPI PCI Offset DCh [0]) = 1b
> +  /// Enable the access to the BIOS space for both read and write cycles
> +  ///
> +  PciSegmentOr8 (
> +    SpiBaseAddress + R_SPI_CFG_BC,
> +    B_SPI_CFG_BC_WPD
> +    );
> +
> +  ///
> +  /// PCH BIOS Spec Section 3.7 BIOS Region SMM Protection Enabling
> +  /// If the following steps are implemented:
> +  ///  - Set the EISS bit (SPI PCI Offset DCh [5]) = 1b
> +  ///  - Follow the 1st recommendation in section 3.6
> +  /// the BIOS Region can only be updated by following the steps bellow:
> +  ///  - Once all threads enter SMM
> +  ///  - Read memory location FED30880h OR with 00000001h, place the
> result in EAX,
> +  ///    and write data to lower 32 bits of MSR 1FEh (sample code available)
> +  ///  - Set BIOSWE bit (SPI PCI Offset DCh [0]) = 1b
> +  ///  - Modify BIOS Region
> +  ///  - Clear BIOSWE bit (SPI PCI Offset DCh [0]) = 0b
> +  ///
> +  if ((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) &
> B_SPI_CFG_BC_EISS) != 0) {
> +    PchSetInSmmSts ();
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This function is a hook for Spi to enable BIOS Write Protect
> +
> +
> +**/
> +VOID
> +EFIAPI
> +EnableBiosWriteProtect (
> +  VOID
> +  )
> +{
> +  UINT64     SpiBaseAddress;
> +
> +  SpiBaseAddress = PCI_SEGMENT_LIB_ADDRESS (
> +                     DEFAULT_PCI_SEGMENT_NUMBER_PCH,
> +                     DEFAULT_PCI_BUS_NUMBER_PCH,
> +                     PCI_DEVICE_NUMBER_PCH_SPI,
> +                     PCI_FUNCTION_NUMBER_PCH_SPI,
> +                     0
> +                     );
> +  ///
> +  /// Clear BIOSWE bit (SPI PCI Offset DCh [0]) = 0b
> +  /// Disable the access to the BIOS space for write cycles
> +  ///
> +  PciSegmentAnd8 (
> +    SpiBaseAddress + R_SPI_CFG_BC,
> +    (UINT8) (~B_SPI_CFG_BC_WPD)
> +    );
> +
> +  ///
> +  /// Check if EISS bit is set
> +  ///
> +  if (((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC)) &
> B_SPI_CFG_BC_EISS) == B_SPI_CFG_BC_EISS) {
> +    PchClearInSmmSts ();
> +  }
> +}
> +
> +/**
> +  Check if it's granted to do flash write.
> +
> +  @retval TRUE    It's secure to do flash write.
> +  @retval FALSE   It's not secure to do flash write.
> +**/
> +BOOLEAN
> +IsSpiFlashWriteGranted (
> +  VOID
> +  )
> +{
> +  EFI_STATUS    Status;
> +  UINT32        CpuIndex;
> +  UINT64        ProcessorId;
> +
> +  if (mSmmCpuProtocol == NULL) {
> +    Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL,
> (VOID **)&mSmmCpuProtocol);
> +    ASSERT_EFI_ERROR (Status);
> +    if (mSmmCpuProtocol == NULL) {
> +      return TRUE;
> +    }
> +  }
> +
> +  for (CpuIndex = 0; CpuIndex < gSmst->NumberOfCpus; CpuIndex++) {
> +    Status = mSmmCpuProtocol->ReadSaveState (
> +                                mSmmCpuProtocol,
> +                                sizeof (ProcessorId),
> +                                EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID,
> +                                CpuIndex,
> +                                &ProcessorId
> +                                );
> +    //
> +    // If the processor is in SMM at the time the SMI occurred,
> +    // it will return success. Otherwise, EFI_NOT_FOUND is returned.
> +    //
> +    if (EFI_ERROR (Status)) {
> +      return FALSE;
> +    }
> +  }
> +
> +  return TRUE;
> +}
> --
> 2.16.2.windows.1


  parent reply	other threads:[~2019-08-17  1:14 UTC|newest]

Thread overview: 121+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-17  0:15 [edk2-platforms][PATCH V1 00/37] Coffee Lake and Whiskey Lake support Kubacki, Michael A
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 01/37] CoffeelakeSiliconPkg: Add package and Include headers Kubacki, Michael A
2019-08-17  0:51   ` Nate DeSimone
2019-08-17  1:08   ` Chiu, Chasel
2019-08-17  1:18   ` Chaganty, Rangasai V
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 02/37] CoffeelakeSiliconPkg/Cpu: Add " Kubacki, Michael A
2019-08-17  0:51   ` Nate DeSimone
2019-08-17  1:08   ` Chiu, Chasel
2019-08-17  6:58   ` Chaganty, Rangasai V
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 03/37] CoffeelakeSiliconPkg/Me: " Kubacki, Michael A
2019-08-17  0:51   ` Nate DeSimone
2019-08-17  1:08   ` Chiu, Chasel
2019-08-17  7:04   ` Chaganty, Rangasai V
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 04/37] CoffeelakeSiliconPkg/Pch: Add include headers Kubacki, Michael A
2019-08-17  0:51   ` Nate DeSimone
2019-08-17  1:08   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 05/37] CoffeelakeSiliconPkg/Pch: Add ConfigBlock headers Kubacki, Michael A
2019-08-17  0:51   ` Nate DeSimone
2019-08-17  1:09   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 06/37] CoffeelakeSiliconPkg/Pch: Add Library include headers Kubacki, Michael A
2019-08-17  0:51   ` Nate DeSimone
2019-08-17  1:09   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 07/37] CoffeelakeSiliconPkg/Pch: Add PPI and Protocol " Kubacki, Michael A
2019-08-17  0:51   ` Nate DeSimone
2019-08-17  1:09   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 08/37] CoffeelakeSiliconPkg/Pch: Add Register " Kubacki, Michael A
2019-08-17  0:51   ` Nate DeSimone
2019-08-17  1:09   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 09/37] CoffeelakeSiliconPkg/Pch: Add Private " Kubacki, Michael A
2019-08-17  0:51   ` Nate DeSimone
2019-08-17  1:12   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 10/37] CoffeelakeSiliconPkg/Pch: Add Private/Library " Kubacki, Michael A
2019-08-17  0:52   ` Nate DeSimone
2019-08-17  1:09   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 11/37] CoffeelakeSiliconPkg/Pch: Add Private/Protocol " Kubacki, Michael A
2019-08-17  0:51   ` Nate DeSimone
2019-08-17  1:10   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 12/37] CoffeelakeSiliconPkg/SampleCode: Add Include headers Kubacki, Michael A
2019-08-17  0:52   ` Nate DeSimone
2019-08-17  1:12   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 13/37] CoffeelakeSiliconPkg/SystemAgent: " Kubacki, Michael A
2019-08-17  0:52   ` Nate DeSimone
2019-08-17  1:12   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 14/37] CoffeelakeSiliconPkg: Add package common library instances Kubacki, Michael A
2019-08-17  0:52   ` Nate DeSimone
2019-08-17  1:12   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 15/37] CoffeelakeSiliconPkg/Cpu: Add " Kubacki, Michael A
2019-08-17  0:52   ` Nate DeSimone
2019-08-17  1:15   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 16/37] CoffeelakeSiliconPkg/Me: " Kubacki, Michael A
2019-08-17  0:52   ` Nate DeSimone
2019-08-17  1:12   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 17/37] CoffeelakeSiliconPkg/Pch: Add Base " Kubacki, Michael A
2019-08-17  0:52   ` Nate DeSimone
2019-08-17  1:13   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 18/37] CoffeelakeSiliconPkg/Pch: Add DXE " Kubacki, Michael A
2019-08-17  0:52   ` Nate DeSimone
2019-08-17  1:13   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 19/37] CoffeelakeSiliconPkg/Pch: Add PEI " Kubacki, Michael A
2019-08-17  0:52   ` Nate DeSimone
2019-08-17  1:13   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 20/37] CoffeelakeSiliconPkg/Pch: Add SMM " Kubacki, Michael A
2019-08-17  0:53   ` Nate DeSimone
2019-08-17  1:16   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 21/37] CoffeelakeSiliconPkg/Pch: Add Base " Kubacki, Michael A
2019-08-17  0:52   ` Nate DeSimone
2019-08-17  1:13   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 22/37] CoffeelakeSiliconPkg/Pch: Add DXE private " Kubacki, Michael A
2019-08-17  0:52   ` Nate DeSimone
2019-08-17  1:13   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 23/37] CoffeelakeSiliconPkg/Pch: Add PEI " Kubacki, Michael A
2019-08-17  0:53   ` Nate DeSimone
2019-08-17  1:14   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 24/37] CoffeelakeSiliconPkg/Pch: Add SMM " Kubacki, Michael A
2019-08-17  0:53   ` Nate DeSimone
2019-08-17  1:14   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 25/37] CoffeelakeSiliconPkg/SystemAgent: Add " Kubacki, Michael A
2019-08-17  0:53   ` Nate DeSimone
2019-08-17  1:14   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 26/37] CoffeelakeSiliconPkg/Pch: Add modules Kubacki, Michael A
2019-08-17  0:53   ` Nate DeSimone
2019-08-17  1:14   ` Chiu, Chasel [this message]
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 27/37] CoffeelakeSiliconPkg/Pch: Add PchSmiDispatcher Kubacki, Michael A
2019-08-17  0:53   ` Nate DeSimone
2019-08-17  1:15   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 28/37] CoffeelakeSiliconPkg/SystemAgent: Add modules Kubacki, Michael A
2019-08-17  0:53   ` Nate DeSimone
2019-08-17  1:15   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 29/37] CoffeelakeSiliconPkg: Add package DSC files Kubacki, Michael A
2019-08-17  0:53   ` Nate DeSimone
2019-08-17  1:14   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 30/37] Maintainers.txt: Add CoffeelakeSiliconPkg maintainers Kubacki, Michael A
2019-08-17  0:53   ` Nate DeSimone
2019-08-17  1:15   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 31/37] WhiskeylakeOpenBoardPkg: Add package and headers Kubacki, Michael A
2019-08-17  0:54   ` Nate DeSimone
2019-08-17  1:16   ` Chiu, Chasel
2019-08-19 18:09   ` Sinha, Ankit
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 32/37] WhiskeylakeOpenBoardPkg/WhiskeylakeURvp: Add headers Kubacki, Michael A
2019-08-17  0:54   ` Nate DeSimone
2019-08-17  1:16   ` Chiu, Chasel
2019-08-17  0:15 ` [edk2-platforms][PATCH V1 33/37] WhiskeylakeOpenBoardPkg: Add library instances Kubacki, Michael A
2019-08-17  0:54   ` Nate DeSimone
2019-08-17  1:16   ` Chiu, Chasel
2019-08-17  0:16 ` [edk2-platforms][PATCH V1 34/37] WhiskeylakeOpenBoardPkg/WhiskeylakeURvp: " Kubacki, Michael A
2019-08-17  0:54   ` Nate DeSimone
2019-08-17  1:17   ` Chiu, Chasel
2019-08-17 20:08   ` Chaganty, Rangasai V
2019-08-17  0:16 ` [edk2-platforms][PATCH V1 35/37] WhiskeylakeOpenBoardPkg: Add modules Kubacki, Michael A
2019-08-17  0:54   ` Nate DeSimone
2019-08-17  1:17   ` Chiu, Chasel
2019-08-17  7:50   ` Chaganty, Rangasai V
2019-08-17  0:16 ` [edk2-platforms][PATCH V1 36/37] WhiskeylakeOpenBoardPkg/WhiskeylakeURvp: Add DSC and build files Kubacki, Michael A
2019-08-17  0:54   ` Nate DeSimone
2019-08-17  1:16   ` Chiu, Chasel
2019-08-17 20:11   ` Chaganty, Rangasai V
2019-08-17  0:16 ` [edk2-platforms][PATCH V1 37/37] Add WhiskeylakeOpenBoardPkg to global build config and documentation Kubacki, Michael A
2019-08-17  0:54   ` Nate DeSimone
2019-08-17  1:17   ` Chiu, Chasel
2019-08-17 20:00   ` Chaganty, Rangasai V
2019-08-19 18:14 ` [edk2-platforms][PATCH V1 00/37] Coffee Lake and Whiskey Lake support Sinha, Ankit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3C3EFB470A303B4AB093197B6777CCEC504623AC@PGSMSX111.gar.corp.intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox