From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 192.55.52.93, mailfrom: nathaniel.l.desimone@intel.com) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by groups.io with SMTP; Fri, 16 Aug 2019 17:53:28 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Aug 2019 17:53:27 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,395,1559545200"; d="scan'208";a="171573462" Received: from orsmsx106.amr.corp.intel.com ([10.22.225.133]) by orsmga008.jf.intel.com with ESMTP; 16 Aug 2019 17:53:27 -0700 Received: from orsmsx158.amr.corp.intel.com (10.22.240.20) by ORSMSX106.amr.corp.intel.com (10.22.225.133) with Microsoft SMTP Server (TLS) id 14.3.439.0; Fri, 16 Aug 2019 17:53:26 -0700 Received: from orsmsx114.amr.corp.intel.com ([169.254.8.96]) by ORSMSX158.amr.corp.intel.com ([169.254.10.29]) with mapi id 14.03.0439.000; Fri, 16 Aug 2019 17:53:26 -0700 From: "Nate DeSimone" To: "Kubacki, Michael A" , "devel@edk2.groups.io" CC: "Chaganty, Rangasai V" , "Chiu, Chasel" , "Gao, Liming" , "Kinney, Michael D" , "Sinha, Ankit" Subject: Re: [edk2-platforms][PATCH V1 26/37] CoffeelakeSiliconPkg/Pch: Add modules Thread-Topic: [edk2-platforms][PATCH V1 26/37] CoffeelakeSiliconPkg/Pch: Add modules Thread-Index: AQHVVJEZ4lCmVMn60UuC76kVx+dcsab+gzAQ Date: Sat, 17 Aug 2019 00:53:26 +0000 Message-ID: <02A34F284D1DA44BB705E61F7180EF0AAEE12A79@ORSMSX114.amr.corp.intel.com> References: <20190817001603.30632-1-michael.a.kubacki@intel.com> <20190817001603.30632-27-michael.a.kubacki@intel.com> In-Reply-To: <20190817001603.30632-27-michael.a.kubacki@intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiYmVlNTE1YjctMjA3My00MmU2LWI1ZmUtNzMzMTA0NjljZjJmIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiRFp0Nmhkd2g3RHBCU01oaFZ6bUp3bVQ4cUFOTExFd2lkRFo4aEVWVUxGTXUrZ1VITmRvWU94UHpyXC9meTJKdlcifQ== x-ctpclassification: CTP_NT x-originating-ip: [10.22.254.139] MIME-Version: 1.0 Return-Path: nathaniel.l.desimone@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Nate DeSimone -----Original Message----- From: Kubacki, Michael A=20 Sent: Friday, August 16, 2019 5:16 PM To: devel@edk2.groups.io Cc: Chaganty, Rangasai V ; Chiu, Chasel ; Desimone, Nathaniel L = ; Gao, Liming ; Kinney, Michael D ; Sinha, Ankit Subject: [edk2-platforms][PATCH V1 26/37] CoffeelakeSiliconPkg/Pch: Add mod= ules REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D2082 * 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 Cc: Chasel Chiu Cc: Nate DeSimone Cc: Liming Gao Cc: Michael D Kinney Cc: Ankit Sinha Signed-off-by: Michael Kubacki --- 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.in= f | 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/SmmControlDri= ver.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/SmmControlDri= ver.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/PchInitDxeC= nl.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeCnl.i= nf 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.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PchInitDxe +FILE_GUID =3D DE23ACEE-CF55-4fb6-AA77-984AB53DE823 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D DXE_DRIVER +ENTRY_POINT =3D 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/PchInitDxeF= spCnl.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeFs= pCnl.inf new file mode 100644 index 0000000000..528cfd0296 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Dxe/PchInitDxeFspCnl.i= nf @@ -0,0 +1,77 @@ +## @file +# Component description file for Pch Initialization driver for FSP packag= e +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010005 +BASE_NAME =3D PchInitDxe +FILE_GUID =3D 5AA5031E-4CB6-43D4-B219-FE50FF5D116C +MODULE_TYPE =3D PEIM +VERSION_STRING =3D 1.0 +ENTRY_POINT =3D 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.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PchInitSmm +FILE_GUID =3D D7B10D4E-67E6-4C74-83E9-F9AF0ACC33CC +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D DXE_SMM_DRIVER +PI_SPECIFICATION_VERSION =3D 1.10 +ENTRY_POINT =3D PchInitSmmEntryPoint +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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 th= at PCI MMIO resource has been prepared and available for this driver to all= ocate. +gEfiSmmBase2ProtocolGuid # This is for SmmServicesTableLib + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/S= mmControl.inf b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDx= e/SmmControl.inf new file mode 100644 index 0000000000..ff712f8635 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmContr= ol.inf @@ -0,0 +1,54 @@ +## @file +# Component description file for SmmControl module +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D SmmControl +FILE_GUID =3D A0BAD9F7-AB78-491b-B583-C52B7F84B9E0 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D DXE_RUNTIME_DRIVER +ENTRY_POINT =3D SmmControlDriverEntryInit +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D PchSpiSmm +FILE_GUID =3D 27F4917B-A707-4aad-9676-26DF168CBF0D +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D DXE_SMM_DRIVER +PI_SPECIFICATION_VERSION =3D 1.10 +ENTRY_POINT =3D 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _PCH_INIT_DXE_H_ +#define _PCH_INIT_DXE_H_ + +#include +#include +#include +#include + +// +// 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 disabl= ed +**/ +EFI_STATUS +PchHdAudioAcpiInit ( + VOID + ); + +/** + Configure eMMC in HS400 Mode + + @param[in] This A pointer to PCH_EMMC_TUNING_PRO= TOCOL structure + @param[in] Revision Revision parameter used to verif= y 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 st= ructure + + @retval EFI_SUCCESS The function completed successfu= lly + @retval EFI_NOT_FOUND The item was not found + @retval EFI_OUT_OF_RESOURCES The request could not be complet= ed 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 detect= ion, + then set the SATA SPD and PxE corresponding, and set the Register Lock o= n 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 initiali= ze 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _PCH_INIT_SMM_H_ +#define _PCH_INIT_SMM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 R= ootPort 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 Roo= t ports + + @param[in] DispatchHandle Handle of this dispatch function + @param[in] RpContext Rootport context, which contains R= ootPort 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 R= ootPort 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_CAL= LBACK_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/S= mmControlDriver.h b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/Runti= meDxe/SmmControlDriver.h new file mode 100644 index 0000000000..08e64fa5a7 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmContr= olDriver.h @@ -0,0 +1,132 @@ +/** @file + Header file for SMM Control Driver. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _SMM_CONTROL_DRIVER_H_ +#define _SMM_CONTROL_DRIVER_H_ + +#include + + +#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_D= ATA, SmmControl, SMM_CONTROL_DEV_SIGNATURE) + +// +// Prototypes +// + +/** + SmmControl DXE RUNTIME Module Entry Point\n + - Introduction\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 program= med. + If SmmControl Runtime DXE driver is run before Status Code Runtime P= rotocol + 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 dep= endency file. + - EFI_SMM_BASE2_PROTOCOL + - Documented in the System Management Mode Core Interface Specificat= ion. + + - @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 C= ontrol 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 insta= nce + @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 opera= tion + @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 suppo= rted +**/ +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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include + +#include "PchInit.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// 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 =3D GetSerialIoDeviceNumber (Device); + FuncNum =3D GetSerialIoFunctionNumber (Device); + + for (Index =3D 0; Index < mPchConfigHob->Interrupt.NumOfDevIntConfig; In= dex++) { + if ((mPchConfigHob->Interrupt.DevIntConfig[Index].Device =3D=3D DevNum= ) && + (mPchConfigHob->Interrupt.DevIntConfig[Index].Function =3D=3D Func= Num)) { + return mPchConfigHob->Interrupt.DevIntConfig[Index]; + } + } + return EmptyRecord; +} + +/** + Update ASL definitions for SerialIo devices. + + @retval EFI_SUCCESS The function completed successfull= y +**/ +EFI_STATUS +UpdateSerialIoAcpiData ( + VOID + ) +{ + PCH_SERIAL_IO_CONTROLLER Index; + + for (Index =3D 0; Index < GetPchMaxSerialIoControllersNum (); Index++) { + mPchNvsAreaProtocol.Area->SMD[Index] =3D mPchConfigHob->SerialIo.DevMo= de[Index]; + mPchNvsAreaProtocol.Area->SIR[Index] =3D (GetInterruptPolicy (Index)).= Irq; + mPchNvsAreaProtocol.Area->SB0[Index] =3D (UINT32) FindSerialIoBar (Ind= ex, 0); + mPchNvsAreaProtocol.Area->SB1[Index] =3D (UINT32) FindSerialIoBar (Ind= ex, 1); + } + if (IsPchH ()) { + mPchNvsAreaProtocol.Area->SMD[PchSerialIoIndexI2C4] =3D PchSerialIoDis= abled; + mPchNvsAreaProtocol.Area->SMD[PchSerialIoIndexI2C5] =3D PchSerialIoDis= abled; + } + + 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 =3D GetFirstGuidHob (&gPchRstHobGuid); + if (Hob =3D=3D NULL) { + DEBUG (( DEBUG_INFO , "PchUpdateNvsAreaAfterRemapping: cannot fetch Rs= tHob" )); + return; + } + + RstHob =3D (PCH_RST_HOB *) GET_GUID_HOB_DATA (Hob); + + for (Index =3D 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) { + mPchNvsAreaProtocol.Area->RstPcieStorageInterfaceType[Index] = =3D RstHob->RstCrConfiguration[Index].DeviceInterface; + mPchNvsAreaProtocol.Area->RstPcieStoragePmCapPtr[Index] = =3D RstHob->SavedRemapedDeviceConfigSpace[Index].PmCapPtr; + mPchNvsAreaProtocol.Area->RstPcieStoragePcieCapPtr[Index] = =3D RstHob->SavedRemapedDeviceConfigSpace[Index].PcieCapPtr; + mPchNvsAreaProtocol.Area->RstPcieStorageL1ssCapPtr[Index] = =3D RstHob->SavedRemapedDeviceConfigSpace[Index].L1ssCapPtr; + mPchNvsAreaProtocol.Area->RstPcieStorageEpL1ssControl2[Index] = =3D RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointL1ssControl2; + mPchNvsAreaProtocol.Area->RstPcieStorageEpL1ssControl1[Index] = =3D RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointL1ssControl1; + mPchNvsAreaProtocol.Area->RstPcieStorageLtrCapPtr[Index] = =3D RstHob->SavedRemapedDeviceConfigSpace[Index].LtrCapPtr; + mPchNvsAreaProtocol.Area->RstPcieStorageEpLtrData[Index] = =3D RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointLtrData; + mPchNvsAreaProtocol.Area->RstPcieStorageEpLctlData16[Index] = =3D RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointLctlData16; + mPchNvsAreaProtocol.Area->RstPcieStorageEpDctlData16[Index] = =3D RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointDctlData16; + mPchNvsAreaProtocol.Area->RstPcieStorageEpDctl2Data16[Index] = =3D RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointDctl2Data16; + mPchNvsAreaProtocol.Area->RstPcieStorageRpDctl2Data16[Index] = =3D RstHob->SavedRemapedDeviceConfigSpace[Index].RootPortDctl2Data16; + mPchNvsAreaProtocol.Area->RstPcieStorageUniqueTableBar[Index] = =3D RstHob->RstCrConfiguration[Index].EndPointUniqueMsixTableBar; + mPchNvsAreaProtocol.Area->RstPcieStorageUniqueTableBarValue[Index] = =3D RstHob->RstCrConfiguration[Index].EndPointUniqueMsixTableBarValue; + mPchNvsAreaProtocol.Area->RstPcieStorageUniquePbaBar[Index] = =3D RstHob->RstCrConfiguration[Index].EndPointUniqueMsixPbaBar; + mPchNvsAreaProtocol.Area->RstPcieStorageUniquePbaBarValue[Index] = =3D RstHob->RstCrConfiguration[Index].EndPointUniqueMsixPbaBarValue; + mPchNvsAreaProtocol.Area->RstPcieStorageRootPortNum[Index] = =3D 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 th= e callback. + @param[in] Context A pointer to private data registered wit= h 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 =3D 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 initiali= ze the driver +**/ +EFI_STATUS +PchAcpiInit ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + EFI_EVENT EndOfDxeEvent; + + DEBUG ((DEBUG_INFO, "Install PCH NVS protocol\n")); + + Status =3D (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (PCH_NVS_AREA),= (VOID **) &mPchNvsAreaProtocol.Area); + ASSERT_EFI_ERROR (Status); + + ZeroMem ((VOID *) mPchNvsAreaProtocol.Area, sizeof (PCH_NVS_AREA)); + Status =3D 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 =3D 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 =3D gBS->LocateProtocol (&gPchPolicyProtocolGuid, NULL, (VOID **)= &PchPolicy); + ASSERT_EFI_ERROR (Status); + + /// + /// Get GPIO DXE Config Block + /// + Status =3D GetConfigBlock ((VOID *)PchPolicy, &gGpioDxeConfigGuid, (VOID= *)&GpioDxeConfig); + ASSERT_EFI_ERROR (Status); + + // + // Update ASL PCIE port address according to root port device and functi= on + // + for (Index =3D 0; Index < GetPchMaxPciePortNum (); Index++) { + Status =3D GetPchPcieRpDevFun (Index, &RpDev, &RpFun); + ASSERT_EFI_ERROR (Status); + + Data32 =3D ((UINT8) RpDev << 16) | (UINT8) RpFun; + mPchNvsAreaProtocol.Area->RpAddress[Index] =3D Data32; + + // + // Update Maximum Snoop Latency and Maximum No-Snoop Latency values fo= r PCIE + // + mPchNvsAreaProtocol.Area->PcieLtrMaxSnoopLatency[Index] =3D mPchConf= igHob->PcieRp.RootPort[Index].LtrMaxSnoopLatency; + mPchNvsAreaProtocol.Area->PcieLtrMaxNoSnoopLatency[Index] =3D mPchConf= igHob->PcieRp.RootPort[Index].LtrMaxNoSnoopLatency; + } + + // + // Update PCHS. + // + mPchNvsAreaProtocol.Area->PchSeries =3D PchSeries (); + // + // Update PCHG. + // + mPchNvsAreaProtocol.Area->PchGeneration =3D (UINT16) PchGeneration (); + // + // Update PSTP. + // + mPchNvsAreaProtocol.Area->PchStepping =3D (UINT16) PchStepping (); + // + // Update HPET base address. + // + PchHpetBaseGet (&HpetBaseAdress); + mPchNvsAreaProtocol.Area->HPTE =3D TRUE; // @todo remove the N= VS, since it's always enabled. + mPchNvsAreaProtocol.Area->HPTB =3D HpetBaseAdress; + // + // Update SBREG_BAR. + // + mPchNvsAreaProtocol.Area->SBRG =3D PCH_PCR_BASE_ADDRESS; + + // + // Update PMC ACPIBASE and PWRMBASE + // + mPchNvsAreaProtocol.Area->PMBS =3D PmcGetAcpiBase (); + + mPchNvsAreaProtocol.Area->PWRM =3D PmcGetPwrmBase (); + + // + // Update GPIO device ACPI variables + // + mPchNvsAreaProtocol.Area->SGIR =3D mPchConfigHob->Interrupt.GpioIrqRoute= ; + mPchNvsAreaProtocol.Area->GPHD =3D (UINT8)GpioDxeConfig->HideGpioAcpiDev= ice; + + // + // 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 m= apped to GPE0. + // If Group is mapped to 1-Tier GPE information is also stored on what G= roup DW + // is mapped to GPE_DWx. Because GPE_DWx register is 32 bits large if gr= oups 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 =3D (UINT8) GpioGetGroupIndexFromGroup (G= roupToGpeDwX[0]); + mPchNvsAreaProtocol.Area->GEI1 =3D (UINT8) GpioGetGroupIndexFromGroup (G= roupToGpeDwX[1]); + mPchNvsAreaProtocol.Area->GEI2 =3D (UINT8) GpioGetGroupIndexFromGroup (G= roupToGpeDwX[2]); + mPchNvsAreaProtocol.Area->GED0 =3D (UINT8) GroupDw[0]; + mPchNvsAreaProtocol.Area->GED1 =3D (UINT8) GroupDw[1]; + mPchNvsAreaProtocol.Area->GED2 =3D (UINT8) GroupDw[2]; + + // + // SCS Configuration + // + // Update eMMC HS400 mode enablement + // + mPchNvsAreaProtocol.Area->EMH4 =3D (UINT8) mPchConfigHob->Scs.ScsEmmcHs4= 00Enabled; + mPchNvsAreaProtocol.Area->EmmcEnabled =3D (UINT8) mPchConfigHob->Scs.Scs= EmmcEnabled; + + // + // 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 =3D 0x1; + break; + case DriverStrength40Ohm: + mPchNvsAreaProtocol.Area->EMDS =3D 0x4; + break; + case DriverStrength50Ohm: + default: + mPchNvsAreaProtocol.Area->EMDS =3D 0x0; + } + + mPchNvsAreaProtocol.Area->SdPowerEnableActiveHigh =3D (UINT8) mPchConfig= Hob->Scs.ScsSdPowerEnableActiveHigh; + mPchNvsAreaProtocol.Area->SdCardEnabled =3D (UINT8) mPchConfig= Hob->Scs.ScsSdCardEnabled; + + // + // SATA configuration. + // + if (PciSegmentRead16 (GetSataRegBase (SATA_1_CONTROLLER_INDEX) + PCI_DEV= ICE_ID_OFFSET) =3D=3D 0xFFFF) { + mPchNvsAreaProtocol.Area->SataPortPresence =3D 0; + } else { + mPchNvsAreaProtocol.Area->SataPortPresence =3D PciSegmentRead8 (GetSat= aRegBase (SATA_1_CONTROLLER_INDEX) + R_SATA_CFG_PCS + 2); + } + + // + // CPU SKU + // + mPchNvsAreaProtocol.Area->CpuSku =3D GetCpuSku (); + + mPchNvsAreaProtocol.Area->SlpS0VmRuntimeControl =3D (UINT8)mPchConfigHob= ->Pm.SlpS0VmRuntimeControl; + mPchNvsAreaProtocol.Area->SlpS0Vm070VSupport =3D (UINT8)mPchConfigHob= ->Pm.SlpS0Vm070VSupport; + mPchNvsAreaProtocol.Area->SlpS0Vm075VSupport =3D (UINT8)mPchConfigHob= ->Pm.SlpS0Vm075VSupport; + mPchNvsAreaProtocol.Area->PsOnEnable =3D (UINT8)mPchConfigHob= ->Pm.PsOnEnable; + + for (Index =3D 0; Index < GetPchMaxPciePortNum (); Index++) { + mPchNvsAreaProtocol.Area->LtrEnable[Index] =3D (UINT8)mPchConfigHob->= PcieRp.RootPort[Index].LtrEnable; + } + + mPchNvsAreaProtocol.Area->GBES =3D PchIsGbePresent (); + + // + // Update PCH Trace Hub Mode + // + mPchNvsAreaProtocol.Area->PchTraceHubMode =3D (UINT8) mPchConfigHob-= >PchTraceHub.PchTraceHubMode; + // + // if SCRPD0[24] is set, force TH to be host debugger mode. + // + if (MmioRead32 (PCH_TRACE_HUB_MTB_BASE_ADDRESS) !=3D 0xFFFFFFFF) { + if (MmioRead32 (PCH_TRACE_HUB_MTB_BASE_ADDRESS + R_TRACE_HUB_MEM_CSR_M= TB_SCRATCHPAD0) & BIT24) { + mPchNvsAreaProtocol.Area->PchTraceHubMode =3D TraceHubModeHostDebugg= er; + } + } + + // + // Update TWMB, Temp memory base address + // + mPchNvsAreaProtocol.Area->TempRsvdMemBase =3D (UINT32) PcdGet32 (PcdSili= conInitTempMemBaseAddr); + + return Status; +} + +/** + Initialize PCH Nvs Area opeartion region. + +**/ +VOID +PatchPchNvsAreaAddress ( + VOID + ) +{ + EFI_STATUS Status; + UINT32 Address; + UINT16 Length; + + Status =3D InitializeAslUpdateLib (); + ASSERT_EFI_ERROR (Status); + + Address =3D (UINT32) (UINTN) mPchNvsAreaProtocol.Area; + Length =3D (UINT16) sizeof (PCH_NVS_AREA); + DEBUG ((DEBUG_INFO, "PatchPchNvsAreaAddress: PCH NVS Address %x Length %= x\n", Address, Length)); + Status =3D UpdateNameAslCode (SIGNATURE_32 ('P','N','V','B'), &Address,= sizeof (Address)); + ASSERT_EFI_ERROR (Status); + Status =3D 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include "PchInit.h" +#include + +/** + 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 =3D (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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include + +#include "PchInit.h" +#include +#include +#include +#include +#include +#include +#include +#include + +PCH_HDA_NHLT_ENDPOINTS mPchHdaNhltEndpoints[HdaEndpointMax] =3D +{ + {HdaDmicX1, B_HDA_DMIC_1CH_48KHZ_16BIT_FORMAT, = 0, FALSE}, + {HdaDmicX2, (B_HDA_DMIC_2CH_48KHZ_16BIT_FORMAT | B_HDA_DMIC_2CH_48KH= Z_32BIT_FORMAT), 0, FALSE}, + {HdaDmicX4, (B_HDA_DMIC_4CH_48KHZ_16BIT_FORMAT | B_HDA_DMIC_4CH_48KH= Z_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_I2= S_RENDER_DEVICE_INFO, FALSE}, + {HdaI2sRender2, B_HDA_I2S_RTK274_RENDER_4CH_48KHZ_24BIT_FORMAT, B_HDA_I2= S_RENDER_DEVICE_INFO, FALSE}, + {HdaI2sCapture, B_HDA_I2S_RTK274_CAPTURE_4CH_48KHZ_24BIT_FORMAT, B_HDA_I= 2S_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 =3D 0; + + DEBUG ((DEBUG_INFO, "AllocateAudioDspStolenMemory()\n")); + + // + // Reserve memory to store Acpi Debug data. + // + DspStolenMemBaseAddress =3D 0xFFFFFFFF; + Status =3D 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 =3D (UINT32) DspStolenMemBaseAddress; + DEBUG ((DEBUG_INFO, "mPchNvsAreaProtocol.Area->DSPM =3D 0x%016x\n", mPch= NvsAreaProtocol.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 =3D NULL; + Xsdt =3D NULL; + Nhlt =3D NULL; + + /// + /// Find the AcpiSupport protocol returns RSDP (or RSD PTR) address. + /// + DEBUG ((DEBUG_INFO, "LocateNhltAcpiTable() Start\n")); + + Status =3D EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID *) = &Rsdp); + if (EFI_ERROR (Status) || (Rsdp =3D=3D NULL)) { + DEBUG ((DEBUG_ERROR, "EFI_ERROR or Rsdp =3D=3D NULL\n")); + return NULL; + } + + Xsdt =3D (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress; + if (Xsdt =3D=3D NULL || Xsdt->Signature !=3D EFI_ACPI_5_0_EXTENDED_SYSTE= M_DESCRIPTION_TABLE_SIGNATURE) { + // If XSDT has not been found, check RSDT + Xsdt =3D (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress; + if (Xsdt =3D=3D NULL || Xsdt->Signature !=3D EFI_ACPI_5_0_ROOT_SYSTEM_= DESCRIPTION_TABLE_SIGNATURE) { + DEBUG ((DEBUG_ERROR, "XSDT/RSDT =3D=3D NULL or wrong signature\n")); + return NULL; + } + } + + for (Index =3D sizeof (EFI_ACPI_DESCRIPTION_HEADER); Index < Xsdt->Lengt= h; Index =3D Index + sizeof (UINT64)) { + Data64 =3D *(UINT64 *) ((UINT8 *) Xsdt + Index); + Nhlt =3D (NHLT_ACPI_TABLE *) (UINTN) Data64; + if (Nhlt->Header.Signature =3D=3D NHLT_ACPI_TABLE_SIGNATURE) { + break; + } + } + + if (Nhlt =3D=3D NULL || Nhlt->Header.Signature !=3D NHLT_ACPI_TABLE_SIGN= ATURE) { + DEBUG ((DEBUG_ERROR, "Nhlt =3D=3D NULL or wrong signature\n")); + return NULL; + } + + DEBUG ((DEBUG_INFO, "Found NhltTable, Address =3D 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 =3D NULL; + NhltTable =3D NULL; + AcpiTableKey =3D 0; + + DEBUG ((DEBUG_INFO, "PublishNhltAcpiTable() Start\n")); + + // + // Locate ACPI support protocol + // + Status =3D gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID = **) &AcpiTable); + if ( EFI_ERROR (Status) || AcpiTable =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + NhltConstructor (mPchHdaNhltEndpoints, &NhltTable, &TableLength); + NhltAcpiHeaderConstructor (NhltTable, TableLength); + + Status =3D 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 polic= y. + + @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 =3D 0x%016x, Le= ngth =3D 0x%08x\n", NhltAcpiTableAddress, NhltAcpiTableLength)); + DEBUG ((DEBUG_INFO, " FeatureMask =3D 0x%08x\n", HdAudioDxeConfig->DspFe= atureMask)); + + mPchNvsAreaProtocol.Area->NHLA =3D NhltAcpiTableAddress; + mPchNvsAreaProtocol.Area->NHLL =3D NhltAcpiTableLength; + mPchNvsAreaProtocol.Area->ADFM =3D HdAudioDxeConfig->DspFeatureMask; + mPchNvsAreaProtocol.Area->SWQ0 =3D HdAudioConfigHob->AudioLinkSndw1 ? 0 = : BIT1; + mPchNvsAreaProtocol.Area->SWQ1 =3D HdAudioConfigHob->AudioLinkSndw2 ? 0 = : BIT1; + mPchNvsAreaProtocol.Area->SWQ2 =3D HdAudioConfigHob->AudioLinkSndw3 ? 0 = : BIT1; + mPchNvsAreaProtocol.Area->SWQ3 =3D 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 =3D NULL; + + Status =3D EFI_SUCCESS; + + if (HdAudioDxeConfig->NhltDefaultFlow =3D=3D TRUE) { + switch (HdAudioDxeConfig->DspEndpointDmic) { + case PchHdaDmic1chArray: + mPchHdaNhltEndpoints[HdaDmicX1].Enable =3D TRUE; + break; + case PchHdaDmic2chArray: + mPchHdaNhltEndpoints[HdaDmicX2].Enable =3D TRUE; + break; + case PchHdaDmic4chArray: + mPchHdaNhltEndpoints[HdaDmicX4].Enable =3D TRUE; + break; + case PchHdaDmicDisabled: + default: + mPchHdaNhltEndpoints[HdaDmicX2].Enable =3D FALSE; + mPchHdaNhltEndpoints[HdaDmicX4].Enable =3D FALSE; + } + + if (HdAudioDxeConfig->DspEndpointBluetooth) { + mPchHdaNhltEndpoints[HdaBtRender].Enable =3D TRUE; + mPchHdaNhltEndpoints[HdaBtCapture].Enable =3D TRUE; + } + + if (HdAudioDxeConfig->DspEndpointI2s) { + mPchHdaNhltEndpoints[HdaI2sRender1].Enable =3D TRUE; + mPchHdaNhltEndpoints[HdaI2sRender2].Enable =3D TRUE; + mPchHdaNhltEndpoints[HdaI2sCapture].Enable =3D TRUE; + } + + Status =3D PublishNhltAcpiTable (); + } + NhltTable =3D LocateNhltAcpiTable (); + if (NhltTable =3D=3D NULL) { + return EFI_LOAD_ERROR; + } + + UpdateHdaAcpiData ((UINT64) (UINTN) NhltTable, (UINT32) (NhltTable->Head= er.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 disabl= ed +**/ +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 =3D &mPchConfigHob->HdAudio; + + /// + /// Get PCH Policy Protocol + /// + Status =3D gBS->LocateProtocol (&gPchPolicyProtocolGuid, NULL, (VOID **)= &PchPolicy); + ASSERT_EFI_ERROR (Status); + + /// + /// Get HD Audio DXE Config Block + /// + Status =3D GetConfigBlock ((VOID *)PchPolicy, &gHdAudioDxeConfigGuid, (V= OID *)&HdAudioDxeConfig); + ASSERT_EFI_ERROR (Status); + + HdaPciBase =3D 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) =3D=3D 0xFFFF)= || (HdAudioConfigHob->DspEnable =3D=3D FALSE)) { + // Do not set ACPI tables if HDAudio is Function disabled or DSP is di= sabled + DEBUG ((DEBUG_INFO, "AudioDSP: Non-HDAudio ACPI Table (NHLT) not set!\= n")); + return EFI_UNSUPPORTED; + } + + Status =3D SetHdaAcpiTable (HdAudioConfigHob, HdAudioDxeConfig); + + DEBUG ((DEBUG_INFO, "PchHdAudioAcpiInit() End - Status =3D %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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include + +#include "PchInit.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// 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 =3D GetFirstGuidHob (&gPchConfigHobGuid); + ASSERT (HobPtr.Guid !=3D NULL); + mPchConfigHob =3D (PCH_CONFIG_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid); + + // + // Get Silicon Config data HOB + // + HobPtr.Guid =3D GetFirstGuidHob (&gSiConfigHobGuid); + ASSERT (HobPtr.Guid !=3D NULL); + mSiConfigHobData =3D (SI_CONFIG_HOB_DATA *) GET_GUID_HOB_DATA (HobPtr.Gu= id); + + 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 =3D 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) =3D=3D 0xFFF= F) { + 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 =3D 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_M= EMORY_SPACE); + + // + // Program the Flash Protection Range Register based on policy + // + DlockValue =3D MmioRead32 (PchSpiBar0 + R_SPI_MEM_DLOCK); + for (Index =3D 0; Index < PCH_FLASH_PROTECTED_RANGES; ++Index) { + if ((mPchConfigHob->ProtectRange[Index].WriteProtectionEnable || + mPchConfigHob->ProtectRange[Index].ReadProtectionEnable) !=3D TRU= E) { + continue; + } + + // + // Proceed to program the register after ensure it is enabled + // + Data32 =3D 0; + Data32 |=3D (mPchConfigHob->ProtectRange[Index].WriteProtectionEnable = =3D=3D TRUE) ? B_SPI_MEM_PRX_WPE : 0; + Data32 |=3D (mPchConfigHob->ProtectRange[Index].ReadProtectionEnable = =3D=3D TRUE) ? B_SPI_MEM_PRX_RPE : 0; + Data32 |=3D ((UINT32) mPchConfigHob->ProtectRange[Index].ProtectedRang= eLimit << N_SPI_MEM_PRX_PRL) & B_SPI_MEM_PRX_PRL_MASK; + Data32 |=3D ((UINT32) mPchConfigHob->ProtectRange[Index].ProtectedRang= eBase << N_SPI_MEM_PRX_PRB) & B_SPI_MEM_PRX_PRB_MASK; + DEBUG ((DEBUG_INFO, "Protected range %d: 0x%08x \n", Index, Data32)); + + DlockValue |=3D (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_P= RX))) + ); + } + // + // 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 Lo= ck-Down bit + /// (SPI_BAR0 + 04[15]) at end of post. When set to 1, those Flash Prog= ram 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 dis= able Write Status in HW sequencing + /// + + // + // Ensure there is no pending SPI trasaction before setting lock bits + // + Timer =3D 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 erro= r. + // + DEBUG ((DEBUG_ERROR, "SPI Cycle timeout\n")); + ASSERT (FALSE); + break; + } + MicroSecondDelay (SPI_WAIT_PERIOD); + Timer +=3D SPI_WAIT_PERIOD; + } + + Data16And =3D B_SPI_MEM_HSFSC_SCIP; + Data16 =3D 0; + S3BootScriptSaveMemPoll ( + S3BootScriptWidthUint16, + PchSpiBar0 + R_SPI_MEM_HSFSC, + &Data16And, + &Data16, + SPI_WAIT_PERIOD, + SPI_WAIT_TIME / SPI_WAIT_PERIOD + ); + + // + // Clear any outstanding status + // + Data16Or =3D 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 =3D 0xFFFF; + MmioAndThenOr16 (PchSpiBar0 + R_SPI_MEM_HSFSC, Data16And, Data16Or); + S3BootScriptSaveMemReadWrite ( + S3BootScriptWidthUint16, + PchSpiBar0 + R_SPI_MEM_HSFSC, + &Data16Or, + &Data16And + ); + + // + // Set WRSDIS + // + Data16Or =3D B_SPI_MEM_HSFSC_WRSDIS; + Data16And =3D 0xFFFF; + MmioAndThenOr16 (PchSpiBar0 + R_SPI_MEM_HSFSC, Data16And, Data16Or); + S3BootScriptSaveMemReadWrite ( + S3BootScriptWidthUint16, + PchSpiBar0 + R_SPI_MEM_HSFSC, + &Data16Or, + &Data16And + ); + + // + // Set FLOCKDN + // + Data16Or =3D B_SPI_MEM_HSFSC_FLOCKDN; + Data16And =3D 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 =3D 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 =3D 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 =3D=3D 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 th= eir 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 =3D=3D 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) + PciLpcRegBas= e + R_LPC_CFG_BC) + ); + + // + // Reads back for posted write to take effect + // + Data8 =3D 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) + PciSpiRegBas= e + R_SPI_CFG_BC) + ); + + // + // Reads back for posted write to take effect + // + Data8 =3D 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 By= te blocks, respectively, + /// cannot be unlocked until next reset. + /// + Data32And =3D 0xFFFFFFFF; + Data32Or =3D 0x0; + + if (mPchConfigHob->LockDown.BiosInterface =3D=3D TRUE) { + Data32Or =3D B_RTC_PCR_CONF_BILD; + } + if (mPchConfigHob->LockDown.RtcMemoryLock =3D=3D TRUE) { + Data32Or |=3D (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 =3D (UINT32)~(BIT0); + Data32Or =3D 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 =3D 0xFFFF; + Data16Or =3D 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 =3D 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) =3D=3D 0xFFFF)= { + return; + } + if ((PciSegmentRead32 (EspiPciBase + R_ESPI_CFG_PCBC) & B_ESPI_CFG_PCBC_= ESPI_EN) =3D=3D 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 Configur= ation + // and Capabilities register of each slave using Get_Configuration and S= et_Configuration functionality. + // + // NOTE: The setting is also done in PEI, but might be cleared by PCI bu= s during PCI enumeration. + // Therefore, reeable it after PCI enumeration done. + // + if (mPchConfigHob->Espi.BmeMasterSlaveEnabled =3D=3D TRUE) { + PciSegmentOr8 (EspiPciBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_BUS_M= ASTER); + } +} + +/** + 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 =3D SiScheduleResetPerformReset (); + ASSERT (!ResetStatus); + } + + ProcessAllLocks (); + + // + // Perform remaining configuration for PCH SATA on End of DXE + // + ConfigurePchSataOnEndOfDxe (); + // + // PSTHCTL (0xD00h[2]) =3D 1, PSTH IOSF Primary Trunk Clock Gating Enabl= e (PSTHIOSFPTCGE) + // + Data32And =3D 0xFFFFFFFF; + Data32Or =3D 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include + +#include "PchInit.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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] =3D 1b) which = prevent writes + /// to the Global SMI Enable bit (GLB_SMI_EN ABASE + 30h[0]). Enabling t= his bit will + /// mitigate malicious software attempts to gain system management mode = privileges. + /// + if (mPchConfigHob->LockDown.GlobalSmi =3D=3D TRUE) { + /// + /// Save Global SMI Enable bit setting before BIOS enables SMI_LOCK du= ring S3 resume + /// + ABase =3D PmcGetAcpiBase (); + Data32Or =3D IoRead32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN)); + if ((Data32Or & B_ACPI_IO_SMI_EN_GBL_SMI) !=3D 0) { + Data32And =3D 0xFFFFFFFF; + Data32Or |=3D 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 =3D gBS->LocateProtocol (&gPchPcieIoTrapProtocolGuid, NULL, (VOID= **) &PchPcieIoTrapProtocol); + if (EFI_ERROR (Status)) { + return; + } + mPcieIoTrapAddress =3D PchPcieIoTrapProtocol->PcieTrapAddress; + DEBUG ((DEBUG_INFO, "PcieIoTrapAddress: %0x\n", mPcieIoTrapAddress)); + + if (mPcieIoTrapAddress !=3D 0) { + // + // Save PCH PCIE IoTrap address to re-config PCIE power management set= ting after resume from S3 + // + Data32 =3D 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 =3D gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid,= NULL, (VOID **) &ProtocolPointer); + if (EFI_SUCCESS !=3D Status) { + return; + } + gBS->CloseEvent (Event); + + // + // Enable Thermal MSE + // + ThermalPciBase =3D 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) !=3D 0xFFFF= ) { + if (((PciSegmentRead32 (ThermalPciBase + R_THERMAL_CFG_MEM_TBAR) & B_T= HERMAL_CFG_MEM_TBAR_MASK) !=3D 0) || + ((PciSegmentRead32 (ThermalPciBase + R_THERMAL_CFG_MEM_TBARH) !=3D= 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/LegacyBo= ot. + // It is guaranteed that only one of two events below will be signalled + // + Status =3D gBS->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_CALLBACK, + PchOnExitBootServices, + NULL, + &ExitBootServicesEvent + ); + ASSERT_EFI_ERROR (Status); + + Status =3D 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")); +} +/** + PchInit DXE Module Entry Point\n + - Introduction\n + The PchInit module is a DXE driver that initializes the Intel Platfo= rm Controller Hub + following the PCH BIOS specification and EDS requirements and recomm= endations. It consumes + the PCH_POLICY_HOB SI_POLICY_HOB for expected configurations per pol= icy. + This is the standard EFI driver point that detects whether there is = an supported PCH in + the system and if so, initializes the chipset. + + - Details\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 PC= H 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_PROTOC= OL @endlink + + - References\n + - @link _PCH_POLICY PCH_POLICY_HOB @endlink. + - @link _SI_POLICY_STRUCT SI_POLICY_HOB @endlink. + + - Integration Checklists\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 Specifica= tion 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 initiali= ze 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 =3D ImageHandle; + + PchInitEntryPointCommon (); + + InitializePchDevice (); + + Status =3D 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 th= e callback. + @param[in] Context A pointer to private data registered wit= h the callback function. +**/ +VOID +EFIAPI +PchOnBootToOs ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + /// + /// Closed the event to avoid call twice + /// + if (Event !=3D NULL) { + gBS->CloseEvent (Event); + } + + ConfigureSerialIoAtBoot (); + + return; +} + +/** + PCH initialization on ExitBootService. This event is used if only ExitBo= otService is used + and not in legacy boot + + @param[in] Event A pointer to the Event that triggered th= e callback. + @param[in] Context A pointer to private data registered wit= h 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 th= e callback. + @param[in] Context A pointer to private data registered wit= h the callback function. +**/ +VOID +EFIAPI +PchOnReadyToBoot ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + DEBUG ((DEBUG_INFO, "Uefi PchOnReadyToBoot() Start\n")); + + if (Event !=3D NULL) { + gBS->CloseEvent (Event); + } + + // + // Trigger an Iotrap SMI to config PCIE power management setting after P= CI enumrate is done + // + if (mPcieIoTrapAddress !=3D 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#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[] =3D { + { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERM= INATE_LIST), + &gEfiPciEnumerationCompleteProtocolGuid, + PchOnPciEnumCompleteFsp + } +}; + +/** + FSP PchInit Module Entry Point for FSP\n + + @param[in] FileHandle PEIM's file handle + @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES t= able published by the PEI Foundation + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initiali= ze 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 =3D 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_SERVICE= S table published by the PEI Foundation + @param[in] NotifyDescriptor Address of the notification descriptor dat= a 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 initiali= ze 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include + +#include "PchInit.h" +#include +#include + +/** + Perform the remaining configuration on PCH SATA to perform device detect= ion, + then set the SATA SPD and PxE corresponding, and set the Register Lock o= n PCH SATA + + @retval None +**/ +VOID +ConfigurePchSataOnEndOfDxe ( + VOID + ) +{ + UINT64 PciSataRegBase; + UINT16 SataPortsEnabled; + UINT32 DwordReg; + UINTN Index; + UINT32 SataCtrlIndex; + + for (SataCtrlIndex =3D 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 =3D GetSataRegBase (SataCtrlIndex); + SataPortsEnabled =3D 0; + + DwordReg =3D PciSegmentRead32 (PciSataRegBase + R_SATA_CFG_PCS); + for (Index =3D 0; Index < GetPchMaxSataPortNum (SataCtrlIndex); Index+= +) { + if ((mPchConfigHob->Sata[SataCtrlIndex].PortSettings[Index].HotPlug = =3D=3D TRUE) || + (DwordReg & (B_SATA_CFG_PCS_P0P << Index)) || + (mPchConfigHob->Sata[SataCtrlIndex].TestMode =3D=3D TRUE) || + (mPchConfigHob->Sata[SataCtrlIndex].PortSettings[Index].Extern= al =3D=3D TRUE)) { + SataPortsEnabled |=3D (mPchConfigHob->Sata[SataCtrlIndex].PortSe= ttings[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_MA= P, + 1, + (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) + PciSataRegBa= se + R_SATA_CFG_MAP) + ); + + /// + /// Program PCS "Port X Enabled", SATA PCI offset 94h[7:0] =3D Port 0~= 7 Enabled bit as per SataPortsEnabled value. + /// + PciSegmentOr16 (PciSataRegBase + R_SATA_CFG_PCS, SataPortsEnabled); + S3BootScriptSaveMemWrite ( + S3BootScriptWidthUint16, + PcdGet64 (PcdPciExpressBaseAddress) + PciSataRegBase + R_SATA_CFG_PC= S, + 1, + (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) + PciSataRegBa= se + 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_SA= TAGC, + 1, + (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) + PciSataRegBa= se + 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include "PchInit.h" +#include +#include +#include + +/** + 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 =3D 0; Index < PchSerialIoIndexMax; Index++) { + if (mPchConfigHob->SerialIo.DevMode[Index] =3D=3D PchSerialIoDisabled)= { + if (IsSerialIoFunctionZero (Index)) { + if (IsSerialIoDeviceEnabled (GetSerialIoDeviceNumber (Index), GetS= erialIoFunctionNumber (Index))) { + PciCfgBase =3D FindSerialIoBar (Index,1); + MmioOr32 (PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS, B_SERIAL_IO= _CFG_PME_CTRL_STS_PWR_ST); + } + } + continue; + } + if ((Index >=3D PchSerialIoIndexUart0) && + (mPchConfigHob->SerialIo.EnableDebugUartAfterPost) && + (mPchConfigHob->SerialIo.DebugUartNumber =3D=3D (UINT32) (Index - = PchSerialIoIndexUart0))) { + continue; + } + PciCfgBase =3D FindSerialIoBar (Index,1); + MmioOr32 (PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS, B_SERIAL_IO_CFG_P= ME_CTRL_STS_PWR_ST); + MmioRead32 (PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS); + if (mPchConfigHob->SerialIo.DevMode[Index] =3D=3D PchSerialIoPci) { + MmioAnd32 (PciCfgBase + PCI_COMMAND_OFFSET, (UINT32)~(EFI_PCI_COMMAN= D_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER) ); + if (mPchConfigHob->SerialIo.DebugUartNumber =3D=3D (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/PchSerialIo= Dxe.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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include + +#include "PchInit.h" +#include +#include +#include +#include + +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_H= ID_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,{E= ND_DEVICE_PATH_LENGTH,0}} + +GLOBAL_REMOVE_IF_UNREFERENCED SERIALIO_DEVICE_PATH gSerialIoPath =3D { + 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=3D0; iSerialIo.DevMode[i] =3D=3D PchSerialIoHidden || + mPchConfigHob->SerialIo.DevMode[i] =3D=3D PchSerialIoAcpi) { + for (BarNumber =3D 0; BarNumber<=3D1; BarNumber++) { + Bar =3D FindSerialIoBar (i,BarNumber); + Status =3D gDS->AddMemorySpace ( + EfiGcdMemoryTypeReserved, + Bar, + V_SERIAL_IO_CFG_BAR_SIZE, + 0 + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + Status =3D 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 =3D 0; Controller < PchSerialIoIndexMax; Controller++) { + if (mPchConfigHob->SerialIo.DevMode[Controller] =3D=3D PchSerialIoAcpi= ) { + NewHandle =3D NULL; + CopyMem (gSerialIoPath.HidString, GetSerialIoAcpiHid (Controller), S= ERIALIO_HID_LENGTH); + NewPath =3D DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL*)&gSerial= IoPath); + 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 =3D 0; Index < PchSerialIoIndexMax; Index++) { + if (mPchConfigHob->SerialIo.DevMode[Index] =3D=3D PchSerialIoDisabled)= { + if (IsSerialIoFunctionZero (Index)) { + if (IsSerialIoDeviceEnabled (GetSerialIoDeviceNumber (Index), GetS= erialIoFunctionNumber (Index))) { + PciCfgBase =3D FindSerialIoBar (Index,1); + Data32 =3D MmioRead32 (PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS= ); + Data32 |=3D B_SERIAL_IO_CFG_PME_CTRL_STS_PWR_ST; + S3BootScriptSaveMemWrite (S3BootScriptWidthUint32, PciCfgBase + = R_SERIAL_IO_CFG_PME_CTRL_STS, 1, &Data32); + } + } + continue; + } + if ((Index >=3D PchSerialIoIndexUart0) && + (mPchConfigHob->SerialIo.EnableDebugUartAfterPost) && + (mPchConfigHob->SerialIo.DebugUartNumber =3D=3D (UINT32) (Index - = PchSerialIoIndexUart0))) { + continue; + } + PciCfgBase =3D FindSerialIoBar (Index,1); + Data32 =3D MmioRead32 (PciCfgBase + R_SERIAL_IO_CFG_PME_CTRL_STS); + Data32 |=3D B_SERIAL_IO_CFG_PME_CTRL_STS_PWR_ST; + S3BootScriptSaveMemWrite (S3BootScriptWidthUint32, PciCfgBase + R_SERI= AL_IO_CFG_PME_CTRL_STS, 1, &Data32); + if (mPchConfigHob->SerialIo.DevMode[Index] =3D=3D PchSerialIoPci) { + Data32 =3D MmioRead32 (PciCfgBase + PCI_COMMAND_OFFSET); + Data32 &=3D (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/PchBiosWrit= eProtect.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchBiosWrit= eProtect.c new file mode 100644 index 0000000000..7fe1567c9f --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchBiosWriteProtec= t.c @@ -0,0 +1,156 @@ +/** @file + PCH BIOS Write Protect Driver. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "PchInitSmm.h" +#include +#include +#include + +// +// Global variables +// +GLOBAL_REMOVE_IF_UNREFERENCED PCH_TCO_SMI_DISPATCH_PROTOCOL *mPchTcoSm= iDispatchProtocol; +GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mSpiRegBas= e; +GLOBAL_REMOVE_IF_UNREFERENCED PCH_ESPI_SMI_DISPATCH_PROTOCOL *mEspiSmmD= ispatchProtocol; +GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mLpcRegBas= e; + +/** + This hardware SMI handler will be run every time the BIOS Write Enable b= it 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 b= it 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 !=3D TRUE) { + return EFI_SUCCESS; + } + + mSpiRegBase =3D 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 =3D 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 =3D NULL; + Status =3D gSmst->SmmLocateProtocol (&gPchTcoSmiDispatchProtocolGuid, NU= LL, (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 handl= e the SPI BIOS WP SMI + // to avoid SMI deadloop on SPI WPD write. + // + Handle =3D NULL; + Status =3D mPchTcoSmiDispatchProtocol->SpiBiosWpRegister ( + mPchTcoSmiDispatchProtocol, + PchSpiBiosWpCallback, + &Handle + ); + ASSERT_EFI_ERROR (Status); + + // + // Always register an LPC/eSPI BiosWp callback function to handle TCO BI= OSWR 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 =3D NULL; + Status =3D gSmst->SmmLocateProtocol (&gPchEspiSmiDispatchProtocolGuid,= NULL, (VOID **) &mEspiSmmDispatchProtocol); + ASSERT_EFI_ERROR (Status); + + // + // Register an ESpiBiosWp callback function to handle BIOSWR SMI + // + Handle =3D NULL; + Status =3D mEspiSmmDispatchProtocol->BiosWrProtectRegister ( + mEspiSmmDispatchProtocol, + PchLpcBiosWpCallback, + &Handle + ); + ASSERT_EFI_ERROR (Status); + } else { + // + // Register an LPC BiosWp callback function to handle TCO BIOSWR SMI + // + Handle =3D NULL; + Status =3D 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "PchInitSmm.h" +#include +#include +#include + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL *m= PchIoTrap; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_SX_DISPATCH2_PROTOCOL *m= SxDispatch; + +GLOBAL_REMOVE_IF_UNREFERENCED PCH_NVS_AREA *m= PchNvsArea; +GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mA= cpiBaseAddr; + +// +// NOTE: The module variables of policy here are only valid in post time, = but not runtime time. +// +GLOBAL_REMOVE_IF_UNREFERENCED PCH_CONFIG_HOB *m= PchConfigHob; +GLOBAL_REMOVE_IF_UNREFERENCED SI_CONFIG_HOB_DATA *m= SiConfigHobData; + +// +// The reserved MMIO range to be used in Sx handler +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS mR= esvMmioBaseAddr; +GLOBAL_REMOVE_IF_UNREFERENCED UINTN mR= esvMmioSize; + +/** + SMBUS Sx entry SMI handler. +**/ +VOID +SmbusSxCallback ( + VOID + ) +{ + UINT64 SmbusRegBase; + UINT16 SmbusIoBase; + + SmbusRegBase =3D 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) =3D=3D 0xFFFFFFFF) { + return; + } + + SmbusIoBase =3D PciSegmentRead16 (SmbusRegBase + R_SMBUS_CFG_BASE) & B_S= MBUS_CFG_BASE_BAR; + if (SmbusIoBase =3D=3D 0) { + return; + } + + PciSegmentOr8 (SmbusRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_IO_SPA= CE); + // + // 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 =3D PcdGet32 (PcdSiliconInitTempMemBaseAddr); + mResvMmioSize =3D PcdGet32 (PcdSiliconInitTempMemSize); + DEBUG ((DEBUG_INFO, "mResvMmioBaseAddr %x, mResvMmioSize %x\n", mResvMmi= oBaseAddr, mResvMmioSize)); +} + +/** + Initializes the PCH SMM handler for for PCIE hot plug support + PchInit SMM Module Entry Point\n + - Introduction\n + The PchInitSmm module is a SMM driver that initializes the Intel Pla= tform Controller Hub + SMM requirements and services. It consumes the PCH_POLICY_HOB and SI= _POLICY_HOB for expected + configurations per policy. + + - Details\n + This module provides SMI handlers to services PCIE HotPlug SMI, LinkAc= tive SMI, and LinkEq SMI. + And also provides port 0x61 emulation support, registers BIOS WP handl= er 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 GPI= O 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_PROT= OCOL @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 + + - References\n + - @link _PCH_POLICY PCH_POLICY_HOB @endlink. + - @link _SI_POLICY_STRUCT SI_POLICY_HOB @endlink. + + - Integration Checklists\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 Specifica= tion 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 =3D gSmst->SmmLocateProtocol ( + &gEfiSmmIoTrapDispatch2ProtocolGuid, + NULL, + (VOID **) &mPchIoTrap + ); + ASSERT_EFI_ERROR (Status); + + Status =3D gSmst->SmmLocateProtocol ( + &gEfiSmmSxDispatch2ProtocolGuid, + NULL, + (VOID**) &mSxDispatch + ); + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->LocateProtocol (&gPchNvsAreaProtocolGuid, NULL, (VOID **= ) &PchNvsAreaProtocol); + ASSERT_EFI_ERROR (Status); + mPchNvsArea =3D PchNvsAreaProtocol->Area; + + // + // Get PCH Data HOB. + // + HobPtr.Guid =3D GetFirstGuidHob (&gPchConfigHobGuid); + ASSERT (HobPtr.Guid !=3D NULL); + mPchConfigHob =3D (PCH_CONFIG_HOB *) GET_GUID_HOB_DATA (HobPtr.Guid); + + HobPtr.Guid =3D GetFirstGuidHob (&gSiConfigHobGuid); + ASSERT (HobPtr.Guid !=3D NULL); + mSiConfigHobData =3D (SI_CONFIG_HOB_DATA *) GET_GUID_HOB_DATA (HobPtr.Gu= id); + + mAcpiBaseAddr =3D PmcGetAcpiBase (); + + AllocateReservedMmio (); + + Status =3D InitializePchPcieSmm (ImageHandle, SystemTable); + ASSERT_EFI_ERROR (Status); + + Status =3D InstallPchBiosWriteProtect (ImageHandle, SystemTable); + ASSERT_EFI_ERROR (Status); + + Status =3D 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include "PchInitSmm.h" +#include +#include +#include +#include + +/** + Checks if Lan is Enabled or Disabled + + @retval BOOLEAN TRUE if device is enabled, FALSE otherwise. +**/ +BOOLEAN +IsGbeEnabled ( + VOID + ) +{ + UINT64 GbePciBase; + + GbePciBase =3D 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) !=3D 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 =3D GbeMdiSetPage (GbeBar, PHY_MDI_PAGE_769_PORT_CONTROL_REGISTER= S); + if (EFI_ERROR (Status)) return; + + // + // 3. Set registry to 17 Port General Configuration + // 4. Copy all settings from Port General Configuration + // + Status =3D 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 =3D 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_REGISET= ER_17_PGC_MACPD_ENABLE) & (~B_PHY_MDI_PAGE_769_REGISETER_17_PGC_HOST_WAKE_U= P)); + if (EFI_ERROR (Status)) return; + + // + // 6. Read Receive Address Low and Receive Address High from MMIO + // + RAL0 =3D MmioRead32 (GbeBar + R_LAN_MEM_CSR_RAL); + RAH0 =3D MmioRead32 (GbeBar + R_LAN_MEM_CSR_RAH); + + // + // 7. Set page to 800 Wake Up Registers + // 8. Wait 4 mSec + // + Status =3D 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 =3D GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_800_REGISETER_16_RA= L0); + if (EFI_ERROR (Status)) return; + + // + // 10. Program first 16 bits [0:15] out of 48 in Receive Address Low 1/2 + // + Status =3D 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 =3D GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_800_REGISETER_17_RA= L1); + if (EFI_ERROR (Status)) return; + + // + // 12. Program second 16 bits [16:31] out of 48 in Receive Address Low 2= /2 + // + Status =3D 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 =3D GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_800_REGISETER_18_RA= H0); + if (EFI_ERROR (Status)) return; + + // + // 14. Program last 16 bits [32:47] out of 48 + // + Status =3D 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 =3D GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_800_REGISETER_19_RA= H1); + if (EFI_ERROR (Status)) return; + + // + // 16. Set Address Valid + // + Status =3D 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 =3D GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_800_REGISETER_1_WUC= ); + if (EFI_ERROR (Status)) return; + + // + // 18. Copy WakeUp Control from MAC MMIO + // + WUC =3D (UINT16) MmioRead32 (GbeBar + R_LAN_MEM_CSR_WUC); + + // + // 19. Store WakeUp Contorl into LCD + // Modify APME bit to enable APM wake up + // + Status =3D 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 =3D GbeMdiSetPage (GbeBar, PHY_MDI_PAGE_803_HOST_WOL_PACKET); + if (EFI_ERROR (Status)) return; + + // + // 22. Set registry to 66 Host WoL Packet Clear + // + Status =3D GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_803_REGISETER_66_HW= PC); + if (EFI_ERROR (Status)) return; + + // + // 23. Clear WOL Packet + // + Status =3D 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 =3D GbeMdiSetPage (GbeBar, PHY_MDI_PAGE_769_PORT_CONTROL_REGISTER= S); + if (EFI_ERROR (Status)) return; + + // + // 26. Set registry to 17 Port General Configuration + // + Status =3D GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_769_REGISETER_17_PG= C); + if (EFI_ERROR (Status)) return; + + // + // 27. Copy all settings from Port General Configuration + // + Status =3D 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 =3D 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_REGISET= ER_17_PGC_HOST_WAKE_UP) & (~B_PHY_MDI_PAGE_769_REGISETER_17_PGC_MACPD_ENABL= E)); + 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 trans= ition + 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 =3D 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) =3D=3D 0xFFFF) = { + return; + } + + // + // Check if GbE device is in D0 + // + if ((PciSegmentRead16 (LanRegBase + R_LAN_CFG_PMCS) & B_LAN_CFG_PMCS_PS)= !=3D V_LAN_CFG_PMCS_PS0) { + return; + } + + ASSERT (mResvMmioSize >=3D (1 << N_LAN_CFG_MBARA_ALIGN)); + GbeBar =3D (UINT32) mResvMmioBaseAddr; + if (GbeBar =3D=3D 0) { + ASSERT (FALSE); + return; + } + + // + // Enable MMIO decode using reserved range. + // + PciSegmentAnd16 (LanRegBase + PCI_COMMAND_OFFSET, (UINT16) ~EFI_PCI_COMM= AND_MEMORY_SPACE); + PciSegmentWrite32 (LanRegBase + R_LAN_CFG_MBARA, GbeBar); + PciSegmentOr16 (LanRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_= SPACE); + + // + // If MBARA offset 5800h [0] =3D 1b then proceed with the w/a + // + if (MmioRead32 (GbeBar + R_LAN_MEM_CSR_WUC) & B_LAN_MEM_CSR_WUC_APME) { + Status =3D 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_COMM= AND_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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "PchInitSmm.h" +#include +#include +#include + +GLOBAL_REMOVE_IF_UNREFERENCED PCH_PCIE_DEVICE_OVERRIDE *mDevAspmOverrid= e; +GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mNumOfDevAspmOve= rride; +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 mTempRootPortBus= NumMin; +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mTempRootPortBus= NumMax; + +GLOBAL_REMOVE_IF_UNREFERENCED PCH_PCIE_ROOT_PORT_CONFIG mPcieRootPortCon= fig[PCH_MAX_PCIE_ROOT_PORTS]; + +GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mPciePmTrapExecu= ted =3D 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 =3D PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + mPchBusNumber, + (UINT32) RpDevice, + (UINT32) RpFunction, + 0 + ); + + if (PciSegmentRead16 (RpBase + PCI_VENDOR_ID_OFFSET) =3D=3D 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 ta= kes a few milliseconds to stabilize + // + DownstreamDevicePresent =3D !!(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 behin= d it + /// Wait up to 100ms, according to PCIE spec chapter 6.7.3.3 + /// + Timeout =3D 100 * 1000; + while ((PciSegmentRead16 (RpBase + R_PCH_PCIE_CFG_LSTS) & B_PCIE_LSTS_= LA) =3D=3D 0 ) { + MicroSecondDelay (10); + Timeout-=3D10; + if (Timeout =3D=3D 0) { + return; + } + } + SecBus =3D PciSegmentRead8 (RpBase + PCI_BRIDGE_SECONDARY_BUS_REGISTE= R_OFFSET); + SubBus =3D PciSegmentRead8 (RpBase + PCI_BRIDGE_SUBORDINATE_BUS_REGIS= TER_OFFSET); + ASSERT (SecBus !=3D 0 && SubBus !=3D 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 =3D PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, Se= cBus, 0, 0, 0); + EpPcieCapPtr =3D PcieFindCapId (DEFAULT_PCI_SEGMENT_NUMBER_PCH, SecBus= , 0, 0, EFI_PCI_CAPABILITY_ID_PCIEXP); + EpMaxSpeed =3D PciSegmentRead8 (EpBase + EpPcieCapPtr + R_PCIE_LCAP_OF= FSET) & B_PCIE_LCAP_MLS; + if (EpMaxSpeed >=3D 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 R= ootPort 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 Roo= t ports + + @param[in] DispatchHandle Handle of this dispatch function + @param[in] RpContext Rootport context, which contains R= ootPort 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 R= ootPort 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 generat= ed by PCIe RP when + /// enabled and the SMI subroutine would invoke the Software Preset/Coef= ficient 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 =3D GetPchMaxPciePortNum (); + + for (PortIndex =3D 0; PortIndex < MaxPciePortNum; PortIndex++) { + GetPchPcieRpDevFun (PortIndex, &RpDevice, &RpFunction); + RpBase =3D PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, DE= FAULT_PCI_BUS_NUMBER_PCH, (UINT32) RpDevice, (UINT32) RpFunction, 0); + + if (PciSegmentRead16 (RpBase) !=3D 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_CAL= LBACK_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 =3D=3D PciePmTrap) { + if (mPciePmTrapExecuted =3D=3D FALSE) { + PchPciePmIoTrapSmiCallback (); + mPciePmTrapExecuted =3D 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 =3D 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 =3D GetPchMaxPciePortNum (); + + // + // Locate Pch Pcie Smi Dispatch Protocol + // + Status =3D gSmst->SmmLocateProtocol (&gPchPcieSmiDispatchProtocolGuid, N= ULL, (VOID**)&PchPcieSmiDispatchProtocol); + ASSERT_EFI_ERROR (Status); + + mPchBusNumber =3D DEFAULT_PCI_BUS_NUMBER_PCH; + mTempRootPortBusNumMin =3D PcdGet8 (PcdSiliconInitTempPciBusMin); + mTempRootPortBusNumMax =3D PcdGet8 (PcdSiliconInitTempPciBusMax); + + ASSERT (sizeof mPcieRootPortConfig =3D=3D sizeof mPchConfigHob->PcieRp.R= ootPort); + CopyMem ( + mPcieRootPortConfig, + &(mPchConfigHob->PcieRp.RootPort), + sizeof (mPcieRootPortConfig) + ); + + mDevAspmOverride =3D NULL; + mNumOfDevAspmOverride =3D 0; + + Hob =3D GetFirstGuidHob (&gPchDeviceTableHobGuid); + if (Hob !=3D NULL) { + DevTableSize =3D GET_GUID_HOB_DATA_SIZE (Hob); + ASSERT ((DevTableSize % sizeof (PCH_PCIE_DEVICE_OVERRIDE)) =3D=3D 0); + mNumOfDevAspmOverride =3D DevTableSize / sizeof (PCH_PCIE_DEVICE_OVERR= IDE); + DEBUG ((DEBUG_INFO, "Found PcieDeviceTable HOB (%d entries)\n", mNumOf= DevAspmOverride)); + Status =3D 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 =3D 0; PortIndex < MaxPciePortNum; PortIndex++) { + GetPchPcieRpDevFun (PortIndex, &RpDevice, &RpFunction); + RpBase =3D PCI_SEGMENT_LIB_ADDRESS (DEFAULT_PCI_SEGMENT_NUMBER_PCH, DE= FAULT_PCI_BUS_NUMBER_PCH, (UINT32) RpDevice, (UINT32) RpFunction, 0); + // + // Skip the root port function which is not enabled + // + if (PciSegmentRead32 (RpBase) =3D=3D 0xFFFFFFFF) { + continue; + } + + // + // Register SMI Handlers for Hot Plug and Link Active State Change + // + Data8 =3D PciSegmentRead8 (RpBase + R_PCH_PCIE_CFG_SLCAP); + if (Data8 & B_PCIE_SLCAP_HPC) { + PcieHandle =3D NULL; + Status =3D PchPcieSmiDispatchProtocol->HotPlugRegister ( + PchPcieSmiDispatchProtocol, + PchPcieSmiRpHandlerFunction, + PortIndex, + &PcieHandle + ); + ASSERT_EFI_ERROR (Status); + + Status =3D PchPcieSmiDispatchProtocol->LinkActiveRegister ( + PchPcieSmiDispatchProtocol, + PchPcieLinkActiveStateChange, + PortIndex, + &PcieHandle + ); + ASSERT_EFI_ERROR (Status); + + Data32Or =3D B_PCH_PCIE_CFG_MPC_HPME; + Data32And =3D (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 Devic= es. + // + Data8 =3D PciSegmentRead8 (RpBase + R_PCH_PCIE_CFG_LCAP); + if ((Data8 & B_PCIE_LCAP_MLS) =3D=3D V_PCIE_LCAP_MLS_GEN3) { + Status =3D PchPcieSmiDispatchProtocol->LinkEqRegister ( + PchPcieSmiDispatchProtocol, + PchPcieLinkEqHandlerFunction, + PortIndex, + &PcieHandle + ); + ASSERT_EFI_ERROR (Status); + } + } + + ASSERT_EFI_ERROR (Status); + + PchIoTrapContext.Type =3D WriteTrap; + PchIoTrapContext.Length =3D 4; + PchIoTrapContext.Address =3D 0; + Status =3D mPchIoTrap->Register ( + mPchIoTrap, + (EFI_SMM_HANDLER_ENTRY_POINT2) PchPcieIoTrapSmiCa= llback, + &PchIoTrapContext, + &PchIoTrapHandle + ); + ASSERT_EFI_ERROR (Status); + + // + // Install the PCH Pcie IoTrap protocol + // + (gBS->AllocatePool) (EfiBootServicesData, sizeof (PCH_PCIE_IOTRAP_PROTOC= OL), (VOID **)&PchPcieIoTrapProtocol); + PchPcieIoTrapProtocol->PcieTrapAddress =3D PchIoTrapContext.Address; + + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gPchPcieIoTrapProtocolGuid, + PchPcieIoTrapProtocol, + NULL + ); + + // + // Register the callback for S3 entry + // + SxDispatchContext.Type =3D SxS3; + SxDispatchContext.Phase =3D SxEntry; + Status =3D mSxDispatch->Register ( + mSxDispatch, + PchPcieS3EntryCallBack, + &SxDispatchContext, + &SxDispatchHandle + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "InitializePchPcieSmm, IoTrap @ %x () End\n", PchIoT= rapContext.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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "PchInitSmm.h" + +/// +/// Global variables +/// +GLOBAL_REMOVE_IF_UNREFERENCED PCH_SMI_DISPATCH_PROTOCOL *mPchSmiDispat= chProtocol; + +/** + This hardware SMI handler will be run every time the flash write/earse h= appens. + + @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 =3D NULL; + Status =3D gSmst->SmmLocateProtocol (&gPchSmiDispatchProtocolGuid, NULL,= (VOID **) &mPchSmiDispatchProtocol); + ASSERT_EFI_ERROR (Status); + + /// + /// Register an SpiAsync callback function + /// + Handle =3D NULL; + Status =3D mPchSmiDispatchProtocol->SpiAsyncRegister ( + mPchSmiDispatchProtocol, + PchSpiAsyncCallback, + &Handle + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/S= mmControlDriver.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/Runti= meDxe/SmmControlDriver.c new file mode 100644 index 0000000000..d843de3ad8 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/SmmControl/RuntimeDxe/SmmContr= olDriver.c @@ -0,0 +1,399 @@ +/** @file + This is the driver that publishes the SMM Control Protocol. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 virtu= al 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)); +} + +/** + SmmControl DXE RUNTIME Module Entry Point\n + - Introduction\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 program= med. + If SmmControl Runtime DXE driver is run before Status Code Runtime P= rotocol + 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 dep= endency file. + - EFI_SMM_BASE2_PROTOCOL + - Documented in the System Management Mode Core Interface Specificat= ion. + + - @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 C= ontrol 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 =3D PmcGetAcpiBase (); + + Status =3D EFI_SUCCESS; + if (mABase !=3D 0) { + // + // Install the instance of the protocol + // + mSmmControl.Signature =3D SMM_CONTROL_PRIVATE_DA= TA_SIGNATURE; + mSmmControl.Handle =3D ImageHandle; + + mSmmControl.SmmControl.Trigger =3D Activate; + mSmmControl.SmmControl.Clear =3D Deactivate; + mSmmControl.SmmControl.MinimumTriggerPeriod =3D 0; + + // + // Install our protocol interfaces on the device's handle + // + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &mSmmControl.Handle, + &gEfiSmmControl2ProtocolGuid, + &mSmmControl.SmmControl, + NULL + ); + } else { + Status =3D EFI_DEVICE_ERROR; + return Status; + } + + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + SmmControlVirtualAddressChangeEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &Event + ); + // + // Disable any PCH SMIs that, for whatever reason, are asserted after th= e 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 =3D mABase + R_ACPI_IO_SMI_EN; + OutputData =3D IoRead32 ((UINTN) OutputPort); + OutputData |=3D (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 =3D R_PCH_IO_APM_CNT; + OutputData =3D 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 =3D EFI_SUCCESS; + + // + // Clear the Power Button Override Status Bit, it gates EOS from being s= et. + // + OutputPort =3D mABase + R_ACPI_IO_PM1_STS; + OutputData =3D 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 =3D mABase + R_ACPI_IO_SMI_STS; + OutputData =3D 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 =3D mABase + R_ACPI_IO_SMI_EN; + OutputData =3D IoRead32 ((UINTN) OutputPort); + OutputData |=3D 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 S= MI_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 insta= nce + @param[in, out] CommandPort The buffer contains data to the co= mmand port + @param[in, out] DataPort The buffer contains data to the da= ta port + @param[in] Periodic Periodic or not + @param[in] ActivationInterval Interval of periodic SMI + + @retval EFI Status Describing the result of the opera= tion + @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 =3D=3D NULL) { + Data =3D 0xFF; + } else { + Data =3D *CommandPort; + } + // + // Clear any pending the APM SMI + // + Status =3D 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 suppo= rted +**/ +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 =3D IoRead16 ((UINTN) mABase + R_ACPI_IO_PM1_CNT); + SciEn =3D (BOOLEAN) ((Data & B_ACPI_IO_PM1_CNT_SCI_EN) =3D=3D B_ACPI= _IO_PM1_CNT_SCI_EN); + + if (!SciEn) { + // + // Clear any SMIs that double as SCIs (when SCI_EN=3D=3D0) + // + 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 o= f the wake source. + // + IoAnd32 ((UINTN) mABase + R_ACPI_IO_GPE0_EN_127_96, (UINT32) ~B_ACPI_I= O_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 =3D IoRead32 ((UINTN) mABase + R_ACPI_IO_SMI_EN); + // + // clear all bits except those tied to SCI_EN + // + Data &=3D B_ACPI_IO_SMI_EN_BIOS_RLS; + // + // enable SMIs and specifically enable writes to APM_CNT. + // + Data |=3D 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 c= leared 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/Sili= con/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 Inte= rface. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// 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 ensu= re the MMIO range +// won't overlap with SMRAM range, and trusted. +// +GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mSpiResvMmioAddr; + +/** + SPI Runtime SMM Module Entry Point\n + - Introduction\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. + + - Integration Check List\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 handle= r, + and the SMI occurrence is asynchronous to normal mode code execution= , + proper synchronization mechanism must be applied, e.g. disable SMI b= efore + 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 m= ay + not be effective as platform may well set the SMI_LOCK bit (i.e., PM= C 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 drive= r. + @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initiali= ze 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 =3D PCH_SPI_BASE_ADDRESS; + + /// + /// Allocate pool for SPI protocol instance + /// + Status =3D gSmst->SmmAllocatePool ( + EfiRuntimeServicesData, /// MemoryType don't care + sizeof (SPI_INSTANCE), + (VOID **) &mSpiInstance + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (mSpiInstance =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ZeroMem ((VOID *) mSpiInstance, sizeof (SPI_INSTANCE)); + /// + /// Initialize the SPI protocol instance + /// + Status =3D SpiProtocolConstructor (mSpiInstance); + if (EFI_ERROR (Status)) { + return Status; + } + /// + /// Install the SMM PCH_SPI_PROTOCOL interface + /// + Status =3D 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 =3D PciSegmentRead32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0) = & ~(B_SPI_CFG_BAR0_MASK); + + if (SpiBar0 !=3D 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, mSpiResvM= mioAddr); + PciSegmentOr8 (SpiInstance->PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_C= OMMAND_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 initi= alized + @retval EFI_ACCESS_DENIED The BIOS Region can only be updated in S= MM phase + +**/ +EFI_STATUS +EFIAPI +DisableBiosWriteProtect ( + VOID + ) +{ + UINT64 SpiBaseAddress; + + SpiBaseAddress =3D 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]) =3D 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]) =3D 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 resul= t in EAX, + /// and write data to lower 32 bits of MSR 1FEh (sample code availabl= e) + /// - Set BIOSWE bit (SPI PCI Offset DCh [0]) =3D 1b + /// - Modify BIOS Region + /// - Clear BIOSWE bit (SPI PCI Offset DCh [0]) =3D 0b + /// + if ((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_CFG_BC_EISS= ) !=3D 0) { + PchSetInSmmSts (); + } + + return EFI_SUCCESS; +} + +/** + This function is a hook for Spi to enable BIOS Write Protect + + +**/ +VOID +EFIAPI +EnableBiosWriteProtect ( + VOID + ) +{ + UINT64 SpiBaseAddress; + + SpiBaseAddress =3D 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]) =3D 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_EI= SS) =3D=3D 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 =3D=3D NULL) { + Status =3D gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (V= OID **)&mSmmCpuProtocol); + ASSERT_EFI_ERROR (Status); + if (mSmmCpuProtocol =3D=3D NULL) { + return TRUE; + } + } + + for (CpuIndex =3D 0; CpuIndex < gSmst->NumberOfCpus; CpuIndex++) { + Status =3D 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; +} --=20 2.16.2.windows.1