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/SmmControl.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/SmmControlDriver.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/SmmControlDriver.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/SmmControl.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf
new file mode 100644
index 0000000000..ff712f8635
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.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/SmmControlDriver.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h
new file mode 100644
index 0000000000..08e64fa5a7
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.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_HID_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/SmmControlDriver.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c
new file mode 100644
index 0000000000..d843de3ad8
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.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
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#45907): https://edk2.groups.io/g/devel/message/45907
Mute This Topic: https://groups.io/mt/32918201/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>
-----Original Message-----
From: Kubacki, Michael A
Sent: Friday, August 16, 2019 5:16 PM
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/SmmControl.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/SmmControlDriver.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/SmmControlDriver.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/SmmControl.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.inf
new file mode 100644
index 0000000000..ff712f8635
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControl.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/SmmControlDriver.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.h
new file mode 100644
index 0000000000..08e64fa5a7
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.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_HID_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/SmmControlDriver.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.c
new file mode 100644
index 0000000000..d843de3ad8
--- /dev/null
+++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmControlDriver.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
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#45940): https://edk2.groups.io/g/devel/message/45940
Mute This Topic: https://groups.io/mt/32918201/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
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
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#45987): https://edk2.groups.io/g/devel/message/45987
Mute This Topic: https://groups.io/mt/32918201/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2025 Red Hat, Inc.